mirror of https://github.com/dahall/Vanara.git
Added swdevices.h methods and fixed solution build
parent
c4e2e367f6
commit
a954e70b5a
|
@ -0,0 +1,415 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Vanara.InteropServices;
|
||||
|
||||
namespace Vanara.PInvoke
|
||||
{
|
||||
/// <summary>Items from the CfgMgr32.dll</summary>
|
||||
public static partial class CfgMgr32
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a device with backing in the registry and allows the caller to then make calls to Software Device API functions with
|
||||
/// the hSwDevice handle.
|
||||
/// </summary>
|
||||
/// <param name="hSwDevice">The handle for the software device.</param>
|
||||
/// <param name="CreateResult">An HRESULT that indicates if the enumeration of the software device was successful.</param>
|
||||
/// <param name="pContext">The context that was optionally supplied by the client app to SwDeviceCreate.</param>
|
||||
/// <param name="pszDeviceInstanceId">The device instance ID that PnP assigned to the device.</param>
|
||||
/// <returns>None</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The operating system calls the <c>SW_DEVICE_CREATE_CALLBACK</c> callback function after PnP enumerates the device. After the
|
||||
/// callback function is called, the device has backing in the registry and calls to Software Device API functions can be made by
|
||||
/// using the hSwDevice handle. You can also use other APIs that work with devices for the device that is created.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// PnP enumeration of a device is the first step that a device undergoes. After PnP enumeration of the device, the device only has
|
||||
/// registry backing, and you can set properties against the device. Just because PnP enumerated the device, the device hasn't
|
||||
/// started yet, and no driver for the device has registered or enabled interfaces yet. In many cases, we recommend that apps wait
|
||||
/// for device-interface arrival if they want to use the device.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <c>Note</c> The callback function supplies the device instance ID for the created device. We recommend that callers of the
|
||||
/// Software Device API not try to guess at or construct the device instance ID themselves; always use the value provided by the
|
||||
/// callback function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The callback function will execute on an arbitrary thread-pool thread. Client apps can perform as much work as needed in the
|
||||
/// callback function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// In Windows 8, you can't call SwDeviceClose inside the callback function. Doing so will cause a deadlock. Be careful of releasing
|
||||
/// a ref counted object that will call <c>SwDeviceClose</c> when its destructor runs. In Windows 8.1, this restriction is lifted,
|
||||
/// and you can call <c>SwDeviceClose</c> inside the callback function.
|
||||
/// </para>
|
||||
/// <para>Always check the HRESULT that is passed to CreateResult to make sure PnP was able to enumerate the device.</para>
|
||||
/// </remarks>
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/swdevice/nc-swdevice-sw_device_create_callback SW_DEVICE_CREATE_CALLBACK
|
||||
// SwDeviceCreateCallback; void SwDeviceCreateCallback( HSWDEVICE hSwDevice, HRESULT CreateResult, PVOID pContext, PCWSTR
|
||||
// pszDeviceInstanceId ) {...}
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
[PInvokeData("swdevice.h", MSDNShortId = "NC:swdevice.SW_DEVICE_CREATE_CALLBACK")]
|
||||
public delegate void SW_DEVICE_CREATE_CALLBACK([In] HSWDEVICE hSwDevice, HRESULT CreateResult, [In, Optional] IntPtr pContext, [Optional, MarshalAs(UnmanagedType.LPWStr)] string pszDeviceInstanceId);
|
||||
|
||||
/// <summary>Specifies capabilities of the software device.</summary>
|
||||
[PInvokeData("swdevicedef.h", MSDNShortId = "NS:swdevicedef._SW_DEVICE_CREATE_INFO")]
|
||||
[Flags]
|
||||
public enum SW_DEVICE_CAPABILITIES
|
||||
{
|
||||
/// <summary>No capabilities have been specified.</summary>
|
||||
SWDeviceCapabilitiesNone = 0x00000000,
|
||||
|
||||
/// <summary>
|
||||
/// This bit specifies that the device is removable from its parent. Setting this flag is equivalent to a bus driver setting the
|
||||
/// Removable member of the DEVICE_CAPABILTIES structure for a PDO.
|
||||
/// </summary>
|
||||
SWDeviceCapabilitiesRemovable = 0x00000001,
|
||||
|
||||
/// <summary>
|
||||
/// This bit suppresses UI that would normally be shown during installation. Setting this flag is equivalent to a bus driver
|
||||
/// setting the SilentInstall member of the DEVICE_CAPABILTIES structure for a PDO.
|
||||
/// </summary>
|
||||
SWDeviceCapabilitiesSilentInstall = 0x00000002,
|
||||
|
||||
/// <summary>
|
||||
/// This bit prevents the device from being displayed in some UI. Setting this flag is equivalent to a bus driver setting the
|
||||
/// NoDisplayInUI member of the DEVICE_CAPABILTIES structure for a PDO.
|
||||
/// </summary>
|
||||
SWDeviceCapabilitiesNoDisplayInUI = 0x00000004,
|
||||
|
||||
/// <summary>
|
||||
/// Specify this bit when the client wants a driver to be loaded on the device and when this driver is required for correct
|
||||
/// function of the client’s feature. When this bit is specified, at least one of pszzHardwareIds or pszzCompatibleIds must be
|
||||
/// filled in. If this bit is specified and if a driver can't be found, the device shows a yellow bang in Device Manager to
|
||||
/// indicate that the device has a problem, and Troubleshooters flag this as a device with a problem. Setting this bit is
|
||||
/// equivalent to a bus driver not setting the RawDeviceOK member of the DEVICE_CAPABILTIES structure for a PDO. When this bit
|
||||
/// is specified, the driver owns creating interfaces for the device, and you can't call SwDeviceInterfaceRegister for the device.
|
||||
/// </summary>
|
||||
SWDeviceCapabilitiesDriverRequired = 0x00000008
|
||||
}
|
||||
|
||||
[PInvokeData("swdevicedef.h")]
|
||||
public enum SW_DEVICE_LIFETIME
|
||||
{
|
||||
SWDeviceLifetimeHandle,
|
||||
SWDeviceLifetimeParentPresent,
|
||||
SWDeviceLifetimeMax
|
||||
}
|
||||
|
||||
/// <summary>Closes the software device handle. When the handle is closed, PnP will initiate the process of removing the device.</summary>
|
||||
/// <param name="hSwDevice">The <c>HSWDEVICE</c> handle to close.</param>
|
||||
/// <returns>None</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// After <c>SwDeviceClose</c> returns, the operating system is guaranteed to not call the SW_DEVICE_CREATE_CALLBACK callback
|
||||
/// function, and any calls to Software Device API functions that were in progress are guaranteed to have completed.
|
||||
/// </para>
|
||||
/// <para>You can call <c>SwDeviceClose</c> at any time even if the callback function hasn't been called yet.</para>
|
||||
/// <para>
|
||||
/// In Windows 8, you can't call <c>SwDeviceClose</c> inside the SW_DEVICE_CREATE_CALLBACK callback function. Doing so will cause a
|
||||
/// deadlock. Be careful of releasing a ref counted object that will call <c>SwDeviceClose</c> when its destructor runs. In Windows
|
||||
/// 8.1, this restriction is lifted, and you can call <c>SwDeviceClose</c> inside the callback function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// By calling <c>SwDeviceClose</c>, you initiate the process of removing a device from PnP. The call to <c>SwDeviceClose</c>
|
||||
/// returns before this removal is complete. But you can safely call SwDeviceCreate immediately after <c>SwDeviceClose</c>. The new
|
||||
/// create will be queued until the previous removal processing completes, and then the device will be re-created.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// PnP removal makes the device "Not present." PnP removal of a device is the same us unplugging a USB device. All the persisted
|
||||
/// property state for the device remains in memory.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/swdevice/nf-swdevice-swdeviceclose void SwDeviceClose( HSWDEVICE hSwDevice );
|
||||
[DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
|
||||
[PInvokeData("swdevice.h", MSDNShortId = "NF:swdevice.SwDeviceClose")]
|
||||
public static extern void SwDeviceClose(HSWDEVICE hSwDevice);
|
||||
|
||||
/// <summary>Provides a handle to a software device.</summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct HSWDEVICE : IHandle
|
||||
{
|
||||
private readonly IntPtr handle;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="HSWDEVICE"/> struct.</summary>
|
||||
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||
public HSWDEVICE(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||
|
||||
/// <summary>Returns an invalid handle by instantiating a <see cref="HSWDEVICE"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||
public static HSWDEVICE NULL => new(IntPtr.Zero);
|
||||
|
||||
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||
public bool IsNull => handle == IntPtr.Zero;
|
||||
|
||||
/// <summary>Performs an explicit conversion from <see cref="HSWDEVICE"/> to <see cref="IntPtr"/>.</summary>
|
||||
/// <param name="h">The handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static explicit operator IntPtr(HSWDEVICE h) => h.handle;
|
||||
|
||||
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HSWDEVICE"/>.</summary>
|
||||
/// <param name="h">The pointer to a handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator HSWDEVICE(IntPtr h) => new(h);
|
||||
|
||||
/// <summary>Implements the operator !=.</summary>
|
||||
/// <param name="h1">The first handle.</param>
|
||||
/// <param name="h2">The second handle.</param>
|
||||
/// <returns>The result of the operator.</returns>
|
||||
public static bool operator !=(HSWDEVICE h1, HSWDEVICE h2) => !(h1 == h2);
|
||||
|
||||
/// <summary>Implements the operator ==.</summary>
|
||||
/// <param name="h1">The first handle.</param>
|
||||
/// <param name="h2">The second handle.</param>
|
||||
/// <returns>The result of the operator.</returns>
|
||||
public static bool operator ==(HSWDEVICE h1, HSWDEVICE h2) => h1.Equals(h2);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => obj is HSWDEVICE h && handle == h.handle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => handle.GetHashCode();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IntPtr DangerousGetHandle() => handle;
|
||||
}
|
||||
|
||||
/// <summary>Describes info that PnP uses to create the software device.</summary>
|
||||
/// <remarks>
|
||||
/// You can only specify this info at creation time, and you can't later call the Software Device API to modify this info, by
|
||||
/// setting properties, for example.
|
||||
/// </remarks>
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/swdevicedef/ns-swdevicedef-sw_device_create_info typedef struct
|
||||
// _SW_DEVICE_CREATE_INFO { ULONG cbSize; PCWSTR pszInstanceId; PCZZWSTR pszzHardwareIds; PCZZWSTR pszzCompatibleIds; const GUID
|
||||
// *pContainerId; ULONG CapabilityFlags; PCWSTR pszDeviceDescription; PCWSTR pszDeviceLocation; const SECURITY_DESCRIPTOR
|
||||
// *pSecurityDescriptor; } SW_DEVICE_CREATE_INFO, *PSW_DEVICE_CREATE_INFO;
|
||||
[PInvokeData("swdevicedef.h", MSDNShortId = "NS:swdevicedef._SW_DEVICE_CREATE_INFO")]
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct SW_DEVICE_CREATE_INFO
|
||||
{
|
||||
/// <summary>The size in bytes of this structure. Use it as a version field. Initialize it to sizeof(SW_DEVICE_CREATE_INFO).</summary>
|
||||
public uint cbSize;
|
||||
|
||||
/// <summary>
|
||||
/// A string that represents the instance ID portion of the device instance ID. This value is used for IRP_MN_QUERY_ID
|
||||
/// <c>BusQueryInstanceID</c>. 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.
|
||||
/// </summary>
|
||||
public string pszInstanceId;
|
||||
|
||||
/// <summary>
|
||||
/// A list of strings for the hardware IDs for the software device. This value is used for IRP_MN_QUERY_ID
|
||||
/// <c>BusQueryHardwareIDs</c>. If a client expects a driver or device metadata to bind to the device, the client specifies
|
||||
/// hardware IDs.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler))]
|
||||
public string[] pszzHardwareIds;
|
||||
|
||||
/// <summary>
|
||||
/// A list of strings for the compatible IDs for the software device. This value is used for IRP_MN_QUERY_ID
|
||||
/// <c>BusQueryCompatibleIDs</c>. If a client expects a class driver to load, the client specifies compatible IDs that match the
|
||||
/// class driver. If a driver isn't needed, we recommend to specify a compatible ID to classify the type of software device. In
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler))]
|
||||
public string[] pszzCompatibleIds;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// <c>BusQueryContainerIDs</c>. For typical situations, we recommend to set this member to <c>NULL</c> and use the
|
||||
/// <c>SWDeviceCapabilitiesRemovable</c> flag to control whether the device inherits the parent's container ID or if PnP assigns
|
||||
/// a new random container ID. If the client needs to explicitly control the container ID, specify a <c>GUID</c> in the variable
|
||||
/// that this member points to.
|
||||
/// </summary>
|
||||
public GuidPtr pContainerId;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A combination of <c>SW_DEVICE_CAPABILITIES</c> values that are combined by using a bitwise OR operation. The resulting value
|
||||
/// specifies capabilities of the software device. The capability that you can specify when you create a software device are a
|
||||
/// subset of the capabilities that a bus driver can specify by using the <c>DEVICE_CAPABILTIES</c> structure. Only capabilities
|
||||
/// that make sense to allow changing for a software only device are supported. The rest receive appropriate default values.
|
||||
/// Here are possible values:
|
||||
/// </para>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Value</term>
|
||||
/// <term>Meaning</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>SWDeviceCapabilitiesNone 0x00000000</term>
|
||||
/// <term>No capabilities have been specified.</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>SWDeviceCapabilitiesRemovable 0x00000001</term>
|
||||
/// <term>
|
||||
/// This bit specifies that the device is removable from its parent. Setting this flag is equivalent to a bus driver setting the
|
||||
/// Removable member of the DEVICE_CAPABILTIES structure for a PDO.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>SWDeviceCapabilitiesSilentInstall 0x00000002</term>
|
||||
/// <term>
|
||||
/// This bit suppresses UI that would normally be shown during installation. Setting this flag is equivalent to a bus driver
|
||||
/// setting the SilentInstall member of the DEVICE_CAPABILTIES structure for a PDO.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>SWDeviceCapabilitiesNoDisplayInUI 0x00000004</term>
|
||||
/// <term>
|
||||
/// This bit prevents the device from being displayed in some UI. Setting this flag is equivalent to a bus driver setting the
|
||||
/// NoDisplayInUI member of the DEVICE_CAPABILTIES structure for a PDO.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>SWDeviceCapabilitiesDriverRequired 0x00000008</term>
|
||||
/// <term>
|
||||
/// Specify this bit when the client wants a driver to be loaded on the device and when this driver is required for correct
|
||||
/// function of the client’s feature. When this bit is specified, at least one of pszzHardwareIds or pszzCompatibleIds must be
|
||||
/// filled in. If this bit is specified and if a driver can't be found, the device shows a yellow bang in Device Manager to
|
||||
/// indicate that the device has a problem, and Troubleshooters flag this as a device with a problem. Setting this bit is
|
||||
/// equivalent to a bus driver not setting the RawDeviceOK member of the DEVICE_CAPABILTIES structure for a PDO. When this bit
|
||||
/// is specified, the driver owns creating interfaces for the device, and you can't call SwDeviceInterfaceRegister for the device.
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public SW_DEVICE_CAPABILITIES CapabilityFlags;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A string that contains the text that is displayed for the device name in the UI. This value is used for
|
||||
/// IRP_MN_QUERY_DEVICE_TEXT <c>DeviceTextDescription</c>.
|
||||
/// </para>
|
||||
/// <para><c>Note</c>
|
||||
/// <para></para>
|
||||
/// When an INF is matched against the device, the name from the INF overrides this name unless steps are taken to preserve this name.
|
||||
/// <para></para>
|
||||
/// We recommend that this string be a reference to a localizable resource. For the syntax of referencing resources, see DEVPROP_TYPE_STRING_INDIRECT.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public string pszDeviceDescription;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A string that contains the text that is displayed for the device location in the UI. This value is used for
|
||||
/// IRP_MN_QUERY_DEVICE_TEXT <c>DeviceTextLocationInformation</c>.
|
||||
/// </para>
|
||||
/// <para><c>Note</c> Specifying a location is uncommon.</para>
|
||||
/// </summary>
|
||||
public string pszDeviceLocation;
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to a SECURITY_DESCRIPTOR structure that contains the security information associated with the software device. If
|
||||
/// this member is <c>NULL</c>, the I/O Manager assigns the default security descriptor to the device. If a custom security
|
||||
/// descriptor is needed, specify a self-relative security descriptor.
|
||||
/// </summary>
|
||||
public PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
||||
}
|
||||
|
||||
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HSWDEVICE"/> that is disposed using <see cref="SwDeviceClose"/>.</summary>
|
||||
public class SafeHSWDEVICE : SafeHANDLE
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="SafeHSWDEVICE"/> class and assigns an existing handle.</summary>
|
||||
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||
/// <param name="ownsHandle">
|
||||
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||
/// </param>
|
||||
public SafeHSWDEVICE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafeHSWDEVICE"/> class.</summary>
|
||||
private SafeHSWDEVICE() : base() { }
|
||||
|
||||
/// <summary>Performs an implicit conversion from <see cref="SafeHSWDEVICE"/> to <see cref="HSWDEVICE"/>.</summary>
|
||||
/// <param name="h">The safe handle instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator HSWDEVICE(SafeHSWDEVICE h) => h.handle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool InternalReleaseHandle() { SwDeviceClose(handle); return true; }
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>Initiates the enumeration of a software device.</summary>
|
||||
/// <param name="pszEnumeratorName">
|
||||
/// A string that names the enumerator of the software device. Choose a name that represents the component that enumerates the devices.
|
||||
/// </param>
|
||||
/// <param name="pszParentDeviceInstance">
|
||||
/// <para>A string that specifies the device instance ID of the device that is the parent of the software device.</para>
|
||||
/// <para>
|
||||
/// This can be HTREE\ROOT\0, but we recommend to keep children of the root device to a minimum. We also recommend that the
|
||||
/// preferred parent of a software device be a real device that the software device is extending the functionality for. In
|
||||
/// situations where a software device doesn't have such a natural parent, create a device as a child of the root that can collect
|
||||
/// all the software devices that a component will enumerate; then, enumerate the actual software devices as children of this device
|
||||
/// grouping node. This keeps the children of the root device to a manageable number.
|
||||
/// </para>
|
||||
/// </param>
|
||||
/// <param name="pCreateInfo">A pointer to a SW_DEVICE_CREATE_INFO structure that describes info that PnP uses to create the device.</param>
|
||||
/// <param name="cPropertyCount">The number of DEVPROPERTY structures in the pProperties array.</param>
|
||||
/// <param name="pProperties">
|
||||
/// An optional array of DEVPROPERTY structures. These properties are set on the device after it is created but before a
|
||||
/// notification that the device has been created are sent. For more info, see Remarks. This pointer can be <c>NULL</c>.
|
||||
/// </param>
|
||||
/// <param name="pCallback">
|
||||
/// The SW_DEVICE_CREATE_CALLBACK callback function that the operating system calls after PnP enumerates the device.
|
||||
/// </param>
|
||||
/// <param name="pContext">
|
||||
/// An optional client context that the operating system passes to the callback function. This pointer can be <c>NULL</c>.
|
||||
/// </param>
|
||||
/// <param name="phSwDevice">
|
||||
/// A pointer to a variable that receives the <c>HSWDEVICE</c> handle that represents the device. Call SwDeviceClose to close this
|
||||
/// handle after the client app wants PnP to remove the device.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// S_OK is returned if device enumeration was successfully initiated. This does not mean that the device has been successfully
|
||||
/// enumerated. Check the CreateResult parameter of the SW_DEVICE_CREATE_CALLBACK callback function to determine if the device was
|
||||
/// successfully enumerated.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para><c>SwDeviceCreate</c> returns a handle that represents the device. After this handle is closed, PnP will remove the device.</para>
|
||||
/// <para>The calling process must have Administrator access in order to initiate the enumeration of a software device.</para>
|
||||
/// <para>
|
||||
/// PnP forms the device instance ID of a software device as "SWD&lt;pszEnumeratorName>&lt;pszInstanceId>," but this
|
||||
/// string might change or PnP might decorate the name. Always get the device instance ID from the callback function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// There is a subtle difference between properties that are set as part of a <c>SwDeviceCreate</c> call and properties that are
|
||||
/// later set by calling SwDevicePropertySet. Properties that are set as part of <c>SwDeviceCreate</c> are stored in memory; if the
|
||||
/// device is uninstalled or a null driver wipes out the property stores, these properties are written out again by the Software
|
||||
/// Device API feature when PnP re-enumerates the devices. This is all transparent to the client. Properties that are set using
|
||||
/// <c>SwDevicePropertySet</c> after the enumeration don't persist in memory. But, if you set a property by using
|
||||
/// <c>SwDeviceCreate</c>, you can update the value with <c>SwDevicePropertySet</c>, and this update is applied to the in-memory
|
||||
/// value as well as the persisted store.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// We recommend that all properties be specified as part of the call to <c>SwDeviceCreate</c> when possible and that these
|
||||
/// properties be specified for every call to <c>SwDeviceCreate</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <c>Note</c> The operating system might possibly call SW_DEVICE_CREATE_CALLBACK before the call to <c>SwDeviceCreate</c> returns.
|
||||
/// For this reason, the software device handle for the device is supplied as a parameter to the callback function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// You can create a software device as the child of a parent that is not present at the time. PnP will enumerate the software
|
||||
/// device after the parent becomes present.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/swdevice/nf-swdevice-swdevicecreate HRESULT SwDeviceCreate( PCWSTR
|
||||
// pszEnumeratorName, PCWSTR pszParentDeviceInstance, const SW_DEVICE_CREATE_INFO *pCreateInfo, ULONG cPropertyCount, const
|
||||
// DEVPROPERTY *pProperties, SW_DEVICE_CREATE_CALLBACK pCallback, PVOID pContext, PHSWDEVICE phSwDevice );
|
||||
[DllImport(Lib_Cfgmgr32, SetLastError = false, ExactSpelling = true)]
|
||||
[PInvokeData("swdevice.h", MSDNShortId = "NF:swdevice.SwDeviceCreate")]
|
||||
public static extern HRESULT SwDeviceCreate([MarshalAs(UnmanagedType.LPWStr)] string pszEnumeratorName, [MarshalAs(UnmanagedType.LPWStr)] string pszParentDeviceInstance,
|
||||
in SW_DEVICE_CREATE_INFO pCreateInfo, uint cPropertyCount, [In, Optional, MarshalAs(UnmanagedType.LPArray)] DEVPROPERTY[] pProperties, SW_DEVICE_CREATE_CALLBACK pCallback,
|
||||
[In, Optional] IntPtr pContext, out SafeHSWDEVICE phSwDevice);
|
||||
|
||||
SwDeviceGetLifetime Gets the lifetime of a software device.
|
||||
SwDeviceInterfacePropertySet Sets properties on a software device interface.
|
||||
SwDeviceInterfaceRegister Registers a device interface for a software device and optionally sets properties on that interface.
|
||||
SwDeviceInterfaceSetState Enables or disables a device interface for a software device.
|
||||
SwDevicePropertySet Sets properties on a software device.
|
||||
SwDeviceSetLifetime Manages the lifetime of a software device.
|
||||
SwMemFree Frees memory that other Software Device API functions allocated.
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -309,7 +309,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.CfgMgr32", "
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.TextServicesFramework", "PInvoke\TextServicesFramework\Vanara.PInvoke.TextServicesFramework.csproj", "{17DE6265-EE0F-42E5-AE1A-7ACCDD8A45E8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CfgMgr32", "UnitTests\PInvoke\CfgMgr32\CfgMgr32.csproj", "{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CfgMgr32", "UnitTests\PInvoke\CfgMgr32\CfgMgr32.csproj", "{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -1012,9 +1012,7 @@ Global
|
|||
{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Loading…
Reference in New Issue