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,
}
}