ReactOS  0.4.13-dev-79-gcd489d8
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);
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 
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:
204  break;
205  case REG_DWORD:
206  if (size)
207  {
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 
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 
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 
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 
322 }
323 
325 {
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 
334  {
336 
337  if (error == ERROR_FILE_EXISTS)
338  {
340  {
342  exit(0);
343  }
344 
346  }
347  else
348  {
349  WCHAR *str;
350 
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);
398  ret = export_registry_data(hFile, hkey, long_key);
401 
402  RegCloseKey(hkey);
403 
404  return ret;
405 
406 error:
409  return 1;
410 }
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
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
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
#define argv
Definition: mplay32.c:18
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
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
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
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
unsigned int BOOL
Definition: ntddk_ex.h:94
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
WCHAR * build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
Definition: reg.c:632
GLsizeiptr size
Definition: glext.h:5919
static HANDLE get_file_handle(WCHAR *filename, BOOL overwrite_file)
Definition: export.c:329
__wchar_t WCHAR
Definition: xmlstorage.h:180
#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
unsigned char BYTE
Definition: mem.h:68
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
#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:7783
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:596
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