diff --git a/PInvoke/SetupAPI/SetupAPI.DiFuncs.cs b/PInvoke/SetupAPI/SetupAPI.DiFuncs.cs index e5b00d91..98849080 100644 --- a/PInvoke/SetupAPI/SetupAPI.DiFuncs.cs +++ b/PInvoke/SetupAPI/SetupAPI.DiFuncs.cs @@ -1,9 +1,8 @@ +using Microsoft.Win32.SafeHandles; using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; using System.Text; -using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke @@ -1211,7 +1210,7 @@ namespace Vanara.PInvoke // REGSAM samDesired, HINF InfHandle, PCSTR InfSectionName ); [DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiCreateDeviceInterfaceRegKeyA")] - public static extern HKEY SetupDiCreateDeviceInterfaceRegKey(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + public static extern SafeRegistryHandle SetupDiCreateDeviceInterfaceRegKey(HDEVINFO DeviceInfoSet, in SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, [Optional] uint Reserved, System.Security.AccessControl.RegistryRights samDesired, [In, Optional] HINF InfHandle, [In, Optional, MarshalAs(UnmanagedType.LPTStr)] string InfSectionName); @@ -1294,7 +1293,7 @@ namespace Vanara.PInvoke // HINF InfHandle, PCSTR InfSectionName ); [DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiCreateDevRegKeyA")] - public static extern HKEY SetupDiCreateDevRegKey(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, DICS_FLAG Scope, + public static extern SafeRegistryHandle SetupDiCreateDevRegKey(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, DICS_FLAG Scope, uint HwProfile, DIREG KeyType, [In, Optional] HINF InfHandle, [In, Optional, MarshalAs(UnmanagedType.LPTStr)] string InfSectionName); /// @@ -1687,16 +1686,10 @@ namespace Vanara.PInvoke [PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupDiEnumDeviceInfo")] public static IEnumerable SetupDiEnumDeviceInfo(HDEVINFO DeviceInfoSet) { - var data = new SP_DEVINFO_DATA { cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA)) }; - for (uint i = 0; true; i++) - { - if (!SetupDiEnumDeviceInfo(DeviceInfoSet, i, ref data)) - { - Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_NO_MORE_ITEMS); - yield break; - } + var data = StructHelper.InitWithSize(); + for (uint i = 0; SetupDiEnumDeviceInfo(DeviceInfoSet, i, ref data); i++) yield return data; - } + Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_NO_MORE_ITEMS); } /// @@ -2845,24 +2838,13 @@ namespace Vanara.PInvoke /// A pointer to a NULL-terminated string that specifies: /// /// - /// /// An identifier (ID) of a Plug and Play (PnP) enumerator. This ID can either be the enumerator's globally unique identifier (GUID) /// or symbolic name. For example, "PCI" can be used to specify the PCI PnP enumerator. Other examples of symbolic names for PnP /// enumerators include "USB", "PCMCIA", and "SCSI". - /// - /// - /// - /// A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the Flags parameter. /// + /// A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the Flags parameter /// - /// This pointer is optional and can be - /// NULL - /// . If an - /// Enumerator - /// value is not used to select devices, set - /// Enumerator - /// to - /// NULL + /// This pointer is optional and can be NULL. If an Enumerator value is not used to select devices, set Enumerator to NULL. /// For more information about how to set the Enumerator value, see the following Remarks section. /// /// @@ -2875,22 +2857,34 @@ namespace Vanara.PInvoke /// information set. This parameter can be a bitwise OR of one or more of the following flags. For more information about combining /// these control options, see the following Remarks section. /// - /// DIGCF_ALLCLASSES - /// Return a list of installed devices for the specified device setup classes or device interface classes. - /// DIGCF_DEVICEINTERFACE - /// + /// + /// + /// DIGCF_ALLCLASSES + /// Return a list of installed devices for the specified device setup classes or device interface classes. + /// + /// + /// DIGCF_DEVICEINTERFACE + /// /// Return devices that support device interfaces for the specified device interface classes. This flag must be set in the Flags /// parameter if the Enumerator parameter specifies a device instance ID. - /// - /// DIGCF_DEFAULT - /// + /// + /// + /// + /// DIGCF_DEFAULT + /// /// Return only the device that is associated with the system default device interface, if one is set, for the specified device /// interface classes. - /// - /// DIGCF_PRESENT - /// Return only devices that are currently present. - /// DIGCF_PROFILE - /// Return only devices that are a part of the current hardware profile. + /// + /// + /// + /// DIGCF_PRESENT + /// Return only devices that are currently present. + /// + /// + /// DIGCF_PROFILE + /// Return only devices that are a part of the current hardware profile. + /// + /// /// /// /// The handle to an existing device information set to which SetupDiGetClassDevsEx adds the requested device information @@ -2929,29 +2923,19 @@ namespace Vanara.PInvoke /// or only for a specified device setup class: /// /// + /// To return devices for all device setup classes, set the DIGCF_ALLCLASSES flag and set the ClassGuid parameter to NULL. /// - /// To return devices for all device setup classes, set the DIGCF_ALLCLASSES flag and set the ClassGuid parameter to NULL. - /// - /// - /// /// To return devices only for a specific device setup class, do not set DIGCF_ALLCLASSES and use ClassGuid to supply the GUID of /// the device setup class. - /// /// /// /// In addition, you can use the following filtering options to further restrict which devices are returned. /// + /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. + /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. /// - /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. - /// - /// - /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. - /// - /// - /// /// To return devices for a specific PnP enumerator only, use the Enumerator parameter to supply the GUID or symbolic name of the /// enumerator. If Enumerator is NULL, SetupDiGetClassDevsEx returns devices for all PnP enumerators. - /// /// /// /// Device Interface Class Control Options @@ -2961,20 +2945,16 @@ namespace Vanara.PInvoke /// /// /// - /// /// To return devices that support a device interface of any class, set the DIGCF_DEVICEINTERFACE flag, set the DIGCF_ALLCLASSES /// flag, and set ClassGuid to NULL. The function adds to the device information set a device information element that /// represents such a device, and then adds to the device information element a device interface list that contains all the device /// interfaces that the device supports. - /// /// /// - /// /// To return only devices that support a device interface of a specified class, set the DIGCF_DEVICEINTERFACE flag and use the /// ClassGuid parameter to supply the class GUID of the device interface class. The function adds to the device information set a /// device information element that represents such a device, and then adds a device interface of the specified class to the device /// interface list for that device information element. - /// /// /// /// @@ -2983,35 +2963,25 @@ namespace Vanara.PInvoke /// /// /// - /// /// To return only the device that supports the system default interface, if one is set, for a specified device interface class, set /// the DIGCF_DEVICEINTERFACE flag, set the DIGCF_DEFAULT flag, and use ClassGuid to supply the class GUID of the device interface /// class. The function adds to the device information set a device information element that represents such a device, and then adds /// the system default interface to the device interface list for that device information element. - /// /// /// - /// /// To return a device that supports a system default interface for an unspecified device interface class, set the /// DIGCF_DEVICEINTERFACE flag, set the DIGCF_ALLCLASSES flag, set the DIGCF_DEFAULT flag, and set ClassGuid to NULL. The /// function adds to the device information set a device information element that represents such a device, and then adds the system /// default interface to the device interface list for that device information element. - /// /// /// /// You can also use the following options in combination with the other options to further restrict which devices are returned. /// + /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. + /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. /// - /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. - /// - /// - /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. - /// - /// - /// /// To return only a specific device, set the DIGCF_DEVICEINTERFACE flag and use the Enumerator parameter to supply the device /// instance ID of the device. To include all possible devices, set Enumerator to NULL. - /// /// /// /// Retrieving Devices in a Device Setup Class That Support a Device Interface Class @@ -3023,14 +2993,18 @@ namespace Vanara.PInvoke /// /// /// - /// /// Call SetupDiCreateDeviceInfoList to create an empty device information set for the "Volume" device setup class. Set ClassGuid to /// a pointer to the class GUID for the "Volume" device setup class and set hwndParent as appropriate. In response to such a call, /// the function will return a handle to type HDEVINFO to the device information set. - /// /// /// - /// Call SetupDiGetClassDevsEx with the following settings: + /// Call SetupDiGetClassDevsEx with the following settings: + /// + /// Set ClassGuid to a pointer to the class GUID of the "mounted device" device interface class. + /// Set Flags to DIGCF_DEVICEINTERFACE. + /// Set DeviceInfoSet to the HDEVINFO handle obtained in step (1). + /// Set hwndParent as appropriate and the remaining parameters to NULL. + /// /// /// /// @@ -3061,24 +3035,13 @@ namespace Vanara.PInvoke /// A pointer to a NULL-terminated string that specifies: /// /// - /// /// An identifier (ID) of a Plug and Play (PnP) enumerator. This ID can either be the enumerator's globally unique identifier (GUID) /// or symbolic name. For example, "PCI" can be used to specify the PCI PnP enumerator. Other examples of symbolic names for PnP /// enumerators include "USB", "PCMCIA", and "SCSI". - /// - /// - /// - /// A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the Flags parameter. /// + /// A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the Flags parameter /// - /// This pointer is optional and can be - /// NULL - /// . If an - /// Enumerator - /// value is not used to select devices, set - /// Enumerator - /// to - /// NULL + /// This pointer is optional and can be NULL. If an Enumerator value is not used to select devices, set Enumerator to NULL. /// For more information about how to set the Enumerator value, see the following Remarks section. /// /// @@ -3091,22 +3054,34 @@ namespace Vanara.PInvoke /// information set. This parameter can be a bitwise OR of one or more of the following flags. For more information about combining /// these control options, see the following Remarks section. /// - /// DIGCF_ALLCLASSES - /// Return a list of installed devices for the specified device setup classes or device interface classes. - /// DIGCF_DEVICEINTERFACE - /// + /// + /// + /// DIGCF_ALLCLASSES + /// Return a list of installed devices for the specified device setup classes or device interface classes. + /// + /// + /// DIGCF_DEVICEINTERFACE + /// /// Return devices that support device interfaces for the specified device interface classes. This flag must be set in the Flags /// parameter if the Enumerator parameter specifies a device instance ID. - /// - /// DIGCF_DEFAULT - /// + /// + /// + /// + /// DIGCF_DEFAULT + /// /// Return only the device that is associated with the system default device interface, if one is set, for the specified device /// interface classes. - /// - /// DIGCF_PRESENT - /// Return only devices that are currently present. - /// DIGCF_PROFILE - /// Return only devices that are a part of the current hardware profile. + /// + /// + /// + /// DIGCF_PRESENT + /// Return only devices that are currently present. + /// + /// + /// DIGCF_PROFILE + /// Return only devices that are a part of the current hardware profile. + /// + /// /// /// /// The handle to an existing device information set to which SetupDiGetClassDevsEx adds the requested device information @@ -3145,29 +3120,19 @@ namespace Vanara.PInvoke /// or only for a specified device setup class: /// /// + /// To return devices for all device setup classes, set the DIGCF_ALLCLASSES flag and set the ClassGuid parameter to NULL. /// - /// To return devices for all device setup classes, set the DIGCF_ALLCLASSES flag and set the ClassGuid parameter to NULL. - /// - /// - /// /// To return devices only for a specific device setup class, do not set DIGCF_ALLCLASSES and use ClassGuid to supply the GUID of /// the device setup class. - /// /// /// /// In addition, you can use the following filtering options to further restrict which devices are returned. /// + /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. + /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. /// - /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. - /// - /// - /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. - /// - /// - /// /// To return devices for a specific PnP enumerator only, use the Enumerator parameter to supply the GUID or symbolic name of the /// enumerator. If Enumerator is NULL, SetupDiGetClassDevsEx returns devices for all PnP enumerators. - /// /// /// /// Device Interface Class Control Options @@ -3177,20 +3142,16 @@ namespace Vanara.PInvoke /// /// /// - /// /// To return devices that support a device interface of any class, set the DIGCF_DEVICEINTERFACE flag, set the DIGCF_ALLCLASSES /// flag, and set ClassGuid to NULL. The function adds to the device information set a device information element that /// represents such a device, and then adds to the device information element a device interface list that contains all the device /// interfaces that the device supports. - /// /// /// - /// /// To return only devices that support a device interface of a specified class, set the DIGCF_DEVICEINTERFACE flag and use the /// ClassGuid parameter to supply the class GUID of the device interface class. The function adds to the device information set a /// device information element that represents such a device, and then adds a device interface of the specified class to the device /// interface list for that device information element. - /// /// /// /// @@ -3199,35 +3160,25 @@ namespace Vanara.PInvoke /// /// /// - /// /// To return only the device that supports the system default interface, if one is set, for a specified device interface class, set /// the DIGCF_DEVICEINTERFACE flag, set the DIGCF_DEFAULT flag, and use ClassGuid to supply the class GUID of the device interface /// class. The function adds to the device information set a device information element that represents such a device, and then adds /// the system default interface to the device interface list for that device information element. - /// /// /// - /// /// To return a device that supports a system default interface for an unspecified device interface class, set the /// DIGCF_DEVICEINTERFACE flag, set the DIGCF_ALLCLASSES flag, set the DIGCF_DEFAULT flag, and set ClassGuid to NULL. The /// function adds to the device information set a device information element that represents such a device, and then adds the system /// default interface to the device interface list for that device information element. - /// /// /// /// You can also use the following options in combination with the other options to further restrict which devices are returned. /// + /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. + /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. /// - /// To return only devices that are present in the system, set the DIGCF_PRESENT flag. - /// - /// - /// To return only devices that are part of the current hardware profile, set the DIGCF_PROFILE flag. - /// - /// - /// /// To return only a specific device, set the DIGCF_DEVICEINTERFACE flag and use the Enumerator parameter to supply the device /// instance ID of the device. To include all possible devices, set Enumerator to NULL. - /// /// /// /// Retrieving Devices in a Device Setup Class That Support a Device Interface Class @@ -3239,14 +3190,18 @@ namespace Vanara.PInvoke /// /// /// - /// /// Call SetupDiCreateDeviceInfoList to create an empty device information set for the "Volume" device setup class. Set ClassGuid to /// a pointer to the class GUID for the "Volume" device setup class and set hwndParent as appropriate. In response to such a call, /// the function will return a handle to type HDEVINFO to the device information set. - /// /// /// - /// Call SetupDiGetClassDevsEx with the following settings: + /// Call SetupDiGetClassDevsEx with the following settings: + /// + /// Set ClassGuid to a pointer to the class GUID of the "mounted device" device interface class. + /// Set Flags to DIGCF_DEVICEINTERFACE. + /// Set DeviceInfoSet to the HDEVINFO handle obtained in step (1). + /// Set hwndParent as appropriate and the remaining parameters to NULL. + /// /// /// /// @@ -3389,5 +3344,173 @@ namespace Vanara.PInvoke [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetupDiGetClassInstallParams(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, [In, Optional] IntPtr ClassInstallParams, uint ClassInstallParamsSize, out uint RequiredSize); + + /// Provides a for that is disposed using . + public class SafeHDEVINFO : SafeHANDLE + { + private readonly Lazy detail; + + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHDEVINFO(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) => detail = new Lazy(GetDetail); + + /// Initializes a new instance of the class. + private SafeHDEVINFO() : base() => detail = new Lazy(GetDetail); + + /// + /// If the device information set is for a remote computer, this member is a configuration manager machine handle for the remote + /// computer. If the device information set is for the local computer, this member is HANDLE.NULL. + /// + public HANDLE MachineHandle => detail.Value.RemoteMachineHandle; + + /// + /// A string that contains the name of the remote computer. If the device information set is for the local computer, this member + /// is . + /// + public string MachineName => detail.Value.RemoteMachineName == "" ? null : detail.Value.RemoteMachineName; + + /// + /// The setup class GUID that is associated with the device information set or if there is no associated + /// setup class. + /// + public Guid? ClassGuid => detail.Value.ClassGuid == Guid.Empty ? null : detail.Value.ClassGuid; + + /// + /// Returns a handle to a device information set that contains requested device information elements for a local or a remote computer. + /// + /// + /// The GUID for a device setup class or a device interface class. This value is optional and can be NULL. If a GUID + /// value is not used to select devices, set ClassGuid to NULL. + /// + /// + /// A pointer to a NULL-terminated string that specifies: + /// + /// + /// An identifier (ID) of a Plug and Play (PnP) enumerator. This ID can either be the enumerator's globally unique identifier + /// (GUID) or symbolic name. For example, "PCI" can be used to specify the PCI PnP enumerator. Other examples of symbolic names + /// for PnP enumerators include "USB", "PCMCIA", and "SCSI". + /// + /// + /// A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the Flags parameter + /// + /// + /// + /// This pointer is optional and can be NULL. If an Enumerator value is not used to select devices, set Enumerator to NULL. + /// + /// + /// + /// + /// A value that specifies control options that filter the device information elements that are added to the device information set. + /// + /// + /// + /// A string that contains the name of a remote computer on which the devices reside. A value of NULL for MachineName + /// specifies that the device is installed on the local computer. + /// + /// + /// If the operation succeeds, SetupDiGetClassDevsEx returns a handle to a device information set that contains all + /// installed devices that matched the supplied parameters. If the operation fails, the function returns INVALID_HANDLE_VALUE. + /// To get extended error information, call GetLastError. + /// + /// See for more detail. + public static SafeHDEVINFO Create(Guid? classGuid, DIGCF flags = DIGCF.DIGCF_PRESENT, string pnpFilter = null, string machineName = null) + { + if (classGuid.HasValue) + return Win32Error.ThrowLastErrorIfInvalid(SetupDiGetClassDevsEx(classGuid.Value, pnpFilter, default, flags, default, machineName)); + else + return Win32Error.ThrowLastErrorIfInvalid(SetupDiGetClassDevsEx(IntPtr.Zero, pnpFilter, default, flags, default, machineName)); + } + + /// + /// Creates an empty device information set on a remote or a local computer and optionally associates the set with a device + /// setup class. + /// + /// + /// The GUID of the device setup class to associate with the newly created device information set. If this parameter is + /// specified, only devices of this class can be included in this device information set. If this parameter is set to the device information set is not associated with a specific device setup class. + /// + /// + /// A string that contains the name of a computer on a network. If a name is specified, only devices on that computer can be + /// created and opened in this device information set. If this parameter is set to , the device + /// information set is for devices on the local computer. + /// + /// A handle to an empty device information set. + /// + /// If the device information set is for devices on a remote computer (MachineName is not NULL), all subsequent + /// operations on this set or any of its elements must use routines that support device information sets with remote elements. + /// The SetupDi Xxx routines that do not provide this support, such as SetupDiCallClassInstaller, have a statement to + /// that effect in their reference page. + /// + public static SafeHDEVINFO CreateEmpty(Guid? classGuid = null, string machineName = null) + { + if (classGuid.HasValue) + return Win32Error.ThrowLastErrorIfInvalid(SetupDiCreateDeviceInfoListEx(classGuid.Value, default, machineName)); + else + return Win32Error.ThrowLastErrorIfInvalid(SetupDiCreateDeviceInfoListEx(IntPtr.Zero, default, machineName)); + } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HDEVINFO(SafeHDEVINFO h) => h.handle; + + /// Adjusts the current handle to include additional requested device information elements. + /// + /// The GUID for a device setup class or a device interface class. This value is optional and can be NULL. If a GUID + /// value is not used to select devices, set ClassGuid to NULL. + /// + /// + /// A pointer to a NULL-terminated string that specifies: + /// + /// + /// An identifier (ID) of a Plug and Play (PnP) enumerator. This ID can either be the enumerator's globally unique identifier + /// (GUID) or symbolic name. For example, "PCI" can be used to specify the PCI PnP enumerator. Other examples of symbolic names + /// for PnP enumerators include "USB", "PCMCIA", and "SCSI". + /// + /// + /// A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the Flags parameter + /// + /// + /// + /// This pointer is optional and can be NULL. If an Enumerator value is not used to select devices, set Enumerator to NULL. + /// + /// + /// + /// + /// A value that specifies control options that filter the device information elements that are added to the device information set. + /// + /// + /// + /// If the operation succeeds, SetupDiGetClassDevsEx returns a handle to a device information set that contains all + /// installed devices that matched the supplied parameters. If the operation fails, the function returns INVALID_HANDLE_VALUE. + /// To get extended error information, call GetLastError. + /// + /// See for more detail. + public void Adjust(Guid? classGuid, DIGCF flags = DIGCF.DIGCF_ALLCLASSES, string pnpFilter = null) + { + SafeHDEVINFO hNew; + if (classGuid.HasValue) + hNew = SetupDiGetClassDevsEx(classGuid.Value, pnpFilter, default, flags, handle, MachineName); + else + hNew = SetupDiGetClassDevsEx(IntPtr.Zero, pnpFilter, default, flags, handle, MachineName); + Win32Error.ThrowLastErrorIfInvalid(hNew); + SetHandle(hNew.handle); + hNew.SetHandleAsInvalid(); + } + + /// + protected override bool InternalReleaseHandle() => SetupDiDestroyDeviceInfoList(handle); + + private SP_DEVINFO_LIST_DETAIL_DATA GetDetail() + { + var data = StructHelper.InitWithSize(); + Win32Error.ThrowLastErrorIfFalse(SetupDiGetDeviceInfoListDetail(handle, ref data)); + return data; + } + } } } \ No newline at end of file diff --git a/PInvoke/SetupAPI/SetupAPI.DiFuncs2.cs b/PInvoke/SetupAPI/SetupAPI.DiFuncs2.cs index 0449bd01..04d8bf6e 100644 --- a/PInvoke/SetupAPI/SetupAPI.DiFuncs2.cs +++ b/PInvoke/SetupAPI/SetupAPI.DiFuncs2.cs @@ -1484,49 +1484,6 @@ namespace Vanara.PInvoke return false; } - /// Converts memory retrieved from a property call to a managed object of the correct type. - /// The allocated memory. - /// The type of the property. - /// A managed object with the value from the memory. - public static object SetupDiPropertyToManagedObject(ISafeMemoryHandle mem, DEVPROPTYPE propType) - { - 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 = 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; - } - /// /// The SetupDiGetDevicePropertyKeys function retrieves an array of the device property keys that represent the device /// properties that are set for a device instance. @@ -3137,6 +3094,50 @@ namespace Vanara.PInvoke public static extern SafeRegistryHandle SetupDiOpenDevRegKey(HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, DICS_FLAG Scope, uint HwProfile, DIREG KeyType, RegistryRights samDesired); + /// Converts memory retrieved from a property call to a managed object of the correct type. + /// The allocated memory. + /// The type of the property. + /// The type to which to convert the result if ambiguous. + /// A managed object with the value from the memory. + 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; + } + /// The SetupDiRegisterCoDeviceInstallers function is the default handler for DIF_REGISTER_COINSTALLERS. /// /// A handle to the device information set that contains a device information element that represents the device for which to diff --git a/PInvoke/SetupAPI/SetupAPI.Funcs.cs b/PInvoke/SetupAPI/SetupAPI.Funcs.cs index 0eb9f0b9..4d6a8190 100644 --- a/PInvoke/SetupAPI/SetupAPI.Funcs.cs +++ b/PInvoke/SetupAPI/SetupAPI.Funcs.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; using System.Text; -using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke @@ -1174,72 +1171,6 @@ namespace Vanara.PInvoke [MarshalAs(UnmanagedType.LPTStr)] out string ActualSourceFileName, out uint SourceFileSize, out uint TargetFileSize, out FILE_COMPRESSION CompressionType); - /// Provides a for that is disposed using . - public class SafeHDSKSPC : SafeHANDLE - { - /// Initializes a new instance of the class and assigns an existing handle. - /// An object that represents the pre-existing handle to use. - /// - /// to reliably release the handle during the finalization phase; otherwise, (not recommended). - /// - public SafeHDSKSPC(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } - - /// Initializes a new instance of the class. - private SafeHDSKSPC() : base() { } - - /// Performs an implicit conversion from to . - /// The safe handle instance. - /// The result of the conversion. - public static implicit operator HDSKSPC(SafeHDSKSPC h) => h.handle; - - /// - protected override bool InternalReleaseHandle() => SetupDestroyDiskSpaceList(handle); - } - - /// Provides a for that is disposed using . - public class SafeHDEVINFO : SafeHANDLE - { - /// Initializes a new instance of the class and assigns an existing handle. - /// An object that represents the pre-existing handle to use. - /// - /// to reliably release the handle during the finalization phase; otherwise, (not recommended). - /// - public SafeHDEVINFO(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } - - /// Initializes a new instance of the class. - private SafeHDEVINFO() : base() { } - - /// Performs an implicit conversion from to . - /// The safe handle instance. - /// The result of the conversion. - public static implicit operator HDEVINFO(SafeHDEVINFO h) => h.handle; - - /// - protected override bool InternalReleaseHandle() => SetupDiDestroyDeviceInfoList(handle); - } - - /// Provides a for that is disposed using . - public class SafeHINF : SafeHANDLE - { - /// Initializes a new instance of the class and assigns an existing handle. - /// An object that represents the pre-existing handle to use. - /// - /// to reliably release the handle during the finalization phase; otherwise, (not recommended). - /// - public SafeHINF(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } - - /// Initializes a new instance of the class. - private SafeHINF() : base() { } - - /// Performs an implicit conversion from to . - /// The safe handle instance. - /// The result of the conversion. - public static implicit operator HINF(SafeHINF h) => h.handle; - - /// - protected override bool InternalReleaseHandle() { SetupCloseInfFile(handle); return true; } - } - /// /// /// [This function is available for use in the operating systems indicated in the Requirements section. It may be altered or @@ -1293,13 +1224,57 @@ namespace Vanara.PInvoke /// section in the INF file (for example, OptionType=NetAdapter). /// /// - // https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupopeninffilea - // WINSETUPAPI HINF SetupOpenInfFileA( PCSTR FileName, PCSTR InfClass, DWORD InfStyle, PUINT ErrorLine ); + // https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupopeninffilea WINSETUPAPI HINF SetupOpenInfFileA( + // PCSTR FileName, PCSTR InfClass, DWORD InfStyle, PUINT ErrorLine ); [DllImport(Lib_SetupAPI, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("setupapi.h", MSDNShortId = "NF:setupapi.SetupOpenInfFileA")] public static extern SafeHINF SetupOpenInfFile([MarshalAs(UnmanagedType.LPTStr)] string FileName, [Optional, MarshalAs(UnmanagedType.LPTStr)] string InfClass, INF_STYLE InfStyle, out uint ErrorLine); + /// Provides a for that is disposed using . + public class SafeHDSKSPC : SafeHANDLE + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHDSKSPC(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHDSKSPC() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HDSKSPC(SafeHDSKSPC h) => h.handle; + + /// + protected override bool InternalReleaseHandle() => SetupDestroyDiskSpaceList(handle); + } + + /// Provides a for that is disposed using . + public class SafeHINF : SafeHANDLE + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHINF(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHINF() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HINF(SafeHINF h) => h.handle; + + /// + protected override bool InternalReleaseHandle() { SetupCloseInfFile(handle); return true; } + } + /* SetupDeleteErrorA SetupDeleteErrorW diff --git a/PInvoke/SetupAPI/SetupAPI.cs b/PInvoke/SetupAPI/SetupAPI.cs index 6e2300a2..4bc72afe 100644 --- a/PInvoke/SetupAPI/SetupAPI.cs +++ b/PInvoke/SetupAPI/SetupAPI.cs @@ -196,6 +196,7 @@ namespace Vanara.PInvoke /// // https://docs.microsoft.com/en-us/previous-versions/ff543546(v=vs.85) [PInvokeData("Devpropdef.h")] + [Flags] public enum DEVPROPTYPE : uint { /// @@ -576,6 +577,7 @@ namespace Vanara.PInvoke /// function and set the function input parameters as follows: /// /// + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] DEVPROP_TYPE_STRING_LIST = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST, /// @@ -657,6 +659,7 @@ namespace Vanara.PInvoke /// set the function input parameters as follows: /// /// + [CorrespondingType(typeof(byte[]))] DEVPROP_TYPE_BINARY = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY, /// @@ -779,6 +782,7 @@ namespace Vanara.PInvoke /// /// Note: PE images can use either resource table type (STRINGTABLE resources, or message-table resources). /// + [CorrespondingType(typeof(string))] DEVPROP_TYPE_STRING_INDIRECT = 0x00000019, /// @@ -1834,18 +1838,23 @@ namespace Vanara.PInvoke /// (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. /// + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPCRP_UPPERFILTERS = 0x00000011, /// /// (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. /// + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPCRP_LOWERFILTERS = 0x00000012, /// /// The function returns the device's security descriptor as a SECURITY_DESCRIPTOR structure in self-relative format (described /// in the Microsoft Windows SDK documentation). /// + [CorrespondingType(typeof(byte[]))] SPCRP_SECURITY = 0x00000017, /// @@ -1853,24 +1862,28 @@ namespace Vanara.PInvoke /// see Security Descriptor Definition Language (Windows). For information about the format of security descriptor strings, see /// Security Descriptor Definition Language (Windows). /// + [CorrespondingType(typeof(string))] SPCRP_SECURITY_SDS = 0x00000018, /// /// The function returns a DWORD value that represents the device type for the class. For more information, see Specifying /// Device Types. /// + [CorrespondingType(typeof(FILE_DEVICE))] SPCRP_DEVTYPE = 0x00000019, /// /// 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. /// + [CorrespondingType(typeof(BOOL))] SPCRP_EXCLUSIVE = 0x0000001A, /// /// The function returns flags indicating device characteristics for the class. For a list of characteristics flags, see the /// DeviceCharacteristics parameter to IoCreateDevice. /// + [CorrespondingType(typeof(uint))] SPCRP_CHARACTERISTICS = 0x0000001B, } @@ -1893,12 +1906,15 @@ namespace Vanara.PInvoke public enum SPDRP { /// The function retrieves the device's address. + [CorrespondingType(typeof(uint))] SPDRP_ADDRESS = 0x0000001C, /// The function retrieves the device's bus number. + [CorrespondingType(typeof(uint))] SPDRP_BUSNUMBER = 0x00000015, /// The function retrieves the GUID for the device's bus type. + [CorrespondingType(typeof(Guid))] SPDRP_BUSTYPEGUID = 0x00000013, /// @@ -1952,67 +1968,83 @@ namespace Vanara.PInvoke /// /// /// + [CorrespondingType(typeof(CM_DEVCAP))] SPDRP_CAPABILITIES = 0x0000000F, /// /// 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. /// + [CorrespondingType(typeof(uint))] SPDRP_CHARACTERISTICS = 0x0000001B, /// The function retrieves a REG_SZ string that contains the device setup class of a device. + [CorrespondingType(typeof(string))] SPDRP_CLASS = 0x00000007, /// The function retrieves a REG_SZ string that contains the GUID that represents the device setup class of a device. + [CorrespondingType(typeof(string))] SPDRP_CLASSGUID = 0x00000008, /// /// 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. /// + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPDRP_COMPATIBLEIDS = 0x00000002, /// /// 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. /// + [CorrespondingType(typeof(CONFIGFLAG))] SPDRP_CONFIGFLAGS = 0x0000000A, /// /// (Windows XP and later) The function retrieves a CM_POWER_DATA structure that contains the device's power management information. /// + [CorrespondingType(typeof(CM_POWER_DATA))] SPDRP_DEVICE_POWER_DATA = 0x0000001E, /// The function retrieves a REG_SZ string that contains the description of a device. + [CorrespondingType(typeof(string))] SPDRP_DEVICEDESC = 0x00000000, /// /// The function retrieves a DWORD value that represents the device's type. For more information, see Specifying Device Types. /// + [CorrespondingType(typeof(FILE_DEVICE))] SPDRP_DEVTYPE = 0x00000019, /// /// 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. /// + [CorrespondingType(typeof(string))] SPDRP_DRIVER = 0x00000009, /// The function retrieves a REG_SZ string that contains the name of the device's enumerator. + [CorrespondingType(typeof(string))] SPDRP_ENUMERATOR_NAME = 0x00000016, /// /// 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. /// + [CorrespondingType(typeof(BOOL))] SPDRP_EXCLUSIVE = 0x0000001A, /// The function retrieves a REG_SZ string that contains the friendly name of a device. + [CorrespondingType(typeof(string))] SPDRP_FRIENDLYNAME = 0x0000000C, /// /// 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. /// + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPDRP_HARDWAREID = 0x00000001, /// @@ -2020,51 +2052,64 @@ namespace Vanara.PInvoke /// 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. /// + [CorrespondingType(typeof(CM_INSTALL_STATE))] SPDRP_INSTALL_STATE = 0x00000022, /// The function retrieves the device's legacy bus type as an INTERFACE_TYPE value (defined in Wdm.h and Ntddk.h). + [CorrespondingType(typeof(INTERFACE_TYPE))] SPDRP_LEGACYBUSTYPE = 0x00000014, /// The function retrieves a REG_SZ string that contains the hardware location of a device. + [CorrespondingType(typeof(string))] SPDRP_LOCATION_INFORMATION = 0x0000000D, /// /// (Windows Server 2003 and later) The function retrieves a REG_MULTI_SZ string that represents the location of the device in /// the device tree. /// + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPDRP_LOCATION_PATHS = 0x00000023, /// The function retrieves a REG_MULTI_SZ string that contains the names of a device's lower-filter drivers. + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPDRP_LOWERFILTERS = 0x00000012, /// The function retrieves a REG_SZ string that contains the name of the device manufacturer. + [CorrespondingType(typeof(string))] SPDRP_MFG = 0x0000000B, /// /// The function retrieves a REG_SZ string that contains the name that is associated with the device's PDO. For more /// information, see IoCreateDevice. /// + [CorrespondingType(typeof(string))] SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E, /// /// (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. /// + [CorrespondingType(typeof(CM_REMOVAL_POLICY))] SPDRP_REMOVAL_POLICY = 0x0000001F, /// /// (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. /// + [CorrespondingType(typeof(CM_REMOVAL_POLICY))] SPDRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000020, /// /// (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. /// + [CorrespondingType(typeof(CM_REMOVAL_POLICY))] SPDRP_REMOVAL_POLICY_OVERRIDE = 0x00000021, /// The function retrieves a SECURITY_DESCRIPTOR structure for a device. + [CorrespondingType(typeof(byte[]))] SPDRP_SECURITY = 0x00000017, /// @@ -2072,23 +2117,30 @@ namespace Vanara.PInvoke /// descriptor strings, see Security Descriptor Definition Language (Windows). For information about the format of security /// descriptor strings, see Security Descriptor Definition Language (Windows). /// + [CorrespondingType(typeof(string))] SPDRP_SECURITY_SDS = 0x00000018, /// The function retrieves a REG_SZ string that contains the service name for a device. + [CorrespondingType(typeof(string))] SPDRP_SERVICE = 0x00000004, /// /// The function retrieves a DWORD value set to the value of the UINumber member of the device's DEVICE_CAPABILITIES structure. /// + [CorrespondingType(typeof(uint))] SPDRP_UI_NUMBER = 0x00000010, /// The function retrieves a format string (REG_SZ) used to display the UINumber value. + [CorrespondingType(typeof(string))] SPDRP_UI_NUMBER_DESC_FORMAT = 0x0000001D, /// The function retrieves a REG_MULTI_SZ string that contains the names of a device's upper filter drivers. + [CorrespondingType(typeof(System.Collections.Generic.IEnumerable))] + [CorrespondingType(typeof(string[]))] SPDRP_UPPERFILTERS = 0x00000011, /// Base ContainerID (R) + [CorrespondingType(typeof(Guid))] SPDRP_BASE_CONTAINERID = 0x00000024, } @@ -3236,7 +3288,11 @@ namespace Vanara.PInvoke // _SP_DEVINFO_LIST_DETAIL_DATA_W { DWORD cbSize; GUID ClassGuid; HANDLE RemoteMachineHandle; WCHAR // RemoteMachineName[SP_MAX_MACHINENAME_LENGTH]; } SP_DEVINFO_LIST_DETAIL_DATA_W, *PSP_DEVINFO_LIST_DETAIL_DATA_W; [PInvokeData("setupapi.h", MSDNShortId = "NS:setupapi._SP_DEVINFO_LIST_DETAIL_DATA_W")] - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] +#if x64 + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 8)] +#else + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] +#endif public struct SP_DEVINFO_LIST_DETAIL_DATA { /// The size, in bytes, of the SP_DEVINFO_LIST_DETAIL_DATA structure. @@ -3276,7 +3332,11 @@ namespace Vanara.PInvoke // InstallMsgHandlerContext; HSPFILEQ FileQueue; ULONG_PTR ClassInstallReserved; DWORD Reserved; CHAR DriverPath[MAX_PATH]; } // SP_DEVINSTALL_PARAMS_A, *PSP_DEVINSTALL_PARAMS_A; [PInvokeData("setupapi.h", MSDNShortId = "NS:setupapi._SP_DEVINSTALL_PARAMS_A")] - [StructLayout(LayoutKind.Sequential)] +#if x64 + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 8)] +#else + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] +#endif public struct SP_DEVINSTALL_PARAMS { /// The size, in bytes, of the SP_DEVINSTALL_PARAMS structure. @@ -3572,7 +3632,7 @@ namespace Vanara.PInvoke public HSPFILEQ FileQueue; /// A pointer for class-installer data. Co-installers must not use this field. - public UIntPtr ClassInstallReserved; + public IntPtr ClassInstallReserved; /// Reserved. For internal use only. public uint Reserved;