mirror of https://github.com/dahall/Vanara.git
Added nullability to PortableDeviceApi and tests
parent
718d241007
commit
99e7fa0a78
|
@ -1,4 +1,5 @@
|
||||||
using static Vanara.PInvoke.Kernel32;
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
using static Vanara.PInvoke.Kernel32;
|
||||||
using static Vanara.PInvoke.Ole32;
|
using static Vanara.PInvoke.Ole32;
|
||||||
|
|
||||||
namespace Vanara.PInvoke;
|
namespace Vanara.PInvoke;
|
||||||
|
@ -29,62 +30,80 @@ public static partial class PortableDeviceApi
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* This section declares WPD defines
|
* This section declares WPD defines
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
// WPD specific function number used to construct WPD I/O control codes. Drivers should not use this define directly.
|
/// <summary>WPD specific function number used to construct WPD I/O control codes. Drivers should not use this define directly.</summary>
|
||||||
public const ushort WPD_CONTROL_FUNCTION_GENERIC_MESSAGE = 0x42;
|
public const ushort WPD_CONTROL_FUNCTION_GENERIC_MESSAGE = 0x42;
|
||||||
|
|
||||||
// Defines WPD specific IOCTL number used by drivers to detect WPD requests that may require READ and WRITE access to the device.
|
/// <summary>
|
||||||
|
/// Defines WPD specific IOCTL number used by drivers to detect WPD requests that may require READ and WRITE access to the device.
|
||||||
|
/// </summary>
|
||||||
public static readonly uint IOCTL_WPD_MESSAGE_READWRITE_ACCESS = CTL_CODE(DEVICE_TYPE.FILE_DEVICE_WPD, WPD_CONTROL_FUNCTION_GENERIC_MESSAGE, IOMethod.METHOD_BUFFERED, IOAccess.FILE_READ_ACCESS | IOAccess.FILE_WRITE_ACCESS);
|
public static readonly uint IOCTL_WPD_MESSAGE_READWRITE_ACCESS = CTL_CODE(DEVICE_TYPE.FILE_DEVICE_WPD, WPD_CONTROL_FUNCTION_GENERIC_MESSAGE, IOMethod.METHOD_BUFFERED, IOAccess.FILE_READ_ACCESS | IOAccess.FILE_WRITE_ACCESS);
|
||||||
|
|
||||||
// Defines WPD specific IOCTL number used by drivers to detect WPD requests that require READ-only access to the device.
|
/// <summary>Defines WPD specific IOCTL number used by drivers to detect WPD requests that require READ-only access to the device.</summary>
|
||||||
public static readonly uint IOCTL_WPD_MESSAGE_READ_ACCESS = CTL_CODE(DEVICE_TYPE.FILE_DEVICE_WPD, WPD_CONTROL_FUNCTION_GENERIC_MESSAGE, IOMethod.METHOD_BUFFERED, IOAccess.FILE_READ_ACCESS);
|
public static readonly uint IOCTL_WPD_MESSAGE_READ_ACCESS = CTL_CODE(DEVICE_TYPE.FILE_DEVICE_WPD, WPD_CONTROL_FUNCTION_GENERIC_MESSAGE, IOMethod.METHOD_BUFFERED, IOAccess.FILE_READ_ACCESS);
|
||||||
|
|
||||||
// Drivers can use this macro to detect whether the incoming IOCTL is a WPD message or not.
|
/// <summary>Drivers can use this macro to detect whether the incoming IOCTL is a WPD message or not.</summary>
|
||||||
public static bool IS_WPD_IOCTL(uint ControlCode) => ((ControlCode == IOCTL_WPD_MESSAGE_READWRITE_ACCESS) || (ControlCode == IOCTL_WPD_MESSAGE_READ_ACCESS));
|
public static bool IS_WPD_IOCTL(uint ControlCode) => ((ControlCode == IOCTL_WPD_MESSAGE_READWRITE_ACCESS) || (ControlCode == IOCTL_WPD_MESSAGE_READ_ACCESS));
|
||||||
|
|
||||||
// Pre-defined ObjectID for the DEVICE object.
|
/// <summary>Pre-defined ObjectID for the DEVICE object.</summary>
|
||||||
public const string WPD_DEVICE_OBJECT_ID = "DEVICE";
|
public const string WPD_DEVICE_OBJECT_ID = "DEVICE";
|
||||||
|
|
||||||
// Pre-defined IWMDMDevice for the IWMDRMDeviceApp license/metering APIs.
|
/// <summary>Pre-defined IWMDMDevice for the IWMDRMDeviceApp license/metering APIs.</summary>
|
||||||
public static readonly IntPtr WMDRMDEVICEAPP_USE_WPD_DEVICE_PTR = new(-1);
|
public static readonly IntPtr WMDRMDEVICEAPP_USE_WPD_DEVICE_PTR = new(-1);
|
||||||
|
|
||||||
// Pre-defined name of a REG_DWORD value that defines the device type, used for representation purposes only. Functional
|
/// <summary>
|
||||||
// characteristics of the device are decided through functional objects. This value can be retrieved using
|
/// Pre-defined name of a REG_DWORD value that defines the device type, used for representation purposes only. Functional characteristics
|
||||||
// IPortableDeviceManager::GetDeviceProperty(...). See WPD_DEVICE_TYPES enumeration for possible values.
|
/// of the device are decided through functional objects. This value can be retrieved using
|
||||||
|
/// IPortableDeviceManager::GetDeviceProperty(...). See WPD_DEVICE_TYPES enumeration for possible values.
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_TYPE = "PortableDeviceType";
|
public const string PORTABLE_DEVICE_TYPE = "PortableDeviceType";
|
||||||
|
|
||||||
// Pre-defined name of a REG_SZ/REG_EXPAND_SZ/REG_MULTI_SZ value that indicates the location of the device icon file or device icon
|
/// <summary>
|
||||||
// resource. This value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...). This
|
/// Pre-defined name of a REG_SZ/REG_EXPAND_SZ/REG_MULTI_SZ value that indicates the location of the device icon file or device icon
|
||||||
// REG_SZ/REG_EXPAND_SZ/REG_MULTI_SZ value is either in the form "file.dll, resourceID" or a full file path to an icon file. e.g.: "x:\file.ico"
|
/// resource. This value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...). This REG_SZ/REG_EXPAND_SZ/REG_MULTI_SZ
|
||||||
|
/// value is either in the form "file.dll, resourceID" or a full file path to an icon file. e.g.: "x:\file.ico"
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_ICON = "Icons";
|
public const string PORTABLE_DEVICE_ICON = "Icons";
|
||||||
|
|
||||||
// Pre-defined name of a REG_DWORD value that indicates the amount of time in milliseconds the WPD Namespace Extension will keep its
|
/// <summary>
|
||||||
// reference to the device open under idle conditions. This value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...).
|
/// Pre-defined name of a REG_DWORD value that indicates the amount of time in milliseconds the WPD Namespace Extension will keep its
|
||||||
|
/// reference to the device open under idle conditions. This value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...).
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_NAMESPACE_TIMEOUT = "PortableDeviceNameSpaceTimeout";
|
public const string PORTABLE_DEVICE_NAMESPACE_TIMEOUT = "PortableDeviceNameSpaceTimeout";
|
||||||
|
|
||||||
// Pre-defined name of a REG_DWORD value that is used as a flag to indicate whether the device should, or should not, be shown in
|
/// <summary>
|
||||||
// the Explorer view. This value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...). Meaning of values are: 0 =
|
/// Pre-defined name of a REG_DWORD value that is used as a flag to indicate whether the device should, or should not, be shown in the
|
||||||
// include, 1 = exclude. 0 is assumed if this value doesn't exist.
|
/// Explorer view. This value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...). Meaning of values are: 0 = include,
|
||||||
|
/// 1 = exclude. 0 is assumed if this value doesn't exist.
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_NAMESPACE_EXCLUDE_FROM_SHELL = "PortableDeviceNameSpaceExcludeFromShell";
|
public const string PORTABLE_DEVICE_NAMESPACE_EXCLUDE_FROM_SHELL = "PortableDeviceNameSpaceExcludeFromShell";
|
||||||
|
|
||||||
// Pre-defined name of a REG_SZ or REG_MULTI_SZ value containing content type guids that are used indicate for what content types
|
/// <summary>
|
||||||
// the portable device namespace should attempt to automatically generate a thumbnail when placing new content on the device. This
|
/// Pre-defined name of a REG_SZ or REG_MULTI_SZ value containing content type guids that are used indicate for what content types the
|
||||||
// value can be retrieved using IPortableDeviceManager::GetDeviceProperty(...). Values should be a string representation of a GUID,
|
/// portable device namespace should attempt to automatically generate a thumbnail when placing new content on the device. This value can
|
||||||
// in the form '{00000000-0000-0000-0000-000000000000}'. By default the portable device namespace attempts to automatically generate
|
/// be retrieved using IPortableDeviceManager::GetDeviceProperty(...). Values should be a string representation of a GUID, in the form
|
||||||
// thumbnails for WPD_CONTENT_TYPE_IMAGE, if a device does not want this behavior it can set this value to an empty string.
|
/// '{00000000-0000-0000-0000-000000000000}'. By default the portable device namespace attempts to automatically generate thumbnails for
|
||||||
|
/// WPD_CONTENT_TYPE_IMAGE, if a device does not want this behavior it can set this value to an empty string.
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_NAMESPACE_THUMBNAIL_CONTENT_TYPES = "PortableDeviceNameSpaceThumbnailContentTypes";
|
public const string PORTABLE_DEVICE_NAMESPACE_THUMBNAIL_CONTENT_TYPES = "PortableDeviceNameSpaceThumbnailContentTypes";
|
||||||
|
|
||||||
// Pre-defined name of a REG_DWORD value that indicates whether a Portable Device is a Mass Storage Class (MSC) device. This is used
|
/// <summary>
|
||||||
// to avoid duplication of the device in certain views and scenarios that include both file system and Portable Devices. This value
|
/// Pre-defined name of a REG_DWORD value that indicates whether a Portable Device is a Mass Storage Class (MSC) device. This is used to
|
||||||
// can be retrieved using IPortableDeviceManager::GetDeviceProperty(...). Meaning of values are: 0 = device is not mass storage, 1 =
|
/// avoid duplication of the device in certain views and scenarios that include both file system and Portable Devices. This value can be
|
||||||
// device is mass storage. 0 is assumed if this value doesn't exist.
|
/// retrieved using IPortableDeviceManager::GetDeviceProperty(...). Meaning of values are: 0 = device is not mass storage, 1 = device is
|
||||||
|
/// mass storage. 0 is assumed if this value doesn't exist.
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_IS_MASS_STORAGE = "PortableDeviceIsMassStorage";
|
public const string PORTABLE_DEVICE_IS_MASS_STORAGE = "PortableDeviceIsMassStorage";
|
||||||
|
|
||||||
// Pre-defined value identifying the "Windows Media Digital Rights Management 10 for Portable Devices" scheme for protecting
|
/// <summary>
|
||||||
// content. This value can be used by drivers to indicate they support WMDRM10-PD. See WPD_DEVICE_SUPPORTED_DRM_SCHEMES.
|
/// Pre-defined value identifying the "Windows Media Digital Rights Management 10 for Portable Devices" scheme for protecting content.
|
||||||
|
/// This value can be used by drivers to indicate they support WMDRM10-PD. See WPD_DEVICE_SUPPORTED_DRM_SCHEMES.
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_DRM_SCHEME_WMDRM10_PD = "WMDRM10-PD";
|
public const string PORTABLE_DEVICE_DRM_SCHEME_WMDRM10_PD = "WMDRM10-PD";
|
||||||
|
|
||||||
// Pre-defined value identifying the "Portable Device Digital Rights Management" scheme for protecting content. This value can be
|
/// <summary>
|
||||||
// used by drivers to indicate they support PDDRM. See WPD_DEVICE_SUPPORTED_DRM_SCHEMES.
|
/// Pre-defined value identifying the "Portable Device Digital Rights Management" scheme for protecting content. This value can be used
|
||||||
|
/// by drivers to indicate they support PDDRM. See WPD_DEVICE_SUPPORTED_DRM_SCHEMES.
|
||||||
|
/// </summary>
|
||||||
public const string PORTABLE_DEVICE_DRM_SCHEME_PDDRM = "PDDRM";
|
public const string PORTABLE_DEVICE_DRM_SCHEME_PDDRM = "PDDRM";
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -4687,7 +4706,7 @@ public static partial class PortableDeviceApi
|
||||||
/// <param name="ControlCode">The control code.</param>
|
/// <param name="ControlCode">The control code.</param>
|
||||||
/// <param name="pCommandParams">The <see cref="IPortableDeviceValues"/> instance.</param>
|
/// <param name="pCommandParams">The <see cref="IPortableDeviceValues"/> instance.</param>
|
||||||
/// <returns>S_OK on success; otherwise and error code.</returns>
|
/// <returns>S_OK on success; otherwise and error code.</returns>
|
||||||
public static HRESULT VerifyWpdCommandAccessFromMap(uint ControlCode, IPortableDeviceValues pCommandParams)
|
public static HRESULT VerifyWpdCommandAccessFromMap(uint ControlCode, IPortableDeviceValues? pCommandParams)
|
||||||
{
|
{
|
||||||
HRESULT hr = HRESULT.S_OK;
|
HRESULT hr = HRESULT.S_OK;
|
||||||
uint dwExpectedControlCode = IOCTL_WPD_MESSAGE_READWRITE_ACCESS;
|
uint dwExpectedControlCode = IOCTL_WPD_MESSAGE_READWRITE_ACCESS;
|
||||||
|
@ -4737,12 +4756,12 @@ public static partial class PortableDeviceApi
|
||||||
return hr.Succeeded && ControlCode != dwExpectedControlCode ? HRESULT.E_INVALIDARG : hr;
|
return hr.Succeeded && ControlCode != dwExpectedControlCode ? HRESULT.E_INVALIDARG : hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PROPERTYKEY? GetWPDPKey(string propName) => propName is null ? null : PortableDeviceExtensions.GetKeyFromName(propName);
|
private static PROPERTYKEY? GetWPDPKey(string? propName) => propName is null ? null : PortableDeviceExtensions.GetKeyFromName(propName);
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||||
public class WPDCommandAttribute : Attribute
|
public class WPDCommandAttribute : Attribute
|
||||||
{
|
{
|
||||||
public WPDCommandAttribute(WPD_COMMAND_ACCESS_TYPES access = WPD_COMMAND_ACCESS_TYPES.WPD_COMMAND_ACCESS_READ, string depProp = null)
|
public WPDCommandAttribute(WPD_COMMAND_ACCESS_TYPES access = WPD_COMMAND_ACCESS_TYPES.WPD_COMMAND_ACCESS_READ, string? depProp = null)
|
||||||
{
|
{
|
||||||
Access = access;
|
Access = access;
|
||||||
AccessDependency = GetWPDPKey(depProp);
|
AccessDependency = GetWPDPKey(depProp);
|
||||||
|
|
|
@ -9,9 +9,9 @@ public static partial class PortableDeviceApi
|
||||||
{
|
{
|
||||||
private const string Lib_PortableDeviceApi = "PortableDeviceApi.dll";
|
private const string Lib_PortableDeviceApi = "PortableDeviceApi.dll";
|
||||||
|
|
||||||
private delegate HRESULT PDMStrArrGet(string[] arr, ref uint cnt);
|
private delegate HRESULT PDMStrArrGet(string[]? arr, ref uint cnt);
|
||||||
|
|
||||||
private delegate HRESULT PDMStrGet(string devId, StringBuilder str, ref uint sz);
|
private delegate HRESULT PDMStrGet(string devId, StringBuilder? str, ref uint sz);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <c>IEnumPortableDeviceObjectIDs</c> interface enumerates the objects on a portable device. Get this interface initially by
|
/// The <c>IEnumPortableDeviceObjectIDs</c> interface enumerates the objects on a portable device. Get this interface initially by
|
||||||
|
@ -332,7 +332,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-sendcommand HRESULT
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-sendcommand HRESULT
|
||||||
// SendCommand( [in] const DWORD dwFlags, [in] IPortableDeviceValues *pParameters, [out] IPortableDeviceValues **ppResults );
|
// SendCommand( [in] const DWORD dwFlags, [in] IPortableDeviceValues *pParameters, [out] IPortableDeviceValues **ppResults );
|
||||||
IPortableDeviceValues SendCommand([Optional] UInt32 dwFlags, [In] IPortableDeviceValues pParameters);
|
IPortableDeviceValues SendCommand([Optional] uint dwFlags, [In] IPortableDeviceValues pParameters);
|
||||||
|
|
||||||
/// <summary>The <c>Content</c> method retrieves an interface that you can use to access objects on a device.</summary>
|
/// <summary>The <c>Content</c> method retrieves an interface that you can use to access objects on a device.</summary>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
|
@ -391,7 +391,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-advise HRESULT
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevice-advise HRESULT
|
||||||
// Advise( [in] const DWORD dwFlags, [in] IPortableDeviceEventCallback *pCallback, [in] IPortableDeviceValues *pParameters,
|
// Advise( [in] const DWORD dwFlags, [in] IPortableDeviceEventCallback *pCallback, [in] IPortableDeviceValues *pParameters,
|
||||||
// [out] LPWSTR *ppszCookie );
|
// [out] LPWSTR *ppszCookie );
|
||||||
void Advise([Optional] uint dwFlags, IPortableDeviceEventCallback pCallback, [Optional] IPortableDeviceValues pParameters, [MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie);
|
void Advise([Optional] uint dwFlags, IPortableDeviceEventCallback pCallback, [Optional] IPortableDeviceValues? pParameters, [MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <c>Unadvise</c> method unregisters a client from receiving callback notifications. You must call this method if you
|
/// The <c>Unadvise</c> method unregisters a client from receiving callback notifications. You must call this method if you
|
||||||
|
@ -592,7 +592,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getfixedpropertyattributes
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicecapabilities-getfixedpropertyattributes
|
||||||
// HRESULT GetFixedPropertyAttributes( [in] REFGUID Format, [in] REFPROPERTYKEY Key, [out] IPortableDeviceValues **ppAttributes );
|
// HRESULT GetFixedPropertyAttributes( [in] REFGUID Format, [in] REFPROPERTYKEY Key, [out] IPortableDeviceValues **ppAttributes );
|
||||||
IPortableDeviceValues GetFixedPropertyAttributes(in Guid Format, in PROPERTYKEY Key);
|
IPortableDeviceValues? GetFixedPropertyAttributes(in Guid Format, in PROPERTYKEY Key);
|
||||||
|
|
||||||
/// <summary>The <c>Cancel</c> method cancels a pending request on this interface.</summary>
|
/// <summary>The <c>Cancel</c> method cancels a pending request on this interface.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
@ -653,7 +653,7 @@ public static partial class PortableDeviceApi
|
||||||
// HRESULT EnumObjects( [in] const DWORD dwFlags, [in] LPCWSTR pszParentObjectID, [in] IPortableDeviceValues *pFilter, [out]
|
// HRESULT EnumObjects( [in] const DWORD dwFlags, [in] LPCWSTR pszParentObjectID, [in] IPortableDeviceValues *pFilter, [out]
|
||||||
// IEnumPortableDeviceObjectIDs **ppEnum );
|
// IEnumPortableDeviceObjectIDs **ppEnum );
|
||||||
IEnumPortableDeviceObjectIDs EnumObjects([Optional] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID,
|
IEnumPortableDeviceObjectIDs EnumObjects([Optional] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID,
|
||||||
[In, Optional] IPortableDeviceValues pFilter);
|
[In, Optional] IPortableDeviceValues? pFilter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <c>Properties</c> method retrieves the interface that is required to get or set properties on an object on the device.
|
/// The <c>Properties</c> method retrieves the interface that is required to get or set properties on an object on the device.
|
||||||
|
@ -906,7 +906,7 @@ public static partial class PortableDeviceApi
|
||||||
// HRESULT EnumObjects( [in] const DWORD dwFlags, [in] LPCWSTR pszParentObjectID, [in] IPortableDeviceValues *pFilter, [out]
|
// HRESULT EnumObjects( [in] const DWORD dwFlags, [in] LPCWSTR pszParentObjectID, [in] IPortableDeviceValues *pFilter, [out]
|
||||||
// IEnumPortableDeviceObjectIDs **ppEnum );
|
// IEnumPortableDeviceObjectIDs **ppEnum );
|
||||||
new IEnumPortableDeviceObjectIDs EnumObjects([Optional] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID,
|
new IEnumPortableDeviceObjectIDs EnumObjects([Optional] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID,
|
||||||
[In, Optional] IPortableDeviceValues pFilter);
|
[In, Optional] IPortableDeviceValues? pFilter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <c>Properties</c> method retrieves the interface that is required to get or set properties on an object on the device.
|
/// The <c>Properties</c> method retrieves the interface that is required to get or set properties on an object on the device.
|
||||||
|
@ -1293,7 +1293,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceeventcallback-onevent
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceeventcallback-onevent
|
||||||
// HRESULT OnEvent( [in] IPortableDeviceValues *pEventParameters );
|
// HRESULT OnEvent( [in] IPortableDeviceValues *pEventParameters );
|
||||||
void OnEvent([Optional] IPortableDeviceValues pEventParameters);
|
void OnEvent([Optional] IPortableDeviceValues? pEventParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1341,7 +1341,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdevices
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdevices
|
||||||
// HRESULT GetDevices( [in, out] LPWSTR *pPnPDeviceIDs, [in, out] DWORD *pcPnPDeviceIDs );
|
// HRESULT GetDevices( [in, out] LPWSTR *pPnPDeviceIDs, [in, out] DWORD *pcPnPDeviceIDs );
|
||||||
[PreserveSig]
|
[PreserveSig]
|
||||||
HRESULT GetDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] pPnPDeviceIDs,
|
HRESULT GetDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[]? pPnPDeviceIDs,
|
||||||
ref uint pcPnPDeviceIDs);
|
ref uint pcPnPDeviceIDs);
|
||||||
|
|
||||||
/// <summary>The <c>RefreshDeviceList</c> method refreshes the list of devices that are connected to the computer.</summary>
|
/// <summary>The <c>RefreshDeviceList</c> method refreshes the list of devices that are connected to the computer.</summary>
|
||||||
|
@ -1385,7 +1385,7 @@ public static partial class PortableDeviceApi
|
||||||
// HRESULT GetDeviceFriendlyName( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceFriendlyName, [in, out] DWORD
|
// HRESULT GetDeviceFriendlyName( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceFriendlyName, [in, out] DWORD
|
||||||
// *pcchDeviceFriendlyName );
|
// *pcchDeviceFriendlyName );
|
||||||
[PreserveSig]
|
[PreserveSig]
|
||||||
HRESULT GetDeviceFriendlyName([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pDeviceFriendlyName,
|
HRESULT GetDeviceFriendlyName([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder? pDeviceFriendlyName,
|
||||||
[In, Out] ref uint pcchDeviceFriendlyName);
|
[In, Out] ref uint pcchDeviceFriendlyName);
|
||||||
|
|
||||||
/// <summary>Retrieves the description of a device.</summary>
|
/// <summary>Retrieves the description of a device.</summary>
|
||||||
|
@ -1407,7 +1407,7 @@ public static partial class PortableDeviceApi
|
||||||
// HRESULT GetDeviceDescription( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceDescription, [in, out] DWORD
|
// HRESULT GetDeviceDescription( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceDescription, [in, out] DWORD
|
||||||
// *pcchDeviceDescription );
|
// *pcchDeviceDescription );
|
||||||
[PreserveSig]
|
[PreserveSig]
|
||||||
HRESULT GetDeviceDescription([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pDeviceDescription,
|
HRESULT GetDeviceDescription([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder? pDeviceDescription,
|
||||||
[In, Out] ref uint pcchDeviceDescription);
|
[In, Out] ref uint pcchDeviceDescription);
|
||||||
|
|
||||||
/// <summary>Retrieves the name of the device manufacturer.</summary>
|
/// <summary>Retrieves the name of the device manufacturer.</summary>
|
||||||
|
@ -1429,7 +1429,7 @@ public static partial class PortableDeviceApi
|
||||||
// HRESULT GetDeviceManufacturer( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceManufacturer, [in, out] DWORD
|
// HRESULT GetDeviceManufacturer( [in] LPCWSTR pszPnPDeviceID, [in, out] WCHAR *pDeviceManufacturer, [in, out] DWORD
|
||||||
// *pcchDeviceManufacturer );
|
// *pcchDeviceManufacturer );
|
||||||
[PreserveSig]
|
[PreserveSig]
|
||||||
HRESULT GetDeviceManufacturer([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pDeviceManufacturer,
|
HRESULT GetDeviceManufacturer([In, MarshalAs(UnmanagedType.LPWStr)] string pszPnPDeviceID, [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder? pDeviceManufacturer,
|
||||||
[In, Out] ref uint pcchDeviceManufacturer);
|
[In, Out] ref uint pcchDeviceManufacturer);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1506,7 +1506,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getprivatedevices
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getprivatedevices
|
||||||
// HRESULT GetPrivateDevices( [in, out] LPWSTR *pPnPDeviceIDs, [in, out] DWORD *pcPnPDeviceIDs );
|
// HRESULT GetPrivateDevices( [in, out] LPWSTR *pPnPDeviceIDs, [in, out] DWORD *pcPnPDeviceIDs );
|
||||||
[PreserveSig]
|
[PreserveSig]
|
||||||
HRESULT GetPrivateDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] pPnPDeviceIDs, ref uint pcPnPDeviceIDs);
|
HRESULT GetPrivateDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[]? pPnPDeviceIDs, ref uint pcPnPDeviceIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1573,7 +1573,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-getvalues
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceproperties-getvalues
|
||||||
// HRESULT GetValues( [in] LPCWSTR pszObjectID, [in] IPortableDeviceKeyCollection *pKeys, [out] IPortableDeviceValues **ppValues );
|
// HRESULT GetValues( [in] LPCWSTR pszObjectID, [in] IPortableDeviceKeyCollection *pKeys, [out] IPortableDeviceValues **ppValues );
|
||||||
IPortableDeviceValues GetValues([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceKeyCollection pKeys);
|
IPortableDeviceValues GetValues([MarshalAs(UnmanagedType.LPWStr)] string pszObjectID, IPortableDeviceKeyCollection? pKeys);
|
||||||
|
|
||||||
/// <summary>The <c>SetValues</c> method adds or modifies one or more properties on a specified object on a device.</summary>
|
/// <summary>The <c>SetValues</c> method adds or modifies one or more properties on a specified object on a device.</summary>
|
||||||
/// <param name="pszObjectID">The object ID of the object to modify. To specify the device, use WPD_DEVICE_OBJECT_ID.</param>
|
/// <param name="pszObjectID">The object ID of the object to modify. To specify the device, use WPD_DEVICE_OBJECT_ID.</param>
|
||||||
|
@ -1675,7 +1675,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-queuegetvaluesbyobjectlist
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicepropertiesbulk-queuegetvaluesbyobjectlist
|
||||||
// HRESULT QueueGetValuesByObjectList( [in] IPortableDevicePropVariantCollection *pObjectIDs, [in] IPortableDeviceKeyCollection
|
// HRESULT QueueGetValuesByObjectList( [in] IPortableDevicePropVariantCollection *pObjectIDs, [in] IPortableDeviceKeyCollection
|
||||||
// *pKeys, [in] IPortableDevicePropertiesBulkCallback *pCallback, [out] GUID *pContext );
|
// *pKeys, [in] IPortableDevicePropertiesBulkCallback *pCallback, [out] GUID *pContext );
|
||||||
void QueueGetValuesByObjectList(IPortableDevicePropVariantCollection pObjectIDs, [Optional] IPortableDeviceKeyCollection pKeys,
|
void QueueGetValuesByObjectList(IPortableDevicePropVariantCollection pObjectIDs, [Optional] IPortableDeviceKeyCollection? pKeys,
|
||||||
IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext);
|
IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1763,7 +1763,7 @@ public static partial class PortableDeviceApi
|
||||||
// *pContext );
|
// *pContext );
|
||||||
void QueueGetValuesByObjectFormat(in Guid pguidObjectFormat,
|
void QueueGetValuesByObjectFormat(in Guid pguidObjectFormat,
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID, uint dwDepth,
|
[MarshalAs(UnmanagedType.LPWStr)] string pszParentObjectID, uint dwDepth,
|
||||||
[Optional] IPortableDeviceKeyCollection pKeys, IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext);
|
[Optional] IPortableDeviceKeyCollection? pKeys, IPortableDevicePropertiesBulkCallback pCallback, out Guid pContext);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <c>QueueSetValuesByObjectList</c> method queues a request to set one or more specified values on one or more specified
|
/// The <c>QueueSetValuesByObjectList</c> method queues a request to set one or more specified values on one or more specified
|
||||||
|
@ -2166,7 +2166,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-advise
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservice-advise
|
||||||
// HRESULT Advise( [in] const DWORD dwFlags, [in] IPortableDeviceEventCallback *pCallback, [in] IPortableDeviceValues
|
// HRESULT Advise( [in] const DWORD dwFlags, [in] IPortableDeviceEventCallback *pCallback, [in] IPortableDeviceValues
|
||||||
// *pParameters, [out] LPWSTR *ppszCookie );
|
// *pParameters, [out] LPWSTR *ppszCookie );
|
||||||
void Advise([In, Optional] uint dwFlags, IPortableDeviceEventCallback pCallback, [In, Optional] IPortableDeviceValues pParameters,
|
void Advise([In, Optional] uint dwFlags, IPortableDeviceEventCallback pCallback, [In, Optional] IPortableDeviceValues? pParameters,
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie);
|
[MarshalAs(UnmanagedType.LPWStr)] out string ppszCookie);
|
||||||
|
|
||||||
/// <summary>The <c>Unadvise</c> method unregisters a service event callback object.</summary>
|
/// <summary>The <c>Unadvise</c> method unregisters a service event callback object.</summary>
|
||||||
|
@ -2552,7 +2552,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-invoke
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-invoke
|
||||||
// HRESULT Invoke( [in] REFGUID Method, [in] IPortableDeviceValues *pParameters, [in, out] IPortableDeviceValues **ppResults );
|
// HRESULT Invoke( [in] REFGUID Method, [in] IPortableDeviceValues *pParameters, [in, out] IPortableDeviceValues **ppResults );
|
||||||
void Invoke(in Guid Method, [Optional] IPortableDeviceValues pParameters, out IPortableDeviceValues ppResults);
|
void Invoke(in Guid Method, [Optional] IPortableDeviceValues? pParameters, out IPortableDeviceValues ppResults);
|
||||||
|
|
||||||
/// <summary>The <c>InvokeAsync</c> method asynchronously invokes a method.</summary>
|
/// <summary>The <c>InvokeAsync</c> method asynchronously invokes a method.</summary>
|
||||||
/// <param name="Method">The method to invoke.</param>
|
/// <param name="Method">The method to invoke.</param>
|
||||||
|
@ -2577,7 +2577,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-invokeasync
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-invokeasync
|
||||||
// HRESULT InvokeAsync( [in] REFGUID Method, [in] IPortableDeviceValues *pParameters, [in] IPortableDeviceServiceMethodCallback
|
// HRESULT InvokeAsync( [in] REFGUID Method, [in] IPortableDeviceValues *pParameters, [in] IPortableDeviceServiceMethodCallback
|
||||||
// *pCallback );
|
// *pCallback );
|
||||||
void InvokeAsync(in Guid Method, [Optional] IPortableDeviceValues pParameters, [Optional] IPortableDeviceServiceMethodCallback pCallback);
|
void InvokeAsync(in Guid Method, [Optional] IPortableDeviceValues? pParameters, [Optional] IPortableDeviceServiceMethodCallback? pCallback);
|
||||||
|
|
||||||
/// <summary>The <c>Cancel</c> method cancels a pending method invocation.</summary>
|
/// <summary>The <c>Cancel</c> method cancels a pending method invocation.</summary>
|
||||||
/// <param name="pCallback">
|
/// <param name="pCallback">
|
||||||
|
@ -2595,7 +2595,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-cancel
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledeviceservicemethods-cancel
|
||||||
// HRESULT Cancel( [in] IPortableDeviceServiceMethodCallback *pCallback );
|
// HRESULT Cancel( [in] IPortableDeviceServiceMethodCallback *pCallback );
|
||||||
void Cancel([Optional] IPortableDeviceServiceMethodCallback pCallback);
|
void Cancel([Optional] IPortableDeviceServiceMethodCallback? pCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Callback interface for implemented by clients for retrieving results of an asynchronous service open.</summary>
|
/// <summary>Callback interface for implemented by clients for retrieving results of an asynchronous service open.</summary>
|
||||||
|
@ -2664,7 +2664,7 @@ public static partial class PortableDeviceApi
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdeviceproperty
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceapi/nf-portabledeviceapi-iportabledevicemanager-getdeviceproperty
|
||||||
// HRESULT GetDeviceProperty( [in] LPCWSTR pszPnPDeviceID, [in] LPCWSTR pszDevicePropertyName, [in, out] BYTE *pData, [in, out]
|
// HRESULT GetDeviceProperty( [in] LPCWSTR pszPnPDeviceID, [in] LPCWSTR pszDevicePropertyName, [in, out] BYTE *pData, [in, out]
|
||||||
// DWORD *pcbData, [in, out] DWORD *pdwType );
|
// DWORD *pcbData, [in, out] DWORD *pdwType );
|
||||||
public static T GetDeviceProperty<T>(this IPortableDeviceManager manager, string pszPnPDeviceID, string pszDevicePropertyName)
|
public static T? GetDeviceProperty<T>(this IPortableDeviceManager manager, string pszPnPDeviceID, string pszDevicePropertyName)
|
||||||
{
|
{
|
||||||
var sz = 0U;
|
var sz = 0U;
|
||||||
manager.GetDeviceProperty(pszPnPDeviceID, pszDevicePropertyName, default, ref sz, out _);
|
manager.GetDeviceProperty(pszPnPDeviceID, pszDevicePropertyName, default, ref sz, out _);
|
||||||
|
@ -2672,7 +2672,7 @@ public static partial class PortableDeviceApi
|
||||||
return default;
|
return default;
|
||||||
using var mem = new SafeCoTaskMemHandle(sz);
|
using var mem = new SafeCoTaskMemHandle(sz);
|
||||||
manager.GetDeviceProperty(pszPnPDeviceID, pszDevicePropertyName, mem, ref sz, out var type);
|
manager.GetDeviceProperty(pszPnPDeviceID, pszDevicePropertyName, mem, ref sz, out var type);
|
||||||
return (T)type.GetValue(mem, mem.Size);
|
return (T?)type.GetValue(mem, mem.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Retrieves a list of portable devices connected to the computer.</summary>
|
/// <summary>Retrieves a list of portable devices connected to the computer.</summary>
|
||||||
|
@ -2710,7 +2710,7 @@ public static partial class PortableDeviceApi
|
||||||
if (cnt == 0)
|
if (cnt == 0)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
if (hr.Failed && hr != HRESULT.HRESULT_FROM_WIN32(Win32Error.ERROR_INSUFFICIENT_BUFFER))
|
if (hr.Failed && hr != HRESULT.HRESULT_FROM_WIN32(Win32Error.ERROR_INSUFFICIENT_BUFFER))
|
||||||
throw hr.GetException();
|
throw hr.GetException()!;
|
||||||
var sb = new StringBuilder((int)cnt + 1);
|
var sb = new StringBuilder((int)cnt + 1);
|
||||||
if (cnt > 0)
|
if (cnt > 0)
|
||||||
func(devId, sb, ref cnt).ThrowIfFailed();
|
func(devId, sb, ref cnt).ThrowIfFailed();
|
||||||
|
@ -2724,7 +2724,7 @@ public static partial class PortableDeviceApi
|
||||||
if (cnt == 0)
|
if (cnt == 0)
|
||||||
return new string[0];
|
return new string[0];
|
||||||
if (hr.Failed && hr != HRESULT.HRESULT_FROM_WIN32(Win32Error.ERROR_INSUFFICIENT_BUFFER))
|
if (hr.Failed && hr != HRESULT.HRESULT_FROM_WIN32(Win32Error.ERROR_INSUFFICIENT_BUFFER))
|
||||||
throw hr.GetException();
|
throw hr.GetException()!;
|
||||||
var devices = new string[cnt];
|
var devices = new string[cnt];
|
||||||
if (cnt > 0)
|
if (cnt > 0)
|
||||||
func(devices, ref cnt).ThrowIfFailed();
|
func(devices, ref cnt).ThrowIfFailed();
|
||||||
|
|
|
@ -174,8 +174,8 @@ public static partial class PortableDeviceApi
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceconnectapi/nf-portabledeviceconnectapi-iportabledeviceconnector-connect
|
// https://docs.microsoft.com/en-us/windows/win32/api/portabledeviceconnectapi/nf-portabledeviceconnectapi-iportabledeviceconnector-connect
|
||||||
// HRESULT Connect( [in, optional] IConnectionRequestCallback *pCallback );
|
// HRESULT Connect( [in, optional] IConnectionRequestCallback? *pCallback );
|
||||||
void Connect([Optional] IConnectionRequestCallback pCallback);
|
void Connect([Optional] IConnectionRequestCallback? pCallback);
|
||||||
|
|
||||||
/// <summary>The <c>Disconnect</c> method sends an asynchronous disconnect request to the MTP/Bluetooth device.</summary>
|
/// <summary>The <c>Disconnect</c> method sends an asynchronous disconnect request to the MTP/Bluetooth device.</summary>
|
||||||
/// <param name="pCallback">A pointer to an IConnectionRequestCallback interface.</param>
|
/// <param name="pCallback">A pointer to an IConnectionRequestCallback interface.</param>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using static Vanara.PInvoke.Ole32;
|
using static Vanara.PInvoke.Ole32;
|
||||||
|
@ -19,18 +20,18 @@ public static class PortableDeviceExtensions
|
||||||
/// <param name="parentType">The type in which <paramref name="cmd"/> is defined, if not other than <see cref="Vanara.PInvoke.PortableDeviceApi"/>.</param>
|
/// <param name="parentType">The type in which <paramref name="cmd"/> is defined, if not other than <see cref="Vanara.PInvoke.PortableDeviceApi"/>.</param>
|
||||||
/// <returns>A dictionary containing the result values.</returns>
|
/// <returns>A dictionary containing the result values.</returns>
|
||||||
/// <exception cref="System.InvalidOperationException">Supplied PROPERTYKEY is not a recognized WPD command.</exception>
|
/// <exception cref="System.InvalidOperationException">Supplied PROPERTYKEY is not a recognized WPD command.</exception>
|
||||||
public static IReadOnlyDictionary<PROPERTYKEY, object> ExtractResults(this IPortableDeviceValues results, in PROPERTYKEY cmd, Type parentType = null)
|
public static IReadOnlyDictionary<PROPERTYKEY, object?> ExtractResults(this IPortableDeviceValues results, in PROPERTYKEY cmd, Type? parentType = null)
|
||||||
{
|
{
|
||||||
if (!cmd.TryGetCommandInfo(out _, out _, out var rAttrs, parentType))
|
if (!cmd.TryGetCommandInfo(out _, out _, out var rAttrs, parentType))
|
||||||
throw new InvalidOperationException("Supplied PROPERTYKEY is not a recognized WPD command.");
|
throw new InvalidOperationException("Supplied PROPERTYKEY is not a recognized WPD command.");
|
||||||
var ret = new Dictionary<PROPERTYKEY, object>();
|
var ret = new Dictionary<PROPERTYKEY, object?>();
|
||||||
foreach (var a in rAttrs)
|
foreach (var a in rAttrs)
|
||||||
{
|
{
|
||||||
PROPVARIANT pv = new();
|
PROPVARIANT pv = new();
|
||||||
try { pv = results.GetValue(a.Property); } catch { }
|
try { pv = results.GetValue(a.Property); } catch { }
|
||||||
ret.Add(a.Property, pv.Value);
|
ret.Add(a.Property, pv.Value);
|
||||||
}
|
}
|
||||||
return (IReadOnlyDictionary<PROPERTYKEY, object>)ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Sends a command to the device and retrieves the results synchronously.</summary>
|
/// <summary>Sends a command to the device and retrieves the results synchronously.</summary>
|
||||||
|
@ -38,7 +39,7 @@ public static class PortableDeviceExtensions
|
||||||
/// <param name="cmd">The command's PROPERTYKEY.</param>
|
/// <param name="cmd">The command's PROPERTYKEY.</param>
|
||||||
/// <param name="pkResult">The PROPERTYKEY of the result value to return.</param>
|
/// <param name="pkResult">The PROPERTYKEY of the result value to return.</param>
|
||||||
/// <returns>The value returned in <paramref name="pkResult"/>.</returns>
|
/// <returns>The value returned in <paramref name="pkResult"/>.</returns>
|
||||||
public static object SendCommand(this IPortableDevice device, in PROPERTYKEY cmd, in PROPERTYKEY pkResult) =>
|
public static object? SendCommand(this IPortableDevice device, in PROPERTYKEY cmd, in PROPERTYKEY pkResult) =>
|
||||||
device.SendCommand(cmd).GetValue(pkResult).Value;
|
device.SendCommand(cmd).GetValue(pkResult).Value;
|
||||||
|
|
||||||
/// <summary>Sends a command to the device and retrieves the results synchronously.</summary>
|
/// <summary>Sends a command to the device and retrieves the results synchronously.</summary>
|
||||||
|
@ -49,7 +50,7 @@ public static class PortableDeviceExtensions
|
||||||
/// cref="IPortableDevice.SendCommand(uint, IPortableDeviceValues)"/>.
|
/// cref="IPortableDevice.SendCommand(uint, IPortableDeviceValues)"/>.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The <see cref="IPortableDeviceValues"/> instance returned by <see cref="IPortableDevice.SendCommand(uint, IPortableDeviceValues)"/>.</returns>
|
/// <returns>The <see cref="IPortableDeviceValues"/> instance returned by <see cref="IPortableDevice.SendCommand(uint, IPortableDeviceValues)"/>.</returns>
|
||||||
public static IPortableDeviceValues SendCommand(this IPortableDevice device, in PROPERTYKEY cmd, Action<IPortableDeviceValues> addParams = null)
|
public static IPortableDeviceValues SendCommand(this IPortableDevice device, in PROPERTYKEY cmd, Action<IPortableDeviceValues>? addParams = null)
|
||||||
{
|
{
|
||||||
IPortableDeviceValues cmdParams = new();
|
IPortableDeviceValues cmdParams = new();
|
||||||
cmdParams.SetCommandPKey(cmd);
|
cmdParams.SetCommandPKey(cmd);
|
||||||
|
@ -104,7 +105,7 @@ public static class PortableDeviceExtensions
|
||||||
/// The reflection based lookup is cached so that subsequent lookups are accelerated. As such, expect a slower response the first
|
/// The reflection based lookup is cached so that subsequent lookups are accelerated. As such, expect a slower response the first
|
||||||
/// time this method is called with each unique <paramref name="parentType"/>.
|
/// time this method is called with each unique <paramref name="parentType"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static bool TryGetCommandInfo(this PROPERTYKEY key, out WPDCommandAttribute cmd, out WPDCommandParamAttribute[] param, out WPDCommandResultAttribute[] result, Type parentType = null)
|
public static bool TryGetCommandInfo(this PROPERTYKEY key, [NotNullWhen(true)] out WPDCommandAttribute? cmd, [NotNullWhen(true)] out WPDCommandParamAttribute[]? param, [NotNullWhen(true)] out WPDCommandResultAttribute[]? result, Type? parentType = null)
|
||||||
{
|
{
|
||||||
var pi = GetPI(key, parentType);
|
var pi = GetPI(key, parentType);
|
||||||
parentType ??= typeof(Vanara.PInvoke.PortableDeviceApi);
|
parentType ??= typeof(Vanara.PInvoke.PortableDeviceApi);
|
||||||
|
@ -124,7 +125,7 @@ public static class PortableDeviceExtensions
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static PROPERTYKEY? GetKeyFromName(string keyName, Type parentType = null)
|
internal static PROPERTYKEY? GetKeyFromName(string keyName, Type? parentType = null)
|
||||||
{
|
{
|
||||||
parentType ??= typeof(Vanara.PInvoke.PortableDeviceApi);
|
parentType ??= typeof(Vanara.PInvoke.PortableDeviceApi);
|
||||||
var kv = GetDict(parentType).FirstOrDefault(kv => kv.Value.Name == keyName);
|
var kv = GetDict(parentType).FirstOrDefault(kv => kv.Value.Name == keyName);
|
||||||
|
@ -135,13 +136,13 @@ public static class PortableDeviceExtensions
|
||||||
{
|
{
|
||||||
if (!gReversePKLookup.TryGetValue(type, out var dict))
|
if (!gReversePKLookup.TryGetValue(type, out var dict))
|
||||||
{
|
{
|
||||||
dict = type.GetProperties(BindStPub).ToDictionary(m => (PROPERTYKEY)m.GetValue(null, null));
|
dict = type.GetProperties(BindStPub).ToDictionary(m => (PROPERTYKEY)m.GetValue(null, null)!);
|
||||||
gReversePKLookup.Add(type, dict);
|
gReversePKLookup.Add(type, dict);
|
||||||
}
|
}
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyInfo GetPI(in PROPERTYKEY key, Type parentType = null)
|
private static PropertyInfo? GetPI(in PROPERTYKEY key, Type? parentType = null)
|
||||||
{
|
{
|
||||||
parentType ??= typeof(Vanara.PInvoke.PortableDeviceApi);
|
parentType ??= typeof(Vanara.PInvoke.PortableDeviceApi);
|
||||||
return GetDict(parentType).TryGetValue(key, out var pi) ? pi : null;
|
return GetDict(parentType).TryGetValue(key, out var pi) ? pi : null;
|
||||||
|
|
|
@ -203,7 +203,7 @@ public static partial class PortableDeviceApi
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/wpd_sdk/iportabledevicevalues-getat HRESULT GetAt( [in] const DWORD index,
|
// https://docs.microsoft.com/en-us/windows/win32/wpd_sdk/iportabledevicevalues-getat HRESULT GetAt( [in] const DWORD index,
|
||||||
// [in, out] PROPERTYKEY *pKey, [in, out] PROPVARIANT *pValue );
|
// [in, out] PROPERTYKEY *pKey, [in, out] PROPVARIANT *pValue );
|
||||||
void GetAt(uint index, out PROPERTYKEY pKey, [Out] PROPVARIANT pValue);
|
void GetAt(uint index, out PROPERTYKEY pKey, [Out] PROPVARIANT? pValue);
|
||||||
|
|
||||||
/// <summary>The <c>SetValue</c> method adds a new <c>PROPVARIANT</c> value or overwrites an existing one.</summary>
|
/// <summary>The <c>SetValue</c> method adds a new <c>PROPVARIANT</c> value or overwrites an existing one.</summary>
|
||||||
/// <param name="key">A <c>REFPROPERTYKEY</c> that specifies the item to create or overwrite.</param>
|
/// <param name="key">A <c>REFPROPERTYKEY</c> that specifies the item to create or overwrite.</param>
|
||||||
|
|
|
@ -11,8 +11,10 @@ namespace Vanara.PInvoke.Tests;
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class PortableDeviceApiTests
|
public class PortableDeviceApiTests
|
||||||
{
|
{
|
||||||
IPortableDevice device = null;
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
IPortableDevice device;
|
||||||
IPortableDeviceManager manager;
|
IPortableDeviceManager manager;
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
static readonly Ole32.PROPERTYKEY eventNameProp = new(Guid.NewGuid(), 1);
|
static readonly Ole32.PROPERTYKEY eventNameProp = new(Guid.NewGuid(), 1);
|
||||||
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
|
@ -28,8 +30,6 @@ namespace Vanara.PInvoke.Tests;
|
||||||
public void _TearDown()
|
public void _TearDown()
|
||||||
{
|
{
|
||||||
device?.Close();
|
device?.Close();
|
||||||
device = null;
|
|
||||||
manager = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -47,10 +47,10 @@ namespace Vanara.PInvoke.Tests;
|
||||||
|
|
||||||
class EventCallback : IPortableDeviceEventCallback
|
class EventCallback : IPortableDeviceEventCallback
|
||||||
{
|
{
|
||||||
void IPortableDeviceEventCallback.OnEvent(IPortableDeviceValues pEventParameters)
|
void IPortableDeviceEventCallback.OnEvent(IPortableDeviceValues? pEventParameters)
|
||||||
{
|
{
|
||||||
var evtName = pEventParameters.GetStringValue(eventNameProp);
|
var evtName = pEventParameters?.GetStringValue(eventNameProp);
|
||||||
if (EventWaitHandle.TryOpenExisting(evtName, out var evt))
|
if (evtName is not null && EventWaitHandle.TryOpenExisting(evtName, out var evt))
|
||||||
evt.Set();
|
evt.Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,13 +106,13 @@ namespace Vanara.PInvoke.Tests;
|
||||||
{
|
{
|
||||||
var caps = device.Capabilities();
|
var caps = device.Capabilities();
|
||||||
|
|
||||||
foreach (var catid in caps.GetFunctionalCategories().Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid.Value))
|
foreach (var catid in caps.GetFunctionalCategories().Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid!.Value))
|
||||||
{
|
{
|
||||||
TestContext.WriteLine(GetPI(catid, "WPD_FUNCTIONAL_CATEGORY_")?.Name ?? catid.ToString());
|
TestContext.WriteLine(GetPI(catid, "WPD_FUNCTIONAL_CATEGORY_")?.Name ?? catid.ToString());
|
||||||
foreach (var type in caps.GetSupportedContentTypes(catid).Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid.Value))
|
foreach (var type in caps.GetSupportedContentTypes(catid).Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid!.Value))
|
||||||
{
|
{
|
||||||
TestContext.WriteLine(" t: " + (GetPI(type, "WPD_CONTENT_TYPE_")?.Name ?? type.ToString()));
|
TestContext.WriteLine(" t: " + (GetPI(type, "WPD_CONTENT_TYPE_")?.Name ?? type.ToString()));
|
||||||
foreach (var fmt in caps.GetSupportedFormats(type).Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid.Value))
|
foreach (var fmt in caps.GetSupportedFormats(type).Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid!.Value))
|
||||||
TestContext.WriteLine(" f: " + (GetPI(fmt, "WPD_OBJECT_FORMAT_")?.Name ?? type.ToString()));
|
TestContext.WriteLine(" f: " + (GetPI(fmt, "WPD_OBJECT_FORMAT_")?.Name ?? type.ToString()));
|
||||||
}
|
}
|
||||||
foreach (var obj in caps.GetFunctionalObjects(catid).Enumerate().Where(pv => pv.VarType == VarEnum.VT_LPWSTR).Select(pv => pv.pwszVal))
|
foreach (var obj in caps.GetFunctionalObjects(catid).Enumerate().Where(pv => pv.VarType == VarEnum.VT_LPWSTR).Select(pv => pv.pwszVal))
|
||||||
|
@ -173,7 +173,7 @@ namespace Vanara.PInvoke.Tests;
|
||||||
{
|
{
|
||||||
var caps = device.Capabilities();
|
var caps = device.Capabilities();
|
||||||
|
|
||||||
foreach (var evt in caps.GetSupportedEvents().Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid.Value))
|
foreach (var evt in caps.GetSupportedEvents().Enumerate().Where(pv => pv.VarType == VarEnum.VT_CLSID).Select(pv => pv.puuid!.Value))
|
||||||
{
|
{
|
||||||
TestContext.WriteLine(GetPI(evt, "WPD_EVENT_")?.Name ?? evt.ToString());
|
TestContext.WriteLine(GetPI(evt, "WPD_EVENT_")?.Name ?? evt.ToString());
|
||||||
foreach (var opt in caps.GetEventOptions(evt).Enumerate())
|
foreach (var opt in caps.GetEventOptions(evt).Enumerate())
|
||||||
|
@ -181,9 +181,9 @@ namespace Vanara.PInvoke.Tests;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyInfo GetPI<T>(T t, string prefix) =>
|
private static PropertyInfo? GetPI<T>(T t, string prefix) =>
|
||||||
typeof(PortableDeviceApi).GetProperties(BindingFlags.Public | BindingFlags.Static).
|
typeof(PortableDeviceApi).GetProperties(BindingFlags.Public | BindingFlags.Static).
|
||||||
FirstOrDefault(pi => pi.Name.StartsWith(prefix) && pi.PropertyType.Equals(typeof(T)) && t.Equals(pi.GetValue(null)));
|
FirstOrDefault(pi => pi.Name.StartsWith(prefix) && pi.PropertyType.Equals(typeof(T)) && Equals(t, pi.GetValue(null)));
|
||||||
|
|
||||||
private IPortableDeviceValues GetClientInfo(bool readOnly = true)
|
private IPortableDeviceValues GetClientInfo(bool readOnly = true)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue