ReactOS  0.4.12-dev-75-g00dd17e
export.c
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Hugh McMaster
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <windows.h>
20 #include <stdlib.h>
21 
22 #include <wine/unicode.h>
23 #include <wine/heap.h>
24 
25 #include "reg.h"
26 
27 static void write_file(HANDLE hFile, const WCHAR *str)
28 {
29  DWORD written;
30 
31  WriteFile(hFile, str, lstrlenW(str) * sizeof(WCHAR), &written, NULL);
32 }
33 
34 static WCHAR *escape_string(WCHAR *str, size_t str_len, size_t *line_len)
35 {
36  size_t i, escape_count, pos;
37  WCHAR *buf;
38 
39  for (i = 0, escape_count = 0; i < str_len; i++)
40  {
41  WCHAR c = str[i];
42 
43  if (!c) break;
44 
45  if (c == '\r' || c == '\n' || c == '\\' || c == '"')
46  escape_count++;
47  }
48 
49  buf = heap_xalloc((str_len + escape_count + 1) * sizeof(WCHAR));
50 
51  for (i = 0, pos = 0; i < str_len; i++, pos++)
52  {
53  WCHAR c = str[i];
54 
55  if (!c) break;
56 
57  switch (c)
58  {
59  case '\r':
60  buf[pos++] = '\\';
61  buf[pos] = 'r';
62  break;
63  case '\n':
64  buf[pos++] = '\\';
65  buf[pos] = 'n';
66  break;
67  case '\\':
68  buf[pos++] = '\\';
69  buf[pos] = '\\';
70  break;
71  case '"':
72  buf[pos++] = '\\';
73  buf[pos] = '"';
74  break;
75  default:
76  buf[pos] = c;
77  }
78  }
79 
80  buf[pos] = 0;
81  *line_len = pos;
82  return buf;
83 }
84 
85 static size_t export_value_name(HANDLE hFile, WCHAR *name, size_t len)
86 {
87  static const WCHAR quoted_fmt[] = {'"','%','s','"','=',0};
88  static const WCHAR default_name[] = {'@','=',0};
89  size_t line_len;
90 
91  if (name && *name)
92  {
93  WCHAR *str = escape_string(name, len, &line_len);
94  WCHAR *buf = heap_xalloc((line_len + 4) * sizeof(WCHAR));
95  line_len = sprintfW(buf, quoted_fmt, str);
96  write_file(hFile, buf);
97  heap_free(buf);
98  heap_free(str);
99  }
100  else
101  {
102  line_len = lstrlenW(default_name);
103  write_file(hFile, default_name);
104  }
105 
106  return line_len;
107 }
108 
109 static void export_string_data(WCHAR **buf, WCHAR *data, size_t size)
110 {
111  size_t len = 0, line_len;
112  WCHAR *str;
113  static const WCHAR fmt[] = {'"','%','s','"',0};
114 
115  if (size)
116  len = size / sizeof(WCHAR) - 1;
117  str = escape_string(data, len, &line_len);
118  *buf = heap_xalloc((line_len + 3) * sizeof(WCHAR));
119  sprintfW(*buf, fmt, str);
120  heap_free(str);
121 }
122 
124 {
125  static const WCHAR fmt[] = {'d','w','o','r','d',':','%','0','8','x',0};
126 
127  *buf = heap_xalloc(15 * sizeof(WCHAR));
128  sprintfW(*buf, fmt, *data);
129 }
130 
132 {
133  static const WCHAR hex[] = {'h','e','x',':',0};
134  static const WCHAR hexp_fmt[] = {'h','e','x','(','%','x',')',':',0};
135  size_t line_len;
136 
137  if (type == REG_BINARY)
138  {
139  line_len = lstrlenW(hex);
140  write_file(hFile, hex);
141  }
142  else
143  {
144  WCHAR *buf = heap_xalloc(15 * sizeof(WCHAR));
145  line_len = sprintfW(buf, hexp_fmt, type);
146  write_file(hFile, buf);
147  heap_free(buf);
148  }
149 
150  return line_len;
151 }
152 
153 #define MAX_HEX_CHARS 77
154 
156  DWORD line_len, void *data, DWORD size)
157 {
158  static const WCHAR fmt[] = {'%','0','2','x',0};
159  static const WCHAR hex_concat[] = {'\\','\r','\n',' ',' ',0};
160  size_t num_commas, i, pos;
161 
162  line_len += export_hex_data_type(hFile, type);
163 
164  if (!size) return;
165 
166  num_commas = size - 1;
167  *buf = heap_xalloc(size * 3 * sizeof(WCHAR));
168 
169  for (i = 0, pos = 0; i < size; i++)
170  {
171  pos += sprintfW(*buf + pos, fmt, ((BYTE *)data)[i]);
172  if (i == num_commas) break;
173  (*buf)[pos++] = ',';
174  (*buf)[pos] = 0;
175  line_len += 3;
176 
177  if (line_len >= MAX_HEX_CHARS)
178  {
179  write_file(hFile, *buf);
180  write_file(hFile, hex_concat);
181  line_len = 2;
182  pos = 0;
183  }
184  }
185 }
186 
188 {
189  static const WCHAR newline[] = {'\r','\n',0};
190 
191  write_file(hFile, newline);
192 }
193 
194 static void export_data(HANDLE hFile, WCHAR *value_name, DWORD value_len,
195  DWORD type, void *data, size_t size)
196 {
197  WCHAR *buf = NULL;
198  size_t line_len = export_value_name(hFile, value_name, value_len);
199 
200  switch (type)
201  {
202  case REG_SZ:
203  export_string_data(&buf, data, size);
204  break;
205  case REG_DWORD:
206  if (size)
207  {
208  export_dword_data(&buf, data);
209  break;
210  }
211  /* fall through */
212  case REG_NONE:
213  case REG_EXPAND_SZ:
214  case REG_BINARY:
215  case REG_MULTI_SZ:
216  default:
217  export_hex_data(hFile, &buf, type, line_len, data, size);
218  break;
219  }
220 
221  if (size || type == REG_SZ)
222  {
223  write_file(hFile, buf);
224  heap_free(buf);
225  }
226 
227  export_newline(hFile);
228 }
229 
231 {
232  static const WCHAR fmt[] = {'\r','\n','[','%','s',']','\r','\n',0};
233  WCHAR *buf;
234 
235  buf = heap_xalloc((lstrlenW(name) + 7) * sizeof(WCHAR));
236  sprintfW(buf, fmt, name);
237  write_file(hFile, buf);
238  heap_free(buf);
239 }
240 
242 {
243  LONG rc;
244  DWORD max_value_len = 256, value_len;
245  DWORD max_data_bytes = 2048, data_size;
246  DWORD subkey_len;
247  DWORD i, type, path_len;
248  WCHAR *value_name, *subkey_name, *subkey_path;
249  BYTE *data;
250  HKEY subkey;
251 
252  export_key_name(hFile, path);
253 
254  value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
255  data = heap_xalloc(max_data_bytes);
256 
257  i = 0;
258  for (;;)
259  {
260  value_len = max_value_len;
261  data_size = max_data_bytes;
262  rc = RegEnumValueW(key, i, value_name, &value_len, NULL, &type, data, &data_size);
263 
264  if (rc == ERROR_SUCCESS)
265  {
266  export_data(hFile, value_name, value_len, type, data, data_size);
267  i++;
268  }
269  else if (rc == ERROR_MORE_DATA)
270  {
271  if (data_size > max_data_bytes)
272  {
273  max_data_bytes = data_size;
274  data = heap_xrealloc(data, max_data_bytes);
275  }
276  else
277  {
278  max_value_len *= 2;
279  value_name = heap_xrealloc(value_name, max_value_len * sizeof(WCHAR));
280  }
281  }
282  else break;
283  }
284 
285  heap_free(data);
286  heap_free(value_name);
287 
288  subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
289 
290  path_len = lstrlenW(path);
291 
292  i = 0;
293  for (;;)
294  {
295  subkey_len = MAX_SUBKEY_LEN;
296  rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
297  if (rc == ERROR_SUCCESS)
298  {
299  subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
300  if (!RegOpenKeyExW(key, subkey_name, 0, KEY_READ, &subkey))
301  {
302  export_registry_data(hFile, subkey, subkey_path);
303  RegCloseKey(subkey);
304  }
305  heap_free(subkey_path);
306  i++;
307  }
308  else break;
309  }
310 
311  heap_free(subkey_name);
312  return 0;
313 }
314 
316 {
317  static const WCHAR header[] = { 0xfeff,'W','i','n','d','o','w','s',' ',
318  'R','e','g','i','s','t','r','y',' ','E','d','i','t','o','r',' ',
319  'V','e','r','s','i','o','n',' ','5','.','0','0','\r','\n'};
320 
321  write_file(hFile, header);
322 }
323 
325 {
326  return CreateFileW(filename, GENERIC_WRITE, 0, NULL, action, FILE_ATTRIBUTE_NORMAL, NULL);
327 }
328 
329 static HANDLE get_file_handle(WCHAR *filename, BOOL overwrite_file)
330 {
331  HANDLE hFile = create_file(filename, overwrite_file ? CREATE_ALWAYS : CREATE_NEW);
332 
333  if (hFile == INVALID_HANDLE_VALUE)
334  {
336 
337  if (error == ERROR_FILE_EXISTS)
338  {
339  if (!ask_confirm(STRING_OVERWRITE_FILE, filename))
340  {
342  exit(0);
343  }
344 
345  hFile = create_file(filename, CREATE_ALWAYS);
346  }
347  else
348  {
349  WCHAR *str;
350 
352  FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (WCHAR *)&str, 0, NULL);
353  output_writeconsole(str, lstrlenW(str));
354  LocalFree(str);
355  exit(1);
356  }
357  }
358 
359  return hFile;
360 }
361 
363 {
364  if (strlenW(s) > 2)
365  return FALSE;
366 
367  if ((s[0] == '/' || s[0] == '-') && (s[1] == 'y' || s[1] == 'Y'))
368  return TRUE;
369 
370  return FALSE;
371 }
372 
373 int reg_export(int argc, WCHAR *argv[])
374 {
375  HKEY root, hkey;
376  WCHAR *path, *long_key;
377  BOOL overwrite_file = FALSE;
378  HANDLE hFile;
379  int ret;
380 
381  if (argc == 3 || argc > 5)
382  goto error;
383 
384  if (!parse_registry_key(argv[2], &root, &path, &long_key))
385  return 1;
386 
387  if (argc == 5 && !(overwrite_file = is_overwrite_switch(argv[4])))
388  goto error;
389 
390  if (RegOpenKeyExW(root, path, 0, KEY_READ, &hkey))
391  {
393  return 1;
394  }
395 
396  hFile = get_file_handle(argv[3], overwrite_file);
397  export_file_header(hFile);
398  ret = export_registry_data(hFile, hkey, long_key);
399  export_newline(hFile);
400  CloseHandle(hFile);
401 
402  RegCloseKey(hkey);
403 
404  return ret;
405 
406 error:
409  return 1;
410 }
static int argc
Definition: ServiceArgs.c:12
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define MAX_SUBKEY_LEN
Definition: reg.h:24
static size_t export_value_name(HANDLE hFile, WCHAR *name, size_t len)
Definition: export.c:85
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
#define error(str)
Definition: mkdosfs.c:1605
static BOOL is_overwrite_switch(const WCHAR *s)
Definition: export.c:362
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define REG_BINARY
Definition: nt_native.h:1496
static WCHAR * escape_string(WCHAR *str, size_t str_len, size_t *line_len)
Definition: export.c:34
#define KEY_READ
Definition: nt_native.h:1023
__wchar_t WCHAR
Definition: xmlstorage.h:180
GLsizei const GLchar ** path
Definition: glext.h:7234
static void write_file(HANDLE hFile, const WCHAR *str)
Definition: export.c:27
struct _root root
#define str_len
Definition: treelist.c:89
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:147
BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key)
Definition: reg.c:863
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
#define WCHAR
Definition: msvc.h:43
const char * filename
Definition: ioapi.h:135
static const char hex[16]
Definition: profile.c:123
#define lstrlenW
Definition: compat.h:407
static HANDLE create_file(const WCHAR *filename, DWORD action)
Definition: export.c:324
static char ** argv
Definition: ServiceArgs.c:11
GLenum GLclampf GLint i
Definition: glfuncs.h:14
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
static void export_data(HANDLE hFile, WCHAR *value_name, DWORD value_len, DWORD type, void *data, size_t size)
Definition: export.c:194
long LONG
Definition: pedump.c:60
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
#define STRING_INVALID_KEY
Definition: resource.h:31
const WCHAR * str
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2867
#define STRING_FUNC_HELP
Definition: resource.h:55
smooth NULL
Definition: ftsmooth.c:416
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
WCHAR * build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
Definition: reg.c:632
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizeiptr size
Definition: glext.h:5919
static HANDLE get_file_handle(WCHAR *filename, BOOL overwrite_file)
Definition: export.c:329
#define STRING_INVALID_SYNTAX
Definition: resource.h:52
static int export_registry_data(HANDLE hFile, HKEY key, WCHAR *path)
Definition: export.c:241
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
static void export_key_name(HANDLE hFile, WCHAR *name)
Definition: export.c:230
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define MAX_HEX_CHARS
Definition: export.c:153
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
static size_t export_hex_data_type(HANDLE hFile, DWORD type)
Definition: export.c:131
void * heap_xrealloc(void *buf, size_t size)
Definition: reg.c:94
_In_ HANDLE hFile
Definition: mswsock.h:90
static void export_newline(HANDLE hFile)
Definition: export.c:187
#define ERROR_MORE_DATA
Definition: dderror.h:13
static void export_dword_data(WCHAR **buf, DWORD *data)
Definition: export.c:123
unsigned char BYTE
Definition: ntddk_ex.h:96
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:401
BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info)
Definition: reg.c:172
#define CREATE_ALWAYS
Definition: disk.h:72
static DWORD path_len
Definition: batch.c:31
const WCHAR * action
Definition: action.c:7779
static void export_file_header(HANDLE hFile)
Definition: export.c:315
#define STRING_OVERWRITE_FILE
Definition: resource.h:63
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
static void export_hex_data(HANDLE hFile, WCHAR **buf, DWORD type, DWORD line_len, void *data, DWORD size)
Definition: export.c:155
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
Definition: services.c:325
#define sprintfW
Definition: unicode.h:58
static void newline(int)
Definition: ppl.yy.c:3768
#define CreateFileW
Definition: compat.h:400
Definition: name.c:36
static void export_string_data(WCHAR **buf, WCHAR *data, size_t size)
Definition: export.c:109
#define c
Definition: ke_i.h:80
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
#define CREATE_NEW
Definition: disk.h:69
int reg_export(int argc, WCHAR *argv[])
Definition: export.c:373
void * heap_xalloc(size_t size)
Definition: reg.c:83
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2541
#define REG_NONE
Definition: nt_native.h:1492
void exit(int exitcode)
Definition: _exit.c:33
void output_writeconsole(const WCHAR *str, DWORD wlen)
Definition: reg.c:107
#define REG_DWORD
Definition: sdbapi.c:539
Definition: dsound.c:943
struct CFHEADER header
Definition: fdi.c:109
#define STRING_CANCELLED
Definition: resource.h:43
Definition: path.c:42
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define REG_SZ
Definition: layer.c:22
WINE_UNICODE_INLINE WCHAR * struprW(WCHAR *str)
Definition: unicode.h:288