diff --git a/PInvoke/CfgMgr32/CfgMgr32.Structs.cs b/PInvoke/CfgMgr32/CfgMgr32.Structs.cs
index 3aea421a..95063d45 100644
--- a/PInvoke/CfgMgr32/CfgMgr32.Structs.cs
+++ b/PInvoke/CfgMgr32/CfgMgr32.Structs.cs
@@ -2,6 +2,7 @@ using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
using System.Text;
+using Vanara.Extensions;
using Vanara.InteropServices;
using static Vanara.PInvoke.AdvApi32;
using static Vanara.PInvoke.SetupAPI;
@@ -359,6 +360,14 @@ namespace Vanara.PInvoke
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct CONFLICT_DETAILS
{
+ /// Initializes a new instance of the struct with the size and mask set.
+ /// The mask of items to retrieve.
+ public CONFLICT_DETAILS(CM_CDMASK mask) : this()
+ {
+ CD_ulSize = (uint)Marshal.SizeOf(typeof(CONFLICT_DETAILS));
+ CD_ulMask = mask;
+ }
+
/// Size, in bytes, of the CONFLICT_DETAILS structure.
public uint CD_ulSize;
@@ -434,9 +443,6 @@ namespace Vanara.PInvoke
///
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260 /*MAX_PATH*/)]
public string CD_szDescription;
-
- /// Gets a default value for the structure with the size field set.
- public static readonly CONFLICT_DETAILS Default = new() { CD_ulSize = (uint)Marshal.SizeOf(typeof(CONFLICT_DETAILS)) };
}
///
diff --git a/PInvoke/CfgMgr32/CfgMgr32.cs b/PInvoke/CfgMgr32/CfgMgr32.cs
index c1144893..74b25c18 100644
--- a/PInvoke/CfgMgr32/CfgMgr32.cs
+++ b/PInvoke/CfgMgr32/CfgMgr32.cs
@@ -1743,6 +1743,55 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Free_Res_Des")]
public static extern CONFIGRET CM_Free_Res_Des(out SafeRES_DES prdResDes, RES_DES rdResDes, uint ulFlags = 0);
+ /// The CM_Free_Res_Des function removes a resource descriptor from a logical configuration on the local machine.
+ ///
+ /// Caller-supplied location to receive a handle to the configuration's previous resource descriptor. This parameter can be
+ /// NULL. For more information, see the following Remarks section.
+ ///
+ ///
+ ///
+ /// Caller-supplied handle to the resource descriptor to be removed. This handle must have been previously obtained by calling one
+ /// of the following functions:
+ ///
+ /// CM_Add_Res_Des
+ /// CM_Add_Res_Des_Ex
+ /// CM_Get_Next_Res_Des
+ /// CM_Get_Next_Res_Des_Ex
+ /// CM_Modify_Res_Des
+ /// CM_Modify_Res_Des_Ex
+ ///
+ /// Not used, must be zero.
+ ///
+ ///
+ /// If the operation succeeds, the function returns CR_SUCCESS. Otherwise, it returns one of the CR_-prefixed error codes defined in Cfgmgr32.h.
+ ///
+ ///
+ /// Note Starting with Windows 8, CM_Free_Res_Des returns CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario. To
+ /// request information about the hardware resources on a local machine it is necessary implement an architecture-native version of
+ /// the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ ///
+ ///
+ /// Resource descriptors for each configuration are stored in an array. If you specify an address for prdResDes, then
+ /// CM_Free_Res_Des returns a handle to the resource descriptor that was previous, in the array, to the one removed. If the
+ /// handle specified by rdResDes represents the resource descriptor located first in the array, then prdResDes receives a handle to
+ /// the logical configuration.
+ ///
+ ///
+ /// Note that calling CM_Free_Res_Des frees the resource descriptor, but not the descriptor's handle. To free the handle,
+ /// call CM_Free_Res_Des_Handle.
+ ///
+ ///
+ /// Callers of this function must have SeLoadDriverPrivilege. (Privileges are described in the Microsoft Windows SDK documentation.)
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_free_res_des CMAPI CONFIGRET CM_Free_Res_Des( PRES_DES
+ // prdResDes, RES_DES rdResDes, ULONG ulFlags );
+ [DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Free_Res_Des")]
+ public static extern CONFIGRET CM_Free_Res_Des([In, Optional] IntPtr prdResDes, RES_DES rdResDes, uint ulFlags = 0);
+
///
/// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Free_Res_Des instead.]
///
@@ -1808,6 +1857,71 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Free_Res_Des_Ex")]
public static extern CONFIGRET CM_Free_Res_Des_Ex(out SafeRES_DES prdResDes, RES_DES rdResDes, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+ ///
+ /// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Free_Res_Des instead.]
+ ///
+ /// The CM_Free_Res_Des_Ex function removes a resource descriptor from a logical configuration on either a local or a remote machine.
+ ///
+ ///
+ ///
+ /// Caller-supplied location to receive a handle to the configuration's previous resource descriptor. This parameter can be
+ /// NULL. For more information, see the following Remarks section.
+ ///
+ ///
+ ///
+ /// Caller-supplied handle to the resource descriptor to be removed. This handle must have been previously obtained by calling one
+ /// of the following functions:
+ ///
+ /// CM_Add_Res_Des
+ /// CM_Add_Res_Des_Ex
+ /// CM_Get_Next_Res_Des
+ /// CM_Get_Next_Res_Des_Ex
+ /// CM_Modify_Res_Des
+ /// CM_Modify_Res_Des_Ex
+ ///
+ /// Not used, must be zero.
+ ///
+ /// Caller-supplied machine handle, obtained from a previous call to CM_Connect_Machine.
+ ///
+ /// Note Using this function to access remote machines is not supported beginning with Windows 8 and Windows Server 2012, as
+ /// this functionality has been removed.
+ ///
+ ///
+ ///
+ ///
+ /// If the operation succeeds, the function returns CR_SUCCESS. Otherwise, it returns one of the CR_-prefixed error codes defined in Cfgmgr32.h.
+ ///
+ ///
+ /// Note Starting with Windows 8, CM_Free_Res_Des_Ex returns CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario. To
+ /// request information about the hardware resources on a local machine it is necessary implement an architecture-native version of
+ /// the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ ///
+ ///
+ /// Resource descriptors for each configuration are stored in an array. If you specify an address for prdResDes, then
+ /// CM_Free_Res_Des returns a handle to the resource descriptor that was previous, in the array, to the one removed. If the
+ /// handle specified by rdResDes represents the resource descriptor located first in the array, then prdResDes receives a handle to
+ /// the logical configuration.
+ ///
+ ///
+ /// Note that calling CM_Free_Res_Des_Ex frees the resource descriptor, but not the descriptor's handle. To free the handle,
+ /// call CM_Free_Res_Des_Handle_Ex.
+ ///
+ ///
+ /// Callers of this function must have SeLoadDriverPrivilege. (Privileges are described in the Microsoft Windows SDK documentation.)
+ ///
+ ///
+ /// Functionality to access remote machines has been removed in Windows 8 and Windows Server 2012 and later operating systems thus
+ /// you cannot access remote machines when running on these versions of Windows.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_free_res_des_ex CMAPI CONFIGRET CM_Free_Res_Des_Ex(
+ // PRES_DES prdResDes, RES_DES rdResDes, ULONG ulFlags, HMACHINE hMachine );
+ [DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Free_Res_Des_Ex")]
+ public static extern CONFIGRET CM_Free_Res_Des_Ex([In, Optional] IntPtr prdResDes, RES_DES rdResDes, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+
///
/// The CM_Free_Res_Des_Handle function invalidates a resource description handle and frees its associated memory allocation.
///
@@ -2289,7 +2403,7 @@ namespace Vanara.PInvoke
// ulFlags, HMACHINE hMachine );
[DllImport(Lib_Cfgmgr32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Class_Registry_PropertyW")]
- public static extern CONFIGRET CM_Get_Class_Registry_Property(in Guid ClassGuid, CM_DRP ulProperty, out REG_VALUE_TYPE pulRegDataType, [Out, Optional] IntPtr Buffer,
+ public static extern CONFIGRET CM_Get_Class_Registry_Property(in Guid ClassGuid, CM_CRP ulProperty, out REG_VALUE_TYPE pulRegDataType, [Out, Optional] IntPtr Buffer,
ref uint pulLength, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
///
diff --git a/PInvoke/CfgMgr32/CfgMgr32_2.cs b/PInvoke/CfgMgr32/CfgMgr32_2.cs
index 89015139..5e13b6cc 100644
--- a/PInvoke/CfgMgr32/CfgMgr32_2.cs
+++ b/PInvoke/CfgMgr32/CfgMgr32_2.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections;
+using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
@@ -356,7 +358,9 @@ namespace Vanara.PInvoke
CM_PROB_GUEST_ASSIGNMENT_FAILED = 0x00000039,
}
- /// configuration flags
+ /// Configuration flags
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_HW_Prof_FlagsA")]
+ [Flags]
public enum CSCONFIGFLAG
{
/// The device instance is disabled in the specified hardware profile.
@@ -367,9 +371,6 @@ namespace Vanara.PInvoke
/// The device cannot be started in the specified hardware profile.
CSCONFIGFLAG_DO_NOT_START = 4,
-
- /// Bitwise OR of the other CSCONFIGFLAG_Xxx flags.
- CSCONFIGFLAG_BITS = 7,
}
///
@@ -1575,6 +1576,68 @@ namespace Vanara.PInvoke
public static extern CONFIGRET CM_Get_HW_Prof_Flags_Ex([MarshalAs(UnmanagedType.LPTStr)] string pDeviceID, uint ulHardwareProfile, out CSCONFIGFLAG pulValue,
[In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+ ///
+ /// The CM_Get_Log_Conf_List function obtains the logical configurations, of a specified configuration type, associated with
+ /// a specified device instance on the local machine.
+ ///
+ /// Caller-supplied device instance handle that is bound to the local machine.
+ ///
+ ///
+ /// Caller-supplied flag value indicating the type of logical configuration being requested. One of the flags in the following table
+ /// must be specified.
+ ///
+ ///
+ ///
+ /// Configuration Type Flags
+ /// Definitions
+ ///
+ ///
+ /// BASIC_LOG_CONF
+ /// The caller is requesting basic configuration information.
+ ///
+ ///
+ /// FILTERED_LOG_CONF
+ /// The caller is requesting filtered configuration information.
+ ///
+ ///
+ /// ALLOC_LOG_CONF
+ /// The caller is requesting allocated configuration information.
+ ///
+ ///
+ /// BOOT_LOG_CONF
+ /// The caller is requesting boot configuration information.
+ ///
+ ///
+ /// FORCED_LOG_CONF
+ /// The caller is requesting forced configuration information.
+ ///
+ ///
+ /// OVERRIDE_LOG_CONF
+ /// The caller is requesting override configuration information.
+ ///
+ ///
+ ///
+ ///
+ /// A sequence of safe handles to a logical configurations.
+ ///
+ /// Note Starting with Windows 8, CM_Get_First_Log_Conf returns CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
+ /// To request information about the hardware resources on a local machine it is necessary implement an architecture-native version
+ /// of the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_First_Log_Conf")]
+ public static IEnumerable CM_Get_Log_Conf_List(uint dnDevInst, LOG_CONF_FLAG ulFlags)
+ {
+ CONFIGRET ret = CM_Get_First_Log_Conf(out var lc, dnDevInst, ulFlags);
+ if (ret == CONFIGRET.CR_NO_MORE_LOG_CONF)
+ yield break;
+ ret.ThrowIfFailed();
+ yield return lc;
+ while ((ret = CM_Get_Next_Log_Conf(out lc, lc)) == CONFIGRET.CR_SUCCESS)
+ yield return lc;
+ if (ret != CONFIGRET.CR_NO_MORE_LOG_CONF) ret.ThrowIfFailed();
+ }
+
///
/// The CM_Get_Log_Conf_Priority function obtains the configuration priority of a specified logical configuration on the
/// local machine.
@@ -1937,6 +2000,54 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Next_Res_Des")]
public static extern CONFIGRET CM_Get_Next_Res_Des(out SafeRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ForResource, out RESOURCEID pResourceID, uint ulFlags = 0);
+ ///
+ /// The CM_Get_Next_Res_Des function obtains a handle to the next resource descriptor, of a specified resource type, for a
+ /// logical configuration on the local machine.
+ ///
+ /// Pointer to a location to receive a resource descriptor handle.
+ ///
+ /// Caller-supplied handle to either a resource descriptor or a logical configuration. For more information, see the following
+ /// Remarks section.
+ ///
+ ///
+ /// Caller-supplied resource type identifier, indicating the type of resource descriptor being requested. This must be one of the
+ /// ResType_-prefixed constants defined in Cfgmgr32.h.
+ ///
+ ///
+ /// Pointer to a location to receive a resource type identifier, if ForResource specifies ResType_All. For any other
+ /// ForResource value, callers should set this to NULL.
+ ///
+ /// Not used, must be zero.
+ ///
+ ///
+ /// If the operation succeeds, the function returns CR_SUCCESS. Otherwise, it returns one of the CR_-prefixed error codes defined in Cfgmgr32.h.
+ ///
+ ///
+ /// Note Starting with Windows 8, CM_Get_Next_Res_Des returns CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
+ /// To request information about the hardware resources on a local machine it is necessary implement an architecture-native version
+ /// of the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ ///
+ ///
+ /// To enumerate a logical configuration's resource descriptors, begin by calling CM_Get_Next_Res_Des with the logical
+ /// configuration's handle as the argument for rdResDes. This obtains a handle to the first resource descriptor of the type
+ /// specified by ForResource. Then for each subsequent call to CM_Get_Next_Res_Des, specify the most recently obtained
+ /// descriptor handle as the argument for rdResDes. Repeat until the function returns CR_NO_MORE_RES_DES.
+ ///
+ /// To retrieve the information stored in a resource descriptor, call CM_Get_Res_Des_Data.
+ /// To modify the information stored in a resource descriptor, call CM_Modify_Res_Des.
+ ///
+ /// Callers of CM_Get_Next_Res_Des must call CM_Free_Res_Des_Handle to deallocate the resource descriptor handle, after it is
+ /// no longer needed.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_get_next_res_des CMAPI CONFIGRET CM_Get_Next_Res_Des(
+ // PRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ForResource, PRESOURCEID pResourceID, ULONG ulFlags );
+ [DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Next_Res_Des")]
+ public static extern CONFIGRET CM_Get_Next_Res_Des(out SafeRES_DES prdResDes, LOG_CONF rdResDes, RESOURCEID ForResource, out RESOURCEID pResourceID, uint ulFlags = 0);
+
///
/// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Get_Next_Res_Des instead.]
///
@@ -2000,6 +2111,69 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Next_Res_Des_Ex")]
public static extern CONFIGRET CM_Get_Next_Res_Des_Ex(out SafeRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ForResource, out RESOURCEID pResourceID, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+ ///
+ /// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Get_Next_Res_Des instead.]
+ ///
+ /// The CM_Get_Next_Res_Des_Ex function obtains a handle to the next resource descriptor, of a specified resource type, for a
+ /// logical configuration on a local or a remote machine.
+ ///
+ ///
+ /// Pointer to a location to receive a resource descriptor handle.
+ ///
+ /// Caller-supplied handle to either a resource descriptor or a logical configuration. For more information, see the following
+ /// Remarks section.
+ ///
+ ///
+ /// Caller-supplied resource type identifier, indicating the type of resource descriptor being requested. This must be one of the
+ /// ResType_-prefixed constants defined in Cfgmgr32.h.
+ ///
+ ///
+ /// Pointer to a location to receive a resource type identifier, if ForResource specifies ResType_All. For any other
+ /// ForResource value, callers should set this to NULL.
+ ///
+ /// Not used, must be zero.
+ ///
+ /// Caller-supplied machine handle, obtained from a previous call to CM_Connect_Machine.
+ ///
+ /// Note Using this function to access remote machines is not supported beginning with Windows 8 and Windows Server 2012, as
+ /// this functionality has been removed.
+ ///
+ ///
+ ///
+ ///
+ /// If the operation succeeds, the function returns CR_SUCCESS. Otherwise, it returns one of the CR_-prefixed error codes defined in Cfgmgr32.h.
+ ///
+ ///
+ /// Note Starting with Windows 8, CM_Get_Next_Res_Des_Ex returns CR_CALL_NOT_IMPLEMENTED when used in a Wow64
+ /// scenario. To request information about the hardware resources on a local machine it is necessary implement an
+ /// architecture-native version of the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ ///
+ ///
+ /// To enumerate a logical configuration's resource descriptors, begin by calling CM_Get_Next_Res_Des_Ex with the logical
+ /// configuration's handle as the argument for rdResDes. This obtains a handle to the first resource descriptor of the type
+ /// specified by ForResource. Then for each subsequent call to CM_Get_Next_Res_Des_Ex, specify the most recently obtained
+ /// descriptor handle as the argument for rdResDes. Repeat until the function returns CR_NO_MORE_RES_DES.
+ ///
+ /// To retrieve the information stored in a resource descriptor, call CM_Get_Res_Des_Data_Ex.
+ /// To modify the information stored in a resource descriptor, call CM_Modify_Res_Des_Ex.
+ ///
+ /// Callers of CM_Get_Next_Res_Des_Ex must call CM_Free_Res_Des_Handle to deallocate the resource descriptor handle, after it
+ /// is no longer needed.
+ ///
+ ///
+ /// Functionality to access remote machines has been removed in Windows 8 and Windows Server 2012 and later operating systems thus
+ /// you cannot access remote machines when running on these versions of Windows.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_get_next_res_des_ex CMAPI CONFIGRET
+ // CM_Get_Next_Res_Des_Ex( PRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ForResource, PRESOURCEID pResourceID, ULONG ulFlags,
+ // HMACHINE hMachine );
+ [DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Next_Res_Des_Ex")]
+ public static extern CONFIGRET CM_Get_Next_Res_Des_Ex(out SafeRES_DES prdResDes, LOG_CONF rdResDes, RESOURCEID ForResource, out RESOURCEID pResourceID, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+
///
/// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Get_Parent instead.]
///
@@ -2064,6 +2238,30 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Res_Des_Data")]
public static extern CONFIGRET CM_Get_Res_Des_Data(RES_DES rdResDes, [Out] IntPtr Buffer, uint BufferLen, uint ulFlags = 0);
+ ///
+ /// The CM_Get_Res_Des_Data function retrieves the information stored in a resource descriptor on the local machine.
+ ///
+ /// The type of the data to retrieve.
+ /// Caller-supplied handle to a resource descriptor, obtained by a previous call to CM_Get_Next_Res_Des.
+ ///
+ ///
+ /// Returns the structure specified in as the contents of the resource descriptor.
+ ///
+ ///
+ /// Note Starting with Windows 8, CM_Get_Res_Des_Data throws CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
+ /// To request information about the hardware resources on a local machine it is necessary implement an architecture-native version
+ /// of the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Res_Des_Data")]
+ public static T CM_Get_Res_Des_Data(RES_DES rdResDes) where T : struct
+ {
+ CM_Get_Res_Des_Data_Size(out var size, rdResDes).ThrowIfFailed();
+ using var mem = new SafeCoTaskMemHandle(size);
+ CM_Get_Res_Des_Data(rdResDes, mem, size).ThrowIfFailed();
+ return mem.ToStructure();
+ }
+
///
/// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Get_Res_Des_Data instead.]
///
@@ -2184,6 +2382,38 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Res_Des_Data_Size_Ex")]
public static extern CONFIGRET CM_Get_Res_Des_Data_Size_Ex(out uint pulSize, RES_DES rdResDes, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+ ///
+ /// The CM_Get_Next_Res_Des function obtains a handle to the next resource descriptor, of a specified resource type, for a
+ /// logical configuration on the local machine.
+ ///
+ /// Handle to a logical configuration.
+ ///
+ /// Caller-supplied resource type identifier, indicating the type of resource descriptor being requested. This must be one of the
+ /// ResType_-prefixed constants defined in Cfgmgr32.h.
+ ///
+ /// A sequence of resource descriptor handles and their associated resource type identifiers.
+ ///
+ ///
+ /// Note Starting with Windows 8, CM_Get_Next_Res_Des returns CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
+ /// To request information about the hardware resources on a local machine it is necessary implement an architecture-native version
+ /// of the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ /// To retrieve the information stored in a resource descriptor, call CM_Get_Res_Des_Data.
+ /// To modify the information stored in a resource descriptor, call CM_Modify_Res_Des.
+ ///
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Get_Next_Res_Des")]
+ public static IEnumerable<(SafeRES_DES prdResDes, RESOURCEID pResourceID)> CM_Get_Res_Des_List([In] LOG_CONF lcLogConf, RESOURCEID ForResource = RESOURCEID.ResType_All)
+ {
+ CONFIGRET ret = CM_Get_Next_Res_Des(out var rd, lcLogConf, ForResource, out var resId);
+ if (ret == CONFIGRET.CR_NO_MORE_RES_DES)
+ yield break;
+ ret.ThrowIfFailed();
+ yield return (rd, resId);
+ while ((ret = CM_Get_Next_Res_Des(out rd, rd, ForResource, out resId)) == CONFIGRET.CR_SUCCESS)
+ yield return (rd, resId);
+ if (ret != CONFIGRET.CR_NO_MORE_RES_DES) ret.ThrowIfFailed();
+ }
+
///
/// The CM_Get_Resource_Conflict_Count function obtains the number of conflicts contained in a specified resource conflict list.
///
diff --git a/PInvoke/CfgMgr32/CfgMgr32_3.cs b/PInvoke/CfgMgr32/CfgMgr32_3.cs
index 74532417..5d71ef13 100644
--- a/PInvoke/CfgMgr32/CfgMgr32_3.cs
+++ b/PInvoke/CfgMgr32/CfgMgr32_3.cs
@@ -2,6 +2,7 @@ using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
using System.Text;
+using Vanara.InteropServices;
using static Vanara.PInvoke.AdvApi32;
using static Vanara.PInvoke.SetupAPI;
@@ -1103,6 +1104,58 @@ namespace Vanara.PInvoke
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Modify_Res_Des")]
public static extern CONFIGRET CM_Modify_Res_Des(out SafeRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ResourceID, [In] IntPtr ResourceData, uint ResourceLen, uint ulFlags = 0);
+ /// The CM_Modify_Res_Des function modifies a specified resource descriptor on the local machine.
+ /// The type of the data.
+ ///
+ ///
+ /// Caller-supplied handle to the resource descriptor to be modified. This handle must have been previously obtained by calling one
+ /// of the following functions:
+ ///
+ /// CM_Add_Res_Des
+ /// CM_Add_Res_Des_Ex
+ /// CM_Get_Next_Res_Des
+ /// CM_Get_Next_Res_Des_Ex
+ /// CM_Modify_Res_Des
+ /// CM_Modify_Res_Des_Ex
+ ///
+ ///
+ /// Caller-supplied pointer to a resource descriptor, which can be one of the structures listed under the CM_Add_Res_Des function's
+ /// description of ResourceData.
+ ///
+ ///
+ /// Caller-supplied resource type identifier. This must be one of the ResType_-prefixed constants defined in Cfgmgr32.h.
+ ///
+ ///
+ /// A handle to the modified resource descriptor.
+ ///
+ /// Note Starting with Windows 8, CM_Modify_Res_Des throws CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario. To
+ /// request information about the hardware resources on a local machine it is necessary implement an architecture-native version of
+ /// the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ /// Unable to determine RESOURCEID from type. - T
+ ///
+ ///
+ /// The caller-supplied resource descriptor data replaces the existing data. The values specified for ResourceID and ResourceLen do
+ /// not have to match the existing resource descriptor.
+ ///
+ ///
+ /// If the value specified for ResourceID is ResType_ClassSpecific, then the specified resource descriptor must be the last
+ /// one associated with the logical configuration.
+ ///
+ ///
+ /// Callers of this function must have SeLoadDriverPrivilege. (Privileges are described in the Microsoft Windows SDK documentation.)
+ ///
+ ///
+ public static SafeRES_DES CM_Modify_Res_Des(RES_DES rdResDes, T data, RESOURCEID ResourceID = 0) where T : struct
+ {
+ if (ResourceID == 0 && !CorrespondingTypeAttribute.CanSet(out ResourceID))
+ throw new ArgumentException("Unable to determine RESOURCEID from type.", nameof(T));
+ using var mem = new SafeAnysizeStruct(data);
+ CM_Modify_Res_Des(out var hRD, rdResDes, ResourceID, mem, mem.Size).ThrowIfFailed();
+ return hRD;
+ }
+
///
/// [Beginning with Windows 8 and Windows Server 2012, this function has been deprecated. Please use CM_Modify_Res_Des instead.]
/// The CM_Modify_Res_Des_Ex function modifies a specified resource descriptor on a local or a remote machine.
@@ -1684,8 +1737,53 @@ namespace Vanara.PInvoke
// ULONG ResourceLen, ULONG ulFlags, HMACHINE hMachine );
[DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Query_Resource_Conflict_List")]
- public static extern CONFIGRET CM_Query_Resource_Conflict_List(out SafeCONFLICT_LIST pclConflictList, uint dnDevInst, RESOURCEID ResourceID, IntPtr ResourceData,
- uint ResourceLen, uint ulFlags, [In, Optional] HMACHINE hMachine);
+ public static extern CONFIGRET CM_Query_Resource_Conflict_List(out SafeCONFLICT_LIST pclConflictList, uint dnDevInst, RESOURCEID ResourceID, [In] IntPtr ResourceData,
+ uint ResourceLen, [In, Optional] uint ulFlags, [In, Optional] HMACHINE hMachine);
+
+ ///
+ /// The CM_Query_Resource_Conflict_List function identifies device instances having resource requirements that conflict with
+ /// a specified device instance's resource description.
+ ///
+ /// The type of the supplied data.
+ /// Caller-supplied device instance handle that is bound to the machine handle supplied by hMachine.
+ ///
+ /// Caller-supplied pointer to a resource descriptor, which can be one of the structures listed under the CM_Add_Res_Des function's
+ /// description of ResourceData.
+ ///
+ ///
+ /// Caller-supplied resource type identifier. If 0, then the is determined by .
+ ///
+ ///
+ /// A handle to a conflict list.
+ ///
+ /// Note Starting with Windows 8, CM_Query_Resource_Conflict_List throws CR_CALL_NOT_IMPLEMENTED when used in a Wow64
+ /// scenario. To request information about the hardware resources on a local machine it is necessary implement an
+ /// architecture-native version of the application using the hardware resource APIs. For example: An AMD64 application for AMD64 systems.
+ ///
+ ///
+ ///
+ ///
+ /// When calling CM_Query_Resource_Conflict_List, specify a device instance handle and resource descriptor. (Resource
+ /// descriptors for existing device nodes can be obtained by calling CM_Get_Res_Des_Data.) These parameters indicate the specific
+ /// resources you'd like a specific device to use. The resulting conflict list identifies devices that use the same resources, along
+ /// with resources reserved by the machine.
+ ///
+ ///
+ /// After calling CM_Query_Resource_Conflict_List, an application can call CM_Get_Resource_Conflict_Count to determine the
+ /// number of conflicts contained in the resource conflict list. (The number of conflicts can be zero.) Then the application can
+ /// call CM_Get_Resource_Conflict_Details for each entry in the conflict list.
+ ///
+ /// For information about using device instance handles that are bound to a local or a remote machine, see CM_Get_Child_Ex.
+ ///
+ [PInvokeData("cfgmgr32.h", MSDNShortId = "NF:cfgmgr32.CM_Query_Resource_Conflict_List")]
+ public static SafeCONFLICT_LIST CM_Query_Resource_Conflict_List(uint dnDevInst, T data, RESOURCEID ResourceID = 0) where T : struct
+ {
+ if (ResourceID == 0 && !CorrespondingTypeAttribute.CanSet(out ResourceID))
+ throw new ArgumentException("Unable to determine RESOURCEID from type.", nameof(T));
+ using var mem = new SafeAnysizeStruct(data);
+ CM_Query_Resource_Conflict_List(out var hcl, dnDevInst, ResourceID, mem, mem.Size).ThrowIfFailed();
+ return hcl;
+ }
///
/// The CM_Reenumerate_DevNode function enumerates the devices identified by a specified device node and all of its children.
diff --git a/PInvoke/CfgMgr32/SWDevice.cs b/PInvoke/CfgMgr32/SWDevice.cs
index 750f2901..ade8dfcb 100644
--- a/PInvoke/CfgMgr32/SWDevice.cs
+++ b/PInvoke/CfgMgr32/SWDevice.cs
@@ -522,6 +522,7 @@ namespace Vanara.PInvoke
/// BusQueryInstanceID. Because all software devices are considered "UniqueId" devices, this string must be a unique name
/// for all devices on this software device enumerator. For more info, see Instance IDs.
///
+ [MarshalAs(UnmanagedType.LPWStr)]
public string pszInstanceId;
///
@@ -529,8 +530,9 @@ namespace Vanara.PInvoke
/// BusQueryHardwareIDs. If a client expects a driver or device metadata to bind to the device, the client specifies
/// hardware IDs.
///
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler))]
- public string[] pszzHardwareIds;
+ //[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler))]
+ //public string[] pszzHardwareIds;
+ public IntPtr pszzHardwareIds;
///
/// A list of strings for the compatible IDs for the software device. This value is used for IRP_MN_QUERY_ID
@@ -539,8 +541,9 @@ namespace Vanara.PInvoke
/// addition to the compatible IDs specified in this member, SWD\Generic and possibly SWD\GenericRaw will always be added as the
/// least specific compatible IDs.
///
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler))]
- public string[] pszzCompatibleIds;
+ //[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler))]
+ //public string[] pszzCompatibleIds;
+ public IntPtr pszzCompatibleIds;
///
/// A value that is used to control the base container ID for the software device. This value will be used for IRP_MN_QUERY_ID
@@ -616,6 +619,7 @@ namespace Vanara.PInvoke
/// We recommend that this string be a reference to a localizable resource. For the syntax of referencing resources, see DEVPROP_TYPE_STRING_INDIRECT.
///
///
+ [MarshalAs(UnmanagedType.LPWStr)]
public string pszDeviceDescription;
///
@@ -625,6 +629,7 @@ namespace Vanara.PInvoke
///
/// Note Specifying a location is uncommon.
///
+ [MarshalAs(UnmanagedType.LPWStr)]
public string pszDeviceLocation;
///
diff --git a/UnitTests/PInvoke/CfgMgr32/CfgMgr32Tests.cs b/UnitTests/PInvoke/CfgMgr32/CfgMgr32Tests.cs
index 2ab726ff..ac056a46 100644
--- a/UnitTests/PInvoke/CfgMgr32/CfgMgr32Tests.cs
+++ b/UnitTests/PInvoke/CfgMgr32/CfgMgr32Tests.cs
@@ -4,8 +4,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using System.Runtime.InteropServices;
-using System.Security.AccessControl;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
@@ -19,89 +17,93 @@ namespace Vanara.PInvoke.Tests
{
private static readonly Guid devguid = GUID_DEVCLASS_DISKDRIVE;
private static readonly Lazy leaf = new(() => GetFirstLeaf(root.Value));
- private static readonly Lazy node = new(() => LocateNode(@"USB\ROOT_HUB30\4&3490C39&0&0"));
+ private static readonly Lazy node = new(() => LocateNode(@"SWD\PRINTENUM\WSD-F442E38C-F139-42D3-BCCC-A3653929E4B7")); //@"USB\ROOT_HUB30\4&3490C39&0&0"));
private static readonly Lazy root = new(() => LocateNode());
private ElevPriv priv;
public static uint LeafId => leaf.Value;
-
public static uint NodeId => node.Value;
-
public static uint RootId => root.Value;
- private static uint LocateNode(string devId = null)
- {
- CM_Locate_DevNode(out var di, devId, CM_LOCATE_DEVNODE.CM_LOCATE_DEVNODE_NORMAL).ThrowIfFailed();
- return di;
- }
-
[OneTimeSetUp]
- public void _Setup()
- {
- priv = new ElevPriv("SeLoadDriverPrivilege");
- }
+ public void _Setup() => priv = new ElevPriv("SeLoadDriverPrivilege");
[OneTimeTearDown]
- public void _TearDown()
- {
- priv?.Dispose();
- }
+ public void _TearDown() => priv?.Dispose();
- [Test]
- public void StructSizeTest() => TestContext.Write(string.Join("\n", TestHelper.GetNestedStructSizes(typeof(CfgMgr32))));
+ public void ClassesWithInterfacesTest()
+ {
+ foreach (System.Reflection.FieldInfo fi in typeof(SetupAPI).GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).
+ Where(fi => fi.FieldType == typeof(Guid) && fi.Name.StartsWith("GUID_DEVINTERFACE_")))
+ {
+ CONFIGRET ret = CM_Get_Device_Interface_List_Size(out var len, (Guid)fi.GetValue(null), default, CM_GET_DEVICE_INTERFACE_LIST.CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
+ if (ret == CONFIGRET.CR_SUCCESS && len > 2)
+ TestContext.WriteLine($"{fi.Name}={len}");
+ }
+ }
[Test]
public void CM_Add_Empty_Log_ConfTest()
{
- Assert.That(CM_Add_Empty_Log_Conf(out SafeLOG_CONF hConf, LeafId, PRIORITY.LCPRI_NORMAL, LOG_CONF_FLAG.BASIC_LOG_CONF), Is.EqualTo(CONFIGRET.CR_SUCCESS));
- Assert.That(() => hConf.Dispose(), Throws.Nothing);
+ Assert.That(CM_Add_Empty_Log_Conf(out SafeLOG_CONF hConf, NodeId, PRIORITY.LCPRI_NORMAL, LOG_CONF_FLAG.BASIC_LOG_CONF), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ try
+ {
+ Assert.That(CM_Get_Log_Conf_Priority(hConf, out PRIORITY p), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ Assert.That(PRIORITY.LCPRI_NORMAL, Is.EqualTo(p));
+ }
+ finally
+ {
+ Assert.That(CM_Free_Log_Conf(hConf), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ Assert.That(() => hConf.Dispose(), Throws.Nothing);
+ }
}
[Test]
public void CM_Add_Res_DesTest()
{
- Assert.That(CM_Add_Empty_Log_Conf(out var BootLC1, NodeId, PRIORITY.LCPRI_NORMAL, LOG_CONF_FLAG.BOOT_LOG_CONF), Is.EqualTo(CONFIGRET.CR_SUCCESS));
-
- var memRes = new MEM_RESOURCE
+ Assert.That(CM_Add_Empty_Log_Conf(out SafeLOG_CONF BootLC1, NodeId, PRIORITY.LCPRI_BOOTCONFIG, LOG_CONF_FLAG.BOOT_LOG_CONF | LOG_CONF_FLAG.PRIORITY_EQUAL_FIRST), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ try
{
- MEM_Header = new MEM_DES
- {
- MD_Count = 2,
- MD_Type = MType_Range,
- MD_Alloc_Base = 0xD8000,
- MD_Alloc_End = 0xD9000,
- MD_Flags = MEM_DES_FLAGS.fMD_ROM | MEM_DES_FLAGS.fMD_32 | MEM_DES_FLAGS.fMD_ReadAllowed,
- MD_Reserved = 0
- },
- MEM_Data = new MEM_RANGE[]
- {
- new MEM_RANGE
- {
- MR_Align = 8, //?
- MR_nBytes = 4096,
- MR_Min = 0xD8000,
- MR_Max = 0xDC000,
- MR_Flags = MEM_DES_FLAGS.fMD_ROM | MEM_DES_FLAGS.fMD_32 | MEM_DES_FLAGS.fMD_ReadAllowed,
- MR_Reserved = 0
- },
+ MEM_RESOURCE memRes = MakeResource();
- new MEM_RANGE
- {
- MR_Align = 8, //?
- MR_nBytes = 4096,
- MR_Min = 0xE0000,
- MR_Max = 0xE4000,
- MR_Flags = MEM_DES_FLAGS.fMD_ROM | MEM_DES_FLAGS.fMD_32 | MEM_DES_FLAGS.fMD_ReadAllowed,
- MR_Reserved = 0
- }
+ SafeRES_DES hRD = null;
+ Assert.That(() => hRD = CM_Add_Res_Des(BootLC1, memRes), Throws.Nothing);
+ try
+ {
+ var list = new (SafeRES_DES prdResDes, RESOURCEID pResourceID)[0];
+ Assert.That(() => list = CM_Get_Res_Des_List(BootLC1).ToArray(), Throws.Nothing);
+ Assert.That(list, Is.Not.Empty);
+
+ Assert.That(list[0].pResourceID, Is.EqualTo(RESOURCEID.ResType_Mem));
+ MEM_RESOURCE retMemRes = default;
+ Assert.That(() => retMemRes = CM_Get_Res_Des_Data(list[0].prdResDes), Throws.Nothing);
+ Assert.That(retMemRes.MEM_Data.Length, Is.EqualTo(memRes.MEM_Data.Length));
+
+ memRes.MEM_Data[0].MR_Min = 0xDA00;
+ memRes.MEM_Data[0].MR_Max = 0xDE00;
+ Assert.That(() => hRD = CM_Modify_Res_Des(list[0].prdResDes, memRes), Throws.Nothing);
}
- };
+ finally
+ {
+ CM_Free_Res_Des(IntPtr.Zero, hRD);
+ hRD?.Dispose();
+ }
+ }
+ finally
+ {
+ CM_Free_Log_Conf(BootLC1);
+ BootLC1.Dispose();
+ }
+ }
- SafeRES_DES hRD = null;
- Assert.That(() => hRD = CM_Add_Res_Des(BootLC1, memRes), Throws.Nothing);
- hRD?.Dispose();
- BootLC1.Dispose();
+ [Test]
+ public void CM_Clear_Log_Conf_List()
+ {
+ var lc = new SafeLOG_CONF[0];
+ Assert.That(() => lc = CM_Get_Log_Conf_List(NodeId, LOG_CONF_FLAG.BOOT_LOG_CONF).ToArray(), Throws.Nothing);
+ foreach (SafeLOG_CONF l in lc)
+ CM_Free_Log_Conf(l);
}
[Test]
@@ -114,8 +116,8 @@ namespace Vanara.PInvoke.Tests
[Test]
public void CM_Enable_DevNodeTest()
{
- Assert.That(CM_Disable_DevNode(LeafId), Is.EqualTo(CONFIGRET.CR_SUCCESS));
- Assert.That(CM_Enable_DevNode(LeafId), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ Assert.That(CM_Disable_DevNode(NodeId), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ Assert.That(CM_Enable_DevNode(NodeId), Is.EqualTo(CONFIGRET.CR_SUCCESS));
}
[Test]
@@ -160,19 +162,6 @@ namespace Vanara.PInvoke.Tests
}
}
- [Test]
- public void CM_Get_Class_PropertyTest()
- {
- var cls = devguid;
- var pkey = DEVPKEY_DeviceClass_IconPath;
- var sz = 0U;
- Assert.That(CM_Get_Class_Property(cls, pkey, out var dpType, default, ref sz, CM_CLASS_PROPERTY.CM_CLASS_PROPERTY_INSTALLER), Is.EqualTo(CONFIGRET.CR_BUFFER_SMALL));
- using var mem = new SafeCoTaskMemHandle(sz * StringHelper.GetCharSize());
- Assert.That(CM_Get_Class_Property(cls, pkey, out _, mem, ref sz, CM_CLASS_PROPERTY.CM_CLASS_PROPERTY_INSTALLER), Is.EqualTo(CONFIGRET.CR_SUCCESS));
- TestContext.WriteLine($"{cls}: Type={dpType}, Size={sz}");
- mem.ToStringEnum().WriteValues();
- }
-
[Test]
public void CM_Get_Class_Property_KeysTest()
{
@@ -184,28 +173,57 @@ namespace Vanara.PInvoke.Tests
}
[Test]
- public void CM_Get_Class_Registry_PropertyTest()
+ public void CM_GetSet_Class_PropertyTest()
{
- var cls = devguid;
- var prop = CM_DRP.CM_DRP_CAPABILITIES;
+ Guid cls = devguid;
+ DEVPROPKEY pkey = DEVPKEY_DeviceClass_IconPath;
+
+ // Get value
var sz = 0U;
- Assert.That(CM_Get_Class_Registry_Property(cls, prop, out var dpType, default, ref sz), Is.EqualTo(CONFIGRET.CR_BUFFER_SMALL));
- using var mem = new SafeCoTaskMemHandle(sz * StringHelper.GetCharSize());
- Assert.That(CM_Get_Class_Registry_Property(cls, prop, out _, mem, ref sz), Is.EqualTo(CONFIGRET.CR_SUCCESS));
- TestContext.WriteLine($"{cls}: Type={dpType}, Size={sz}");
- TestContext.Write(mem.Dump);
+ Assert.That(CM_Get_Class_Property(cls, pkey, out DEVPROPTYPE dpType, default, ref sz, CM_CLASS_PROPERTY.CM_CLASS_PROPERTY_INSTALLER), Is.EqualTo(CONFIGRET.CR_BUFFER_SMALL));
+ var strings = new string[0];
+ using (var mem = new SafeCoTaskMemHandle(sz * StringHelper.GetCharSize()))
+ {
+ Assert.That(CM_Get_Class_Property(cls, pkey, out _, mem, ref sz, CM_CLASS_PROPERTY.CM_CLASS_PROPERTY_INSTALLER), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ TestContext.WriteLine($"{cls}: Type={dpType}, Size={sz}");
+ strings = mem.ToStringEnum().ToArray();
+ strings.WriteValues();
+ }
+
+ // Set bogus value
+ using (var mem = SafeCoTaskMemHandle.CreateFromStringList(new[] { "A", "B" }))
+ {
+ Assert.That(CM_Set_Class_Property(devguid, pkey, DEVPROPTYPE.DEVPROP_TYPE_STRING_LIST, mem, mem.Size), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ }
+
+ // Reset correct value
+ using (var mem = SafeCoTaskMemHandle.CreateFromStringList(strings))
+ {
+ Assert.That(CM_Set_Class_Property(devguid, pkey, DEVPROPTYPE.DEVPROP_TYPE_STRING_LIST, mem, mem.Size), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ }
}
[Test]
- public void CM_Get_Device_IDTest()
+ public void CM_GetSet_Class_Registry_PropertyTest()
{
- var di = RootId;
- Assert.That(CM_Get_Device_ID_Size(out var len, di), Is.EqualTo(CONFIGRET.CR_SUCCESS));
- Assert.That(len, Is.Not.Zero);
- var sb = new StringBuilder((int)len+1);
- Assert.That(CM_Get_Device_ID(di, sb, len+1), Is.EqualTo(CONFIGRET.CR_SUCCESS));
- Assert.That(sb.Length, Is.Not.Zero);
- TestContext.Write($"ID: {di} ({sb})");
+ Guid cls = devguid;
+ CM_CRP prop = CM_CRP.CM_CRP_CHARACTERISTICS;
+
+ var sz = 0U;
+ Assert.That(CM_Get_Class_Registry_Property(cls, prop, out _, default, ref sz), Is.EqualTo(CONFIGRET.CR_BUFFER_SMALL));
+ uint val = 0;
+ using (var mem = new SafeCoTaskMemHandle(sz * StringHelper.GetCharSize()))
+ {
+ Assert.That(CM_Get_Class_Registry_Property(cls, prop, out REG_VALUE_TYPE dpType, mem, ref sz), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ TestContext.WriteLine($"{cls}: Type={dpType}, Size={sz}");
+ TestContext.Write(val = (uint)dpType.GetValue(mem, mem.Size));
+ }
+
+ using (var mem = SafeCoTaskMemHandle.CreateFromStructure(val > 0 ? 0U : 256))
+ Assert.That(CM_Set_Class_Registry_Property(cls, prop, mem, mem.Size), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+
+ using (var mem = SafeCoTaskMemHandle.CreateFromStructure(val))
+ Assert.That(CM_Set_Class_Registry_Property(cls, prop, mem, mem.Size), Is.EqualTo(CONFIGRET.CR_SUCCESS));
}
[Test]
@@ -217,99 +235,131 @@ namespace Vanara.PInvoke.Tests
TestContext.Write(string.Join("\n", mem.ToStringEnum()));
}
+ [Test]
+ public void CM_Get_Device_IDTest()
+ {
+ var di = RootId;
+ Assert.That(CM_Get_Device_ID_Size(out var len, di), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ Assert.That(len, Is.Not.Zero);
+ var sb = new StringBuilder((int)len + 1);
+ Assert.That(CM_Get_Device_ID(di, sb, len + 1), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ Assert.That(sb.Length, Is.Not.Zero);
+ TestContext.Write($"ID: {di} ({sb})");
+ }
+
[Test]
public void CM_Get_Device_Interface_AliasTest()
{
//Assert.That(CM_Get_Device_Interface_Alias(), Is.EqualTo(CONFIGRET.CR_SUCCESS));
}
- public void ClassesWithInterfacesTest()
+ [Test]
+ public void CM_Get_Device_Interface_PropertiesTest() => Assert.That(() =>
{
- foreach (var fi in typeof(SetupAPI).GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).
- Where(fi => fi.FieldType == typeof(Guid) && fi.Name.StartsWith("GUID_DEVINTERFACE_")))
+ foreach (var devInt in CM_Get_Device_Interface_List(GUID_DEVINTERFACE_NET, CM_GET_DEVICE_INTERFACE_LIST.CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
- var ret = CM_Get_Device_Interface_List_Size(out var len, (Guid)fi.GetValue(null), default, CM_GET_DEVICE_INTERFACE_LIST.CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
- if (ret == CONFIGRET.CR_SUCCESS && len > 2)
- TestContext.WriteLine($"{fi.Name}={len}");
+ TestContext.WriteLine(devInt);
+
+ uint size = 0;
+ CONFIGRET ret = CM_Get_Device_Interface_Property_Keys(devInt, default, ref size);
+ if (ret == CONFIGRET.CR_NO_SUCH_VALUE) continue;
+ Assert.That(ret, Is.EqualTo(CONFIGRET.CR_BUFFER_SMALL));
+ Assert.That(size, Is.GreaterThan(0));
+ var keys = new DEVPROPKEY[size];
+ Assert.That(CM_Get_Device_Interface_Property_Keys(devInt, keys, ref size), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+
+ foreach (DEVPROPKEY key in keys)
+ {
+ TestContext.Write($" {key} ({(key.TryGetReadOnly(out var ro) ? (ro ? "R" : "RW") : "?")}): ");
+ size = 0;
+ ret = CM_Get_Device_Interface_Property(devInt, key, out DEVPROPTYPE pType, default, ref size);
+ if (ret == CONFIGRET.CR_NO_SUCH_VALUE) continue;
+ Assert.That(ret, Is.EqualTo(CONFIGRET.CR_BUFFER_SMALL));
+ Assert.That(size, Is.GreaterThan(0));
+ using var mem = new SafeCoTaskMemHandle((int)size);
+ Assert.That(CM_Get_Device_Interface_Property(devInt, key, out _, mem, ref size), Is.EqualTo(CONFIGRET.CR_SUCCESS));
+ try
+ {
+ var o = pType.GetObject(mem);
+ TestContext.WriteLine(o is null ? "(null)" : (o.GetType().IsArray ? string.Join(", ", ((Array)o).Cast