Vanara/PInvoke/SetupAPI/SetupAPI.DiFuncs2.cs

4901 lines
298 KiB
C#

using Microsoft.Win32.SafeHandles;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
/// <summary>Items from the SetupAPI.dll</summary>
public static partial class SetupAPI
{
/// <summary>
/// The <c>SetupDiGetClassProperty</c> function retrieves a device property that is set for a device setup class or a device
/// interface class.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to a GUID that identifies the device setup class or device interface class for which to retrieve a device property
/// that is set for the device class. For information about specifying the class type, see the Flags parameter.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the requested device class property.
/// </param>
/// <param name="PropertyType">
/// A pointer to a DEVPROPTYPE-typed variable that receives the property-data-type identifier of the requested device class
/// property, where the property-data-type identifier is the bitwise OR between a base-data-type identifier and, if the base data
/// type is modified, a property-data-type modifier.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that receives the requested device class property. <c>SetupDiGetClassProperty</c> retrieves the requested
/// property value only if the buffer is large enough to hold all the property value data. The pointer can be <c>NULL</c>. If the
/// pointer is set to <c>NULL</c> and RequiredSize is supplied, <c>SetupDiGetClassProperty</c> returns the size of the device class
/// property, in bytes, in *RequiredSize.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="RequiredSize">
/// A pointer to a DWORD-typed variable that receives either the size, in bytes, of the device class property if the device class
/// property is retrieved or the required buffer size if the buffer is not large enough. This pointer can be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">
/// <para>One of the following values, which specifies whether the class is a device setup class or a device interface class.</para>
/// <para>DICLASSPROP_INSTALLER</para>
/// <para>ClassGuid specifies a device setup class. This flag cannot be used with DICLASSPROP_INTERFACE.</para>
/// <para>DICLASSPROP_INTERFACE</para>
/// <para>ClassGuid specifies a device interface class. This flag cannot be used with DICLASSPROP_INSTALLER.</para>
/// </param>
/// <returns>
/// <para>
/// <c>SetupDiGetClassProperty</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged error
/// can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_CLASS</term>
/// <term>
/// The device setup class that is specified by ClassGuid is not valid. This error can occur only if the DICLASSPROP_INSTALLER flag
/// is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An unspecified parameter is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REFERENCE_STRING</term>
/// <term>The device interface reference string is not valid. This error can be returned if the DICLASSPROP_INTERFACE flag is specified.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified internal data value was not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertyBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_CLASS</term>
/// <term>
/// The device interface class that is specified by ClassGuid does not exist. This error can occur only if the DICLASSPROP_INTERFACE
/// flag is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>An internal data buffer that was passed to a system call was too small.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>The requested device property does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetClassProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiGetClassProperty</c>.</para>
/// <para>A caller of <c>SetupDiGetClassProperty</c> must be a member of the Administrators group to set a device interface property.</para>
/// <para>
/// To obtain the device property keys that represent the device properties that are set for a device class on a local computer,
/// call SetupDiGetClassPropertyKeys.
/// </para>
/// <para>To retrieve a device class property on a remote computer, call SetupDiGetClassPropertyEx.</para>
/// <para>
/// To set a device class property on a local computer, call SetupDiSetClassProperty <c>,</c> and to set a device class property on
/// a remote computer, call SetupDiSetClassPropertyEx.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetclasspropertyw WINSETUPAPI BOOL
// SetupDiGetClassPropertyW( const GUID *ClassGuid, const DEVPROPKEY *PropertyKey, DEVPROPTYPE *PropertyType, PBYTE PropertyBuffer,
// DWORD PropertyBufferSize, PDWORD RequiredSize, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetClassPropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetClassProperty(in Guid ClassGuid, in DEVPROPKEY PropertyKey, out DEVPROPTYPE PropertyType,
[Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, out uint RequiredSize, DICLASSPROP Flags);
/// <summary>
/// The <c>SetupDiGetClassPropertyEx</c> function retrieves a class property for a device setup class or a device interface class on
/// a local or remote computer.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to a GUID that identifies the device setup class or device interface class for which to retrieve a device property for
/// the device class. For information about specifying the class type, see the Flags parameter.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the requested device class property.
/// </param>
/// <param name="PropertyType">
/// A pointer to a DEVPROPTYPE-typed variable that receives the property-data-type identifier of the requested device class
/// property, where the property-data-type identifier is the bitwise OR between a base-data-type identifier and, if the base data
/// type is modified, a property-data-type modifier.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that receives the requested device class property. <c>SetupDiGetClassPropertyEx</c> retrieves the
/// requested property value only if the buffer is large enough to hold all the property value data. The pointer can be <c>NULL</c>.
/// If the pointer is set to <c>NULL</c> and RequiredSize is supplied, <c>SetupDiGetClassPropertyEx</c> returns the size of the
/// device class property, in bytes, in *RequiredSize.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="RequiredSize">
/// A pointer to a DWORD-typed variable that receives either the size, in bytes, of the device class property if the property is
/// retrieved or the required buffer size if the buffer is not large enough. This pointer can be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">
/// <para>One of the following values, which specifies whether the class is a device setup class or a device interface class:</para>
/// <para>DICLASSPROP_INSTALLER</para>
/// <para>ClassGuid specifies a device setup class. This flag cannot be used with DICLASSPROP_INTERFACE.</para>
/// <para>DICLASSPROP_INTERFACE</para>
/// <para>ClassGuid specifies a device interface class. This flag cannot be used with DICLASSPROP_INSTALLER.</para>
/// </param>
/// <param name="MachineName">
/// A pointer to a NULL-terminated string that contains the UNC name, including the "\" prefix, of a computer. The pointer can be
/// set to <c>NULL</c>. If MachineName is <c>NULL</c>, <c>SetupDiGetClassPropertyEx</c> retrieves the requested device class
/// property from the local computer.
/// </param>
/// <param name="Reserved">This parameter must be set to <c>NULL</c>.</param>
/// <returns>
/// <para>
/// <c>SetupDiGetClassPropertyEx</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_CLASS</term>
/// <term>
/// The device setup class that is specified by ClassGuid is not valid. This error can occur only if the DICLASSPROP_INSTALLER flag
/// is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An unspecified parameter is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REFERENCE_STRING</term>
/// <term>The device interface reference string is not valid. This error can be returned if the DICLASSPROP_INTERFACE flag is specified.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified internal data value was not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertyBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_MACHINENAME</term>
/// <term>The computer name that is specified by MachineName is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_CLASS</term>
/// <term>
/// The device interface class that is specified by ClassGuid does not exist. This error can occur only if the DICLASSPROP_INTERFACE
/// flag is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>An internal data buffer that was passed to a system call was too small.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>The requested device property does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetClassPropertyEx</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiGetClassPropertyEx</c>.</para>
/// <para>A caller of <c>SetupDiGetClassPropertyEx</c> must be a member of the Administrators group to set a device interface property.</para>
/// <para>
/// To obtain the device property keys that represent the device properties that are set for a device class on a remote computer,
/// call SetupDiGetClassPropertyKeysEx.
/// </para>
/// <para>To retrieve a device class property on a local computer, call SetupDiGetClassProperty.</para>
/// <para>
/// To set a device class property on a local computer, call SetupDiSetClassProperty <c>,</c> and to set a device class property on
/// a remote computer, call SetupDiSetClassPropertyEx.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetclasspropertyexw WINSETUPAPI BOOL
// SetupDiGetClassPropertyExW( const GUID *ClassGuid, const DEVPROPKEY *PropertyKey, DEVPROPTYPE *PropertyType, PBYTE
// PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize, DWORD Flags, PCWSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetClassPropertyExW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetClassPropertyEx(in Guid ClassGuid, in DEVPROPKEY PropertyKey, out DEVPROPTYPE PropertyType,
[Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, out uint RequiredSize, DICLASSPROP Flags,
[Optional, MarshalAs(UnmanagedType.LPWStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>
/// The <c>SetupDiGetClassPropertyKeys</c> function retrieves an array of the device property keys that represent the device
/// properties that are set for a device setup class or a device interface class.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to a GUID that represents a device setup class or a device interface class. <c>SetupDiGetClassPropertyKeys</c>
/// retrieves an array of the device property keys that represent device properties that are set for the specified class. For
/// information about specifying the class type, see the Flags parameter.
/// </param>
/// <param name="PropertyKeyArray">
/// A pointer to a buffer that receives an array of DEVPROPKEY-typed values, where each value is a device property key that
/// represents a device property that is set for the device class. The pointer is optional and can be <c>NULL</c>. For more
/// information, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyKeyCount">
/// The size, in DEVPROPKEY-typed values, of the PropertyKeyArray buffer. If PropertyKeyArray is set to <c>NULL</c>,
/// PropertyKeyCount must be set to zero.
/// </param>
/// <param name="RequiredPropertyKeyCount">
/// A pointer to a DWORD-typed variable that receives the number of requested property keys. The parameter is optional and can be
/// set to <c>NULL</c>.
/// </param>
/// <param name="Flags">
/// <para>
/// One of the following values, which specifies whether to retrieve property keys for a device setup class or for a device
/// interface class:
/// </para>
/// <para>DICLASSPROP_INSTALLER</para>
/// <para>ClassGuid specifies a device setup class. This flag cannot be used with DICLASSPROP_INTERFACE.</para>
/// <para>DICLASSPROP_INTERFACE</para>
/// <para>ClassGuid specifies a device interface class. This flag cannot be used with DICLASSPROP_INSTALLER.</para>
/// </param>
/// <returns>
/// <para>
/// <c>SetupDiGetClassPropertyKeys</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_CLASS</term>
/// <term>
/// If the DICLASSPROP_INSTALLER flag is specified, this error code indicates that the device setup class that is specified by
/// ClassGuid does not exist.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REFERENCE_STRING</term>
/// <term>
/// The reference string for the device interface that is specified by ClassGuild is not valid. This error can be returned if the
/// DICLASSPROP_INTERFACE flag is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified data value is not valid. One possibility is that the ClassGuid value is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An unspecified parameter is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyKeyArray is NULL, and PropertKeyCount is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_CLASS</term>
/// <term>
/// If the DICLASSPROP_INTERFACE flag is specified, this error code indicates that the device interface class that is specified by
/// ClassGuid does not exist.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICENT_BUFFER</term>
/// <term>
/// The PropertyKeyArray buffer is not large enough to hold all the property keys, or an internal data buffer that was passed to a
/// system call was too small.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetClassPropertyKeys</c> is part of the unified device property model.</para>
/// <para>
/// A caller of <c>SetupDiGetClassPropertyKeys</c> must be a member of the Administrators group to retrieve device property keys for
/// a device class.
/// </para>
/// <para>
/// If the PropertyKeyArray buffer is not large enough to hold all the requested property keys, <c>SetupDiGetClassPropertyKeys</c>
/// does not retrieve any property keys and returns ERROR_INSUFFICIENT_BUFFER. If the caller supplied a RequiredPropertyKeyCount
/// pointer, <c>SetupDiGetClassPropertyKeys</c> sets the value of *RequiredPropertyKeyCount to the required size, in
/// DEVPROPKEY-typed values, of the PropertyKeyArray buffer.
/// </para>
/// <para>
/// To retrieve a device class property on a local computer, call SetupDiGetClassProperty. To set a device class property on a local
/// computer, call SetupDiSetClassProperty.
/// </para>
/// <para>To retrieve the property keys for a device setup class or device interface class on a remote computer, call SetupDiGetClassPropertyKeysEx.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetclasspropertykeys WINSETUPAPI BOOL
// SetupDiGetClassPropertyKeys( const GUID *ClassGuid, DEVPROPKEY *PropertyKeyArray, DWORD PropertyKeyCount, PDWORD
// RequiredPropertyKeyCount, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetClassPropertyKeys")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetClassPropertyKeys(in Guid ClassGuid,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] DEVPROPKEY[] PropertyKeyArray, uint PropertyKeyCount,
out uint RequiredPropertyKeyCount, DICLASSPROP Flags);
/// <summary>
/// The <c>SetupDiGetClassPropertyKeysEx</c> function retrieves an array of the device property keys that represent the device
/// properties that are set for a device setup class or a device interface class on a local or a remote computer.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to a GUID that represents a device setup class or a device interface class. <c>SetupDiGetClassPropertyKeysEx</c>
/// retrieves an array of the device property keys that represent device properties that are set for the specified class. For
/// information about specifying the class type, see the Flags parameter.
/// </param>
/// <param name="PropertyKeyArray">
/// A pointer to a buffer that receives an array of DEVPROPKEY-typed values, where each value is a device property key that
/// represents a device property that is set for the device setup class. The pointer is optional and can be <c>NULL</c>. For more
/// information, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyKeyCount">
/// The size, in DEVPROPKEY-type values, of the PropertyKeyArray buffer. If PropertyKeyArray is set to <c>NULL</c>, PropertyKeyCount
/// must be set to zero.
/// </param>
/// <param name="RequiredPropertyKeyCount">
/// A pointer to a DWORD-typed variable that receives the number of requested property keys. The pointer is optional and can be set
/// to <c>NULL</c>.
/// </param>
/// <param name="Flags">
/// <para>
/// One of the following values, which specifies whether to retrieve class property keys for a device setup class or for a device
/// interface class.
/// </para>
/// <para>DICLASSPROP_INSTALLER</para>
/// <para>ClassGuid specifies a device setup class. This flag cannot be used with DICLASSPROP_INTERFACE.</para>
/// <para>DICLASSPROP_INTERFACE</para>
/// <para>ClassGuid specifies a device interface class. This flag cannot be used with DICLASSPROP_INSTALLER.</para>
/// </param>
/// <param name="MachineName">
/// A pointer to a NULL-terminated string that contains the UNC name, including the "\" prefix, of a computer. The pointer can be
/// <c>NULL</c>. If the pointer is <c>NULL</c>, <c>SetupDiGetClassPropertyKeysEx</c> retrieves the requested information from the
/// local computer.
/// </param>
/// <param name="Reserved">This parameter must be set to <c>NULL</c>.</param>
/// <returns>
/// <para>
/// <c>SetupDiGetClassPropertyKeysEx</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_CLASS</term>
/// <term>
/// If the DICLASSPROP_INSTALLER flag is specified, this error code indicates that the device setup class that is specified by
/// ClassGuid does not exist.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REFERENCE_STRING</term>
/// <term>
/// The reference string for the device interface that is specified by ClassGuild is not valid. This error might be returned when
/// the DICLASSPROP_INTERFACE flag is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified data value is not valid. One possibility is that the ClassGuid value is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An unspecified parameter is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyKeyArray is NULL, and PropertKeyCount is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_MACHINENAME</term>
/// <term>The computer name that is specified by MachineName is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_CLASS</term>
/// <term>
/// If the DICLASSPROP_INTERFACE flag is specified, this error code indicates that the device interface class that is specified by
/// ClassGuid does not exist.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICENT_BUFFER</term>
/// <term>
/// The PropertyKeyArray buffer is not large enough to hold all the property keys, or an internal data buffer that was passed to a
/// system call was too small.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetClassPropertyKeysEx</c> is part of the unified device property model.</para>
/// <para>
/// A caller of <c>SetupDiGetClassPropertyKeysEx</c> must be a member of the Administrators group to retrieve device property keys
/// for a device class.
/// </para>
/// <para>
/// If the PropertyKeyArray buffer is not large enough to hold all the requested property keys, <c>SetupDiGetClassPropertyKeysEx</c>
/// does not retrieve any property keys and returns ERROR_INSUFFICIENT_BUFFER. If the caller supplied a RequiredPropertyKeyCount
/// pointer, <c>SetupDiGetClassPropertyKeysEx</c> sets the value of *RequiredPropertyKeyCount to the required size, in
/// DEVPROPKEY-typed values, of the PropertyKeyArray buffer.
/// </para>
/// <para>
/// To retrieve a device class property on a remote computer, call SetupDiGetClassPropertyEx, and to set a device class property on
/// a remote computer, call SetupDiSetClassPropertyEx.
/// </para>
/// <para>To retrieve the property keys for a device setup class or device interface class on a local computer, call SetupDiGetClassPropertyKeys.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetclasspropertykeysexw WINSETUPAPI BOOL
// SetupDiGetClassPropertyKeysExW( const GUID *ClassGuid, DEVPROPKEY *PropertyKeyArray, DWORD PropertyKeyCount, PDWORD
// RequiredPropertyKeyCount, DWORD Flags, PCWSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetClassPropertyKeysExW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetClassPropertyKeysEx(in Guid ClassGuid,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] DEVPROPKEY[] PropertyKeyArray, uint PropertyKeyCount,
out uint RequiredPropertyKeyCount, DICLASSPROP Flags, [Optional, MarshalAs(UnmanagedType.LPWStr)] string MachineName,
[In, Optional] IntPtr Reserved);
/// <summary>
/// The <c>SetupDiGetClassRegistryProperty</c> function retrieves a property for a specified device setup class from the registry.
/// </summary>
/// <param name="ClassGuid">A pointer to a GUID representing the device setup class for which a property is to be retrieved.</param>
/// <param name="Property">
/// <para>A value that identifies the property to be retrieved. This must be one of the following values:</para>
/// <para>SPCRP_CHARACTERISTICS</para>
/// <para>
/// The function returns flags indicating device characteristics for the class. For a list of characteristics flags, see the
/// DeviceCharacteristics parameter to IoCreateDevice.
/// </para>
/// <para>SPCRP_DEVTYPE</para>
/// <para>
/// The function returns a DWORD value that represents the device type for the class. For more information, see Specifying Device Types.
/// </para>
/// <para>SPCRP_EXCLUSIVE</para>
/// <para>
/// The function returns a DWORD value indicating whether users can obtain exclusive access to devices for this class. The returned
/// value is one if exclusive access is allowed, or zero otherwise.
/// </para>
/// <para>SPCRP_LOWERFILTERS</para>
/// <para>
/// (Windows Vista and later) The function returns a REG_MULTI_SZ list of the service names of the lower filter drivers that are
/// installed for the device setup class.
/// </para>
/// <para>SPCRP_SECURITY</para>
/// <para>
/// The function returns the device's security descriptor as a SECURITY_DESCRIPTOR structure in self-relative format (described in
/// the Microsoft Windows SDK documentation).
/// </para>
/// <para>SPCRP_SECURITY_SDS</para>
/// <para>
/// The function returns the device's security descriptor as a text string. For information about security descriptor strings, see
/// Security Descriptor Definition Language (Windows). For information about the format of security descriptor strings, see Security
/// Descriptor Definition Language (Windows).
/// </para>
/// <para>SPCRP_UPPERFILTERS</para>
/// <para>
/// (Windows Vista and later) The function returns a REG_MULTI_SZ list of the service names of the upper filter drivers that are
/// installed for the device setup class.
/// </para>
/// </param>
/// <param name="PropertyRegDataType">
/// A pointer to a variable of type DWORD that receives the property data type as one of the REG_-prefixed registry data types. This
/// parameter is optional and can be <c>NULL</c>. If this parameter is <c>NULL</c>, S <c>etupDiGetClassRegistryProperty</c> does not
/// return the data type.
/// </param>
/// <param name="PropertyBuffer">A pointer to a buffer that receives the requested property.</param>
/// <param name="PropertyBufferSize">The size, in bytes, of the PropertyBuffer buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the required size, in bytes, of the PropertyBuffer buffer. If the
/// PropertyBuffer buffer is too small, and RequiredSize is not <c>NULL</c>, the function sets RequiredSize to the minimum buffer
/// size that is required to receive the requested property.
/// </param>
/// <param name="MachineName">
/// A pointer to a NULL-terminated string that contains the name of a remote system from which to retrieve the specified device
/// class property. This parameter is optional and can be <c>NULL</c>. If this parameter is <c>NULL</c>, the property is retrieved
/// from the local system.
/// </param>
/// <param name="Reserved">Reserved, must be <c>NULL</c>.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetclassregistrypropertya WINSETUPAPI BOOL
// SetupDiGetClassRegistryPropertyA( const GUID *ClassGuid, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD
// PropertyBufferSize, PDWORD RequiredSize, PCSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetClassRegistryPropertyA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetClassRegistryProperty(in Guid ClassGuid, SPCRP Property, out REG_VALUE_TYPE PropertyRegDataType,
[Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, out uint RequiredSize,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>The <c>SetupDiGetCustomDeviceProperty</c> function retrieves a specified custom device property from the registry.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element that represents the device for which to
/// retrieve a custom device property.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <param name="CustomPropertyName">A registry value name representing a custom property.</param>
/// <param name="Flags">
/// <para>A flag value that indicates how the requested information should be returned. The flag can be zero or one of the following:</para>
/// <para>DICUSTOMDEVPROP_MERGE_MULTISZ</para>
/// <para>
/// If set, the function retrieves both device instance-specific property values and hardware ID-specific property values,
/// concatenated as a REG_MULTI_SZ-typed string. (For more information, see the <c>Remarks</c> section on this reference page.)
/// </para>
/// </param>
/// <param name="PropertyRegDataType">
/// A pointer to a variable of type DWORD that receives the data type of the retrieved property. The data type is specified as one
/// of the REG_-prefixed constants that represents registry data types. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="PropertyBuffer">A pointer to a buffer that receives requested property information.</param>
/// <param name="PropertyBufferSize">The size, in bytes, of the PropertyBuffer buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the buffer size, in bytes, that is required to receive the requested
/// information. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// <c>SetupDiGetCustomDeviceProperty</c> returns the required size, regardless of whether the PropertyBuffer buffer is large enough
/// to receive the requested information.
/// </param>
/// <returns>
/// If the operation succeeds, <c>SetupDiGetCustomDeviceProperty</c> returns <c>TRUE</c>. Otherwise, the function returns
/// <c>FALSE</c> and the logged error can be retrieved with a call to GetLastError. If the PropertyBuffer buffer is not large enough
/// to receive the requested information, <c>SetupDiGetCustomDeviceProperty</c> returns <c>FALSE</c> and a subsequent call to
/// GetLastError will return ERROR_INSUFFICIENT_BUFFER.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiGetCustomDeviceProperty</c> retrieves device properties that are associated with a single device instance or with all
/// devices matching a certain hardware ID. (For information about hardware IDs, see Device Identification Strings).
/// </para>
/// <para>
/// Vendors can set properties for a device instance by using INF AddReg directives in INF DDInstall.HW sections and specifying the
/// <c>HKR</c> registry root.
/// </para>
/// <para>Only the system can set properties for hardware IDs. The system supplies an "Icon" property for some hardware IDs.</para>
/// <para>
/// The function first checks to see if the specified property exists for the specified device instance. If so, the property's value
/// is returned. If not, the function checks to see if the property exists for all devices matching the hardware ID of the specified
/// device instance. If so, the property's value is returned. If DICUSTOMDEVPROP_MERGE_MULTISZ is set in Flags, the function returns
/// the property values associated with both the device instance and the hardware ID, if they both exist.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetcustomdevicepropertya WINSETUPAPI BOOL
// SetupDiGetCustomDevicePropertyA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PCSTR CustomPropertyName, DWORD Flags,
// PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetCustomDevicePropertyA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetCustomDeviceProperty(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
[MarshalAs(UnmanagedType.LPTStr)] string CustomPropertyName, DICUSTOMDEVPROP Flags, out REG_VALUE_TYPE PropertyRegDataType,
[Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, out uint RequiredSize);
/// <summary>
/// The <c>SetupDiGetDeviceInfoListClass</c> function retrieves the GUID for the device setup class associated with a device
/// information set if the set has an associated class.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set to query.</param>
/// <param name="ClassGuid">A pointer to variable of type GUID that receives the GUID for the associated class.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If the specified device information set does not have an associated class because a class GUID was not specified when the set
/// was created with SetupDiCreateDeviceInfoList, the function fails. In this case, a call to GetLastError returns ERROR_NO_ASSOCIATED_CLASS.
/// </para>
/// <para>
/// If a device information set is for a remote computer, use SetupDiGetDeviceInfoListDetail to get the associated remote computer
/// handle and computer name.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinfolistclass WINSETUPAPI BOOL
// SetupDiGetDeviceInfoListClass( HDEVINFO DeviceInfoSet, LPGUID ClassGuid );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInfoListClass")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInfoListClass(HDEVINFO DeviceInfoSet, out Guid ClassGuid);
/// <summary>
/// The <c>SetupDiGetDeviceInfoListDetail</c> function retrieves information associated with a device information set including the
/// class GUID, remote computer handle, and remote computer name.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to retrieve information.</param>
/// <param name="DeviceInfoSetDetailData">
/// A pointer to a caller-initialized SP_DEVINFO_LIST_DETAIL_DATA structure that receives the device information set information.
/// For more information about this structure, see the following <c>Remarks</c> section.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If the parameters are valid, <c>SetupDiGetDeviceInfoListDetail</c> sets values in the DeviceInfoSetDetailData structure (except
/// for the <c>cbSize</c> field) and returns status NO_ERROR.
/// </para>
/// <para>
/// A caller of <c>SetupDiGetDeviceInfoListDetail</c> must set DeviceInfoSetDetailData. <c>cbSize</c> to
/// <c>sizeof</c>(SP_DEVINFO_LIST_DETAIL_DATA) or the function will fail and the call to GetLastError will return ERROR_INVALID_USER_BUFFER.
/// </para>
/// <para>
/// If <c>SetupDiGetDeviceInfoListDetail</c> completes successfully, DeviceInfoSetDetailData. <c>ClassGuid</c> contains the class
/// GUID associated with the device information set or a GUID_NULL structure.
/// </para>
/// <para>
/// If <c>SetupDiGetDeviceInfoListDetail</c> completes successfully and the device information set is for a remote system,
/// DeviceInfoSetDetailData. <c>RemoteMachineHandle</c> contains the ConfigMgr32 system handle for accessing the remote system and
/// DeviceInfoSetDetailData. <c>RemoteMachineName</c> contains the name of the remote system. If there is a remote handle for the
/// device information set, it must be used when calling <c>CM_</c> Xxx <c>_Ex</c> functions because the DevInst handles are
/// relative to the remote handle.
/// </para>
/// <para>
/// If the device information set is for the local computer, DeviceInfoSetDetailData. <c>RemoteMachineHandle</c> is <c>NULL</c> and
/// DeviceInfoSetDetailData. <c>RemoteMachineName</c> is an empty string.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinfolistdetaila WINSETUPAPI BOOL
// SetupDiGetDeviceInfoListDetailA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInfoListDetailA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInfoListDetail(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_LIST_DETAIL_DATA DeviceInfoSetDetailData);
/// <summary>
/// The <c>SetupDiGetDeviceInstallParams</c> function retrieves device installation parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set that contains the device installation parameters to retrieve.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This parameter is
/// optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiGetDeviceInstallParams</c> retrieves the installation
/// parameters for the specified device. If this parameter is <c>NULL</c>, the function retrieves the global device installation
/// parameters that are associated with DeviceInfoSet.
/// </param>
/// <param name="DeviceInstallParams">
/// A pointer to an SP_DEVINSTALL_PARAMS structure that receives the device install parameters. DeviceInstallParams. <c>cbSize</c>
/// must be set to the size, in bytes, of the structure before calling this function.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinstallparamsa WINSETUPAPI BOOL
// SetupDiGetDeviceInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS_A
// DeviceInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInstallParams(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, ref SP_DEVINSTALL_PARAMS DeviceInstallParams);
/// <summary>
/// The <c>SetupDiGetDeviceInstallParams</c> function retrieves device installation parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set that contains the device installation parameters to retrieve.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This parameter is
/// optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiGetDeviceInstallParams</c> retrieves the installation
/// parameters for the specified device. If this parameter is <c>NULL</c>, the function retrieves the global device installation
/// parameters that are associated with DeviceInfoSet.
/// </param>
/// <param name="DeviceInstallParams">
/// A pointer to an SP_DEVINSTALL_PARAMS structure that receives the device install parameters. DeviceInstallParams. <c>cbSize</c>
/// must be set to the size, in bytes, of the structure before calling this function.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinstallparamsa WINSETUPAPI BOOL
// SetupDiGetDeviceInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS_A
// DeviceInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInstallParams(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData, ref SP_DEVINSTALL_PARAMS DeviceInstallParams);
/// <summary>
/// The <c>SetupDiGetDeviceInstanceId</c> function retrieves the device instance ID that is associated with a device information element.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the device information element that represents the device for which to
/// retrieve a device instance ID.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <param name="DeviceInstanceId">
/// A pointer to the character buffer that will receive the NULL-terminated device instance ID for the specified device information
/// element. For information about device instance IDs, see Device Identification Strings.
/// </param>
/// <param name="DeviceInstanceIdSize">The size, in characters, of the DeviceInstanceId buffer.</param>
/// <param name="RequiredSize">
/// A pointer to the variable that receives the number of characters required to store the device instance ID.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinstanceida WINSETUPAPI BOOL
// SetupDiGetDeviceInstanceIdA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSTR DeviceInstanceId, DWORD
// DeviceInstanceIdSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInstanceIdA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInstanceId(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
[Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder DeviceInstanceId, uint DeviceInstanceIdSize, out uint RequiredSize);
/// <summary>The <c>SetupDiGetDeviceInterfaceAlias</c> function returns an alias of a specified device interface.</summary>
/// <param name="DeviceInfoSet">
/// A pointer to the device information set that contains the device interface for which to retrieve an alias. This handle is
/// typically returned by SetupDiGetClassDevs.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the device interface in DeviceInfoSet for which to retrieve an
/// alias. This pointer is typically returned by SetupDiEnumDeviceInterfaces.
/// </param>
/// <param name="AliasInterfaceClassGuid">A pointer to a GUID that specifies the interface class of the alias to retrieve.</param>
/// <param name="AliasDeviceInterfaceData">
/// A pointer to a caller-allocated buffer that contains, on successful return, a completed SP_DEVICE_INTERFACE_DATA structure that
/// identifies the requested alias. The caller must set AliasDeviceInterfaceData <c>.cbSize</c> to
/// <c>sizeof</c>(SP_DEVICE_INTERFACE_DATA) before calling this function.
/// </param>
/// <returns>
/// <para>
/// <c>SetupDiGetDeviceInterfaceAlias</c> returns <c>TRUE</c> if the function completed without error. If the function completed
/// with an error, <c>FALSE</c> is returned and the error code for the failure can be retrieved by calling GetLastError.
/// </para>
/// <para>Possible errors returned by GetLastError are listed in the following table.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>Invalid DeviceInfoSet or invalid DeviceInterfaceData parameter.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_DEVICE</term>
/// <term>There is no alias of class AliasInterfaceClassGuid for the specified device interface.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>Invalid AliasDeviceInterfaceData buffer.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Device interfaces are considered aliases if they are of different interface classes but are supported by the same device and
/// have identical reference strings.
/// </para>
/// <para>
/// <c>SetupDiGetDeviceInterfaceAlias</c> can be used to locate a device that exposes more than one interface. For example, consider
/// a disk that can be part of a fault-tolerant volume and can contain encrypted data. The function driver for the disk device could
/// register a fault-tolerant-volume interface and an encrypted-volume interface. These interfaces are device interface aliases if
/// the function driver registers them with identical reference strings and they refer to the same device. (The reference strings
/// will likely be <c>NULL</c> and therefore are equal.)
/// </para>
/// <para>
/// To locate such a multi-interface device, first locate all available devices that expose one of the interfaces, such as the
/// fault-tolerant-volume interface, using SetupDiGetClassDevs and SetupDiEnumDeviceInterfaces. Then, pass a device with the first
/// interface (fault-tolerant-volume) to <c>SetupDiGetDeviceInterfaceAlias</c> and request an alias of the other interface class (encrypted-volume).
/// </para>
/// <para>
/// If the requested alias exists but the caller-supplied AliasDeviceInterfaceData buffer is invalid, this function successfully
/// adds the device interface element to DevInfoSet but returns <c>FALSE</c> for the return value. In this case, GetLastError
/// returns ERROR_INVALID_USER_BUFFER.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacealias WINSETUPAPI BOOL
// SetupDiGetDeviceInterfaceAlias( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, const GUID
// *AliasInterfaceClassGuid, PSP_DEVICE_INTERFACE_DATA AliasDeviceInterfaceData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInterfaceAlias")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceAlias(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
in Guid AliasInterfaceClassGuid, ref SP_DEVICE_INTERFACE_DATA AliasDeviceInterfaceData);
/// <summary>The <c>SetupDiGetDeviceInterfaceDetail</c> function returns details about a device interface.</summary>
/// <param name="DeviceInfoSet">
/// A pointer to the device information set that contains the interface for which to retrieve details. This handle is typically
/// returned by SetupDiGetClassDevs.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the interface in DeviceInfoSet for which to retrieve details.
/// A pointer of this type is typically returned by SetupDiEnumDeviceInterfaces.
/// </param>
/// <param name="DeviceInterfaceDetailData">
/// A pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA structure to receive information about the specified interface. This parameter
/// is optional and can be <c>NULL</c>. This parameter must be <c>NULL</c> if DeviceInterfaceDetailSize is zero. If this parameter
/// is specified, the caller must set DeviceInterfaceDetailData <c>.cbSize</c> to <c>sizeof</c>(SP_DEVICE_INTERFACE_DETAIL_DATA)
/// before calling this function. The <c>cbSize</c> member always contains the size of the fixed part of the data structure, not a
/// size reflecting the variable-length string at the end.
/// </param>
/// <param name="DeviceInterfaceDetailDataSize">
/// <para>
/// The size of the DeviceInterfaceDetailData buffer. The buffer must be at least ( <c>offsetof</c>(SP_DEVICE_INTERFACE_DETAIL_DATA,
/// <c>DevicePath</c>) + <c>sizeof</c>(TCHAR)) bytes, to contain the fixed part of the structure and a single <c>NULL</c> to
/// terminate an empty MULTI_SZ string.
/// </para>
/// <para>This parameter must be zero if DeviceInterfaceDetailData is <c>NULL</c>.</para>
/// </param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the required size of the DeviceInterfaceDetailData buffer. This size
/// includes the size of the fixed part of the structure plus the number of bytes required for the variable-length device path
/// string. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to a buffer that receives information about the device that supports the requested interface. The caller must set
/// DeviceInfoData <c>.cbSize</c> to <c>sizeof</c>(SP_DEVINFO_DATA). This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// <c>SetupDiGetDeviceInterfaceDetail</c> returns <c>TRUE</c> if the function completed without error. If the function completed
/// with an error, <c>FALSE</c> is returned and the error code for the failure can be retrieved by calling GetLastError.
/// </returns>
/// <remarks>
/// <para>Using this function to get details about an interface is typically a two-step process:</para>
/// <list type="number">
/// <item>
/// <term>
/// Get the required buffer size. Call <c>SetupDiGetDeviceInterfaceDetail</c> with a <c>NULL</c> DeviceInterfaceDetailData pointer,
/// a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize variable. In response to such a call, this function returns
/// the required buffer size at RequiredSize and fails with GetLastError returning ERROR_INSUFFICIENT_BUFFER.
/// </term>
/// </item>
/// <item>
/// <term>Allocate an appropriately sized buffer and call the function again to get the interface details.</term>
/// </item>
/// </list>
/// <para>
/// The interface detail returned by this function consists of a device path that can be passed to Win32 functions such as
/// CreateFile. Do not attempt to parse the device path symbolic name. The device path can be reused across system starts.
/// </para>
/// <para>
/// <c>SetupDiGetDeviceInterfaceDetail</c> can be used to get just the DeviceInfoData. If the interface exists but
/// DeviceInterfaceDetailData is <c>NULL</c>, this function fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and the
/// DeviceInfoData structure is filled with information about the device that exposes the interface.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacedetaila WINSETUPAPI BOOL
// SetupDiGetDeviceInterfaceDetailA( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
// PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize,
// PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInterfaceDetailA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
[Out, Optional] IntPtr DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, out uint RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>The <c>SetupDiGetDeviceInterfaceDetail</c> function returns details about a device interface.</summary>
/// <param name="DeviceInfoSet">
/// A pointer to the device information set that contains the interface for which to retrieve details. This handle is typically
/// returned by SetupDiGetClassDevs.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the interface in DeviceInfoSet for which to retrieve details.
/// A pointer of this type is typically returned by SetupDiEnumDeviceInterfaces.
/// </param>
/// <param name="DeviceInterfaceDetailData">
/// A pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA structure to receive information about the specified interface. This parameter
/// is optional and can be <c>NULL</c>. This parameter must be <c>NULL</c> if DeviceInterfaceDetailSize is zero. If this parameter
/// is specified, the caller must set DeviceInterfaceDetailData <c>.cbSize</c> to <c>sizeof</c>(SP_DEVICE_INTERFACE_DETAIL_DATA)
/// before calling this function. The <c>cbSize</c> member always contains the size of the fixed part of the data structure, not a
/// size reflecting the variable-length string at the end.
/// </param>
/// <param name="DeviceInterfaceDetailDataSize">
/// <para>
/// The size of the DeviceInterfaceDetailData buffer. The buffer must be at least ( <c>offsetof</c>(SP_DEVICE_INTERFACE_DETAIL_DATA,
/// <c>DevicePath</c>) + <c>sizeof</c>(TCHAR)) bytes, to contain the fixed part of the structure and a single <c>NULL</c> to
/// terminate an empty MULTI_SZ string.
/// </para>
/// <para>This parameter must be zero if DeviceInterfaceDetailData is <c>NULL</c>.</para>
/// </param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the required size of the DeviceInterfaceDetailData buffer. This size
/// includes the size of the fixed part of the structure plus the number of bytes required for the variable-length device path
/// string. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to a buffer that receives information about the device that supports the requested interface. The caller must set
/// DeviceInfoData <c>.cbSize</c> to <c>sizeof</c>(SP_DEVINFO_DATA). This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// <c>SetupDiGetDeviceInterfaceDetail</c> returns <c>TRUE</c> if the function completed without error. If the function completed
/// with an error, <c>FALSE</c> is returned and the error code for the failure can be retrieved by calling GetLastError.
/// </returns>
/// <remarks>
/// <para>Using this function to get details about an interface is typically a two-step process:</para>
/// <list type="number">
/// <item>
/// <term>
/// Get the required buffer size. Call <c>SetupDiGetDeviceInterfaceDetail</c> with a <c>NULL</c> DeviceInterfaceDetailData pointer,
/// a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize variable. In response to such a call, this function returns
/// the required buffer size at RequiredSize and fails with GetLastError returning ERROR_INSUFFICIENT_BUFFER.
/// </term>
/// </item>
/// <item>
/// <term>Allocate an appropriately sized buffer and call the function again to get the interface details.</term>
/// </item>
/// </list>
/// <para>
/// The interface detail returned by this function consists of a device path that can be passed to Win32 functions such as
/// CreateFile. Do not attempt to parse the device path symbolic name. The device path can be reused across system starts.
/// </para>
/// <para>
/// <c>SetupDiGetDeviceInterfaceDetail</c> can be used to get just the DeviceInfoData. If the interface exists but
/// DeviceInterfaceDetailData is <c>NULL</c>, this function fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and the
/// DeviceInfoData structure is filled with information about the device that exposes the interface.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacedetaila WINSETUPAPI BOOL
// SetupDiGetDeviceInterfaceDetailA( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
// PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize,
// PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInterfaceDetailA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
[Out, Optional] IntPtr DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, out uint RequiredSize, IntPtr DeviceInfoData = default);
/// <summary>The <c>SetupDiGetDeviceInterfaceDetail</c> function returns details about a device interface.</summary>
/// <param name="DeviceInfoSet">
/// A pointer to the device information set that contains the interface for which to retrieve details. This handle is typically
/// returned by SetupDiGetClassDevs.
/// </param>
/// <param name="DeviceInterfaceData">
/// An SP_DEVICE_INTERFACE_DATA structure that specifies the interface in DeviceInfoSet for which to retrieve details. This value is
/// typically returned by SetupDiEnumDeviceInterfaces.
/// </param>
/// <param name="DeviceInterfacePath">
/// A string that contains the device interface path. This path can be passed to Win32 functions such as CreateFile.
/// </param>
/// <param name="DeviceInfoData">Receives information about the device that supports the requested interface.</param>
/// <returns>
/// <c>SetupDiGetDeviceInterfaceDetail</c> returns <c>TRUE</c> if the function completed without error. If the function completed
/// with an error, <c>FALSE</c> is returned and the error code for the failure can be retrieved by calling GetLastError.
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacedetaila WINSETUPAPI BOOL
// SetupDiGetDeviceInterfaceDetailA( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
// PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize,
// PSP_DEVINFO_DATA DeviceInfoData );
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInterfaceDetailA")]
public static bool SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, out string DeviceInterfacePath, out SP_DEVINFO_DATA DeviceInfoData)
{
SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, default, 0, out var sz);
Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER);
using var mem = new SafeSP_DEVICE_INTERFACE_DETAIL_DATA(sz);
DeviceInfoData = new SP_DEVINFO_DATA { cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA)) };
var ret = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, mem, sz, out sz, ref DeviceInfoData);
DeviceInterfacePath = ret ? mem.DevicePath : null;
return ret;
}
/// <summary>The <c>SetupDiGetDeviceInterfaceProperty</c> function retrieves a device property that is set for a device interface.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device interface for which to retrieve a device interface property.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that represents the device interface for which to retrieve a device interface property.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device interface property key of the device interface property to retrieve.
/// </param>
/// <param name="PropertyType">
/// A pointer to a DEVPROPTYPE-typed variable that receives the property-data-type identifier of the requested device interface
/// property. The property-data-type identifier is a bitwise OR between a base-data-type identifier and, if the base-data type is
/// modified, a property-data-type modifier.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that receives the requested device interface property. <c>SetupDiGetDeviceInterfaceProperty</c> retrieves
/// the requested property only if the buffer is large enough to hold all the property value data. The pointer can be <c>NULL</c>.
/// If the pointer is set to <c>NULL</c> and RequiredSize is supplied, <c>SetupDiGetDeviceInterfaceProperty</c> returns the size of
/// the property, in bytes, in *RequiredSize.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="RequiredSize">
/// A pointer to a DWORD-typed variable that receives the size, in bytes, of either the device interface property if the property is
/// retrieved or the required buffer size, if the buffer is not large enough. This pointer can be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <returns>
/// <para>
/// <c>SetupDiGetDeviceInterfaceProperty</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the
/// logged error can be retrieved by calling GetLastError.
/// </para>
/// <para>
/// The following table includes some of the more common error codes that this function might log. Other error codes can be set by
/// the device installer functions that are called by this API.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>
/// A supplied parameter is not valid. One possibility is that the device interface that is specified by DeviceInterfaceData is not valid.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified internal data value was not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertyBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVICE_INTERFACE</term>
/// <term>The device interface that is specified by DeviceInterfaceData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>
/// The PropertyBuffer buffer is not large enough to hold the property value, or an internal data buffer that was passed to a system
/// call was too small.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>The requested device property does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetDeviceInterfaceProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiGetDeviceInterfaceProperty</c>.</para>
/// <para>
/// A caller of <c>SetupDiGetDeviceInterfaceProperty</c> must be a member of the Administrators group to set a device interface property.
/// </para>
/// <para>To obtain the device property keys that represent the device properties that are set for a device interface, call SetupDiGetDeviceInterfacePropertyKeys.</para>
/// <para>To set a device interface property, call SetupDiSetDeviceInterfaceProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacepropertyw WINSETUPAPI BOOL
// SetupDiGetDeviceInterfacePropertyW( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, const DEVPROPKEY
// *PropertyKey, DEVPROPTYPE *PropertyType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInterfacePropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceProperty(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
in DEVPROPKEY PropertyKey, out DEVPROPTYPE PropertyType, [Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize,
out uint RequiredSize, [In, Optional] uint Flags);
/// <summary>
/// The <c>SetupDiGetDeviceInterfacePropertyKeys</c> function retrieves an array of device property keys that represent the device
/// properties that are set for a device interface.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set. This device information set contains a device interface for which to retrieve an array of
/// the device property keys that represent the device properties that are set for a device interface.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that represents the device interface for which to retrieve the requested
/// array of device property keys.
/// </param>
/// <param name="PropertyKeyArray">
/// A pointer to a buffer that receives an array of DEVPROPKEY-typed values, where each value is a device property key for a device
/// property that is set for the device interface. The pointer is optional and can be <c>NULL</c>. For more information, see the
/// <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyKeyCount">
/// The size, in DEVPROPKEY-typed elements, of the PropertyKeyArray buffer. If PropertyKeyArray is <c>NULL</c>, PropertyKeyCount
/// must be set to zero.
/// </param>
/// <param name="RequiredPropertyKeyCount">
/// A pointer to a DWORD-typed variable that receives the number of requested device property keys. The pointer is optional and can
/// be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged error can be retrieved
/// by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An internal data value is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A parameter is not valid. One possibility is that the device interface that is specified by DevInterfaceData is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyKeyArray is NULL, and PropertKeyCount is not zero. .</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVICE_INTERFACE</term>
/// <term>The device interface that is specified by DeviceInterfaceData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The PropertyKeyArray buffer is not large enough to hold all the requested property keys.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetDeviceInterfacePropertyKeys</c> is part of the unified device property model.</para>
/// <para>
/// If the PropertyKeyArray buffer is not large enough to hold all the requested property keys,
/// <c>SetupDiGetDeviceInterfacePropertyKeys</c> does not retrieve any property keys and returns ERROR_INSUFFICIENT_BUFFER. If the
/// caller supplied a RequiredPropertyKeyCount pointer, <c>SetupDiGetDeviceInterfacePropertyKeys</c> sets the value of
/// *RequiredPropertyKeyCount to the required size, in DEVPROPKEY-typed values, of the PropertyKeyArray buffer.
/// </para>
/// <para>
/// To retrieve a device interface property, call SetupDiGetDeviceInterfaceProperty <c>,</c> and to set a device interface property,
/// call SetupDiSetDeviceInterfaceProperty.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacepropertykeys WINSETUPAPI BOOL
// SetupDiGetDeviceInterfacePropertyKeys( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, DEVPROPKEY
// *PropertyKeyArray, DWORD PropertyKeyCount, PDWORD RequiredPropertyKeyCount, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceInterfacePropertyKeys")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfacePropertyKeys(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] DEVPROPKEY[] PropertyKeyArray, uint PropertyKeyCount,
out uint RequiredPropertyKeyCount, [In, Optional] uint Flags);
/// <summary>The <c>SetupDiGetDeviceProperty</c> function retrieves a device instance property.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device instance for which to retrieve a device instance property.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to the SP_DEVINFO_DATA structure that represents the device instance for which to retrieve a device instance property.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the requested device instance property.
/// </param>
/// <param name="PropertyType">
/// A pointer to a DEVPROPTYPE-typed variable that receives the property-data-type identifier of the requested device instance
/// property, where the property-data-type identifier is the bitwise OR between a base-data-type identifier and, if the base-data
/// type is modified, a property-data-type modifier.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that receives the requested device instance property. <c>SetupDiGetDeviceProperty</c> retrieves the
/// requested property only if the buffer is large enough to hold all the property value data. The pointer can be <c>NULL</c>. If
/// the pointer is set to <c>NULL</c> and RequiredSize is supplied, <c>SetupDiGetDeviceProperty</c> returns the size of the
/// property, in bytes, in *RequiredSize.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="RequiredSize">
/// A pointer to a DWORD-typed variable that receives the size, in bytes, of either the device instance property if the property is
/// retrieved or the required buffer size if the buffer is not large enough. This pointer can be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <returns>
/// <para>
/// <c>SetupDiGetDeviceProperty</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A supplied parameter is not valid. One possibility is that the device information element is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified internal data value was not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL and PropertBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVINST</term>
/// <term>The device instance that is specified by DevInfoData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>
/// The PropertyBuffer buffer is too small to hold the requested property value, or an internal data buffer that was passed to a
/// system call was too small.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>The requested device property does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetDeviceProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiGetDeviceProperty</c>.</para>
/// <para>To obtain the device property keys that represent the device properties that are set for a device instance, call SetupDiGetDevicePropertyKeys.</para>
/// <para>To set a device instance property, call SetupDiSetDeviceProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdevicepropertyw WINSETUPAPI BOOL
// SetupDiGetDevicePropertyW( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, const DEVPROPKEY *PropertyKey, DEVPROPTYPE
// *PropertyType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDevicePropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceProperty(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, in DEVPROPKEY PropertyKey,
out DEVPROPTYPE PropertyType, [Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, out uint RequiredSize, uint Flags = 0);
/// <summary>The <c>SetupDiGetDeviceProperty</c> function retrieves a device instance property.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device instance for which to retrieve a device instance property.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to the SP_DEVINFO_DATA structure that represents the device instance for which to retrieve a device instance property.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the requested device instance property.
/// </param>
/// <param name="Value">
/// A pointer to a buffer that receives the requested device instance property. <c>SetupDiGetDeviceProperty</c> retrieves the
/// requested property only if the buffer is large enough to hold all the property value data. The pointer can be <c>NULL</c>. If
/// the pointer is set to <c>NULL</c> and RequiredSize is supplied, <c>SetupDiGetDeviceProperty</c> returns the size of the
/// property, in bytes, in *RequiredSize.
/// </param>
/// <returns>
/// <para>
/// <c>SetupDiGetDeviceProperty</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A supplied parameter is not valid. One possibility is that the device information element is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An unspecified internal data value was not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL and PropertBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVINST</term>
/// <term>The device instance that is specified by DevInfoData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>
/// The PropertyBuffer buffer is too small to hold the requested property value, or an internal data buffer that was passed to a
/// system call was too small.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>The requested device property does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetDeviceProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiGetDeviceProperty</c>.</para>
/// <para>To obtain the device property keys that represent the device properties that are set for a device instance, call SetupDiGetDevicePropertyKeys.</para>
/// <para>To set a device instance property, call SetupDiSetDeviceProperty.</para>
/// </remarks>
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDevicePropertyW")]
public static bool SetupDiGetDeviceProperty(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, in DEVPROPKEY PropertyKey, out object Value)
{
Value = null;
if (!SetupDiGetDeviceProperty(DeviceInfoSet, DeviceInfoData, PropertyKey, out _, default, 0, out var sz) && Win32Error.GetLastError() != Win32Error.ERROR_INSUFFICIENT_BUFFER)
return false;
using var mem = new SafeCoTaskMemHandle(sz);
if (SetupDiGetDeviceProperty(DeviceInfoSet, DeviceInfoData, PropertyKey, out var propType, mem, mem.Size, out _))
{
Value = SetupDiPropertyToManagedObject(mem, propType);
return true;
}
return false;
}
/// <summary>
/// The <c>SetupDiGetDevicePropertyKeys</c> function retrieves an array of the device property keys that represent the device
/// properties that are set for a device instance.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set. This device information set contains the device instance for which this function retrieves
/// an array of device property keys. The property keys represent the device properties that are set for the device instance.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the device instance for which to retrieve the requested array of
/// device property keys.
/// </param>
/// <param name="PropertyKeyArray">
/// A pointer to a buffer that receives an array of DEVPROPKEY-typed values, where each value is a device property key that
/// represents a device property that is set for the device instance. The pointer is optional and can be <c>NULL</c>. For more
/// information, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyKeyCount">
/// The size, in DEVPROPKEY-typed values, of the PropertyKeyArray buffer. If PropertyKeyArray is set to <c>NULL</c>,
/// PropertyKeyCount must be set to zero.
/// </param>
/// <param name="RequiredPropertyKeyCount">
/// A pointer to a DWORD-typed variable that receives the number of requested device property keys. The pointer is optional and can
/// be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <returns>
/// <para>
/// <c>SetupDiGetDevicePropertyKeys</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A supplied parameter is not valid. One possibility is that the device information element is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>An internal data value is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyKeyArray is NULL and PropertKeyCount is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVINST</term>
/// <term>The device instance that is specified by DevInfoData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The PropertyKeyArray buffer is too small to hold all the requested property keys.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiGetDevicePropertyKeys</c> is part of the unified device property model.</para>
/// <para>
/// If the ProperKeyArray buffer is not large enough to hold all the requested property keys, <c>SetupDiGetDevicePropertyKeys</c>
/// does not retrieve any property keys and returns ERROR_INSUFFICIENT_BUFFER. If the caller supplied a RequiredPropertyKeyCount
/// pointer, <c>SetupDiGetDevicePropertyKeys</c> sets the value of *RequiredPropertyKeyCount to the required size, in
/// DEVPROPKEY-typed values, of the PropertyKeyArray buffer.
/// </para>
/// <para>To retrieve a device instance property, call SetupDiGetDeviceProperty, and to set a device instance property, call SetupDiSetDeviceProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdevicepropertykeys WINSETUPAPI BOOL
// SetupDiGetDevicePropertyKeys( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DEVPROPKEY *PropertyKeyArray, DWORD
// PropertyKeyCount, PDWORD RequiredPropertyKeyCount, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDevicePropertyKeys")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDevicePropertyKeys(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
[Out, Optional, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] DEVPROPKEY[] PropertyKeyArray, uint PropertyKeyCount,
out uint RequiredPropertyKeyCount, uint Flags = 0);
/// <summary>The <c>SetupDiGetDeviceRegistryProperty</c> function retrieves a specified Plug and Play device property.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device for which to retrieve
/// a Plug and Play property.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <param name="Property">
/// <para>One of the following values that specifies the property to be retrieved:</para>
/// <para>SPDRP_ADDRESS</para>
/// <para>The function retrieves the device's address.</para>
/// <para>SPDRP_BUSNUMBER</para>
/// <para>The function retrieves the device's bus number.</para>
/// <para>SPDRP_BUSTYPEGUID</para>
/// <para>The function retrieves the GUID for the device's bus type.</para>
/// <para>SPDRP_CAPABILITIES</para>
/// <para>
/// The function retrieves a bitwise OR of the following CM_DEVCAP_Xxx flags in a DWORD. The device capabilities that are
/// represented by these flags correspond to the device capabilities that are represented by the members of the DEVICE_CAPABILITIES
/// structure. The CM_DEVCAP_Xxx constants are defined in Cfgmgr32.h.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>CM_DEVCAP_Xxx flag</term>
/// <term>Corresponding DEVICE_CAPABILITIES structure member</term>
/// </listheader>
/// <item>
/// <term>CM_DEVCAP_LOCKSUPPORTED</term>
/// <term>LockSupported</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_EJECTSUPPORTED</term>
/// <term>EjectSupported</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_REMOVABLE</term>
/// <term>Removable</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_DOCKDEVICE</term>
/// <term>DockDevice</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_UNIQUEID</term>
/// <term>UniqueID</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_SILENTINSTALL</term>
/// <term>SilentInstall</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_RAWDEVICEOK</term>
/// <term>RawDeviceOK</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_SURPRISEREMOVALOK</term>
/// <term>SurpriseRemovalOK</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_HARDWAREDISABLED</term>
/// <term>HardwareDisabled</term>
/// </item>
/// <item>
/// <term>CM_DEVCAP_NONDYNAMIC</term>
/// <term>NonDynamic</term>
/// </item>
/// </list>
/// <para>SPDRP_CHARACTERISTICS</para>
/// <para>
/// The function retrieves a bitwise OR of a device's characteristics flags in a DWORD. For a description of these flags, which are
/// defined in Wdm.h and Ntddk.h, see the DeviceCharacteristics parameter of the IoCreateDevice function.
/// </para>
/// <para>SPDRP_CLASS</para>
/// <para>The function retrieves a REG_SZ string that contains the device setup class of a device.</para>
/// <para>SPDRP_CLASSGUID</para>
/// <para>The function retrieves a REG_SZ string that contains the GUID that represents the device setup class of a device.</para>
/// <para>SPDRP_COMPATIBLEIDS</para>
/// <para>
/// The function retrieves a REG_MULTI_SZ string that contains the list of compatible IDs for a device. For information about
/// compatible IDs, see Device Identification Strings.
/// </para>
/// <para>SPDRP_CONFIGFLAGS</para>
/// <para>
/// The function retrieves a bitwise OR of a device's configuration flags in a DWORD value. The configuration flags are represented
/// by the CONFIGFLAG_Xxx bitmasks that are defined in Regstr.h.
/// </para>
/// <para>SPDRP_DEVICE_POWER_DATA</para>
/// <para>(Windows XP and later) The function retrieves a CM_POWER_DATA structure that contains the device's power management information.</para>
/// <para>SPDRP_DEVICEDESC</para>
/// <para>The function retrieves a REG_SZ string that contains the description of a device.</para>
/// <para>SPDRP_DEVTYPE</para>
/// <para>The function retrieves a DWORD value that represents the device's type. For more information, see Specifying Device Types.</para>
/// <para>SPDRP_DRIVER</para>
/// <para>
/// The function retrieves a string that identifies the device's software key (sometimes called the driver key). For more
/// information about driver keys, see Registry Trees and Keys for Devices and Drivers.
/// </para>
/// <para>SPDRP_ENUMERATOR_NAME</para>
/// <para>The function retrieves a REG_SZ string that contains the name of the device's enumerator.</para>
/// <para>SPDRP_EXCLUSIVE</para>
/// <para>
/// The function retrieves a DWORD value that indicates whether a user can obtain exclusive use of the device. The returned value is
/// one if exclusive use is allowed, or zero otherwise. For more information, see IoCreateDevice.
/// </para>
/// <para>SPDRP_FRIENDLYNAME</para>
/// <para>The function retrieves a REG_SZ string that contains the friendly name of a device.</para>
/// <para>SPDRP_HARDWAREID</para>
/// <para>
/// The function retrieves a REG_MULTI_SZ string that contains the list of hardware IDs for a device. For information about hardware
/// IDs, see Device Identification Strings.
/// </para>
/// <para>SPDRP_INSTALL_STATE</para>
/// <para>
/// (Windows XP and later) The function retrieves a DWORD value that indicates the installation state of a device. The installation
/// state is represented by one of the CM_INSTALL_STATE_Xxx values that are defined in Cfgmgr32.h. The CM_INSTALL_STATE_Xxx values
/// correspond to the DEVICE_INSTALL_STATE enumeration values.
/// </para>
/// <para>SPDRP_LEGACYBUSTYPE</para>
/// <para>The function retrieves the device's legacy bus type as an INTERFACE_TYPE value (defined in Wdm.h and Ntddk.h).</para>
/// <para>SPDRP_LOCATION_INFORMATION</para>
/// <para>The function retrieves a REG_SZ string that contains the hardware location of a device.</para>
/// <para>SPDRP_LOCATION_PATHS</para>
/// <para>
/// (Windows Server 2003 and later) The function retrieves a REG_MULTI_SZ string that represents the location of the device in the
/// device tree.
/// </para>
/// <para>SPDRP_LOWERFILTERS</para>
/// <para>The function retrieves a REG_MULTI_SZ string that contains the names of a device's lower-filter drivers.</para>
/// <para>SPDRP_MFG</para>
/// <para>The function retrieves a REG_SZ string that contains the name of the device manufacturer.</para>
/// <para>SPDRP_PHYSICAL_DEVICE_OBJECT_NAME</para>
/// <para>
/// The function retrieves a REG_SZ string that contains the name that is associated with the device's PDO. For more information,
/// see IoCreateDevice.
/// </para>
/// <para>SPDRP_REMOVAL_POLICY</para>
/// <para>
/// (Windows XP and later) The function retrieves the device's current removal policy as a DWORD that contains one of the
/// CM_REMOVAL_POLICY_Xxx values that are defined in Cfgmgr32.h.
/// </para>
/// <para>SPDRP_REMOVAL_POLICY_HW_DEFAULT</para>
/// <para>
/// (Windows XP and later) The function retrieves the device's hardware-specified default removal policy as a DWORD that contains
/// one of the CM_REMOVAL_POLICY_Xxx values that are defined in Cfgmgr32.h.
/// </para>
/// <para>SPDRP_REMOVAL_POLICY_OVERRIDE</para>
/// <para>
/// (Windows XP and later) The function retrieves the device's override removal policy (if it exists) from the registry, as a DWORD
/// that contains one of the CM_REMOVAL_POLICY_Xxx values that are defined in Cfgmgr32.h.
/// </para>
/// <para>SPDRP_SECURITY</para>
/// <para>The function retrieves a SECURITY_DESCRIPTOR structure for a device.</para>
/// <para>SPDRP_SECURITY_SDS</para>
/// <para>
/// The function retrieves a REG_SZ string that contains the device's security descriptor. For information about security descriptor
/// strings, see Security Descriptor Definition Language (Windows). For information about the format of security descriptor strings,
/// see Security Descriptor Definition Language (Windows).
/// </para>
/// <para>SPDRP_SERVICE</para>
/// <para>The function retrieves a REG_SZ string that contains the service name for a device.</para>
/// <para>SPDRP_UI_NUMBER</para>
/// <para>
/// The function retrieves a DWORD value set to the value of the <c>UINumber</c> member of the device's DEVICE_CAPABILITIES structure.
/// </para>
/// <para>SPDRP_UI_NUMBER_DESC_FORMAT</para>
/// <para>The function retrieves a format string (REG_SZ) used to display the <c>UINumber</c> value.</para>
/// <para>SPDRP_UPPERFILTERS</para>
/// <para>The function retrieves a REG_MULTI_SZ string that contains the names of a device's upper filter drivers.</para>
/// </param>
/// <param name="PropertyRegDataType">
/// A pointer to a variable that receives the data type of the property that is being retrieved. This is one of the standard
/// registry data types. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that receives the property that is being retrieved. If this parameter is set to <c>NULL</c>, and
/// PropertyBufferSize is also set to zero, the function returns the required size for the buffer in RequiredSize.
/// </param>
/// <param name="PropertyBufferSize">The size, in bytes, of the PropertyBuffer buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the required size, in bytes, of the PropertyBuffer buffer that is required
/// to hold the data for the requested property. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// <c>SetupDiGetDeviceRegistryProperty</c> returns <c>TRUE</c> if the call was successful. Otherwise, it returns <c>FALSE</c> and
/// the logged error can be retrieved by making a call to GetLastError. <c>SetupDiGetDeviceRegistryProperty</c> returns the
/// ERROR_INVALID_DATA error code if the requested property does not exist for a device or if the property data is not valid.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya WINSETUPAPI BOOL
// SetupDiGetDeviceRegistryPropertyA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD
// PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDeviceRegistryPropertyA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceRegistryProperty(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, SPDRP Property,
out REG_VALUE_TYPE PropertyRegDataType, [Out, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, out uint RequiredSize);
/// <summary>
/// The <c>SetupDiGetDriverInfoDetail</c> function retrieves driver information detail for a device information set or a particular
/// device information element in the device information set.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a driver information element for which to retrieve driver information.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element that represents the device for which to
/// retrieve driver information. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// <c>SetupDiGetDriverInfoDetail</c> retrieves information about a driver in a driver list for the specified device. If this
/// parameter is <c>NULL</c>, <c>SetupDiGetDriverInfoDetail</c> retrieves information about a driver that is a member of the global
/// class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver information element that represents the driver for which to
/// retrieve details. If DeviceInfoData is specified, the driver must be a member of the driver list for the device that is
/// specified by DeviceInfoData. Otherwise, the driver must be a member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoDetailData">
/// <para>
/// A pointer to an SP_DRVINFO_DETAIL_DATA structure that receives detailed information about the specified driver. If this
/// parameter is not specified, DriverInfoDetailDataSize must be zero. If this parameter is specified, DriverInfoDetailData.
/// <c>cbSize</c> must be set to the value of <c>sizeof(</c> SP_DRVINFO_DETAIL_DATA <c>)</c> before it calls <c>SetupDiGetDriverInfoDetail</c>.
/// </para>
/// <para><c>Note</c> DriverInfoDetailData. <c>cbSize</c> must not be set to the value of the DriverInfoDetailDataSize parameter.</para>
/// </param>
/// <param name="DriverInfoDetailDataSize">The size, in bytes, of the DriverInfoDetailData buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable that receives the number of bytes required to store the detailed driver information. This value includes
/// both the size of the structure and the additional bytes required for the variable-length character buffer at the end that holds
/// the hardware ID list and the compatible ID list. The lists are in REG_MULTI_SZ format. For information about hardware and
/// compatible IDs, see Device Identification Strings.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks>
/// If the specified driver information member and the caller-supplied buffer are both valid, this function is guaranteed to fill in
/// all static fields in the SP_DRVINFO_DETAIL_DATA structure and as many IDs as possible in the variable-length buffer at the end
/// while still maintaining REG_MULTI_SZ format. In this case, the function returns <c>FALSE</c> and a call to GetLastError returns
/// ERROR_INSUFFICIENT_BUFFER. If specified, RequiredSize contains the total number of bytes required for the structure with all IDs.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdriverinfodetaila WINSETUPAPI BOOL
// SetupDiGetDriverInfoDetailA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData,
// PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData, DWORD DriverInfoDetailDataSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDriverInfoDetailA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDriverInfoDetail(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, in SP_DRVINFO_DATA_V2 DriverInfoData,
ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData, uint DriverInfoDetailDataSize, out uint RequiredSize);
/// <summary>
/// The <c>SetupDiGetDriverInfoDetail</c> function retrieves driver information detail for a device information set or a particular
/// device information element in the device information set.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a driver information element for which to retrieve driver information.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element that represents the device for which to
/// retrieve driver information. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// <c>SetupDiGetDriverInfoDetail</c> retrieves information about a driver in a driver list for the specified device. If this
/// parameter is <c>NULL</c>, <c>SetupDiGetDriverInfoDetail</c> retrieves information about a driver that is a member of the global
/// class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver information element that represents the driver for which to
/// retrieve details. If DeviceInfoData is specified, the driver must be a member of the driver list for the device that is
/// specified by DeviceInfoData. Otherwise, the driver must be a member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoDetailData">
/// <para>
/// A pointer to an SP_DRVINFO_DETAIL_DATA structure that receives detailed information about the specified driver. If this
/// parameter is not specified, DriverInfoDetailDataSize must be zero. If this parameter is specified, DriverInfoDetailData.
/// <c>cbSize</c> must be set to the value of <c>sizeof(</c> SP_DRVINFO_DETAIL_DATA <c>)</c> before it calls <c>SetupDiGetDriverInfoDetail</c>.
/// </para>
/// <para><c>Note</c> DriverInfoDetailData. <c>cbSize</c> must not be set to the value of the DriverInfoDetailDataSize parameter.</para>
/// </param>
/// <param name="DriverInfoDetailDataSize">The size, in bytes, of the DriverInfoDetailData buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable that receives the number of bytes required to store the detailed driver information. This value includes
/// both the size of the structure and the additional bytes required for the variable-length character buffer at the end that holds
/// the hardware ID list and the compatible ID list. The lists are in REG_MULTI_SZ format. For information about hardware and
/// compatible IDs, see Device Identification Strings.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks>
/// If the specified driver information member and the caller-supplied buffer are both valid, this function is guaranteed to fill in
/// all static fields in the SP_DRVINFO_DETAIL_DATA structure and as many IDs as possible in the variable-length buffer at the end
/// while still maintaining REG_MULTI_SZ format. In this case, the function returns <c>FALSE</c> and a call to GetLastError returns
/// ERROR_INSUFFICIENT_BUFFER. If specified, RequiredSize contains the total number of bytes required for the structure with all IDs.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdriverinfodetaila WINSETUPAPI BOOL
// SetupDiGetDriverInfoDetailA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData,
// PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData, DWORD DriverInfoDetailDataSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDriverInfoDetailA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDriverInfoDetail(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData, in SP_DRVINFO_DATA_V2 DriverInfoData,
ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData, uint DriverInfoDetailDataSize, out uint RequiredSize);
/// <summary>
/// The <c>SetupDiGetDriverInstallParams</c> function retrieves driver installation parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a driver information element that represents the driver for which to retrieve
/// installation parameters.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that contains a device information element that represents the device for which to
/// retrieve installation parameters. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// <c>SetupDiGetDriverInstallParams</c> retrieves information about a driver that is a member of a driver list for the specified
/// device. If this parameter is <c>NULL</c>, <c>SetupDiGetDriverInstallParams</c> retrieves information about a driver that is a
/// member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver information element that represents the driver for which to
/// retrieve installation parameters. If DeviceInfoData is supplied, the driver must be a member of the driver list for the device
/// that is specified by DeviceInfoData. Otherwise, the driver must be a member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInstallParams">
/// A pointer to an SP_DRVINSTALL_PARAMS structure to receive the installation parameters for this driver.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdriverinstallparamsa WINSETUPAPI BOOL
// SetupDiGetDriverInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData,
// PSP_DRVINSTALL_PARAMS DriverInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDriverInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDriverInstallParams(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
in SP_DRVINFO_DATA_V2 DriverInfoData, ref SP_DRVINSTALL_PARAMS DriverInstallParams);
/// <summary>
/// The <c>SetupDiGetDriverInstallParams</c> function retrieves driver installation parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a driver information element that represents the driver for which to retrieve
/// installation parameters.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that contains a device information element that represents the device for which to
/// retrieve installation parameters. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// <c>SetupDiGetDriverInstallParams</c> retrieves information about a driver that is a member of a driver list for the specified
/// device. If this parameter is <c>NULL</c>, <c>SetupDiGetDriverInstallParams</c> retrieves information about a driver that is a
/// member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver information element that represents the driver for which to
/// retrieve installation parameters. If DeviceInfoData is supplied, the driver must be a member of the driver list for the device
/// that is specified by DeviceInfoData. Otherwise, the driver must be a member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInstallParams">
/// A pointer to an SP_DRVINSTALL_PARAMS structure to receive the installation parameters for this driver.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdriverinstallparamsa WINSETUPAPI BOOL
// SetupDiGetDriverInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData,
// PSP_DRVINSTALL_PARAMS DriverInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetDriverInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDriverInstallParams(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData,
in SP_DRVINFO_DATA_V2 DriverInfoData, ref SP_DRVINSTALL_PARAMS DriverInstallParams);
/// <summary>
/// The <c>SetupDiGetHwProfileFriendlyName</c> function retrieves the friendly name associated with a hardware profile ID.
/// </summary>
/// <param name="HwProfile">
/// The hardware profile ID associated with the friendly name to retrieve. If this parameter is 0, the friendly name for the current
/// hardware profile is retrieved.
/// </param>
/// <param name="FriendlyName">A pointer to a string buffer to receive the friendly name.</param>
/// <param name="FriendlyNameSize">The size, in characters, of the FriendlyName buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the number of characters required to retrieve the friendly name (including a
/// NULL terminator).
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks>Call SetupDiGetHwProfileFriendlyNameEx to get the friendly name of a hardware profile ID on a remote computer.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigethwprofilefriendlynamea WINSETUPAPI BOOL
// SetupDiGetHwProfileFriendlyNameA( DWORD HwProfile, PSTR FriendlyName, DWORD FriendlyNameSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetHwProfileFriendlyNameA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetHwProfileFriendlyName(uint HwProfile, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder FriendlyName,
uint FriendlyNameSize, out uint RequiredSize);
/// <summary>
/// The <c>SetupDiGetHwProfileFriendlyNameEx</c> function retrieves the friendly name associated with a hardware profile ID on a
/// local or remote computer.
/// </summary>
/// <param name="HwProfile">
/// Supplies the hardware profile ID associated with the friendly name to retrieve. If this parameter is 0, the friendly name for
/// the current hardware profile is retrieved.
/// </param>
/// <param name="FriendlyName">A pointer to a character buffer to receive the friendly name.</param>
/// <param name="FriendlyNameSize">The size, in characters, of the FriendlyName buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable to receive the number of characters required to store the friendly name (including a NULL terminator).
/// This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="MachineName">
/// A pointer to NULL-terminated string that contains the name of a remote computer on which the hardware profile ID resides. This
/// parameter is optional and can be <c>NULL</c>. If MachineName is <c>NULL</c>, the hardware profile ID is on the local computer.
/// </param>
/// <param name="Reserved">Must be <c>NULL</c>.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigethwprofilefriendlynameexa WINSETUPAPI BOOL
// SetupDiGetHwProfileFriendlyNameExA( DWORD HwProfile, PSTR FriendlyName, DWORD FriendlyNameSize, PDWORD RequiredSize, PCSTR
// MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetHwProfileFriendlyNameExA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetHwProfileFriendlyNameEx(uint HwProfile, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder FriendlyName,
uint FriendlyNameSize, out uint RequiredSize, [Optional, MarshalAs(UnmanagedType.LPTStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>The <c>SetupDiGetHwProfileList</c> function retrieves a list of all currently defined hardware profile IDs.</summary>
/// <param name="HwProfileList">A pointer to an array to receive the list of currently defined hardware profile IDs.</param>
/// <param name="HwProfileListSize">The number of DWORDs in the HwProfileList buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the number of hardware profiles currently defined. If the number is larger
/// than HwProfileListSize, the list is truncated to fit the array size. The value returned in RequiredSize indicates the array size
/// required to store the entire list of hardware profiles. In this case, the function fails and a call to GetLastError returns ERROR_INSUFFICIENT_BUFFER.
/// </param>
/// <param name="CurrentlyActiveIndex">
/// A pointer to a variable of type DWORD that receives the index of the currently active hardware profile in the retrieved hardware
/// profile list. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError.
/// </returns>
/// <remarks>Call SetupDiGetHwProfileListEx to retrieve the hardware profile IDs for a remote computer.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigethwprofilelist WINSETUPAPI BOOL
// SetupDiGetHwProfileList( PDWORD HwProfileList, DWORD HwProfileListSize, PDWORD RequiredSize, PDWORD CurrentlyActiveIndex );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetHwProfileList")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetHwProfileList([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] HwProfileList,
uint HwProfileListSize, out uint RequiredSize, out uint CurrentlyActiveIndex);
/// <summary>
/// The <c>SetupDiGetHwProfileListEx</c> function retrieves a list of all currently defined hardware profile IDs on a local or
/// remote computer.
/// </summary>
/// <param name="HwProfileList">A pointer to an array to receive the list of currently defined hardware profile IDs.</param>
/// <param name="HwProfileListSize">The number of DWORDs in the HwProfileList buffer.</param>
/// <param name="RequiredSize">
/// A pointer to a variable of type DWORD that receives the number of hardware profiles that are currently defined. If the number is
/// larger than HwProfileListSize, the list is truncated to fit the array size. The value returned in RequiredSize indicates the
/// array size required to store the entire list of hardware profiles.
/// </param>
/// <param name="CurrentlyActiveIndex">
/// A pointer to a variable that receives the index of the currently active hardware profile in the retrieved hardware profile list.
/// This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="MachineName">
/// A pointer to a NULL-terminated string that contains the name of a remote system for which to retrieve the list of hardware
/// profile IDs. This parameter is optional and can be <c>NULL</c>. If this parameter is <c>NULL</c>, the list is retrieved for the
/// local system.
/// </param>
/// <param name="Reserved">Must be <c>NULL</c>.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by making a call to GetLastError. If the required size is larger than HwProfileListSize, <c>SetupDiGetHwProfileListEx</c>
/// returns <c>FALSE</c> and a call to GetLastError returns ERROR_INSUFFICIENT_BUFFER.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigethwprofilelistexa WINSETUPAPI BOOL
// SetupDiGetHwProfileListExA( PDWORD HwProfileList, DWORD HwProfileListSize, PDWORD RequiredSize, PDWORD CurrentlyActiveIndex,
// PCSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetHwProfileListExA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetHwProfileListEx([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] HwProfileList,
uint HwProfileListSize, out uint RequiredSize, out uint CurrentlyActiveIndex,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>The <c>SetupDiGetINFClass</c> function returns the class of a specified device INF file.</summary>
/// <param name="InfName">
/// A pointer to a NULL-terminated string that supplies the name of a device INF file. This name can include a path. However, if
/// just the file name is specified, the file is searched for in each directory that is listed in the <c>DevicePath</c> entry under
/// the <c>HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion</c> subkey of the registry. The maximum length in characters, including a
/// NULL terminator, of a NULL-terminated INF file name is MAX_PATH.
/// </param>
/// <param name="ClassGuid">
/// A pointer to a variable of type GUID that receives the class GUID for the specified INF file. If the INF file does not specify a
/// class name, the function returns a GUID_NULL structure. Call SetupDiClassGuidsFromName to determine whether one or more classes
/// with this name are already installed.
/// </param>
/// <param name="ClassName">
/// A pointer to a buffer that receives a NULL-terminated string that contains the name of the class for the specified INF file. If
/// the INF file does not specify a class name but does specify a GUID, this buffer receives the name that is retrieved by calling
/// SetupDiClassNameFromGuid. However, if <c>SetupDiClassNameFromGuid</c> cannot retrieve a class name (for example, the class is
/// not installed), it returns an empty string.
/// </param>
/// <param name="ClassNameSize">
/// The size, in characters, of the buffer that is pointed to by the ClassName parameter. The maximum length of a NULL-terminated
/// class name, in characters, is MAX_CLASS_NAME_LEN.
/// </param>
/// <param name="RequiredSize">
/// A pointer to a DWORD-typed variable that receives the number of characters that are required to store the class name, including
/// a terminating <c>NULL</c>. This pointer is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>Do not use this function with INF files for Windows 9x or Millennium Edition.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetinfclassw WINSETUPAPI BOOL SetupDiGetINFClassW(
// PCWSTR InfName, LPGUID ClassGuid, PWSTR ClassName, DWORD ClassNameSize, PDWORD RequiredSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetINFClassW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetINFClass([MarshalAs(UnmanagedType.LPTStr)] string InfName, out Guid ClassGuid,
[Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder ClassName, uint ClassNameSize, out uint RequiredSize);
/// <summary>
/// The <c>SetupDiGetSelectedDevice</c> function retrieves the selected device information element in a device information set.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to retrieve the selected device information element.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that receives information about the selected device information element for
/// DeviceInfoSet. The caller must set DeviceInfoData. <c>cbSize</c> to <c>sizeof</c>(SP_DEVINFO_DATA). If a device is currently not
/// selected, the function fails and a call to GetLastError returns ERROR_NO_DEVICE_SELECTED.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks><c>SetupDiGetSelectedDevice</c> is usually used by an installation wizard.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetselecteddevice WINSETUPAPI BOOL
// SetupDiGetSelectedDevice( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetSelectedDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetSelectedDevice(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiGetSelectedDriver</c> function retrieves the selected driver for a device information set or a particular device
/// information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to retrieve a selected driver.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element that represents the device in
/// DeviceInfoSet for which to retrieve the selected driver. This parameter is optional and can be <c>NULL</c>. If this parameter is
/// specified, <c>SetupDiGetSelectedDriver</c> retrieves the selected driver for the specified device. If this parameter is
/// <c>NULL</c>, <c>SetupDiGetSelectedDriver</c> retrieves the selected class driver in the global class driver list that is
/// associated with DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">A pointer to an SP_DRVINFO_DATA structure that receives information about the selected driver.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError. If a driver has not been selected for the specified device instance, the logged error is ERROR_NO_DRIVER_SELECTED.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetselecteddriverw WINSETUPAPI BOOL
// SetupDiGetSelectedDriverW( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_W DriverInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetSelectedDriverW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetSelectedDriver(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, ref SP_DRVINFO_DATA_V2 DriverInfoData);
/// <summary>
/// The <c>SetupDiGetSelectedDriver</c> function retrieves the selected driver for a device information set or a particular device
/// information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to retrieve a selected driver.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element that represents the device in
/// DeviceInfoSet for which to retrieve the selected driver. This parameter is optional and can be <c>NULL</c>. If this parameter is
/// specified, <c>SetupDiGetSelectedDriver</c> retrieves the selected driver for the specified device. If this parameter is
/// <c>NULL</c>, <c>SetupDiGetSelectedDriver</c> retrieves the selected class driver in the global class driver list that is
/// associated with DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">A pointer to an SP_DRVINFO_DATA structure that receives information about the selected driver.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError. If a driver has not been selected for the specified device instance, the logged error is ERROR_NO_DRIVER_SELECTED.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetselecteddriverw WINSETUPAPI BOOL
// SetupDiGetSelectedDriverW( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_W DriverInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiGetSelectedDriverW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetSelectedDriver(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData, ref SP_DRVINFO_DATA_V2 DriverInfoData);
/// <summary>The <c>SetupDiInstallClass</c> function installs the <c>ClassInstall32</c> section of the specified INF file.</summary>
/// <param name="hwndParent">
/// The handle to the parent window for any user interface that is used to install this class. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="InfFileName">
/// A pointer to a NULL-terminated string that contains the name of the INF file that contains an INF ClassInstall32 section.
/// </param>
/// <param name="Flags">
/// <para>These flags control the installation process. Can be a combination of the following:</para>
/// <para>DI_NOVCP</para>
/// <para>
/// Set this flag if FileQueue is supplied. DI_NOVCP instructs the <c>SetupInstallFromInfSection</c> function (described in
/// Microsoft Windows SDK documentation) not to create a queue of its own and to use the caller-supplied queue instead. If this flag
/// is set, files are not copied just queued.
/// </para>
/// <para>DI_NOBROWSE</para>
/// <para>
/// Set this flag to disable browsing if a copy operation cannot find a specified file. If the caller supplies a file queue, this
/// flag is ignored.
/// </para>
/// <para>DI_FORCECOPY</para>
/// <para>
/// Set this flag to always copy files, even if they are already present on the user's computer. If the caller supplies a file
/// queue, this flag is ignored.
/// </para>
/// <para>DI_QUIETINSTALL</para>
/// <para>
/// Set this flag to suppress the user interface unless absolutely necessary. For example, do not display the progress dialog. If
/// the caller supplies a file queue, this flag is ignored.
/// </para>
/// </param>
/// <param name="FileQueue">
/// If the DI_NOVCP flag is set, this parameter supplies a handle to a file queue where file operations should be queued but not committed.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>The caller of this function must be a member of the Administrators group.</para>
/// <para>This function is called by a class installer when it installs a device of a new device class.</para>
/// <para>To install an interface class or a device class, use SetupDiInstallClassEx.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiinstallclassa WINSETUPAPI BOOL
// SetupDiInstallClassA( HWND hwndParent, PCSTR InfFileName, DWORD Flags, HSPFILEQ FileQueue );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiInstallClassA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiInstallClass([In, Optional] HWND hwndParent, [MarshalAs(UnmanagedType.LPTStr)] string InfFileName,
DI_FLAGS Flags, [In, Optional] HSPFILEQ FileQueue);
/// <summary>The <c>SetupDiInstallClassEx</c> function installs a class installer or an interface class.</summary>
/// <param name="hwndParent">
/// The handle to the parent window for any user interface that is used to install this class. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="InfFileName">
/// <para>
/// A pointer to a NULL-terminated string that contains the name of an INF file. This parameter is optional and can be <c>NULL</c>.
/// If this function is being used to install a class installer, the INF file contains an INF ClassInstall32 section and this
/// parameter must not be <c>NULL</c>.
/// </para>
/// <para>If this function is being used to install an interface class, the INF file contains an INF InterfaceInstall32 section.</para>
/// </param>
/// <param name="Flags">
/// <para>A value of type DWORD that controls the installation process. Flags can be zero or a bitwise OR of the following values:</para>
/// <para>DI_NOVCP</para>
/// <para>Set this flag if FileQueue is supplied.</para>
/// <para>
/// DI_NOVCP instructs the <c>SetupInstallFromInfSection</c> function not to create a queue of its own and to use the
/// caller-supplied queue instead.
/// </para>
/// <para>If this flag is set, files are not copied just queued.</para>
/// <para>For more information about the <c>SetupInstallFromInfSection</c> function, see the Microsoft Windows SDK documentation.</para>
/// <para>DI_NOBROWSE</para>
/// <para>
/// Set this flag to disable browsing if a copy operation cannot find a specified file. If the caller supplies a file queue, this
/// flag is ignored.
/// </para>
/// <para>DI_FORCECOPY</para>
/// <para>
/// Set this flag to always copy files, even if they are already present on the user's computer. If the caller supplies a file
/// queue, this flag is ignored.
/// </para>
/// <para>DI_QUIETINSTALL</para>
/// <para>
/// Set this flag to suppress the user interface unless absolutely necessary. For example, do not display the progress dialog. If
/// the caller supplies a file queue, this flag is ignored.
/// </para>
/// </param>
/// <param name="FileQueue">
/// If the DI_NOVCP flag is set, this parameter supplies a handle to a file queue where file operations should be queued but not committed.
/// </param>
/// <param name="InterfaceClassGuid">
/// A pointer to a GUID that identifies the interface class to be installed. This parameter is optional and can be <c>NULL</c>. If
/// this parameter is specified, this function is being used to install the interface class represented by the GUID. If this
/// parameter is <c>NULL</c>, this function is being used to install a class installer.
/// </param>
/// <param name="Reserved1">Reserved. Must be zero.</param>
/// <param name="Reserved2">Reserved. Must be zero.</param>
/// <returns>
/// <c>SetupDiInstallClassEx</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error
/// can be retrieved with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>The caller of this function must be a member of the Administrators group.</para>
/// <para>
/// <c>SetupDiInstallClassEx</c> is typically called by a class installer to install a new device setup class or a new device
/// interface class.
/// </para>
/// <para>
/// <c>Note</c> An interface class can also be installed automatically by calling SetupDiInstallDeviceInterfaces to install the
/// device interfaces for a device.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiinstallclassexw WINSETUPAPI BOOL
// SetupDiInstallClassExW( HWND hwndParent, PCWSTR InfFileName, DWORD Flags, HSPFILEQ FileQueue, const GUID *InterfaceClassGuid,
// PVOID Reserved1, PVOID Reserved2 );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiInstallClassExW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiInstallClassEx([In, Optional] HWND hwndParent, [Optional, MarshalAs(UnmanagedType.LPTStr)] string InfFileName,
DI_FLAGS Flags, [In, Optional] HSPFILEQ FileQueue, in Guid InterfaceClassGuid, [In, Optional] IntPtr Reserved1, [In, Optional] IntPtr Reserved2);
/// <summary>The <c>SetupDiInstallClassEx</c> function installs a class installer or an interface class.</summary>
/// <param name="hwndParent">
/// The handle to the parent window for any user interface that is used to install this class. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="InfFileName">
/// <para>
/// A pointer to a NULL-terminated string that contains the name of an INF file. This parameter is optional and can be <c>NULL</c>.
/// If this function is being used to install a class installer, the INF file contains an INF ClassInstall32 section and this
/// parameter must not be <c>NULL</c>.
/// </para>
/// <para>If this function is being used to install an interface class, the INF file contains an INF InterfaceInstall32 section.</para>
/// </param>
/// <param name="Flags">
/// <para>A value of type DWORD that controls the installation process. Flags can be zero or a bitwise OR of the following values:</para>
/// <para>DI_NOVCP</para>
/// <para>Set this flag if FileQueue is supplied.</para>
/// <para>
/// DI_NOVCP instructs the <c>SetupInstallFromInfSection</c> function not to create a queue of its own and to use the
/// caller-supplied queue instead.
/// </para>
/// <para>If this flag is set, files are not copied just queued.</para>
/// <para>For more information about the <c>SetupInstallFromInfSection</c> function, see the Microsoft Windows SDK documentation.</para>
/// <para>DI_NOBROWSE</para>
/// <para>
/// Set this flag to disable browsing if a copy operation cannot find a specified file. If the caller supplies a file queue, this
/// flag is ignored.
/// </para>
/// <para>DI_FORCECOPY</para>
/// <para>
/// Set this flag to always copy files, even if they are already present on the user's computer. If the caller supplies a file
/// queue, this flag is ignored.
/// </para>
/// <para>DI_QUIETINSTALL</para>
/// <para>
/// Set this flag to suppress the user interface unless absolutely necessary. For example, do not display the progress dialog. If
/// the caller supplies a file queue, this flag is ignored.
/// </para>
/// </param>
/// <param name="FileQueue">
/// If the DI_NOVCP flag is set, this parameter supplies a handle to a file queue where file operations should be queued but not committed.
/// </param>
/// <param name="InterfaceClassGuid">
/// A pointer to a GUID that identifies the interface class to be installed. This parameter is optional and can be <c>NULL</c>. If
/// this parameter is specified, this function is being used to install the interface class represented by the GUID. If this
/// parameter is <c>NULL</c>, this function is being used to install a class installer.
/// </param>
/// <param name="Reserved1">Reserved. Must be zero.</param>
/// <param name="Reserved2">Reserved. Must be zero.</param>
/// <returns>
/// <c>SetupDiInstallClassEx</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error
/// can be retrieved with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>The caller of this function must be a member of the Administrators group.</para>
/// <para>
/// <c>SetupDiInstallClassEx</c> is typically called by a class installer to install a new device setup class or a new device
/// interface class.
/// </para>
/// <para>
/// <c>Note</c> An interface class can also be installed automatically by calling SetupDiInstallDeviceInterfaces to install the
/// device interfaces for a device.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiinstallclassexw WINSETUPAPI BOOL
// SetupDiInstallClassExW( HWND hwndParent, PCWSTR InfFileName, DWORD Flags, HSPFILEQ FileQueue, const GUID *InterfaceClassGuid,
// PVOID Reserved1, PVOID Reserved2 );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiInstallClassExW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiInstallClassEx([In, Optional] HWND hwndParent, [Optional, MarshalAs(UnmanagedType.LPTStr)] string InfFileName,
DI_FLAGS Flags, [In, Optional] HSPFILEQ FileQueue, [In, Optional] IntPtr InterfaceClassGuid, [In, Optional] IntPtr Reserved1,
[In, Optional] IntPtr Reserved2);
/// <summary>The <c>SetupDiInstallDevice</c> function is the default handler for the DIF_INSTALLDEVICE installation request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set for the local system that contains a device information element that represents the
/// device to install.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This is an IN-OUT
/// parameter because DeviceInfoData. <c>DevInst</c> might be updated with a new handle value upon return.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiInstallDevice</c> installs a driver from the INF file. SetupAPI's definition of the "driver" is really a "driver
/// node." Therefore, when this function installs a driver, it also installs the items in the following list:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The service(s) for the device.</term>
/// </item>
/// <item>
/// <term>The driver files.</term>
/// </item>
/// <item>
/// <term>Device-specific co-installers (if any).</term>
/// </item>
/// <item>
/// <term>Property-page providers (if any).</term>
/// </item>
/// <item>
/// <term>Control-panel applets (if any).</term>
/// </item>
/// </list>
/// <para>This function also registers any required device interfaces.</para>
/// <para>A successful installation includes, but is not limited to, the following steps:</para>
/// <list type="bullet">
/// <item>
/// <term>Create a driver key in the registry and write appropriate entries (such as <c>InfPath</c> and <c>ProviderName</c>).</term>
/// </item>
/// <item>
/// <term>
/// Locate and process the INF DDInstall section for the device. The section might be OS/architecture-specific. The DDInstall
/// section's <c>AddReg</c> and <c>DelReg</c> entries are directed at the device's software key. Locate and process the DDInstall
/// <c>.HW</c> section whose <c>AddReg</c> and <c>DelReg</c> entries are directed at the device's hardware key. Locate and process
/// the INF DDInstall.LogConfigOverride section, if present, to supply an override configuration for the device. Locate and process
/// the INF DDInstall.Services section to add services for the device (and potentially remove any old services that are no longer necessary).
/// </term>
/// </item>
/// <item>
/// <term>Copy the INF file to the system INF directory.</term>
/// </item>
/// <item>
/// <term>Possibly perform the other file operations, based on flag settings in the device installation parameters.</term>
/// </item>
/// <item>
/// <term>Load the drivers for the device. This includes the function driver and any upper or lower-filter drivers.</term>
/// </item>
/// <item>
/// <term>Call the drivers' AddDevice routines.</term>
/// </item>
/// <item>
/// <term>Start the device by sending an IRP_MN_START_DEVICE I/O request packet (IRP).</term>
/// </item>
/// </list>
/// <para>
/// Windows does not start the device if the DI_NEEDRESTART, DI_NEEDREBOOT, or DI_DONOTCALLCONFIGMG flag is set in the
/// SP_DEVINSTALL_PARAMS structure.
/// </para>
/// <para>
/// A class installer should return ERROR_DI_DO_DEFAULT or call this function when handling a DIF_INSTALLDEVICE request. This
/// function performs many tasks for device installation and that list of tasks might be expanded in future releases. If a class
/// installer performs device installation without calling this function, the class installer might not work correctly on future
/// versions of the operating system.
/// </para>
/// <para>
/// If Windows cannot locate an INF file for the device, it will send DIF_INSTALLDEVICE in an attempt to install a null driver.
/// <c>SetupDiInstallDevice</c> installs a null driver only if the device supports raw mode or is a non-PnP device (reported by
/// IoReportDetectedDevice). For more information, see DIF_INSTALLDEVICE.
/// </para>
/// <para>
/// If the DI_FLAGSEX_SETFAILEDINSTALL flag is set in the SP_DEVINSTALL_PARAMS structure, <c>SetupDiInstallDevice</c> just sets the
/// FAILEDINSTALL flag in the device's <c>ConfigFlags</c> registry value.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiInstallDevice</c> and only in those situations where the class
/// installer must perform device installation operations after <c>SetupDiInstallDevice</c> completes the default device
/// installation operation. In such situations, the class installer must directly call <c>SetupDiInstallDevice</c> when the
/// installer processes a DIF_INSTALLDEVICE request. For more information about calling the default handler, see Calling Default DIF
/// Code Handlers.
/// </para>
/// <para>The caller of <c>SetupDiInstallDevice</c> must be a member of the Administrators group.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiinstalldevice WINSETUPAPI BOOL
// SetupDiInstallDevice( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiInstallDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiInstallDevice(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiInstallDeviceInterfaces</c> function is the default handler for the DIF_INSTALLINTERFACES installation request.
/// </summary>
/// <param name="DeviceInfoSet">
/// A pointer to the device information set that contains a device information element that represents the device for which to
/// install interfaces. The device information set must contain only elements for the local system.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <returns>
/// <c>SetupDiInstallDeviceInterfaces</c> returns <c>TRUE</c> if the function completed without error. If the function completed
/// with an error, <c>FALSE</c> is returned and the error code for the failure can be retrieved by calling GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiInstallDeviceInterfaces</c> processes each <c>AddInterface</c> entry in the DDInstall. <c>Interfaces</c> section of a
/// device INF file and creates each interface by calling SetupDiCreateDeviceInterface.
/// </para>
/// <para>The caller of <c>SetupDiInstallDeviceInterfaces</c> must be a member of the Administrators group.</para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiInstallDeviceInterfaces</c> and only in those situations where the
/// class installer must perform device interface installation operations after <c>SetupDiInstallDeviceInterfaces</c> completes the
/// default device interface installation operation. In such situations, the class installer must directly call
/// <c>SetupDiInstallDeviceInterfaces</c> when the installer processes a DIF_INSTALLINTERFACES request. For more information about
/// calling the default handler, see Calling Default DIF Code Handlers.
/// </para>
/// <para>For information about INF file format, see INF File Sections and Directives.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiinstalldeviceinterfaces WINSETUPAPI BOOL
// SetupDiInstallDeviceInterfaces( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiInstallDeviceInterfaces")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiInstallDeviceInterfaces(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiInstallDriverFiles</c> function is the default handler for the DIF_INSTALLDEVICEFILES installation request.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the device information element that represents the device for which to
/// install files. The device information set must not contain remote elements.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// The caller of <c>SetupDiInstallDriverFiles</c> must be a member of the Administrators group if this function is being used to
/// install files. However, if this function is being used to build up a file queue, membership in the Administrators group is not required.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiInstallDriverFiles</c> and only in those situations where the class
/// installer must perform driver file installation operations after <c>SetupDiInstallDriverFiles</c> completes the default driver
/// file installation operation. In such situations, the class installer must directly call <c>SetupDiInstallDriverFiles</c> when
/// the installer processes a DIF_INSTALLDEVICEFILES request. For more information about calling the default handler, see Calling
/// Default DIF Code Handlers.
/// </para>
/// <para>
/// The operation of <c>SetupDiInstallDriverFiles</c> is similar to the SetupDiInstallDevice function. However, this function
/// performs only the file copy operations that are performed by <c>SetupDiInstallDevice</c>.
/// </para>
/// <para>A driver must be selected for the specified device information set or element before this function is called.</para>
/// <para>This function processes the <c>CopyFiles</c>, <c>Delfiles</c>, and <c>Renfiles</c> entries in the selected INF file.</para>
/// <para>The DeviceInfoSet must only contain elements on the local computer.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiinstalldriverfiles WINSETUPAPI BOOL
// SetupDiInstallDriverFiles( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiInstallDriverFiles")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiInstallDriverFiles(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData);
/// <summary>The <c>SetupDiLoadClassIcon</c> function loads both the large and mini-icon for the specified class.</summary>
/// <param name="ClassGuid">A pointer to the GUID of the class for which the icon(s) should be loaded.</param>
/// <param name="LargeIcon">
/// A pointer to an icon handle that receives the handle value for the loaded large icon for the specified class. This pointer is
/// optional and can be <c>NULL</c>. If the pointer is <c>NULL</c>, the large icon is not loaded.
/// </param>
/// <param name="MiniIconIndex">
/// A pointer to an INT-typed variable that receives the index of the mini-icon for the specified class. The mini-icon is stored in
/// the device installer's mini-icon cache. The pointer is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// The icons of the class are either predefined and loaded from the device installer's internal cache, or they are loaded directly
/// from the class installer's executable. This function queries the registry value <c>ICON</c> in the specified class's section. If
/// the <c>ICON</c> value is specified, it indicates which mini-icon to load.
/// </para>
/// <para>
/// If the <c>ICON</c> value is negative, the absolute value represents a predefined icon in the class's registry. See
/// SetupDiDrawMiniIcon for a list of the predefined mini-icons.
/// </para>
/// <para>
/// If the <c>ICON</c> value is positive, it represents an icon in the class installer's executable image that will be extracted.
/// The value 1 is reserved. This function also uses the <c>INSTALLER32</c> registry value and then the <c>ENUMPROPPAGES32</c>
/// registry value to determine which executable image to extract the icons from. For more information about these registry values,
/// see INF ClassInstall32 Section.
/// </para>
/// <para>
/// When a caller is finished using the icon, the caller must call <c>DestroyIcon</c> (which is described in the Microsoft Windows
/// SDK documentation).
/// </para>
/// <para>
/// If the LargeIcon parameter is specified, but the ClassGuid parameter does not supply a valid class GUID or the <c>Icon</c>
/// registry value of the class is not valid, <c>SetupDiLoadClassIcon</c> loads the default large icon, returns the handle for the
/// large icon, and, if the MiniIconIndex parameter is specified, returns the index of the default mini-icon.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiloadclassicon WINSETUPAPI BOOL
// SetupDiLoadClassIcon( const GUID *ClassGuid, HICON *LargeIcon, PINT MiniIconIndex );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiLoadClassIcon")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiLoadClassIcon(in Guid ClassGuid, out HICON LargeIcon, out int MiniIconIndex);
/// <summary>The <c>SetupDiLoadClassIcon</c> function loads both the large and mini-icon for the specified class.</summary>
/// <param name="ClassGuid">A pointer to the GUID of the class for which the icon(s) should be loaded.</param>
/// <param name="LargeIcon">
/// A pointer to an icon handle that receives the handle value for the loaded large icon for the specified class. This pointer is
/// optional and can be <c>NULL</c>. If the pointer is <c>NULL</c>, the large icon is not loaded.
/// </param>
/// <param name="MiniIconIndex">
/// A pointer to an INT-typed variable that receives the index of the mini-icon for the specified class. The mini-icon is stored in
/// the device installer's mini-icon cache. The pointer is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// The icons of the class are either predefined and loaded from the device installer's internal cache, or they are loaded directly
/// from the class installer's executable. This function queries the registry value <c>ICON</c> in the specified class's section. If
/// the <c>ICON</c> value is specified, it indicates which mini-icon to load.
/// </para>
/// <para>
/// If the <c>ICON</c> value is negative, the absolute value represents a predefined icon in the class's registry. See
/// SetupDiDrawMiniIcon for a list of the predefined mini-icons.
/// </para>
/// <para>
/// If the <c>ICON</c> value is positive, it represents an icon in the class installer's executable image that will be extracted.
/// The value 1 is reserved. This function also uses the <c>INSTALLER32</c> registry value and then the <c>ENUMPROPPAGES32</c>
/// registry value to determine which executable image to extract the icons from. For more information about these registry values,
/// see INF ClassInstall32 Section.
/// </para>
/// <para>
/// When a caller is finished using the icon, the caller must call <c>DestroyIcon</c> (which is described in the Microsoft Windows
/// SDK documentation).
/// </para>
/// <para>
/// If the LargeIcon parameter is specified, but the ClassGuid parameter does not supply a valid class GUID or the <c>Icon</c>
/// registry value of the class is not valid, <c>SetupDiLoadClassIcon</c> loads the default large icon, returns the handle for the
/// large icon, and, if the MiniIconIndex parameter is specified, returns the index of the default mini-icon.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiloadclassicon WINSETUPAPI BOOL
// SetupDiLoadClassIcon( const GUID *ClassGuid, HICON *LargeIcon, PINT MiniIconIndex );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiLoadClassIcon")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiLoadClassIcon(in Guid ClassGuid, [In, Optional] IntPtr LargeIcon, [In, Optional] IntPtr MiniIconIndex);
/// <summary>The <c>SetupDiLoadDeviceIcon</c> function retrieves an icon for a specified device.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the device information element that represents the device for which to
/// retrieve an icon.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <param name="cxIcon">
/// The width, in pixels, of the icon to be retrieved. Use the system metric index SM_CXICON to specify a default-sized icon or use
/// the system metric index SM_CXSMICON to specify a small icon. The system metric indexes are defined in Winuser.h, and their
/// associated values can be retrieved by a call to the GetSystemMetrics function. (The <c>GetSystemMetrics</c> function is
/// documented in the Microsoft Windows SDK.)
/// </param>
/// <param name="cyIcon">
/// The height, in pixels, of the icon to be retrieved. Use SM_CXICON to specify a default-sized icon or use SM_CXSMICON to specify
/// a small icon.
/// </param>
/// <param name="Flags">Not used. Must set to zero.</param>
/// <param name="hIcon">
/// A pointer to a handle to an icon that receives a handle to the icon that this function retrieves. After the application that
/// calls this function is finished using the icon, the application must call DestroyIcon to delete the icon. ( <c>DestroyIcon</c>
/// is documented in the Microsoft Windows SDK.)
/// </param>
/// <returns>
/// <c>SetupDiLoadDeviceIcon</c> returns <c>TRUE</c> if the function succeeds in retrieving the icon for the specified device.
/// Otherwise, the function returns <c>FALSE</c> and the logged error can be retrieved by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para><c>SetupDiLoadDeviceIcon</c> attempts to retrieve an icon for the device as follows:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// If the DEVPKEY_DrvPkg_Icon device property of the device includes a list of resource-identifier strings, the function attempts
/// to retrieve the icon that is specified by the first resource-identifier string in the list.
/// </term>
/// </item>
/// <item>
/// <term>
/// If the function cannot retrieve a device-specific icon, it will then attempt to retrieve the class icon for the device. For
/// information about class icons, see SetupDiLoadClassIcon.
/// </term>
/// </item>
/// <item>
/// <term>
/// If the function cannot retrieve the class icon for the device, it will then attempt to retrieve the icon for the Unknown device
/// setup class, where the icon for the Unknown device setup class includes the image of a question mark (?).
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiloaddeviceicon WINSETUPAPI BOOL
// SetupDiLoadDeviceIcon( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, UINT cxIcon, UINT cyIcon, DWORD Flags, HICON
// *hIcon );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiLoadDeviceIcon")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiLoadDeviceIcon(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, uint cxIcon, uint cyIcon,
[In, Optional] uint Flags, out HICON hIcon);
/// <summary>The <c>SetupDiOpenClassRegKey</c> function opens the setup class registry key or a specific class's subkey.</summary>
/// <param name="ClassGuid">
/// A pointer to the GUID of the setup class whose key is to be opened. This parameter is optional and can be <c>NULL</c>. If this
/// parameter is <c>NULL</c>, the root of the setup class tree ( <c>HKLM\SYSTEM\CurrentControlSet\Control\Class</c>) is opened.
/// </param>
/// <param name="samDesired">
/// The registry security access for the key to be opened. For information about registry security access values of type REGSAM, see
/// the Microsoft Windows SDK documentation.
/// </param>
/// <returns>
/// <para>
/// If the function is successful, it returns a handle to an opened registry key where information about this setup class can be stored/retrieved.
/// </para>
/// <para>If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this function to be a
/// member of the Administrators group.
/// </para>
/// <para>This function does not create a registry key if it does not already exist.</para>
/// <para>The handle returned from this function must be closed by calling RegCloseKey.</para>
/// <para>To open the interface class registry key or a specific interface class subkey, call SetupDiOpenClassRegKeyEx.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopenclassregkey WINSETUPAPI HKEY
// SetupDiOpenClassRegKey( const GUID *ClassGuid, REGSAM samDesired );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenClassRegKey")]
public static extern SafeRegistryHandle SetupDiOpenClassRegKey(in Guid ClassGuid, RegistryRights samDesired);
/// <summary>The <c>SetupDiOpenClassRegKey</c> function opens the setup class registry key or a specific class's subkey.</summary>
/// <param name="ClassGuid">
/// A pointer to the GUID of the setup class whose key is to be opened. This parameter is optional and can be <c>NULL</c>. If this
/// parameter is <c>NULL</c>, the root of the setup class tree ( <c>HKLM\SYSTEM\CurrentControlSet\Control\Class</c>) is opened.
/// </param>
/// <param name="samDesired">
/// The registry security access for the key to be opened. For information about registry security access values of type REGSAM, see
/// the Microsoft Windows SDK documentation.
/// </param>
/// <returns>
/// <para>
/// If the function is successful, it returns a handle to an opened registry key where information about this setup class can be stored/retrieved.
/// </para>
/// <para>If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this function to be a
/// member of the Administrators group.
/// </para>
/// <para>This function does not create a registry key if it does not already exist.</para>
/// <para>The handle returned from this function must be closed by calling RegCloseKey.</para>
/// <para>To open the interface class registry key or a specific interface class subkey, call SetupDiOpenClassRegKeyEx.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopenclassregkey WINSETUPAPI HKEY
// SetupDiOpenClassRegKey( const GUID *ClassGuid, REGSAM samDesired );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenClassRegKey")]
public static extern SafeRegistryHandle SetupDiOpenClassRegKey([In, Optional] IntPtr ClassGuid, RegistryRights samDesired);
/// <summary>
/// The <c>SetupDiOpenClassRegKeyEx</c> function opens the device setup class registry key, the device interface class registry key,
/// or a specific class's subkey. This function opens the specified key on the local computer or on a remote computer.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to the GUID of the class whose registry key is to be opened. This parameter is optional and can be <c>NULL</c>. If
/// this parameter is <c>NULL</c>, the root of the class tree ( <c>HKLM\SYSTEM\CurrentControlSet\Control\Class</c>) is opened.
/// </param>
/// <param name="samDesired">
/// The registry security access for the key to be opened. For information about registry security access values of type REGSAM, see
/// the Microsoft Windows SDK documentation.
/// </param>
/// <param name="Flags">
/// <para>The type of registry key to be opened, which is specified by one of the following:</para>
/// <para>DIOCR_INSTALLER</para>
/// <para>Open a setup class key. If ClassGuid is <c>NULL</c>, open the root key of the class installer branch.</para>
/// <para>DIOCR_INTERFACE</para>
/// <para>Open an interface class key. If ClassGuid is <c>NULL</c>, open the root key of the interface class branch.</para>
/// </param>
/// <param name="MachineName">
/// Optionally points to a string that contains the name of a remote computer on which to open the specified key.
/// </param>
/// <param name="Reserved">Reserved. Must be <c>NULL</c>.</param>
/// <returns>
/// <para>
/// <c>SetupDiOpenClassRegKeyEx</c> returns a handle to an opened registry key where information about this setup class can be stored/retrieved.
/// </para>
/// <para>If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this function to be a
/// member of the Administrators group.
/// </para>
/// <para><c>SetupDiOpenClassRegKeyEx</c> does not create a registry key if it does not already exist.</para>
/// <para>Callers of this function must close the handle returned from this function by calling RegCloseKey.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopenclassregkeyexa WINSETUPAPI HKEY
// SetupDiOpenClassRegKeyExA( const GUID *ClassGuid, REGSAM samDesired, DWORD Flags, PCSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenClassRegKeyExA")]
public static extern SafeRegistryHandle SetupDiOpenClassRegKeyEx(in Guid ClassGuid, RegistryRights samDesired, DIOCR Flags,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>
/// The <c>SetupDiOpenClassRegKeyEx</c> function opens the device setup class registry key, the device interface class registry key,
/// or a specific class's subkey. This function opens the specified key on the local computer or on a remote computer.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to the GUID of the class whose registry key is to be opened. This parameter is optional and can be <c>NULL</c>. If
/// this parameter is <c>NULL</c>, the root of the class tree ( <c>HKLM\SYSTEM\CurrentControlSet\Control\Class</c>) is opened.
/// </param>
/// <param name="samDesired">
/// The registry security access for the key to be opened. For information about registry security access values of type REGSAM, see
/// the Microsoft Windows SDK documentation.
/// </param>
/// <param name="Flags">
/// <para>The type of registry key to be opened, which is specified by one of the following:</para>
/// <para>DIOCR_INSTALLER</para>
/// <para>Open a setup class key. If ClassGuid is <c>NULL</c>, open the root key of the class installer branch.</para>
/// <para>DIOCR_INTERFACE</para>
/// <para>Open an interface class key. If ClassGuid is <c>NULL</c>, open the root key of the interface class branch.</para>
/// </param>
/// <param name="MachineName">
/// Optionally points to a string that contains the name of a remote computer on which to open the specified key.
/// </param>
/// <param name="Reserved">Reserved. Must be <c>NULL</c>.</param>
/// <returns>
/// <para>
/// <c>SetupDiOpenClassRegKeyEx</c> returns a handle to an opened registry key where information about this setup class can be stored/retrieved.
/// </para>
/// <para>If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this function to be a
/// member of the Administrators group.
/// </para>
/// <para><c>SetupDiOpenClassRegKeyEx</c> does not create a registry key if it does not already exist.</para>
/// <para>Callers of this function must close the handle returned from this function by calling RegCloseKey.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopenclassregkeyexa WINSETUPAPI HKEY
// SetupDiOpenClassRegKeyExA( const GUID *ClassGuid, REGSAM samDesired, DWORD Flags, PCSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenClassRegKeyExA")]
public static extern SafeRegistryHandle SetupDiOpenClassRegKeyEx([In, Optional] IntPtr ClassGuid, RegistryRights samDesired, DIOCR Flags,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>
/// The <c>SetupDiOpenDeviceInfo</c> function adds a device information element for a device instance to a device information set,
/// if one does not already exist in the device information set, and retrieves information that identifies the device information
/// element for the device instance in the device information set.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set to which <c>SetupDiOpenDeviceInfo</c> adds a device information element, if one does not
/// already exist, for the device instance that is specified by DeviceInstanceId.
/// </param>
/// <param name="DeviceInstanceId">
/// A pointer to a NULL-terminated string that supplies the device instance identifier of a device (for example,
/// "Root*PNP0500\0000"). If DeviceInstanceId is <c>NULL</c> or references a zero-length string, <c>SetupDiOpenDeviceInfo</c> adds a
/// device information element to the supplied device information set, if one does not already exist, for the root device in the
/// device tree.
/// </param>
/// <param name="hwndParent">The handle to the top-level window to use for any user interface related to installing the device.</param>
/// <param name="OpenFlags">
/// <para>
/// A variable of DWORD type that controls how the device information element is opened. The value of this parameter can be one or
/// more of the following:
/// </para>
/// <para>DIOD_CANCEL_REMOVE</para>
/// <para>
/// If this flag is specified and the device had been marked for pending removal, the operating system cancels the pending removal.
/// </para>
/// <para>DIOD_INHERIT_CLASSDRVS</para>
/// <para>
/// If this flag is specified, the resulting device information element inherits the class driver list, if any, associated with the
/// device information set. In addition, if there is a selected driver for the device information set, that same driver is selected
/// for the new device information element.
/// </para>
/// <para>If the device information element was already present, its class driver list, if any, is replaced with the inherited list.</para>
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to a caller-supplied SP_DEVINFO_DATA structure that receives information about the device information element for the
/// device instance that is specified by DeviceInstanceId. The caller must set <c>cbSize</c> to <c>sizeof(</c> SP_DEVINFO_DATA
/// <c>)</c>. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <returns>
/// <c>SetupDiOpenDeviceInfo</c> returns <c>TRUE</c> if it is successful. Otherwise, the function returns <c>FALSE</c> and the
/// logged error can be retrieved with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If this device instance is being added to a set that has an associated class, the device class must be the same or the call will
/// fail. In this case, a call to GetLastError returns ERROR_CLASS_MISMATCH.
/// </para>
/// <para>
/// If the new device information element is successfully opened but the caller-supplied DeviceInfoData buffer is invalid, this
/// function returns <c>FALSE</c>. In this case, a call to GetLastError returns ERROR_INVALID_USER_BUFFER. However, the device
/// information element is added as a new member of the set anyway.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopendeviceinfoa WINSETUPAPI BOOL
// SetupDiOpenDeviceInfoA( HDEVINFO DeviceInfoSet, PCSTR DeviceInstanceId, HWND hwndParent, DWORD OpenFlags, PSP_DEVINFO_DATA
// DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenDeviceInfoA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiOpenDeviceInfo(HDEVINFO DeviceInfoSet, [Optional, MarshalAs(UnmanagedType.LPTStr)] string DeviceInstanceId,
[In, Optional] HWND hwndParent, DIOD OpenFlags, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiOpenDeviceInterface</c> function retrieves information about a device interface and adds the interface to the
/// specified device information set for a local system or a remote system.
/// </summary>
/// <param name="DeviceInfoSet">
/// A pointer to a device information set that contains, or will contain, a device information element that represents the device
/// that supports the interface to open.
/// </param>
/// <param name="DevicePath">
/// A pointer to a NULL-terminated string that supplies the name of the device interface to be opened. This name is a Win32 device
/// path that is typically received in a PnP notification structure or obtained by a previous call to SetupDiEnumDeviceInterfaces
/// and its related functions.
/// </param>
/// <param name="OpenFlags">
/// <para>Flags that determine how the device interface element is to be opened. The only valid flag is as follows:</para>
/// <para>DIODI_NO_ADD</para>
/// <para>
/// Specifies that the device information element for the underlying device will not be created if that element is not already
/// present in the specified device information set. For more information, see the following <c>Remarks</c> section.
/// </para>
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to a caller-initialized SP_DEVICE_INTERFACE_DATA structure that receives the requested interface data. This pointer is
/// optional and can be <c>NULL</c>. If a buffer is supplied, the caller must set the <c>cbSize</c> member of the structure to
/// <c>sizeof(</c> SP_DEVICE_INTERFACE_DATA <c>)</c> before calling <c>SetupDiOpenDeviceInterface</c>. For more information, see the
/// following <c>Remarks</c> section.
/// </param>
/// <returns>
/// <c>SetupDiOpenDeviceInterface</c> returns <c>TRUE</c> if the function completed without error. If the function completed with an
/// error, it returns <c>FALSE</c> and the error code for the failure can be retrieved by calling GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If a device interface element for the interface already exists in DeviceInfoSet, <c>SetupDiOpenDeviceInterface</c> updates the
/// flags. Therefore, this function can be used to update the flags for a device interface. For example, an interface might have
/// been inactive when it was first opened, but has subsequently become active. If the device information element for the underlying
/// device is not already present in DeviceInfoSet, this function creates one and adds it to DeviceInfoSet.
/// </para>
/// <para>
/// If the function successfully opens the new device interface but the caller did not supply a valid structure in the
/// DeviceInterfaceData parameter, the function will return <c>FALSE</c> and a subsequent call to GetLastError will return
/// ERROR_INVALID_USER_BUFFER. However, in this situation, <c>SetupDiOpenDeviceInterface</c> does add the requested interface to the
/// device information set.
/// </para>
/// <para>
/// If the new device interface is successfully opened, but the caller-supplied DeviceInterfaceData buffer is invalid, this function
/// returns <c>FALSE</c> and GetLastError returns ERROR_INVALID_USER_BUFFER. The caller's buffer error does not prevent the
/// interface from being opened.
/// </para>
/// <para>
/// If the DIODI_NO_ADD flag is specified for the OpenFlags parameter, and a device information element for the underlying device is
/// not already present in the specified device information set, this function returns <c>FALSE</c> and GetLastError returns ERROR_NO_SUCH_DEVICE_INTERFACE.
/// </para>
/// <para>
/// When the application has finished using the information that <c>SetupDiOpenDeviceInterface</c> retrieved <c>,</c> the
/// application must call SetupDiDeleteDeviceInterfaceData.
/// </para>
/// <para>
/// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINKattribute can be passed in as the value of the DevicePath argument of the
/// <c>SetupDiOpenDeviceInterface</c> function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopendeviceinterfacew WINSETUPAPI BOOL
// SetupDiOpenDeviceInterfaceW( HDEVINFO DeviceInfoSet, PCWSTR DevicePath, DWORD OpenFlags, PSP_DEVICE_INTERFACE_DATA
// DeviceInterfaceData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenDeviceInterfaceW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiOpenDeviceInterface(HDEVINFO DeviceInfoSet, [MarshalAs(UnmanagedType.LPTStr)] string DevicePath,
DIODI OpenFlags, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
/// <summary>
/// The <c>SetupDiOpenDeviceInterfaceRegKey</c> function opens the registry subkey that is used by applications and drivers to store
/// information that is specific to a device interface.
/// </summary>
/// <param name="DeviceInfoSet">
/// A pointer to a device information set that contains the device interface for which to open a registry subkey.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the device interface. This pointer can be returned by
/// SetupDiCreateDeviceInterface or SetupDiEnumDeviceInterfaces.
/// </param>
/// <param name="Reserved">Reserved. Must be zero.</param>
/// <param name="samDesired">
/// The requested registry security access to the registry subkey. For information about registry security access values of type
/// REGSAM, see the Microsoft Windows SDK documentation.
/// </param>
/// <returns>
/// <c>SetupDiOpenDeviceInterfaceRegKey</c> returns a handle to the opened registry key. If the function fails, it returns
/// INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this function to be a
/// member of the Administrators group.
/// </para>
/// <para>Close the handle returned from by function by calling RegCloseKey.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopendeviceinterfaceregkey WINSETUPAPI HKEY
// SetupDiOpenDeviceInterfaceRegKey( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, DWORD Reserved, REGSAM
// samDesired );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenDeviceInterfaceRegKey")]
public static extern SafeRegistryHandle SetupDiOpenDeviceInterfaceRegKey(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
[In, Optional] uint Reserved, RegistryRights samDesired);
/// <summary>The <c>SetupDiOpenDevRegKey</c> function opens a registry key for device-specific configuration information.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element that represents the device for which to open a
/// registry key.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <param name="Scope">
/// <para>
/// The scope of the registry key to open. The scope determines where the information is stored. The scope can be global or specific
/// to a hardware profile. The scope is specified by one of the following values:
/// </para>
/// <para>DICS_FLAG_GLOBAL</para>
/// <para>
/// Open a key to store global configuration information. This information is not specific to a particular hardware profile. This
/// opens a key that is rooted at <c>HKEY_LOCAL_MACHINE.</c> The exact key opened depends on the value of the KeyType parameter.
/// </para>
/// <para>DICS_FLAG_CONFIGSPECIFIC</para>
/// <para>
/// Open a key to store hardware profile-specific configuration information. This key is rooted at one of the hardware-profile
/// specific branches, instead of <c>HKEY_LOCAL_MACHINE</c>. The exact key opened depends on the value of the KeyType parameter.
/// </para>
/// </param>
/// <param name="HwProfile">
/// <para>A hardware profile value, which is set as follows:</para>
/// <list type="bullet">
/// <item>
/// <term>If Scope is set to DICS_FLAG_CONFIGSPECIFIC, HwProfile specifies the hardware profile of the key that is to be opened.</term>
/// </item>
/// <item>
/// <term>If HwProfile is 0, the key for the current hardware profile is opened.</term>
/// </item>
/// <item>
/// <term>If Scope is DICS_FLAG_GLOBAL, HwProfile is ignored.</term>
/// </item>
/// </list>
/// </param>
/// <param name="KeyType">
/// <para>The type of registry storage key to open, which can be one of the following values:</para>
/// <para>DIREG_DEV</para>
/// <para>Open a hardware key for the device.</para>
/// <para>DIREG_DRV</para>
/// <para>Open a software key for the device.</para>
/// <para>For more information about a device's hardware and software keys, see Registry Trees and Keys for Devices and Drivers.</para>
/// </param>
/// <param name="samDesired">
/// The registry security access that is required for the requested key. For information about registry security access values of
/// type REGSAM, see the Microsoft Windows SDK documentation.
/// </param>
/// <returns>
/// <para>
/// If the function is successful, it returns a handle to an opened registry key where private configuration data about this device
/// instance can be stored/retrieved.
/// </para>
/// <para>If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// Depending on the value that is passed in the samDesired parameter, it might be necessary for the caller of this function to be a
/// member of the Administrators group.
/// </para>
/// <para>Close the handle returned from this function by calling RegCloseKey.</para>
/// <para>
/// The specified device instance must be registered before this function is called. However, be aware that the operating system
/// automatically registers PnP device instances. For information about how to register non-PnP device instances, see SetupDiRegisterDeviceInfo.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiopendevregkey WINSETUPAPI HKEY
// SetupDiOpenDevRegKey( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Scope, DWORD HwProfile, DWORD KeyType,
// REGSAM samDesired );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiOpenDevRegKey")]
public static extern SafeRegistryHandle SetupDiOpenDevRegKey(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
DICS_FLAG Scope, uint HwProfile, DIREG KeyType, RegistryRights samDesired);
/// <summary>Converts memory retrieved from a property call to a managed object of the correct type.</summary>
/// <param name="mem">The allocated memory.</param>
/// <param name="propType">The type of the property.</param>
/// <param name="convType">The type to which to convert the result if ambiguous.</param>
/// <returns>A managed object with the value from the memory.</returns>
public static object SetupDiPropertyToManagedObject(ISafeMemoryHandle mem, DEVPROPTYPE propType, Type convType = null)
{
object Value = null;
switch (propType)
{
case DEVPROPTYPE.DEVPROP_TYPE_EMPTY:
case DEVPROPTYPE.DEVPROP_TYPE_NULL:
break;
case DEVPROPTYPE.DEVPROP_TYPE_SECURITY_DESCRIPTOR:
Value = new RawSecurityDescriptor(mem.GetBytes(0, mem.Size), 0);
break;
case DEVPROPTYPE.DEVPROP_TYPE_STRING_INDIRECT:
Value = mem.ToString(-1, CharSet.Unicode);
break;
case DEVPROPTYPE.DEVPROP_TYPE_STRING_LIST:
Value = mem.ToStringEnum(CharSet.Unicode).ToArray();
break;
default:
(DEVPROPTYPE type, DEVPROPTYPE mod) spt = propType.Split();
var type = convType ?? CorrespondingTypeAttribute.GetCorrespondingTypes(spt.type).FirstOrDefault();
if (type is not null)
{
Value = spt.mod switch
{
0 => mem.DangerousGetHandle().Convert(mem.Size, type, CharSet.Unicode),
DEVPROPTYPE.DEVPROP_TYPEMOD_ARRAY => mem.DangerousGetHandle().ToArray(type, mem.Size / Marshal.SizeOf(type), 0, mem.Size),
_ => null
};
}
Value ??= mem.GetBytes(0, mem.Size);
break;
}
return Value;
}
/// <summary>The <c>SetupDiRegisterCoDeviceInstallers</c> function is the default handler for DIF_REGISTER_COINSTALLERS.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element that represents the device for which to
/// register co-installers. The device information set must not contain any remote elements.
/// </param>
/// <param name="DeviceInfoData">A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.</param>
/// <returns>
/// <c>SetupDiRegisterCoDeviceInstallers</c> returns <c>TRUE</c> if the function succeeds. If the function returns <c>FALSE</c>,
/// call GetLastError for extended error information.
/// </returns>
/// <remarks>
/// <para>The caller of <c>SetupDiRegisterCoDeviceInstallers</c> must be a member of the Administrators group.</para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiRegisterCoDeviceInstallers</c> and only in those situations where the
/// class installer must perform co-installer registration operations after <c>SetupDiRegisterCoDeviceInstallers</c> completes the
/// default co-installer registration operation. In such situations, the class installer must directly call
/// <c>SetupDiRegisterCoDeviceInstallers</c> when the installer processes a DIF_REGISTER_COINSTALLERS request. For more information
/// about calling the default handler, see Calling Default DIF Code Handlers.
/// </para>
/// <para>
/// <c>SetupDiRegisterCoDeviceInstallers</c> reads the INF file for the device specified by DeviceInfoData and creates registry
/// entries to register any device-specific co-installers listed in the INF file. Co-installers are listed in an INF
/// DDInstall.CoInstallers section. This function also copies the files for the co-installers, unless the DI_NOFILECOPY flag is set.
/// </para>
/// <para>
/// If there is no driver selected, or the device has an INF file for Windows 9x or Millennium Edition, this function does not
/// register any co-installers.
/// </para>
/// <para>
/// Registering a new device-specific co-installer invalidates the Device Installer's current list of co-installers. After a
/// successful registration, the Device Installer updates its list of co-installers.
/// </para>
/// <para>This function only registers device-specific co-installers, not class co-installers.</para>
/// <para>For more information about how to write and register device-specific co-installers, see Writing a Co-installer.</para>
/// <para>The device information set specified by DeviceInfoSet must only contain elements on the local computer.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiregistercodeviceinstallers WINSETUPAPI BOOL
// SetupDiRegisterCoDeviceInstallers( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiRegisterCoDeviceInstallers")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiRegisterCoDeviceInstallers(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData);
/// <summary>The <c>SetupDiRegisterDeviceInfo</c> function is the default handler for the DIF_REGISTERDEVICE request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device to register. The
/// device information set must not contain any remote elements.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This is an IN-OUT
/// parameter because DeviceInfoData. <c>DevInst</c> might be updated with a new handle value upon return.
/// </param>
/// <param name="Flags">
/// <para>A flag value that controls how the device is registered, which can be zero or the following value:</para>
/// <para>SPRDI_FIND_DUPS</para>
/// <para>
/// Search for a previously-existing device instance that corresponds to the device that is represented by DeviceInfoData. If this
/// flag is not specified, the device instance is registered regardless of whether a device instance already exists for it.
/// </para>
/// <para>If the caller supplies CompareProc, the caller must also set this flag.</para>
/// </param>
/// <param name="CompareProc">
/// A pointer to a comparison callback function to use in duplicate detection. This parameter is optional and can be <c>NULL</c>. If
/// this parameter is specified, the callback function is called for each device instance that is of the same class as the device
/// instance that is being registered.
/// <para>
/// The compare function must return ERROR_DUPLICATE_FOUND if it finds that the two devices are duplicates. Otherwise, it should
/// return NO_ERROR. If some other error is encountered, the callback function should return the appropriate ERROR_* code to
/// indicate the failure.
/// </para>
/// <para>
/// If CompareProc is not specified and duplication detection is requested, a default comparison behavior is used. The default is to
/// compare the new device's detect signature with the detect signature of all other devices in the class. The detect signature is
/// contained in the class-specific resource descriptor of the device's boot log configuration.
/// </para>
/// </param>
/// <param name="CompareContext">
/// A pointer to a caller-supplied context buffer that is passed into the callback function. This parameter is ignored if
/// CompareProc is not specified.
/// </param>
/// <param name="DupDeviceInfoData">
/// <para>
/// A pointer to an SP_DEVINFO_DATA structure to receive information about a duplicate device instance, if any, discovered as a
/// result of attempting to register this device. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// the caller must set DupDeviceInfoData. <c>cbSize</c> to <c>sizeof</c>(SP_DEVINFO_DATA). This will be filled in if the function
/// returns <c>FALSE</c>, and GetLastError returns ERROR_DUPLICATE_FOUND. This device information element is added as a member of
/// the specified DeviceInfoSet, if not already a member. If DupDeviceInfoData is not specified, the duplicate is not added to the
/// device information set.
/// </para>
/// <para>If you call this function when handling a DIF_REGISTERDEVICE request, the DupDeviceInfoData parameter must be <c>NULL</c>.</para>
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiRegisterDeviceInfo</c> is primarily designed to register a non-PnP device with the Plug and Play (PnP) manager on a
/// local computer. Although <c>SetupDiRegisterDeviceInfo</c> will not fail if the device information set is for a remote computer,
/// the result is of limited use because the device information set cannot subsequently be used with DIF_Xxx installation requests
/// or <c>SetupDi</c> Xxx functions that do not support operations on a remote computer. For example, calling
/// <c>SetupDiCreateDevRegKey</c> to execute an INF section for a newly registered device on a remote computer will fail.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiRegisterDeviceInfo</c> and only in those situations where the class
/// installer must perform device registration operations after <c>SetupDiRegisterDeviceInfo</c> completes the default device
/// registration operation. In such situations, the class installer must directly call <c>SetupDiRegisterDeviceInfo</c> when the
/// installer processes a DIF_REGISTERDEVICE request. For more information about calling the default handler, see Calling Default
/// DIF Code Handlers.
/// </para>
/// <para>
/// After registering a device information element, the caller should update any stored copies of the <c>DevInst</c> handle
/// associated with this device. This is necessary because the handle value might have changed during registration. The caller does
/// not have to retrieve the SP_DEVINFO_DATA structure again because the <c>DevInst</c> field of the structure is updated to reflect
/// the current value of the handle.
/// </para>
/// <para>
/// Do not directly call this function for PnP device instances. PnP device instances are automatically registered by the operating
/// system. However, you must register non-PnP device instances in one of the following ways:
/// </para>
/// <list type="number">
/// <item>
/// <term>
/// If your installation application uses a DIF_DETECT request to successfully detect a device, it should also use a
/// DIF_REGISTERDEVICE request to register the device instance. The request should be handled in the default manner. (By default,
/// SetupDiCallClassInstaller first calls the class installer and class co-installers to do duplicate detection and register the
/// device instance. If these installers do not register the device instance, <c>SetupDiCallClassInstaller</c> calls
/// <c>SetupDiRegisterDeviceInfo</c> to do duplicate detection and register the device instance.)
/// </term>
/// </item>
/// <item>
/// <term>
/// If your installation application creates a device instance (for example, by calling SetupDiCreateDeviceInfo) but does not do
/// duplicate detection, your installation application should use a DIF_REGISTERDEVICE request to register the device instance. The
/// request should be handled in the default manner as described earlier.
/// </term>
/// </item>
/// <item>
/// <term>
/// If your installation application creates a new device and does duplicate detection, your installation application should use a
/// DIF_REGISTERDEVICE request but should prevent <c>SetupDiCallClassInstaller</c> from calling <c>SetupDiRegisterDeviceInfo</c>. To
/// prevent <c>SetupDiCallClassInstaller</c> from calling <c>SetupDiRegisterDeviceInfo</c>, set the DI_NODI_DEFAULTACTION flag in
/// the <c>Flags</c> member of the SP_DEVINSTALL_PARAMS structure for the device instance. The caller of
/// <c>SetupDiRegisterDeviceInfo</c> must be a member of the Administrators group.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiregisterdeviceinfo WINSETUPAPI BOOL
// SetupDiRegisterDeviceInfo( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Flags, PSP_DETSIG_CMPPROC CompareProc,
// PVOID CompareContext, PSP_DEVINFO_DATA DupDeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiRegisterDeviceInfo")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiRegisterDeviceInfo(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, SPRDI Flags,
[In, Optional] PSP_DETSIG_CMPPROC CompareProc, [In, Optional] IntPtr CompareContext, ref SP_DEVINFO_DATA DupDeviceInfoData);
/// <summary>The <c>SetupDiRegisterDeviceInfo</c> function is the default handler for the DIF_REGISTERDEVICE request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device to register. The
/// device information set must not contain any remote elements.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This is an IN-OUT
/// parameter because DeviceInfoData. <c>DevInst</c> might be updated with a new handle value upon return.
/// </param>
/// <param name="Flags">
/// <para>A flag value that controls how the device is registered, which can be zero or the following value:</para>
/// <para>SPRDI_FIND_DUPS</para>
/// <para>
/// Search for a previously-existing device instance that corresponds to the device that is represented by DeviceInfoData. If this
/// flag is not specified, the device instance is registered regardless of whether a device instance already exists for it.
/// </para>
/// <para>If the caller supplies CompareProc, the caller must also set this flag.</para>
/// </param>
/// <param name="CompareProc">
/// A pointer to a comparison callback function to use in duplicate detection. This parameter is optional and can be <c>NULL</c>. If
/// this parameter is specified, the callback function is called for each device instance that is of the same class as the device
/// instance that is being registered.
/// <para>
/// The compare function must return ERROR_DUPLICATE_FOUND if it finds that the two devices are duplicates. Otherwise, it should
/// return NO_ERROR. If some other error is encountered, the callback function should return the appropriate ERROR_* code to
/// indicate the failure.
/// </para>
/// <para>
/// If CompareProc is not specified and duplication detection is requested, a default comparison behavior is used. The default is to
/// compare the new device's detect signature with the detect signature of all other devices in the class. The detect signature is
/// contained in the class-specific resource descriptor of the device's boot log configuration.
/// </para>
/// </param>
/// <param name="CompareContext">
/// A pointer to a caller-supplied context buffer that is passed into the callback function. This parameter is ignored if
/// CompareProc is not specified.
/// </param>
/// <param name="DupDeviceInfoData">
/// <para>
/// A pointer to an SP_DEVINFO_DATA structure to receive information about a duplicate device instance, if any, discovered as a
/// result of attempting to register this device. This parameter is optional and can be <c>NULL</c>. If this parameter is specified,
/// the caller must set DupDeviceInfoData. <c>cbSize</c> to <c>sizeof</c>(SP_DEVINFO_DATA). This will be filled in if the function
/// returns <c>FALSE</c>, and GetLastError returns ERROR_DUPLICATE_FOUND. This device information element is added as a member of
/// the specified DeviceInfoSet, if not already a member. If DupDeviceInfoData is not specified, the duplicate is not added to the
/// device information set.
/// </para>
/// <para>If you call this function when handling a DIF_REGISTERDEVICE request, the DupDeviceInfoData parameter must be <c>NULL</c>.</para>
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiRegisterDeviceInfo</c> is primarily designed to register a non-PnP device with the Plug and Play (PnP) manager on a
/// local computer. Although <c>SetupDiRegisterDeviceInfo</c> will not fail if the device information set is for a remote computer,
/// the result is of limited use because the device information set cannot subsequently be used with DIF_Xxx installation requests
/// or <c>SetupDi</c> Xxx functions that do not support operations on a remote computer. For example, calling
/// <c>SetupDiCreateDevRegKey</c> to execute an INF section for a newly registered device on a remote computer will fail.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiRegisterDeviceInfo</c> and only in those situations where the class
/// installer must perform device registration operations after <c>SetupDiRegisterDeviceInfo</c> completes the default device
/// registration operation. In such situations, the class installer must directly call <c>SetupDiRegisterDeviceInfo</c> when the
/// installer processes a DIF_REGISTERDEVICE request. For more information about calling the default handler, see Calling Default
/// DIF Code Handlers.
/// </para>
/// <para>
/// After registering a device information element, the caller should update any stored copies of the <c>DevInst</c> handle
/// associated with this device. This is necessary because the handle value might have changed during registration. The caller does
/// not have to retrieve the SP_DEVINFO_DATA structure again because the <c>DevInst</c> field of the structure is updated to reflect
/// the current value of the handle.
/// </para>
/// <para>
/// Do not directly call this function for PnP device instances. PnP device instances are automatically registered by the operating
/// system. However, you must register non-PnP device instances in one of the following ways:
/// </para>
/// <list type="number">
/// <item>
/// <term>
/// If your installation application uses a DIF_DETECT request to successfully detect a device, it should also use a
/// DIF_REGISTERDEVICE request to register the device instance. The request should be handled in the default manner. (By default,
/// SetupDiCallClassInstaller first calls the class installer and class co-installers to do duplicate detection and register the
/// device instance. If these installers do not register the device instance, <c>SetupDiCallClassInstaller</c> calls
/// <c>SetupDiRegisterDeviceInfo</c> to do duplicate detection and register the device instance.)
/// </term>
/// </item>
/// <item>
/// <term>
/// If your installation application creates a device instance (for example, by calling SetupDiCreateDeviceInfo) but does not do
/// duplicate detection, your installation application should use a DIF_REGISTERDEVICE request to register the device instance. The
/// request should be handled in the default manner as described earlier.
/// </term>
/// </item>
/// <item>
/// <term>
/// If your installation application creates a new device and does duplicate detection, your installation application should use a
/// DIF_REGISTERDEVICE request but should prevent <c>SetupDiCallClassInstaller</c> from calling <c>SetupDiRegisterDeviceInfo</c>. To
/// prevent <c>SetupDiCallClassInstaller</c> from calling <c>SetupDiRegisterDeviceInfo</c>, set the DI_NODI_DEFAULTACTION flag in
/// the <c>Flags</c> member of the SP_DEVINSTALL_PARAMS structure for the device instance. The caller of
/// <c>SetupDiRegisterDeviceInfo</c> must be a member of the Administrators group.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiregisterdeviceinfo WINSETUPAPI BOOL
// SetupDiRegisterDeviceInfo( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Flags, PSP_DETSIG_CMPPROC CompareProc,
// PVOID CompareContext, PSP_DEVINFO_DATA DupDeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiRegisterDeviceInfo")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiRegisterDeviceInfo(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, SPRDI Flags,
[In, Optional] PSP_DETSIG_CMPPROC CompareProc, [In, Optional] IntPtr CompareContext, [In, Optional] IntPtr DupDeviceInfoData);
/// <summary>The <c>SetupDiRemoveDevice</c> function is the default handler for the DIF_REMOVE installation request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set for the local system that contains a device information element that represents the device
/// to remove.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This is an IN-OUT
/// parameter because DeviceInfoSet. <c>DevInst</c> might be updated with a new handle value upon return. If this is a global
/// removal or the last hardware profile-specific removal, all traces of the device instance are deleted from the registry and the
/// handle will be <c>NULL</c>.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to <c>GetLastError</c>.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiRemoveDevice</c> removes the device from the system. It deletes the device's hardware and software registry keys and
/// any hardware-profile-specific registry keys (configuration-specific registry keys). This function dynamically stops the device
/// if its <c>DevInst</c> is active and this is a global removal or the last configuration-specific removal. If the device cannot be
/// dynamically stopped, flags are set in the Install Parameter block of the device information set that eventually cause the user
/// to be prompted to restart the computer.
/// </para>
/// <para>
/// Device removal is either global to all hardware profiles or specific to one hardware profile as specified by the <c>Scope</c>
/// member of the SP_REMOVEDEVICE_PARAMS structure that supplies the class installation parameters for the DIF_REMOVE request.
/// Configuration-specific removal is only appropriate for root-enumerated devices and should only be requested by system code.
/// </para>
/// <para>The caller of <c>SetupDiRemoveDevice</c> must be a member of the Administrators group.</para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiRemoveDevice</c> and only in those situations where the class installer
/// must perform device removal operations after <c>SetupDiRemoveDevice</c> completes the default device removal operation. In such
/// situations, the class installer must directly call <c>SetupDiRemoveDevice</c> when the installer processes a DIF_REMOVE request.
/// For more information about calling the default handler, see Calling Default DIF Code Handlers.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiremovedevice WINSETUPAPI BOOL SetupDiRemoveDevice(
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiRemoveDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiRemoveDevice(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>The <c>SetupDiRemoveDeviceInterface</c> function removes a registered device interface from the system.</summary>
/// <param name="DeviceInfoSet">
/// A pointer to the device information set that contains the device interface to remove. This handle is typically returned by <c>SetupDiGetClassDevs</c>.
/// </param>
/// <param name="DeviceInterfaceData">
/// <para>
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the device interface in DeviceInfoSet to remove. This pointer
/// is typically returned by SetupDiEnumDeviceInterfaces.
/// </para>
/// <para>
/// After the interface is removed, this function sets the SPINT_REMOVED flag in DeviceInterfaceData <c>.Flags</c>. It also clears
/// the SPINT_ACTIVE flag, but be aware that this flag should have already been cleared before this function was called.
/// </para>
/// </param>
/// <returns>
/// <c>SetupDiRemoveDeviceInterface</c> returns <c>TRUE</c> if the function completed without error. If the function completed with
/// an error, it returns <c>FALSE</c> and the error code for the failure can be retrieved by calling GetLastError.
/// </returns>
/// <remarks>
/// <para>The caller of this function must be a member of the Administrators group.</para>
/// <para>
/// <c>SetupDiRemoveDeviceInterface</c> removes the specified device interface from the system. This includes deleting the
/// associated registry key.
/// </para>
/// <para>Call SetupDiDeleteDeviceInterfaceData to delete the interface from a device information list.</para>
/// <para>
/// A device interface must be disabled to be removed. If the interface is enabled, this function fails and GetLastError returns
/// ERROR_DEVICE_INTERFACE_ACTIVE. Disable an interface by using whatever interface-specific mechanism is provided (for example, an
/// IOCTL). If the caller has no way to disable an interface and the interface must be removed, the caller must stop the underlying
/// device by using SetupDiChangeState. Stopping the device disables all the interfaces exposed by the device.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiremovedeviceinterface WINSETUPAPI BOOL
// SetupDiRemoveDeviceInterface( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiRemoveDeviceInterface")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiRemoveDeviceInterface(HDEVINFO DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
/// <summary>
/// The <c>SetupDiRestartDevices</c> function restarts a specified device or, if necessary, restarts all devices that are operated
/// by the same function and filter drivers that operate the specified device.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains the device information element that represents the device to restart.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure for the device information member that represents the device to restart. This
/// parameter is also an output parameter because <c>SetupDiRestartDevices</c> updates the device installation parameters for this
/// device information member and the status and problem code of the corresponding device instance. For more information about these
/// updates, see the following <c>Remarks</c> section.
/// </param>
/// <returns>
/// If the operation succeeds, <c>SetupDiRestartDevices</c> returns <c>TRUE</c>; otherwise, the function returns <c>FALSE</c> and
/// the logged error can be retrieved by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiRestartDevices</c> should be called only by a class installer when a class installer is handling a DIF_INSTALLDEVICE
/// request and only in rare situations where the class installer must perform operations after all default installation operations,
/// except for starting a device, have completed . For more information about calling <c>SetupDiRestartDevices</c> in these
/// situations, see DIF_INSTALLDEVICE.
/// </para>
/// <para>
/// <c>SetupDiRestartDevices</c> restarts only the specified device if the restart can be performed without affecting the
/// installation of other devices that are operated by the same function driver or filter drivers that operate the device.
/// Specifically, if the restart of the specified device does not copy new files or modify any files that were previously installed
/// for the device, <c>SetupDiRestartDevices</c> restarts only the specified device. Otherwise, the function restarts all devices
/// that are operated by the same function and filter drivers that operate the specified device.
/// </para>
/// <para>
/// <c>SetupDiRestartDevices</c> updates the device installation parameters and device status to reflect the result of the attempted
/// restart operation. For example:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>If the device is started, <c>SetupDiRestartDevices</c> sets the device status to DN_STARTED.</term>
/// </item>
/// <item>
/// <term>
/// If a system restart is necessary to start a device, <c>SetupDiRestartDevices</c> sets the DI_NEEDREBOOT flag in the <c>Flags</c>
/// member of the SP_DEVINSTALL_PARAMETER structure that is associated with the device information element and sets the problem code
/// for the device to CM_PROB_NEED_RESTART.
/// </term>
/// </item>
/// </list>
/// <para>
/// The CM_Get_DevNode_Status function retrieves the status and problem code for a device instance and the
/// SetupDiGetDeviceInstallParams function retrieves the device installation parameters for the device information element that
/// represents the device instance.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdirestartdevices WINSETUPAPI BOOL
// SetupDiRestartDevices( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiRestartDevices")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiRestartDevices(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiSelectBestCompatDrv</c> function is the default handler for the DIF_SELECTBESTCOMPATDRV installation request.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device for which to select
/// the best compatible driver.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.
/// <c>SetupDiSelectBestCompatDrv</c> selects the best driver for a device information element from the compatible driver list for
/// the specified device.
/// </param>
/// <returns>
/// If the operation succeeds, <c>SetupDiSelectBestCompatDrv</c> returns <c>TRUE</c>. Otherwise, the function returns <c>FALSE</c>
/// and the logged error can be retrieved by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If the caller of <c>SetupDiSelectBestCompatDrv</c> is a member of the Administrators group and the class of the device is
/// different that the class of the selected driver, <c>SetupDiSelectBestCompatDrv</c> sets the class of the device to the class of
/// the driver. If this behavior is not desired, call this function at a lower privilege level.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiSelectBestCompatDrv</c> and only in those situations where the class
/// installer must perform driver selection operations after <c>SetupDiSelectBestCompatDrv</c> completes the default driver
/// selection operation. In such situations, the class installer must directly call <c>SetupDiSelectBestCompatDrv</c> when the
/// installer processes a DIF_SELECTBESTCOMPATDRV request. For more information about calling the default handler, see Calling
/// Default DIF Code Handlers.
/// </para>
/// <para>
/// <c>SetupDiSelectBestCompatDrv</c> is primarily designed to select the best compatible driver for a device information element on
/// a local computer. Although <c>SetupDiSelectBestCompatDrv</c> will not fail if the device information set is for a remote
/// computer, the result is of limited use because the device information set cannot subsequently be used as input with DIF_Xxx
/// installation requests or <c>SetupDi</c> Xxx functions that do not support operations for a remote computer. In particular, the
/// device information set cannot subsequently be used as input with a DIF_INSTALLDEVICE installation request to install a device on
/// a remote computer.
/// </para>
/// <para>For information about how the best driver is selected, see How Windows Selects Drivers.</para>
/// <para>To get the selected driver for a device, call SetupDiGetSelectedDriver.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiselectbestcompatdrv WINSETUPAPI BOOL
// SetupDiSelectBestCompatDrv( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSelectBestCompatDrv")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSelectBestCompatDrv(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiSelectBestCompatDrv</c> function is the default handler for the DIF_SELECTBESTCOMPATDRV installation request.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device for which to select
/// the best compatible driver.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet.
/// <c>SetupDiSelectBestCompatDrv</c> selects the best driver for a device information element from the compatible driver list for
/// the specified device.
/// </param>
/// <returns>
/// If the operation succeeds, <c>SetupDiSelectBestCompatDrv</c> returns <c>TRUE</c>. Otherwise, the function returns <c>FALSE</c>
/// and the logged error can be retrieved by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If the caller of <c>SetupDiSelectBestCompatDrv</c> is a member of the Administrators group and the class of the device is
/// different that the class of the selected driver, <c>SetupDiSelectBestCompatDrv</c> sets the class of the device to the class of
/// the driver. If this behavior is not desired, call this function at a lower privilege level.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiSelectBestCompatDrv</c> and only in those situations where the class
/// installer must perform driver selection operations after <c>SetupDiSelectBestCompatDrv</c> completes the default driver
/// selection operation. In such situations, the class installer must directly call <c>SetupDiSelectBestCompatDrv</c> when the
/// installer processes a DIF_SELECTBESTCOMPATDRV request. For more information about calling the default handler, see Calling
/// Default DIF Code Handlers.
/// </para>
/// <para>
/// <c>SetupDiSelectBestCompatDrv</c> is primarily designed to select the best compatible driver for a device information element on
/// a local computer. Although <c>SetupDiSelectBestCompatDrv</c> will not fail if the device information set is for a remote
/// computer, the result is of limited use because the device information set cannot subsequently be used as input with DIF_Xxx
/// installation requests or <c>SetupDi</c> Xxx functions that do not support operations for a remote computer. In particular, the
/// device information set cannot subsequently be used as input with a DIF_INSTALLDEVICE installation request to install a device on
/// a remote computer.
/// </para>
/// <para>For information about how the best driver is selected, see How Windows Selects Drivers.</para>
/// <para>To get the selected driver for a device, call SetupDiGetSelectedDriver.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiselectbestcompatdrv WINSETUPAPI BOOL
// SetupDiSelectBestCompatDrv( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSelectBestCompatDrv")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSelectBestCompatDrv(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData);
/// <summary>The <c>SetupDiSelectDevice</c> function is the default handler for the DIF_SELECTDEVICE request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device for which to select a driver.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element. This parameter is optional and can be
/// <c>NULL</c>. If this parameter is specified, <c>SetupDiSelectDevice</c> selects the driver for the specified device and sets
/// DeviceInfoData. <c>ClassGuid</c> to the GUID of the device setup class for the selected driver. If this parameter is
/// <c>NULL</c>, <c>SetupDiSelectDevice</c> sets the selected driver in the global class driver list for DeviceInfoSet.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiSelectDevice</c> handles the user interface that allows the user to select a driver for the specified device, or a
/// device information set if a device is not specified. By setting the <c>Flags</c> field of the SP_DEVINSTALL_PARAMS structure for
/// the device, or the device information set if a device is not specified, the caller can specify special handling of the user
/// interface, for example, to allow users to select a driver from an OEM installation disk.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiSelectDevice</c> and only in those situations where the class installer
/// must perform driver selection operations after <c>SetupDiSelectDevice</c> completes the default driver selection operation. In
/// such situations, the class installer must directly call <c>SetupDiSelectDevice</c> when the installer processes a
/// DIF_SELECTDEVICE request. For more information about calling the default handler, see Calling Default DIF Code Handlers.
/// </para>
/// <para>
/// <c>SetupDiSelectDevice</c> is primarily designed to select a driver for a device on a local computer before installing the
/// device. Although <c>SetupDiSelectDevice</c> will not fail if the device information set is for a remote computer, the result is
/// of limited use because the device information set cannot subsequently be used with DIF_Xxx installation requests or
/// <c>SetupDi</c> Xxx functions that do not support operations on a remote computer. In particular, the device information set
/// cannot be used as input with a DIF_INSTALLDEVICE installation request to install a device on a remote computer.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiselectdevice WINSETUPAPI BOOL SetupDiSelectDevice(
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSelectDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSelectDevice(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>The <c>SetupDiSelectDevice</c> function is the default handler for the DIF_SELECTDEVICE request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the device for which to select a driver.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element. This parameter is optional and can be
/// <c>NULL</c>. If this parameter is specified, <c>SetupDiSelectDevice</c> selects the driver for the specified device and sets
/// DeviceInfoData. <c>ClassGuid</c> to the GUID of the device setup class for the selected driver. If this parameter is
/// <c>NULL</c>, <c>SetupDiSelectDevice</c> sets the selected driver in the global class driver list for DeviceInfoSet.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiSelectDevice</c> handles the user interface that allows the user to select a driver for the specified device, or a
/// device information set if a device is not specified. By setting the <c>Flags</c> field of the SP_DEVINSTALL_PARAMS structure for
/// the device, or the device information set if a device is not specified, the caller can specify special handling of the user
/// interface, for example, to allow users to select a driver from an OEM installation disk.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiSelectDevice</c> and only in those situations where the class installer
/// must perform driver selection operations after <c>SetupDiSelectDevice</c> completes the default driver selection operation. In
/// such situations, the class installer must directly call <c>SetupDiSelectDevice</c> when the installer processes a
/// DIF_SELECTDEVICE request. For more information about calling the default handler, see Calling Default DIF Code Handlers.
/// </para>
/// <para>
/// <c>SetupDiSelectDevice</c> is primarily designed to select a driver for a device on a local computer before installing the
/// device. Although <c>SetupDiSelectDevice</c> will not fail if the device information set is for a remote computer, the result is
/// of limited use because the device information set cannot subsequently be used with DIF_Xxx installation requests or
/// <c>SetupDi</c> Xxx functions that do not support operations on a remote computer. In particular, the device information set
/// cannot be used as input with a DIF_INSTALLDEVICE installation request to install a device on a remote computer.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiselectdevice WINSETUPAPI BOOL SetupDiSelectDevice(
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSelectDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSelectDevice(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData);
/// <summary>
/// The <c>SetupDiSelectOEMDrv</c> function selects a driver for a device information set or a particular device information element
/// that uses an OEM path supplied by the user.
/// </summary>
/// <param name="hwndParent">
/// A window handle that will be the parent of any dialogs created during the processing of this function. This parameter can be
/// used to override the <c>hwndParent</c> field in the installation parameters block of the specified device information set or element.
/// </param>
/// <param name="DeviceInfoSet">A handle to the device information set for which to select a driver.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is
/// optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiSelectOEMDrv</c> associates the selected driver with
/// the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSelectOEMDrv</c> associates the selected driver with the
/// global class driver list for DeviceInfoSet.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiSelectOEMDrv</c> is primarily designed to select an OEM driver for a device on a local computer before installing the
/// device on that computer. Although <c>SetupDiSelectOEMDrv</c> will not fail if the device information set is for a remote
/// computer, the result is of limited use because the device information set cannot subsequently be used with DIF_Xxx installation
/// requests or <c>SetupDi</c> Xxx functions that do not support operations on a remote computer. In particular, the device
/// information set cannot be used as input with a DIF_INSTALLDEVICE installation request to install a device on a remote computer.
/// </para>
/// <para>
/// <c>SetupDiSelectOEMDrv</c> prompts the user for the OEM path and then calls the class installer to select a driver from the OEM path.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiselectoemdrv WINSETUPAPI BOOL SetupDiSelectOEMDrv(
// HWND hwndParent, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSelectOEMDrv")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSelectOEMDrv([In, Optional] HWND hwndParent, HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiSelectOEMDrv</c> function selects a driver for a device information set or a particular device information element
/// that uses an OEM path supplied by the user.
/// </summary>
/// <param name="hwndParent">
/// A window handle that will be the parent of any dialogs created during the processing of this function. This parameter can be
/// used to override the <c>hwndParent</c> field in the installation parameters block of the specified device information set or element.
/// </param>
/// <param name="DeviceInfoSet">A handle to the device information set for which to select a driver.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is
/// optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiSelectOEMDrv</c> associates the selected driver with
/// the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSelectOEMDrv</c> associates the selected driver with the
/// global class driver list for DeviceInfoSet.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiSelectOEMDrv</c> is primarily designed to select an OEM driver for a device on a local computer before installing the
/// device on that computer. Although <c>SetupDiSelectOEMDrv</c> will not fail if the device information set is for a remote
/// computer, the result is of limited use because the device information set cannot subsequently be used with DIF_Xxx installation
/// requests or <c>SetupDi</c> Xxx functions that do not support operations on a remote computer. In particular, the device
/// information set cannot be used as input with a DIF_INSTALLDEVICE installation request to install a device on a remote computer.
/// </para>
/// <para>
/// <c>SetupDiSelectOEMDrv</c> prompts the user for the OEM path and then calls the class installer to select a driver from the OEM path.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiselectoemdrv WINSETUPAPI BOOL SetupDiSelectOEMDrv(
// HWND hwndParent, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSelectOEMDrv")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSelectOEMDrv([In, Optional] HWND hwndParent, HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData);
/// <summary>
/// The <c>SetupDiSetClassInstallParams</c> function sets or clears class install parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to set class install parameters.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the device for which to set class install parameters. This parameter
/// is optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiSetClassInstallParams</c> sets the class
/// installation parameters for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetClassInstallParams</c> sets the
/// class install parameters that are associated with DeviceInfoSet.
/// </param>
/// <param name="ClassInstallParams">
/// <para>
/// A pointer to a buffer that contains the new class install parameters to use. The SP_CLASSINSTALL_HEADER structure at the
/// beginning of this buffer must have its <c>cbSize</c> field set to <c>sizeof(</c> SP_CLASSINSTALL_HEADER <c>)</c> and the
/// <c>InstallFunction</c> field must be set to the DI_FUNCTION code that reflects the type of parameters contained in the rest of
/// the buffer.
/// </para>
/// <para>
/// If ClassInstallParams is not specified, the current class install parameters, if any, are cleared for the specified device
/// information set or element.
/// </para>
/// </param>
/// <param name="ClassInstallParamsSize">
/// The size, in bytes, of the ClassInstallParams buffer. If the buffer is not supplied (that is, the class install parameters are
/// being cleared), ClassInstallParamsSize must be 0.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// All parameters are validated before any changes are made. Therefore, a return value of <c>FALSE</c> indicates that no parameters
/// were modified.
/// </para>
/// <para>
/// A side effect of setting class install parameters is that the DI_CLASSINSTALLPARAMS flag is set. If the caller wants to set the
/// parameters, but disable their use, this flag must be cleared by a call to <c>SetupDiSetDeviceInstallParams</c>.
/// </para>
/// <para>If the class install parameters are cleared, the DI_CLASSINSTALLPARAMS flag is reset.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetclassinstallparamsa WINSETUPAPI BOOL
// SetupDiSetClassInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_CLASSINSTALL_HEADER
// ClassInstallParams, DWORD ClassInstallParamsSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetClassInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetClassInstallParams(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
[In, Optional] IntPtr ClassInstallParams, uint ClassInstallParamsSize);
/// <summary>
/// The <c>SetupDiSetClassInstallParams</c> function sets or clears class install parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to set class install parameters.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the device for which to set class install parameters. This parameter
/// is optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiSetClassInstallParams</c> sets the class
/// installation parameters for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetClassInstallParams</c> sets the
/// class install parameters that are associated with DeviceInfoSet.
/// </param>
/// <param name="ClassInstallParams">
/// <para>
/// A pointer to a buffer that contains the new class install parameters to use. The SP_CLASSINSTALL_HEADER structure at the
/// beginning of this buffer must have its <c>cbSize</c> field set to <c>sizeof(</c> SP_CLASSINSTALL_HEADER <c>)</c> and the
/// <c>InstallFunction</c> field must be set to the DI_FUNCTION code that reflects the type of parameters contained in the rest of
/// the buffer.
/// </para>
/// <para>
/// If ClassInstallParams is not specified, the current class install parameters, if any, are cleared for the specified device
/// information set or element.
/// </para>
/// </param>
/// <param name="ClassInstallParamsSize">
/// The size, in bytes, of the ClassInstallParams buffer. If the buffer is not supplied (that is, the class install parameters are
/// being cleared), ClassInstallParamsSize must be 0.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// All parameters are validated before any changes are made. Therefore, a return value of <c>FALSE</c> indicates that no parameters
/// were modified.
/// </para>
/// <para>
/// A side effect of setting class install parameters is that the DI_CLASSINSTALLPARAMS flag is set. If the caller wants to set the
/// parameters, but disable their use, this flag must be cleared by a call to <c>SetupDiSetDeviceInstallParams</c>.
/// </para>
/// <para>If the class install parameters are cleared, the DI_CLASSINSTALLPARAMS flag is reset.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetclassinstallparamsa WINSETUPAPI BOOL
// SetupDiSetClassInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_CLASSINSTALL_HEADER
// ClassInstallParams, DWORD ClassInstallParamsSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetClassInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetClassInstallParams(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData,
[In, Optional] IntPtr ClassInstallParams, uint ClassInstallParamsSize);
/// <summary>
/// The <c>SetupDiSetClassProperty</c> function sets a class property for a device setup class or a device interface class.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to a GUID that identifies the device setup class or device interface class for which to set a device property. For
/// information about how to specify the class type, see the Flags parameter.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the device class property to set.
/// </param>
/// <param name="PropertyType">
/// A DEVPROPTYPE-typed value that represents the property-data-type identifier for the device class property. For more information
/// about the property-data-type identifier, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that contains the property value of the device class. If either the property or the data is being deleted,
/// this pointer must be set to <c>NULL</c>, and PropertyBufferSize must be set to zero. For more information about property data,
/// see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="Flags">
/// <para>One of the following values, which specifies whether the class is a device setup class or a device interface class:</para>
/// <para>DICLASSPROP_INSTALLER</para>
/// <para>ClassGuid specifies a device setup class. This flag cannot be used with DICLASSPROP_INTERFACE.</para>
/// <para>DICLASSPROP_INTERFACE</para>
/// <para>ClassGuid specifies a device interface class. This flag cannot be used with DICLASSPROP_INSTALLER.</para>
/// </param>
/// <returns>
/// <para>
/// <c>SetupDiSetClassProperty</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged error
/// can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_CLASS</term>
/// <term>
/// The device setup class that is specified by ClassGuid is not valid. This error can occur only if the DICLASSPROP_INSTALLER flag
/// is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REFERENCE_STRING</term>
/// <term>The device interface reference string is not valid. This error can occur only if the DICLASSPROP_INTERFACE flag is specified.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>
/// An unspecified internal data value was not valid. This error could be logged if the ClassGuid value is not a valid GUID or the
/// property value is not consistent with the property type specified by PropertyType.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertyBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_CLASS</term>
/// <term>
/// The device interface class that is specified by ClassGuid does not exist. This error can occur only if the DICLASSPROP_INTERFACE
/// flag is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>An internal data buffer that was passed to a system call was too small.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>An unspecified item was not found. One possibility is that the property to be deleted does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiSetClassProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiSetClassProperty</c>.</para>
/// <para>A caller of <c>SetupDiSetClassProperty</c> must be a member of the Administrators group to set a device interface property.</para>
/// <para><c>SetupDiSetClassProperty</c> enforces requirements on the property-data-type identifier and the property value.</para>
/// <para>
/// To obtain the device property keys that represent the device properties that are set for a device class on a local computer,
/// call SetupDiGetClassPropertyKeys.
/// </para>
/// <para>
/// To retrieve a device class property on a local computer, call SetupDiGetClassProperty, and to retrieve a device class property
/// on a remote computer, call SetupDiGetClassPropertyEx.
/// </para>
/// <para>To set a device class property on a remote computer, call SetupDiSetClassPropertyEx.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetclasspropertyw WINSETUPAPI BOOL
// SetupDiSetClassPropertyW( const GUID *ClassGuid, const DEVPROPKEY *PropertyKey, DEVPROPTYPE PropertyType, const PBYTE
// PropertyBuffer, DWORD PropertyBufferSize, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetClassPropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetClassProperty(in Guid ClassGuid, in DEVPROPKEY PropertyKey, DEVPROPTYPE PropertyType,
[In, Optional] IntPtr PropertyBuffer, [In, Optional] uint PropertyBufferSize, DICLASSPROP Flags);
/// <summary>
/// The <c>SetupDiSetClassPropertyEx</c> function sets a device property for a device setup class or a device interface class on a
/// local or remote computer.
/// </summary>
/// <param name="ClassGuid">
/// A pointer to a GUID that identifies the device setup class or device interface class for which to set a device property. For
/// information about how to specify the class type, see the Flags parameter.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the device class property to set.
/// </param>
/// <param name="PropertyType">
/// A DEVPROPTYPE-typed value that represents the property-data-type identifier for the class property. For more information about
/// the property-data-type identifier, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that contains the class property value. If either the property or the property value is being deleted,
/// this pointer must be set to <c>NULL</c>, and PropertyBufferSize must be set to zero. For more information about property value
/// requirements, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. The property buffer size must be consistent with the property-data-type
/// identifier that is supplied by PropertyType. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="Flags">
/// <para>One of the following values, which specifies whether the class is a device setup class or a device interface class:</para>
/// <para>DICLASSPROP_INSTALLER</para>
/// <para>ClassGuid specifies a device setup class. This flag cannot be used with DICLASSPROP_INTERFACE.</para>
/// <para>DICLASSPROP_INTERFACE</para>
/// <para>ClassGuid specifies a device interface class. This flag cannot be used with DICLASSPROP_INSTALLER.</para>
/// </param>
/// <param name="MachineName">
/// A pointer to a NULL-terminated Unicode string that contains the UNC name, including the "\" prefix, of a computer. This pointer
/// can be set to <c>NULL</c>. If the pointer is <c>NULL</c>, <c>SetupDiSetClassPropertyEx</c> sets the class property for a class
/// that is installed on the local computer.
/// </param>
/// <param name="Reserved">This parameter must be set to <c>NULL</c>.</param>
/// <returns>
/// <para>
/// <c>SetupDiSetClassPropertyEx</c> returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged
/// error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_CLASS</term>
/// <term>
/// The device setup class that is specified by ClassGuid is not valid. This error can occur only if the DICLASSPROP_INSTALLER flag
/// is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REFERENCE_STRING</term>
/// <term>The device interface reference string is not valid. This error can occur only if the DICLASSPROP_INTERFACE flag is specified.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>
/// An unspecified internal data value was not valid. This error could be logged if either the ClassGuid value is not a valid GUID
/// or the property value does not match the property type specified by PropertyType.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertyBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_MACHINENAME</term>
/// <term>The computer name that is specified by MachineName is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_INTERFACE_CLASS</term>
/// <term>
/// The device interface class that is specified by ClassGuid does not exist. This error can occur only if the DICLASSPROP_INTERFACE
/// flag is specified.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>An internal data buffer that was passed to a system call was too small.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>An unspecified item was not found. One possibility is that the property to be deleted does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiSetClassPropertyEx</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiSetClassPropertyEx</c>.</para>
/// <para>A caller of <c>SetupDiSetClassPropertyEx</c> must be a member of the Administrators group to set a device interface property.</para>
/// <para><c>SetupDiSetClassPropertyEx</c> enforces requirements on the property-data-type identifier and the property value.</para>
/// <para>
/// To obtain the device property keys that represent the device properties that are set for a device class on a remote computer,
/// call SetupDiGetClassPropertyKeysEx.
/// </para>
/// <para>
/// To retrieve a device class property on a local computer, call SetupDiGetClassProperty <c>,</c> and to retrieve a device class
/// property on a remote computer, call SetupDiGetClassPropertyEx.
/// </para>
/// <para>To set a device class property on a local computer, call SetupDiSetClassProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetclasspropertyexw WINSETUPAPI BOOL
// SetupDiSetClassPropertyExW( const GUID *ClassGuid, const DEVPROPKEY *PropertyKey, DEVPROPTYPE PropertyType, const PBYTE
// PropertyBuffer, DWORD PropertyBufferSize, DWORD Flags, PCWSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetClassPropertyExW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetClassPropertyEx(in Guid ClassGuid, in DEVPROPKEY PropertyKey, DEVPROPTYPE PropertyType,
[In, Optional] IntPtr PropertyBuffer, [In, Optional] uint PropertyBufferSize, DICLASSPROP Flags,
[Optional, MarshalAs(UnmanagedType.LPWStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>The <c>SetupDiSetClassRegistryProperty</c> function sets a specified device class property in the registry.</summary>
/// <param name="ClassGuid">A pointer to the GUID that identifies the device class for which a property is to be set.</param>
/// <param name="Property">
/// <para>A value that identifies the property to be set, which must be one of the following:</para>
/// <para>SPCRP_CHARACTERISTICS</para>
/// <para>
/// The caller supplies flags that specify the device characteristics for the class. For a list of characteristics flags, see the
/// DeviceCharacteristics parameter of IoCreateDevice. Device characteristics should be set when the device class is installed and
/// should not be changed after the device class is installed.
/// </para>
/// <para>SPCRP_DEVTYPE</para>
/// <para>
/// The caller supplies the device type for the class. For more information, see Specifying Device Types. Device type should be set
/// when a device class is installed and should not be changed after the device class is installed.
/// </para>
/// <para>SPCRP_EXCLUSIVE</para>
/// <para>
/// The caller supplies a DWORD value that specifies whether users can obtain exclusive access to devices for this class. The
/// supplied value is 1 if exclusive access is allowed, or zero otherwise. The exclusive setting for a device should be set when a
/// device class is installed and should not be changed after the device class is installed.
/// </para>
/// <para>SPCRP_LOWERFILTERS</para>
/// <para>
/// (Windows Vista and later) The caller supplies a REG_MULTI_SZ list of the service names of the lower filter drivers that are
/// installed for the device setup class. For more information about how to install a class filter driver, see Installing a Filter
/// Driver and INF ClassInstall32 Section.
/// </para>
/// <para>SPCRP_SECURITY</para>
/// <para>
/// The caller supplies the device's security descriptor as a SECURITY_DESCRIPTOR structure in self-relative format (described in
/// the Microsoft Windows SDK documentation).
/// </para>
/// <para>SPCRP_SECURITY_SDS</para>
/// <para>
/// The caller supplies the device's security descriptor as a text string. For information about security descriptor strings, see
/// Security Descriptor Definition Language (Windows). For information about the format of security descriptor strings, see Security
/// Descriptor Definition Language (Windows).
/// </para>
/// <para>SPCRP_UPPERFILTERS</para>
/// <para>
/// (Windows Vista and later) The caller supplies a REG_MULTI_SZ list of the service names of the upper filter drivers that are
/// installed for the device setup class. For more information about how to install a class filter driver, see Installing a Filter
/// Driver and INF ClassInstall32 Section.
/// </para>
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that supplies the specified property. This parameter is optional and can be <c>NULL</c>.
/// </param>
/// <param name="PropertyBufferSize">The size, in bytes, of the PropertyBuffer buffer.</param>
/// <param name="MachineName">
/// A pointer to a NULL-terminated string that contains the name of a remote system on which to set the specified device class
/// property. This parameter is optional and can be <c>NULL</c>. If this parameter is <c>NULL</c>, the property is set on the name
/// of the local system.
/// </param>
/// <param name="Reserved">Reserved, must be <c>NULL</c>.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>The caller of this function must be a member of the Administrators group.</para>
/// <para>To determine the data type for a device class property, call SetupDiGetClassRegistryProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetclassregistrypropertyw WINSETUPAPI BOOL
// SetupDiSetClassRegistryPropertyW( const GUID *ClassGuid, DWORD Property, const BYTE *PropertyBuffer, DWORD PropertyBufferSize,
// PCWSTR MachineName, PVOID Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetClassRegistryPropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetClassRegistryProperty(in Guid ClassGuid, SPCRP Property, [In, Optional] IntPtr PropertyBuffer,
uint PropertyBufferSize, [Optional, MarshalAs(UnmanagedType.LPTStr)] string MachineName, [In, Optional] IntPtr Reserved);
/// <summary>
/// The <c>SetupDiSetDeviceInstallParams</c> function sets device installation parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to set device installation parameters.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is
/// optional and can be set to <c>NULL</c>. If this parameter is specified, <c>SetupDiSetDeviceInstallParams</c> sets the
/// installation parameters for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetDeviceInstallParams</c> sets
/// the installation parameters that are associated with the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DeviceInstallParams">
/// A pointer to an SP_DEVINSTALL_PARAMS structure that contains the new values of the parameters. The DeviceInstallParams.
/// <c>cbSize</c> must be set to the size, in bytes, of the structure before this function is called.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// All parameters are validated before any changes are made. Therefore, a return value of <c>FALSE</c> indicates that no parameters
/// were modified.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdeviceinstallparamsa WINSETUPAPI BOOL
// SetupDiSetDeviceInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS_A
// DeviceInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDeviceInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDeviceInstallParams(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
in SP_DEVINSTALL_PARAMS DeviceInstallParams);
/// <summary>
/// The <c>SetupDiSetDeviceInstallParams</c> function sets device installation parameters for a device information set or a
/// particular device information element.
/// </summary>
/// <param name="DeviceInfoSet">A handle to the device information set for which to set device installation parameters.</param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is
/// optional and can be set to <c>NULL</c>. If this parameter is specified, <c>SetupDiSetDeviceInstallParams</c> sets the
/// installation parameters for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetDeviceInstallParams</c> sets
/// the installation parameters that are associated with the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DeviceInstallParams">
/// A pointer to an SP_DEVINSTALL_PARAMS structure that contains the new values of the parameters. The DeviceInstallParams.
/// <c>cbSize</c> must be set to the size, in bytes, of the structure before this function is called.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// All parameters are validated before any changes are made. Therefore, a return value of <c>FALSE</c> indicates that no parameters
/// were modified.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdeviceinstallparamsa WINSETUPAPI BOOL
// SetupDiSetDeviceInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS_A
// DeviceInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDeviceInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDeviceInstallParams(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData,
in SP_DEVINSTALL_PARAMS DeviceInstallParams);
/// <summary>
/// The <c>SetupDiSetDeviceInterfaceDefault</c> function sets a device interface as the default interface for a device interface class.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the device interface to set as the default for a device interface class.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the device interface in DeviceInfoSet.
/// </param>
/// <param name="Flags">Not used, must be zero.</param>
/// <param name="Reserved">Reserved for future use, must be <c>NULL</c>.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// A caller must have Administrator privileges to set the default interface for a device interface class. However, if the requested
/// default interface is the same as the currently set default interface, the function returns <c>TRUE</c> regardless of whether the
/// caller has Administrator privileges.
/// </para>
/// <para>
/// If the function successfully sets the specified device interface as the default for the device class, it updates the Flags
/// member of the supplied SP_DEVICE_INTERFACE_DATA structure.
/// </para>
/// <para>
/// Call SetupDiGetClassDevs to obtain a DevInfoSet handle to a device information set that contains the device interface to set as
/// the default for a device interface class. To obtain the DeviceInterfaceData pointer to the device interface element, call
/// SetupDiEnumDeviceInterfaces to enumerate the interfaces in the device information set. To retrieve information about an
/// enumerated interface, call SetupDiGetDeviceInterfaceDetail.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdeviceinterfacedefault WINSETUPAPI BOOL
// SetupDiSetDeviceInterfaceDefault( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, DWORD Flags, PVOID
// Reserved );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDeviceInterfaceDefault")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDeviceInterfaceDefault(HDEVINFO DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
[In, Optional] uint Flags, [In, Optional] IntPtr Reserved);
/// <summary>The <c>SetupDiSetDeviceInterfaceProperty</c> function sets a device property of a device interface.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains the device interface for which to set a device interface property.
/// </param>
/// <param name="DeviceInterfaceData">
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that represents the device interface for which to set a device interface property.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the device interface property to set.
/// </param>
/// <param name="PropertyType">
/// A DEVPROPTYPE-typed value that represents the property-data-type identifier of the device interface property to set. For more
/// information about the property-data-type identifier, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that contains the device interface property value. If either the property or the interface value is being
/// deleted, this pointer must be set to <c>NULL</c>, and PropertyBufferSize must be set to zero. For more information about
/// property value data, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. The property buffer size must be consistent with the property-data-type
/// identifier that is supplied by PropertyType. If PropertyBuffer is set to <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="Flags">Must be set to zero.</param>
/// <returns>
/// <para>
/// <c>SetupDiSetDeviceInterfaceProperty</c> returns <c>TRUE</c> if it is successful. Otherwise, this function returns <c>FALSE</c>,
/// and the logged error can be retrieved by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>
/// A supplied parameter is not valid. One possibility is that the device interface specified by DeviceInterfaceData is not valid.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>
/// An unspecified data value was not valid. This error could be logged if either the symbolic link name of the device interface is
/// not valid or the property-data-type identifier is not valid.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVICE_INTERFACE</term>
/// <term>The device interface that is specified by DeviceInterfaceData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>An internal data buffer that was passed to a system call was too small.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>An unspecified internal element was not found. One possibility is that a property to be deleted does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiSetDeviceInterfaceProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiSetDeviceInterfaceProperty</c>.</para>
/// <para>
/// A caller of <c>SetupDiSetDeviceInterfaceProperty</c> must be a member of the Administrators group to set a device interface property.
/// </para>
/// <para><c>SetupDiSetDeviceInterfaceProperty</c> enforces requirements on the property-data-type identifier and the property value.</para>
/// <para>To obtain the device property keys that represent the device properties that are set for a device interface, call SetupDiGetDeviceInterfacePropertyKeys.</para>
/// <para>To retrieve a device interface property, call SetupDiGetDeviceInterfaceProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdeviceinterfacepropertyw WINSETUPAPI BOOL
// SetupDiSetDeviceInterfacePropertyW( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, const DEVPROPKEY
// *PropertyKey, DEVPROPTYPE PropertyType, const PBYTE PropertyBuffer, DWORD PropertyBufferSize, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDeviceInterfacePropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDeviceInterfaceProperty(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
in DEVPROPKEY PropertyKey, DEVPROPTYPE PropertyType, [In, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, [In, Optional] uint Flags);
/// <summary>The <c>SetupDiSetDeviceProperty</c> function sets a device instance property.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set. This device information set contains a device information element that represents the
/// device instance for which to set a device instance property.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to the SP_DEVINFO_DATA structure that identifies the device instance for which to set a device instance property.
/// </param>
/// <param name="PropertyKey">
/// A pointer to a DEVPROPKEY structure that represents the device property key of the device instance property to set.
/// </param>
/// <param name="PropertyType">
/// A DEVPROPTYPE-typed value that represents the property-data-type identifier for the device instance property. For more
/// information, see the <c>Remarks</c> section later in this topic.
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that contains the device instance property value. If the property is being deleted or set to a <c>NULL</c>
/// value, this pointer must be <c>NULL</c>, and PropertyBufferSize must be set to zero.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of the PropertyBuffer buffer. If PropertyBuffer is <c>NULL</c>, PropertyBufferSize must be set to zero.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c>, and the logged error can be retrieved
/// by calling GetLastError.
/// </para>
/// <para>The following table includes some of the more common error codes that this function might log.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value of Flags is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The device information set that is specified by DevInfoSet is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A supplied parameter is not valid. One possibility is that the device information element is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_REG_PROPERTY</term>
/// <term>The property key that is supplied by PropertyKey is not valid or the property is not writable.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>
/// The property-data-type identifier that is supplied by PropertyType, or the property value that is supplied by PropertyBuffer, is
/// not valid.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_USER_BUFFER</term>
/// <term>A user buffer is not valid. One possibility is that PropertyBuffer is NULL, and PropertyBufferSize is not zero.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVINST</term>
/// <term>The device instance that is specified by DevInfoData does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>An internal data buffer that was passed to a system call was too small.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>There was not enough system memory available to complete the operation.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>An unspecified internal element was not found. One possibility is that the property to be deleted does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have Administrator privileges.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>SetupDiSetDeviceProperty</c> is part of the unified device property model.</para>
/// <para>SetupAPI supports only a Unicode version of <c>SetupDiSetDeviceProperty</c>.</para>
/// <para>A caller of <c>SetupDiSetDeviceProperty</c> must be a member of the Administrators group to set a device instance property.</para>
/// <para><c>SetupDiSetDeviceProperty</c> enforces requirements on the property-data-type identifier and the property value.</para>
/// <para>To obtain the device property keys for the instance device properties that are set for a device, call SetupDiGetDevicePropertyKeys.</para>
/// <para>To retrieve a device instance property, call SetupDiGetDeviceProperty.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdevicepropertyw WINSETUPAPI BOOL
// SetupDiSetDevicePropertyW( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, const DEVPROPKEY *PropertyKey, DEVPROPTYPE
// PropertyType, const PBYTE PropertyBuffer, DWORD PropertyBufferSize, DWORD Flags );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDevicePropertyW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDeviceProperty(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
in DEVPROPKEY PropertyKey, DEVPROPTYPE PropertyType, [In, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize, [In, Optional] uint Flags);
/// <summary>The <c>SetupDiSetDeviceRegistryProperty</c> function sets a Plug and Play device property for a device.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element that represents the device for which to set a
/// Plug and Play device property.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. If the
/// <c>ClassGuid</c> property is set, DeviceInfoData. <c>ClassGuid</c> is set upon return to the new class for the device.
/// </param>
/// <param name="Property">
/// <para>One of the following values, which identifies the property to be set. For descriptions of these values, see SetupDiGetDeviceRegistryProperty.</para>
/// <list type="bullet">
/// <item>
/// <term>SPDRP_CONFIGFLAGS</term>
/// </item>
/// <item>
/// <term>SPDRP_EXCLUSIVE</term>
/// </item>
/// <item>
/// <term>SPDRP_FRIENDLYNAME</term>
/// </item>
/// <item>
/// <term>SPDRP_LOCATION_INFORMATION</term>
/// </item>
/// <item>
/// <term>SPDRP_LOWERFILTERS</term>
/// </item>
/// <item>
/// <term>SPDRP_REMOVAL_POLICY_OVERRIDE</term>
/// </item>
/// <item>
/// <term>SPDRP_SECURITY</term>
/// </item>
/// <item>
/// <term>SPDRP_SECURITY_SDS</term>
/// </item>
/// <item>
/// <term>SPDRP_UI_NUMBER_DESC_FORMAT</term>
/// </item>
/// <item>
/// <term>SPDRP_UPPERFILTERS</term>
/// </item>
/// </list>
/// <para>The following values are reserved for use by the operating system and cannot be used in the Property parameter:</para>
/// <list type="bullet">
/// <item>
/// <term>SPDRP_ADDRESS</term>
/// </item>
/// <item>
/// <term>SPDRP_BUSNUMBER</term>
/// </item>
/// <item>
/// <term>SPDRP_BUSTYPEGUID</term>
/// </item>
/// <item>
/// <term>SPDRP_CHARACTERISTICS</term>
/// </item>
/// <item>
/// <term>SPDRP_CAPABILITIES</term>
/// </item>
/// <item>
/// <term>SPDRP_CLASS</term>
/// </item>
/// <item>
/// <term>SPDRP_CLASSGUID</term>
/// </item>
/// <item>
/// <term>SPDRP_DEVICE_POWER_DATA</term>
/// </item>
/// <item>
/// <term>SPDRP_DEVICEDESC</term>
/// </item>
/// <item>
/// <term>SPDRP_DEVTYPE</term>
/// </item>
/// <item>
/// <term>SPDRP_DRIVER</term>
/// </item>
/// <item>
/// <term>SPDRP_ENUMERATOR_NAME</term>
/// </item>
/// <item>
/// <term>SPDRP_INSTALL_STATE</term>
/// </item>
/// <item>
/// <term>SPDRP_LEGACYBUSTYPE</term>
/// </item>
/// <item>
/// <term>SPDRP_LOCATION_PATHS</term>
/// </item>
/// <item>
/// <term>SPDRP_MFG</term>
/// </item>
/// <item>
/// <term>SPDRP_PHYSICAL_DEVICE_OBJECT_NAME</term>
/// </item>
/// <item>
/// <term>SPDRP_REMOVAL_POLICY</term>
/// </item>
/// <item>
/// <term>SPDRP_REMOVAL_POLICY_HW_DEFAULT</term>
/// </item>
/// <item>
/// <term>SPDRP_SERVICE</term>
/// </item>
/// <item>
/// <term>SPDRP_UI_NUMBER</term>
/// </item>
/// </list>
/// </param>
/// <param name="PropertyBuffer">
/// A pointer to a buffer that contains the new data for the property. If the property is being cleared, then this pointer should be
/// <c>NULL</c> and PropertyBufferSize must be zero.
/// </param>
/// <param name="PropertyBufferSize">
/// The size, in bytes, of PropertyBuffer. If PropertyBuffer is <c>NULL</c>, then this field must be zero.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>The caller of this function must be a member of the Administrators group.</para>
/// <para>
/// The class name property cannot be set because it is based on the corresponding class GUID and is automatically updated when that
/// property is changed. When the ClassGUID property changes, <c>SetupDiSetDeviceRegistryProperty</c> automatically cleans up any
/// software keys associated with the device.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdeviceregistrypropertya WINSETUPAPI BOOL
// SetupDiSetDeviceRegistryPropertyA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, const BYTE
// *PropertyBuffer, DWORD PropertyBufferSize );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDeviceRegistryPropertyA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDeviceRegistryProperty(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData,
SPDRP Property, [In, Optional] IntPtr PropertyBuffer, uint PropertyBufferSize);
/// <summary>The <c>SetupDiSetDriverInstallParams</c> function sets driver installation parameters for a driver information element.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a driver information element that represents the driver for which to set
/// installation parameters.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is
/// optional and can be set to <c>NULL</c>. If this parameter is specified, <c>SetupDiSetDriverInstallParams</c> sets the driver
/// installation parameters for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetDriverInstallParams</c> sets
/// driver installation parameters for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver for which installation parameters are set. If DeviceInfoData
/// is specified, this driver must be a member of a driver list that is associated with DeviceInfoData. If DeviceInfoData is
/// <c>NULL</c>, this driver must be a member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInstallParams">A pointer to an SP_DRVINSTALL_PARAMS structure that specifies the new driver install parameters.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdriverinstallparamsa WINSETUPAPI BOOL
// SetupDiSetDriverInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData,
// PSP_DRVINSTALL_PARAMS DriverInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDriverInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDriverInstallParams(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
in SP_DRVINFO_DATA_V2 DriverInfoData, in SP_DRVINSTALL_PARAMS DriverInstallParams);
/// <summary>The <c>SetupDiSetDriverInstallParams</c> function sets driver installation parameters for a driver information element.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a driver information element that represents the driver for which to set
/// installation parameters.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is
/// optional and can be set to <c>NULL</c>. If this parameter is specified, <c>SetupDiSetDriverInstallParams</c> sets the driver
/// installation parameters for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetDriverInstallParams</c> sets
/// driver installation parameters for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver for which installation parameters are set. If DeviceInfoData
/// is specified, this driver must be a member of a driver list that is associated with DeviceInfoData. If DeviceInfoData is
/// <c>NULL</c>, this driver must be a member of the global class driver list for DeviceInfoSet.
/// </param>
/// <param name="DriverInstallParams">A pointer to an SP_DRVINSTALL_PARAMS structure that specifies the new driver install parameters.</param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetdriverinstallparamsa WINSETUPAPI BOOL
// SetupDiSetDriverInstallParamsA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData,
// PSP_DRVINSTALL_PARAMS DriverInstallParams );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetDriverInstallParamsA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetDriverInstallParams(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData,
in SP_DRVINFO_DATA_V2 DriverInfoData, in SP_DRVINSTALL_PARAMS DriverInstallParams);
/// <summary>
/// The <c>SetupDiSetSelectedDevice</c> function sets a device information element as the selected member of a device information
/// set. This function is typically used by an installation wizard.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the device information element to set as the selected member of the device
/// information set.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet to set as the selected
/// member of DeviceInfoSet.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetselecteddevice WINSETUPAPI BOOL
// SetupDiSetSelectedDevice( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetSelectedDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetSelectedDevice(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData);
/// <summary>
/// The <c>SetupDiSetSelectedDriver</c> function sets, or resets, the selected driver for a device information element or the
/// selected class driver for a device information set.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the driver list from which to select a driver for a device information
/// element or for the device information set.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This parameter is
/// optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiSetSelectedDriver</c> sets, or resets, the selected
/// driver for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetSelectedDriver</c> sets, or resets, the selected
/// class driver for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// <para>
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver to be selected. This parameter is optional and can be
/// <c>NULL</c>. If this parameter and DeviceInfoData are supplied, the specified driver must be a member of a driver list that is
/// associated with DeviceInfoData. If this parameter is specified and DeviceInfoData is <c>NULL</c>, the driver must be a member of
/// the global class driver list for DeviceInfoSet. If this parameter is <c>NULL</c>, the selected driver is reset for the device
/// information element, if DeviceInfoData is specified, or the device information set, if DeviceInfoData is <c>NULL</c>.
/// </para>
/// <para>
/// If the DriverInfoData. <c>Reserved</c> is <c>NULL</c>, the caller is requesting a search for a driver node with the specified
/// parameters ( <c>DriverType</c>, <c>Description</c>, and <c>ProviderName</c>). If a match is found, that driver node is selected.
/// The <c>Reserved</c> field is updated on output to reflect the actual driver node where the match was found. If a match is not
/// found, the function fails and a call to GetLastError returns ERROR_INVALID_PARAMETER.
/// </para>
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If the caller of <c>SetupDiSetSelectedDriver</c> is a member of the Administrators group, the class of the device is set to the
/// class of the selected driver, provided that the two classes are different.
/// </para>
/// <para>
/// If DriverInfoData is <c>NULL</c>, <c>SetupDiSetSelectedDriver</c> resets the selected driver. As a result, there is no selected driver.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetselecteddrivera WINSETUPAPI BOOL
// SetupDiSetSelectedDriverA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetSelectedDriverA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetSelectedDriver(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref SP_DRVINFO_DATA_V2 DriverInfoData);
/// <summary>
/// The <c>SetupDiSetSelectedDriver</c> function sets, or resets, the selected driver for a device information element or the
/// selected class driver for a device information set.
/// </summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains the driver list from which to select a driver for a device information
/// element or for the device information set.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This parameter is
/// optional and can be <c>NULL</c>. If this parameter is specified, <c>SetupDiSetSelectedDriver</c> sets, or resets, the selected
/// driver for the specified device. If this parameter is <c>NULL</c>, <c>SetupDiSetSelectedDriver</c> sets, or resets, the selected
/// class driver for DeviceInfoSet.
/// </param>
/// <param name="DriverInfoData">
/// <para>
/// A pointer to an SP_DRVINFO_DATA structure that specifies the driver to be selected. This parameter is optional and can be
/// <c>NULL</c>. If this parameter and DeviceInfoData are supplied, the specified driver must be a member of a driver list that is
/// associated with DeviceInfoData. If this parameter is specified and DeviceInfoData is <c>NULL</c>, the driver must be a member of
/// the global class driver list for DeviceInfoSet. If this parameter is <c>NULL</c>, the selected driver is reset for the device
/// information element, if DeviceInfoData is specified, or the device information set, if DeviceInfoData is <c>NULL</c>.
/// </para>
/// <para>
/// If the DriverInfoData. <c>Reserved</c> is <c>NULL</c>, the caller is requesting a search for a driver node with the specified
/// parameters ( <c>DriverType</c>, <c>Description</c>, and <c>ProviderName</c>). If a match is found, that driver node is selected.
/// The <c>Reserved</c> field is updated on output to reflect the actual driver node where the match was found. If a match is not
/// found, the function fails and a call to GetLastError returns ERROR_INVALID_PARAMETER.
/// </para>
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// with a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// If the caller of <c>SetupDiSetSelectedDriver</c> is a member of the Administrators group, the class of the device is set to the
/// class of the selected driver, provided that the two classes are different.
/// </para>
/// <para>
/// If DriverInfoData is <c>NULL</c>, <c>SetupDiSetSelectedDriver</c> resets the selected driver. As a result, there is no selected driver.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdisetselecteddrivera WINSETUPAPI BOOL
// SetupDiSetSelectedDriverA( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA_A DriverInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiSetSelectedDriverA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiSetSelectedDriver(HDEVINFO DeviceInfoSet, [In, Optional] IntPtr DeviceInfoData, [In, Optional] IntPtr DriverInfoData);
/// <summary>The <c>SetupDiUnremoveDevice</c> function is the default handler for the DIF_UNREMOVE installation request.</summary>
/// <param name="DeviceInfoSet">
/// A handle to a device information set for the local system that contains a device information element that represents a device to
/// restore and to restart.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that specifies the device information element in DeviceInfoSet. This is an IN-OUT
/// parameter because DeviceInfoData. <c>DevInst</c> might be updated with a new handle value on return.
/// </param>
/// <returns>
/// The function returns <c>TRUE</c> if it is successful. Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved
/// by a call to GetLastError.
/// </returns>
/// <remarks>
/// <para>
/// <c>SetupDiUnremoveDevice</c> restores a device to a hardware profile. This function starts the device, if possible, or it sets a
/// flag in the device install parameters that eventually causes the user to be prompted to shut down the system.
/// </para>
/// <para>
/// <c>Note</c> Only a class installer should call <c>SetupDiUnremoveDevice</c> and only in those situations where the class
/// installer must perform device unremove operations after <c>SetupDiUnremoveDevice</c> completes the default device unremove
/// operation. In such situations, the class installer must directly call <c>SetupDiUnremoveDevice</c> when the installer processes
/// a DIF_UNREMOVE request. For more information about calling the default handler, see Calling Default DIF Code Handlers.
/// </para>
/// <para>
/// The device being restored must have class install parameters for DIF_UNREMOVE or the function fails and GetLastError returns ERROR_NO_CLASSINSTALL_PARAMS.
/// </para>
/// <para>The DeviceInfoSet must only contain elements on the local computer.</para>
/// <para>The caller of <c>SetupDiUnremoveDevice</c> must be a member of the Administrators group.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdiunremovedevice WINSETUPAPI BOOL
// SetupDiUnremoveDevice( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData );
[DllImport(Lib_SetupAPI, SetLastError = true, ExactSpelling = true)]
[PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiUnremoveDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiUnremoveDevice(HDEVINFO DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
}
}