using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Vanara.InteropServices; using Vanara.PInvoke; namespace Vanara.Extensions { /// Extension methods for registry types. public static class RegistryTypeExt { /// Gets a given a system type. /// The type. /// A compatible . If no good match is found, is returned. public static REG_VALUE_TYPE GetFromType(Type type) { if (typeof(IEnumerable).IsAssignableFrom(type)) return REG_VALUE_TYPE.REG_MULTI_SZ; switch (Type.GetTypeCode(type)) { case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: return REG_VALUE_TYPE.REG_DWORD; case TypeCode.Int64: case TypeCode.UInt64: return REG_VALUE_TYPE.REG_QWORD; case TypeCode.Char: case TypeCode.String: return REG_VALUE_TYPE.REG_SZ; default: break; } if (typeof(IEnumerable).IsAssignableFrom(type) || type.IsMarshalable()) return REG_VALUE_TYPE.REG_BINARY; return REG_VALUE_TYPE.REG_SZ; } /// Gets a given a system type. /// The type. /// A compatible . If no good match is found, is returned. public static REG_VALUE_TYPE GetFromType() => GetFromType(typeof(T)); /// Extract the value of this registry type from a pointer. /// The registry type value. /// The allocated memory pointer. /// The size of the allocated memory. /// The character set to use in conversion if applicable. /// The extracted value. /// Registry links cannot be retrived from a pointer. Please use RegOpenKeyEx. public static object GetValue(this REG_VALUE_TYPE value, IntPtr ptr, uint size, CharSet charSet = CharSet.Auto) { switch (value) { case REG_VALUE_TYPE.REG_DWORD: case REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN: var data = ptr.Convert(4); if (BitConverter.IsLittleEndian && value == REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN || !BitConverter.IsLittleEndian && value == REG_VALUE_TYPE.REG_DWORD) Array.Reverse(data); return BitConverter.ToUInt32(data, 0); case REG_VALUE_TYPE.REG_EXPAND_SZ: return Environment.ExpandEnvironmentVariables(StringHelper.GetString(ptr, charSet, size)); case REG_VALUE_TYPE.REG_MULTI_SZ: return ptr.ToStringEnum(charSet, 0, size).ToArray(); case REG_VALUE_TYPE.REG_QWORD: return ptr.Convert(size); case REG_VALUE_TYPE.REG_SZ: return StringHelper.GetString(ptr, charSet, size); case REG_VALUE_TYPE.REG_RESOURCE_LIST: case REG_VALUE_TYPE.REG_FULL_RESOURCE_DESCRIPTOR: case REG_VALUE_TYPE.REG_RESOURCE_REQUIREMENTS_LIST: case REG_VALUE_TYPE.REG_BINARY: return ptr.Convert(size); case REG_VALUE_TYPE.REG_LINK: throw new InvalidOperationException("Registry links cannot be retrived from a pointer. Please use RegOpenKeyEx."); default: case REG_VALUE_TYPE.REG_NONE: return ptr; } } } } namespace Vanara.PInvoke { /// /// A registry value can store data in various formats. When you store data under a registry value, for instance by calling the /// RegSetValueEx function, you can specify one of the following values to indicate the type of data being stored. When you retrieve a /// registry value, functions such as RegQueryValueEx use these values to indicate the type of data retrieved. /// [PInvokeData("winnt.h")] public enum REG_VALUE_TYPE : uint { /// No defined value type. REG_NONE = 0, /// Binary data in any form. [CorrespondingType(typeof(byte[]))] REG_BINARY = 3, /// A 32-bit number. [CorrespondingType(typeof(uint))] REG_DWORD = 4, /// /// A 32-bit number in little-endian format. /// Windows is designed to run on little-endian computer architectures. /// Therefore, this value is defined as REG_DWORD in the Windows header files. /// [CorrespondingType(typeof(uint))] REG_DWORD_LITTLE_ENDIAN = 4, /// /// A 32-bit number in big-endian format. /// Some UNIX systems support big-endian architectures. /// REG_DWORD_BIG_ENDIAN = 5, /// /// A null-terminated string that contains unexpanded references to environment variables (for example, "%PATH%"). It will be a /// Unicode or ANSI string depending on whether you use the Unicode or ANSI functions. To expand the environment variable /// references, use the ExpandEnvironmentStrings function. /// [CorrespondingType(typeof(string))] REG_EXPAND_SZ = 2, /// /// A null-terminated Unicode string that contains the target path of a symbolic link that was created by calling the RegCreateKeyEx /// function with REG_OPTION_CREATE_LINK. /// REG_LINK = 6, /// /// A sequence of null-terminated strings, terminated by an empty string (\0). /// The following is an example: /// String1\0String2\0String3\0LastString\0\0 /// /// The first \0 terminates the first string, the second to the last \0 terminates the last string, and the final \0 terminates the /// sequence.Note that the final terminator must be factored into the length of the string. /// /// [CorrespondingType(typeof(IEnumerable))] REG_MULTI_SZ = 7, /// A 64-bit number. [CorrespondingType(typeof(ulong))] REG_QWORD = 11, /// /// A 64-bit number in little-endian format. /// /// Windows is designed to run on little-endian computer architectures. Therefore, this value is defined as REG_QWORD in the Windows /// header files. /// /// [CorrespondingType(typeof(ulong))] REG_QWORD_LITTLE_ENDIAN = 11, /// /// A null-terminated string. This will be either a Unicode or an ANSI string, depending on whether you use the Unicode or ANSI functions. /// [CorrespondingType(typeof(string))] REG_SZ = 1, /// Resource list in the resource map. REG_RESOURCE_LIST = 8, /// Resource list in the hardware description. REG_FULL_RESOURCE_DESCRIPTOR = 9, /// Resource requirement list. REG_RESOURCE_REQUIREMENTS_LIST = 10, } }