// Author:
// Miguel de Icaza (miguel@ximian.com)
// Erik LeBel (eriklebel@yahoo.ca)
+// Gert Driesen (drieseng@users.sourceforge.net)
//
-
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+#if !NET_2_1
+
using System;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using Microsoft.Win32.SafeHandles;
namespace Microsoft.Win32
{
/// <summary>
/// Wrapper class for Windows Registry Entry.
/// </summary>
+ [ComVisible (true)]
public sealed class RegistryKey : MarshalByRefObject, IDisposable
{
- const char NullChar = '\0';
-
- // Arbitrary max size for key/values names that can be fetched.
- // .NET framework SDK docs say that the max name length that can
- // be used is 255 characters, we'll allow for a bit more.
- const int BufferMaxLength = 1024;
+ //
+ // This represents the backend data, used when creating the
+ // RegistryKey object
+ //
+ object handle;
+#if NET_4_0
+ SafeRegistryHandle safe_handle;
+#endif
- // FIXME must be a way to determin this dynamically?
- const int Int32ByteSize = 4;
+ object hive; // the RegistryHive if the key represents a base key
+ readonly string qname; // the fully qualified registry key name
+ readonly bool isRemoteRoot; // is an instance of a remote root key?
+ readonly bool isWritable; // is the key openen in writable mode
- // FIXME this is hard coded on Mono, can it be determined dynamically?
- readonly int NativeBytesPerCharacter = Marshal.SystemDefaultCharSize;
+ static readonly IRegistryApi RegistryApi;
- // FIXME this should be determined dynamically.
- // It will be used to decode some return strings
- // for which embeded '\0' must be preserved.
- readonly Encoding Decoder = Encoding.Unicode;
-
-
- IntPtr hkey; // the reg key handle
- string qname; // the fully qualified registry key name
- bool isRoot; // is the an instance of a root key?
-
- IRegistryApi reg_api;
+ static RegistryKey ()
+ {
+ if (Path.DirectorySeparatorChar == '\\')
+ RegistryApi = new Win32RegistryApi ();
+ else
+ RegistryApi = new UnixRegistryApi ();
+ }
/// <summary>
/// Construct an instance of a root registry key entry.
/// </summary>
- internal RegistryKey (RegistryHive hiveId, string keyName)
+ internal RegistryKey (RegistryHive hiveId) : this (hiveId,
+ new IntPtr ((int) hiveId), false)
{
- hkey = new IntPtr ((int)hiveId);
- qname = keyName;
- isRoot = true;
-
- InitRegistryApi ();
}
-
+
/// <summary>
- /// Construct an instance of a registry key entry.
+ /// Construct an instance of a root registry key entry.
/// </summary>
- internal RegistryKey (IntPtr hkey, string keyName)
- {
- this.hkey = hkey;
- qname = keyName;
- isRoot = false;
-
- InitRegistryApi ();
- }
-
- internal void InitRegistryApi ()
+ internal RegistryKey (RegistryHive hiveId, IntPtr keyHandle, bool remoteRoot)
{
- if (Path.DirectorySeparatorChar == '\\')
- reg_api = new Win32RegistryApi ();
- }
-
- private IRegistryApi RegistryApi {
- get {
- if (reg_api == null)
- throw new NotImplementedException ("The registry is" +
- " only available on Windows.");
- return reg_api;
- }
+ hive = hiveId;
+ handle = keyHandle;
+ qname = GetHiveName (hiveId);
+ isRemoteRoot = remoteRoot;
+ isWritable = true; // always consider root writable
}
/// <summary>
- /// Fetch the inetrnal registry key.
+ /// Construct an instance of a registry key entry.
/// </summary>
- private IntPtr Handle {
- get { return hkey; }
+ internal RegistryKey (object data, string keyName, bool writable)
+ {
+ handle = data;
+ qname = keyName;
+ isWritable = writable;
}
-
#region PublicAPI
/// <summary>
/// Dispose of registry key object. Close the
/// key if it's still open.
/// </summary>
+#if NET_4_0
+ public void Dispose ()
+#else
void IDisposable.Dispose ()
+#endif
{
- Close ();
GC.SuppressFinalize (this);
+ Close ();
}
/// </summary>
public void Flush()
{
- RegTrace (" +Flush");
- RegistryApi.RegFlushKey (Handle);
- RegTrace (" -Flush");
+ RegistryApi.Flush (this);
}
/// <summary>
- /// Close the current registry key. This may not
- /// flush the state of the registry right away.
+ /// Close the current registry key and flushes the state of the registry
+ /// right away.
/// </summary>
public void Close()
{
- if (isRoot)
+ Flush ();
+
+ // a handle to a remote hive must be closed, while one to a local
+ // hive should not be closed
+ if (!isRemoteRoot && IsRoot)
return;
- RegTrace (" +Close");
- RegistryApi.RegCloseKey (Handle);
- hkey = IntPtr.Zero;
- RegTrace (" -Close");
+ RegistryApi.Close (this);
+ handle = null;
+#if NET_4_0
+ safe_handle = null;
+#endif
}
/// </summary>
public int SubKeyCount {
get {
- RegTrace (" +SubKeyCount");
AssertKeyStillValid ();
-
- int index, result;
- byte[] stringBuffer = new byte [BufferMaxLength];
-
- for (index = 0; true; index ++)
- {
- result = RegistryApi.RegEnumKey (Handle, index,
- stringBuffer, BufferMaxLength);
-
- if (result == Win32ResultCode.Success)
- continue;
-
- if (result == Win32ResultCode.NoMoreEntries)
- break;
-
- // something is wrong!!
- RegTrace ("Win32Api::ReEnumKey result='{0}' name='{1}'",
- result, Name);
- GenerateException (result);
- }
-
- RegTrace (" -SubKeyCount");
- return index;
+
+ return RegistryApi.SubKeyCount (this);
}
}
/// </summary>
public int ValueCount {
get {
- RegTrace (" +ValueCount");
AssertKeyStillValid ();
-
- int index, result, type, bufferCapacity;
- StringBuilder buffer = new StringBuilder (BufferMaxLength);
-
- for (index = 0; true; index ++)
- {
- type = 0;
- bufferCapacity = buffer.Capacity;
- result = RegistryApi.RegEnumValue (Handle, index,
- buffer, ref bufferCapacity,
- IntPtr.Zero, ref type,
- IntPtr.Zero, IntPtr.Zero);
-
- if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
- continue;
-
- if (result == Win32ResultCode.NoMoreEntries)
- break;
-
- // something is wrong
- RegTrace ("Win32Api::RegEnumValue result='{0}' name='{1}'",
- result, Name);
- GenerateException (result);
+
+ return RegistryApi.ValueCount (this);
+ }
+ }
+
+#if NET_4_0
+ [ComVisible (false)]
+ [MonoTODO ("Not implemented in Unix")]
+ public SafeRegistryHandle Handle {
+ get {
+ AssertKeyStillValid ();
+
+ if (safe_handle == null) {
+ IntPtr h = RegistryApi.GetHandle (this);
+ safe_handle = new SafeRegistryHandle (h, true);
}
- RegTrace (" -ValueCount");
- return index;
+ return safe_handle;
+ }
+ }
+
+ [ComVisible (false)]
+ [MonoLimitation ("View is ignored in Mono.")]
+ public RegistryView View {
+ get {
+ return RegistryView.Default;
}
}
+#endif
/// <summary>
/// </summary>
public void SetValue (string name, object value)
{
- RegTrace (" +SetValue");
AssertKeyStillValid ();
-
+
if (value == null)
- throw new ArgumentNullException ();
-
- Type type = value.GetType ();
- int result;
+ throw new ArgumentNullException ("value");
- if (type == typeof (int))
- {
- int rawValue = (int)value;
- result = RegistryApi.RegSetValueEx (Handle, name,
- IntPtr.Zero, RegistryApi.RegDwordType,
- ref rawValue, Int32ByteSize);
- }
- else if (type == typeof (byte[]))
- {
- byte[] rawValue = (byte[]) value;
- result = RegistryApi.RegSetValueEx (Handle, name,
- IntPtr.Zero, RegistryApi.RegBinaryType,
- rawValue, rawValue.Length);
- }
- else if (type == typeof (string[]))
- {
- string[] vals = (string[]) value;
- StringBuilder fullStringValue = new StringBuilder ();
- foreach (string v in vals)
- {
- fullStringValue.Append (v);
- fullStringValue.Append (NullChar);
- }
- fullStringValue.Append (NullChar);
+ if (name != null)
+ AssertKeyNameLength (name);
- byte[] rawValue = Decoder.GetBytes (fullStringValue.ToString ());
-
- result = RegistryApi.RegSetValueEx (Handle, name,
- IntPtr.Zero, RegistryApi.RegStringArrayType,
- rawValue, rawValue.Length);
- }
- else if (type.IsArray)
- {
- throw new ArgumentException ("Only string and byte arrays can written as registry values");
- }
- else
- {
- string rawValue = String.Format ("{0}{1}", value, NullChar);
- result = RegistryApi.RegSetValueEx (Handle, name,
- IntPtr.Zero, RegistryApi.RegStringType,
- rawValue, rawValue.Length * NativeBytesPerCharacter);
- }
+ if (!IsWritable)
+ throw new UnauthorizedAccessException ("Cannot write to the registry key.");
- // handle the result codes
- if (result != Win32ResultCode.Success)
- {
- RegTrace ("Win32Api::RegSetValueEx: result: {0}", result);
- GenerateException (result);
- }
+ RegistryApi.SetValue (this, name, value);
+ }
+
+ [ComVisible (false)]
+ public void SetValue (string name, object value, RegistryValueKind valueKind)
+ {
+ AssertKeyStillValid ();
- RegTrace (" -SetValue");
+ if (value == null)
+ throw new ArgumentNullException ("value");
+
+ if (name != null)
+ AssertKeyNameLength (name);
+
+ if (!IsWritable)
+ throw new UnauthorizedAccessException ("Cannot write to the registry key.");
+
+ RegistryApi.SetValue (this, name, value, valueKind);
}
-
/// <summary>
/// Open the sub key specified, for read access.
/// </summary>
- public RegistryKey OpenSubKey (string keyName)
+ public RegistryKey OpenSubKey (string name)
{
- return OpenSubKey (keyName, false);
+ return OpenSubKey (name, false);
}
/// <summary>
/// Open the sub key specified.
/// </summary>
- public RegistryKey OpenSubKey (string keyName, bool writtable)
+ public RegistryKey OpenSubKey (string name, bool writable)
{
- RegTrace (" +OpenSubKey");
AssertKeyStillValid ();
- AssertKeyNameNotNull (keyName);
-
- int access = RegistryApi.OpenRegKeyRead;
- if (writtable) access |= RegistryApi.OpenRegKeyWrite;
-
- IntPtr subKeyHandle;
- int result = RegistryApi.RegOpenKeyEx (Handle, keyName, IntPtr.Zero,
- access, out subKeyHandle);
- if (result == Win32ResultCode.FileNotFound)
- {
- RegTrace (" -OpenSubKey");
- return null;
- }
-
- if (result != Win32ResultCode.Success)
- {
- RegTrace ("Win32Api::RegOpenKeyEx result='{0}' key name='{1}'",
- result, CombineName (keyName));
- GenerateException (result);
- }
-
- RegistryKey subKey = new RegistryKey (subKeyHandle, CombineName (keyName));
- RegTrace (" -OpenSubKey");
- return subKey;
+ if (name == null)
+ throw new ArgumentNullException ("name");
+
+ AssertKeyNameLength (name);
+
+ return RegistryApi.OpenSubKey (this, name, writable);
}
/// </summary>
public object GetValue (string name)
{
- RegTrace (" +GetValue");
- object obj = GetValueImpl (name, false, null);
- RegTrace (" -GetValue");
- return obj;
+ return GetValue (name, null);
}
/// </summary>
public object GetValue (string name, object defaultValue)
{
- RegTrace (" +GetValue");
- object obj = GetValueImpl (name, true, defaultValue);
- RegTrace (" -GetValue");
- return obj;
+ AssertKeyStillValid ();
+
+ return RegistryApi.GetValue (this, name, defaultValue,
+ RegistryValueOptions.None);
+ }
+
+ [ComVisible (false)]
+ public object GetValue (string name, object defaultValue, RegistryValueOptions options)
+ {
+ AssertKeyStillValid ();
+
+ return RegistryApi.GetValue (this, name, defaultValue, options);
+ }
+
+ [ComVisible (false)]
+ public RegistryValueKind GetValueKind (string name)
+ {
+ return RegistryApi.GetValueKind (this, name);
}
-
/// <summary>
/// Create a sub key.
/// </summary>
- public RegistryKey CreateSubKey (string keyName)
+ public RegistryKey CreateSubKey (string subkey)
{
- RegTrace (" +CreateSubKey");
AssertKeyStillValid ();
- AssertKeyNameNotNull (keyName);
-
- IntPtr subKeyHandle;
- int result = RegistryApi.RegCreateKey (Handle , keyName, out subKeyHandle);
+ AssertKeyNameNotNull (subkey);
+ AssertKeyNameLength (subkey);
- if (result != Win32ResultCode.Success)
- {
- RegTrace ("Win32Api::RegCreateKey: result='{0}' key name='{1}'",
- result, CombineName (keyName));
- GenerateException (result);
- }
-
- RegistryKey subKey = new RegistryKey (subKeyHandle, CombineName (keyName));
- RegTrace (" -CreateSubKey");
- return subKey;
+ if (!IsWritable)
+ throw new UnauthorizedAccessException ("Cannot write to the registry key.");
+ return RegistryApi.CreateSubKey (this, subkey);
}
-
+
+ [ComVisible (false)]
+ [MonoLimitation ("permissionCheck is ignored in Mono")]
+ public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck)
+ {
+ return CreateSubKey (subkey);
+ }
+
+ [ComVisible (false)]
+ [MonoLimitation ("permissionCheck and registrySecurity are ignored in Mono")]
+ public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity)
+ {
+ return CreateSubKey (subkey);
+ }
+
+#if NET_4_0
+ [ComVisible (false)]
+ [MonoLimitation ("permissionCheck is ignored in Mono")]
+ public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions options)
+ {
+ AssertKeyStillValid ();
+ AssertKeyNameNotNull (subkey);
+ AssertKeyNameLength (subkey);
+
+ if (!IsWritable)
+ throw new UnauthorizedAccessException ("Cannot write to the registry key.");
+
+ return RegistryApi.CreateSubKey (this, subkey, options);
+ }
+
+ [ComVisible (false)]
+ [MonoLimitation ("permissionCheck and registrySecurity are ignored in Mono")]
+ public RegistryKey CreateSubKey (string subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions registryOptions,
+ RegistrySecurity registrySecurity)
+ {
+ return CreateSubKey (subkey, permissionCheck, registryOptions);
+ }
+#endif
+
/// <summary>
/// Delete the specified subkey.
/// <summary>
/// Delete the specified subkey.
/// </summary>
- public void DeleteSubKey(string keyName, bool shouldThrowWhenKeyMissing)
+ public void DeleteSubKey(string subkey, bool throwOnMissingSubKey)
{
- RegTrace (" +DeleteSubKey");
AssertKeyStillValid ();
- AssertKeyNameNotNull (keyName);
-
- RegistryKey child = OpenSubKey (keyName);
+ AssertKeyNameNotNull (subkey);
+ AssertKeyNameLength (subkey);
+
+ if (!IsWritable)
+ throw new UnauthorizedAccessException ("Cannot write to the registry key.");
+
+ RegistryKey child = OpenSubKey (subkey);
- if (child == null)
- {
- if (shouldThrowWhenKeyMissing)
- throw new ArgumentException ("key " + keyName);
- RegTrace (" -DeleteSubKey");
+ if (child == null) {
+ if (throwOnMissingSubKey)
+ throw new ArgumentException ("Cannot delete a subkey tree"
+ + " because the subkey does not exist.");
return;
}
- if (child.SubKeyCount > 0)
- throw new InvalidOperationException ("key " + keyName + " has sub keys");
-
- child.Close ();
-
- int result = RegistryApi.RegDeleteKey (Handle, keyName);
- if (result == Win32ResultCode.FileNotFound)
- {
- if (shouldThrowWhenKeyMissing)
- throw new ArgumentException ("key " + keyName);
- RegTrace (" -DeleteSubKey");
- return;
+ if (child.SubKeyCount > 0){
+ throw new InvalidOperationException ("Registry key has subkeys"
+ + " and recursive removes are not supported by this method.");
}
- if (result != Win32ResultCode.Success)
- {
- RegTrace ("Win32Api::RegDeleteKey: result='{0}' key name='{1}'",
- result, CombineName (keyName));
- GenerateException (result);
- }
+ child.Close ();
- RegTrace (" -DeleteSubKey");
+ RegistryApi.DeleteKey (this, subkey, throwOnMissingSubKey);
}
/// <summary>
/// Delete a sub tree (node, and values alike).
/// </summary>
- public void DeleteSubKeyTree(string keyName)
+ public void DeleteSubKeyTree(string subkey)
+ {
+ DeleteSubKeyTree (subkey, true);
+ }
+
+#if NET_4_0
+ public
+#endif
+ void DeleteSubKeyTree (string subkey, bool throwOnMissingSubKey)
{
// Note: this is done by deleting sub-nodes recursively.
// The preformance is not very good. There may be a
// better way to implement this.
- RegTrace (" +DeleteSubKeyTree");
+
AssertKeyStillValid ();
- AssertKeyNameNotNull (keyName);
+ AssertKeyNameNotNull (subkey);
+ AssertKeyNameLength (subkey);
- RegistryKey child = OpenSubKey (keyName, true);
- if (child == null)
- throw new ArgumentException ("key " + keyName);
+ RegistryKey child = OpenSubKey (subkey, true);
+ if (child == null) {
+ if (!throwOnMissingSubKey)
+ return;
+
+ throw new ArgumentException ("Cannot delete a subkey tree"
+ + " because the subkey does not exist.");
+ }
child.DeleteChildKeysAndValues ();
child.Close ();
- DeleteSubKey (keyName, false);
- RegTrace (" -DeleteSubKeyTree");
+ DeleteSubKey (subkey, false);
}
/// <summary>
/// Delete a value from the registry.
/// </summary>
- public void DeleteValue(string value)
+ public void DeleteValue(string name)
{
- DeleteValue (value, true);
+ DeleteValue (name, true);
}
/// <summary>
/// Delete a value from the registry.
/// </summary>
- public void DeleteValue(string value, bool shouldThrowWhenKeyMissing)
+ public void DeleteValue(string name, bool throwOnMissingValue)
{
- RegTrace (" +DeleteValue");
AssertKeyStillValid ();
- AssertKeyNameNotNull (value);
-
- int result = RegistryApi.RegDeleteValue (Handle, value);
-
- if (result == Win32ResultCode.FileNotFound)
- {
- if (shouldThrowWhenKeyMissing)
- throw new ArgumentException ("value " + value);
- RegTrace (" -DeleteValue");
- return;
- }
-
- if (result != Win32ResultCode.Success)
- {
- RegTrace ("Win32Api::RegDeleteValue: result='{0}' value name='{1}'",
- result, CombineName (value));
- GenerateException (result);
- }
-
- RegTrace (" -DeleteValue");
+
+ if (name == null)
+ throw new ArgumentNullException ("name");
+
+ if (!IsWritable)
+ throw new UnauthorizedAccessException ("Cannot write to the registry key.");
+
+ RegistryApi.DeleteValue (this, name, throwOnMissingValue);
+ }
+
+ public RegistrySecurity GetAccessControl ()
+ {
+ return GetAccessControl (AccessControlSections.Owner |
+ AccessControlSections.Group |
+ AccessControlSections.Access);
+ }
+
+ public RegistrySecurity GetAccessControl (AccessControlSections includeSections)
+ {
+ return new RegistrySecurity (Name, includeSections);
}
/// </summary>
public string[] GetSubKeyNames()
{
- RegTrace (" +GetSubKeyNames");
AssertKeyStillValid ();
-
- byte[] buffer = new byte [BufferMaxLength];
- int bufferCapacity = BufferMaxLength;
- ArrayList keys = new ArrayList ();
-
- for (int index = 0; true; index ++)
- {
- int result = RegistryApi.RegEnumKey (Handle, index, buffer, bufferCapacity);
-
- if (result == Win32ResultCode.Success)
- {
- keys.Add (DecodeString (buffer));
- continue;
- }
-
- if (result == Win32ResultCode.NoMoreEntries)
- break;
- // should not be here!
- RegTrace ("Win32Api::RegEnumKey: result='{0}' value name='{1}'",
- result, CombineName (Name));
- GenerateException (result);
- }
-
- RegTrace (" -GetSubKeyNames");
- return (string []) keys.ToArray (typeof(String));
+ return RegistryApi.GetSubKeyNames (this);
}
/// </summary>
public string[] GetValueNames()
{
- RegTrace (" +GetValueNames");
AssertKeyStillValid ();
-
- ArrayList values = new ArrayList ();
-
- for (int index = 0; true; index ++)
- {
- StringBuilder buffer = new StringBuilder (BufferMaxLength);
- int bufferCapacity = buffer.Capacity;
- int type = 0;
-
- int result = RegistryApi.RegEnumValue (Handle, index, buffer, ref bufferCapacity,
- IntPtr.Zero, ref type, IntPtr.Zero, IntPtr.Zero);
+ return RegistryApi.GetValueNames (this);
+ }
- if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
- {
- values.Add (buffer.ToString ());
- continue;
- }
-
- if (result == Win32ResultCode.NoMoreEntries)
- break;
-
- // should not be here!
- RegTrace ("RegistryApi.RegEnumValue: result code='{0}' name='{1}'",
- result, CombineName (Name));
- GenerateException (result);
- }
+#if NET_4_0
+ [ComVisible (false)]
+ [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ [MonoTODO ("Not implemented on unix")]
+ public static RegistryKey FromHandle (SafeRegistryHandle handle)
+ {
+ if (handle == null)
+ throw new ArgumentNullException ("handle");
- RegTrace (" -GetValueNames");
- return (string []) values.ToArray (typeof(String));
+ return RegistryApi.FromHandle (handle);
}
+
+ [ComVisible (false)]
+ [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ [MonoTODO ("Not implemented on unix")]
+ public static RegistryKey FromHandle (SafeRegistryHandle handle, RegistryView view)
+ {
+ return FromHandle (handle);
+ }
+#endif
- [MonoTODO]
+ [MonoTODO ("Not implemented on unix")]
public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey,string machineName)
{
- throw new NotImplementedException ();
+ if (machineName == null)
+ throw new ArgumentNullException ("machineName");
+ return RegistryApi.OpenRemoteBaseKey (hKey, machineName);
+ }
+
+#if NET_4_0
+ [ComVisible (false)]
+ [MonoTODO ("Not implemented on unix")]
+ public static RegistryKey OpenRemoteBaseKey (RegistryHive hKey, string machineName, RegistryView view)
+ {
+ if (machineName == null)
+ throw new ArgumentNullException ("machineName");
+ return RegistryApi.OpenRemoteBaseKey (hKey, machineName);
+ }
+
+ [ComVisible (false)]
+ [MonoLimitation ("View is ignored in Mono")]
+ public static RegistryKey OpenBaseKey (RegistryHive hKey, RegistryView view)
+ {
+ switch (hKey) {
+ case RegistryHive.ClassesRoot:
+ return Registry.ClassesRoot;
+ case RegistryHive.CurrentConfig:
+ return Registry.CurrentConfig;
+ case RegistryHive.CurrentUser:
+ return Registry.CurrentUser;
+ case RegistryHive.DynData:
+ return Registry.DynData;
+ case RegistryHive.LocalMachine:
+ return Registry.LocalMachine;
+ case RegistryHive.PerformanceData:
+ return Registry.PerformanceData;
+ case RegistryHive.Users:
+ return Registry.Users;
+ }
+
+ throw new ArgumentException ("hKey");
+ }
+#endif
+
+ [ComVisible (false)]
+ public RegistryKey OpenSubKey (string name, RegistryKeyPermissionCheck permissionCheck)
+ {
+ return OpenSubKey (name, permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree);
+ }
+
+ [ComVisible (false)]
+ [MonoLimitation ("rights are ignored in Mono")]
+ public RegistryKey OpenSubKey (string name, RegistryKeyPermissionCheck permissionCheck, RegistryRights rights)
+ {
+ return OpenSubKey (name, permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree);
+ }
+
+ public void SetAccessControl (RegistrySecurity registrySecurity)
+ {
+ if (null == registrySecurity)
+ throw new ArgumentNullException ("registrySecurity");
+
+ registrySecurity.PersistModifications (Name);
}
/// </summary>
public override string ToString()
{
- return String.Format ("{0} [0x{1:X}]", Name, Handle.ToInt32 ());
+ AssertKeyStillValid ();
+
+ return RegistryApi.ToString (this);
}
#endregion // PublicAPI
-
+ internal bool IsRoot {
+ get { return hive != null; }
+ }
+
+ private bool IsWritable {
+ get { return isWritable; }
+ }
+
+ internal RegistryHive Hive {
+ get {
+ if (!IsRoot)
+ throw new NotSupportedException ();
+ return (RegistryHive) hive;
+ }
+ }
+
+ // returns the key handle for the win32 implementation and the
+ // KeyHandler for the unix implementation
+ internal object InternalHandle {
+ get { return handle; }
+ }
+
/// <summary>
/// validate that the registry key handle is still usable.
/// </summary>
private void AssertKeyStillValid ()
{
- if (Handle == IntPtr.Zero)
+ if (handle == null)
throw new ObjectDisposedException ("Microsoft.Win32.RegistryKey");
}
private void AssertKeyNameNotNull (string subKeyName)
{
if (subKeyName == null)
- throw new ArgumentNullException ();
+ throw new ArgumentNullException ("name");
+ }
+
+ private void AssertKeyNameLength (string name)
+ {
+ if (name.Length > 255)
+ throw new ArgumentException ("Name of registry key cannot be greater than 255 characters");
}
-
/// <summary>
/// Utility method to delelte a key's sub keys and values.
/// </summary>
private void DeleteChildKeysAndValues ()
{
- RegTrace (" +DeleteChildKeysAndValues");
- if (isRoot)
- {
- RegTrace (" -DeleteChildKeysAndValues");
+ if (IsRoot)
return;
- }
string[] subKeys = GetSubKeyNames ();
foreach (string subKey in subKeys)
}
string[] values = GetValueNames ();
- foreach (string value in values)
- {
+ foreach (string value in values) {
DeleteValue (value, false);
}
-
- RegTrace (" -DeleteChildKeysAndValues");
}
-
- /// <summary>
- /// Acctually read a registry value. Requires knoledge of the
- /// value's type and size.
- /// </summary>
- private object GetValueImpl (string name, bool returnDefaultValue, object defaultValue)
- {
- RegTrace (" +GetValueImpl");
- AssertKeyStillValid ();
-
- int type = 0;
- int size = 0;
- object obj = null;
-
- int result = RegistryApi.RegQueryValueEx (Handle, name, IntPtr.Zero,
- ref type, IntPtr.Zero, ref size);
-
- if (result == Win32ResultCode.FileNotFound)
- {
- if (returnDefaultValue) {
- RegTrace (" -GetValueImpl");
- return defaultValue;
- }
- return null;
- }
-
- if (result != Win32ResultCode.MoreData && result != Win32ResultCode.Success )
- {
- RegTrace ("Win32Api::RegQueryValueEx: result='{0}' name='{1}' type='{2}' size='{3}'",
- result, name, type, size);
- GenerateException (result);
- }
-
- if (type == RegistryApi.RegStringType || type == RegistryApi.RegEnvironmentString)
- {
- byte[] data;
- result = GetBinaryValue (name, type, out data, size);
- obj = DecodeString (data);
- }
- else if (type == RegistryApi.RegDwordType)
- {
- int data = 0;
- result = RegistryApi.RegQueryValueEx (Handle, name, IntPtr.Zero,
- ref type, ref data, ref size);
- obj = data;
- }
- else if (type == RegistryApi.RegBinaryType)
- {
- byte[] data;
- result = GetBinaryValue (name, type, out data, size);
- obj = data;
- }
- else if (type == RegistryApi.RegStringArrayType)
- {
- obj = null;
- byte[] data;
- result = GetBinaryValue (name, type, out data, size);
-
- if (result == Win32ResultCode.Success)
- obj = DecodeString (data).Split (NullChar);
- }
- else
- {
- // should never get here
- throw new SystemException ();
- }
-
- // check result codes again:
- if (result != Win32ResultCode.Success)
- {
- RegTrace ("Win32Api::RegQueryValueEx: result='{0}' name='{1}'",
- result, name);
- GenerateException (result);
- }
-
- RegTrace (" -ReadValueImpl");
- return obj;
- }
-
-
- /// <summary>
- /// Get a binary value.
- /// </summary>
- private int GetBinaryValue (string name, int type, out byte[] data, int size)
- {
- byte[] internalData = new byte [size];
- int result = RegistryApi.RegQueryValueEx (Handle, name,
- IntPtr.Zero, ref type, internalData, ref size);
- data = internalData;
- return result;
- }
-
-
/// <summary>
/// decode a byte array as a string, and strip trailing nulls
/// </summary>
- private string DecodeString (byte[] data)
+ static internal string DecodeString (byte[] data)
{
- string stringRep = Decoder.GetString (data);
- int idx = stringRep.IndexOf (NullChar);
- if (idx >= 0)
- stringRep = stringRep.Substring (0, idx);
+ string stringRep = Encoding.Unicode.GetString (data);
+ int idx = stringRep.IndexOf ('\0');
+ if (idx != -1)
+ stringRep = stringRep.TrimEnd ('\0');
return stringRep;
}
-
-
- /// <summary>
- /// utility: Combine the sub key name to the current name to produce a
- /// fully qualified sub key name.
- /// </summary>
- private string CombineName (string localName)
+
+ static internal IOException CreateMarkedForDeletionException ()
{
- return String.Format ("{0}\\{1}", Name, localName);
+ throw new IOException ("Illegal operation attempted on a"
+ + " registry key that has been marked for deletion.");
}
-
-
- /// <summary>
- /// convert a win32 error code into an appropriate exception.
- /// </summary>
- private void GenerateException (int errorCode)
- {
- switch (errorCode) {
- case Win32ResultCode.FileNotFound:
- case Win32ResultCode.InvalidParameter:
- throw new ArgumentException ();
-
- case Win32ResultCode.AccessDenied:
- throw new SecurityException ();
- default:
- // unidentified system exception
- throw new SystemException ();
- }
- }
-
-#if (false)
- /// <summary>
- /// dump trace messages if this code was compiled with tracing enabled.
- /// </summary>
- [Conditional("TRACE")]
- private static void RegTrace (string message, params object[] args)
+ static string GetHiveName (RegistryHive hive)
{
- message = "REG " + message;
- if (args.Length > 0)
- message = String.Format (message, args);
+ switch (hive) {
+ case RegistryHive.ClassesRoot:
+ return "HKEY_CLASSES_ROOT";
+ case RegistryHive.CurrentConfig:
+ return "HKEY_CURRENT_CONFIG";
+ case RegistryHive.CurrentUser:
+ return "HKEY_CURRENT_USER";
+ case RegistryHive.DynData:
+ return "HKEY_DYN_DATA";
+ case RegistryHive.LocalMachine:
+ return "HKEY_LOCAL_MACHINE";
+ case RegistryHive.PerformanceData:
+ return "HKEY_PERFORMANCE_DATA";
+ case RegistryHive.Users:
+ return "HKEY_USERS";
+ }
- Trace.WriteLine (message);
- //Console.WriteLine (message);
- }
-#endif
- private static void RegTrace (string message, params object[] args)
- {
+ throw new NotImplementedException (string.Format (
+ "Registry hive '{0}' is not implemented.", hive.ToString ()));
}
+
}
}
+#endif // NET_2_1
+