dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnetlib/runtime/Microsoft/Win32 FileKeyProvid


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnetlib/runtime/Microsoft/Win32 FileKeyProvider.cs, NONE, 1.1 Registry.cs, 1.3, 1.4
Date: Thu, 24 Jul 2003 01:02:47 -0400

Update of /cvsroot/dotgnu-pnet/pnetlib/runtime/Microsoft/Win32
In directory subversions:/tmp/cvs-serv18392/runtime/Microsoft/Win32

Modified Files:
        Registry.cs 
Added Files:
        FileKeyProvider.cs 
Log Message:


Implement a file-based registry provider for non-Win32 systems;
the data is stored under the "$HOME/.cli/registry" directory.


--- NEW FILE ---
/*
 * FileKeyProvider.cs - Implementation of the
 *                      "Microsoft.Win32.FileKeyProvider" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace Microsoft.Win32
{

#if CONFIG_WIN32_SPECIFICS

using System;
using System.Collections;
using System.IO;
using System.Security;
using Platform;

// This class implements a file-based registry on disk.  The registry
// is stored within the "$HOME/.cli" directory.  This can be overridden
// with the "CLI_STORAGE_ROOT" environment variable.
//
// Each registry key is stored as a sub-directory within the filesystem.
// Sub-keys are represented as sub-directories underneath their parent.
//
// Values are stored in a file called "values.reg" within the sub-directory
// that corresponds to the registry key.  The format is XML-based, with
// the following structure:
//
//    <values>
//      <value name="foo" type="bar">...</value>
//      ...
//    </values>
//
// The "type" attribute may be set to one of "string", "int", "uint",
// "long", "ulong", "binary", or "strings".  In the first 5 cases,
// the text within the "value" tag is the string form of the value.
// If the type is not recognized, it is treated as "string".
//
// In the case of "binary", the content is the base64-encoded binary
// value.  In the case of "strings", the content is a list of "string"
// tags, each one defining an individual list element.  e.g.
//
//    <values>
//      <value name="foo" type="strings">
//        <string>abc</string>
//        <string>def</string>
//        ...
//      </value>
//      ...
//    </values>

internal sealed class FileKeyProvider : IRegistryKeyProvider
{
        // Internal state.
        private String directory;
        private String fullName;
        private SecurityElement values;
        private bool modified;

        // Directory names under "$HOME/.cli/registry" that correspond
        // to the various registry hives.
        private static readonly String[] hiveDirectories = {
                        "ClassesRoot",
                        "CurrentUser",
                        "LocalMachine",
                        "Users",
                        "PerformanceData",
                        "CurrentConfig",
                        "DynData"
                };

        // Create a directory.
        private static void CreateDirectory(String name)
                        {
                                if(Directory.Exists(name))
                                {
                                        return;
                                }
                                Errno error = DirMethods.CreateDirectory(name);
                                if(error != Errno.Success && error != 
Errno.EEXIST)
                                {
                                        throw new NotSupportedException();
                                }
                        }

        // Constructors.
        private FileKeyProvider(FileKeyProvider parent, String name)
                        {
                                // Record the name information for later.
                                this.fullName = parent.fullName + "\\" + name;

                                // Build the full pathname for the directory.
                                this.directory =
                                        parent.directory + 
Path.DirectorySeparatorChar + name;
                        }
        public FileKeyProvider(RegistryHive hive, String name)
                        {
                                // Record the name information for later.
                                this.fullName = name;

                                // Find the root position of the registry.
                                String root = Environment.GetEnvironmentVariable
                                        ("CLI_STORAGE_ROOT");
                                if(root == null || root == String.Empty)
                                {
                                        String home = 
Environment.GetEnvironmentVariable("HOME");
                                        if(home == null || home == String.Empty 
||
                                           !Directory.Exists(home))
                                        {
                                                throw new 
NotSupportedException();
                                        }
                                        root = home + 
Path.DirectorySeparatorChar + ".cli";
                                        CreateDirectory(root);
                                }

                                // Build the full pathname for the hive 
directory.
                                directory = root + Path.DirectorySeparatorChar 
+ "registry";
                                CreateDirectory(directory);
                                directory = directory + 
Path.DirectorySeparatorChar +
                                                hiveDirectories
                                                        [((int)hive) - 
((int)RegistryHive.ClassesRoot)];
                                CreateDirectory(directory);
                        }

        // Close a reference to this key and flush any modifications to disk.
        public void Close(bool writable)
                        {
                                Flush();
                        }

        // Create a subkey underneath this particular registry key.
        public IRegistryKeyProvider CreateSubKey(String subkey)
                        {
                                String dir = directory + 
Path.DirectorySeparatorChar + subkey;
                                if(Directory.Exists(dir))
                                {
                                        return new FileKeyProvider(this, 
subkey);
                                }
                                Errno error = DirMethods.CreateDirectory(dir);
                                if(error == Errno.Success || error == 
Errno.EEXIST)
                                {
                                        return new FileKeyProvider(this, 
subkey);
                                }
                                throw new 
ArgumentException(_("IO_RegistryKeyNotExist"));
                        }

        // Returns true if we should delete subkeys from their parents.
        public bool DeleteFromParents
                        {
                                get
                                {
                                        // Use "Delete" and "DeleteTree".
                                        return false;
                                }
                        }

        // Delete a subkey of this key entry.  Returns false if not present.
        public bool DeleteSubKey(String name)
                        {
                                // Not used by this registry key provider.
                                return false;
                        }

        // Delete this key entry.
        public void Delete()
                        {
                                try
                                {
                                        
if((Directory.GetDirectories(directory)).Length != 0)
                                        {
                                                throw new 
InvalidOperationException
                                                        
(_("IO_RegistryHasSubKeys"));
                                        }
                                        File.Delete(directory + 
Path.DirectorySeparatorChar +
                                                                "values.reg");
                                        Directory.Delete(directory);
                                }
                                catch(IOException)
                                {
                                        // We probably couldn't delete because 
it doesn't exist.
                                }
                        }

        // Delete a subkey entry and all of its descendents.
        // Returns false if not present.
        public bool DeleteSubKeyTree(String name)
                        {
                                // Not used by this registry key provider.
                                return false;
                        }

        // Delete this key entry and all of its descendents.
        public void DeleteTree()
                        {
                                try
                                {
                                        Directory.Delete(directory, true);
                                }
                                catch(IOException)
                                {
                                        // We probably couldn't delete because 
it doesn't exist.
                                }
                        }

        // Fetch the contents of the "values.reg" file into the internal cache.
        private void ReadToCache()
                        {
                                try
                                {
                                        StreamReader reader = new StreamReader
                                                (directory + 
Path.DirectorySeparatorChar +
                                                 "values.reg");
                                        String xml = reader.ReadToEnd();
                                        reader.Close();
                                        values = SecurityElement.Parse(xml);
                                }
                                catch(IOException)
                                {
                                        values = new SecurityElement("values");
                                }
                        }

        // Find the security element corresponding to a particular value.
        private SecurityElement FindValue(String name)
                        {
                                if(values == null)
                                {
                                        ReadToCache();
                                }
                                ArrayList children = values.Children;
                                if(children != null)
                                {
                                        foreach(SecurityElement e in children)
                                        {
                                                if(e.Tag == "value" &&
                                                   e.Attribute("name") == name)
                                                {
                                                        return e;
                                                }
                                        }
                                }
                                return null;
                        }

        // Delete a particular value underneath this registry key.
        // Returns false if the value is missing.
        public bool DeleteValue(String name)
                        {
                                lock(this)
                                {
                                        SecurityElement e = FindValue(name);
                                        if(e != null)
                                        {
                                                values.Children.Remove(e);
                                                modified = true;
                                                return true;
                                        }
                                        else
                                        {
                                                return false;
                                        }
                                }
                        }

        // Flush all modifications to this registry key.
        public void Flush()
                        {
                                lock(this)
                                {
                                        if(values != null && modified)
                                        {
                                                try
                                                {
                                                        StreamWriter writer = 
new StreamWriter
                                                                (directory + 
Path.DirectorySeparatorChar +
                                                                 "values.reg");
                                                        
writer.Write(values.ToString());
                                                        writer.Close();
                                                }
                                                catch(IOException)
                                                {
                                                        // Could not create the 
file for some reason.
                                                }
                                        }
                                        values = null;
                                        modified = false;
                                }
                        }

        // Get the names of all subkeys underneath this registry key.
        public String[] GetSubKeyNames()
                        {
                                return Directory.GetDirectories(directory);
                        }

        // Get a value from underneath this registry key.
        public Object GetValue(String name, Object defaultValue)
                        {
                                lock(this)
                                {
                                        SecurityElement e = FindValue(name);
                                        if(e != null)
                                        {
                                                String type = 
e.Attribute("type");
                                                if(type == null)
                                                {
                                                        type = "string";
                                                }
                                                Object value;
                                                String text = e.Text;
                                                if(text == null)
                                                {
                                                        text = String.Empty;
                                                }
                                                switch(type)
                                                {
                                                        case "string": default:
                                                        {
                                                                value = text;
                                                        }
                                                        break;

                                                        case "int":
                                                        {
                                                                value = 
Int32.Parse(text);
                                                        }
                                                        break;

                                                        case "uint":
                                                        {
                                                                value = 
UInt32.Parse(text);
                                                        }
                                                        break;

                                                        case "long":
                                                        {
                                                                value = 
Int64.Parse(text);
                                                        }
                                                        break;

                                                        case "ulong":
                                                        {
                                                                value = 
UInt64.Parse(text);
                                                        }
                                                        break;

                                                        case "binary":
                                                        {
                                                                value = 
Convert.FromBase64String(text);
                                                        }
                                                        break;

                                                        case "strings":
                                                        {
                                                                ArrayList 
children = e.Children;
                                                                ArrayList list 
= new ArrayList();
                                                                if(children != 
null)
                                                                {
                                                                        
foreach(SecurityElement elem in children)
                                                                        {
                                                                                
if(elem.Tag == "string")
                                                                                
{
                                                                                
        text = elem.Text;
                                                                                
        if(text == null)
                                                                                
        {
                                                                                
                text = String.Empty;
                                                                                
        }
                                                                                
        list.Add(text);
                                                                                
}
                                                                        }
                                                                }
                                                                value = 
list.ToArray(typeof(String));
                                                        }
                                                        break;
                                                }
                                                return value;
                                        }
                                        else
                                        {
                                                return defaultValue;
                                        }
                                }
                        }

        // Get the names of all values underneath this registry key.
        public String[] GetValueNames()
                        {
                                lock(this)
                                {
                                        if(values == null)
                                        {
                                                ReadToCache();
                                        }
                                        ArrayList children = values.Children;
                                        ArrayList list = new ArrayList();
                                        if(children != null)
                                        {
                                                foreach(SecurityElement elem in 
children)
                                                {
                                                        if(elem.Tag == "value")
                                                        {
                                                                
list.Add(elem.Attribute("name"));
                                                        }
                                                }
                                        }
                                        return 
(String[])(list.ToArray(typeof(String)));
                                }
                        }

        // Open a subkey.
        public IRegistryKeyProvider OpenSubKey(String name, bool writable)
                        {
                                String dir = directory + 
Path.DirectorySeparatorChar + name;
                                if(Directory.Exists(dir))
                                {
                                        return new FileKeyProvider(this, name);
                                }
                                else
                                {
                                        return null;
                                }
                        }

        // Set a value under this registry key.
        public void SetValue(String name, Object value)
                        {
                                lock(this)
                                {
                                        // Find or create a tag for this name.
                                        SecurityElement e = FindValue(name);
                                        if(e == null)
                                        {
                                                e = new 
SecurityElement("value");
                                                e.AddAttribute("name", 
SecurityElement.Escape(name));
                                                values.AddChild(e);
                                        }

                                        // Modify the value associated with the 
tag.
                                        e.Children = null;
                                        if(value is String)
                                        {
                                                e.SetAttribute("type", 
"string");
                                                e.Text = 
SecurityElement.Escape((String)value);
                                        }
                                        else if(value is int)
                                        {
                                                e.SetAttribute("type", "int");
                                                e.Text = 
((int)value).ToString();
                                        }
                                        else if(value is uint)
                                        {
                                                e.SetAttribute("type", "uint");
                                                e.Text = 
((uint)value).ToString();
                                        }
                                        else if(value is long)
                                        {
                                                e.SetAttribute("type", "long");
                                                e.Text = 
((long)value).ToString();
                                        }
                                        else if(value is ulong)
                                        {
                                                e.SetAttribute("type", "ulong");
                                                e.Text = 
((ulong)value).ToString();
                                        }
                                        else if(value is byte[])
                                        {
                                                e.SetAttribute("type", 
"binary");
                                                e.Text = 
Convert.ToBase64String((byte[])value);
                                        }
                                        else if(value is String[])
                                        {
                                                e.SetAttribute("type", 
"strings");
                                                String[] list = (String[])value;
                                                SecurityElement child;
                                                foreach(String str in list)
                                                {
                                                        child = new 
SecurityElement("string");
                                                        if(str == null)
                                                        {
                                                                str = 
String.Empty;
                                                        }
                                                        child.Text = 
SecurityElement.Escape(str);
                                                        e.AddChild(child);
                                                }
                                        }
                                        else
                                        {
                                                // Treat everything else as a 
string.
                                                e.SetAttribute("type", 
"string");
                                                e.Text = 
SecurityElement.Escape(value.ToString());
                                        }

                                        // The value has been modified.
                                        modified = true;
                                }
                        }

        // Get the name of this registry key provider.
        public String Name
                        {
                                get
                                {
                                        return fullName;
                                }
                        }

        // Get the number of subkeys underneath this key.
        public int SubKeyCount
                        {
                                get
                                {
                                        return 
(Directory.GetDirectories(directory)).Length;
                                }
                        }

        // Get the number of values that are associated with this key.
        public int ValueCount
                        {
                                get
                                {
                                        lock(this)
                                        {
                                                if(values == null)
                                                {
                                                        return 0;
                                                }
                                                ArrayList children = 
values.Children;
                                                int count = 0;
                                                if(children != null)
                                                {
                                                        foreach(SecurityElement 
elem in children)
                                                        {
                                                                if(elem.Tag == 
"value")
                                                                {
                                                                        ++count;
                                                                }
                                                        }
                                                }
                                                return count;
                                        }
                                }
                        }

}; // class FileKeyProvider

#endif // CONFIG_WIN32_SPECIFICS

}; // namespace Microsoft.Win32

Index: Registry.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/runtime/Microsoft/Win32/Registry.cs,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** Registry.cs 29 May 2003 05:38:18 -0000      1.3
--- Registry.cs 24 Jul 2003 05:02:44 -0000      1.4
***************
*** 92,95 ****
--- 92,106 ----
                                        }
  
+                                       // Try to create a file-based provider 
for the hive.
+                                       try
+                                       {
+                                               providers[index] = new 
FileKeyProvider(hKey, name);
+                                               return providers[index];
+                                       }
+                                       catch(NotSupportedException)
+                                       {
+                                               // Could not create the hive 
directory - fall through.
+                                       }
+ 
                                        // Create a memory-based provider on 
all other systems.
                                        providers[index] = new MemoryKeyProvider





reply via email to

[Prev in Thread] Current Thread [Next in Thread]