/// <summary> /// Creates a virtual device node (hardware ID) in the provided device class. /// </summary> /// <param name="className">The device class name.</param> /// <param name="classGuid">The GUID of the device class.</param> /// <param name="node">The node path terminated by two null characters.</param> /// <returns>True on success, false otherwise.</returns> public static bool Create(string className, Guid classGuid, string node) { var deviceInfoSet = (IntPtr)(-1); var deviceInfoData = new SetupApiWrapper.SP_DEVINFO_DATA(); try { deviceInfoSet = SetupApiWrapper.SetupDiCreateDeviceInfoList(ref classGuid, IntPtr.Zero); if (deviceInfoSet == (IntPtr)(-1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } deviceInfoData.cbSize = Marshal.SizeOf(deviceInfoData); if (!SetupApiWrapper.SetupDiCreateDeviceInfo( deviceInfoSet, className, ref classGuid, null, IntPtr.Zero, SetupApiWrapper.DICD_GENERATE_ID, ref deviceInfoData )) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!SetupApiWrapper.SetupDiSetDeviceRegistryProperty( deviceInfoSet, ref deviceInfoData, SetupApiWrapper.SPDRP_HARDWAREID, node, node.Length * 2 )) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!SetupApiWrapper.SetupDiCallClassInstaller( SetupApiWrapper.DIF_REGISTERDEVICE, deviceInfoSet, ref deviceInfoData )) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { if (deviceInfoSet != (IntPtr)(-1)) { SetupApiWrapper.SetupDiDestroyDeviceInfoList(deviceInfoSet); } } return(true); }
/// <summary> /// Removed a device node identified by class GUID, path and instance ID. /// </summary> /// <param name="classGuid">The device class GUID.</param> /// <param name="instanceId">The instance ID.</param> /// <param name="rebootRequired">True if a reboot is required to complete the uninstall action, false otherwise.</param> /// <returns>True on success, false otherwise.</returns> public static bool Remove(Guid classGuid, string instanceId, out bool rebootRequired) { var deviceInfoSet = IntPtr.Zero; var installParams = Marshal.AllocHGlobal(584); // Max struct size on x64 platform try { var deviceInfoData = new SetupApiWrapper.SP_DEVINFO_DATA(); deviceInfoData.cbSize = Marshal.SizeOf(deviceInfoData); deviceInfoSet = SetupApiWrapper.SetupDiGetClassDevs( ref classGuid, IntPtr.Zero, IntPtr.Zero, SetupApiWrapper.DIGCF_PRESENT | SetupApiWrapper.DIGCF_DEVICEINTERFACE ); if (SetupApiWrapper.SetupDiOpenDeviceInfo( deviceInfoSet, instanceId, IntPtr.Zero, 0, ref deviceInfoData )) { var props = new SetupApiWrapper.SP_REMOVEDEVICE_PARAMS { ClassInstallHeader = new SetupApiWrapper.SP_CLASSINSTALL_HEADER() }; props.ClassInstallHeader.cbSize = Marshal.SizeOf(props.ClassInstallHeader); props.ClassInstallHeader.InstallFunction = SetupApiWrapper.DIF_REMOVE; props.Scope = SetupApiWrapper.DI_REMOVEDEVICE_GLOBAL; props.HwProfile = 0x00; // Prepare class (un-)installer if (SetupApiWrapper.SetupDiSetClassInstallParams( deviceInfoSet, ref deviceInfoData, ref props, Marshal.SizeOf(props) )) { // Invoke class installer with uninstall action if (!SetupApiWrapper.SetupDiCallClassInstaller(SetupApiWrapper.DIF_REMOVE, deviceInfoSet, ref deviceInfoData)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // Fill cbSize field Marshal.WriteInt32( installParams, 0, // cbSize is first field, always 32 bits long IntPtr.Size == 4 ? 556 /* x86 size */ : 584 /* x64 size */ ); // Fill SP_DEVINSTALL_PARAMS struct if (!SetupApiWrapper.SetupDiGetDeviceInstallParams(deviceInfoSet, ref deviceInfoData, installParams)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // Grab Flags field of SP_DEVINSTALL_PARAMS (offset of 32 bits) var flags = Marshal.ReadInt32(installParams, Marshal.SizeOf(typeof(uint))); // Test for restart/reboot flags being present rebootRequired = (flags & SetupApiWrapper.DI_NEEDRESTART) != 0 || (flags & SetupApiWrapper.DI_NEEDREBOOT) != 0; return(true); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { if (deviceInfoSet != IntPtr.Zero) { SetupApiWrapper.SetupDiDestroyDeviceInfoList(deviceInfoSet); } Marshal.FreeHGlobal(installParams); } }