ReactOS  0.4.12-dev-57-g7050ac4
import.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 <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include <wine/unicode.h>
25 #include <wine/debug.h>
26 #include <wine/heap.h>
27 
28 #include "reg.h"
29 
31 
32 static WCHAR *GetWideString(const char *strA)
33 {
34  if (strA)
35  {
36  WCHAR *strW;
37  int len = MultiByteToWideChar(CP_ACP, 0, strA, -1, NULL, 0);
38 
39  strW = heap_xalloc(len * sizeof(WCHAR));
40  MultiByteToWideChar(CP_ACP, 0, strA, -1, strW, len);
41  return strW;
42  }
43  return NULL;
44 }
45 
46 static WCHAR *GetWideStringN(const char *strA, int size, DWORD *len)
47 {
48  if (strA)
49  {
50  WCHAR *strW;
51  *len = MultiByteToWideChar(CP_ACP, 0, strA, size, NULL, 0);
52 
53  strW = heap_xalloc(*len * sizeof(WCHAR));
54  MultiByteToWideChar(CP_ACP, 0, strA, size, strW, *len);
55  return strW;
56  }
57  *len = 0;
58  return NULL;
59 }
60 
61 static WCHAR *(*get_line)(FILE *);
62 
63 /* parser definitions */
65 {
66  HEADER, /* parsing the registry file version header */
67  PARSE_WIN31_LINE, /* parsing a Windows 3.1 registry line */
68  LINE_START, /* at the beginning of a registry line */
69  KEY_NAME, /* parsing a key name */
70  DELETE_KEY, /* deleting a registry key */
71  DEFAULT_VALUE_NAME, /* parsing a default value name */
72  QUOTED_VALUE_NAME, /* parsing a double-quoted value name */
73  DATA_START, /* preparing for data parsing operations */
74  DELETE_VALUE, /* deleting a registry value */
75  DATA_TYPE, /* parsing the registry data type */
76  STRING_DATA, /* parsing REG_SZ data */
77  DWORD_DATA, /* parsing DWORD data */
78  HEX_DATA, /* parsing REG_BINARY, REG_NONE, REG_EXPAND_SZ or REG_MULTI_SZ data */
79  EOL_BACKSLASH, /* preparing to parse multiple lines of hex data */
80  HEX_MULTILINE, /* parsing multiple lines of hex data */
81  UNKNOWN_DATA, /* parsing an unhandled or invalid data type */
82  SET_VALUE, /* adding a value to the registry */
84 };
85 
86 struct parser
87 {
88  FILE *file; /* pointer to a registry file */
89  WCHAR two_wchars[2]; /* first two characters from the encoding check */
90  BOOL is_unicode; /* parsing Unicode or ASCII data */
91  short int reg_version; /* registry file version */
92  HKEY hkey; /* current registry key */
93  WCHAR *key_name; /* current key name */
94  WCHAR *value_name; /* value name */
95  DWORD parse_type; /* generic data type for parsing */
96  DWORD data_type; /* data type */
97  void *data; /* value data */
98  DWORD data_size; /* size of the data (in bytes) */
99  BOOL backslash; /* TRUE if the current line contains a backslash */
100  enum parser_state state; /* current parser state */
101 };
102 
103 typedef WCHAR *(*parser_state_func)(struct parser *parser, WCHAR *pos);
104 
105 /* parser state machine functions */
106 static WCHAR *header_state(struct parser *parser, WCHAR *pos);
107 static WCHAR *parse_win31_line_state(struct parser *parser, WCHAR *pos);
108 static WCHAR *line_start_state(struct parser *parser, WCHAR *pos);
109 static WCHAR *key_name_state(struct parser *parser, WCHAR *pos);
110 static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos);
111 static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos);
112 static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos);
113 static WCHAR *data_start_state(struct parser *parser, WCHAR *pos);
114 static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos);
115 static WCHAR *data_type_state(struct parser *parser, WCHAR *pos);
116 static WCHAR *string_data_state(struct parser *parser, WCHAR *pos);
117 static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos);
118 static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos);
119 static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos);
120 static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos);
121 static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos);
122 static WCHAR *set_value_state(struct parser *parser, WCHAR *pos);
123 
125 {
126  header_state, /* HEADER */
127  parse_win31_line_state, /* PARSE_WIN31_LINE */
128  line_start_state, /* LINE_START */
129  key_name_state, /* KEY_NAME */
130  delete_key_state, /* DELETE_KEY */
131  default_value_name_state, /* DEFAULT_VALUE_NAME */
132  quoted_value_name_state, /* QUOTED_VALUE_NAME */
133  data_start_state, /* DATA_START */
134  delete_value_state, /* DELETE_VALUE */
135  data_type_state, /* DATA_TYPE */
136  string_data_state, /* STRING_DATA */
137  dword_data_state, /* DWORD_DATA */
138  hex_data_state, /* HEX_DATA */
139  eol_backslash_state, /* EOL_BACKSLASH */
140  hex_multiline_state, /* HEX_MULTILINE */
141  unknown_data_state, /* UNKNOWN_DATA */
142  set_value_state, /* SET_VALUE */
143 };
144 
145 /* set the new parser state and return the previous one */
146 static inline enum parser_state set_state(struct parser *parser, enum parser_state state)
147 {
148  enum parser_state ret = parser->state;
149  parser->state = state;
150  return ret;
151 }
152 
153 /******************************************************************************
154  * Converts a hex representation of a DWORD into a DWORD.
155  */
157 {
158  WCHAR *p, *end;
159  int count = 0;
160 
161  while (*str == ' ' || *str == '\t') str++;
162  if (!*str) goto error;
163 
164  p = str;
165  while (isxdigitW(*p))
166  {
167  count++;
168  p++;
169  }
170  if (count > 8) goto error;
171 
172  end = p;
173  while (*p == ' ' || *p == '\t') p++;
174  if (*p && *p != ';') goto error;
175 
176  *end = 0;
177  *dw = strtoulW(str, &end, 16);
178  return TRUE;
179 
180 error:
181  return FALSE;
182 }
183 
184 /******************************************************************************
185  * Converts comma-separated hex data into a binary string and modifies
186  * the input parameter to skip the concatenating backslash, if found.
187  *
188  * Returns TRUE or FALSE to indicate whether parsing was successful.
189  */
190 static BOOL convert_hex_csv_to_hex(struct parser *parser, WCHAR **str)
191 {
192  size_t size;
193  BYTE *d;
194  WCHAR *s;
195 
196  parser->backslash = FALSE;
197 
198  /* The worst case is 1 digit + 1 comma per byte */
199  size = ((lstrlenW(*str) + 1) / 2) + parser->data_size;
200  parser->data = heap_xrealloc(parser->data, size);
201 
202  s = *str;
203  d = (BYTE *)parser->data + parser->data_size;
204 
205  while (*s)
206  {
207  WCHAR *end;
208  unsigned long wc;
209 
210  wc = strtoulW(s, &end, 16);
211  if (wc > 0xff) return FALSE;
212 
213  if (s == end && wc == 0)
214  {
215  while (*end == ' ' || *end == '\t') end++;
216  if (*end == '\\')
217  {
218  parser->backslash = TRUE;
219  *str = end + 1;
220  return TRUE;
221  }
222  else if (*end == ';')
223  return TRUE;
224  return FALSE;
225  }
226 
227  *d++ = wc;
228  parser->data_size++;
229 
230  if (*end && *end != ',')
231  {
232  while (*end == ' ' || *end == '\t') end++;
233  if (*end && *end != ';') return FALSE;
234  return TRUE;
235  }
236 
237  if (*end) end++;
238  s = end;
239  }
240 
241  return TRUE;
242 }
243 
244 /******************************************************************************
245  * Parses the data type of the registry value being imported and modifies
246  * the input parameter to skip the string representation of the data type.
247  *
248  * Returns TRUE or FALSE to indicate whether a data type was found.
249  */
250 static BOOL parse_data_type(struct parser *parser, WCHAR **line)
251 {
252  struct data_type { const WCHAR *tag; int len; int type; int parse_type; };
253 
254  static const WCHAR quote[] = {'"'};
255  static const WCHAR hex[] = {'h','e','x',':'};
256  static const WCHAR dword[] = {'d','w','o','r','d',':'};
257  static const WCHAR hexp[] = {'h','e','x','('};
258 
259  static const struct data_type data_types[] = {
260  /* tag len type parse type */
261  { quote, 1, REG_SZ, REG_SZ },
262  { hex, 4, REG_BINARY, REG_BINARY },
263  { dword, 6, REG_DWORD, REG_DWORD },
264  { hexp, 4, -1, REG_BINARY }, /* REG_NONE, REG_EXPAND_SZ, REG_MULTI_SZ */
265  { NULL, 0, 0, 0 }
266  };
267 
268  const struct data_type *ptr;
269 
270  for (ptr = data_types; ptr->tag; ptr++)
271  {
272  if (strncmpW(ptr->tag, *line, ptr->len))
273  continue;
274 
275  parser->parse_type = ptr->parse_type;
276  parser->data_type = ptr->parse_type;
277  *line += ptr->len;
278 
279  if (ptr->type == -1)
280  {
281  WCHAR *end;
282  DWORD val;
283 
284  if (!**line || tolowerW((*line)[1]) == 'x')
285  return FALSE;
286 
287  /* "hex(xx):" is special */
288  val = wcstoul(*line, &end, 16);
289  if (*end != ')' || *(end + 1) != ':' || (val == ~0u && errno == ERANGE))
290  return FALSE;
291 
292  parser->data_type = val;
293  *line = end + 2;
294  }
295  return TRUE;
296  }
297  return FALSE;
298 }
299 
300 /******************************************************************************
301  * Replaces escape sequences with their character equivalents and
302  * null-terminates the string on the first non-escaped double quote.
303  *
304  * Assigns a pointer to the remaining unparsed data in the line.
305  * Returns TRUE or FALSE to indicate whether a closing double quote was found.
306  */
307 static BOOL unescape_string(WCHAR *str, WCHAR **unparsed)
308 {
309  int str_idx = 0; /* current character under analysis */
310  int val_idx = 0; /* the last character of the unescaped string */
311  int len = lstrlenW(str);
312  BOOL ret;
313 
314  for (str_idx = 0; str_idx < len; str_idx++, val_idx++)
315  {
316  if (str[str_idx] == '\\')
317  {
318  str_idx++;
319  switch (str[str_idx])
320  {
321  case 'n':
322  str[val_idx] = '\n';
323  break;
324  case 'r':
325  str[val_idx] = '\r';
326  break;
327  case '0':
328  str[val_idx] = '\0';
329  break;
330  case '\\':
331  case '"':
332  str[val_idx] = str[str_idx];
333  break;
334  default:
335  if (!str[str_idx]) return FALSE;
336  output_message(STRING_ESCAPE_SEQUENCE, str[str_idx]);
337  str[val_idx] = str[str_idx];
338  break;
339  }
340  }
341  else if (str[str_idx] == '"')
342  break;
343  else
344  str[val_idx] = str[str_idx];
345  }
346 
347  ret = (str[str_idx] == '"');
348  *unparsed = str + str_idx + 1;
349  str[val_idx] = '\0';
350  return ret;
351 }
352 
353 static HKEY parse_key_name(WCHAR *key_name, WCHAR **key_path)
354 {
355  if (!key_name) return 0;
356 
357  *key_path = strchrW(key_name, '\\');
358  if (*key_path) (*key_path)++;
359 
360  return path_get_rootkey(key_name);
361 }
362 
363 static void close_key(struct parser *parser)
364 {
365  if (parser->hkey)
366  {
367  heap_free(parser->key_name);
368  parser->key_name = NULL;
369 
370  RegCloseKey(parser->hkey);
371  parser->hkey = NULL;
372  }
373 }
374 
375 static LONG open_key(struct parser *parser, WCHAR *path)
376 {
377  HKEY key_class;
378  WCHAR *key_path;
379  LONG res;
380 
381  close_key(parser);
382 
383  /* Get the registry class */
384  if (!path || !(key_class = parse_key_name(path, &key_path)))
386 
387  res = RegCreateKeyExW(key_class, key_path, 0, NULL, REG_OPTION_NON_VOLATILE,
388  KEY_ALL_ACCESS, NULL, &parser->hkey, NULL);
389 
390  if (res == ERROR_SUCCESS)
391  {
392  parser->key_name = heap_xalloc((lstrlenW(path) + 1) * sizeof(WCHAR));
393  lstrcpyW(parser->key_name, path);
394  }
395  else
396  parser->hkey = NULL;
397 
398  return res;
399 }
400 
401 static void free_parser_data(struct parser *parser)
402 {
403  if (parser->parse_type == REG_DWORD || parser->parse_type == REG_BINARY)
404  heap_free(parser->data);
405 
406  parser->data = NULL;
407  parser->data_size = 0;
408 }
409 
410 static void prepare_hex_string_data(struct parser *parser)
411 {
412  if (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ ||
413  parser->data_type == REG_SZ)
414  {
415  if (parser->is_unicode)
416  {
417  WCHAR *data = parser->data;
418  DWORD len = parser->data_size / sizeof(WCHAR);
419 
420  if (data[len - 1] != 0)
421  {
422  data[len] = 0;
423  parser->data_size += sizeof(WCHAR);
424  }
425  }
426  else
427  {
428  BYTE *data = parser->data;
429 
430  if (data[parser->data_size - 1] != 0)
431  {
432  data[parser->data_size] = 0;
433  parser->data_size++;
434  }
435 
436  parser->data = GetWideStringN(parser->data, parser->data_size, &parser->data_size);
437  parser->data_size *= sizeof(WCHAR);
438  heap_free(data);
439  }
440  }
441 }
442 
449 };
450 
452 {
453  static const WCHAR header_31[] = {'R','E','G','E','D','I','T',0};
454  static const WCHAR header_40[] = {'R','E','G','E','D','I','T','4',0};
455  static const WCHAR header_50[] = {'W','i','n','d','o','w','s',' ',
456  'R','e','g','i','s','t','r','y',' ','E','d','i','t','o','r',' ',
457  'V','e','r','s','i','o','n',' ','5','.','0','0',0};
458 
459  while (*s == ' ' || *s == '\t') s++;
460 
461  if (!strcmpW(s, header_31))
462  return REG_VERSION_31;
463 
464  if (!strcmpW(s, header_40))
465  return REG_VERSION_40;
466 
467  if (!strcmpW(s, header_50))
468  return REG_VERSION_50;
469 
470  /* The Windows version accepts registry file headers beginning with "REGEDIT" and ending
471  * with other characters, as long as "REGEDIT" appears at the start of the line. For example,
472  * "REGEDIT 4", "REGEDIT9" and "REGEDIT4FOO" are all treated as valid file headers.
473  * In all such cases, however, the contents of the registry file are not imported.
474  */
475  if (!strncmpW(s, header_31, 7)) /* "REGEDIT" without NUL */
476  return REG_VERSION_FUZZY;
477 
478  return REG_VERSION_INVALID;
479 }
480 
481 /* handler for parser HEADER state */
482 static WCHAR *header_state(struct parser *parser, WCHAR *pos)
483 {
484  WCHAR *line, *header;
485 
486  if (!(line = get_line(parser->file)))
487  return NULL;
488 
489  if (!parser->is_unicode)
490  {
491  header = heap_xalloc((lstrlenW(line) + 3) * sizeof(WCHAR));
492  header[0] = parser->two_wchars[0];
493  header[1] = parser->two_wchars[1];
494  lstrcpyW(header + 2, line);
495  parser->reg_version = parse_file_header(header);
496  heap_free(header);
497  }
498  else parser->reg_version = parse_file_header(line);
499 
500  switch (parser->reg_version)
501  {
502  case REG_VERSION_31:
503  set_state(parser, PARSE_WIN31_LINE);
504  break;
505  case REG_VERSION_40:
506  case REG_VERSION_50:
507  set_state(parser, LINE_START);
508  break;
509  default:
510  get_line(NULL); /* Reset static variables */
511  return NULL;
512  }
513 
514  return line;
515 }
516 
517 /* handler for parser PARSE_WIN31_LINE state */
518 static WCHAR *parse_win31_line_state(struct parser *parser, WCHAR *pos)
519 {
520  WCHAR *line, *value;
521  static WCHAR hkcr[] = {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T'};
522  unsigned int key_end = 0;
523 
524  if (!(line = get_line(parser->file)))
525  return NULL;
526 
527  if (strncmpW(line, hkcr, ARRAY_SIZE(hkcr)))
528  return line;
529 
530  /* get key name */
531  while (line[key_end] && !isspaceW(line[key_end])) key_end++;
532 
533  value = line + key_end;
534  while (*value == ' ' || *value == '\t') value++;
535 
536  if (*value == '=') value++;
537  if (*value == ' ') value++; /* at most one space is skipped */
538 
539  line[key_end] = 0;
540 
541  if (open_key(parser, line) != ERROR_SUCCESS)
542  {
544  return line;
545  }
546 
547  parser->value_name = NULL;
548  parser->data_type = REG_SZ;
549  parser->data = value;
550  parser->data_size = (lstrlenW(value) + 1) * sizeof(WCHAR);
551 
552  set_state(parser, SET_VALUE);
553  return value;
554 }
555 
556 /* handler for parser LINE_START state */
557 static WCHAR *line_start_state(struct parser *parser, WCHAR *pos)
558 {
559  WCHAR *line, *p;
560 
561  if (!(line = get_line(parser->file)))
562  return NULL;
563 
564  for (p = line; *p; p++)
565  {
566  switch (*p)
567  {
568  case '[':
569  set_state(parser, KEY_NAME);
570  return p + 1;
571  case '@':
572  set_state(parser, DEFAULT_VALUE_NAME);
573  return p;
574  case '"':
575  set_state(parser, QUOTED_VALUE_NAME);
576  return p + 1;
577  case ' ':
578  case '\t':
579  break;
580  default:
581  return p;
582  }
583  }
584 
585  return p;
586 }
587 
588 /* handler for parser KEY_NAME state */
589 static WCHAR *key_name_state(struct parser *parser, WCHAR *pos)
590 {
591  WCHAR *p = pos, *key_end;
592 
593  if (*p == ' ' || *p == '\t' || !(key_end = strrchrW(p, ']')))
594  goto done;
595 
596  *key_end = 0;
597 
598  if (*p == '-')
599  {
600  set_state(parser, DELETE_KEY);
601  return p + 1;
602  }
603  else if (open_key(parser, p) != ERROR_SUCCESS)
605 
606 done:
607  set_state(parser, LINE_START);
608  return p;
609 }
610 
611 /* handler for parser DELETE_KEY state */
612 static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos)
613 {
614  WCHAR *p = pos;
615 
616  close_key(parser);
617 
618  if (*p == 'H' || *p == 'h')
619  {
620  HKEY root;
621  WCHAR *path;
622 
623  root = parse_key_name(p, &path);
624 
625  if (root && path && *path)
626  RegDeleteTreeW(root, path);
627  }
628 
629  set_state(parser, LINE_START);
630  return p;
631 }
632 
633 /* handler for parser DEFAULT_VALUE_NAME state */
634 static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos)
635 {
636  heap_free(parser->value_name);
637  parser->value_name = NULL;
638 
639  set_state(parser, DATA_START);
640  return pos + 1;
641 }
642 
643 /* handler for parser QUOTED_VALUE_NAME state */
644 static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos)
645 {
646  WCHAR *val_name = pos, *p;
647 
648  if (parser->value_name)
649  {
650  heap_free(parser->value_name);
651  parser->value_name = NULL;
652  }
653 
654  if (!unescape_string(val_name, &p))
655  goto invalid;
656 
657  /* copy the value name in case we need to parse multiple lines and the buffer is overwritten */
658  parser->value_name = heap_xalloc((lstrlenW(val_name) + 1) * sizeof(WCHAR));
659  lstrcpyW(parser->value_name, val_name);
660 
661  set_state(parser, DATA_START);
662  return p;
663 
664 invalid:
665  set_state(parser, LINE_START);
666  return val_name;
667 }
668 
669 /* handler for parser DATA_START state */
670 static WCHAR *data_start_state(struct parser *parser, WCHAR *pos)
671 {
672  WCHAR *p = pos;
673  unsigned int len;
674 
675  while (*p == ' ' || *p == '\t') p++;
676  if (*p != '=') goto invalid;
677  p++;
678  while (*p == ' ' || *p == '\t') p++;
679 
680  /* trim trailing whitespace */
681  len = strlenW(p);
682  while (len > 0 && (p[len - 1] == ' ' || p[len - 1] == '\t')) len--;
683  p[len] = 0;
684 
685  if (*p == '-')
686  set_state(parser, DELETE_VALUE);
687  else
688  set_state(parser, DATA_TYPE);
689  return p;
690 
691 invalid:
692  set_state(parser, LINE_START);
693  return p;
694 }
695 
696 /* handler for parser DELETE_VALUE state */
697 static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos)
698 {
699  WCHAR *p = pos + 1;
700 
701  while (*p == ' ' || *p == '\t') p++;
702  if (*p && *p != ';') goto done;
703 
704  RegDeleteValueW(parser->hkey, parser->value_name);
705 
706 done:
707  set_state(parser, LINE_START);
708  return p;
709 }
710 
711 /* handler for parser DATA_TYPE state */
712 static WCHAR *data_type_state(struct parser *parser, WCHAR *pos)
713 {
714  WCHAR *line = pos;
715 
716  if (!parse_data_type(parser, &line))
717  {
718  set_state(parser, LINE_START);
719  return line;
720  }
721 
722  switch (parser->parse_type)
723  {
724  case REG_SZ:
725  set_state(parser, STRING_DATA);
726  break;
727  case REG_DWORD:
728  set_state(parser, DWORD_DATA);
729  break;
730  case REG_BINARY: /* all hex data types, including undefined */
731  set_state(parser, HEX_DATA);
732  break;
733  default:
734  set_state(parser, UNKNOWN_DATA);
735  }
736 
737  return line;
738 }
739 
740 /* handler for parser STRING_DATA state */
741 static WCHAR *string_data_state(struct parser *parser, WCHAR *pos)
742 {
743  WCHAR *line;
744 
745  parser->data = pos;
746 
747  if (!unescape_string(parser->data, &line))
748  goto invalid;
749 
750  while (*line == ' ' || *line == '\t') line++;
751  if (*line && *line != ';') goto invalid;
752 
753  parser->data_size = (lstrlenW(parser->data) + 1) * sizeof(WCHAR);
754 
755  set_state(parser, SET_VALUE);
756  return line;
757 
758 invalid:
759  free_parser_data(parser);
760  set_state(parser, LINE_START);
761  return line;
762 }
763 
764 /* handler for parser DWORD_DATA state */
765 static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos)
766 {
767  WCHAR *line = pos;
768 
769  parser->data = heap_xalloc(sizeof(DWORD));
770 
771  if (!convert_hex_to_dword(line, parser->data))
772  goto invalid;
773 
774  parser->data_size = sizeof(DWORD);
775 
776  set_state(parser, SET_VALUE);
777  return line;
778 
779 invalid:
780  free_parser_data(parser);
781  set_state(parser, LINE_START);
782  return line;
783 }
784 
785 /* handler for parser HEX_DATA state */
786 static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos)
787 {
788  WCHAR *line = pos;
789 
790  if (!*line)
791  goto set_value;
792 
793  if (!convert_hex_csv_to_hex(parser, &line))
794  goto invalid;
795 
796  if (parser->backslash)
797  {
798  set_state(parser, EOL_BACKSLASH);
799  return line;
800  }
801 
802  prepare_hex_string_data(parser);
803 
804 set_value:
805  set_state(parser, SET_VALUE);
806  return line;
807 
808 invalid:
809  free_parser_data(parser);
810  set_state(parser, LINE_START);
811  return line;
812 }
813 
814 /* handler for parser EOL_BACKSLASH state */
815 static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos)
816 {
817  WCHAR *p = pos;
818 
819  while (*p == ' ' || *p == '\t') p++;
820  if (*p && *p != ';') goto invalid;
821 
822  set_state(parser, HEX_MULTILINE);
823  return pos;
824 
825 invalid:
826  free_parser_data(parser);
827  set_state(parser, LINE_START);
828  return p;
829 }
830 
831 /* handler for parser HEX_MULTILINE state */
832 static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos)
833 {
834  WCHAR *line;
835 
836  if (!(line = get_line(parser->file)))
837  {
838  prepare_hex_string_data(parser);
839  set_state(parser, SET_VALUE);
840  return pos;
841  }
842 
843  while (*line == ' ' || *line == '\t') line++;
844  if (!*line || *line == ';') return line;
845 
846  if (!isxdigitW(*line)) goto invalid;
847 
848  set_state(parser, HEX_DATA);
849  return line;
850 
851 invalid:
852  free_parser_data(parser);
853  set_state(parser, LINE_START);
854  return line;
855 }
856 
857 /* handler for parser UNKNOWN_DATA state */
858 static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos)
859 {
860  FIXME("Unknown registry data type [0x%x]\n", parser->data_type);
861 
862  set_state(parser, LINE_START);
863  return pos;
864 }
865 
866 /* handler for parser SET_VALUE state */
867 static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
868 {
869  RegSetValueExW(parser->hkey, parser->value_name, 0, parser->data_type,
870  parser->data, parser->data_size);
871 
872  free_parser_data(parser);
873 
874  if (parser->reg_version == REG_VERSION_31)
875  set_state(parser, PARSE_WIN31_LINE);
876  else
877  set_state(parser, LINE_START);
878 
879  return pos;
880 }
881 
882 #define REG_VAL_BUF_SIZE 4096
883 
884 static WCHAR *get_lineA(FILE *fp)
885 {
886  static WCHAR *lineW;
887  static size_t size;
888  static char *buf, *next;
889  char *line;
890 
891  heap_free(lineW);
892 
893  if (!fp) goto cleanup;
894 
895  if (!size)
896  {
897  size = REG_VAL_BUF_SIZE;
898  buf = heap_xalloc(size);
899  *buf = 0;
900  next = buf;
901  }
902  line = next;
903 
904  while (next)
905  {
906  char *p = strpbrk(line, "\r\n");
907  if (!p)
908  {
909  size_t len, count;
910  len = strlen(next);
911  memmove(buf, next, len + 1);
912  if (size - len < 3)
913  {
914  size *= 2;
915  buf = heap_xrealloc(buf, size);
916  }
917  if (!(count = fread(buf + len, 1, size - len - 1, fp)))
918  {
919  next = NULL;
920  lineW = GetWideString(buf);
921  return lineW;
922  }
923  buf[len + count] = 0;
924  next = buf;
925  line = buf;
926  continue;
927  }
928  next = p + 1;
929  if (*p == '\r' && *(p + 1) == '\n') next++;
930  *p = 0;
931  lineW = GetWideString(line);
932  return lineW;
933  }
934 
935 cleanup:
936  lineW = NULL;
937  if (size) heap_free(buf);
938  size = 0;
939  return NULL;
940 }
941 
942 static WCHAR *get_lineW(FILE *fp)
943 {
944  static size_t size;
945  static WCHAR *buf, *next;
946  WCHAR *line;
947 
948  if (!fp) goto cleanup;
949 
950  if (!size)
951  {
952  size = REG_VAL_BUF_SIZE;
953  buf = heap_xalloc(size * sizeof(WCHAR));
954  *buf = 0;
955  next = buf;
956  }
957  line = next;
958 
959  while (next)
960  {
961  static const WCHAR line_endings[] = {'\r','\n',0};
962  WCHAR *p = strpbrkW(line, line_endings);
963  if (!p)
964  {
965  size_t len, count;
966  len = strlenW(next);
967  memmove(buf, next, (len + 1) * sizeof(WCHAR));
968  if (size - len < 3)
969  {
970  size *= 2;
971  buf = heap_xrealloc(buf, size * sizeof(WCHAR));
972  }
973  if (!(count = fread(buf + len, sizeof(WCHAR), size - len - 1, fp)))
974  {
975  next = NULL;
976  return buf;
977  }
978  buf[len + count] = 0;
979  next = buf;
980  line = buf;
981  continue;
982  }
983  next = p + 1;
984  if (*p == '\r' && *(p + 1) == '\n') next++;
985  *p = 0;
986  return line;
987  }
988 
989 cleanup:
990  if (size) heap_free(buf);
991  size = 0;
992  return NULL;
993 }
994 
996 {
997  FILE *fp;
998  static const WCHAR rb_mode[] = {'r','b',0};
999  BYTE s[2];
1000  struct parser parser;
1001  WCHAR *pos;
1002 
1003  fp = _wfopen(filename, rb_mode);
1004  if (!fp)
1005  {
1007  return 1;
1008  }
1009 
1010  if (fread(s, sizeof(WCHAR), 1, fp) != 1)
1011  goto error;
1012 
1013  parser.is_unicode = (s[0] == 0xff && s[1] == 0xfe);
1014  get_line = parser.is_unicode ? get_lineW : get_lineA;
1015 
1016  parser.file = fp;
1017  parser.two_wchars[0] = s[0];
1018  parser.two_wchars[1] = s[1];
1019  parser.reg_version = -1;
1020  parser.hkey = NULL;
1021  parser.key_name = NULL;
1022  parser.value_name = NULL;
1023  parser.parse_type = 0;
1024  parser.data_type = 0;
1025  parser.data = NULL;
1026  parser.data_size = 0;
1027  parser.backslash = FALSE;
1028  parser.state = HEADER;
1029 
1030  pos = parser.two_wchars;
1031 
1032  /* parser main loop */
1033  while (pos)
1034  pos = (parser_funcs[parser.state])(&parser, pos);
1035 
1036  if (parser.reg_version == REG_VERSION_INVALID)
1037  goto error;
1038 
1039  heap_free(parser.value_name);
1040  close_key(&parser);
1041 
1042  fclose(fp);
1043  return 0;
1044 
1045 error:
1046  fclose(fp);
1047  return 1;
1048 }
static WCHAR * quoted_value_name_state(struct parser *parser, WCHAR *pos)
Definition: import.c:644
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static WCHAR * parse_win31_line_state(struct parser *parser, WCHAR *pos)
Definition: import.c:518
static const WCHAR invalid[]
Definition: assoc.c:39
WCHAR * value_name
Definition: import.c:94
char strA[12]
Definition: clipboard.c:2028
static WCHAR * eol_backslash_state(struct parser *parser, WCHAR *pos)
Definition: import.c:815
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static WCHAR * get_lineA(FILE *fp)
Definition: import.c:884
static WCHAR * set_value_state(struct parser *parser, WCHAR *pos)
Definition: import.c:867
#define TRUE
Definition: types.h:120
static void close_key(struct parser *parser)
Definition: import.c:363
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static WCHAR * GetWideStringN(const char *strA, int size, DWORD *len)
Definition: import.c:46
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL is_unicode
Definition: import.c:90
reg_versions
Definition: import.c:443
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strpbrk(const char *String, const char *Delimiters)
Definition: utclib.c:302
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define REG_BINARY
Definition: nt_native.h:1496
_Check_return_ _CRTIMP FILE *__cdecl _wfopen(_In_z_ const wchar_t *_Filename, _In_z_ const wchar_t *_Mode)
static HKEY parse_key_name(WCHAR *key_name, WCHAR **key_path)
Definition: import.c:353
__wchar_t WCHAR
Definition: xmlstorage.h:180
GLsizei const GLchar ** path
Definition: glext.h:7234
#define DWORD
Definition: msvc.h:34
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
#define CP_ACP
Definition: compat.h:99
WINE_UNICODE_INLINE int isspaceW(WCHAR wc)
Definition: unicode.h:165
GLuint GLuint GLsizei count
Definition: gl.h:1545
struct _root root
enum parser_state state
Definition: import.c:100
static WCHAR * header_state(struct parser *parser, WCHAR *pos)
Definition: import.c:482
WINE_DEFAULT_DEBUG_CHANNEL(reg)
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble * u
Definition: glfuncs.h:88
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:147
int errno
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
WCHAR two_wchars[2]
Definition: import.c:89
static WCHAR * GetWideString(const char *strA)
Definition: import.c:32
#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
BOOL backslash
Definition: import.c:99
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1094
WINE_UNICODE_INLINE int strncmpW(const WCHAR *str1, const WCHAR *str2, int n)
Definition: unicode.h:235
static void prepare_hex_string_data(struct parser *parser)
Definition: import.c:410
void * data
Definition: import.c:97
DWORD parse_type
Definition: import.c:95
while(1)
Definition: macro.lex.yy.c:743
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
_Check_return_opt_ _CRTIMP size_t __cdecl fread(_Out_writes_bytes_(_ElementSize *_Count) void *_DstBuf, _In_ size_t _ElementSize, _In_ size_t _Count, _Inout_ FILE *_File)
WCHAR strW[12]
Definition: clipboard.c:2029
long LONG
Definition: pedump.c:60
#define REG_MULTI_SZ
Definition: nt_native.h:1501
PINFCACHELINE line
Definition: inffile.c:113
#define FIXME(fmt,...)
Definition: debug.h:110
static enum parser_state set_state(struct parser *parser, enum parser_state state)
Definition: import.c:146
static PVOID ptr
Definition: dispmode.c:27
#define quote
Definition: macro.lex.yy.c:534
#define STRING_FILE_NOT_FOUND
Definition: resource.h:58
const WCHAR * str
short int reg_version
Definition: import.c:91
smooth NULL
Definition: ftsmooth.c:416
static WCHAR * unknown_data_state(struct parser *parser, WCHAR *pos)
Definition: import.c:858
Definition: parser.c:48
HRESULT set_value(const struct table *table, UINT row, UINT column, LONGLONG val, CIMTYPE type)
Definition: table.c:209
GLuint GLfloat * val
Definition: glext.h:7180
static WCHAR * key_name_state(struct parser *parser, WCHAR *pos)
Definition: import.c:589
Definition: import.c:66
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4917
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizeiptr size
Definition: glext.h:5919
#define d
Definition: ke_i.h:81
WINE_UNICODE_INLINE WCHAR * strpbrkW(const WCHAR *str, const WCHAR *accept)
Definition: unicode.h:261
static WCHAR * line_start_state(struct parser *parser, WCHAR *pos)
Definition: import.c:557
WINE_UNICODE_INLINE WCHAR tolowerW(WCHAR ch)
Definition: unicode.h:135
unsigned long DWORD
Definition: ntddk_ex.h:95
static WCHAR * data_type_state(struct parser *parser, WCHAR *pos)
Definition: import.c:712
REFIID LPVOID DWORD dw
Definition: atlbase.h:40
unsigned int error
Definition: inffile.c:115
FILE * file
Definition: import.c:88
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
WINE_UNICODE_INLINE int isxdigitW(WCHAR wc)
Definition: unicode.h:175
#define ERANGE
Definition: acclib.h:92
int ret
static WCHAR * delete_value_state(struct parser *parser, WCHAR *pos)
Definition: import.c:697
HKEY hkey
Definition: import.c:92
static WCHAR * get_lineW(FILE *fp)
Definition: import.c:942
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
int reg_import(const WCHAR *filename)
Definition: import.c:995
void * heap_xrealloc(void *buf, size_t size)
Definition: reg.c:94
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
#define STRING_OPEN_KEY_FAILED
Definition: resource.h:59
static BOOL convert_hex_to_dword(WCHAR *str, DWORD *dw)
Definition: import.c:156
GLsizei const GLfloat * value
Definition: glext.h:6069
unsigned char BYTE
Definition: ntddk_ex.h:96
static BOOL parse_data_type(struct parser *parser, WCHAR **line)
Definition: import.c:250
#define STRING_ESCAPE_SEQUENCE
Definition: resource.h:60
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
static WCHAR *(* get_line)(FILE *)
Definition: import.c:61
const CHAR * end
Definition: inffile.c:106
LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
Definition: reg.c:1755
static BOOL unescape_string(WCHAR *str, WCHAR **unparsed)
Definition: import.c:307
static unsigned __int64 next
Definition: rand_nt.c:6
static WCHAR * string_data_state(struct parser *parser, WCHAR *pos)
Definition: import.c:741
#define lstrcpyW
Definition: compat.h:406
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2368
parser_state
Definition: import.c:64
#define ARRAY_SIZE(a)
Definition: main.h:24
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
Definition: services.c:325
UINT len
Definition: wql.tab.c:110
static int reg
Definition: i386-dis.c:1275
#define MultiByteToWideChar
Definition: compat.h:100
static WCHAR * dword_data_state(struct parser *parser, WCHAR *pos)
Definition: import.c:765
WCHAR * key_name
Definition: import.c:93
HKEY path_get_rootkey(const WCHAR *path)
Definition: reg.c:210
Definition: import.c:86
DWORD data_type
Definition: import.c:96
static LONG open_key(struct parser *parser, WCHAR *path)
Definition: import.c:375
static WCHAR * delete_key_state(struct parser *parser, WCHAR *pos)
Definition: import.c:612
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
static WCHAR * data_start_state(struct parser *parser, WCHAR *pos)
Definition: import.c:670
GLuint res
Definition: glext.h:9613
static const parser_state_func parser_funcs[NB_PARSER_STATES]
Definition: import.c:124
static enum reg_versions parse_file_header(const WCHAR *s)
Definition: import.c:451
char * cleanup(char *str)
Definition: wpickclick.c:99
void * heap_xalloc(size_t size)
Definition: reg.c:83
#define strtoulW(s1, s2, b)
Definition: unicode.h:41
static WCHAR * hex_multiline_state(struct parser *parser, WCHAR *pos)
Definition: import.c:832
static BOOL convert_hex_csv_to_hex(struct parser *parser, WCHAR **str)
Definition: import.c:190
static WCHAR * hex_data_state(struct parser *parser, WCHAR *pos)
Definition: import.c:786
GLfloat GLfloat p
Definition: glext.h:8902
static WCHAR * default_value_name_state(struct parser *parser, WCHAR *pos)
Definition: import.c:634
#define REG_VAL_BUF_SIZE
Definition: import.c:882
#define REG_DWORD
Definition: sdbapi.c:539
static void free_parser_data(struct parser *parser)
Definition: import.c:401
WCHAR *(* parser_state_func)(struct parser *parser, WCHAR *pos)
Definition: import.c:103
struct CFHEADER header
Definition: fdi.c:109
DWORD data_size
Definition: import.c:98
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define REG_SZ
Definition: layer.c:22
char * tag
Definition: main.c:59