This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / system / regedit / regedit.c
diff --git a/subsys/system/regedit/regedit.c b/subsys/system/regedit/regedit.c
new file mode 100644 (file)
index 0000000..023abb7
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Windows regedit.exe registry editor implementation.
+ *
+ * Copyright 2002 Andriy Palamarchuk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <windows.h>
+#include "regproc.h"
+
+static char *usage =
+"Usage:\n"
+"    regedit filename\n"
+"    regedit /E filename [regpath]\n"
+"    regedit /D regpath\n"
+"\n"
+"filename - registry file name\n"
+"regpath - name of the registry key\n"
+"\n"
+"When is called without any switches adds contents of the specified\n"
+"registry file to the registry\n"
+"\n"
+"Switches:\n"
+"    /E - exports contents of the specified registry key to the specified\n"
+"      file. Exports the whole registry if no key is specified.\n"
+"    /D - deletes specified registry key\n"
+"    /S - silent execution, can be used with any other switch.\n"
+"      The only existing mode, exists for compatibility with Windows regedit.\n"
+"    /V - advanced mode, can be used with any other switch.\n"
+"      Ignored, exists for compatibility with Windows regedit.\n"
+"    /L - location of system.dat file. Can be used with any other switch.\n"
+"      Ignored. Exists for compatibility with Windows regedit.\n"
+"    /R - location of user.dat file. Can be used with any other switch.\n"
+"      Ignored. Exists for compatibility with Windows regedit.\n"
+"    /? - print this help. Any other switches are ignored.\n"
+"    /C - create registry from. Not implemented.\n"
+"\n"
+"The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
+"This program is command-line compatible with Microsoft Windows\n"
+"regedit. The difference with Windows regedit - this application has\n"
+"command-line interface only.\n";
+
+typedef enum {
+    ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
+} REGEDIT_ACTION;
+
+BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s);
+
+/**
+ * Process unknown switch.
+ *
+ * Params:
+ *   chu - the switch character in upper-case.
+ *   s - the command line string where s points to the switch character.
+ */
+void error_unknown_switch(char chu, char *s)
+{
+    if (isalpha(chu))
+    {
+        printf("%s: Undefined switch /%c!\n", getAppName(), chu);
+    } else {
+        printf("%s: Alphabetic character is expected after '%c' "
+               "in switch specification\n", getAppName(), *(s - 1));
+    }
+    exit(1);
+}
+
+BOOL ProcessCmdLine(LPSTR lpCmdLine)
+{
+    REGEDIT_ACTION action = ACTION_UNDEF;
+    LPSTR s = lpCmdLine;        /* command line pointer */
+    CHAR ch = *s;               /* current character */
+
+    setAppName("regedit");
+    while (ch && ((ch == '-') || (ch == '/')))
+    {
+        char chu;
+        char ch2;
+
+        s++;
+        ch = *s;
+        ch2 = *(s+1);
+        chu = toupper(ch);
+        if (!ch2 || isspace(ch2))
+        {
+            if (chu == 'S' || chu == 'V')
+            {
+                /* ignore these switches */
+            } else {
+                switch (chu)
+                {
+                case 'D':
+                    action = ACTION_DELETE;
+                    break;
+                case 'E':
+                    action = ACTION_EXPORT;
+                    break;
+                case '?':
+                    printf(usage);
+                    exit(0);
+                    break;
+                default:
+                    error_unknown_switch(chu, s);
+                    break;
+                }
+            }
+            s++;
+        } else {
+            if (ch2 == ':')
+            {
+                switch (chu)
+                {
+                case 'L':
+                    /* fall through */
+                case 'R':
+                    s += 2;
+                    while (*s && !isspace(*s))
+                    {
+                        s++;
+                    }
+                    break;
+                default:
+                    error_unknown_switch(chu, s);
+                    break;
+                }
+            } else {
+                /* this is a file name, starting from '/' */
+                s--;
+                break;
+            }
+        }
+        /* skip spaces to the next parameter */
+        ch = *s;
+        while (ch && isspace(ch))
+        {
+            s++;
+            ch = *s;
+        }
+    }
+
+    if (*s && action == ACTION_UNDEF)
+        action = ACTION_ADD;
+
+    if (action == ACTION_UNDEF)
+        return FALSE;
+
+    return PerformRegAction(action, s);
+}
+
+BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
+{
+    switch (action)
+    {
+    case ACTION_ADD:
+    {
+        CHAR filename[MAX_PATH];
+        FILE *reg_file;
+
+        get_file_name(&s, filename);
+        if (!filename[0])
+        {
+            printf("%s: No file name is specified\n", getAppName());
+            printf(usage);
+            exit(1);
+        }
+
+        while(filename[0])
+        {
+            reg_file = fopen(filename, "r");
+            if (reg_file)
+            {
+                processRegLines(reg_file, doSetValue);
+            } else {
+                perror("");
+                printf("%s: Can't open file \"%s\"\n", getAppName(), filename);
+                exit(1);
+            }
+            get_file_name(&s, filename);
+        }
+        break;
+    }
+    case ACTION_DELETE:
+    {
+        CHAR reg_key_name[KEY_MAX_LEN];
+
+        get_file_name(&s, reg_key_name);
+        if (!reg_key_name[0])
+        {
+            printf("%s: No registry key is specified for removal\n",
+                   getAppName());
+            printf(usage);
+            exit(1);
+        }
+        delete_registry_key(reg_key_name);
+        break;
+    }
+    case ACTION_EXPORT:
+    {
+        CHAR filename[MAX_PATH];
+
+        filename[0] = '\0';
+        get_file_name(&s, filename);
+        if (!filename[0])
+        {
+            printf("%s: No file name is specified\n", getAppName());
+            printf(usage);
+            exit(1);
+        }
+
+        if (s[0])
+        {
+            CHAR reg_key_name[KEY_MAX_LEN];
+
+            get_file_name(&s, reg_key_name);
+            export_registry_key(filename, reg_key_name);
+        } else {
+            export_registry_key(filename, NULL);
+        }
+        break;
+    }
+    default:
+        printf("%s: Unhandled action!\n", getAppName());
+        exit(1);
+        break;
+    }
+    return TRUE;
+}