secur32: Check for actual return value on invalid QuerySecurityPackageInfo call.
[wine] / programs / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <windows.h>
24 #include "regproc.h"
25
26 static const 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.\n";
56
57 typedef enum {
58     ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
59 } REGEDIT_ACTION;
60
61 BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s);
62
63 /**
64  * Process unknown switch.
65  *
66  * Params:
67  *   chu - the switch character in upper-case.
68  *   s - the command line string where s points to the switch character.
69  */
70 static void error_unknown_switch(char chu, char *s)
71 {
72     if (isalpha(chu)) {
73         fprintf(stderr,"%s: Undefined switch /%c!\n", getAppName(), chu);
74     } else {
75         fprintf(stderr,"%s: Alphabetic character is expected after '%c' "
76                 "in swit ch specification\n", getAppName(), *(s - 1));
77     }
78     exit(1);
79 }
80
81 BOOL ProcessCmdLine(LPSTR lpCmdLine)
82 {
83     REGEDIT_ACTION action = ACTION_UNDEF;
84     LPSTR s = lpCmdLine;        /* command line pointer */
85     CHAR ch = *s;               /* current character */
86
87     setAppName("regedit");
88     while (ch && ((ch == '-') || (ch == '/'))) {
89         char chu;
90         char ch2;
91
92         s++;
93         ch = *s;
94         ch2 = *(s+1);
95         chu = toupper(ch);
96         if (!ch2 || isspace(ch2)) {
97             if (chu == 'S' || chu == 'V') {
98                 /* ignore these switches */
99             } else {
100                 switch (chu) {
101                 case 'D':
102                     action = ACTION_DELETE;
103                     break;
104                 case 'E':
105                     action = ACTION_EXPORT;
106                     break;
107                 case '?':
108                     fprintf(stderr,usage);
109                     exit(0);
110                     break;
111                 default:
112                     error_unknown_switch(chu, s);
113                     break;
114                 }
115             }
116             s++;
117         } else {
118             if (ch2 == ':') {
119                 switch (chu) {
120                 case 'L':
121                     /* fall through */
122                 case 'R':
123                     s += 2;
124                     while (*s && !isspace(*s)) {
125                         s++;
126                     }
127                     break;
128                 default:
129                     error_unknown_switch(chu, s);
130                     break;
131                 }
132             } else {
133                 /* this is a file name, starting from '/' */
134                 s--;
135                 break;
136             }
137         }
138         /* skip spaces to the next parameter */
139         ch = *s;
140         while (ch && isspace(ch)) {
141             s++;
142             ch = *s;
143         }
144     }
145
146     if (*s && action == ACTION_UNDEF)
147         action = ACTION_ADD;
148
149     if (action == ACTION_UNDEF)
150         return FALSE;
151
152     return PerformRegAction(action, s);
153 }
154
155 BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
156 {
157     switch (action) {
158     case ACTION_ADD: {
159             CHAR filename[MAX_PATH];
160             FILE *reg_file;
161
162             get_file_name(&s, filename);
163             if (!filename[0]) {
164                 fprintf(stderr,"%s: No file name is specified\n", getAppName());
165                 fprintf(stderr,usage);
166                 exit(1);
167             }
168
169             while(filename[0]) {
170                 char* realname = NULL;
171                 int size;
172                 size=SearchPath(NULL,filename,NULL,0,NULL,NULL);
173                 if (size>0)
174                 {
175                     realname=HeapAlloc(GetProcessHeap(),0,size);
176                     size=SearchPath(NULL,filename,NULL,size,realname,NULL);
177                 }
178                 if (size==0)
179                 {
180                     fprintf(stderr,"%s: File not found \"%s\" (%d)\n",
181                             getAppName(),filename,GetLastError());
182                     exit(1);
183                 }
184                 reg_file = fopen(realname, "r");
185                 if (reg_file==NULL)
186                 {
187                     perror("");
188                     fprintf(stderr,"%s: Can't open file \"%s\"\n", getAppName(), filename);
189                     exit(1);
190                 }
191                 processRegLines(reg_file, doSetValue);
192                 if (realname)
193                 {
194                     HeapFree(GetProcessHeap(),0,realname);
195                     fclose(reg_file);
196                 }
197                 get_file_name(&s, filename);
198             }
199             break;
200         }
201     case ACTION_DELETE: {
202             CHAR reg_key_name[KEY_MAX_LEN];
203
204             get_file_name(&s, reg_key_name);
205             if (!reg_key_name[0]) {
206                 fprintf(stderr,"%s: No registry key is specified for removal\n",
207                         getAppName());
208                 fprintf(stderr,usage);
209                 exit(1);
210             }
211             delete_registry_key(reg_key_name);
212             break;
213         }
214     case ACTION_EXPORT: {
215             CHAR filename[MAX_PATH];
216
217             filename[0] = '\0';
218             get_file_name(&s, filename);
219             if (!filename[0]) {
220                 fprintf(stderr,"%s: No file name is specified\n", getAppName());
221                 fprintf(stderr,usage);
222                 exit(1);
223             }
224
225             if (s[0]) {
226                 CHAR reg_key_name[KEY_MAX_LEN];
227
228                 get_file_name(&s, reg_key_name);
229                 export_registry_key(filename, reg_key_name);
230             } else {
231                 export_registry_key(filename, NULL);
232             }
233             break;
234         }
235     default:
236         fprintf(stderr,"%s: Unhandled action!\n", getAppName());
237         exit(1);
238         break;
239     }
240     return TRUE;
241 }