title: Access HKCU for impersonated user: P/Invoke "RegOpenCurrentUser" returns empty handle in Windows XP
body: <p>I have a problem to access the HKEY_CURRENT_USER registry key for an impersonated user.</p>
  
  <p>After some research, I'm currently using Win32 Api <code>RegOpenCurrentUser</code>.
  Since there's no documentation in P/Invoke website, I've retrieved this signature from what I've found on <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724894%28v=vs.85%29.aspx" rel="nofollow">this MSDN page</a>:</p>
  
  <pre><code>[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
  public static extern int RegOpenCurrentUser(int samDesired, out IntPtr phkResult);
  </code></pre>
  
  <p>I'm using it this way:</p>
  
  <pre><code>public class LocalRegistryAccess
  {
      [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
      public static extern int RegOpenCurrentUser(int samDesired, out IntPtr phkResult);
  
      public enum RegistrySecurity
      {
          KEY_ALL_ACCESS = 0xF003F,
          KEY_CREATE_LINK = 0x0020,
          KEY_CREATE_SUB_KEY = 0x0004,
          KEY_ENUMERATE_SUB_KEYS = 0x0008,
          KEY_EXECUTE = 0x20019,
          KEY_NOTIFY = 0x0010,
          KEY_QUERY_VALUE = 0x0001,
          KEY_READ = 0x20019,
          KEY_SET_VALUE = 0x0002,
          KEY_WOW64_32KEY = 0x0200,
          KEY_WOW64_64KEY = 0x0100,
          KEY_WRITE = 0x20006,
      }
  
      public IntPtr GetImpersonatedUserRegistryHandle(RegistrySecurity _access)
      {
          IntPtr safeHandle = new IntPtr();
          int result = RegOpenCurrentUser((int)_access, out safeHandle);
  
          return safeHandle;
      }
  
      public RegistryKey _pointerToRegistryKey(IntPtr hKey, bool writable, bool ownsHandle)
      {
          //Get the BindingFlags for private contructors
          System.Reflection.BindingFlags privateConstructors = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
  
          //Get the Type for the SafeRegistryHandle
          Type safeRegistryHandleType = typeof(Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid).Assembly.GetType("Microsoft.Win32.SafeHandles.SafeRegistryHandle");
  
          //Get the array of types matching the args of the ctor we want
          Type[] safeRegistryHandleCtorTypes = new Type[] { typeof(IntPtr), typeof(bool) };
  
          //Get the constructorinfo for our object
          System.Reflection.ConstructorInfo safeRegistryHandleCtorInfo = safeRegistryHandleType.GetConstructor(privateConstructors, null, safeRegistryHandleCtorTypes, null);
  
          //Invoke the constructor, getting us a SafeRegistryHandle
          Object safeHandle = safeRegistryHandleCtorInfo.Invoke(new Object[] { hKey, ownsHandle });
  
          //Get the type of a RegistryKey
          Type registryKeyType = typeof(RegistryKey);
  
          //Get the array of types matching the args of the ctor we want
          Type[] registryKeyConstructorTypes = new Type[] { safeRegistryHandleType, typeof(bool) };
  
          //Get the constructorinfo for our object
          System.Reflection.ConstructorInfo registryKeyCtorInfo = registryKeyType.GetConstructor(privateConstructors, null, registryKeyConstructorTypes, null);
  
          //Invoke the constructor, getting us a RegistryKey
          RegistryKey resultKey = (RegistryKey)registryKeyCtorInfo.Invoke(new Object[] { safeHandle, writable });
  
          //return the resulting key
          return resultKey;
      }
  }
  
  public class UserManagement
  {
      LocalRegistryAccess regAccess = new LocalRegistryAccess();
  
      using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(token))
      {
          IntPtr localRegistryHandle = regAccess.GetImpersonatedUserRegistryHandle(LocalRegistryAccess.RegistrySecurity.KEY_ALL_ACCESS);
          using(RegistryKey localRegistry = regAccess._pointerToRegistryKey(localRegistryHandle, true, true))
          {
              // Manage HKCU for impersonated user
          }
      }
  }
  </code></pre>
  
  <p>This code seems to work correctly on Windows 7, but does not work in Windows XP Embedded: my method <code>GetImpersonatedUserRegistryHandle</code> always return an empty handle.</p>
  
  <p>Any thought? Am I missing some instruction in order to make this code compatible with Windows XP Embedded?</p>