Skip to content

Commit a3d3905

Browse files
author
dahall
committed
Fixed and finished adding LPArray generator
1 parent 1890c40 commit a3d3905

File tree

20 files changed

+121
-120
lines changed

20 files changed

+121
-120
lines changed

CodeGen/Generator/TypeDeclSyntaxExt.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ public static bool NameEquals(this ArgumentSyntax arg, string name) =>
1919
public static void Remove(this List<ParameterSyntax> values, string name)
2020
{
2121
var idx = values.FindIndex(t => t.Identifier.Text == name);
22-
if (idx < 0) throw new AmbiguousMatchException("The specified item was not found in the list.");
23-
values.RemoveAt(idx);
22+
if (idx >= 0)
23+
values.RemoveAt(idx);
2424
}
2525

2626
public static void Replace<T>(this List<T> values, T match, T replacement) where T : SyntaxNode
2727
{
2828
var idx = values.FindIndex(t => t.IsEquivalentTo(match));
29-
values[idx] = idx >= 0 ? replacement : throw new AmbiguousMatchException("The specified item was not found in the list.");
29+
if (idx >= 0)
30+
values[idx] = replacement;
3031
}
3132

3233
public static bool IsPartial(this TypeDeclarationSyntax tds) =>

CodeGen/Generator/VanaraAttributeGenerator.cs

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141

4242
using Microsoft.CodeAnalysis.CSharp;
4343
using System.Collections.Immutable;
44+
using System.ComponentModel;
45+
using System.Linq;
4446
using System.Runtime.InteropServices;
4547
using System.Xml;
4648
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -78,11 +80,11 @@ internal enum SizeParamType
7880
static string UniqueName(string n) => $"{n}{uid++}";
7981

8082
static readonly MethAttrHandler[] methodAttributes = [
81-
new("System.Runtime.InteropServices.MarshalAsAttribute", IsParamWithArgs, BuildMarshalAsMethod, ParentForExtMethod, GetParamMeth), // IUnknown, Interface, LPArray
82-
new("Vanara.PInvoke.IgnoreAttribute", IsParamInNotNewMethod, BuildIgnoreMethod, ParentForExtMethod, GetParamMeth),
83-
new("Vanara.PInvoke.SizeDefAttribute", IsParamInNotNewMethod, BuildSizeDefMethod, ParentForExtMethod, GetParamMeth),
84-
new("Vanara.PInvoke.AddAsCtorAttribute", IsParamInNotNewStaticMethod, DummyBuilder, GetParamType, GetParamMeth),
85-
new("Vanara.PInvoke.AddAsMemberAttribute", IsParamInNotNewStaticMethod, DummyBuilder, GetParamType, GetParamMeth),
83+
new("System.Runtime.InteropServices.MarshalAsAttribute", IsParamInNestedType, BuildMarshalAsMethod, ParentForExtMethod, GetParamMeth), // IUnknown, Interface, LPArray
84+
new("Vanara.PInvoke.IgnoreAttribute", IsParamInMethod, BuildIgnoreMethod, ParentForExtMethod, GetParamMeth),
85+
new("Vanara.PInvoke.SizeDefAttribute", IsParamInMethod, BuildSizeDefMethod, ParentForExtMethod, GetParamMeth),
86+
new("Vanara.PInvoke.AddAsCtorAttribute", IsParamInStaticMethod, DummyBuilder, GetParamType, GetParamMeth),
87+
new("Vanara.PInvoke.AddAsMemberAttribute", IsParamInStaticMethod, DummyBuilder, GetParamType, GetParamMeth),
8688
//("Vanara.PInvoke.SuppressAutoGenAttribute", static (n, t) => n is MethodDeclarationSyntax),
8789
];
8890

@@ -98,7 +100,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
98100
{
99101
// Process each attribute in the methodAttributes array
100102
var attributeProviders = methodAttributes
101-
.Select(attr => context.SyntaxProvider.ForAttributeWithMetadataName(attr.AttrName, (n, t) => attr.Validator(n, t) && NoSuppress(attr.meth((ParameterSyntax)n)), (ctx, _) => ((ParameterSyntax)ctx.TargetNode, ctx.Attributes)).Collect())
103+
.Select(attr => context.SyntaxProvider.ForAttributeWithMetadataName(attr.AttrName, (n, t) => attr.Validator(n, t), (ctx, _) => ((ParameterSyntax)ctx.TargetNode, ctx.Attributes)).Collect())
102104
.ToArray();
103105

104106
// Process type-level methodAttributes (those without method transforms)
@@ -128,8 +130,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
128130
GenerateCode(spc, value.Left.Left.Left.Left.Left.Left.Left.Left, value.Left.Left.Left.Left.Left.Left.Left.Right,
129131
value.Right.AddRange(value.Left.Right).AddRange(value.Left.Left.Right).AddRange(value.Left.Left.Left.Right).AddRange(value.Left.Left.Left.Left.Right),
130132
value.Left.Left.Left.Left.Left.Right.AddRange(value.Left.Left.Left.Left.Left.Left.Right)));
131-
132-
static bool NoSuppress(MethodDeclarationSyntax ms) => !ms.Modifiers.Any(SyntaxKind.NewKeyword) && !ms.AttributeLists.SelectMany(al => al.Attributes).Any(a => a.Name.ToString().Contains("SuppressAutoGen"));
133133
}
134134

135135
private static void GenerateCode(SourceProductionContext context, Compilation compilation, ImmutableArray<AdditionalText> addtlFiles, ImmutableArray<(ParameterSyntax paramNode, ImmutableArray<AttributeData> attrDatas)> paramNodes,
@@ -187,7 +187,7 @@ private static void GenerateCode(SourceProductionContext context, Compilation co
187187
continue;
188188

189189
// Add distinct using directives from 'usings' to the compilation unit
190-
usings = [.. usings.DistinctBy(u => u.Name?.ToString())];
190+
usings = [.. usings.DistinctBy(u => u.Alias?.ToString() ?? u.Name?.ToString())];
191191

192192
// Build new syntax tree, starting with nsDecl, adding any containing types with their modifiers, and finally the typeDecl with the new values from methLookup.Values
193193
SyntaxNode topDecl = typeDecl.WithMembers(List<MemberDeclarationSyntax>(methLookup.Values.Select(bb => bb.ToMethod())));
@@ -581,6 +581,7 @@ private static void BuildMarshalAsMethod(SourceProductionContext context, Compil
581581
UnmanagedType.IUnknown => decl.WithType(ParseTypeName(genericType + (decl.Type is not null && decl.Type.ToString().EndsWith("?") ? "?" : "")))
582582
.WithoutAttribute("MarshalAs"),
583583
UnmanagedType.Interface => decl.WithoutAttribute("MarshalAs"),
584+
UnmanagedType.LPArray when modAttr is ModType.In => decl.WithoutAttribute("MarshalAs"),
584585
_ => decl.WithoutTrivia()
585586
};
586587
tmpbuilder.parameters.Replace(decl, newParam);
@@ -598,7 +599,16 @@ private static void BuildMarshalAsMethod(SourceProductionContext context, Compil
598599
// Create the invocation expression capturing the return value if the return type is not `void`
599600
tmpbuilder.statements.invokeArgs = [.. tmpbuilder.statements.invokeArgs.Select(a => a switch
600601
{
601-
var a1 when a1.NameEquals(refParamName) => Argument(ParseExpression($"typeof({(unmanagedType == UnmanagedType.IUnknown ? genericType : decl.Type!.ToString().TrimEnd('?'))}).GUID")),
602+
var a1 when a1.NameEquals(refParamName) => unmanagedType switch
603+
{
604+
UnmanagedType.IUnknown => Argument(ParseExpression($"typeof({genericType}).GUID")),
605+
UnmanagedType.Interface => Argument(ParseExpression($"typeof({decl.Type!.ToString().TrimEnd('?')}).GUID")),
606+
UnmanagedType.LPArray when modAttr is ModType.In && methodDecl.ParameterList.Parameters.FirstOrDefault(p => p.Identifier.Text == refParamName) is ParameterSyntax refParam =>
607+
paramTypeIsNullable
608+
? Argument(ParseExpression($"({refParam.Type})Convert.ChangeType({decl.Identifier.Text}?.Length ?? 0, typeof({refParam.Type}))"))
609+
: Argument(ParseExpression($"({refParam.Type})Convert.ChangeType({decl.Identifier.Text}.Length, typeof({refParam.Type}))")),
610+
_ => a1,
611+
},
602612
var a1 when a1.Expression is IdentifierNameSyntax ins && ins.Identifier.Text == decl.Identifier.Text => isOutParam
603613
? Argument(null, MethodBodyBuilder.outToken, DeclarationExpression(IdentifierName("var"), SingleVariableDesignation(Identifier(altArg))))
604614
: Argument(IdentifierName(ins.Identifier.Text)),
@@ -624,16 +634,22 @@ var a1 when a1.NameEquals(refParamName) => Argument(ParseExpression($"typeof({(u
624634
// Process the xml docs for the method
625635
if (tmpbuilder.docs is not null)
626636
{
627-
// Get the xml node for the IID parameter docs
628-
XmlNode? iidNode = tmpbuilder.docs.SelectSingleNode($"//param[@name='{refParamName}']");
629-
if (iidNode is not null)
637+
// Get the xml node for the ref parameter docs
638+
XmlNode? refNode = tmpbuilder.docs.SelectSingleNode($"//param[@name='{refParamName}']");
639+
if (refNode is not null)
630640
{
631-
// Add the IID parameter docs to the method docs as the value of the typeParam tag
641+
// Add the ref parameter docs to the method docs as the value of the typeParam tag
632642
if (unmanagedType == UnmanagedType.IUnknown)
633-
tmpbuilder.docs.InsertTypeParamDocAfter(genericType, iidNode.InnerXml);
643+
tmpbuilder.docs.InsertTypeParamDocAfter(genericType, refNode.InnerXml);
634644

635-
// Remove the IID parameter docs
636-
iidNode.ParentNode?.RemoveChild(iidNode);
645+
// Remove the ref parameter docs
646+
refNode.ParentNode?.RemoveChild(refNode);
647+
648+
// Remove the "<paramref name="refParamName"/>" tags from the entire document
649+
XmlElement replElem = tmpbuilder.docs.CreateElement("c");
650+
replElem.InnerText = refParamName;
651+
foreach (var n in tmpbuilder.docs.SelectNodes($"//paramref[@name='{refParamName}']").Cast<XmlElement>().Where(n => n.ParentNode is not null))
652+
n.ParentNode?.ReplaceChild(replElem, n);
637653
}
638654
}
639655

@@ -676,25 +692,36 @@ bool ValidateAttr(out string refParamName, out UnmanagedType unmanagedType)
676692
break;
677693

678694
case UnmanagedType.LPArray:
679-
//refindex = GetIndex("SizeParamIndex");
680-
//if (refindex == -1 || modAttr != ModType.In)
681-
// return false;
682-
//break;
695+
refindex = GetIndex("SizeParamIndex");
696+
if (refindex == -1 || modAttr != ModType.In)
697+
return false;
698+
break;
699+
683700
default:
684701
return false;
685702
}
686703
}
687704

688-
// If there's an refindex, then make sure it points to a valid Guid parameter
705+
// If there's an refindex, then make sure it points to a valid parameter
689706
if (refindex >= 0)
690707
{
691708
var iidParam = methodDecl.ParameterList.Parameters[refindex];
692709
var paramType = iidParam.Type?.ToString();
693-
var hasInModifier = iidParam.Modifiers.Any(SyntaxKind.InKeyword);
694-
var hasStructAttribute = !hasInModifier && iidParam.AttributeLists
695-
.SelectMany(al => al.Attributes)
696-
.Any(attr => attr.Name.ToFullString() == "MarshalAs" && attr.ArgumentList?.Arguments.FirstOrDefault()?.ToString() == "UnmanagedType.Struct");
697-
if ((paramType == "System.Guid" || paramType == "Guid") && (hasInModifier || hasStructAttribute))
710+
// For interfaces, confirm param type is Guid
711+
if (unmanagedType is UnmanagedType.IUnknown or UnmanagedType.Interface)
712+
{
713+
var hasInModifier = iidParam.Modifiers.Any(SyntaxKind.InKeyword);
714+
var hasStructAttribute = !hasInModifier && iidParam.AttributeLists
715+
.SelectMany(al => al.Attributes)
716+
.Any(attr => attr.Name.ToFullString() == "MarshalAs" && attr.ArgumentList?.Arguments.FirstOrDefault()?.ToString() == "UnmanagedType.Struct");
717+
if ((paramType == "System.Guid" || paramType == "Guid") && (hasInModifier || hasStructAttribute))
718+
{
719+
refParamName = iidParam.Identifier.Text;
720+
return true;
721+
}
722+
}
723+
// For LPArray, type is integral so pass along
724+
else if (unmanagedType == UnmanagedType.LPArray)
698725
{
699726
refParamName = iidParam.Identifier.Text;
700727
return true;
@@ -715,18 +742,27 @@ int GetIndex(string attrNamedArg)
715742

716743
private static TypeDeclarationSyntax GetParamType(SourceProductionContext context, ParameterSyntax decl) => GetFirstTypeParent(context, decl);
717744

718-
private static bool IsParamInNotNewStaticMethod(SyntaxNode syntaxNode, CancellationToken cancellationToken) =>
719-
syntaxNode is ParameterSyntax ps && ps.Parent?.Parent is MethodDeclarationSyntax ms && !ms.Modifiers.Any(SyntaxKind.NewKeyword) && ms.Modifiers.Any(SyntaxKind.StaticKeyword);
745+
// Confirm param is in a method is not new or unsafe and does not have SuppressAutoGen attribute
746+
private static bool IsParamInMethod(SyntaxNode syntaxNode, CancellationToken cancellationToken, out MethodDeclarationSyntax? ms)
747+
{
748+
ms = syntaxNode is ParameterSyntax ps && ps.Parent?.Parent is MethodDeclarationSyntax mds
749+
&& !mds.Modifiers.Any(SyntaxKind.UnsafeKeyword) && !mds.Modifiers.Any(SyntaxKind.NewKeyword)
750+
&& !mds.AttributeLists.SelectMany(al => al.Attributes).Any(a => a.Name.ToString().Contains("SuppressAutoGen")) ? mds : null;
751+
return ms is not null;
752+
}
753+
754+
private static bool IsParamInMethod(SyntaxNode syntaxNode, CancellationToken cancellationToken) => IsParamInMethod(syntaxNode, cancellationToken, out _);
720755

721-
private static bool IsParamInNotNewMethod(SyntaxNode syntaxNode, CancellationToken cancellationToken) =>
722-
syntaxNode is ParameterSyntax ps && ps.Parent?.Parent is MethodDeclarationSyntax ms && !ms.Modifiers.Any(SyntaxKind.NewKeyword);
756+
private static bool IsParamInStaticMethod(SyntaxNode syntaxNode, CancellationToken cancellationToken) =>
757+
IsParamInMethod(syntaxNode, cancellationToken, out var ms) && ms!.Modifiers.Any(SyntaxKind.StaticKeyword);
723758

724-
private static bool IsParamWithArgs(SyntaxNode syntaxNode, CancellationToken cancellationToken) => syntaxNode is ParameterSyntax ps &&
725-
ps.Parent?.Parent is MethodDeclarationSyntax ms && !ms.Modifiers.Any(SyntaxKind.NewKeyword) &&
726-
(ms?.Parent is ClassDeclarationSyntax cs && cs.IsPartial() || ms?.Parent is InterfaceDeclarationSyntax && ms?.Parent?.Parent is ClassDeclarationSyntax ccs && ccs.IsPartial());
759+
private static bool IsParamInNestedType(SyntaxNode syntaxNode, CancellationToken cancellationToken) =>
760+
IsParamInMethod(syntaxNode, cancellationToken, out var ms) &&
761+
((ms?.Parent is ClassDeclarationSyntax cs && cs.IsPartial() && ms.Modifiers.Any(SyntaxKind.StaticKeyword) && ms.Modifiers.Any(SyntaxKind.ExternKeyword)) ||
762+
(ms?.Parent is InterfaceDeclarationSyntax && ms?.Parent?.Parent is ClassDeclarationSyntax ccs && ccs.IsPartial()));
727763

728764
private static bool IsPartialType(SyntaxNode syntaxNode, CancellationToken cancellationToken) => syntaxNode is TypeDeclarationSyntax tds && tds.IsPartial();
729-
765+
730766
private static TypeDeclarationSyntax ParentForExtMethod(SourceProductionContext context, ParameterSyntax decl)
731767
{
732768
var parentClass = decl.Parent?.Parent?.Parent is ClassDeclarationSyntax cs ? cs : (decl.Parent?.Parent?.Parent is InterfaceDeclarationSyntax && decl.Parent?.Parent?.Parent?.Parent is ClassDeclarationSyntax ccs ? ccs : null);

PInvoke/ComCtl32/CommCtrl.ImageList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2550,7 +2550,7 @@ public partial class SafeHIMAGELIST
25502550
{
25512551
/// <summary>Gets the IImageList interface for this handle.</summary>
25522552
/// <value>The interface.</value>
2553-
public IImageList Interface => HIMAGELIST_QueryInterface<IImageList>(handle);
2553+
public IImageList Interface => HIMAGELIST_QueryInterface<IImageList>(handle)!;
25542554

25552555
/// <summary>Gets a safe HIMAGELIST handle from an <see cref="IImageList"/> instance.</summary>
25562556
/// <param name="iil">An IImageList object.</param>

PInvoke/CoreAudio/AudioClient.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ public interface IAcousticEchoCancellationControl
158158
public interface IAudioAmbisonicsControl
159159
{
160160
/// <summary>Undocumented</summary>
161+
/// <param name="pAmbisonicsParams"></param>
162+
/// <param name="cbAmbisonicsParams"></param>
163+
/// <returns></returns>
161164
[PreserveSig]
162165
HRESULT SetData([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] AMBISONICS_PARAMS[] pAmbisonicsParams,
163166
uint cbAmbisonicsParams);

PInvoke/Cryptography/Crypt32/Wincrypt.OID.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public delegate bool PFN_CRYPT_ENUM_OID_FUNC(CertEncodingType dwEncodingType, [M
6868
[return: MarshalAs(UnmanagedType.Bool)]
6969
public delegate bool PFN_CRYPT_ENUM_OID_INFO(PCCRYPT_OID_INFO pInfo, [In, Out, Optional] IntPtr pvArg);
7070

71-
/// <summary>Flags for <see cref="CryptInstallOIDFunctionAddress"/>.</summary>
71+
/// <summary>Flags for <see cref="CryptInstallOIDFunctionAddress(HINSTANCE, CertEncodingType, string, uint, CRYPT_OID_FUNC_ENTRY[], CryptInstallOIDFuncFlags)"/>.</summary>
7272
[PInvokeData("wincrypt.h", MSDNShortId = "934e8278-0e0b-4402-a2b6-ff1e913d54c9")]
7373
[Flags]
7474
public enum CryptInstallOIDFuncFlags

PInvoke/Cryptography/Crypt32/Wincrypt.Verification.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ public enum CertChainStrongSignFlags
250250
CERT_CHAIN_STRONG_SIGN_DISABLE_END_CHECK_FLAG = 0x00000001,
251251
}
252252

253-
/// <summary>Flags used by <see cref="CertCreateCTLEntryFromCertificateContextProperties"/>.</summary>
253+
/// <summary>Flags used by <see cref="CertCreateCTLEntryFromCertificateContextProperties(PCCERT_CONTEXT, uint, CRYPT_ATTRIBUTE[], CertCreateCTLEntryFlags, IntPtr, IntPtr, ref uint)"/>.</summary>
254254
[PInvokeData("wincrypt.h", MSDNShortId = "90ac512f-3cbe-4543-9b34-8e384f730cfe")]
255255
[Flags]
256256
public enum CertCreateCTLEntryFlags
@@ -305,7 +305,7 @@ public enum CryptMsgEncodeFlags
305305
CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x2,
306306
}
307307

308-
/// <summary>Flags for <see cref="CryptMsgGetAndVerifySigner"/>.</summary>
308+
/// <summary>Flags for <see cref="CryptMsgGetAndVerifySigner(HCRYPTMSG, uint, HCERTSTORE[], CryptMsgSignerFlags, out SafePCCERT_CONTEXT, ref uint)"/>.</summary>
309309
[PInvokeData("wincrypt.h", MSDNShortId = "380c9cf3-27a2-4354-b1c8-97cec33f4e44")]
310310
[Flags]
311311
public enum CryptMsgSignerFlags

PInvoke/DXCore/DXCore.cs

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,65 +2301,6 @@ public interface IDXCoreAdapterList
23012301
bool IsAdapterPreferenceSupported(DXCoreAdapterPreference preference);
23022302
}
23032303

2304-
/// <summary>
2305-
/// Generates a list of adapter objects representing the current adapter state of the system, and meeting the criteria specified. For
2306-
/// programming guidance, and code examples, see <c>Using DXCore to enumerate adapters</c>.
2307-
/// </summary>
2308-
/// <typeparam name="T">The type of the interface that you wish to be returned in ppvAdapterList. This is expected to be IDXCoreAdapterList.</typeparam>
2309-
/// <param name="factory">The <see cref="IDXCoreAdapterFactory"/> instance.</param>
2310-
/// <param name="filterAttributes">
2311-
/// An array of adapter attribute GUIDs. For a list of attribute GUIDs, see DXCore adapter attribute GUIDs. At least one GUID must be
2312-
/// provided. In the case that more than one GUID is provided in the array, only adapters that meet all of the requested attributes will
2313-
/// be included in the returned list.
2314-
/// </param>
2315-
/// <param name="ppvAdapterList">
2316-
/// The address of a pointer to an interface with the IID specified in the riid parameter. Upon successful return, *ppvAdapterList (the
2317-
/// dereferenced address) contains a pointer to the adapter list created.
2318-
/// </param>
2319-
/// <returns>
2320-
/// <para>Type: <b><c>HRESULT</c></b></para>
2321-
/// <para>If the function succeeds, it returns <b>S_OK</b>. Otherwise, it returns an <c><b>HRESULT</b></c><c>error code</c>.</para>
2322-
/// <list type="table">
2323-
/// <listheader>
2324-
/// <description>Return value</description>
2325-
/// <description>Description</description>
2326-
/// </listheader>
2327-
/// <item>
2328-
/// <description>E_INVALIDARG</description>
2329-
/// <description>
2330-
/// <code>nullptr</code>
2331-
/// was provided for <c>filterAttributes</c>, or 0 was provided for <c>numAttributes</c>.
2332-
/// </description>
2333-
/// </item>
2334-
/// <item>
2335-
/// <description>E_NOINTERFACE</description>
2336-
/// <description>An invalid value was provided for <c>riid</c>.</description>
2337-
/// </item>
2338-
/// <item>
2339-
/// <description>E_POINTER</description>
2340-
/// <description>
2341-
/// <code>nullptr</code>
2342-
/// was provided for <c>ppvAdapterList</c>.
2343-
/// </description>
2344-
/// </item>
2345-
/// </list>
2346-
/// </returns>
2347-
/// <remarks>
2348-
/// Even if no adapters are found, as long as the arguments are valid, <b>CreateAdapterList</b> creates a valid
2349-
/// <c>IDXCoreAdapterList</c> object, and returns <b>S_OK</b>. Once generated, the adapters in this specific list won't change. But the
2350-
/// list will be considered stale if one of the adapters later becomes invalid, or if a new adapter arrives that meets the provided
2351-
/// filter criteria. The list returned by <b>CreateAdapterList</b> is not ordered in any particular way, but the ordering of a list is
2352-
/// consistent across multiple calls, and even across operating system restarts. The ordering may change upon system configuration
2353-
/// changes, including the addition or removal of an adapter, or a driver update on an existing adapter. You can register for these
2354-
/// changes with <c>IDXCoreAdapterFactory::RegisterEventNotification</c> using the notification type <b>DXCoreNotificationType.AdapterListStale</b>.
2355-
/// </remarks>
2356-
public static HRESULT CreateAdapterList<T>(this IDXCoreAdapterFactory factory, Guid[] filterAttributes, out T? ppvAdapterList) where T : class
2357-
{
2358-
var hr = factory.CreateAdapterList(filterAttributes.Length, filterAttributes, typeof(T).GUID, out var ppv);
2359-
ppvAdapterList = (T?)ppv;
2360-
return hr;
2361-
}
2362-
23632304
/// <summary>
23642305
/// Creates a DXCore adapter factory, which you can use to generate further DXCore objects. For programming guidance, and code examples,
23652306
/// see Using DXCore to enumerate adapters.

0 commit comments

Comments
 (0)