/// <summary> /// Resolves Interface ID/Symbolic link/Device path to Instance ID. /// </summary> /// <param name="symbolicLink">The device interface path/ID/symbolic link name.</param> /// <returns>The Instance ID.</returns> public static string GetInstanceIdFromInterfaceId(string symbolicLink) { var property = DevicePropertyDevice.InstanceId.ToNativeType(); var buffer = IntPtr.Zero; uint sizeRequired = 2048; try { buffer = Marshal.AllocHGlobal((int)sizeRequired); var ret = SetupApiWrapper.CM_Get_Device_Interface_Property( symbolicLink, ref property, out _, buffer, ref sizeRequired, 0 ); if (ret != SetupApiWrapper.ConfigManagerResult.Success) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(Marshal.PtrToStringUni(buffer)); } finally { Marshal.FreeHGlobal(buffer); } }
private SetupApiWrapper.ConfigManagerResult GetProperty( SetupApiWrapper.DevPropKey propertyKey, out SetupApiWrapper.DevPropType propertyType, out IntPtr valueBuffer, out uint valueBufferSize ) { valueBufferSize = 2018; valueBuffer = Marshal.AllocHGlobal((int)valueBufferSize); var ret = SetupApiWrapper.CM_Get_DevNode_Property( _instanceHandle, ref propertyKey, out propertyType, valueBuffer, ref valueBufferSize, 0 ); if (ret == SetupApiWrapper.ConfigManagerResult.Success) { return(ret); } Marshal.FreeHGlobal(valueBuffer); valueBuffer = IntPtr.Zero; return(ret); }
/// <summary> /// Attempts to restart this device. /// </summary> public void Restart() { var ret = SetupApiWrapper.CM_Query_And_Remove_SubTree( _instanceHandle, IntPtr.Zero, IntPtr.Zero, 0, SetupApiWrapper.CM_QUERY_AND_REMOVE_SUBTREE_FLAGS.CM_REMOVE_NO_RESTART ); if (ret != SetupApiWrapper.ConfigManagerResult.Success) { throw new Win32Exception(Marshal.GetLastWin32Error()); } ret = SetupApiWrapper.CM_Setup_DevNode( _instanceHandle, SetupApiWrapper.CM_SETUP_DEVINST_FLAGS.CM_SETUP_DEVNODE_READY ); if (ret != SetupApiWrapper.ConfigManagerResult.NoSuchDevinst && ret != SetupApiWrapper.ConfigManagerResult.Success) { if (ret != SetupApiWrapper.ConfigManagerResult.Success) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } }
/// <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> /// Instructs the system to re-enumerate hardware devices. /// </summary> /// <returns>True on success, false otherwise.</returns> public static bool Refresh() { if (SetupApiWrapper.CM_Locate_DevNode_Ex(out var devRoot, IntPtr.Zero, 0, IntPtr.Zero) != SetupApiWrapper.ConfigManagerResult.Success) { return(false); } return(SetupApiWrapper.CM_Reenumerate_DevNode_Ex(devRoot, 0, IntPtr.Zero) == SetupApiWrapper.ConfigManagerResult.Success); }
protected Device(string instanceId, DeviceLocationFlags flags) { InstanceId = instanceId; var iFlags = SetupApiWrapper.CM_LOCATE_DEVNODE_FLAG.CM_LOCATE_DEVNODE_NORMAL; switch (flags) { case DeviceLocationFlags.Normal: iFlags = SetupApiWrapper.CM_LOCATE_DEVNODE_FLAG.CM_LOCATE_DEVNODE_NORMAL; break; case DeviceLocationFlags.Phantom: iFlags = SetupApiWrapper.CM_LOCATE_DEVNODE_FLAG.CM_LOCATE_DEVNODE_PHANTOM; break; case DeviceLocationFlags.CancelRemove: iFlags = SetupApiWrapper.CM_LOCATE_DEVNODE_FLAG.CM_LOCATE_DEVNODE_CANCELREMOVE; break; } var ret = SetupApiWrapper.CM_Locate_DevNode( ref _instanceHandle, instanceId, iFlags ); if (ret == SetupApiWrapper.ConfigManagerResult.NoSuchDevinst) { throw new ArgumentException("The supplied instance wasn't found.", nameof(flags)); } if (ret != SetupApiWrapper.ConfigManagerResult.Success) { throw new Win32Exception(Marshal.GetLastWin32Error()); } uint nBytes = 256; var ptrInstanceBuf = Marshal.AllocHGlobal((int)nBytes); try { ret = SetupApiWrapper.CM_Get_Device_ID( _instanceHandle, ptrInstanceBuf, nBytes, 0 ); if (ret != SetupApiWrapper.ConfigManagerResult.Success) { throw new Win32Exception(Marshal.GetLastWin32Error()); } DeviceId = (Marshal.PtrToStringUni(ptrInstanceBuf) ?? string.Empty).ToUpper(); } finally { if (ptrInstanceBuf != IntPtr.Zero) { Marshal.FreeHGlobal(ptrInstanceBuf); } } }
/// <summary> /// Creates or updates an existing property with a given value. /// </summary> /// <typeparam name="T">The type of the property.</typeparam> /// <param name="propertyKey">The <see cref="DevicePropertyKey"/> to update.</param> /// <param name="propertyValue">The value to set.</param> public void SetProperty <T>(DevicePropertyKey propertyKey, T propertyValue) { if (typeof(T) != propertyKey.PropertyType) { throw new ArgumentException( "The supplied object type doesn't match the property type.", nameof(propertyKey) ); } var managedType = typeof(T); var nativePropKey = propertyKey.ToNativeType(); var nativePropType = NativeToManagedTypeMap.FirstOrDefault(t => t.Value == managedType).Key; uint propBufSize = 0; IntPtr buffer = IntPtr.Zero; #region Don't look, nasty trickery /* * Handle some native to managed conversions */ // Regular strings if (managedType == typeof(string)) { var value = (string)(object)propertyValue; buffer = Marshal.StringToHGlobalUni(value); propBufSize = (uint)((value.Length + 1) * 2); } // Double-null-terminated string to list //if (managedType == typeof(string[])) // return (T) (object) Marshal.PtrToStringUni(buffer, (int) size / 2).TrimEnd('\0').Split('\0') // .ToArray(); // Byte & SByte if (managedType == typeof(sbyte) || managedType == typeof(byte)) { var value = (byte)(object)propertyValue; propBufSize = (uint)Marshal.SizeOf(managedType); buffer = Marshal.AllocHGlobal((int)propBufSize); Marshal.WriteByte(buffer, value); } /* * // (U)Int16 * if (managedType == typeof(short) || managedType == typeof(ushort)) || return (T) (object) (ushort) Marshal.ReadInt16(buffer); */ // (U)Int32 if (managedType == typeof(int) || managedType == typeof(uint)) { var value = (uint)(object)propertyValue; propBufSize = (uint)Marshal.SizeOf(managedType); buffer = Marshal.AllocHGlobal((int)propBufSize); Marshal.WriteInt32(buffer, (int)value); } /* * // (U)Int64 * if (managedType == typeof(long) || managedType == typeof(ulong)) || return (T) (object) (ulong) Marshal.ReadInt64(buffer); || ||// FILETIME/DateTimeOffset ||if (managedType == typeof(DateTimeOffset)) || return (T) (object) DateTimeOffset.FromFileTime(Marshal.ReadInt64(buffer)); */ #endregion if (buffer == IntPtr.Zero) { throw new NotImplementedException("Type not supported."); } try { var ret = SetupApiWrapper.CM_Set_DevNode_Property( _instanceHandle, ref nativePropKey, nativePropType, buffer, propBufSize, 0 ); if (ret != SetupApiWrapper.ConfigManagerResult.Success) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { Marshal.FreeHGlobal(buffer); } }
/// <summary> /// Invokes the installation of a driver via provided .INF file. /// </summary> /// <param name="fullInfPath">An absolute path to the .INF file to install.</param> /// <param name="rebootRequired">True if a machine reboot is required, false otherwise.</param> /// <returns>True on success, false otherwise.</returns> public static bool Install(string fullInfPath, out bool rebootRequired) { return(SetupApiWrapper.DiInstallDriver(IntPtr.Zero, fullInfPath, SetupApiWrapper.DIIRFLAG_FORCE_INF, out rebootRequired)); }
/// <summary> /// Given an INF file and a hardware ID, this function installs updated drivers for devices that match the hardware ID. /// </summary> /// <param name="hardwareId">A string that supplies the hardware identifier to match existing devices on the computer.</param> /// <param name="fullInfPath">A string that supplies the full path file name of an INF file.</param> /// <param name="rebootRequired">A variable that indicates whether a restart is required and who should prompt for it.</param> /// <returns> /// The function returns TRUE if a device was upgraded to the specified driver. /// Otherwise, it returns FALSE and the logged error can be retrieved with a call to GetLastError. /// </returns> public static bool Update(string hardwareId, string fullInfPath, out bool rebootRequired) { return(SetupApiWrapper.UpdateDriverForPlugAndPlayDevices(IntPtr.Zero, hardwareId, fullInfPath, SetupApiWrapper.INSTALLFLAG_FORCE | SetupApiWrapper.INSTALLFLAG_NONINTERACTIVE, out rebootRequired)); }
/// <summary> /// Searches for devices matching the provided class GUID and returns the device path and instance ID. /// </summary> /// <param name="target">The class GUID to enumerate.</param> /// <param name="path">The device path of the enumerated device.</param> /// <param name="instanceId">The instance ID of the enumerated device.</param> /// <param name="instance">Optional instance ID (zero-based) specifying the device to process on multiple matches.</param> /// <returns>True if at least one device was found with the provided class, false otherwise.</returns> public static bool Find(Guid target, out string path, out string instanceId, int instance = 0) { var detailDataBuffer = IntPtr.Zero; var deviceInfoSet = IntPtr.Zero; try { SetupApiWrapper.SP_DEVINFO_DATA deviceInterfaceData = new SetupApiWrapper.SP_DEVINFO_DATA(), da = new SetupApiWrapper.SP_DEVINFO_DATA(); int bufferSize = 0, memberIndex = 0; deviceInfoSet = SetupApiWrapper.SetupDiGetClassDevs(ref target, IntPtr.Zero, IntPtr.Zero, SetupApiWrapper.DIGCF_PRESENT | SetupApiWrapper.DIGCF_DEVICEINTERFACE); deviceInterfaceData.cbSize = da.cbSize = Marshal.SizeOf(deviceInterfaceData); while (SetupApiWrapper.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref target, memberIndex, ref deviceInterfaceData)) { SetupApiWrapper.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, ref da); { detailDataBuffer = Marshal.AllocHGlobal(bufferSize); Marshal.WriteInt32(detailDataBuffer, IntPtr.Size == 4 ? 4 + Marshal.SystemDefaultCharSize : 8); if (SetupApiWrapper.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, ref da)) { var pDevicePathName = detailDataBuffer + 4; path = (Marshal.PtrToStringAuto(pDevicePathName) ?? string.Empty).ToUpper(); if (memberIndex == instance) { var nBytes = 256; var ptrInstanceBuf = Marshal.AllocHGlobal(nBytes); SetupApiWrapper.CM_Get_Device_ID(da.DevInst, ptrInstanceBuf, (uint)nBytes, 0); instanceId = (Marshal.PtrToStringAuto(ptrInstanceBuf) ?? string.Empty).ToUpper(); Marshal.FreeHGlobal(ptrInstanceBuf); return(true); } } else { Marshal.FreeHGlobal(detailDataBuffer); } } memberIndex++; } } finally { if (deviceInfoSet != IntPtr.Zero) { SetupApiWrapper.SetupDiDestroyDeviceInfoList(deviceInfoSet); } } path = instanceId = string.Empty; return(false); }
/// <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); } }