Ejemplo n.º 1
0
        /// <summary>
        ///     Returns a device instance property identified by <see cref="DevicePropertyKey" />.
        /// </summary>
        /// <typeparam name="T">The managed type of the fetched porperty value.</typeparam>
        /// <param name="propertyKey">The <see cref="DevicePropertyKey" /> to query for.</param>
        /// <returns>On success, the value of the queried property.</returns>
        public T GetProperty <T>(DevicePropertyKey propertyKey)
        {
            if (typeof(T) != propertyKey.PropertyType)
            {
                throw new ArgumentException(
                          "The supplied object type doesn't match the property type.",
                          nameof(propertyKey)
                          );
            }

            var buffer = IntPtr.Zero;

            try
            {
                var ret = GetProperty(
                    propertyKey.ToNativeType(),
                    out var propertyType,
                    out buffer,
                    out var size
                    );

                if (ret == SetupApiWrapper.ConfigManagerResult.NoSuchValue ||
                    propertyType == SetupApiWrapper.DevPropType.Empty)
                {
                    return(default(T));
                }

                if (ret != SetupApiWrapper.ConfigManagerResult.Success)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                if (!NativeToManagedTypeMap.TryGetValue(propertyType, out var managedType))
                {
                    throw new ArgumentException(
                              "Unknown property type.",
                              nameof(propertyKey)
                              );
                }

                if (typeof(T) != managedType)
                {
                    throw new ArgumentException(
                              "The supplied object type doesn't match the property type.",
                              nameof(propertyKey)
                              );
                }

                #region Don't look, nasty trickery

                /*
                 * Handle some native to managed conversions
                 */

                // Regular strings
                if (managedType == typeof(string))
                {
                    var value = Marshal.PtrToStringUni(buffer);
                    return((T)Convert.ChangeType(value, typeof(T)));
                }

                // 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))
                {
                    return((T)(object)Marshal.ReadByte(buffer));
                }

                // (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))
                {
                    return((T)Convert.ChangeType(Marshal.ReadInt32(buffer), managedType));
                }

                // (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

                throw new NotImplementedException("Type not supported.");
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
Ejemplo n.º 2
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);
            }
        }