[DllImport("Advapi32.dll", EntryPoint = "RegOpenKeyExW", CharSet = CharSet.Unicode)]
static extern int RegOpenKeyEx(IntPtr hKey, [In] string lpSubKey, int ulOptions, int samDesired, out IntPtr phkResult);
[DllImport("Advapi32.dll", EntryPoint = "RegQueryValueExW", CharSet = CharSet.Unicode)]
static extern int RegQueryValueEx(IntPtr hKey, [In] string lpValueName, IntPtr lpReserved, out int lpType, [Out] byte[] lpData, ref int lpcbData);
[DllImport("advapi32.dll")]
static extern int RegCloseKey(IntPtr hKey);
static public readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(-2147483646);
public const int KEY_READ = 0x20019;
public const int KEY_QUERY_VALUE = 0x0001;
public const int KEY_WOW64_64KEY = 0x0100;
public const int KEY_WOW64_32KEY = 0x0200;
public const int REG_NONE = 0;
public const int REG_SZ = 1;
public const int REG_EXPAND_SZ = 2;
public const int REG_BINARY = 3;
public const int REG_DWORD = 4;
public const int REG_DWORD_BIG_ENDIAN = 5;
public const int REG_LINK = 6;
public const int REG_MULTI_SZ = 7;
public const int REG_RESOURCE_LIST = 8;
public const int REG_FULL_RESOURCE_DESCRIPTOR = 9;
public const int REG_RESOURCE_REQUIREMENTS_LIST = 10;
public const int REG_QWORD = 11;
static string GetMachineGuid()
{
IntPtr key;
int error;
if ((error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, @"Software\Microsoft\Cryptography", 0, KEY_READ | KEY_WOW64_64KEY, out key)) != 0)
throw new Win32Exception(error);
try
{
return RegQueryValue(key, "MachineGuid").ToString();
}
finally
{
RegCloseKey(key);
}
}
static object RegQueryValue(IntPtr key, string value)
{
return RegQueryValue(key, value, null);
}
static object RegQueryValue(IntPtr key, string value, object defaultValue)
{
int error, type = 0, dataLength = 0xfde8;
int returnLength = dataLength;
byte[] data = new byte[dataLength];
while ((error = RegQueryValueEx(key, value, IntPtr.Zero, out type, data, ref returnLength)) == 0xea)
{
dataLength *= 2;
returnLength = dataLength;
data = new byte[dataLength];
}
if (error == 2)
return defaultValue; // value doesn't exist
if (error != 0)
throw new Win32Exception(error);
switch (type)
{
case REG_NONE:
case REG_BINARY:
return data;
case REG_DWORD:
return (((data[0] | (data[1] << 8)) | (data[2] << 16)) | (data[3] << 24));
case REG_DWORD_BIG_ENDIAN:
return (((data[3] | (data[2] << 8)) | (data[1] << 16)) | (data[0] << 24));
case REG_QWORD:
{
uint numLow = (uint)(((data[0] | (data[1] << 8)) | (data[2] << 16)) | (data[3] << 24));
uint numHigh = (uint)(((data[4] | (data[5] << 8)) | (data[6] << 16)) | (data[7] << 24));
return (long)(((ulong)numHigh << 32) | (ulong)numLow);
}
case REG_SZ:
return Encoding.Unicode.GetString(data, 0, returnLength);
case REG_EXPAND_SZ:
return Environment.ExpandEnvironmentVariables(Encoding.Unicode.GetString(data, 0, returnLength));
case REG_MULTI_SZ:
{
var strings = new List<string>();
string packed = Encoding.Unicode.GetString(data, 0, returnLength);
int start = 0;
int end = packed.IndexOf('\0', start);
while (end > start)
{
strings.Add(packed.Substring(start, end - start));
start = end + 1;
end = packed.IndexOf('\0', start);
}
return strings.ToArray();
}
default:
throw new NotSupportedException();
}
}