diff --git a/Directory.Packages.props b/Directory.Packages.props
index 61b105a9..4fc3ea82 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,7 +4,7 @@
true
true
- 41.0.25-preview
+ 46.0.5-preview
0.1.12-alpha
diff --git a/src/Microsoft.Windows.CsWin32/Generator.Constant.cs b/src/Microsoft.Windows.CsWin32/Generator.Constant.cs
index 18baa372..081c90c2 100644
--- a/src/Microsoft.Windows.CsWin32/Generator.Constant.cs
+++ b/src/Microsoft.Windows.CsWin32/Generator.Constant.cs
@@ -158,28 +158,187 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
});
}
- private static ObjectCreationExpressionSyntax PropertyKeyValue(CustomAttribute propertyKeyAttribute, TypeSyntax type)
+ private static List> SplitConstantArguments(ReadOnlyMemory args)
{
- CustomAttributeValue args = propertyKeyAttribute.DecodeValue(CustomAttributeTypeProvider.Instance);
- uint a = (uint)args.FixedArguments[0].Value!;
- ushort b = (ushort)args.FixedArguments[1].Value!;
- ushort c = (ushort)args.FixedArguments[2].Value!;
- byte d = (byte)args.FixedArguments[3].Value!;
- byte e = (byte)args.FixedArguments[4].Value!;
- byte f = (byte)args.FixedArguments[5].Value!;
- byte g = (byte)args.FixedArguments[6].Value!;
- byte h = (byte)args.FixedArguments[7].Value!;
- byte i = (byte)args.FixedArguments[8].Value!;
- byte j = (byte)args.FixedArguments[9].Value!;
- byte k = (byte)args.FixedArguments[10].Value!;
- uint pid = (uint)args.FixedArguments[11].Value!;
-
- return ObjectCreationExpression(type).WithInitializer(
- InitializerExpression(SyntaxKind.ObjectInitializerExpression, SeparatedList(new[]
+ List> argExpressions = new();
+
+ // Recursively parse the arguments, splitting on commas that are not nested within curly brances.
+ int start = 0;
+ int depth = 0;
+ for (int i = 0; i < args.Length; i++)
+ {
+ switch (args.Span[i])
+ {
+ case '{':
+ depth++;
+ break;
+ case '}':
+ depth--;
+ break;
+ case ',':
+ if (depth == 0)
+ {
+ ReadOnlyMemory arg = args.Slice(start, i - start);
+
+ argExpressions.Add(TrimCurlyBraces(arg));
+ start = i + 1;
+
+ // Trim a leading space if present.
+ if (args.Span[start] == ' ')
+ {
+ start++;
+ i++;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (start < args.Length)
+ {
+ argExpressions.Add(TrimCurlyBraces(args.Slice(start)));
+ }
+
+ ReadOnlyMemory TrimCurlyBraces(ReadOnlyMemory arg)
+ {
+ return arg.Span[0] == '{' && arg.Span[arg.Length - 1] == '}' ? arg.Slice(1, arg.Length - 2) : arg;
+ }
+
+ return argExpressions;
+ }
+
+ private ObjectCreationExpressionSyntax? CreateConstantViaCtor(List> args, TypeSyntax targetType, TypeDefinition targetTypeDef)
+ {
+ foreach (MethodDefinitionHandle methodDefHandle in targetTypeDef.GetMethods())
+ {
+ MethodDefinition methodDef = this.Reader.GetMethodDefinition(methodDefHandle);
+ if (this.Reader.StringComparer.Equals(methodDef.Name, ".ctor") && methodDef.GetParameters().Count == args.Count)
+ {
+ MethodSignature ctorSignature = methodDef.DecodeSignature(SignatureHandleProvider.Instance, null);
+ var argExpressions = new ArgumentSyntax[args.Count];
+
+ for (int i = 0; i < args.Count; i++)
+ {
+ TypeHandleInfo parameterTypeInfo = ctorSignature.ParameterTypes[i];
+ argExpressions[i] = Argument(this.CreateConstant(args[i], parameterTypeInfo));
+ i++;
+ }
+
+ return ObjectCreationExpression(targetType).AddArgumentListArguments(argExpressions);
+ }
+ }
+
+ return null;
+ }
+
+ private ObjectCreationExpressionSyntax? CreateConstantByField(List> args, TypeSyntax targetType, TypeDefinition targetTypeDef)
+ {
+ if (targetTypeDef.GetFields().Count != args.Count)
+ {
+ return null;
+ }
+
+ var fieldAssignmentExpressions = new AssignmentExpressionSyntax[args.Count];
+ int i = 0;
+ foreach (FieldDefinitionHandle fieldDefHandle in targetTypeDef.GetFields())
+ {
+ FieldDefinition fieldDef = this.Reader.GetFieldDefinition(fieldDefHandle);
+ string fieldName = this.Reader.GetString(fieldDef.Name);
+ TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature(SignatureHandleProvider.Instance, null) with { IsConstantField = true };
+ fieldAssignmentExpressions[i] = AssignmentExpression(
+ SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName(fieldName),
+ this.CreateConstant(args[i], fieldTypeInfo));
+ i++;
+ }
+
+ return ObjectCreationExpression(targetType)
+ .WithArgumentList(null)
+ .WithInitializer(InitializerExpression(SyntaxKind.ObjectInitializerExpression, SeparatedList()).AddExpressions(fieldAssignmentExpressions));
+ }
+
+ private ExpressionSyntax CreateConstant(ReadOnlyMemory argsAsString, TypeHandleInfo targetType)
+ {
+ return targetType switch
+ {
+ ArrayTypeHandleInfo { ElementType: PrimitiveTypeHandleInfo { PrimitiveTypeCode: PrimitiveTypeCode.Byte } } pointerType => this.CreateByteArrayConstant(argsAsString),
+ PrimitiveTypeHandleInfo primitiveType => ToExpressionSyntax(primitiveType.PrimitiveTypeCode, argsAsString),
+ HandleTypeHandleInfo handleType => this.CreateConstant(argsAsString, targetType.ToTypeSyntax(this.fieldTypeSettings, null).Type, (TypeReferenceHandle)handleType.Handle),
+ _ => throw new GenerationFailedException($"Unsupported constant type: {targetType}"),
+ };
+ }
+
+ private ExpressionSyntax CreateConstant(ReadOnlyMemory argsAsString, TypeSyntax targetType, TypeReferenceHandle targetTypeRefHandle)
+ {
+ if (!this.TryGetTypeDefHandle(targetTypeRefHandle, out TypeDefinitionHandle targetTypeDefHandle))
+ {
+ // Special case for System.Guid.
+ TypeReference typeRef = this.Reader.GetTypeReference(targetTypeRefHandle);
+ if (this.Reader.StringComparer.Equals(typeRef.Name, "Guid"))
{
- AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("fmtid"), GuidValue(propertyKeyAttribute)),
- AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("pid"), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(pid))),
- })));
+ List> guidArgs = SplitConstantArguments(argsAsString);
+ return this.CreateGuidConstant(guidArgs);
+ }
+
+ throw new GenerationFailedException("Unrecognized target type.");
+ }
+
+ this.RequestInteropType(targetTypeDefHandle, this.DefaultContext);
+ TypeDefinition typeDef = this.Reader.GetTypeDefinition(targetTypeDefHandle);
+
+ List> args = SplitConstantArguments(argsAsString);
+
+ ObjectCreationExpressionSyntax? result =
+ this.CreateConstantViaCtor(args, targetType, typeDef) ??
+ this.CreateConstantByField(args, targetType, typeDef);
+
+ return result ?? throw new GenerationFailedException($"Unable to construct constant value given {args.Count} fields or constructor arguments.");
+ }
+
+ private ExpressionSyntax CreateByteArrayConstant(ReadOnlyMemory argsAsString)
+ {
+ List> args = SplitConstantArguments(argsAsString);
+ TypeSyntax byteTypeSyntax = PredefinedType(Token(SyntaxKind.ByteKeyword));
+ return CastExpression(
+ MakeReadOnlySpanOfT(byteTypeSyntax),
+ ArrayCreationExpression(ArrayType(byteTypeSyntax).AddRankSpecifiers(ArrayRankSpecifier())).WithInitializer(InitializerExpression(SyntaxKind.ArrayInitializerExpression, SeparatedList())
+ .AddExpressions(args.Select(b => ToExpressionSyntax(PrimitiveTypeCode.Byte, b)).ToArray())));
+ }
+
+ private ExpressionSyntax CreateGuidConstant(List> guidArgs)
+ {
+ if (guidArgs.Count != 11)
+ {
+ throw new GenerationFailedException($"Unexpected element count {guidArgs.Count} when constructing a Guid, which requires 11.");
+ }
+
+ var ctorArgs = new SyntaxToken[11]
+ {
+ Literal(uint.Parse(guidArgs[0].ToString(), CultureInfo.InvariantCulture)),
+ Literal(ushort.Parse(guidArgs[1].ToString(), CultureInfo.InvariantCulture)),
+ Literal(ushort.Parse(guidArgs[2].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[3].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[4].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[5].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[6].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[7].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[8].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[9].ToString(), CultureInfo.InvariantCulture)),
+ Literal(byte.Parse(guidArgs[10].ToString(), CultureInfo.InvariantCulture)),
+ };
+
+ return ObjectCreationExpression(GuidTypeSyntax).AddArgumentListArguments(ctorArgs.Select(t => Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, t))).ToArray());
+ }
+
+ private ExpressionSyntax CreateConstant(CustomAttribute constantAttribute, TypeHandleInfo targetType)
+ {
+ TypeReferenceHandle targetTypeRefHandle = (TypeReferenceHandle)((HandleTypeHandleInfo)targetType).Handle;
+ CustomAttributeValue args = constantAttribute.DecodeValue(CustomAttributeTypeProvider.Instance);
+ return this.CreateConstant(
+ ((string)args.FixedArguments[0].Value!).AsMemory(),
+ targetType.ToTypeSyntax(this.fieldTypeSettings, null).Type,
+ targetTypeRefHandle);
}
private FieldDeclarationSyntax DeclareConstant(FieldDefinition fieldDef)
@@ -193,7 +352,7 @@ private FieldDeclarationSyntax DeclareConstant(FieldDefinition fieldDef)
ExpressionSyntax value =
fieldDef.GetDefaultValue() is { IsNil: false } constantHandle ? ToExpressionSyntax(this.Reader, constantHandle) :
this.FindInteropDecorativeAttribute(customAttributes, nameof(GuidAttribute)) is CustomAttribute guidAttribute ? GuidValue(guidAttribute) :
- this.FindInteropDecorativeAttribute(customAttributes, "PropertyKeyAttribute") is CustomAttribute propertyKeyAttribute ? PropertyKeyValue(propertyKeyAttribute, fieldType.Type) :
+ this.FindInteropDecorativeAttribute(customAttributes, "ConstantAttribute") is CustomAttribute constantAttribute ? this.CreateConstant(constantAttribute, fieldTypeInfo) :
throw new NotSupportedException("Unsupported constant: " + name);
bool requiresUnsafe = false;
if (fieldType.Type is not PredefinedTypeSyntax && value is not ObjectCreationExpressionSyntax)
diff --git a/src/Microsoft.Windows.CsWin32/Generator.Handle.cs b/src/Microsoft.Windows.CsWin32/Generator.Handle.cs
index 512d66f0..27023cac 100644
--- a/src/Microsoft.Windows.CsWin32/Generator.Handle.cs
+++ b/src/Microsoft.Windows.CsWin32/Generator.Handle.cs
@@ -197,6 +197,10 @@ public partial class Generator
ExpressionSyntax noerror = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParseName("winmdroot.Foundation.WIN32_ERROR"), IdentifierName("NO_ERROR"));
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, noerror);
break;
+ case "HGLOBAL":
+ case "HLOCAL":
+ releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, DefaultExpression(releaseMethodReturnType.Type));
+ break;
default:
throw new NotSupportedException($"Return type {identifierName.Identifier.ValueText} on release method {releaseMethod} not supported.");
}
diff --git a/src/Microsoft.Windows.CsWin32/SimpleSyntaxFactory.cs b/src/Microsoft.Windows.CsWin32/SimpleSyntaxFactory.cs
index 418e5c8f..f19ad681 100644
--- a/src/Microsoft.Windows.CsWin32/SimpleSyntaxFactory.cs
+++ b/src/Microsoft.Windows.CsWin32/SimpleSyntaxFactory.cs
@@ -98,6 +98,7 @@ internal static class SimpleSyntaxFactory
internal static readonly SyntaxToken SemicolonWithLineFeed = TokenWithLineFeed(SyntaxKind.SemicolonToken);
internal static readonly IdentifierNameSyntax InlineArrayIndexerExtensionsClassName = IdentifierName("InlineArrayIndexerExtensions");
internal static readonly TypeSyntax SafeHandleTypeSyntax = IdentifierName("SafeHandle");
+ internal static readonly IdentifierNameSyntax GuidTypeSyntax = IdentifierName(nameof(Guid));
internal static readonly IdentifierNameSyntax IntPtrTypeSyntax = IdentifierName(nameof(IntPtr));
internal static readonly IdentifierNameSyntax UIntPtrTypeSyntax = IdentifierName(nameof(UIntPtr));
internal static readonly AttributeSyntax ComImportAttributeSyntax = Attribute(IdentifierName("ComImport"));
@@ -371,7 +372,7 @@ internal static ObjectCreationExpressionSyntax GuidValue(CustomAttribute guidAtt
byte j = (byte)args.FixedArguments[9].Value!;
byte k = (byte)args.FixedArguments[10].Value!;
- return ObjectCreationExpression(IdentifierName(nameof(Guid))).AddArgumentListArguments(
+ return ObjectCreationExpression(GuidTypeSyntax).AddArgumentListArguments(
Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(ToHex(a), a))),
Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(ToHex(b), b))),
Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(ToHex(c), c))),
@@ -415,7 +416,7 @@ internal static ExpressionSyntax ToHexExpressionSyntax(MetadataReader reader, Co
ExpressionSyntax UncheckedSignedWrapper(LiteralExpressionSyntax value, SyntaxKind signedType)
{
- return assignableToSignedInteger && value.Token.Text.StartsWith("0xF", StringComparison.OrdinalIgnoreCase)
+ return assignableToSignedInteger && char.ToUpper(value.Token.Text[2]) is '8' or '9' or (>= 'A' and <= 'F')
? UncheckedExpression(CastExpression(PredefinedType(Token(signedType)), value))
: value;
}
@@ -453,4 +454,24 @@ static ExpressionSyntax FloatExpression(float value)
LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(value));
}
}
+
+ internal static ExpressionSyntax ToExpressionSyntax(PrimitiveTypeCode primitiveTypeCode, ReadOnlyMemory valueAsString)
+ {
+ string valueAsStringReally = valueAsString.ToString();
+ return primitiveTypeCode switch
+ {
+ PrimitiveTypeCode.Int64 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(long.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.Byte => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(byte.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.SByte => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(sbyte.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.Int16 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(short.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.UInt16 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(ushort.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.Int32 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(int.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.UInt32 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(uint.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.UInt64 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(ulong.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.Single => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(float.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.Double => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(double.Parse(valueAsStringReally, CultureInfo.InvariantCulture))),
+ PrimitiveTypeCode.String => LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(valueAsStringReally)),
+ _ => throw new NotSupportedException($"Unrecognized primitive type code: {primitiveTypeCode}."),
+ };
+ }
}
diff --git a/test/GenerationSandbox.Tests/BasicTests.cs b/test/GenerationSandbox.Tests/BasicTests.cs
index b4c62419..1012c7e8 100644
--- a/test/GenerationSandbox.Tests/BasicTests.cs
+++ b/test/GenerationSandbox.Tests/BasicTests.cs
@@ -200,7 +200,7 @@ public void CreateFile()
var path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
using var fileHandle = PInvoke.CreateFile(
path,
- FILE_ACCESS_FLAGS.FILE_GENERIC_WRITE,
+ (uint)FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE,
FILE_SHARE_MODE.FILE_SHARE_NONE,
lpSecurityAttributes: default,
FILE_CREATION_DISPOSITION.CREATE_NEW,
diff --git a/test/GenerationSandbox.Tests/ComRuntimeTests.cs b/test/GenerationSandbox.Tests/ComRuntimeTests.cs
index f05c2537..6a058844 100644
--- a/test/GenerationSandbox.Tests/ComRuntimeTests.cs
+++ b/test/GenerationSandbox.Tests/ComRuntimeTests.cs
@@ -14,8 +14,8 @@ public void RemotableInterface()
IServiceProvider serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(
PInvoke.CSIDL_DESKTOP,
null,
- (int)ShellWindowTypeConstants.SWC_DESKTOP,
+ ShellWindowTypeConstants.SWC_DESKTOP,
out int hwnd,
- (int)ShellWindowFindWindowOptions.SWFO_NEEDDISPATCH);
+ ShellWindowFindWindowOptions.SWFO_NEEDDISPATCH);
}
}
diff --git a/test/GenerationSandbox.Tests/NativeMethods.txt b/test/GenerationSandbox.Tests/NativeMethods.txt
index 16543a6d..a9df0184 100644
--- a/test/GenerationSandbox.Tests/NativeMethods.txt
+++ b/test/GenerationSandbox.Tests/NativeMethods.txt
@@ -6,6 +6,7 @@ CreateFile
CSIDL_DESKTOP
DISPLAYCONFIG_VIDEO_SIGNAL_INFO
EnumWindows
+FILE_ACCESS_RIGHTS
GetProcAddress
GetTickCount
GetWindowText
diff --git a/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs b/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs
new file mode 100644
index 00000000..3683886e
--- /dev/null
+++ b/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+public class ConstantsTests : GeneratorTestBase
+{
+ public ConstantsTests(ITestOutputHelper logger)
+ : base(logger)
+ {
+ }
+
+ [Theory]
+ [InlineData("SECURITY_NULL_SID_AUTHORITY")] // SID_IDENTIFIER_AUTHORITY with byte[6] inline array
+ [InlineData("g_wszStreamBufferRecordingDuration")] // string
+ [InlineData("HWND_BOTTOM")] // A constant typed as a typedef'd struct
+ [InlineData("D2D1_DEFAULT_FLATTENING_TOLERANCE")] // a float constant
+ [InlineData("WIA_CATEGORY_FINISHED_FILE")] // GUID constant
+ [InlineData("DEVPKEY_MTPBTH_IsConnected")] // DEVPROPKEY constant
+ [InlineData("PKEY_AudioEndpoint_FormFactor")] // PROPERTYKEY constant
+ [InlineData("X509_CERT")] // A constant defined as PCSTR
+ [InlineData("RT_CURSOR")] // PCWSTR constant
+ [InlineData("HBMMENU_POPUP_RESTORE")] // A HBITMAP handle as a constant
+
+ public void InterestingConstants(string name)
+ {
+ this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.X64));
+ this.generator = this.CreateGenerator();
+ Assert.True(this.generator.TryGenerate(name, CancellationToken.None));
+ this.CollectGeneratedCode(this.generator);
+ this.AssertNoDiagnostics();
+ }
+}
diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs
index 9218c3e3..3bd90926 100644
--- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs
+++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs
@@ -301,8 +301,9 @@ protected async Task CreateCompilationAsync(ReferenceAssembli
ImmutableArray metadataReferences = await references.ResolveAsync(LanguageNames.CSharp, default);
// Workaround for https://github.com/dotnet/roslyn-sdk/issues/699
+ const string winRTPackageId = "Microsoft.Windows.SDK.Contracts";
metadataReferences = metadataReferences.AddRange(
- Directory.GetFiles(Path.Combine(Path.GetTempPath(), "test-packages", "Microsoft.Windows.SDK.Contracts.10.0.19041.1", "ref", "netstandard2.0"), "*.winmd").Select(p => MetadataReference.CreateFromFile(p)));
+ Directory.GetFiles(Path.Combine(Path.GetTempPath(), "test-packages", $"{winRTPackageId}.{references.Packages.Single(id => string.Equals(id.Id, winRTPackageId, StringComparison.OrdinalIgnoreCase)).Version}", "ref", "netstandard2.0"), "*.winmd").Select(p => MetadataReference.CreateFromFile(p)));
// CONSIDER: How can I pass in the source generator itself, with AdditionalFiles, so I'm exercising that code too?
var compilation = CSharpCompilation.Create(
@@ -355,7 +356,7 @@ protected static class MyReferenceAssemblies
{
#pragma warning disable SA1202 // Elements should be ordered by access - because field initializer depend on each other
private static readonly ImmutableArray AdditionalLegacyPackages = ImmutableArray.Create(
- new PackageIdentity("Microsoft.Windows.SDK.Contracts", "10.0.19041.1"));
+ new PackageIdentity("Microsoft.Windows.SDK.Contracts", "10.0.22621.2"));
private static readonly ImmutableArray AdditionalModernPackages = AdditionalLegacyPackages.AddRange(ImmutableArray.Create(
new PackageIdentity("System.Runtime.CompilerServices.Unsafe", "6.0.0"),
diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
index 1b39e6c1..154b1fe6 100644
--- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
+++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
@@ -152,6 +152,8 @@ public void InterestingAPIs(
"PZZWSTR",
"PCZZSTR",
"PCZZWSTR",
+ "RoCreatePropertySetSerializer", // References a WinRT API
+ "LocalLock", // returns HLOCAL, which requires special release support
"LoadLibraryEx", // method with a reserved parameter
"IEnumNetCfgComponent", // interface with a method containing an `[Reserved] out` parameter (bonkers, I know).
"IEventSubscription",
@@ -174,11 +176,9 @@ public void InterestingAPIs(
"JsRuntimeVersion", // An enum that has an extra member in a separate header file.
"ReportEvent", // Failed at one point
"DISPLAYCONFIG_VIDEO_SIGNAL_INFO", // Union, explicit layout, bitmask, nested structs
- "g_wszStreamBufferRecordingDuration", // Constant string field
"MFVideoAlphaBitmap", // field named params
"DDRAWI_DDVIDEOPORT_INT", // field that is never used
"MainAVIHeader", // dwReserved field is a fixed length array
- "HBMMENU_POPUP_RESTORE", // A HBITMAP handle as a constant
"RpcServerRegisterIfEx", // Optional attribute on delegate type.
"RpcSsSwapClientAllocFree", // Parameters typed as pointers to in delegates and out delegates
"RPC_DISPATCH_TABLE", // Struct with a field typed as a delegate
@@ -186,7 +186,6 @@ public void InterestingAPIs(
"DDHAL_DESTROYDRIVERDATA", // Struct with a field typed as a delegate
"I_RpcServerInqAddressChangeFn", // p/invoke that returns a function pointer
"WSPUPCALLTABLE", // a delegate with a delegate in its signature
- "HWND_BOTTOM", // A constant typed as a typedef'd struct
"BOOL", // a special cased typedef struct
"uregex_getMatchCallback", // friendly overload with delegate parameter, and out parameters
"CreateDispatcherQueueController", // References a WinRT type
@@ -207,11 +206,6 @@ public void InterestingAPIs(
"PICTYPE", // An enum with -1 as an enum value
"CoCreateInstance", // a hand-written friendly overload
"JsVariantToValue",
- "D2D1_DEFAULT_FLATTENING_TOLERANCE", // a float constant
- "WIA_CATEGORY_FINISHED_FILE", // GUID constant
- "DEVPKEY_MTPBTH_IsConnected", // DEVPROPKEY constant
- "PKEY_AudioEndpoint_FormFactor", // PROPERTYKEY constant
- "RT_CURSOR", // PCWSTR constant
"IOleUILinkContainerW", // An IUnknown-derived interface with no GUID
"FILE_TYPE_NOTIFICATION_INPUT",
"DS_SELECTION_LIST", // A struct with a fixed-length inline array of potentially managed structs
@@ -221,7 +215,6 @@ public void InterestingAPIs(
"IDelayedPropertyStoreFactory", // interface inheritance across namespaces
"D3D9ON12_ARGS", // Contains an inline array of IUnknown objects
"NCryptOpenKey", // Generates a SafeHandle based on a UIntPtr
- "X509_CERT", // A constant defined as PCSTR
"CIDLData_CreateFromIDArray", // Method with out parameter of a possibly marshaled interop type shared with the BCL,
"ID3D12Resource", // COM interface with base types
"OpenTrace", // the CloseTrace method called by the SafeHandle returns WIN32_ERROR. The handle is ALWAYS 64-bits.
@@ -893,6 +886,7 @@ public void ProjectReferenceBetweenThreeGeneratingProjects(bool internalsVisible
// Now produce more code in a referencing project that needs HANDLE, which is found *twice*, once in each referenced project.
this.generator = this.CreateGenerator();
Assert.True(this.generator.TryGenerate("CreateFile", CancellationToken.None));
+ Assert.True(this.generator.TryGenerate("FILE_ACCESS_RIGHTS", CancellationToken.None));
this.CollectGeneratedCode(this.generator);
// Consume the API to verify the user experience isn't broken.
@@ -909,7 +903,7 @@ static unsafe void Main()
{
HANDLE h = PInvoke.CreateFile(
default(PCWSTR),
- FILE_ACCESS_FLAGS.FILE_ADD_FILE,
+ (uint)FILE_ACCESS_RIGHTS.FILE_ADD_FILE,
FILE_SHARE_MODE.FILE_SHARE_READ,
null,
FILE_CREATION_DISPOSITION.CREATE_NEW,