update for HEAD-2003091401
[reactos.git] / subsys / system / regedit / regedit.c
1 /*
2  * Windows regedit.exe registry editor implementation.
3  *
4  * Copyright 2002 Andriy Palamarchuk
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <windows.h>
24 #include "regproc.h"
25
26 static char *usage =
27 "Usage:\n"
28 "    regedit filename\n"
29 "    regedit /E filename [regpath]\n"
30 "    regedit /D regpath\n"
31 "\n"
32 "filename - registry file name\n"
33 "regpath - name of the registry key\n"
34 "\n"
35 "When is called without any switches adds contents of the specified\n"
36 "registry file to the registry\n"
37 "\n"
38 "Switches:\n"
39 "    /E - exports contents of the specified registry key to the specified\n"
40 "       file. Exports the whole registry if no key is specified.\n"
41 "    /D - deletes specified registry key\n"
42 "    /S - silent execution, can be used with any other switch.\n"
43 "       The only existing mode, exists for compatibility with Windows regedit.\n"
44 "    /V - advanced mode, can be used with any other switch.\n"
45 "       Ignored, exists for compatibility with Windows regedit.\n"
46 "    /L - location of system.dat file. Can be used with any other switch.\n"
47 "       Ignored. Exists for compatibility with Windows regedit.\n"
48 "    /R - location of user.dat file. Can be used with any other switch.\n"
49 "       Ignored. Exists for compatibility with Windows regedit.\n"
50 "    /? - print this help. Any other switches are ignored.\n"
51 "    /C - create registry from. Not implemented.\n"
52 "\n"
53 "The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
54 "This program is command-line compatible with Microsoft Windows\n"
55 "regedit. The difference with Windows regedit - this application has\n"
56 "command-line interface only.\n";
57
58 typedef enum {
59     ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
60 } REGEDIT_ACTION;
61
62 BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s);
63
64 /**
65  * Process unknown switch.
66  *
67  * Params:
68  *   chu - the switch character in upper-case.
69  *   s - the command line string where s points to the switch character.
70  */
71 void error_unknown_switch(char chu, char *s)
72 {
73     if (isalpha(chu))
74     {
75         printf("%s: Undefined switch /%c!\n", getAppName(), chu);
76     } else {
77         printf("%s: Alphabetic character is expected after '%c' "
78                "in switch specification\n", getAppName(), *(s - 1));
79     }
80     exit(1);
81 }
82
83 BOOL ProcessCmdLine(LPSTR lpCmdLine)
84 {
85     REGEDIT_ACTION action = ACTION_UNDEF;
86     LPSTR s = lpCmdLine;        /* command line pointer */
87     CHAR ch = *s;               /* current character */
88
89     setAppName("regedit");
90     while (ch && ((ch == '-') || (ch == '/')))
91     {
92         char chu;
93         char ch2;
94
95         s++;
96         ch = *s;
97         ch2 = *(s+1);
98         chu = toupper(ch);
99         if (!ch2 || isspace(ch2))
100         {
101             if (chu == 'S' || chu == 'V')
102             {
103                 /* ignore these switches */
104             } else {
105                 switch (chu)
106                 {
107                 case 'D':
108                     action = ACTION_DELETE;
109                     break;
110                 case 'E':
111                     action = ACTION_EXPORT;
112                     break;
113                 case '?':
114                     printf(usage);
115                     exit(0);
116                     break;
117                 default:
118                     error_unknown_switch(chu, s);
119                     break;
120                 }
121             }
122             s++;
123         } else {
124             if (ch2 == ':')
125             {
126                 switch (chu)
127                 {
128                 case 'L':
129                     /* fall through */
130                 case 'R':
131                     s += 2;
132                     while (*s && !isspace(*s))
133                     {
134                         s++;
135                     }
136                     break;
137                 default:
138                     error_unknown_switch(chu, s);
139                     break;
140                 }
141             } else {
142                 /* this is a file name, starting from '/' */
143                 s--;
144                 break;
145             }
146         }
147         /* skip spaces to the next parameter */
148         ch = *s;
149         while (ch && isspace(ch))
150         {
151             s++;
152             ch = *s;
153         }
154     }
155
156     if (*s && action == ACTION_UNDEF)
157         action = ACTION_ADD;
158
159     if (action == ACTION_UNDEF)
160         return FALSE;
161
162     return PerformRegAction(action, s);
163 }
164
165 BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
166 {
167     switch (action)
168     {
169     case ACTION_ADD:
170     {
171         CHAR filename[MAX_PATH];
172         FILE *reg_file;
173
174         get_file_name(&s, filename);
175         if (!filename[0])
176         {
177             printf("%s: No file name is specified\n", getAppName());
178             printf(usage);
179             exit(1);
180         }
181
182         while(filename[0])
183         {
184             reg_file = fopen(filename, "r");
185             if (reg_file)
186             {
187                 processRegLines(reg_file, doSetValue);
188             } else {
189                 perror("");
190                 printf("%s: Can't open file \"%s\"\n", getAppName(), filename);
191                 exit(1);
192             }
193             get_file_name(&s, filename);
194         }
195         break;
196     }
197     case ACTION_DELETE:
198     {
199         CHAR reg_key_name[KEY_MAX_LEN];
200
201         get_file_name(&s, reg_key_name);
202         if (!reg_key_name[0])
203         {
204             printf("%s: No registry key is specified for removal\n",
205                    getAppName());
206             printf(usage);
207             exit(1);
208         }
209         delete_registry_key(reg_key_name);
210         break;
211     }
212     case ACTION_EXPORT:
213     {
214         CHAR filename[MAX_PATH];
215
216         filename[0] = '\0';
217         get_file_name(&s, filename);
218         if (!filename[0])
219         {
220             printf("%s: No file name is specified\n", getAppName());
221             printf(usage);
222             exit(1);
223         }
224
225         if (s[0])
226         {
227             CHAR reg_key_name[KEY_MAX_LEN];
228
229             get_file_name(&s, reg_key_name);
230             export_registry_key(filename, reg_key_name);
231         } else {
232             export_registry_key(filename, NULL);
233         }
234         break;
235     }
236     default:
237         printf("%s: Unhandled action!\n", getAppName());
238         exit(1);
239         break;
240     }
241     return TRUE;
242 }