How read the 64 bit registry from a 32 bit application or vice versa

http://www.rhyous.com/2011/01/24/how-read-the-64-bit-registry-from-a-32-bit-application-or-vice-versa/

How read the 64 bit registry from a 32 bit application or vice versa

I found out that I needed to read the 64 bit registry from a 32 bit app today.

Why you might ask?

Well, I need to get the RegisteredOrganization value from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion and unfortunately Microsoft has a bug where the WOW6432 version of this key always says Microsoft, so a 32 bit application would always return Microsoft as the RegisteredOrganization, regardless of what the user entered when they installed the OS. This is hardly desired.

Note: This is also why all Visual Studio projects created in Windows 7 64 bit have Microsoft in the project’s Assembly Information. Change the WOW6432 version of the RegisteredOrganization and you fix this Visual Studio issue.

Well, turns out C# doesn’t have functionality until .NET 4, so prior to .NET 4, to choose the 64 bit hive when running a 32 bit app, so we have to do use a DLLImport and use RegOpenKeyEx, RegCloseKey, and RegQueryValueEx.

I don’t have this well commented, and it is not very newbie proof, but here are three different ways to do this. Hopefully you can understand one or more of these.

Example 1 – .NET 4 Example

Here is how to do this in .NET 4.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

using Microsoft.Win32;

namespace Read64bitRegistryFrom32bitApp

{

class Program

{

static void Main(string[] args)

{

string value64 = string.Empty;

string value32 = string.Empty;

RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);

localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");

if (localKey != null)

{

value64 = localKey.GetValue("RegisteredOrganization").ToString();

}

RegistryKey localKey32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);

localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");

if (localKey32 != null)

{

value32 = localKey32.GetValue("RegisteredOrganization").ToString();

}

}

}

}

.NET 3.5 SP1 and Prior

This can also be done in .NET 3.5 and prior but it is not easy.
We have to do use a DLLImport and use RegOpenKeyEx, RegCloseKey, and RegQueryValueEx. Here are some examples.

Example 1 – A console application to read the 64 bit registry from a 32 bit application or vice versa

Here is the code in a simple one file project:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

using System;

using System.Runtime.InteropServices;

using System.Text;

namespace Read64bitRegistryFrom32bitApp

{

class Program

{

static void Main(string[] args)

{

string value64 = GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");

Console.WriteLine(value64);

string value32 = GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");

Console.WriteLine(value32);

}

public enum RegSAM

{

QueryValue = 0x0001,

SetValue = 0x0002,

CreateSubKey = 0x0004,

EnumerateSubKeys = 0x0008,

Notify = 0x0010,

CreateLink = 0x0020,

WOW64_32Key = 0x0200,

WOW64_64Key = 0x0100,

WOW64_Res = 0x0300,

Read = 0x00020019,

Write = 0x00020006,

Execute = 0x00020019,

AllAccess = 0x000f003f

}

public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);

public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);

#region Member Variables

#region Read 64bit Reg from 32bit app

[DllImport("Advapi32.dll")]

static extern uint RegOpenKeyEx(

UIntPtr hKey,

string lpSubKey,

uint ulOptions,

int samDesired,

out int phkResult);

[DllImport("Advapi32.dll")]

static extern uint RegCloseKey(int hKey);

[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]

public static extern int RegQueryValueEx(

int hKey, string lpValueName,

int lpReserved,

ref uint lpType,

System.Text.StringBuilder lpData,

ref uint lpcbData);

#endregion

#endregion

#region Functions

static public string GetRegKey64(UIntPtr inHive, String inKeyName, String inPropertyName)

{

return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName);

}

static public string GetRegKey32(UIntPtr inHive, String inKeyName, String inPropertyName)

{

return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName);

}

static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)

{

//UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;

int hkey = 0;

try

{

uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);

if (0 != lResult) return null;

uint lpType = 0;

uint lpcbData = 1024;

StringBuilder AgeBuffer = new StringBuilder(1024);

RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData);

string Age = AgeBuffer.ToString();

return Age;

}

finally

{

if (0 != hkey) RegCloseKey(hkey);

}

}

#endregion

}

}

Example 2 – A static class to read the 64 bit registry from a 32 bit application or vice versa

Or if you want this in its own separate class, here is a static class you can add to your project.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

using System;

using System.Runtime.InteropServices;

using System.Text;

namespace Read64bitRegistryFrom32bitApp

{

public enum RegSAM

{

QueryValue = 0x0001,

SetValue = 0x0002,

CreateSubKey = 0x0004,

EnumerateSubKeys = 0x0008,

Notify = 0x0010,

CreateLink = 0x0020,

WOW64_32Key = 0x0200,

WOW64_64Key = 0x0100,

WOW64_Res = 0x0300,

Read = 0x00020019,

Write = 0x00020006,

Execute = 0x00020019,

AllAccess = 0x000f003f

}

public static class RegHive

{

public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);

public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);

}

public static class RegistryWOW6432

{

#region Member Variables

#region Read 64bit Reg from 32bit app

[DllImport("Advapi32.dll")]

static extern uint RegOpenKeyEx(

UIntPtr hKey,

string lpSubKey,

uint ulOptions,

int samDesired,

out int phkResult);

[DllImport("Advapi32.dll")]

static extern uint RegCloseKey(int hKey);

[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]

public static extern int RegQueryValueEx(

int hKey, string lpValueName,

int lpReserved,

ref uint lpType,

System.Text.StringBuilder lpData,

ref uint lpcbData);

#endregion

#endregion

#region Functions

static public string GetRegKey64(UIntPtr inHive, String inKeyName, String inPropertyName)

{

return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName);

}

static public string GetRegKey32(UIntPtr inHive, String inKeyName, String inPropertyName)

{

return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName);

}

static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)

{

//UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;

int hkey = 0;

try

{

uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);

if (0 != lResult) return null;

uint lpType = 0;

uint lpcbData = 1024;

StringBuilder AgeBuffer = new StringBuilder(1024);

RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData);

string Age = AgeBuffer.ToString();

return Age;

}

finally

{

if (0 != hkey) RegCloseKey(hkey);

}

}

#endregion

#region Enums

#endregion

}

}

Here is an example of using this class.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

using System;

using System.Runtime.InteropServices;

using System.Text;

namespace Read64bitRegistryFrom32bitApp

{

class Program

{

static void Main(string[] args)

{

string value64 = RegistryWOW6432.GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");

string value32 = RegistryWOW6432.GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");

}

}

}

Example 3 – Adding extension methods to the managed RegistryKey object that read the 64 bit registry from a 32 bit application or vice versa

You know what else is a cool idea? Making it an extension class to the normal managed registry C# code. So you can create a regular managed RegistryKey and then just call an extension function off it.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

using System;

using System.Runtime.InteropServices;

using System.Text;

using Microsoft.Win32;

namespace Read64bitRegistryFrom32bitApp

{

/// <summary>

/// An extension class to allow a registry key to allow it to get the

/// registry in the 32 bit (Wow6432Node) or 64 bit regular registry key

/// </summary>

public static class RegistryWOW6432

{

#region Member Variables

#region Read 64bit Reg from 32bit app

public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);

public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);

[DllImport("Advapi32.dll")]

static extern uint RegOpenKeyEx(

UIntPtr hKey,

string lpSubKey,

uint ulOptions,

int samDesired,

out int phkResult);

[DllImport("Advapi32.dll")]

static extern uint RegCloseKey(int hKey);

[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]

public static extern int RegQueryValueEx(

int hKey, string lpValueName,

int lpReserved,

ref uint lpType,

System.Text.StringBuilder lpData,

ref uint lpcbData);

#endregion

#endregion

#region Functions

public static string GetRegKey64(this RegistryKey inKey, String inPropertyName)

{

string strKey = inKey.ToString();

string regHive = strKey.Split('\\')[0];

string regPath = strKey.Substring(strKey.IndexOf('\\') +1);

return GetRegKey64(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName);

}

public static string GetRegKey32(this RegistryKey inKey, String inPropertyName)

{

string strKey = inKey.ToString();

string regHive = strKey.Split('\\')[0];

string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);

return GetRegKey64(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName);

}

private static UIntPtr GetRegHiveFromString(string inString)

{

if (inString == "HKEY_LOCAL_MACHINE")

return HKEY_LOCAL_MACHINE;

if (inString == "HKEY_CURRENT_USER")

return HKEY_CURRENT_USER;

return UIntPtr.Zero;

}

static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)

{

//UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;

int hkey = 0;

try

{

uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);

if (0 != lResult) return null;

uint lpType = 0;

uint lpcbData = 1024;

StringBuilder AgeBuffer = new StringBuilder(1024);

RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData);

string Age = AgeBuffer.ToString();

return Age;

}

finally

{

if (0 != hkey) RegCloseKey(hkey);

}

}

#endregion

#region Enums

public enum RegSAM

{

QueryValue = 0x0001,

SetValue = 0x0002,

CreateSubKey = 0x0004,

EnumerateSubKeys = 0x0008,

Notify = 0x0010,

CreateLink = 0x0020,

WOW64_32Key = 0x0200,

WOW64_64Key = 0x0100,

WOW64_Res = 0x0300,

Read = 0x00020019,

Write = 0x00020006,

Execute = 0x00020019,

AllAccess = 0x000f003f

}

#endregion

}

}

Here is an example of using these extension functions.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

using System;

using System.Runtime.InteropServices;

using System.Text;

using Microsoft.Win32;

namespace Read64bitRegistryFrom32bitApp

{

class Program

{

static void Main(string[] args)

{

string value64 = string.Empty;

string value32 = string.Empty;

RegistryKey localKey = Registry.LocalMachine;

localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");

if (localKey != null)

{

value32 = localKey.GetRegKey32("RegisteredOrganization");

value64 = localKey.GetRegKey64("RegisteredOrganization");

}

}

}

}

If anything is confusing please comment.

Resources:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s