xref: /reactos/base/applications/regedit/regedit.c (revision 29fa274d)
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include <regedit.h>
22 
23 
24 static const char *usage =
25     "Usage:\n"
26     "    regedit filename\n"
27     "    regedit /E filename [regpath]\n"
28     "    regedit /D regpath\n"
29     "\n"
30     "filename - registry file name\n"
31     "regpath - name of the registry key\n"
32     "\n"
33     "When is called without any switches adds contents of the specified\n"
34     "registry file to the registry\n"
35     "\n"
36     "Switches:\n"
37     "    /E - exports contents of the specified registry key to the specified\n"
38     "	file. Exports the whole registry if no key is specified.\n"
39     "    /D - deletes specified registry key\n"
40     "    /S - silent execution, can be used with any other switch.\n"
41     "	The only existing mode, exists for compatibility with Windows regedit.\n"
42     "    /V - advanced mode, can be used with any other switch.\n"
43     "	Ignored, exists for compatibility with Windows regedit.\n"
44     "    /L - location of system.dat file. Can be used with any other switch.\n"
45     "	Ignored. Exists for compatibility with Windows regedit.\n"
46     "    /R - location of user.dat file. Can be used with any other switch.\n"
47     "	Ignored. Exists for compatibility with Windows regedit.\n"
48     "    /? - print this help. Any other switches are ignored.\n"
49     "    /C - create registry from. Not implemented.\n"
50     "\n"
51     "The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
52     "This program is command-line compatible with Microsoft Windows\n"
53     "regedit.\n";
54 
55 typedef enum {
56     ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
57 } REGEDIT_ACTION;
58 
59 BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s);
60 
61 /**
62  * Process unknown switch.
63  *
64  * Params:
65  *   chu - the switch character in upper-case.
66  *   s - the command line string where s points to the switch character.
67  */
68 static void error_unknown_switch(char chu, char *s)
69 {
70     if (isalpha(chu)) {
71         fprintf(stderr,"%s: Undefined switch /%c!\n", getAppName(), chu);
72     } else {
73         fprintf(stderr,"%s: Alphabetic character is expected after '%c' "
74                 "in swit ch specification\n", getAppName(), *(s - 1));
75     }
76     exit(1);
77 }
78 
79 BOOL ProcessCmdLine(LPSTR lpCmdLine)
80 {
81     REGEDIT_ACTION action = ACTION_UNDEF;
82     LPSTR s = lpCmdLine;        /* command line pointer */
83     CHAR ch = *s;               /* current character */
84 
85     setAppName("regedit");
86     while (ch && ((ch == '-') || (ch == '/'))) {
87         char chu;
88         char ch2;
89 
90         s++;
91         ch = *s;
92         ch2 = *(s+1);
93         chu = (CHAR) toupper(ch);
94         if (!ch2 || isspace(ch2)) {
95             if (chu == 'S' || chu == 'V') {
96                 /* ignore these switches */
97             } else {
98                 switch (chu) {
99                 case 'D':
100                     action = ACTION_DELETE;
101                     break;
102                 case 'E':
103                     action = ACTION_EXPORT;
104                     break;
105                 case '?':
106                     fprintf(stderr,usage);
107                     exit(0);
108                     break;
109                 default:
110                     error_unknown_switch(chu, s);
111                     break;
112                 }
113             }
114             s++;
115         } else {
116             if (ch2 == ':') {
117                 switch (chu) {
118                 case 'L':
119                     /* fall through */
120                 case 'R':
121                     s += 2;
122                     while (*s && !isspace(*s)) {
123                         s++;
124                     }
125                     break;
126                 default:
127                     error_unknown_switch(chu, s);
128                     break;
129                 }
130             } else {
131                 /* this is a file name, starting from '/' */
132                 s--;
133                 break;
134             }
135         }
136         /* skip spaces to the next parameter */
137         ch = *s;
138         while (ch && isspace(ch)) {
139             s++;
140             ch = *s;
141         }
142     }
143 
144     if (*s && action == ACTION_UNDEF)
145         action = ACTION_ADD;
146 
147     if (action == ACTION_UNDEF)
148         return FALSE;
149 
150     return PerformRegAction(action, s);
151 }
152 
153 BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
154 {
155     switch (action) {
156     case ACTION_ADD: {
157             CHAR filename[MAX_PATH];
158             FILE *reg_file;
159 
160             get_file_name(&s, filename);
161             if (!filename[0]) {
162                 fprintf(stderr,"%s: No file name is specified\n", getAppName());
163                 fprintf(stderr,usage);
164                 exit(1);
165             }
166 
167             while(filename[0]) {
168                 reg_file = fopen(filename, "r");
169                 if (reg_file) {
170                     processRegLines(reg_file, doSetValue);
171                     fclose(reg_file);
172                 } else {
173                     perror("");
174                     fprintf(stderr,"%s: Can't open file \"%s\"\n", getAppName(), filename);
175                     exit(1);
176                 }
177                 get_file_name(&s, filename);
178             }
179             break;
180         }
181     case ACTION_DELETE: {
182             CHAR reg_key_name[KEY_MAX_LEN];
183 
184             get_file_name(&s, reg_key_name);
185             if (!reg_key_name[0]) {
186                 fprintf(stderr,"%s: No registry key is specified for removal\n",
187                         getAppName());
188                 fprintf(stderr,usage);
189                 exit(1);
190             }
191             delete_registry_key(reg_key_name);
192             break;
193         }
194     case ACTION_EXPORT: {
195             CHAR filename[MAX_PATH];
196             LPCTSTR pszFilename;
197 #ifdef UNICODE
198             WCHAR filename_wide[MAX_PATH];
199 #endif
200 
201             filename[0] = '\0';
202             get_file_name(&s, filename);
203             if (!filename[0]) {
204                 fprintf(stderr,"%s: No file name is specified\n", getAppName());
205                 fprintf(stderr,usage);
206                 exit(1);
207             }
208 
209 #ifdef UNICODE
210             MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_wide,
211                 sizeof(filename_wide) / sizeof(filename_wide[0]));
212             pszFilename = filename_wide;
213 #else
214             pszFilename = filename;
215 #endif
216 
217             if (s[0]) {
218                 CHAR reg_key_name[KEY_MAX_LEN];
219 
220                 get_file_name(&s, reg_key_name);
221                 export_registry_key(pszFilename, reg_key_name);
222             } else {
223                 export_registry_key(pszFilename, NULL);
224             }
225             break;
226         }
227     default:
228         fprintf(stderr,"%s: Unhandled action!\n", getAppName());
229         exit(1);
230         break;
231     }
232     return TRUE;
233 }
234