import.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  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. #include <errno.h>
  19. #include <stdio.h>
  20. #include "reg.h"
  21. #include <wine/debug.h>
  22. WINE_DEFAULT_DEBUG_CHANNEL(reg);
  23. static WCHAR *GetWideString(const char *strA)
  24. {
  25. if (strA)
  26. {
  27. WCHAR *strW;
  28. int len = MultiByteToWideChar(CP_ACP, 0, strA, -1, NULL, 0);
  29. strW = malloc(len * sizeof(WCHAR));
  30. MultiByteToWideChar(CP_ACP, 0, strA, -1, strW, len);
  31. return strW;
  32. }
  33. return NULL;
  34. }
  35. static WCHAR *GetWideStringN(const char *strA, int size, DWORD *len)
  36. {
  37. if (strA)
  38. {
  39. WCHAR *strW;
  40. *len = MultiByteToWideChar(CP_ACP, 0, strA, size, NULL, 0);
  41. strW = malloc(*len * sizeof(WCHAR));
  42. MultiByteToWideChar(CP_ACP, 0, strA, size, strW, *len);
  43. return strW;
  44. }
  45. *len = 0;
  46. return NULL;
  47. }
  48. static WCHAR *(*get_line)(FILE *);
  49. /* parser definitions */
  50. enum parser_state
  51. {
  52. HEADER, /* parsing the registry file version header */
  53. PARSE_WIN31_LINE, /* parsing a Windows 3.1 registry line */
  54. LINE_START, /* at the beginning of a registry line */
  55. KEY_NAME, /* parsing a key name */
  56. DELETE_KEY, /* deleting a registry key */
  57. DEFAULT_VALUE_NAME, /* parsing a default value name */
  58. QUOTED_VALUE_NAME, /* parsing a double-quoted value name */
  59. DATA_START, /* preparing for data parsing operations */
  60. DELETE_VALUE, /* deleting a registry value */
  61. DATA_TYPE, /* parsing the registry data type */
  62. STRING_DATA, /* parsing REG_SZ data */
  63. DWORD_DATA, /* parsing DWORD data */
  64. HEX_DATA, /* parsing REG_BINARY, REG_NONE, REG_EXPAND_SZ or REG_MULTI_SZ data */
  65. EOL_BACKSLASH, /* preparing to parse multiple lines of hex data */
  66. HEX_MULTILINE, /* parsing multiple lines of hex data */
  67. UNKNOWN_DATA, /* parsing an unhandled or invalid data type */
  68. SET_VALUE, /* adding a value to the registry */
  69. NB_PARSER_STATES
  70. };
  71. struct parser
  72. {
  73. FILE *file; /* pointer to a registry file */
  74. WCHAR two_wchars[2]; /* first two characters from the encoding check */
  75. BOOL is_unicode; /* parsing Unicode or ASCII data */
  76. short int reg_version; /* registry file version */
  77. HKEY hkey; /* current registry key */
  78. WCHAR *key_name; /* current key name */
  79. WCHAR *value_name; /* value name */
  80. DWORD parse_type; /* generic data type for parsing */
  81. DWORD data_type; /* data type */
  82. void *data; /* value data */
  83. DWORD data_size; /* size of the data (in bytes) */
  84. BOOL backslash; /* TRUE if the current line contains a backslash */
  85. enum parser_state state; /* current parser state */
  86. };
  87. typedef WCHAR *(*parser_state_func)(struct parser *parser, WCHAR *pos);
  88. /* parser state machine functions */
  89. static WCHAR *header_state(struct parser *parser, WCHAR *pos);
  90. static WCHAR *parse_win31_line_state(struct parser *parser, WCHAR *pos);
  91. static WCHAR *line_start_state(struct parser *parser, WCHAR *pos);
  92. static WCHAR *key_name_state(struct parser *parser, WCHAR *pos);
  93. static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos);
  94. static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos);
  95. static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos);
  96. static WCHAR *data_start_state(struct parser *parser, WCHAR *pos);
  97. static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos);
  98. static WCHAR *data_type_state(struct parser *parser, WCHAR *pos);
  99. static WCHAR *string_data_state(struct parser *parser, WCHAR *pos);
  100. static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos);
  101. static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos);
  102. static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos);
  103. static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos);
  104. static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos);
  105. static WCHAR *set_value_state(struct parser *parser, WCHAR *pos);
  106. static const parser_state_func parser_funcs[NB_PARSER_STATES] =
  107. {
  108. header_state, /* HEADER */
  109. parse_win31_line_state, /* PARSE_WIN31_LINE */
  110. line_start_state, /* LINE_START */
  111. key_name_state, /* KEY_NAME */
  112. delete_key_state, /* DELETE_KEY */
  113. default_value_name_state, /* DEFAULT_VALUE_NAME */
  114. quoted_value_name_state, /* QUOTED_VALUE_NAME */
  115. data_start_state, /* DATA_START */
  116. delete_value_state, /* DELETE_VALUE */
  117. data_type_state, /* DATA_TYPE */
  118. string_data_state, /* STRING_DATA */
  119. dword_data_state, /* DWORD_DATA */
  120. hex_data_state, /* HEX_DATA */
  121. eol_backslash_state, /* EOL_BACKSLASH */
  122. hex_multiline_state, /* HEX_MULTILINE */
  123. unknown_data_state, /* UNKNOWN_DATA */
  124. set_value_state, /* SET_VALUE */
  125. };
  126. /* set the new parser state and return the previous one */
  127. static inline enum parser_state set_state(struct parser *parser, enum parser_state state)
  128. {
  129. enum parser_state ret = parser->state;
  130. parser->state = state;
  131. return ret;
  132. }
  133. /******************************************************************************
  134. * Converts a hex representation of a DWORD into a DWORD.
  135. */
  136. static BOOL convert_hex_to_dword(WCHAR *str, DWORD *dw)
  137. {
  138. WCHAR *p, *end;
  139. int count = 0;
  140. while (*str == ' ' || *str == '\t') str++;
  141. if (!*str) goto error;
  142. p = str;
  143. while (iswxdigit(*p))
  144. {
  145. count++;
  146. p++;
  147. }
  148. if (count > 8) goto error;
  149. end = p;
  150. while (*p == ' ' || *p == '\t') p++;
  151. if (*p && *p != ';') goto error;
  152. *end = 0;
  153. *dw = wcstoul(str, &end, 16);
  154. return TRUE;
  155. error:
  156. return FALSE;
  157. }
  158. /******************************************************************************
  159. * Converts comma-separated hex data into a binary string and modifies
  160. * the input parameter to skip the concatenating backslash, if found.
  161. *
  162. * Returns TRUE or FALSE to indicate whether parsing was successful.
  163. */
  164. static BOOL convert_hex_csv_to_hex(struct parser *parser, WCHAR **str)
  165. {
  166. size_t size;
  167. BYTE *d;
  168. WCHAR *s;
  169. parser->backslash = FALSE;
  170. /* The worst case is 1 digit + 1 comma per byte */
  171. size = ((lstrlenW(*str) + 1) / 2) + parser->data_size;
  172. parser->data = realloc(parser->data, size);
  173. s = *str;
  174. d = (BYTE *)parser->data + parser->data_size;
  175. while (*s)
  176. {
  177. WCHAR *end;
  178. unsigned long wc;
  179. wc = wcstoul(s, &end, 16);
  180. if (wc > 0xff) return FALSE;
  181. if (s == end && wc == 0)
  182. {
  183. while (*end == ' ' || *end == '\t') end++;
  184. if (*end == '\\')
  185. {
  186. parser->backslash = TRUE;
  187. *str = end + 1;
  188. return TRUE;
  189. }
  190. else if (*end == ';')
  191. return TRUE;
  192. return FALSE;
  193. }
  194. *d++ = wc;
  195. parser->data_size++;
  196. if (*end && *end != ',')
  197. {
  198. while (*end == ' ' || *end == '\t') end++;
  199. if (*end && *end != ';') return FALSE;
  200. return TRUE;
  201. }
  202. if (*end) end++;
  203. s = end;
  204. }
  205. return TRUE;
  206. }
  207. /******************************************************************************
  208. * Parses the data type of the registry value being imported and modifies
  209. * the input parameter to skip the string representation of the data type.
  210. *
  211. * Returns TRUE or FALSE to indicate whether a data type was found.
  212. */
  213. static BOOL parse_data_type(struct parser *parser, WCHAR **line)
  214. {
  215. struct data_type { const WCHAR *tag; int len; int type; int parse_type; };
  216. static const struct data_type data_types[] = {
  217. /* tag len type parse type */
  218. { L"\"", 1, REG_SZ, REG_SZ },
  219. { L"hex:", 4, REG_BINARY, REG_BINARY },
  220. { L"dword:", 6, REG_DWORD, REG_DWORD },
  221. { L"hex(", 4, -1, REG_BINARY }, /* REG_NONE, REG_EXPAND_SZ, REG_MULTI_SZ */
  222. { NULL, 0, 0, 0 }
  223. };
  224. const struct data_type *ptr;
  225. for (ptr = data_types; ptr->tag; ptr++)
  226. {
  227. if (wcsncmp(ptr->tag, *line, ptr->len))
  228. continue;
  229. parser->parse_type = ptr->parse_type;
  230. parser->data_type = ptr->parse_type;
  231. *line += ptr->len;
  232. if (ptr->type == -1)
  233. {
  234. WCHAR *end;
  235. DWORD val;
  236. if (!**line || towlower((*line)[1]) == 'x')
  237. return FALSE;
  238. /* "hex(xx):" is special */
  239. val = wcstoul(*line, &end, 16);
  240. if (*end != ')' || *(end + 1) != ':' || (val == ~0u && errno == ERANGE))
  241. return FALSE;
  242. parser->data_type = val;
  243. *line = end + 2;
  244. }
  245. return TRUE;
  246. }
  247. return FALSE;
  248. }
  249. /******************************************************************************
  250. * Replaces escape sequences with their character equivalents and
  251. * null-terminates the string on the first non-escaped double quote.
  252. *
  253. * Assigns a pointer to the remaining unparsed data in the line.
  254. * Returns TRUE or FALSE to indicate whether a closing double quote was found.
  255. */
  256. static BOOL unescape_string(WCHAR *str, WCHAR **unparsed)
  257. {
  258. int str_idx = 0; /* current character under analysis */
  259. int val_idx = 0; /* the last character of the unescaped string */
  260. int len = lstrlenW(str);
  261. BOOL ret;
  262. for (str_idx = 0; str_idx < len; str_idx++, val_idx++)
  263. {
  264. if (str[str_idx] == '\\')
  265. {
  266. str_idx++;
  267. switch (str[str_idx])
  268. {
  269. case 'n':
  270. str[val_idx] = '\n';
  271. break;
  272. case 'r':
  273. str[val_idx] = '\r';
  274. break;
  275. case '0':
  276. return FALSE;
  277. case '\\':
  278. case '"':
  279. str[val_idx] = str[str_idx];
  280. break;
  281. default:
  282. if (!str[str_idx]) return FALSE;
  283. output_message(STRING_ESCAPE_SEQUENCE, str[str_idx]);
  284. str[val_idx] = str[str_idx];
  285. break;
  286. }
  287. }
  288. else if (str[str_idx] == '"')
  289. break;
  290. else
  291. str[val_idx] = str[str_idx];
  292. }
  293. ret = (str[str_idx] == '"');
  294. *unparsed = str + str_idx + 1;
  295. str[val_idx] = '\0';
  296. return ret;
  297. }
  298. static HKEY parse_key_name(WCHAR *key_name, WCHAR **key_path)
  299. {
  300. if (!key_name) return 0;
  301. *key_path = wcschr(key_name, '\\');
  302. if (*key_path) (*key_path)++;
  303. return path_get_rootkey(key_name);
  304. }
  305. static void close_key(struct parser *parser)
  306. {
  307. if (parser->hkey)
  308. {
  309. free(parser->key_name);
  310. parser->key_name = NULL;
  311. RegCloseKey(parser->hkey);
  312. parser->hkey = NULL;
  313. }
  314. }
  315. static LONG open_key(struct parser *parser, WCHAR *path)
  316. {
  317. HKEY key_class;
  318. WCHAR *key_path;
  319. LONG res;
  320. close_key(parser);
  321. /* Get the registry class */
  322. if (!path || !(key_class = parse_key_name(path, &key_path)))
  323. return ERROR_INVALID_PARAMETER;
  324. res = RegCreateKeyExW(key_class, key_path, 0, NULL, REG_OPTION_NON_VOLATILE,
  325. KEY_ALL_ACCESS, NULL, &parser->hkey, NULL);
  326. if (res == ERROR_SUCCESS)
  327. {
  328. parser->key_name = malloc((lstrlenW(path) + 1) * sizeof(WCHAR));
  329. lstrcpyW(parser->key_name, path);
  330. }
  331. else
  332. parser->hkey = NULL;
  333. return res;
  334. }
  335. static void free_parser_data(struct parser *parser)
  336. {
  337. if (parser->parse_type == REG_DWORD || parser->parse_type == REG_BINARY)
  338. free(parser->data);
  339. parser->data = NULL;
  340. parser->data_size = 0;
  341. }
  342. static void prepare_hex_string_data(struct parser *parser)
  343. {
  344. if (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ ||
  345. parser->data_type == REG_SZ)
  346. {
  347. if (parser->is_unicode)
  348. {
  349. WCHAR *data = parser->data;
  350. DWORD len = parser->data_size / sizeof(WCHAR);
  351. if (data[len - 1] != 0)
  352. {
  353. data[len] = 0;
  354. parser->data_size += sizeof(WCHAR);
  355. }
  356. }
  357. else
  358. {
  359. BYTE *data = parser->data;
  360. if (data[parser->data_size - 1] != 0)
  361. {
  362. data[parser->data_size] = 0;
  363. parser->data_size++;
  364. }
  365. parser->data = GetWideStringN(parser->data, parser->data_size, &parser->data_size);
  366. parser->data_size *= sizeof(WCHAR);
  367. free(data);
  368. }
  369. }
  370. }
  371. enum reg_versions {
  372. REG_VERSION_31,
  373. REG_VERSION_40,
  374. REG_VERSION_50,
  375. REG_VERSION_FUZZY,
  376. REG_VERSION_INVALID
  377. };
  378. static enum reg_versions parse_file_header(const WCHAR *s)
  379. {
  380. static const WCHAR *header_31 = L"REGEDIT";
  381. while (*s == ' ' || *s == '\t') s++;
  382. if (!lstrcmpW(s, header_31))
  383. return REG_VERSION_31;
  384. if (!lstrcmpW(s, L"REGEDIT4"))
  385. return REG_VERSION_40;
  386. if (!lstrcmpW(s, L"Windows Registry Editor Version 5.00"))
  387. return REG_VERSION_50;
  388. /* The Windows version accepts registry file headers beginning with "REGEDIT" and ending
  389. * with other characters, as long as "REGEDIT" appears at the start of the line. For example,
  390. * "REGEDIT 4", "REGEDIT9" and "REGEDIT4FOO" are all treated as valid file headers.
  391. * In all such cases, however, the contents of the registry file are not imported.
  392. */
  393. if (!wcsncmp(s, header_31, 7)) /* "REGEDIT" without NUL */
  394. return REG_VERSION_FUZZY;
  395. return REG_VERSION_INVALID;
  396. }
  397. /* handler for parser HEADER state */
  398. static WCHAR *header_state(struct parser *parser, WCHAR *pos)
  399. {
  400. WCHAR *line, *header;
  401. if (!(line = get_line(parser->file)))
  402. return NULL;
  403. if (!parser->is_unicode)
  404. {
  405. header = malloc((lstrlenW(line) + 3) * sizeof(WCHAR));
  406. header[0] = parser->two_wchars[0];
  407. header[1] = parser->two_wchars[1];
  408. lstrcpyW(header + 2, line);
  409. parser->reg_version = parse_file_header(header);
  410. free(header);
  411. }
  412. else parser->reg_version = parse_file_header(line);
  413. switch (parser->reg_version)
  414. {
  415. case REG_VERSION_31:
  416. set_state(parser, PARSE_WIN31_LINE);
  417. break;
  418. case REG_VERSION_40:
  419. case REG_VERSION_50:
  420. set_state(parser, LINE_START);
  421. break;
  422. default:
  423. get_line(NULL); /* Reset static variables */
  424. return NULL;
  425. }
  426. return line;
  427. }
  428. /* handler for parser PARSE_WIN31_LINE state */
  429. static WCHAR *parse_win31_line_state(struct parser *parser, WCHAR *pos)
  430. {
  431. WCHAR *line, *value;
  432. unsigned int key_end = 0;
  433. if (!(line = get_line(parser->file)))
  434. return NULL;
  435. if (wcsncmp(line, L"HKEY_CLASSES_ROOT", 17)) /* "HKEY_CLASSES_ROOT" without NUL */
  436. return line;
  437. /* get key name */
  438. while (line[key_end] && !iswspace(line[key_end])) key_end++;
  439. value = line + key_end;
  440. while (*value == ' ' || *value == '\t') value++;
  441. if (*value == '=') value++;
  442. if (*value == ' ') value++; /* at most one space is skipped */
  443. line[key_end] = 0;
  444. if (open_key(parser, line) != ERROR_SUCCESS)
  445. {
  446. output_message(STRING_KEY_IMPORT_FAILED, line);
  447. return line;
  448. }
  449. parser->value_name = NULL;
  450. parser->data_type = REG_SZ;
  451. parser->data = value;
  452. parser->data_size = (lstrlenW(value) + 1) * sizeof(WCHAR);
  453. set_state(parser, SET_VALUE);
  454. return value;
  455. }
  456. /* handler for parser LINE_START state */
  457. static WCHAR *line_start_state(struct parser *parser, WCHAR *pos)
  458. {
  459. WCHAR *line, *p;
  460. if (!(line = get_line(parser->file)))
  461. return NULL;
  462. for (p = line; *p; p++)
  463. {
  464. switch (*p)
  465. {
  466. case '[':
  467. set_state(parser, KEY_NAME);
  468. return p + 1;
  469. case '@':
  470. set_state(parser, DEFAULT_VALUE_NAME);
  471. return p;
  472. case '"':
  473. set_state(parser, QUOTED_VALUE_NAME);
  474. return p + 1;
  475. case ' ':
  476. case '\t':
  477. break;
  478. default:
  479. return p;
  480. }
  481. }
  482. return p;
  483. }
  484. /* handler for parser KEY_NAME state */
  485. static WCHAR *key_name_state(struct parser *parser, WCHAR *pos)
  486. {
  487. WCHAR *p = pos, *key_end;
  488. if (*p == ' ' || *p == '\t' || !(key_end = wcsrchr(p, ']')))
  489. goto done;
  490. *key_end = 0;
  491. if (*p == '-')
  492. {
  493. set_state(parser, DELETE_KEY);
  494. return p + 1;
  495. }
  496. else if (open_key(parser, p) != ERROR_SUCCESS)
  497. output_message(STRING_KEY_IMPORT_FAILED, p);
  498. done:
  499. set_state(parser, LINE_START);
  500. return p;
  501. }
  502. /* handler for parser DELETE_KEY state */
  503. static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos)
  504. {
  505. WCHAR *p = pos;
  506. close_key(parser);
  507. if (*p == 'H' || *p == 'h')
  508. {
  509. HKEY root;
  510. WCHAR *path;
  511. root = parse_key_name(p, &path);
  512. if (root && path && *path)
  513. RegDeleteTreeW(root, path);
  514. }
  515. set_state(parser, LINE_START);
  516. return p;
  517. }
  518. /* handler for parser DEFAULT_VALUE_NAME state */
  519. static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos)
  520. {
  521. free(parser->value_name);
  522. parser->value_name = NULL;
  523. set_state(parser, DATA_START);
  524. return pos + 1;
  525. }
  526. /* handler for parser QUOTED_VALUE_NAME state */
  527. static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos)
  528. {
  529. WCHAR *val_name = pos, *p;
  530. free(parser->value_name);
  531. parser->value_name = NULL;
  532. if (!unescape_string(val_name, &p))
  533. goto invalid;
  534. /* copy the value name in case we need to parse multiple lines and the buffer is overwritten */
  535. parser->value_name = malloc((lstrlenW(val_name) + 1) * sizeof(WCHAR));
  536. lstrcpyW(parser->value_name, val_name);
  537. set_state(parser, DATA_START);
  538. return p;
  539. invalid:
  540. set_state(parser, LINE_START);
  541. return val_name;
  542. }
  543. /* handler for parser DATA_START state */
  544. static WCHAR *data_start_state(struct parser *parser, WCHAR *pos)
  545. {
  546. WCHAR *p = pos;
  547. unsigned int len;
  548. while (*p == ' ' || *p == '\t') p++;
  549. if (*p != '=') goto invalid;
  550. p++;
  551. while (*p == ' ' || *p == '\t') p++;
  552. /* trim trailing whitespace */
  553. len = lstrlenW(p);
  554. while (len > 0 && (p[len - 1] == ' ' || p[len - 1] == '\t')) len--;
  555. p[len] = 0;
  556. if (*p == '-')
  557. set_state(parser, DELETE_VALUE);
  558. else
  559. set_state(parser, DATA_TYPE);
  560. return p;
  561. invalid:
  562. set_state(parser, LINE_START);
  563. return p;
  564. }
  565. /* handler for parser DELETE_VALUE state */
  566. static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos)
  567. {
  568. WCHAR *p = pos + 1;
  569. while (*p == ' ' || *p == '\t') p++;
  570. if (*p && *p != ';') goto done;
  571. RegDeleteValueW(parser->hkey, parser->value_name);
  572. done:
  573. set_state(parser, LINE_START);
  574. return p;
  575. }
  576. /* handler for parser DATA_TYPE state */
  577. static WCHAR *data_type_state(struct parser *parser, WCHAR *pos)
  578. {
  579. WCHAR *line = pos;
  580. if (!parse_data_type(parser, &line))
  581. {
  582. set_state(parser, LINE_START);
  583. return line;
  584. }
  585. switch (parser->parse_type)
  586. {
  587. case REG_SZ:
  588. set_state(parser, STRING_DATA);
  589. break;
  590. case REG_DWORD:
  591. set_state(parser, DWORD_DATA);
  592. break;
  593. case REG_BINARY: /* all hex data types, including undefined */
  594. set_state(parser, HEX_DATA);
  595. break;
  596. default:
  597. set_state(parser, UNKNOWN_DATA);
  598. }
  599. return line;
  600. }
  601. /* handler for parser STRING_DATA state */
  602. static WCHAR *string_data_state(struct parser *parser, WCHAR *pos)
  603. {
  604. WCHAR *line;
  605. parser->data = pos;
  606. if (!unescape_string(parser->data, &line))
  607. goto invalid;
  608. while (*line == ' ' || *line == '\t') line++;
  609. if (*line && *line != ';') goto invalid;
  610. parser->data_size = (lstrlenW(parser->data) + 1) * sizeof(WCHAR);
  611. set_state(parser, SET_VALUE);
  612. return line;
  613. invalid:
  614. free_parser_data(parser);
  615. set_state(parser, LINE_START);
  616. return line;
  617. }
  618. /* handler for parser DWORD_DATA state */
  619. static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos)
  620. {
  621. WCHAR *line = pos;
  622. parser->data = malloc(sizeof(DWORD));
  623. if (!convert_hex_to_dword(line, parser->data))
  624. goto invalid;
  625. parser->data_size = sizeof(DWORD);
  626. set_state(parser, SET_VALUE);
  627. return line;
  628. invalid:
  629. free_parser_data(parser);
  630. set_state(parser, LINE_START);
  631. return line;
  632. }
  633. /* handler for parser HEX_DATA state */
  634. static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos)
  635. {
  636. WCHAR *line = pos;
  637. if (!*line)
  638. goto set_value;
  639. if (!convert_hex_csv_to_hex(parser, &line))
  640. goto invalid;
  641. if (parser->backslash)
  642. {
  643. set_state(parser, EOL_BACKSLASH);
  644. return line;
  645. }
  646. prepare_hex_string_data(parser);
  647. set_value:
  648. set_state(parser, SET_VALUE);
  649. return line;
  650. invalid:
  651. free_parser_data(parser);
  652. set_state(parser, LINE_START);
  653. return line;
  654. }
  655. /* handler for parser EOL_BACKSLASH state */
  656. static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos)
  657. {
  658. WCHAR *p = pos;
  659. while (*p == ' ' || *p == '\t') p++;
  660. if (*p && *p != ';') goto invalid;
  661. set_state(parser, HEX_MULTILINE);
  662. return pos;
  663. invalid:
  664. free_parser_data(parser);
  665. set_state(parser, LINE_START);
  666. return p;
  667. }
  668. /* handler for parser HEX_MULTILINE state */
  669. static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos)
  670. {
  671. WCHAR *line;
  672. if (!(line = get_line(parser->file)))
  673. {
  674. prepare_hex_string_data(parser);
  675. set_state(parser, SET_VALUE);
  676. return pos;
  677. }
  678. while (*line == ' ' || *line == '\t') line++;
  679. if (!*line || *line == ';') return line;
  680. if (!iswxdigit(*line)) goto invalid;
  681. set_state(parser, HEX_DATA);
  682. return line;
  683. invalid:
  684. free_parser_data(parser);
  685. set_state(parser, LINE_START);
  686. return line;
  687. }
  688. /* handler for parser UNKNOWN_DATA state */
  689. static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos)
  690. {
  691. FIXME("Unknown registry data type [0x%x]\n", parser->data_type);
  692. set_state(parser, LINE_START);
  693. return pos;
  694. }
  695. /* handler for parser SET_VALUE state */
  696. static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
  697. {
  698. RegSetValueExW(parser->hkey, parser->value_name, 0, parser->data_type,
  699. parser->data, parser->data_size);
  700. free_parser_data(parser);
  701. if (parser->reg_version == REG_VERSION_31)
  702. set_state(parser, PARSE_WIN31_LINE);
  703. else
  704. set_state(parser, LINE_START);
  705. return pos;
  706. }
  707. #define REG_VAL_BUF_SIZE 4096
  708. static WCHAR *get_lineA(FILE *fp)
  709. {
  710. static WCHAR *lineW;
  711. static size_t size;
  712. static char *buf, *next;
  713. char *line;
  714. free(lineW);
  715. if (!fp) goto cleanup;
  716. if (!size)
  717. {
  718. size = REG_VAL_BUF_SIZE;
  719. buf = malloc(size);
  720. *buf = 0;
  721. next = buf;
  722. }
  723. line = next;
  724. while (next)
  725. {
  726. char *p = strpbrk(line, "\r\n");
  727. if (!p)
  728. {
  729. size_t len, count;
  730. len = strlen(next);
  731. memmove(buf, next, len + 1);
  732. if (size - len < 3)
  733. {
  734. size *= 2;
  735. buf = realloc(buf, size);
  736. }
  737. if (!(count = fread(buf + len, 1, size - len - 1, fp)))
  738. {
  739. next = NULL;
  740. lineW = GetWideString(buf);
  741. return lineW;
  742. }
  743. buf[len + count] = 0;
  744. next = buf;
  745. line = buf;
  746. continue;
  747. }
  748. next = p + 1;
  749. if (*p == '\r' && *(p + 1) == '\n') next++;
  750. *p = 0;
  751. lineW = GetWideString(line);
  752. return lineW;
  753. }
  754. cleanup:
  755. lineW = NULL;
  756. free(buf);
  757. size = 0;
  758. return NULL;
  759. }
  760. static WCHAR *get_lineW(FILE *fp)
  761. {
  762. static size_t size;
  763. static WCHAR *buf, *next;
  764. WCHAR *line;
  765. if (!fp) goto cleanup;
  766. if (!size)
  767. {
  768. size = REG_VAL_BUF_SIZE;
  769. buf = malloc(size * sizeof(WCHAR));
  770. *buf = 0;
  771. next = buf;
  772. }
  773. line = next;
  774. while (next)
  775. {
  776. WCHAR *p = wcspbrk(line, L"\r\n");
  777. if (!p)
  778. {
  779. size_t len, count;
  780. len = lstrlenW(next);
  781. memmove(buf, next, (len + 1) * sizeof(WCHAR));
  782. if (size - len < 3)
  783. {
  784. size *= 2;
  785. buf = realloc(buf, size * sizeof(WCHAR));
  786. }
  787. if (!(count = fread(buf + len, sizeof(WCHAR), size - len - 1, fp)))
  788. {
  789. next = NULL;
  790. return buf;
  791. }
  792. buf[len + count] = 0;
  793. next = buf;
  794. line = buf;
  795. continue;
  796. }
  797. next = p + 1;
  798. if (*p == '\r' && *(p + 1) == '\n') next++;
  799. *p = 0;
  800. return line;
  801. }
  802. cleanup:
  803. free(buf);
  804. size = 0;
  805. return NULL;
  806. }
  807. int reg_import(int argc, WCHAR *argvW[])
  808. {
  809. WCHAR *filename, *pos;
  810. FILE *fp;
  811. BYTE s[2];
  812. struct parser parser;
  813. if (argc > 4) goto invalid;
  814. if (argc == 4)
  815. {
  816. WCHAR *str = argvW[3];
  817. if (*str != '/' && *str != '-')
  818. goto invalid;
  819. str++;
  820. if (lstrcmpiW(str, L"reg:32") && lstrcmpiW(str, L"reg:64"))
  821. goto invalid;
  822. }
  823. filename = argvW[2];
  824. fp = _wfopen(filename, L"rb");
  825. if (!fp)
  826. {
  827. output_message(STRING_FILE_NOT_FOUND, filename);
  828. return 1;
  829. }
  830. if (fread(s, sizeof(WCHAR), 1, fp) != 1)
  831. goto error;
  832. parser.is_unicode = (s[0] == 0xff && s[1] == 0xfe);
  833. get_line = parser.is_unicode ? get_lineW : get_lineA;
  834. parser.file = fp;
  835. parser.two_wchars[0] = s[0];
  836. parser.two_wchars[1] = s[1];
  837. parser.reg_version = -1;
  838. parser.hkey = NULL;
  839. parser.key_name = NULL;
  840. parser.value_name = NULL;
  841. parser.parse_type = 0;
  842. parser.data_type = 0;
  843. parser.data = NULL;
  844. parser.data_size = 0;
  845. parser.backslash = FALSE;
  846. parser.state = HEADER;
  847. pos = parser.two_wchars;
  848. /* parser main loop */
  849. while (pos)
  850. pos = (parser_funcs[parser.state])(&parser, pos);
  851. if (parser.reg_version == REG_VERSION_INVALID)
  852. goto error;
  853. free(parser.value_name);
  854. close_key(&parser);
  855. fclose(fp);
  856. return 0;
  857. error:
  858. fclose(fp);
  859. return 1;
  860. invalid:
  861. output_message(STRING_INVALID_SYNTAX);
  862. output_message(STRING_FUNC_HELP, wcsupr(argvW[1]));
  863. return 1;
  864. }