ReactOS  0.4.12-dev-36-g472787f
regedit.c
Go to the documentation of this file.
1 /*
2  * Windows regedit.exe registry editor implementation.
3  *
4  * Copyright (C) 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 static const LPCWSTR usage =
24  L"Usage:\n"
25  L" regedit filenames\n"
26  L" regedit /E filename [regpath]\n"
27  L" regedit /D regpath\n"
28  L"\n"
29  L"filenames - List of registry files names\n"
30  L"filename - Registry file name\n"
31  L"regpath - Name of the registry key\n"
32  L"\n"
33  L"When is called without any switches adds contents of the specified\n"
34  L"registry files to the registry.\n"
35  L"\n"
36  L"Switches:\n"
37  L" /E - Exports contents of the specified registry key to the specified\n"
38  L" file. Exports the whole registry if no key is specified.\n"
39  L" /D - Deletes specified registry key\n"
40  L" /S - Silent execution, can be used with any other switch.\n"
41  L" The only existing mode, exists for compatibility with Windows regedit.\n"
42  L" /V - Advanced mode, can be used with any other switch.\n"
43  L" Ignored, exists for compatibility with Windows regedit.\n"
44  L" /L - Location of system.dat file. Can be used with any other switch.\n"
45  L" Ignored. Exists for compatibility with Windows regedit.\n"
46  L" /R - Location of user.dat file. Can be used with any other switch.\n"
47  L" Ignored. Exists for compatibility with Windows regedit.\n"
48  L" /? - Print this help. Any other switches are ignored.\n"
49  L" /C - Create registry from. Not implemented.\n"
50  L"\n"
51  L"The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
52  L"This program is command-line compatible with Microsoft Windows\n"
53  L"regedit.\n";
54 
55 typedef enum
56 {
59 
60 
62 {
63  return L"regedit";
64 }
65 
66 /******************************************************************************
67  * Copies file name from command line string to the buffer.
68  * Rewinds the command line string pointer to the next non-space character
69  * after the file name.
70  * Buffer contains an empty string if no filename was found;
71  *
72  * params:
73  * command_line - command line current position pointer
74  * where *s[0] is the first symbol of the file name.
75  * file_name - buffer to write the file name to.
76  */
77 void get_file_name(LPWSTR *command_line, LPWSTR file_name)
78 {
79  WCHAR *s = *command_line;
80  size_t pos = 0; /* position of pointer "s" in *command_line */
81  file_name[0] = 0;
82 
83  if (!s[0])
84  {
85  return;
86  }
87 
88  if (s[0] == L'"')
89  {
90  s++;
91  (*command_line)++;
92  while(s[0] != L'"')
93  {
94  if (!s[0])
95  {
96  fwprintf(stderr, L"%s: Unexpected end of file name!\n", getAppName());
97  exit(1);
98  }
99  s++;
100  pos++;
101  }
102  }
103  else
104  {
105  while(s[0] && !iswspace(s[0]))
106  {
107  s++;
108  pos++;
109  }
110  }
111  memcpy(file_name, *command_line, pos * sizeof(WCHAR));
112  /* remove the last backslash */
113  if (file_name[pos - 1] == L'\\')
114  {
115  file_name[pos - 1] = L'\0';
116  }
117  else
118  {
119  file_name[pos] = L'\0';
120  }
121 
122  if (s[0])
123  {
124  s++;
125  pos++;
126  }
127  while(s[0] && iswspace(s[0]))
128  {
129  s++;
130  pos++;
131  }
132  (*command_line) += pos;
133 }
134 
136 {
137  switch (action)
138  {
139  case ACTION_ADD:
140  {
141  WCHAR szText[512];
143  FILE *fp;
144 
145  get_file_name(&s, filename);
146  if (!filename[0])
147  {
148  InfoMessageBox(NULL, MB_OK | MB_ICONINFORMATION, NULL, L"No file name is specified.");
150  exit(4);
151  }
152 
153  while (filename[0])
154  {
155  /* Request import confirmation */
156  if (!silent)
157  {
158  int choice;
159 
160  LoadStringW(hInst, IDS_IMPORT_PROMPT, szText, COUNT_OF(szText));
161 
162  choice = InfoMessageBox(NULL, MB_YESNOCANCEL | MB_ICONWARNING, szTitle, szText, filename);
163 
164  switch (choice)
165  {
166  case IDNO:
167  goto cont;
168  case IDCANCEL:
169  /* The cancel case is useful if the user is importing more than one registry file
170  at a time, and wants to back out anytime during the import process. This way, the
171  user doesn't have to resort to ending the regedit process abruptly just to cancel
172  the operation. */
173  return TRUE;
174  default:
175  break;
176  }
177  }
178 
179  /* Open the file */
180  fp = _wfopen(filename, L"r");
181 
182  /* Import it */
183  if (fp == NULL || !import_registry_file(fp))
184  {
185  /* Error opening the file */
186  if (!silent)
187  {
188  LoadStringW(hInst, IDS_IMPORT_ERROR, szText, COUNT_OF(szText));
189  InfoMessageBox(NULL, MB_OK | MB_ICONERROR, szTitle, szText, filename);
190  }
191  }
192  else
193  {
194  /* Show successful import */
195  if (!silent)
196  {
197  LoadStringW(hInst, IDS_IMPORT_OK, szText, COUNT_OF(szText));
198  InfoMessageBox(NULL, MB_OK | MB_ICONINFORMATION, szTitle, szText, filename);
199  }
200  }
201 
202  /* Close the file */
203  if (fp) fclose(fp);
204 
205 cont:
206  get_file_name(&s, filename);
207  }
208  break;
209  }
210 
211  case ACTION_DELETE:
212  {
213  WCHAR reg_key_name[KEY_MAX_LEN];
214  get_file_name(&s, reg_key_name);
215  if (!reg_key_name[0])
216  {
217  InfoMessageBox(NULL, MB_OK | MB_ICONINFORMATION, NULL, L"No registry key is specified for removal.");
219  exit(6);
220  }
221  delete_registry_key(reg_key_name);
222  break;
223  }
224 
225  case ACTION_EXPORT:
226  {
228 
229  filename[0] = L'\0';
230  get_file_name(&s, filename);
231  if (!filename[0])
232  {
233  InfoMessageBox(NULL, MB_OK | MB_ICONINFORMATION, NULL, L"No file name is specified.");
235  exit(7);
236  }
237 
238  if (s[0])
239  {
240  WCHAR reg_key_name[KEY_MAX_LEN];
241  get_file_name(&s, reg_key_name);
242  export_registry_key(filename, reg_key_name, REG_FORMAT_4);
243  }
244  else
245  {
247  }
248  break;
249  }
250 
251  default:
252  fwprintf(stderr, L"%s: Unhandled action!\n", getAppName());
253  exit(8);
254  break;
255  }
256 
257  return TRUE;
258 }
259 
268 {
269  if (iswalpha(chu))
270  {
271  fwprintf(stderr, L"%s: Undefined switch /%c!\n", getAppName(), chu);
272  }
273  else
274  {
275  fwprintf(stderr, L"%s: Alphabetic character is expected after '%c' "
276  L"in switch specification\n", getAppName(), *(s - 1));
277  }
278  exit(1);
279 }
280 
282 {
283  BOOL silent = FALSE;
285  LPWSTR s = lpCmdLine; /* command line pointer */
286  WCHAR ch = *s; /* current character */
287 
288  while (ch && ((ch == L'-') || (ch == L'/')))
289  {
290  WCHAR chu;
291  WCHAR ch2;
292 
293  s++;
294  ch = *s;
295  ch2 = *(s + 1);
296  chu = towupper(ch);
297  if (!ch2 || iswspace(ch2))
298  {
299  if (chu == L'S')
300  {
301  /* Silence dialogs */
302  silent = TRUE;
303  }
304  else if (chu == L'V')
305  {
306  /* Ignore this switch */
307  }
308  else
309  {
310  switch (chu)
311  {
312  case L'D':
313  action = ACTION_DELETE;
314  break;
315  case L'E':
316  action = ACTION_EXPORT;
317  break;
318  case L'?':
320  exit(3);
321  break;
322  default:
323  error_unknown_switch(chu, s);
324  break;
325  }
326  }
327  s++;
328  }
329  else
330  {
331  if (ch2 == L':')
332  {
333  switch (chu)
334  {
335  case L'L':
336  /* fall through */
337  case L'R':
338  s += 2;
339  while (*s && !iswspace(*s))
340  {
341  s++;
342  }
343  break;
344  default:
345  error_unknown_switch(chu, s);
346  break;
347  }
348  }
349  else
350  {
351  /* this is a file name, starting from '/' */
352  s--;
353  break;
354  }
355  }
356  /* skip spaces to the next parameter */
357  ch = *s;
358  while (ch && iswspace(ch))
359  {
360  s++;
361  ch = *s;
362  }
363  }
364 
365  if (*s && action == ACTION_UNDEF)
366  action = ACTION_ADD;
367 
368  if (action != ACTION_UNDEF)
369  return PerformRegAction(action, s, silent);
370  else
371  return FALSE;
372 }
#define TRUE
Definition: types.h:120
_Check_return_ _CRTIMP FILE *__cdecl _wfopen(_In_z_ const wchar_t *_Filename, _In_z_ const wchar_t *_Mode)
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define iswalpha(_c)
Definition: ctype.h:664
int InfoMessageBox(HWND hWnd, UINT uType, LPCWSTR lpTitle, LPCWSTR lpMessage,...)
Definition: error.c:51
const char * filename
Definition: ioapi.h:135
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define MB_ICONWARNING
Definition: winuser.h:780
#define KEY_MAX_LEN
Definition: regproc.h:22
static const WCHAR szText[]
Definition: dialog.c:139
void get_file_name(LPWSTR *command_line, LPWSTR file_name)
Definition: regedit.c:77
_Check_return_opt_ _CRTIMP int __cdecl fwprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const wchar_t *_Format,...)
smooth NULL
Definition: ftsmooth.c:416
#define MB_YESNOCANCEL
Definition: winuser.h:812
#define IDS_IMPORT_PROMPT
Definition: resource.h:195
#define COUNT_OF(a)
Definition: main.h:33
unsigned int BOOL
Definition: ntddk_ex.h:94
#define MAX_PATH
Definition: compat.h:26
TCHAR szTitle[MAX_LOADSTRING]
Definition: magnifier.c:36
#define iswspace(_c)
Definition: ctype.h:669
#define MB_ICONINFORMATION
Definition: winuser.h:796
BOOL PerformRegAction(REGEDIT_ACTION action, LPWSTR s, BOOL silent)
Definition: regedit.c:135
static const WCHAR L[]
Definition: oid.c:1087
#define MB_ICONERROR
Definition: winuser.h:781
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLdouble s
Definition: gl.h:2039
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
#define IDS_IMPORT_ERROR
Definition: resource.h:197
REGEDIT_ACTION
Definition: regedit.c:55
BOOL ProcessCmdLine(LPWSTR lpCmdLine)
Definition: regedit.c:281
HINSTANCE hInst
Definition: dxdiag.c:13
const WCHAR * action
Definition: action.c:7779
#define REG_FORMAT_4
Definition: regproc.h:25
#define IDS_IMPORT_OK
Definition: resource.h:196
LPCWSTR getAppName(void)
Definition: regedit.c:61
#define MB_OK
Definition: winuser.h:784
BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format)
Definition: regproc.c:1310
static LPCWSTR file_name
Definition: protocol.c:146
static void error_unknown_switch(WCHAR chu, LPWSTR s)
Definition: regedit.c:267
FILE * stderr
BOOL import_registry_file(FILE *reg_file)
Definition: regproc.c:1405
#define towupper(c)
Definition: wctype.h:99
#define IDNO
Definition: winuser.h:830
void exit(int exitcode)
Definition: _exit.c:33
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define IDCANCEL
Definition: winuser.h:825
void delete_registry_key(WCHAR *reg_key_name)
Definition: regproc.c:1432