Vanara/PInvoke/NewDev/NewDev.cs

1270 lines
70 KiB
C#

using System;
using System.Runtime.InteropServices;
using static Vanara.PInvoke.SetupAPI;
namespace Vanara.PInvoke
{
/// <summary>Items from the NewDev.dll</summary>
public static partial class NewDev
{
private const string Lib_NewDev = "newdev.dll";
/// <summary>Flags for <see cref="DiInstallDevice(HWND, HDEVINFO, in SP_DEVINFO_DATA, in SP_DRVINFO_DATA_V2, DIID_FLAG, out bool)"/>.</summary>
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiInstallDevice")]
[Flags]
public enum DIID_FLAG : uint
{
/// <summary>
/// If the caller does not specify a driver (DriverInfoData is set to <c>NULL</c>) and <c>DiInstallDevice</c> does not locate a
/// preinstalled driver that matches the specified device. Instead, <c>DiInstallDevice</c> displays the Found New Hardware
/// wizard for the device.
/// </summary>
DIIDFLAG_SHOWSEARCHUI = 0x00000001,
/// <summary>
/// <c>DiInstallDevice</c> does not start finish-install wizard pages or finish-install actions. The caller of
/// <c>DiInstallDevice</c> must start these operations. The caller should only specify this flag if the caller requires that
/// finish-install wizard pages be invoked in the context of a caller-supplied user interface component.
/// </summary>
DIIDFLAG_NOFINISHINSTALLUI = 0x00000002,
/// <summary>
/// <c>DiInstallDevice</c> attempts to install a null driver on the specified device. If this flag is set,
/// <c>DiInstallDevice</c> does not use the DriverInfoData parameter. <c>DiInstallDevice</c> removes all device settings and, if
/// the device cannot run in raw mode, the function sets the status of the device to <c>CM_PROB_FAILED_INSTALL</c>. If
/// <c>DiInstallDevice</c> cannot install a null driver, the resulting state of the device is the same as if the device was
/// connected for the first time to the computer and Windows did not locate a driver for the device.
/// </summary>
DIIDFLAG_INSTALLNULLDRIVER = 0x00000004,
/// <summary>
/// Any additional INF file specified via a CopyINF directive will be installed on any device it is applicable to. Any failure
/// in installing an additional INF will not cause the primary INF's installation to fail.
/// </summary>
DIIDFLAG_INSTALLCOPYINFDRIVERS = 0x00000008,
}
/// <summary>Flags for <see cref="DiInstallDriver"/></summary>
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiInstallDriverA")]
[Flags]
public enum DIIRFLAG : uint
{
/// <summary>Don't copy inf, it has been published</summary>
DIIRFLAG_INF_ALREADY_COPIED = 0x00000001, // Don't copy inf, it has been published
/// <summary>
/// Installs the specified driver on a matching device whether the driver is a better match for the device than the driver that
/// is currently installed on the device.
/// </summary>
DIIRFLAG_FORCE_INF = 0x00000002,
/// <summary>limit installs on hw using the inf</summary>
DIIRFLAG_HW_USING_THE_INF = 0x00000004, // limit installs on hw using the inf
/// <summary>Perform a hotpatch service pack install</summary>
DIIRFLAG_HOTPATCH = 0x00000008, // Perform a hotpatch service pack install
/// <summary>install w/o backup and no rollback</summary>
DIIRFLAG_NOBACKUP = 0x00000010, // install w/o backup and no rollback
/// <summary>Pre-install inf, if possible</summary>
DIIRFLAG_PRE_CONFIGURE_INF = 0x00000020, // Pre-install inf, if possible
/// <summary/>
DIIRFLAG_INSTALL_AS_SET = 0x00000040,
}
/// <summary>Flags for <see cref="DiUninstallDriver"/>.</summary>
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiUninstallDriverW")]
[Flags]
public enum DIURFLAG : uint
{
/// <summary>
/// Removes the driver package from any devices it is installed on, but does not remove the drive package from the Driver Store.
/// </summary>
DIURFLAG_NO_REMOVE_INF = 0x00000001
}
/// <summary>Flags for <see cref="UpdateDriverForPlugAndPlayDevices"/>.</summary>
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.UpdateDriverForPlugAndPlayDevicesA")]
[Flags]
public enum INSTALLFLAG
{
/// <summary>
/// <para>
/// If this flag is set and the function finds a device that matches the HardwareId value, the function installs new drivers for
/// the device whether better drivers already exist on the computer.
/// </para>
/// <para>
/// <c>Important</c> Use this flag only with extreme caution. Setting this flag can cause an older driver to be installed over a
/// newer driver, if a user runs the vendor's application after newer drivers are available.
/// </para>
/// </summary>
INSTALLFLAG_FORCE = 0x00000001,
/// <summary>
/// <para>
/// If this flag is set, the function will not copy, rename, or delete any installation files. Use of this flag should be
/// limited to environments in which file access is restricted or impossible, such as an "embedded" operating system.
/// </para>
/// </summary>
INSTALLFLAG_READONLY = 0x00000002,
/// <summary>
/// <para>
/// If this flag is set, the function will return <c>FALSE</c> when any attempt to display UI is detected. Set this flag only if
/// the function will be called from a component (such as a service) that cannot display UI.
/// </para>
/// <para><c>Note</c> If this flag is set and a UI display is attempted, the device can be left in an indeterminate state.</para>
/// </summary>
INSTALLFLAG_NONINTERACTIVE = 0x00000004,
}
/// <summary>Flags for <see cref="DiRollbackDriver"/></summary>
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiRollbackDriver")]
[Flags]
public enum ROLLBACK_FLAG : uint
{
/// <summary>Suppresses the display of user interface components that are associated with a driver rollback.</summary>
ROLLBACK_FLAG_NO_UI = 0x00000001
}
/// <summary>
/// The <c>DiInstallDevice</c> function installs a specified driver that is preinstalled in the driver store on a specified device
/// that is present in the system.
/// </summary>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiInstallDevice</c> uses to display any user interface component that is associated
/// with installing the device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the specified device.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the specified device in the specified device information set.
/// </param>
/// <param name="DriverInfoData">
/// An pointer to an SP_DRVINFO_DATA structure that specifies the driver to install on the specified device. This parameter is
/// optional and can be set to <c>NULL</c>. If this parameter is <c>NULL</c>, <c>DiInstallDevice</c> searches the drivers
/// preinstalled in the driver store for the driver that is the best match to the specified device, and, if one is found, installs
/// the driver on the specified device.
/// </param>
/// <param name="Flags">
/// <para>A value of type <c>DWORD</c> that specifies zero or the following flag:</para>
/// <para>DIIDFLAG_SHOWSEARCHUI</para>
/// <para>
/// If the caller does not specify a driver (DriverInfoData is set to <c>NULL</c>) and <c>DiInstallDevice</c> does not locate a
/// preinstalled driver that matches the specified device. Instead, <c>DiInstallDevice</c> displays the Found New Hardware wizard
/// for the device.
/// </para>
/// <para>DIIDFLAG_NOFINISHINSTALLUI</para>
/// <para>
/// <c>DiInstallDevice</c> does not start finish-install wizard pages or finish-install actions. The caller of
/// <c>DiInstallDevice</c> must start these operations. The caller should only specify this flag if the caller requires that
/// finish-install wizard pages be invoked in the context of a caller-supplied user interface component.
/// </para>
/// <para>DIIDFLAG_INSTALLNULLDRIVER</para>
/// <para>
/// <c>DiInstallDevice</c> attempts to install a null driver on the specified device. If this flag is set, <c>DiInstallDevice</c>
/// does not use the DriverInfoData parameter. <c>DiInstallDevice</c> removes all device settings and, if the device cannot run in
/// raw mode, the function sets the status of the device to <c>CM_PROB_FAILED_INSTALL</c>. If <c>DiInstallDevice</c> cannot install
/// a null driver, the resulting state of the device is the same as if the device was connected for the first time to the computer
/// and Windows did not locate a driver for the device.
/// </para>
/// <para>DIIDFLAG_INSTALLCOPYINFDRIVERS</para>
/// <para>
/// Any additional INF file specified via a CopyINF directive will be installed on any device it is applicable to. Any failure in
/// installing an additional INF will not cause the primary INF's installation to fail.
/// </para>
/// </param>
/// <param name="NeedReboot">
/// A pointer to a value of type <c>BOOL</c> that <c>DiInstallDevice</c> sets to indicate whether a system restart is required to
/// complete the installation. This parameter is optional and can be set to <c>NULL</c>. If this parameter is supplied and a system
/// restart is required to complete the installation, <c>DiInstallDevice</c> sets the value to <c>TRUE</c>. In this case, the caller
/// is responsible for restarting the system. If this parameter is supplied and a system restart is not required,
/// <c>DiInstallDevice</c> sets this parameter to <c>FALSE</c>. If this parameter is <c>NULL</c> and a system restart is required to
/// complete the installation, <c>DiInstallDevice</c> displays a system restart dialog box.
/// </param>
/// <returns>
/// <para>
/// <c>DiInstallDevice</c> returns <c>TRUE</c> if the function successfully installed the specified driver on the specified device.
/// Otherwise, <c>DiInstallDevice</c> returns <c>FALSE</c> and the logged error can be retrieved by making a call to
/// <c>GetLastError</c>. Some of the more common error values that <c>GetLastError</c> might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows Vista and Windows Server 2008 require that a calling
/// process have Administrator privileges to install a driver on a device.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value that is specified for Flags is not zero or a bitwise OR of the valid flags.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Only call <c>DiInstallDevice</c> if it is necessary to install a specific driver on a specific device. Otherwise, use
/// UpdateDriverForPlugAndPlayDevices or DiInstallDriver to install a driver for a device. For more information about which of these
/// functions to call to install a driver on a device, see SetupAPI Functions that Simplify Driver Installation.
/// </para>
/// <para>
/// Before calling <c>DiInstallDevice</c>, the caller must obtain an SP_DEVINFO_DATA structure to specify the device and,
/// optionally, an SP_DRVINFO_DATA structure to specify a driver for the device.
/// </para>
/// <para>
/// To create a device information set that contains the specified device and to obtain an SP_DEVINFO_DATA structure for the device,
/// do one of the following:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call SetupDiGetClassDevs to retrieve a device information set that contains the device and then call SetupDiEnumDeviceInfo to
/// enumerate the devices in the device information set. On each call, <c>SetupDiEnumDeviceInfo</c> returns an SP_DEVINFO_DATA
/// structure that represents the enumerated device in the device information set. To obtain specific information about the
/// enumerated device, call SetupDiGetDeviceProperty and supply the <c>SP_DEVINFO_DATA</c> structure that is returned by <c>SetupDiEnumDeviceInfo</c>.
/// </term>
/// </item>
/// <item>
/// <term>
/// Call SetupDiOpenDeviceInfo to add a device with a known device instance ID to the device information set.
/// <c>SetupDiOpenDeviceInfo</c> returns an SP_DEVINFO_DATA structure that represents the device in the device information set.
/// </term>
/// </item>
/// </list>
/// <para>
/// To retrieve an SP_DRVINFO_DATA structure for a selected driver, call SetupDiBuildDriverInfoList to build a list of drivers for
/// the device and then call SetupDiEnumDriverInfo to enumerate the elements of the driver list for the device. For each enumerated
/// driver, <c>SetupDiEnumDriverInfo</c> retrieves an <c>SP_DRVINFO_DATA</c> structure that identifies the driver.
/// SetupDiGetDriverInfoDetail can also be called to retrieve additional detail about an enumerated driver.
/// </para>
/// <para>
/// In general, an installation application should set NeedReboot to <c>NULL</c>. This ensures that <c>DiInstallDevice</c> prompts
/// the user to restart the system if a restart is required to complete the installation. An application should supply a NeedReboot
/// pointer only in the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The application must call <c>DiInstallDevice</c> several times to complete an installation. In this case, the application should
/// record whether a <c>TRUE</c> NeedReboot value is returned by any of the calls to <c>DiInstallDevice</c> and, if so, prompt the
/// user to restart the system after the final call to <c>DiInstallDevice</c> returns.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application must perform required operations, other than calling <c>DiInstallDevice</c>, before a system restart should
/// occur. If a system restart is required, the application should finish the required operations and then prompt the user to
/// restart the system.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application is a class installer, in which case, the class installer should set the <c>DI_NEEDREBOOT</c> flag in the
/// <c>Flags</c> member of the SP_DEVINSTALL_PARAMS structure for a device.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diinstalldevice BOOL DiInstallDevice( HWND hwndParent,
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA DriverInfoData, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, ExactSpelling = true)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiInstallDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiInstallDevice([In, Optional] HWND hwndParent, [In] HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
in SP_DRVINFO_DATA_V2 DriverInfoData, DIID_FLAG Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>
/// The <c>DiInstallDevice</c> function installs a specified driver that is preinstalled in the driver store on a specified device
/// that is present in the system.
/// </summary>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiInstallDevice</c> uses to display any user interface component that is associated
/// with installing the device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="DeviceInfoSet">
/// A handle to a device information set that contains a device information element that represents the specified device.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the specified device in the specified device information set.
/// </param>
/// <param name="DriverInfoData">
/// An pointer to an SP_DRVINFO_DATA structure that specifies the driver to install on the specified device. This parameter is
/// optional and can be set to <c>NULL</c>. If this parameter is <c>NULL</c>, <c>DiInstallDevice</c> searches the drivers
/// preinstalled in the driver store for the driver that is the best match to the specified device, and, if one is found, installs
/// the driver on the specified device.
/// </param>
/// <param name="Flags">
/// <para>A value of type <c>DWORD</c> that specifies zero or the following flag:</para>
/// <para>DIIDFLAG_SHOWSEARCHUI</para>
/// <para>
/// If the caller does not specify a driver (DriverInfoData is set to <c>NULL</c>) and <c>DiInstallDevice</c> does not locate a
/// preinstalled driver that matches the specified device. Instead, <c>DiInstallDevice</c> displays the Found New Hardware wizard
/// for the device.
/// </para>
/// <para>DIIDFLAG_NOFINISHINSTALLUI</para>
/// <para>
/// <c>DiInstallDevice</c> does not start finish-install wizard pages or finish-install actions. The caller of
/// <c>DiInstallDevice</c> must start these operations. The caller should only specify this flag if the caller requires that
/// finish-install wizard pages be invoked in the context of a caller-supplied user interface component.
/// </para>
/// <para>DIIDFLAG_INSTALLNULLDRIVER</para>
/// <para>
/// <c>DiInstallDevice</c> attempts to install a null driver on the specified device. If this flag is set, <c>DiInstallDevice</c>
/// does not use the DriverInfoData parameter. <c>DiInstallDevice</c> removes all device settings and, if the device cannot run in
/// raw mode, the function sets the status of the device to <c>CM_PROB_FAILED_INSTALL</c>. If <c>DiInstallDevice</c> cannot install
/// a null driver, the resulting state of the device is the same as if the device was connected for the first time to the computer
/// and Windows did not locate a driver for the device.
/// </para>
/// <para>DIIDFLAG_INSTALLCOPYINFDRIVERS</para>
/// <para>
/// Any additional INF file specified via a CopyINF directive will be installed on any device it is applicable to. Any failure in
/// installing an additional INF will not cause the primary INF's installation to fail.
/// </para>
/// </param>
/// <param name="NeedReboot">
/// A pointer to a value of type <c>BOOL</c> that <c>DiInstallDevice</c> sets to indicate whether a system restart is required to
/// complete the installation. This parameter is optional and can be set to <c>NULL</c>. If this parameter is supplied and a system
/// restart is required to complete the installation, <c>DiInstallDevice</c> sets the value to <c>TRUE</c>. In this case, the caller
/// is responsible for restarting the system. If this parameter is supplied and a system restart is not required,
/// <c>DiInstallDevice</c> sets this parameter to <c>FALSE</c>. If this parameter is <c>NULL</c> and a system restart is required to
/// complete the installation, <c>DiInstallDevice</c> displays a system restart dialog box.
/// </param>
/// <returns>
/// <para>
/// <c>DiInstallDevice</c> returns <c>TRUE</c> if the function successfully installed the specified driver on the specified device.
/// Otherwise, <c>DiInstallDevice</c> returns <c>FALSE</c> and the logged error can be retrieved by making a call to
/// <c>GetLastError</c>. Some of the more common error values that <c>GetLastError</c> might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows Vista and Windows Server 2008 require that a calling
/// process have Administrator privileges to install a driver on a device.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value that is specified for Flags is not zero or a bitwise OR of the valid flags.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Only call <c>DiInstallDevice</c> if it is necessary to install a specific driver on a specific device. Otherwise, use
/// UpdateDriverForPlugAndPlayDevices or DiInstallDriver to install a driver for a device. For more information about which of these
/// functions to call to install a driver on a device, see SetupAPI Functions that Simplify Driver Installation.
/// </para>
/// <para>
/// Before calling <c>DiInstallDevice</c>, the caller must obtain an SP_DEVINFO_DATA structure to specify the device and,
/// optionally, an SP_DRVINFO_DATA structure to specify a driver for the device.
/// </para>
/// <para>
/// To create a device information set that contains the specified device and to obtain an SP_DEVINFO_DATA structure for the device,
/// do one of the following:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call SetupDiGetClassDevs to retrieve a device information set that contains the device and then call SetupDiEnumDeviceInfo to
/// enumerate the devices in the device information set. On each call, <c>SetupDiEnumDeviceInfo</c> returns an SP_DEVINFO_DATA
/// structure that represents the enumerated device in the device information set. To obtain specific information about the
/// enumerated device, call SetupDiGetDeviceProperty and supply the <c>SP_DEVINFO_DATA</c> structure that is returned by <c>SetupDiEnumDeviceInfo</c>.
/// </term>
/// </item>
/// <item>
/// <term>
/// Call SetupDiOpenDeviceInfo to add a device with a known device instance ID to the device information set.
/// <c>SetupDiOpenDeviceInfo</c> returns an SP_DEVINFO_DATA structure that represents the device in the device information set.
/// </term>
/// </item>
/// </list>
/// <para>
/// To retrieve an SP_DRVINFO_DATA structure for a selected driver, call SetupDiBuildDriverInfoList to build a list of drivers for
/// the device and then call SetupDiEnumDriverInfo to enumerate the elements of the driver list for the device. For each enumerated
/// driver, <c>SetupDiEnumDriverInfo</c> retrieves an <c>SP_DRVINFO_DATA</c> structure that identifies the driver.
/// SetupDiGetDriverInfoDetail can also be called to retrieve additional detail about an enumerated driver.
/// </para>
/// <para>
/// In general, an installation application should set NeedReboot to <c>NULL</c>. This ensures that <c>DiInstallDevice</c> prompts
/// the user to restart the system if a restart is required to complete the installation. An application should supply a NeedReboot
/// pointer only in the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The application must call <c>DiInstallDevice</c> several times to complete an installation. In this case, the application should
/// record whether a <c>TRUE</c> NeedReboot value is returned by any of the calls to <c>DiInstallDevice</c> and, if so, prompt the
/// user to restart the system after the final call to <c>DiInstallDevice</c> returns.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application must perform required operations, other than calling <c>DiInstallDevice</c>, before a system restart should
/// occur. If a system restart is required, the application should finish the required operations and then prompt the user to
/// restart the system.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application is a class installer, in which case, the class installer should set the <c>DI_NEEDREBOOT</c> flag in the
/// <c>Flags</c> member of the SP_DEVINSTALL_PARAMS structure for a device.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diinstalldevice BOOL DiInstallDevice( HWND hwndParent,
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA DriverInfoData, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, ExactSpelling = true)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiInstallDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiInstallDevice([In, Optional] HWND hwndParent, [In] HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
[In, Optional] IntPtr DriverInfoData, DIID_FLAG Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>
/// The <c>DiInstallDriver</c> function preinstalls a driver in the driver store and then installs the driver on devices present in
/// the system that the driver supports.
/// </summary>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiInstallDriver</c> uses to display any user interface component that is associated
/// with installing the device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="InfPath">
/// A pointer to a NULL-terminated string that supplies the fully qualified path of the INF file for the driver package.
/// </param>
/// <param name="Flags">
/// <para>A value of type DWORD that specifies zero or DIIRFLAG_FORCE_INF. Typically, this flag should be set to zero.</para>
/// <para>
/// If this flag is zero, <c>DiInstallDriver</c> only installs the specified driver on a device if the driver is a better match for
/// a device than the driver that is currently installed on a device. However, if this flag is set to DIIRFLAG_FORCE_INF,
/// <c>DiInstallDriver</c> installs the specified driver on a matching device whether the driver is a better match for the device
/// than the driver that is currently installed on the device.
/// </para>
/// <para>
/// <c>Caution</c> Forcing the installation of the driver can result in replacing a more compatible or newer driver with a less
/// compatible or older driver.
/// </para>
/// <para>For information about how Windows selects a driver for a device, see</para>
/// <para>How Windows Selects Drivers</para>
/// <para>.</para>
/// </param>
/// <param name="NeedReboot">
/// A pointer to a value of type BOOL that <c>DiInstallDriver</c> sets to indicate whether a system is restart is required to
/// complete the installation. This parameter is optional and can be <c>NULL</c>. If the parameter is supplied and a system restart
/// is required to complete the installation, <c>DiInstallDriver</c> sets the value to <c>TRUE</c>. In this case, the caller must
/// prompt the user to restart the system. If this parameter is supplied and a system restart is not required to complete the
/// installation, <c>DiInstallDriver</c> sets the value to <c>FALSE</c>. If the parameter is <c>NULL</c> and a system restart is
/// required to complete the installation, <c>DiInstallDriver</c> displays a system restart dialog box. For more information about
/// this parameter, see the following <c>Remarks</c> section.
/// </param>
/// <returns>
/// <para>
/// <c>DiInstallDriver</c> returns <c>TRUE</c> if the function successfully preinstalled the specified driver package in the driver
/// store. <c>DiInstallDriver</c> also returns <c>TRUE</c> if the function successfully installed the driver on one or more devices
/// in the system. If the driver package is not successfully installed in the driver store, <c>DiInstallDriver</c> returns
/// <c>FALSE</c> and the logged error can be retrieved by making call to <c>GetLastError</c>. Some of the more common error values
/// that <c>GetLastError</c> might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows requires that the caller have Administrator privileges to
/// preinstall a driver package in the driver store.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The path of the specified INF file does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value specified for Flags is not equal to zero or DIIRFLAG_FORCE_INF.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>DiInstallDriver</c> performs the following operations:</para>
/// <list type="number">
/// <item>
/// <term>
/// Preinstalls the driver package in the driver store. If there is an instance of the same driver package already preinstalled in
/// the driver store, <c>DiInstallDriver</c> first removes that instance and then adds the new instance of the driver package to the
/// driver store.
/// </term>
/// </item>
/// <item>
/// <term>Enumerates devices that are present in the system.</term>
/// </item>
/// <item>
/// <term>
/// If Flags is equal to zero, installs the driver on a device only if the specified driver is a better match for the device than
/// the driver that is currently installed on the device.
/// </term>
/// </item>
/// <item>
/// <term>
/// If Flags is equal to DIIRFLAG_FORCE_INF, installs the driver on a device regardless of whether the driver package is the better
/// match to the device than the driver that is currently installed on the device.
/// </term>
/// </item>
/// </list>
/// <para>
/// In general, an installation application should set NeedReboot to <c>NULL</c> to direct <c>DiInstallDriver</c> to prompt the user
/// to restart the system if a restart is required to complete the installation. An application should supply a NeedReboot pointer
/// only in the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The application must call <c>DiInstallDriver</c> several times to complete an installation. In this case, the application should
/// record whether a <c>TRUE</c> NeedReboot value is returned by any of the calls to <c>DiInstallDriver</c> and, if so, prompt the
/// user to restart the system after the final call to <c>DiInstallDriver</c> returns.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application must perform required operations, other than calling <c>DiInstallDriver</c>, before a system restart should
/// occur. If a system restart is required, the application should finish the required operations and then prompt the user to
/// restart the system.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application is a class installer, in which case, the class installer should set the DI_NEEDREBOOT flag in the <c>Flags</c>
/// member of the SP_DEVINSTALL_PARAMS structure for a device.
/// </term>
/// </item>
/// </list>
/// <para>
/// To install a selected driver on a selected device, call DiInstallDevice. For more info, see SetupAPI Functions that Simplify
/// Driver Installation.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diinstalldrivera BOOL DiInstallDriverA( HWND hwndParent,
// LPCSTR InfPath, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiInstallDriverA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiInstallDriver([In, Optional] HWND hwndParent, string InfPath, DIIRFLAG Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>The <c>DiRollbackDriver</c> function rolls back the driver that is installed on a specified device.</summary>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element that represents the device for which driver
/// rollback is performed.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the specific device in the specified device information set for which
/// driver rollback is performed.
/// </param>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiRollbackDriver</c> uses to display any user interface component that is associated
/// with a driver rollback for the specified device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="Flags">
/// <para>A value of type DWORD that can be set to zero or ROLLBACK_FLAG_NO_UI.</para>
/// <para>
/// Typically, this flag should be set to zero, in which case <c>DiRollbackDriver</c> does not suppress the default user interface
/// components that are associated with a driver rollback. However, if this flag is set to ROLLBACK_FLAG_NO_UI,
/// <c>DiRollbackDriver</c> suppresses the display of user interface components that are associated with a driver rollback.
/// </para>
/// </param>
/// <param name="NeedReboot">
/// <para>
/// A pointer to a value of type BOOL that <c>DiRollbackDriver</c> sets to indicate whether a system restart is required to complete
/// the rollback. This parameter is optional and can be <c>NULL</c>.
/// </para>
/// <para>
/// If the parameter is supplied and a system restart is required to complete the rollback, <c>DiRollbackDriver</c> sets the value
/// to <c>TRUE</c>. In this case, the caller must prompt the user to restart the system. If this parameter is supplied and a system
/// restart is not required to complete the installation, <c>DiRollbackDriver</c> sets the value to <c>FALSE</c>.
/// </para>
/// <para>
/// If the parameter is <c>NULL</c> and a system restart is required to complete the rollback, <c>DiRollbackDriver</c> displays a
/// system restart dialog box.
/// </para>
/// <para>For more information about this parameter, see the following <c>Remarks</c> section.</para>
/// </param>
/// <returns>
/// <para>
/// <c>DiRollbackDriver</c> returns <c>TRUE</c> if the function successfully rolled back the driver for the device; otherwise,
/// <c>DiRollbackDriver</c> returns <c>FALSE</c> and the logged error can be retrieved by making a call to <c>GetLastError</c>. Some
/// of the more common error values that <c>GetLastError</c> might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows requires that the caller have Administrator privileges to
/// roll back a driver package.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value specified for Flags is not equal to zero or ROLLBACK_FLAG_NO_UI.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_MORE_ITEMS</term>
/// <term>A backup driver is not set for the device.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If a previously installed backup driver is set for a device, a driver rollback for the device replaces the driver that is
/// currently installed on the device with the backup driver. Windows maintains at most one backup driver for a device. Windows sets
/// a driver as the backup driver for a device immediately after the driver is successfully installed on the device and Windows
/// determines that the device is functioning correctly. However, if a driver does not install successfully on a device or the
/// device does not function correctly after the installation, Windows does not set the driver as the backup driver for the device.
/// For more information about driver rollback, see information about Device Manager in Help and Support Center.
/// </para>
/// <para>If the specified device has a backup driver, <c>DiRollbackDriver</c> performs the following operations:</para>
/// <list type="number">
/// <item>
/// <term>
/// If Flags is set to zero, <c>DiRollbackDriver</c> prompts the user to confirm whether the backup driver should be installed.
/// Otherwise, if Flags is set to ROLLBACK_FLAG_NO_UI, <c>DiRollbackDriver</c> installs the backup driver without prompting the user
/// to confirm the installation of the backup driver.
/// </term>
/// </item>
/// <item>
/// <term>
/// <c>DiRollbackDriver</c> installs the backup driver. The driver is installed whether the backup driver is a better match for the
/// device than the driver that is currently installed on the device.
/// </term>
/// </item>
/// <item>
/// <term>
/// If the driver that is replaced by the backup driver is not an inbox driver and is not installed on any other devices in the
/// system, <c>DiRollbackDriver</c> removes the driver from the system. <c>DiRollbackDriver</c> removes the driver from the system
/// because it is assumed that a user will replace a driver only if there is a problem with the driver.
/// </term>
/// </item>
/// </list>
/// <para>
/// If the specified device does not have a backup driver, <c>DiRollbackDriver</c> calls <c>SetLastError</c> to set the error
/// ERROR_NO_MORE_ITEMS, does not remove the currently installed driver, and returns <c>FALSE</c>.
/// </para>
/// <para>
/// In general, installation applications should set NeedReboot to <c>NULL</c> so that the system will automatically initiate a
/// system restart if a restart is required to complete the rollback. An application should supply a NeedReboot pointer only in the
/// following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The application must call <c>DiRollbackDriver</c> several times to complete an installation. In this case, the application
/// should record whether a <c>TRUE</c> NeedReboot value is returned by any of the calls to <c>DiRollbackDriver</c> and, if so,
/// prompt the user to restart the system after the final call to <c>DiRollbackDriver</c> returns.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application must perform required operations, other than calling <c>DiRollbackDriver</c>, before a system restart should
/// occur. If a system restart is required, the application should finish the required operations and then prompt the user to
/// restart the system.
/// </term>
/// </item>
/// </list>
/// <para>To install a new driver for a device instead of rolling back the driver for the device, call DiInstallDriver or UpdateDriverForPlugAndPlayDevices.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-dirollbackdriver BOOL DiRollbackDriver( HDEVINFO
// DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, HWND hwndParent, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, ExactSpelling = true)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiRollbackDriver")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiRollbackDriver([In] HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData, [In, Optional] HWND hwndParent,
ROLLBACK_FLAG Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>The <c>DiShowUpdateDevice</c> function displays the Hardware Update wizard for a specified device.</summary>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiShowUpdateDevice</c> uses to display any user interface components that are
/// associated with updating the specified device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element that represents the device for which to show
/// the Hardware Update wizard.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the device for which to show the Hardware Update wizard.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <param name="NeedReboot">
/// A pointer to a value of type BOOL that <c>DiShowUpdateDevice</c> sets to indicate whether a system restart is required to
/// complete the driver update. This parameter is optional and can be <c>NULL</c>. If the parameter is supplied and a system restart
/// is required to complete the driver update, <c>DiShowUpdateDevice</c> sets the value to <c>TRUE</c>. In this case, the caller
/// must prompt the user to restart the system. If this parameter is supplied and a system restart is not required to complete the
/// installation, <c>DiShowUpdateDevice</c> sets the value to <c>FALSE</c>. If the parameter is <c>NULL</c> and a system restart is
/// required to complete the driver update, <c>DiShowUpdateDevice</c> displays a system restart dialog box. For more information
/// about this parameter, see the following <c>Remarks</c> section.
/// </param>
/// <returns>
/// <para>
/// <c>DiShowUpdateDevice</c> returns <c>TRUE</c> if the Hardware Update wizard successfully updated the driver for the specified
/// device. Otherwise, <c>DiShowUpdateDevice</c> returns <c>FALSE</c> and the logged error can be retrieved by making a call to
/// GetLastError. Some of the more common error values that GetLastError might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows requires that the calling process have Administrator
/// privileges to update a driver package.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_CANCELLED</term>
/// <term>The user canceled the Hardware Update wizard.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value specified for Flags is not equal to zero.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// <c>DiShowUpdateDevice</c> displays the Hardware Update wizard for the specified device instance. For information about how to
/// update device drivers by using the Hardware Update wizard, see Help and Support Center.
/// </para>
/// <para>
/// In general, installation applications should set NeedReboot to <c>NULL</c> so that the system will automatically initiate a
/// system restart if a restart is required to complete a hardware update. An application should supply a NeedReboot pointer only in
/// the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The installation application must call <c>DiShowUpdateDevice</c> several times to complete hardware updates. In this case, the
/// application should record whether a <c>TRUE</c> NeedReboot value is returned by any of the calls to <c>DiShowUpdateDevice</c>
/// and, if so, prompt the user to restart the system after the final call to <c>DiShowUpdateDevice</c> returns.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application must perform required operations, other than calling <c>DiShowUpdateDevice</c>, before a system restart should
/// occur. If a system restart is required, the application should finish the required operations and then prompt the user to
/// restart the system.
/// </term>
/// </item>
/// </list>
/// <para>To roll back a driver for a device instead of invoking the Hardware Update wizard, call DiRollbackDriver.</para>
/// <para>To install a new driver for a device instead of invoking the Hardware Update wizard, call DiInstallDriver or UpdateDriverForPlugAndPlayDevices.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-dishowupdatedevice BOOL DiShowUpdateDevice( HWND hwndParent,
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, ExactSpelling = true)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiShowUpdateDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiShowUpdateDevice([In, Optional] HWND hwndParent, HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
uint Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>The <c>DiShowUpdateDriver</c> function displays the Hardware Update wizard for a specified driver.</summary>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiShowUpdateDriver</c> uses to display any user interface components that are
/// associated with updating the specified device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="FilePath">
/// A pointer to a NULL-terminated string that supplies the fully qualified path of the INF file for the driver package.
/// </param>
/// <param name="Flags">This parameter must be set to zero.</param>
/// <param name="NeedReboot">
/// A pointer to a value of type BOOL that <c>DiShowUpdateDriver</c> sets to indicate whether a system restart is required to
/// complete the driver update. This parameter is optional and can be <c>NULL</c>. If the parameter is supplied and a system restart
/// is required to complete the driver update, <c>DiShowUpdateDevice</c> sets the value to <c>TRUE</c>. In this case, the caller
/// must prompt the user to restart the system. If this parameter is supplied and a system restart is not required to complete the
/// installation, <c>DiShowUpdateDevice</c> sets the value to <c>FALSE</c>. If the parameter is <c>NULL</c> and a system restart is
/// required to complete the driver update, <c>DiShowUpdateDevice</c> displays a system restart dialog box. For more information
/// about this parameter, see the following <c>Remarks</c> section.
/// </param>
/// <returns>
/// <para>
/// <c>DiShowUpdateDriver</c> returns <c>TRUE</c> if the Hardware Update wizard successfully updated the driver for the specified
/// device. Otherwise, <c>DiShowUpdateDevice</c> returns <c>FALSE</c> and the logged error can be retrieved by making a call to
/// GetLastError. Some of the more common error values that GetLastError might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows requires that the calling process have Administrator
/// privileges to update a driver package.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_CANCELLED</term>
/// <term>The user canceled the Hardware Update wizard.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value specified for Flags is not equal to zero.</term>
/// </item>
/// </list>
/// </returns>
[DllImport(Lib_NewDev, SetLastError = true, ExactSpelling = true)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiShowUpdateDriver")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiShowUpdateDriver([In, Optional] HWND hwndParent, [In, Optional, MarshalAs(UnmanagedType.LPWStr)] string FilePath,
uint Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>
/// <para>
/// The <c>DiUninstallDevice</c> function uninstalls a device and removes its device node (devnode) from the system. This differs
/// from using SetupDiCallClassInstaller with the DIF_REMOVE code because it attempts to uninstall the device node in addition to
/// child devnodes that are present at the time of the call.
/// </para>
/// <para>
/// Prior to Windows 8 any child devices that are not present at the time of the call will not be uninstalled. However, beginning
/// with Windows 8, any child devices that are not present at the time of the call will be uninstalled.
/// </para>
/// </summary>
/// <param name="hwndParent">
/// A handle to the top-level window that is used to display any user interface component that is associated with the uninstallation
/// request for the device. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="DeviceInfoSet">
/// A handle to the device information set that contains a device information element. This element represents the device to be
/// uninstalled through this call.
/// </param>
/// <param name="DeviceInfoData">
/// A pointer to an SP_DEVINFO_DATA structure that represents the specified device in the specified device information set for which
/// the uninstallation request is performed.
/// </param>
/// <param name="Flags">
/// A value of type DWORD that specifies device uninstallation flags. Starting with Windows 7, this parameter must be set to zero.
/// </param>
/// <param name="NeedReboot">
/// <para>
/// A pointer to a value of type BOOL that <c>DiUninstallDevice</c> sets to indicate whether a system restart is required to
/// complete the device uninstallation request. This parameter is optional and can be set to <c>NULL</c>.
/// </para>
/// <para>
/// If the parameter is given and a system restart is required, <c>DiUninstallDevice</c> sets the value to <c>TRUE</c>. In this
/// case, the application must prompt the user to restart the system. If this parameter is supplied and a system restart is not
/// required, <c>DiUninstallDevice</c> sets the value to <c>FALSE</c>.
/// </para>
/// <para>
/// If this parameter is <c>NULL</c> and a system restart is required to complete the device uninstallation,
/// <c>DiUninstallDevice</c> displays a system restart dialog box.
/// </para>
/// <para>For more information about this parameter, see the <c>Remarks</c> section.</para>
/// </param>
/// <returns>
/// <para>
/// <c>DiUninstallDevice</c> returns <c>TRUE</c> if the function successfully uninstalled the top-level device node that represents
/// the device. Otherwise, <c>DiUninstallDevice</c> returns <c>FALSE</c>, and the logged error can be retrieved by making a call to
/// GetLastError. The following list shows some of the more common error values that <c>GetLastError</c> might return for this API:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows requires that the caller have Administrator privileges to
/// uninstall devices.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value that is specified for the Flags parameter is not equal to zero.</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The return value does not indicate that the removal of all child devnodes has succeeded or failed. Starting with
/// Windows Vista, information about the status of the removal of child devnodes is available in the Setupapi.dev.log file. For more
/// information about this file, see SetupAPI Text Logs.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// <c>DiUninstallDevice</c> performs the same function as SetupDiCallClassInstaller when used with the DIF_REMOVE code. The key
/// difference is that child devnodes for the top-level device are also deleted. <c>DiUninstallDevice</c> only returns failure if
/// the top-level device node failed to be uninstalled, which is consistent with the behavior of <c>SetupDiCallClassInstaller</c>
/// when used with the <c>DIF_REMOVE</c> code. Detailed information about whether child devnode uninstallation succeeded is
/// available in the Setupapi.dev.log file.
/// </para>
/// <para>
/// The device to be uninstalled is specified by providing a device information set that includes the referenced device, and a
/// SP_DEVINFO_DATA structure for the specific device. These are provided in the DeviceInfoSet and DeviceInfoData parameters.
/// </para>
/// <para>
/// To create a device information set that contains the specified device and to obtain an SP_DEVINFO_DATA structure for the device,
/// complete one of the following tasks:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call SetupDiGetClassDevs to retrieve a device information set that contains the device and then call SetupDiEnumDeviceInfo to
/// enumerate the devices in the device information set. On each call, <c>SetupDiEnumDeviceInfo</c> returns an SP_DEVINFO_DATA
/// structure that represents the enumerated device in the device information set.
/// </term>
/// </item>
/// <item>
/// <term>
/// Call SetupDiEnumDeviceInfo to add a device with a known device instance ID to the device information set. SetupDiOpenDeviceInfo
/// returns an SP_DEVINFO_DATA structure that represents the device in the device information set.
/// </term>
/// </item>
/// </list>
/// <para>
/// In case the device uninstallation request requires a restart of the computer, <c>DiUninstallDevice</c> prompts the user to
/// restart the system if the NeedReboot parameter is set to <c>NULL</c>. If there is any user interface window that the application
/// is using, the hwndParent parameter should be set to the value of that window's handle.
/// </para>
/// <para>
/// However, if the application manages the notification of a required system restart, it must set the NeedReboot parameter to a
/// non- <c>NULL</c> value. <c>DiUninstallDevice</c> sets the NeedReboot parameter to <c>TRUE</c> or <c>FALSE</c>, depending on
/// whether a system restart is required.
/// </para>
/// <para>The following list shows examples of why the application might manage the system restart:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// The application has to uninstall several devices. After all the devices are uninstalled, the application should prompt the user
/// to restart the system if any call to <c>DiUninstallDevice</c> returned <c>TRUE</c> in the NeedReboot parameter.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application requires some other operations to occur before the system can be restarted. If a system restart is required, the
/// application should finish the required operations and then prompt the user to restart the system.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application is a class installer. In this case, the class installer should set the <c>DI_NEEDREBOOT</c> flag in the
/// <c>Flags</c> member of the SP_DEVINSTALL_PARAMS structure for a device.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diuninstalldevice BOOL DiUninstallDevice( HWND hwndParent,
// HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, ExactSpelling = true)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiUninstallDevice")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiUninstallDevice(HWND hwndParent, HDEVINFO DeviceInfoSet, in SP_DEVINFO_DATA DeviceInfoData,
uint Flags, [MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>
/// The <c>DiUninstallDriver</c> function removes a driver from any devices it is installed on by installing those devices with
/// another matching driver, if available, or the null driver if no other matching driver is available. Then the specified driver is
/// removed from the driver store.
/// </summary>
/// <param name="hwndParent">
/// A handle to the top-level window that <c>DiUninstallDriver</c> should use to display any user interface component that is
/// associated with uninstalling the driver. This parameter is optional and can be set to <c>NULL</c>.
/// </param>
/// <param name="InfPath">
/// A pointer to a NULL-terminated string that supplies the fully qualified path of the INF file for the driver package.
/// </param>
/// <param name="Flags">
/// <para>
/// A value of type DWORD that specifies zero or one or more of the following flags: DIURFLAG_NO_REMOVE_INF. Typically, this flag
/// should be set to zero.
/// </para>
/// <para>
/// If this flag is zero, <c>DiUninstallDriver</c> only uninstalls the specified driver from a device if the driver is a better
/// match for a device than the driver that is currently installed on a device. However, if this flag is set to
/// DIURFLAG_NO_REMOVE_INF, <c>DiUninstallDriver</c> removes the driver package from any devices it is installed on, but does not
/// remove the drive package from the Driver Store.
/// </para>
/// <para>
/// <c>Caution:</c> Forcing the uninstallation of the driver can result in replacing a more compatible or newer driver with a less
/// compatible or older driver.
/// </para>
/// <para>For information about how Windows selects a driver for a device, see</para>
/// <para>How Windows Selects Drivers</para>
/// <para>.</para>
/// </param>
/// <param name="NeedReboot">
/// A pointer to a value of type BOOL that <c>DiUninstallDriver</c> sets to indicate whether a system restart is required to
/// complete the uninstallation. This parameter is optional and can be <c>NULL</c>. If the parameter is supplied and a system
/// restart is required to complete the uninstallation, <c>DiUninstallDriver</c> sets the value to <c>TRUE</c>. In this case, the
/// caller must prompt the user to restart the system. If this parameter is supplied and a system restart is not required to
/// complete the uninstallation, <c>DiUninstallDriver</c> sets the value to <c>FALSE</c>. If the parameter is <c>NULL</c> and a
/// system restart is required to complete the uninstallation, <c>DiUninstallDriver</c> displays a system restart dialog box. For
/// more information about this parameter, see the following <c>Remarks</c> section.
/// </param>
/// <returns>
/// <para>
/// <c>DiUninstallDriver</c> returns <c>TRUE</c> if the function successfully removes the driver package from any devices it is
/// installed on and is successfully removed from the driver store of the system. If the driver package is not successfully
/// uninstalled from the driver store, <c>DiUninstallDriver</c> returns <c>FALSE</c> and the logged error can be retrieved by making
/// a call to <c>GetLastError</c>. Some of the more common error values that <c>GetLastError</c> might return are as follows:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have Administrator privileges. By default, Windows requires that the caller have Administrator privileges to
/// uninstall a driver package from the driver store.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The path of the specified INF file does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value specified for Flags is not equal to zero or DIURFLAG_NO_REMOVE_INF.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>
/// The calling application is a 32-bit application that is attempting to execute in a 64-bit environment, which is not allowed. For
/// more information, see Installing Devices on 64-Bit Systems.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// In general, an uninstallation application should set NeedReboot to <c>NULL</c> to direct <c>DiUninstallDriver</c> to prompt the
/// user to restart the system if a restart is required to complete the removal. An application should supply a NeedReboot pointer
/// only in the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The application must call <c>DiUninstallDriver</c> several times to complete an uninstallation. In this case, the application
/// should record whether a <c>TRUE</c> NeedReboot value is returned by any of the calls to <c>DiUninstallDriver</c> and, if so,
/// prompt the user to restart the system after the final call to <c>DiUninstallDriver</c> returns.
/// </term>
/// </item>
/// <item>
/// <term>
/// The application must perform required operations, other than calling <c>DiUninstallDriver</c>, before a system restart should
/// occur. If a system restart is required, the application should finish the required operations and then prompt the user to
/// restart the system.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diuninstalldriverw BOOL DiUninstallDriverW( HWND hwndParent,
// LPCWSTR InfPath, DWORD Flags, PBOOL NeedReboot );
[DllImport(Lib_NewDev, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.DiUninstallDriverW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DiUninstallDriver([In, Optional] HWND hwndParent, string InfPath, DIURFLAG Flags,
[MarshalAs(UnmanagedType.Bool)] out bool NeedReboot);
/// <summary>
/// Given an INF file and a hardware ID, the <c>UpdateDriverForPlugAndPlayDevices</c> function installs updated drivers for devices
/// that match the hardware ID.
/// </summary>
/// <param name="hwndParent">A handle to the top-level window to use for any UI related to installing devices.</param>
/// <param name="HardwareId">
/// A pointer to a NULL-terminated string that supplies the hardware identifier to match existing devices on the computer. The
/// maximum length of a NULL-terminated hardware identifier is MAX_DEVICE_ID_LEN. For more information about hardware identifiers,
/// see Device Identification Strings.
/// </param>
/// <param name="FullInfPath">
/// A pointer to a NULL-terminated string that supplies the full path file name of an INF file. The files should be on the
/// distribution media or in a vendor-created directory, not in a system location such as %SystemRoot%\inf.
/// <c>UpdateDriverForPlugAndPlayDevices</c> copies driver files to the appropriate system locations if the installation is successful.
/// </param>
/// <param name="InstallFlags">
/// <para>A caller-supplied value created by using OR to combine zero or more of the following bit flags:</para>
/// <para>INSTALLFLAG_FORCE</para>
/// <para>
/// If this flag is set and the function finds a device that matches the HardwareId value, the function installs new drivers for the
/// device whether better drivers already exist on the computer.
/// </para>
/// <para>
/// <c>Important</c> Use this flag only with extreme caution. Setting this flag can cause an older driver to be installed over a
/// newer driver, if a user runs the vendor's application after newer drivers are available.
/// </para>
/// <para>INSTALLFLAG_READONLY</para>
/// <para>
/// If this flag is set, the function will not copy, rename, or delete any installation files. Use of this flag should be limited to
/// environments in which file access is restricted or impossible, such as an "embedded" operating system.
/// </para>
/// <para>INSTALLFLAG_NONINTERACTIVE</para>
/// <para>
/// If this flag is set, the function will return <c>FALSE</c> when any attempt to display UI is detected. Set this flag only if the
/// function will be called from a component (such as a service) that cannot display UI.
/// </para>
/// <para><c>Note</c> If this flag is set and a UI display is attempted, the device can be left in an indeterminate state.</para>
/// <para>The InstallFlags parameter is typically zero.</para>
/// </param>
/// <param name="bRebootRequired">
/// <para>
/// A pointer to a BOOL-typed variable that indicates whether a restart is required and who should prompt for it. This pointer is
/// optional and can be <c>NULL</c>.
/// </para>
/// <para>
/// If the pointer is <c>NULL</c>, <c>UpdateDriverForPlugAndPlayDevices</c> prompts for a restart after installing drivers, if
/// necessary. If the pointer is supplied, the function returns a BOOLEAN value that is <c>TRUE</c> if the system should be
/// restarted. It is then the caller's responsibility to prompt for a restart.
/// </para>
/// <para>For more information, see the following <c>Remarks</c> section.</para>
/// </param>
/// <returns>
/// <para>The function returns <c>TRUE</c> if a device was upgraded to the specified driver.</para>
/// <para>
/// Otherwise, it returns <c>FALSE</c> and the logged error can be retrieved with a call to <c>GetLastError</c>. Possible error
/// values returned by <c>GetLastError</c> are included in the following table.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The path that was specified for FullInfPath does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_IN_WOW64</term>
/// <term>The calling application is a 32-bit application attempting to execute in a 64-bit environment, which is not allowed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>The value specified for InstallFlags is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_DEVINST</term>
/// <term>The value specified for HardwareId does not match any device on the system. That is, the device is not plugged in.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_MORE_ITEMS</term>
/// <term>
/// The function found a match for the HardwareId value, but the specified driver was not a better match than the current driver and
/// the caller did not specify the INSTALLFLAG_FORCE flag.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// <c>UpdateDriverForPlugAndPlayDevices</c> scans the devices on the system and attempts to install the drivers specified by
/// FullInfPath for any devices that match the specified HardwareId value.
/// </para>
/// <para>
/// The default behavior is to only install the specified drivers if they are better match than the currently installed drivers and
/// the specified drivers are also a better match than any drivers in %SystemRoot%\inf. For more information, see How Windows
/// Selects Drivers.
/// </para>
/// <para>
/// <c>UpdateDriverForPlugAndPlayDevices</c> can also be used to determine whether the device with the specified HardwareId value is
/// plugged in. For more information, see Writing a Device Installation Application.
/// </para>
/// <para>
/// <c>UpdateDriverForPlugAndPlayDevices</c> sends an IRP_MN_QUERY_REMOVE_DEVICE request to the specified device, all the children
/// of the device, and all other devices that are recursively part of the removal relations for the device. If any of these devices
/// fail a query remove request, <c>UpdateDriverForPlugAndPlayDevices</c> sets the DI_NEEDREBOOT flag in the <c>Flags</c> member of
/// the SP_DEVINSTALL_PARAMS structure for the device. For information about removal relations, see the
/// IRP_MN_QUERY_DEVICE_RELATIONS request.
/// </para>
/// <para>
/// Generally, device installation applications should supply <c>NULL</c> for bRebootRequired. So, the system will initiate a
/// restart if necessary. An application should specify a pointer value only in the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The application must call <c>UpdateDriverForPlugAndPlayDevices</c> several times to complete an installation.</term>
/// </item>
/// <item>
/// <term>The application must perform other operations before the restart (if required) occurs.</term>
/// </item>
/// <item>
/// <term>The application is a class installer, which should set DI_NEEDREBOOT in SP_DEVINSTALL_PARAMS if a restart is needed.</term>
/// </item>
/// </list>
/// <para>
/// If the application must call <c>UpdateDriverForPlugAndPlayDevices</c> several times, it should save any <c>TRUE</c> restart
/// status value received and then prompt for a restart after the final call has returned.
/// </para>
/// <para>
/// If the function returns ERROR_IN_WOW64 in a 32-bit application, the application is executing on a 64-bit system, which is not
/// allowed. For more information, see Installing Devices on 64-Bit Systems.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-updatedriverforplugandplaydevicesa BOOL
// UpdateDriverForPlugAndPlayDevicesA( HWND hwndParent, LPCSTR HardwareId, LPCSTR FullInfPath, DWORD InstallFlags, PBOOL
// bRebootRequired );
[DllImport(Lib_NewDev, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("newdev.h", MSDNShortId = "NF:newdev.UpdateDriverForPlugAndPlayDevicesA")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateDriverForPlugAndPlayDevices([In, Optional] HWND hwndParent, string HardwareId,
string FullInfPath, INSTALLFLAG InstallFlags, [MarshalAs(UnmanagedType.Bool)] out bool bRebootRequired);
}
}