Skip to content

Commit c676a8c

Browse files
authored
Support for derived IInspectable COM interfaces in custom winmds (#1459)
1 parent 8ada93c commit c676a8c

39 files changed

+498
-188
lines changed

global.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"allowPrerelease": false
66
},
77
"msbuild-sdks": {
8-
"Microsoft.Build.NoTargets": "3.7.56"
8+
"Microsoft.Build.NoTargets": "3.7.56",
9+
"Microsoft.Windows.WinmdGenerator": "0.63.31-preview"
910
}
1011
}

src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal record ArrayTypeHandleInfo(TypeHandleInfo ElementType, ArrayShape Shape
77
{
88
public override string ToString() => this.ToTypeSyntaxForDisplay().ToString();
99

10-
internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, Generator.GeneratingElement forElement, CustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes)
10+
internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, Generator.GeneratingElement forElement, QualifiedCustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes)
1111
{
1212
TypeSyntaxAndMarshaling element = this.ElementType.ToTypeSyntax(inputs, forElement, customAttributes);
1313
if (inputs.AllowMarshaling || inputs.IsField)

src/Microsoft.Windows.CsWin32/Generator.Com.cs

Lines changed: 48 additions & 45 deletions
Large diffs are not rendered by default.

src/Microsoft.Windows.CsWin32/Generator.Constant.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
139139
FieldDefinition fieldDef = this.Reader.GetFieldDefinition(fieldDefHandle);
140140
FieldDeclarationSyntax constantDeclaration = this.DeclareConstant(fieldDef);
141141

142-
TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature<TypeHandleInfo, SignatureHandleProvider.IGenericContext?>(SignatureHandleProvider.Instance, null) with { IsConstantField = true };
142+
TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature<TypeHandleInfo, SignatureHandleProvider.IGenericContext?>(this.SignatureHandleProvider, null) with { IsConstantField = true };
143143
TypeDefinitionHandle? fieldType = null;
144144
if (fieldTypeInfo is HandleTypeHandleInfo handleInfo && this.IsTypeDefStruct(handleInfo) && handleInfo.Handle.Kind == HandleKind.TypeReference)
145145
{
@@ -213,7 +213,7 @@ ReadOnlyMemory<char> TrimCurlyBraces(ReadOnlyMemory<char> arg)
213213
MethodDefinition methodDef = this.Reader.GetMethodDefinition(methodDefHandle);
214214
if (this.Reader.StringComparer.Equals(methodDef.Name, ".ctor") && methodDef.GetParameters().Count == args.Count)
215215
{
216-
MethodSignature<TypeHandleInfo> ctorSignature = methodDef.DecodeSignature(SignatureHandleProvider.Instance, null);
216+
MethodSignature<TypeHandleInfo> ctorSignature = methodDef.DecodeSignature(this.SignatureHandleProvider, null);
217217
var argExpressions = new ArgumentSyntax[args.Count];
218218

219219
for (int i = 0; i < args.Count; i++)
@@ -245,7 +245,7 @@ ReadOnlyMemory<char> TrimCurlyBraces(ReadOnlyMemory<char> arg)
245245
{
246246
FieldDefinition fieldDef = this.Reader.GetFieldDefinition(fieldDefHandle);
247247
string fieldName = this.Reader.GetString(fieldDef.Name);
248-
TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature(SignatureHandleProvider.Instance, null) with { IsConstantField = true };
248+
TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature(this.SignatureHandleProvider, null) with { IsConstantField = true };
249249
fieldAssignmentExpressions[i] = AssignmentExpression(
250250
SyntaxKind.SimpleAssignmentExpression,
251251
IdentifierName(fieldName),
@@ -354,9 +354,9 @@ private FieldDeclarationSyntax DeclareConstant(FieldDefinition fieldDef)
354354
string name = this.Reader.GetString(fieldDef.Name);
355355
try
356356
{
357-
TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature(SignatureHandleProvider.Instance, null) with { IsConstantField = true };
357+
TypeHandleInfo fieldTypeInfo = fieldDef.DecodeSignature(this.SignatureHandleProvider, null) with { IsConstantField = true };
358358
CustomAttributeHandleCollection customAttributes = fieldDef.GetCustomAttributes();
359-
TypeSyntaxAndMarshaling fieldType = fieldTypeInfo.ToTypeSyntax(this.fieldTypeSettings, GeneratingElement.Constant, customAttributes);
359+
TypeSyntaxAndMarshaling fieldType = fieldTypeInfo.ToTypeSyntax(this.fieldTypeSettings, GeneratingElement.Constant, customAttributes.QualifyWith(this));
360360
bool requiresUnsafe = false;
361361
ExpressionSyntax value =
362362
fieldDef.GetDefaultValue() is { IsNil: false } constantHandle ? ToExpressionSyntax(this.Reader, constantHandle) :

src/Microsoft.Windows.CsWin32/Generator.Delegate.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ private DelegateDeclarationSyntax DeclareDelegate(TypeDefinition typeDef)
5454
}
5555

5656
this.GetSignatureForDelegate(typeDef, out MethodDefinition invokeMethodDef, out MethodSignature<TypeHandleInfo> signature, out CustomAttributeHandleCollection? returnTypeAttributes);
57-
TypeSyntaxAndMarshaling returnValue = signature.ReturnType.ToTypeSyntax(typeSettings, GeneratingElement.Delegate, returnTypeAttributes);
57+
TypeSyntaxAndMarshaling returnValue = signature.ReturnType.ToTypeSyntax(typeSettings, GeneratingElement.Delegate, returnTypeAttributes?.QualifyWith(this));
5858

5959
DelegateDeclarationSyntax result = DelegateDeclaration(returnValue.Type, Identifier(name))
6060
.WithParameterList(FixTrivia(this.CreateParameterList(invokeMethodDef, signature, typeSettings, GeneratingElement.Delegate)))
@@ -113,7 +113,7 @@ private MemberDeclarationSyntax DeclareUntypedDelegate(TypeDefinition typeDef)
113113
private void GetSignatureForDelegate(TypeDefinition typeDef, out MethodDefinition invokeMethodDef, out MethodSignature<TypeHandleInfo> signature, out CustomAttributeHandleCollection? returnTypeAttributes)
114114
{
115115
invokeMethodDef = typeDef.GetMethods().Select(this.Reader.GetMethodDefinition).Single(def => this.Reader.StringComparer.Equals(def.Name, "Invoke"));
116-
signature = invokeMethodDef.DecodeSignature(SignatureHandleProvider.Instance, null);
116+
signature = invokeMethodDef.DecodeSignature(this.SignatureHandleProvider, null);
117117
returnTypeAttributes = this.GetReturnTypeCustomAttributes(invokeMethodDef);
118118
}
119119

@@ -149,6 +149,6 @@ private FunctionPointerParameterSyntax TranslateDelegateToFunctionPointer(TypeHa
149149
return FunctionPointerParameter(delegateTypeDef.Generator.FunctionPointer(delegateTypeDef.Definition));
150150
}
151151

152-
return FunctionPointerParameter(parameterTypeInfo.ToTypeSyntax(this.functionPointerTypeSettings, GeneratingElement.FunctionPointer, customAttributeHandles).GetUnmarshaledType());
152+
return FunctionPointerParameter(parameterTypeInfo.ToTypeSyntax(this.functionPointerTypeSettings, GeneratingElement.FunctionPointer, customAttributeHandles?.QualifyWith(this)).GetUnmarshaledType());
153153
}
154154
}

src/Microsoft.Windows.CsWin32/Generator.Enum.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void AddEnumValue(FieldDefinitionHandle fieldDefHandle)
6565
ConstantHandle valueHandle = fieldDef.GetDefaultValue();
6666
if (valueHandle.IsNil)
6767
{
68-
enumBaseType = fieldDef.DecodeSignature(SignatureHandleProvider.Instance, null).ToTypeSyntax(this.enumTypeSettings, GeneratingElement.EnumValue, null).Type;
68+
enumBaseType = fieldDef.DecodeSignature(this.SignatureHandleProvider, null).ToTypeSyntax(this.enumTypeSettings, GeneratingElement.EnumValue, null).Type;
6969
return;
7070
}
7171

src/Microsoft.Windows.CsWin32/Generator.Extern.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,11 @@ private void DeclareExternMethod(MethodDefinitionHandle methodDefinitionHandle)
184184

185185
// If this method releases a handle, recreate the method signature such that we take the struct rather than the SafeHandle as a parameter.
186186
TypeSyntaxSettings typeSettings = this.MetadataIndex.ReleaseMethods.Contains(entrypoint ?? methodName) ? this.externReleaseSignatureTypeSettings : this.externSignatureTypeSettings;
187-
MethodSignature<TypeHandleInfo> signature = methodDefinition.DecodeSignature(SignatureHandleProvider.Instance, null);
187+
MethodSignature<TypeHandleInfo> signature = methodDefinition.DecodeSignature(this.SignatureHandleProvider, null);
188188
bool requiresUnicodeCharSet = signature.ParameterTypes.Any(p => p is PrimitiveTypeHandleInfo { PrimitiveTypeCode: PrimitiveTypeCode.Char });
189189

190190
CustomAttributeHandleCollection? returnTypeAttributes = this.GetReturnTypeCustomAttributes(methodDefinition);
191-
TypeSyntaxAndMarshaling returnType = signature.ReturnType.ToTypeSyntax(typeSettings, GeneratingElement.ExternMethod, returnTypeAttributes, ParameterAttributes.Out);
191+
TypeSyntaxAndMarshaling returnType = signature.ReturnType.ToTypeSyntax(typeSettings, GeneratingElement.ExternMethod, returnTypeAttributes?.QualifyWith(this), ParameterAttributes.Out);
192192

193193
// Search for any enum substitutions.
194194
TypeSyntax? returnTypeEnumName = this.FindAssociatedEnum(returnTypeAttributes);
@@ -355,7 +355,7 @@ static SyntaxToken RefInOutKeyword(ParameterSyntax p) =>
355355
// Add documentation if we can find it.
356356
exposedMethod = this.AddApiDocumentation(entrypoint ?? methodName, exposedMethod);
357357

358-
this.volatileCode.AddMemberToModule(moduleName, this.DeclareFriendlyOverloads(methodDefinition, exposedMethod, this.methodsAndConstantsClassName, FriendlyOverloadOf.ExternMethod, this.injectedPInvokeHelperMethods));
358+
this.volatileCode.AddMemberToModule(moduleName, this.DeclareFriendlyOverloads(methodDefinition, exposedMethod, this.methodsAndConstantsClassName, FriendlyOverloadOf.ExternMethod, this.injectedPInvokeHelperMethods, avoidWinmdRootAlias: false));
359359
this.volatileCode.AddMemberToModule(moduleName, exposedMethod);
360360
}
361361
catch (Exception ex)

src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ private enum FriendlyOverloadOf
1414
InterfaceMethod,
1515
}
1616

17-
private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefinition methodDefinition, MethodDeclarationSyntax externMethodDeclaration, NameSyntax declaringTypeName, FriendlyOverloadOf overloadOf, HashSet<string> helperMethodsAdded)
17+
private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefinition methodDefinition, MethodDeclarationSyntax externMethodDeclaration, NameSyntax declaringTypeName, FriendlyOverloadOf overloadOf, HashSet<string> helperMethodsAdded, bool avoidWinmdRootAlias)
1818
{
1919
if (!this.options.FriendlyOverloads.Enabled)
2020
{
@@ -59,7 +59,12 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefi
5959
_ => throw new NotSupportedException(overloadOf.ToString()),
6060
};
6161

62-
MethodSignature<TypeHandleInfo> originalSignature = methodDefinition.DecodeSignature(SignatureHandleProvider.Instance, null);
62+
if (avoidWinmdRootAlias)
63+
{
64+
parameterTypeSyntaxSettings = parameterTypeSyntaxSettings with { AvoidWinmdRootAlias = true };
65+
}
66+
67+
MethodSignature<TypeHandleInfo> originalSignature = methodDefinition.DecodeSignature(this.SignatureHandleProvider, null);
6368
CustomAttributeHandleCollection? returnTypeAttributes = null;
6469
var parameters = externMethodDeclaration.ParameterList.Parameters.Select(StripAttributes).ToList();
6570
var lengthParamUsedBy = new Dictionary<int, int>();
@@ -105,7 +110,7 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefi
105110

106111
TypeHandleInfo parameterTypeInfo = originalSignature.ParameterTypes[param.SequenceNumber - 1];
107112
bool isManagedParameterType = this.IsManagedType(parameterTypeInfo);
108-
bool mustRemainAsPointer = parameterTypeInfo is PointerTypeHandleInfo { ElementType: HandleTypeHandleInfo pointedElement } && this.IsStructWithFlexibleArray(pointedElement);
113+
bool mustRemainAsPointer = parameterTypeInfo is PointerTypeHandleInfo { ElementType: HandleTypeHandleInfo pointedElement } && pointedElement.Generator.IsStructWithFlexibleArray(pointedElement);
109114

110115
IdentifierNameSyntax origName = IdentifierName(externParam.Identifier.ValueText);
111116

@@ -146,7 +151,7 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefi
146151
bool hasOut = externParam.Modifiers.Any(SyntaxKind.OutKeyword);
147152
arguments[param.SequenceNumber - 1] = arguments[param.SequenceNumber - 1].WithRefKindKeyword(TokenWithSpace(hasOut ? SyntaxKind.OutKeyword : SyntaxKind.RefKeyword));
148153
}
149-
else if (isOut && !isIn && !isReleaseMethod && parameterTypeInfo is PointerTypeHandleInfo { ElementType: HandleTypeHandleInfo pointedElementInfo } && this.TryGetHandleReleaseMethod(pointedElementInfo.Handle, paramAttributes, out string? outReleaseMethod) && !this.Reader.StringComparer.Equals(methodDefinition.Name, outReleaseMethod))
154+
else if (isOut && !isIn && !isReleaseMethod && parameterTypeInfo is PointerTypeHandleInfo { ElementType: HandleTypeHandleInfo pointedElementInfo } && pointedElementInfo.Generator.TryGetHandleReleaseMethod(pointedElementInfo.Handle, paramAttributes, out string? outReleaseMethod) && !this.Reader.StringComparer.Equals(methodDefinition.Name, outReleaseMethod))
150155
{
151156
if (this.RequestSafeHandle(outReleaseMethod) is TypeSyntax safeHandleType)
152157
{
@@ -668,7 +673,7 @@ bool TryHandleCountParam(TypeSyntax elementType, bool nullableSource)
668673
}
669674

670675
TypeSyntax? returnSafeHandleType = originalSignature.ReturnType is HandleTypeHandleInfo returnTypeHandleInfo
671-
&& this.TryGetHandleReleaseMethod(returnTypeHandleInfo.Handle, returnTypeAttributes, out string? returnReleaseMethod)
676+
&& returnTypeHandleInfo.Generator.TryGetHandleReleaseMethod(returnTypeHandleInfo.Handle, returnTypeAttributes, out string? returnReleaseMethod)
672677
? this.RequestSafeHandle(returnReleaseMethod) : null;
673678
SyntaxToken friendlyMethodName = externMethodDeclaration.Identifier;
674679

@@ -794,7 +799,7 @@ bool TryHandleCountParam(TypeSyntax elementType, bool nullableSource)
794799
// If we're using C# 13 or later, consider adding the overload resolution attribute if it would likely resolve ambiguities.
795800
if (this.LanguageVersion >= (LanguageVersion)1300 && parameters.Count == externMethodDeclaration.ParameterList.Parameters.Count)
796801
{
797-
this.DeclareOverloadResolutionPriorityAttributeIfNecessary();
802+
this.volatileCode.GenerationTransaction(() => this.DeclareOverloadResolutionPriorityAttributeIfNecessary());
798803
friendlyDeclaration = friendlyDeclaration.AddAttributeLists(AttributeList().AddAttributes(OverloadResolutionPriorityAttribute(1)));
799804
}
800805

src/Microsoft.Windows.CsWin32/Generator.Handle.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ public partial class Generator
3636
string releaseMethodModule = this.GetNormalizedModuleName(releaseMethodDef.GetImport());
3737

3838
IdentifierNameSyntax? safeHandleTypeIdentifier = IdentifierName(safeHandleClassName);
39-
safeHandleType = safeHandleTypeIdentifier;
39+
safeHandleType = QualifiedName(ParseName($"global::{this.Namespace}"), safeHandleTypeIdentifier);
4040

41-
MethodSignature<TypeHandleInfo> releaseMethodSignature = releaseMethodDef.DecodeSignature(SignatureHandleProvider.Instance, null);
41+
MethodSignature<TypeHandleInfo> releaseMethodSignature = releaseMethodDef.DecodeSignature(this.SignatureHandleProvider, null);
4242
TypeHandleInfo releaseMethodParameterTypeHandleInfo = releaseMethodSignature.ParameterTypes[0];
4343
TypeSyntaxAndMarshaling releaseMethodParameterType = releaseMethodParameterTypeHandleInfo.ToTypeSyntax(this.externSignatureTypeSettings, GeneratingElement.HelperClassMember, default);
4444

@@ -60,7 +60,10 @@ public partial class Generator
6060
safeHandleType = null;
6161
}
6262

63-
this.volatileCode.AddSafeHandleNameForReleaseMethod(releaseMethod, safeHandleType);
63+
this.volatileCode.GenerationTransaction(delegate
64+
{
65+
this.volatileCode.AddSafeHandleNameForReleaseMethod(releaseMethod, safeHandleType);
66+
});
6467

6568
if (safeHandleType is null)
6669
{
@@ -72,15 +75,18 @@ public partial class Generator
7275
return safeHandleType;
7376
}
7477

75-
this.RequestExternMethod(releaseMethodHandle.Value);
78+
this.volatileCode.GenerationTransaction(delegate
79+
{
80+
this.RequestExternMethod(releaseMethodHandle.Value);
81+
});
7682

7783
// Collect all the known invalid values for this handle.
7884
// If no invalid values are given (e.g. BSTR), we'll just assume 0 is invalid.
7985
HashSet<IntPtr> invalidHandleValues = this.GetInvalidHandleValues(((HandleTypeHandleInfo)releaseMethodParameterTypeHandleInfo).Handle);
8086
IntPtr preferredInvalidValue = GetPreferredInvalidHandleValue(invalidHandleValues, new IntPtr(-1));
8187

8288
CustomAttributeHandleCollection? atts = this.GetReturnTypeCustomAttributes(releaseMethodDef);
83-
TypeSyntaxAndMarshaling releaseMethodReturnType = releaseMethodSignature.ReturnType.ToTypeSyntax(this.externSignatureTypeSettings, GeneratingElement.HelperClassMember, atts);
89+
TypeSyntaxAndMarshaling releaseMethodReturnType = releaseMethodSignature.ReturnType.ToTypeSyntax(this.externSignatureTypeSettings, GeneratingElement.HelperClassMember, atts?.QualifyWith(this));
8490

8591
this.TryGetRenamedMethod(releaseMethod, out string? renamedReleaseMethod);
8692

@@ -257,7 +263,11 @@ public partial class Generator
257263
/// </summary>
258264
"));
259265

260-
this.volatileCode.AddSafeHandleType(safeHandleDeclaration);
266+
this.volatileCode.GenerationTransaction(delegate
267+
{
268+
this.volatileCode.AddSafeHandleType(safeHandleDeclaration);
269+
});
270+
261271
return safeHandleType;
262272
}
263273
catch (Exception ex)

src/Microsoft.Windows.CsWin32/Generator.InlineArrays.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ StatementSyntax ClearSlice(ExpressionSyntax span) =>
731731
}
732732
else
733733
{
734-
qualifiedElementType = fieldTypeHandleInfo.ToTypeSyntax(this.extensionMethodSignatureTypeSettings, GeneratingElement.Other, customAttributes).Type switch
734+
qualifiedElementType = fieldTypeHandleInfo.ToTypeSyntax(this.extensionMethodSignatureTypeSettings, GeneratingElement.Other, customAttributes.QualifyWith(this)).Type switch
735735
{
736736
ArrayTypeSyntax at => at.ElementType,
737737
PointerTypeSyntax ptrType => ptrType.ElementType,

0 commit comments

Comments
 (0)