Пример #1
0
        /// <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);
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        /// <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());
                }
            }
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
 /// <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);
 }
Пример #6
0
        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);
                }
            }
        }
Пример #7
0
        /// <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);
            }
        }
Пример #8
0
 /// <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));
 }
Пример #9
0
 /// <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));
 }
Пример #10
0
        /// <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);
        }
Пример #11
0
        /// <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);
            }
        }