Author: akhaldi Date: Sun Sep 24 11:33:04 2017 New Revision: 75958
URL: http://svn.reactos.org/svn/reactos?rev=75958&view=rev Log: [REG] Sync with Wine Staging 2.16. CORE-13762
39e0e81 reg: Null-terminate incomplete REG_EXPAND_SZ and REG_MULTI_SZ Unicode data. 82fc4c8 reg: Close any open registry keys before starting the key deletion process. 5de883c reg: Use the correct return codes during the import operation. 56e58e4 reg: Delete registry keys via the state machine. d90f2a5 reg: Delete registry values via the state machine. db98cc4 reg: Handle unknown registry data types in the state machine. 32d5368 reg: Import hex data via the state machine. f1874c1 reg: Import REG_DWORD data via the state machine. 038f1c6 reg: Parse data types and import REG_SZ data via the state machine. 0565934 reg: Parse key names and value names in the state machine. 3e87a70 reg: Introduce a partial state machine for importing Windows 3.1 registry data. aa386af reg: Add initial support for the import operation. f2fbbec reg: Rename reg.h to resource.h. c6c95a0 reg: Compile with msvcrt. 8c253c4 reg: Make some variables 'static const'. 337e0f4 reg: Avoid an uninitialized variable warning. 8abec73 reg: Dynamically allocate memory for the value name buffer when deleting all registry values in a specified key. e7ea838 reg: Use a helper function to resize a memory buffer. a1bc33a reg: Use a helper function to free allocated memory. a6e28cc reg: Use a helper function to allocate memory and die on failure. 90da210 reg: Account for sizeof(WCHAR) when resizing the value name buffer during the query operation. fb22f6c reg: Avoid using RegQueryInfoKey() to enumerate subkeys and values in the query operation.
Added: trunk/reactos/base/applications/cmdutils/reg/import.c (with props) trunk/reactos/base/applications/cmdutils/reg/resource.h (with props) Modified: trunk/reactos/base/applications/cmdutils/reg/CMakeLists.txt trunk/reactos/base/applications/cmdutils/reg/lang/bg-BG.rc trunk/reactos/base/applications/cmdutils/reg/lang/cs-CZ.rc trunk/reactos/base/applications/cmdutils/reg/lang/da-DK.rc trunk/reactos/base/applications/cmdutils/reg/lang/de-DE.rc trunk/reactos/base/applications/cmdutils/reg/lang/en-US.rc trunk/reactos/base/applications/cmdutils/reg/lang/es-ES.rc trunk/reactos/base/applications/cmdutils/reg/lang/fr-FR.rc trunk/reactos/base/applications/cmdutils/reg/lang/it-IT.rc trunk/reactos/base/applications/cmdutils/reg/lang/ja-JP.rc trunk/reactos/base/applications/cmdutils/reg/lang/ko-KR.rc trunk/reactos/base/applications/cmdutils/reg/lang/lt-LT.rc trunk/reactos/base/applications/cmdutils/reg/lang/nl-NL.rc trunk/reactos/base/applications/cmdutils/reg/lang/no-NO.rc trunk/reactos/base/applications/cmdutils/reg/lang/pl-PL.rc trunk/reactos/base/applications/cmdutils/reg/lang/pt-PT.rc trunk/reactos/base/applications/cmdutils/reg/lang/ro-RO.rc trunk/reactos/base/applications/cmdutils/reg/lang/ru-RU.rc trunk/reactos/base/applications/cmdutils/reg/lang/sl-SI.rc trunk/reactos/base/applications/cmdutils/reg/lang/sq-AL.rc trunk/reactos/base/applications/cmdutils/reg/lang/sv-SE.rc trunk/reactos/base/applications/cmdutils/reg/lang/tr-TR.rc trunk/reactos/base/applications/cmdutils/reg/lang/uk-UA.rc trunk/reactos/base/applications/cmdutils/reg/lang/zh-CN.rc trunk/reactos/base/applications/cmdutils/reg/lang/zh-TW.rc trunk/reactos/base/applications/cmdutils/reg/reg.c trunk/reactos/base/applications/cmdutils/reg/reg.h trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/base/applications/cmdutils/reg/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/CMakeLists.txt [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -2,7 +2,7 @@ remove_definitions(-D_WIN32_WINNT=0x502) add_definitions(-D_WIN32_WINNT=0x600)
-add_executable(reg reg.c reg.rc) +add_executable(reg import.c reg.c reg.rc) set_module_type(reg win32cui UNICODE) target_link_libraries(reg wine) add_importlibs(reg advapi32 advapi32_vista user32 msvcrt kernel32 ntdll)
Added: trunk/reactos/base/applications/cmdutils/reg/import.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/import.c (added) +++ trunk/reactos/base/applications/cmdutils/reg/import.c [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -0,0 +1,1042 @@ +/* + * Copyright 2017 Hugh McMaster + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windef.h> +#include <winbase.h> +#include <winreg.h> +#include <stdio.h> + +#include <wine/unicode.h> +#include <wine/debug.h> + +#include "reg.h" + +WINE_DEFAULT_DEBUG_CHANNEL(reg); + +static WCHAR *GetWideString(const char *strA) +{ + if (strA) + { + WCHAR *strW; + int len = MultiByteToWideChar(CP_ACP, 0, strA, -1, NULL, 0); + + strW = heap_xalloc(len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, strA, -1, strW, len); + return strW; + } + return NULL; +} + +static WCHAR *GetWideStringN(const char *strA, int size, DWORD *len) +{ + if (strA) + { + WCHAR *strW; + *len = MultiByteToWideChar(CP_ACP, 0, strA, size, NULL, 0); + + strW = heap_xalloc(*len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, strA, size, strW, *len); + return strW; + } + *len = 0; + return NULL; +} + +static WCHAR *(*get_line)(FILE *); + +/* parser definitions */ +enum parser_state +{ + HEADER, /* parsing the registry file version header */ + PARSE_WIN31_LINE, /* parsing a Windows 3.1 registry line */ + LINE_START, /* at the beginning of a registry line */ + KEY_NAME, /* parsing a key name */ + DELETE_KEY, /* deleting a registry key */ + DEFAULT_VALUE_NAME, /* parsing a default value name */ + QUOTED_VALUE_NAME, /* parsing a double-quoted value name */ + DATA_START, /* preparing for data parsing operations */ + DELETE_VALUE, /* deleting a registry value */ + DATA_TYPE, /* parsing the registry data type */ + STRING_DATA, /* parsing REG_SZ data */ + DWORD_DATA, /* parsing DWORD data */ + HEX_DATA, /* parsing REG_BINARY, REG_NONE, REG_EXPAND_SZ or REG_MULTI_SZ data */ + EOL_BACKSLASH, /* preparing to parse multiple lines of hex data */ + HEX_MULTILINE, /* parsing multiple lines of hex data */ + UNKNOWN_DATA, /* parsing an unhandled or invalid data type */ + SET_VALUE, /* adding a value to the registry */ + NB_PARSER_STATES +}; + +struct parser +{ + FILE *file; /* pointer to a registry file */ + WCHAR two_wchars[2]; /* first two characters from the encoding check */ + BOOL is_unicode; /* parsing Unicode or ASCII data */ + short int reg_version; /* registry file version */ + HKEY hkey; /* current registry key */ + WCHAR *key_name; /* current key name */ + WCHAR *value_name; /* value name */ + DWORD parse_type; /* generic data type for parsing */ + DWORD data_type; /* data type */ + void *data; /* value data */ + DWORD data_size; /* size of the data (in bytes) */ + BOOL backslash; /* TRUE if the current line contains a backslash */ + enum parser_state state; /* current parser state */ +}; + +typedef WCHAR *(*parser_state_func)(struct parser *parser, WCHAR *pos); + +/* parser state machine functions */ +static WCHAR *header_state(struct parser *parser, WCHAR *pos); +static WCHAR *parse_win31_line_state(struct parser *parser, WCHAR *pos); +static WCHAR *line_start_state(struct parser *parser, WCHAR *pos); +static WCHAR *key_name_state(struct parser *parser, WCHAR *pos); +static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos); +static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos); +static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos); +static WCHAR *data_start_state(struct parser *parser, WCHAR *pos); +static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos); +static WCHAR *data_type_state(struct parser *parser, WCHAR *pos); +static WCHAR *string_data_state(struct parser *parser, WCHAR *pos); +static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos); +static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos); +static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos); +static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos); +static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos); +static WCHAR *set_value_state(struct parser *parser, WCHAR *pos); + +static const parser_state_func parser_funcs[NB_PARSER_STATES] = +{ + header_state, /* HEADER */ + parse_win31_line_state, /* PARSE_WIN31_LINE */ + line_start_state, /* LINE_START */ + key_name_state, /* KEY_NAME */ + delete_key_state, /* DELETE_KEY */ + default_value_name_state, /* DEFAULT_VALUE_NAME */ + quoted_value_name_state, /* QUOTED_VALUE_NAME */ + data_start_state, /* DATA_START */ + delete_value_state, /* DELETE_VALUE */ + data_type_state, /* DATA_TYPE */ + string_data_state, /* STRING_DATA */ + dword_data_state, /* DWORD_DATA */ + hex_data_state, /* HEX_DATA */ + eol_backslash_state, /* EOL_BACKSLASH */ + hex_multiline_state, /* HEX_MULTILINE */ + unknown_data_state, /* UNKNOWN_DATA */ + set_value_state, /* SET_VALUE */ +}; + +/* set the new parser state and return the previous one */ +static inline enum parser_state set_state(struct parser *parser, enum parser_state state) +{ + enum parser_state ret = parser->state; + parser->state = state; + return ret; +} + +/****************************************************************************** + * Converts a hex representation of a DWORD into a DWORD. + */ +static BOOL convert_hex_to_dword(WCHAR *str, DWORD *dw) +{ + WCHAR *p, *end; + int count = 0; + + while (*str == ' ' || *str == '\t') str++; + if (!*str) goto error; + + p = str; + while (isxdigitW(*p)) + { + count++; + p++; + } + if (count > 8) goto error; + + end = p; + while (*p == ' ' || *p == '\t') p++; + if (*p && *p != ';') goto error; + + *end = 0; + *dw = strtoulW(str, &end, 16); + return TRUE; + +error: + return FALSE; +} + +/****************************************************************************** + * Converts comma-separated hex data into a binary string and modifies + * the input parameter to skip the concatenating backslash, if found. + * + * Returns TRUE or FALSE to indicate whether parsing was successful. + */ +static BOOL convert_hex_csv_to_hex(struct parser *parser, WCHAR **str) +{ + size_t size; + BYTE *d; + WCHAR *s; + + parser->backslash = FALSE; + + /* The worst case is 1 digit + 1 comma per byte */ + size = ((lstrlenW(*str) + 1) / 2) + parser->data_size; + parser->data = heap_xrealloc(parser->data, size); + + s = *str; + d = (BYTE *)parser->data + parser->data_size; + + while (*s) + { + WCHAR *end; + unsigned long wc; + + wc = strtoulW(s, &end, 16); + if (wc > 0xff) return FALSE; + + if (s == end && wc == 0) + { + while (*end == ' ' || *end == '\t') end++; + if (*end == '\') + { + parser->backslash = TRUE; + *str = end + 1; + return TRUE; + } + else if (*end == ';') + return TRUE; + return FALSE; + } + + *d++ = wc; + parser->data_size++; + + if (*end && *end != ',') + { + while (*end == ' ' || *end == '\t') end++; + if (*end && *end != ';') return FALSE; + return TRUE; + } + + if (*end) end++; + s = end; + } + + return TRUE; +} + +/****************************************************************************** + * Parses the data type of the registry value being imported and modifies + * the input parameter to skip the string representation of the data type. + * + * Returns TRUE or FALSE to indicate whether a data type was found. + */ +static BOOL parse_data_type(struct parser *parser, WCHAR **line) +{ + struct data_type { const WCHAR *tag; int len; int type; int parse_type; }; + + static const WCHAR quote[] = {'"'}; + static const WCHAR hex[] = {'h','e','x',':'}; + static const WCHAR dword[] = {'d','w','o','r','d',':'}; + static const WCHAR hexp[] = {'h','e','x','('}; + + static const struct data_type data_types[] = { + /* tag len type parse type */ + { quote, 1, REG_SZ, REG_SZ }, + { hex, 4, REG_BINARY, REG_BINARY }, + { dword, 6, REG_DWORD, REG_DWORD }, + { hexp, 4, -1, REG_BINARY }, /* REG_NONE, REG_EXPAND_SZ, REG_MULTI_SZ */ + { NULL, 0, 0, 0 } + }; + + const struct data_type *ptr; + + for (ptr = data_types; ptr->tag; ptr++) + { + if (strncmpW(ptr->tag, *line, ptr->len)) + continue; + + parser->parse_type = ptr->parse_type; + parser->data_type = ptr->parse_type; + *line += ptr->len; + + if (ptr->type == -1) + { + WCHAR *end; + DWORD val; + + if (!**line || tolowerW((*line)[1]) == 'x') + return FALSE; + + /* "hex(xx):" is special */ + val = wcstoul(*line, &end, 16); + if (*end != ')' || *(end + 1) != ':' || (val == ~0u && errno == ERANGE)) + return FALSE; + + parser->data_type = val; + *line = end + 2; + } + return TRUE; + } + return FALSE; +} + +/****************************************************************************** + * Replaces escape sequences with their character equivalents and + * null-terminates the string on the first non-escaped double quote. + * + * Assigns a pointer to the remaining unparsed data in the line. + * Returns TRUE or FALSE to indicate whether a closing double quote was found. + */ +static BOOL unescape_string(WCHAR *str, WCHAR **unparsed) +{ + int str_idx = 0; /* current character under analysis */ + int val_idx = 0; /* the last character of the unescaped string */ + int len = lstrlenW(str); + BOOL ret; + + for (str_idx = 0; str_idx < len; str_idx++, val_idx++) + { + if (str[str_idx] == '\') + { + str_idx++; + switch (str[str_idx]) + { + case 'n': + str[val_idx] = '\n'; + break; + case 'r': + str[val_idx] = '\r'; + break; + case '0': + str[val_idx] = '\0'; + break; + case '\': + case '"': + str[val_idx] = str[str_idx]; + break; + default: + if (!str[str_idx]) return FALSE; + output_message(STRING_ESCAPE_SEQUENCE, str[str_idx]); + str[val_idx] = str[str_idx]; + break; + } + } + else if (str[str_idx] == '"') + break; + else + str[val_idx] = str[str_idx]; + } + + ret = (str[str_idx] == '"'); + *unparsed = str + str_idx + 1; + str[val_idx] = '\0'; + return ret; +} + +static HKEY parse_key_name(WCHAR *key_name, WCHAR **key_path) +{ + if (!key_name) return 0; + + *key_path = strchrW(key_name, '\'); + if (*key_path) (*key_path)++; + + return path_get_rootkey(key_name); +} + +static void close_key(struct parser *parser) +{ + if (parser->hkey) + { + heap_free(parser->key_name); + parser->key_name = NULL; + + RegCloseKey(parser->hkey); + parser->hkey = NULL; + } +} + +static LONG open_key(struct parser *parser, WCHAR *path) +{ + HKEY key_class; + WCHAR *key_path; + LONG res; + + close_key(parser); + + /* Get the registry class */ + if (!path || !(key_class = parse_key_name(path, &key_path))) + return ERROR_INVALID_PARAMETER; + + res = RegCreateKeyExW(key_class, key_path, 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, NULL, &parser->hkey, NULL); + + if (res == ERROR_SUCCESS) + { + parser->key_name = heap_xalloc((lstrlenW(path) + 1) * sizeof(WCHAR)); + lstrcpyW(parser->key_name, path); + } + else + parser->hkey = NULL; + + return res; +} + +static void free_parser_data(struct parser *parser) +{ + if (parser->parse_type == REG_DWORD || parser->parse_type == REG_BINARY) + heap_free(parser->data); + + parser->data = NULL; + parser->data_size = 0; +} + +static void prepare_hex_string_data(struct parser *parser) +{ + if (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ) + { + if (parser->is_unicode) + { + WCHAR *data = parser->data; + DWORD len = parser->data_size / sizeof(WCHAR); + + if (data[len - 1] != 0) + { + data[len] = 0; + parser->data_size += sizeof(WCHAR); + } + } + else + { + BYTE *data = parser->data; + + if (data[parser->data_size - 1] != 0) + { + data[parser->data_size] = 0; + parser->data_size++; + } + + parser->data = GetWideStringN(parser->data, parser->data_size, &parser->data_size); + parser->data_size *= sizeof(WCHAR); + heap_free(data); + } + } +} + +enum reg_versions { + REG_VERSION_31, + REG_VERSION_40, + REG_VERSION_50, + REG_VERSION_FUZZY, + REG_VERSION_INVALID +}; + +static enum reg_versions parse_file_header(const WCHAR *s) +{ + static const WCHAR header_31[] = {'R','E','G','E','D','I','T',0}; + static const WCHAR header_40[] = {'R','E','G','E','D','I','T','4',0}; + static const WCHAR header_50[] = {'W','i','n','d','o','w','s',' ', + 'R','e','g','i','s','t','r','y',' ','E','d','i','t','o','r',' ', + 'V','e','r','s','i','o','n',' ','5','.','0','0',0}; + + while (*s == ' ' || *s == '\t') s++; + + if (!strcmpW(s, header_31)) + return REG_VERSION_31; + + if (!strcmpW(s, header_40)) + return REG_VERSION_40; + + if (!strcmpW(s, header_50)) + return REG_VERSION_50; + + /* The Windows version accepts registry file headers beginning with "REGEDIT" and ending + * with other characters, as long as "REGEDIT" appears at the start of the line. For example, + * "REGEDIT 4", "REGEDIT9" and "REGEDIT4FOO" are all treated as valid file headers. + * In all such cases, however, the contents of the registry file are not imported. + */ + if (!strncmpW(s, header_31, 7)) /* "REGEDIT" without NUL */ + return REG_VERSION_FUZZY; + + return REG_VERSION_INVALID; +} + +/* handler for parser HEADER state */ +static WCHAR *header_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line, *header; + + if (!(line = get_line(parser->file))) + return NULL; + + if (!parser->is_unicode) + { + header = heap_xalloc((lstrlenW(line) + 3) * sizeof(WCHAR)); + header[0] = parser->two_wchars[0]; + header[1] = parser->two_wchars[1]; + lstrcpyW(header + 2, line); + parser->reg_version = parse_file_header(header); + heap_free(header); + } + else parser->reg_version = parse_file_header(line); + + switch (parser->reg_version) + { + case REG_VERSION_31: + set_state(parser, PARSE_WIN31_LINE); + break; + case REG_VERSION_40: + case REG_VERSION_50: + set_state(parser, LINE_START); + break; + default: + get_line(NULL); /* Reset static variables */ + return NULL; + } + + return line; +} + +/* handler for parser PARSE_WIN31_LINE state */ +static WCHAR *parse_win31_line_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line, *value; + static WCHAR hkcr[] = {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T'}; + unsigned int key_end = 0; + + if (!(line = get_line(parser->file))) + return NULL; + + if (strncmpW(line, hkcr, ARRAY_SIZE(hkcr))) + return line; + + /* get key name */ + while (line[key_end] && !isspaceW(line[key_end])) key_end++; + + value = line + key_end; + while (*value == ' ' || *value == '\t') value++; + + if (*value == '=') value++; + if (*value == ' ') value++; /* at most one space is skipped */ + + line[key_end] = 0; + + if (open_key(parser, line) != ERROR_SUCCESS) + { + output_message(STRING_OPEN_KEY_FAILED, line); + return line; + } + + parser->value_name = NULL; + parser->data_type = REG_SZ; + parser->data = value; + parser->data_size = (lstrlenW(value) + 1) * sizeof(WCHAR); + + set_state(parser, SET_VALUE); + return value; +} + +/* handler for parser LINE_START state */ +static WCHAR *line_start_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line, *p; + + if (!(line = get_line(parser->file))) + return NULL; + + for (p = line; *p; p++) + { + switch (*p) + { + case '[': + set_state(parser, KEY_NAME); + return p + 1; + case '@': + set_state(parser, DEFAULT_VALUE_NAME); + return p; + case '"': + set_state(parser, QUOTED_VALUE_NAME); + return p + 1; + case ' ': + case '\t': + break; + default: + return p; + } + } + + return p; +} + +/* handler for parser KEY_NAME state */ +static WCHAR *key_name_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *p = pos, *key_end; + + if (*p == ' ' || *p == '\t' || !(key_end = strrchrW(p, ']'))) + goto done; + + *key_end = 0; + + if (*p == '-') + { + set_state(parser, DELETE_KEY); + return p + 1; + } + else if (open_key(parser, p) != ERROR_SUCCESS) + output_message(STRING_OPEN_KEY_FAILED, p); + +done: + set_state(parser, LINE_START); + return p; +} + +/* handler for parser DELETE_KEY state */ +static WCHAR *delete_key_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *p = pos; + + close_key(parser); + + if (*p == 'H' || *p == 'h') + { + HKEY root; + WCHAR *path; + + root = parse_key_name(p, &path); + + if (root && path && *path) + RegDeleteTreeW(root, path); + } + + set_state(parser, LINE_START); + return p; +} + +/* handler for parser DEFAULT_VALUE_NAME state */ +static WCHAR *default_value_name_state(struct parser *parser, WCHAR *pos) +{ + heap_free(parser->value_name); + parser->value_name = NULL; + + set_state(parser, DATA_START); + return pos + 1; +} + +/* handler for parser QUOTED_VALUE_NAME state */ +static WCHAR *quoted_value_name_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *val_name = pos, *p; + + if (parser->value_name) + { + heap_free(parser->value_name); + parser->value_name = NULL; + } + + if (!unescape_string(val_name, &p)) + goto invalid; + + /* copy the value name in case we need to parse multiple lines and the buffer is overwritten */ + parser->value_name = heap_xalloc((lstrlenW(val_name) + 1) * sizeof(WCHAR)); + lstrcpyW(parser->value_name, val_name); + + set_state(parser, DATA_START); + return p; + +invalid: + set_state(parser, LINE_START); + return val_name; +} + +/* handler for parser DATA_START state */ +static WCHAR *data_start_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *p = pos; + unsigned int len; + + while (*p == ' ' || *p == '\t') p++; + if (*p != '=') goto invalid; + p++; + while (*p == ' ' || *p == '\t') p++; + + /* trim trailing whitespace */ + len = strlenW(p); + while (len > 0 && (p[len - 1] == ' ' || p[len - 1] == '\t')) len--; + p[len] = 0; + + if (*p == '-') + set_state(parser, DELETE_VALUE); + else + set_state(parser, DATA_TYPE); + return p; + +invalid: + set_state(parser, LINE_START); + return p; +} + +/* handler for parser DELETE_VALUE state */ +static WCHAR *delete_value_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *p = pos + 1; + + while (*p == ' ' || *p == '\t') p++; + if (*p && *p != ';') goto done; + + RegDeleteValueW(parser->hkey, parser->value_name); + +done: + set_state(parser, LINE_START); + return p; +} + +/* handler for parser DATA_TYPE state */ +static WCHAR *data_type_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line = pos; + + if (!parse_data_type(parser, &line)) + { + set_state(parser, LINE_START); + return line; + } + + switch (parser->parse_type) + { + case REG_SZ: + set_state(parser, STRING_DATA); + break; + case REG_DWORD: + set_state(parser, DWORD_DATA); + break; + case REG_BINARY: /* all hex data types, including undefined */ + set_state(parser, HEX_DATA); + break; + default: + set_state(parser, UNKNOWN_DATA); + } + + return line; +} + +/* handler for parser STRING_DATA state */ +static WCHAR *string_data_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line; + + parser->data = pos; + + if (!unescape_string(parser->data, &line)) + goto invalid; + + while (*line == ' ' || *line == '\t') line++; + if (*line && *line != ';') goto invalid; + + parser->data_size = (lstrlenW(parser->data) + 1) * sizeof(WCHAR); + + set_state(parser, SET_VALUE); + return line; + +invalid: + free_parser_data(parser); + set_state(parser, LINE_START); + return line; +} + +/* handler for parser DWORD_DATA state */ +static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line = pos; + + parser->data = heap_xalloc(sizeof(DWORD)); + + if (!convert_hex_to_dword(line, parser->data)) + goto invalid; + + parser->data_size = sizeof(DWORD); + + set_state(parser, SET_VALUE); + return line; + +invalid: + free_parser_data(parser); + set_state(parser, LINE_START); + return line; +} + +/* handler for parser HEX_DATA state */ +static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line = pos; + + if (!convert_hex_csv_to_hex(parser, &line)) + goto invalid; + + if (parser->backslash) + { + set_state(parser, EOL_BACKSLASH); + return line; + } + + prepare_hex_string_data(parser); + + set_state(parser, SET_VALUE); + return line; + +invalid: + free_parser_data(parser); + set_state(parser, LINE_START); + return line; +} + +/* handler for parser EOL_BACKSLASH state */ +static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *p = pos; + + while (*p == ' ' || *p == '\t') p++; + if (*p && *p != ';') goto invalid; + + set_state(parser, HEX_MULTILINE); + return pos; + +invalid: + free_parser_data(parser); + set_state(parser, LINE_START); + return p; +} + +/* handler for parser HEX_MULTILINE state */ +static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos) +{ + WCHAR *line; + + if (!(line = get_line(parser->file))) + { + prepare_hex_string_data(parser); + set_state(parser, SET_VALUE); + return pos; + } + + while (*line == ' ' || *line == '\t') line++; + if (!*line || *line == ';') return line; + + if (!isxdigitW(*line)) goto invalid; + + set_state(parser, HEX_DATA); + return line; + +invalid: + free_parser_data(parser); + set_state(parser, LINE_START); + return line; +} + +/* handler for parser UNKNOWN_DATA state */ +static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos) +{ + FIXME("Unknown registry data type [0x%x]\n", parser->data_type); + + set_state(parser, LINE_START); + return pos; +} + +/* handler for parser SET_VALUE state */ +static WCHAR *set_value_state(struct parser *parser, WCHAR *pos) +{ + RegSetValueExW(parser->hkey, parser->value_name, 0, parser->data_type, + parser->data, parser->data_size); + + free_parser_data(parser); + + if (parser->reg_version == REG_VERSION_31) + set_state(parser, PARSE_WIN31_LINE); + else + set_state(parser, LINE_START); + + return pos; +} + +#define REG_VAL_BUF_SIZE 4096 + +static WCHAR *get_lineA(FILE *fp) +{ + static WCHAR *lineW; + static size_t size; + static char *buf, *next; + char *line; + + heap_free(lineW); + + if (!fp) goto cleanup; + + if (!size) + { + size = REG_VAL_BUF_SIZE; + buf = heap_xalloc(size); + *buf = 0; + next = buf; + } + line = next; + + while (next) + { + char *p = strpbrk(line, "\r\n"); + if (!p) + { + size_t len, count; + len = strlen(next); + memmove(buf, next, len + 1); + if (size - len < 3) + { + size *= 2; + buf = heap_xrealloc(buf, size); + } + if (!(count = fread(buf + len, 1, size - len - 1, fp))) + { + next = NULL; + lineW = GetWideString(buf); + return lineW; + } + buf[len + count] = 0; + next = buf; + line = buf; + continue; + } + next = p + 1; + if (*p == '\r' && *(p + 1) == '\n') next++; + *p = 0; + lineW = GetWideString(line); + return lineW; + } + +cleanup: + lineW = NULL; + if (size) heap_free(buf); + size = 0; + return NULL; +} + +static WCHAR *get_lineW(FILE *fp) +{ + static size_t size; + static WCHAR *buf, *next; + WCHAR *line; + + if (!fp) goto cleanup; + + if (!size) + { + size = REG_VAL_BUF_SIZE; + buf = heap_xalloc(size * sizeof(WCHAR)); + *buf = 0; + next = buf; + } + line = next; + + while (next) + { + static const WCHAR line_endings[] = {'\r','\n',0}; + WCHAR *p = strpbrkW(line, line_endings); + if (!p) + { + size_t len, count; + len = strlenW(next); + memmove(buf, next, (len + 1) * sizeof(WCHAR)); + if (size - len < 3) + { + size *= 2; + buf = heap_xrealloc(buf, size * sizeof(WCHAR)); + } + if (!(count = fread(buf + len, sizeof(WCHAR), size - len - 1, fp))) + { + next = NULL; + return buf; + } + buf[len + count] = 0; + next = buf; + line = buf; + continue; + } + next = p + 1; + if (*p == '\r' && *(p + 1) == '\n') next++; + *p = 0; + return line; + } + +cleanup: + if (size) heap_free(buf); + size = 0; + return NULL; +} + +int reg_import(const WCHAR *filename) +{ + FILE *fp; + static const WCHAR rb_mode[] = {'r','b',0}; + BYTE s[2]; + struct parser parser; + WCHAR *pos; + + fp = _wfopen(filename, rb_mode); + if (!fp) + { + output_message(STRING_FILE_NOT_FOUND, filename); + return 1; + } + + if (fread(s, sizeof(WCHAR), 1, fp) != 1) + goto error; + + parser.is_unicode = (s[0] == 0xff && s[1] == 0xfe); + get_line = parser.is_unicode ? get_lineW : get_lineA; + + parser.file = fp; + parser.two_wchars[0] = s[0]; + parser.two_wchars[1] = s[1]; + parser.reg_version = -1; + parser.hkey = NULL; + parser.key_name = NULL; + parser.value_name = NULL; + parser.parse_type = 0; + parser.data_type = 0; + parser.data = NULL; + parser.data_size = 0; + parser.backslash = FALSE; + parser.state = HEADER; + + pos = parser.two_wchars; + + /* parser main loop */ + while (pos) + pos = (parser_funcs[parser.state])(&parser, pos); + + if (parser.reg_version == REG_VERSION_INVALID) + goto error; + + heap_free(parser.value_name); + close_key(&parser); + + fclose(fp); + return 0; + +error: + fclose(fp); + return 1; +}
Propchange: trunk/reactos/base/applications/cmdutils/reg/import.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/bg-BG.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/bg-BG.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/bg-BG.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/cs-CZ.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/cs-CZ.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/cs-CZ.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -38,4 +38,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/da-DK.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/da-DK.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/da-DK.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/de-DE.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/de-DE.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/de-DE.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/en-US.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/en-US.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/en-US.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/es-ES.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/es-ES.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/es-ES.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/fr-FR.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/fr-FR.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/fr-FR.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/it-IT.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/it-IT.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/it-IT.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/ja-JP.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/ja-JP.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/ja-JP.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/ko-KR.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/ko-KR.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/ko-KR.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/lt-LT.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/lt-LT.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/lt-LT.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/nl-NL.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/nl-NL.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/nl-NL.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/no-NO.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/no-NO.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/no-NO.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/pl-PL.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/pl-PL.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/pl-PL.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/pt-PT.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/pt-PT.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/pt-PT.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/ro-RO.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/ro-RO.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/ro-RO.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -39,4 +39,8 @@ STRING_REG_HELP, "TastaÈi «REG /?» pentru mai multe informaÈii.\n" STRING_FUNC_HELP, "TastaÈi «REG %1 /?» pentru mai multe informaÈii.\n" STRING_VALUE_NOT_SET, "(valoare nealocatÄ)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/ru-RU.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/ru-RU.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/ru-RU.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "ÐведиÑе ""REG /?"" Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÑпÑавки по иÑполÑзованиÑ..\n" STRING_FUNC_HELP, "ÐведиÑе ""REG %1 /?"" Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÑпÑавки по иÑполÑзованиÑ..\n" STRING_VALUE_NOT_SET, "(знаÑение не Ñказано)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/sl-SI.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/sl-SI.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/sl-SI.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/sq-AL.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/sq-AL.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/sq-AL.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -37,4 +37,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/sv-SE.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/sv-SE.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/sv-SE.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/tr-TR.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/tr-TR.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/tr-TR.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -35,4 +35,8 @@ STRING_REG_HELP, "Yardım için ""REG /?"" yazınız.\n" STRING_FUNC_HELP, "Yardım için ""REG %1 /?"" yazınız.\n" STRING_VALUE_NOT_SET, "(DeÄer belirlenmemiÅ.)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/uk-UA.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/uk-UA.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/uk-UA.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -33,4 +33,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/zh-CN.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/zh-CN.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/zh-CN.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -35,4 +35,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/lang/zh-TW.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/lang/zh-TW.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/lang/zh-TW.rc [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -35,4 +35,8 @@ STRING_REG_HELP, "Type ""REG /?"" for help.\n" STRING_FUNC_HELP, "Type ""REG %1 /?"" for help.\n" STRING_VALUE_NOT_SET, "(value not set)" + STRING_IMPORT_USAGE, "REG IMPORT file.reg\n" + STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n" + STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n" + STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\%1!c!]\n" }
Modified: trunk/reactos/base/applications/cmdutils/reg/reg.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/reg.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/reg.c [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -25,10 +25,7 @@ #include <shlwapi.h> #include <wine/unicode.h> #include <wine/debug.h> -#include <errno.h> #include "reg.h" - -#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))
WINE_DEFAULT_DEBUG_CHANNEL(reg);
@@ -84,6 +81,40 @@ {REG_MULTI_SZ, type_multi_sz}, };
+void *heap_xalloc(size_t size) +{ + void *buf = HeapAlloc(GetProcessHeap(), 0, size); + if (!buf) + { + ERR("Out of memory!\n"); + exit(1); + } + return buf; +} + +void *heap_xrealloc(void *buf, size_t size) +{ + void *new_buf; + + if (buf) + new_buf = HeapReAlloc(GetProcessHeap(), 0, buf, size); + else + new_buf = HeapAlloc(GetProcessHeap(), 0, size); + + if (!new_buf) + { + ERR("Out of memory!\n"); + exit(1); + } + + return new_buf; +} + +BOOL heap_free(void *buf) +{ + return HeapFree(GetProcessHeap(), 0, buf); +} + static void output_writeconsole(const WCHAR *str, DWORD wlen) { DWORD count, ret; @@ -99,12 +130,11 @@ * one in that case. */ len = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, NULL, 0, NULL, NULL); - msgA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); - if (!msgA) return; + msgA = heap_xalloc(len);
WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, msgA, len, NULL, NULL); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE); - HeapFree(GetProcessHeap(), 0, msgA); + heap_free(msgA); } }
@@ -125,7 +155,7 @@ LocalFree(str); }
-static void __cdecl output_message(unsigned int id, ...) +void __cdecl output_message(unsigned int id, ...) { WCHAR fmt[1024]; __ms_va_list va_args; @@ -188,7 +218,7 @@ (input_path[length] == 0 || input_path[length] == '\')); }
-static HKEY path_get_rootkey(const WCHAR *path) +HKEY path_get_rootkey(const WCHAR *path) { DWORD i;
@@ -246,7 +276,7 @@ case REG_EXPAND_SZ: { *reg_count = (lstrlenW(data) + 1) * sizeof(WCHAR); - out_data = HeapAlloc(GetProcessHeap(),0,*reg_count); + out_data = heap_xalloc(*reg_count); lstrcpyW((LPWSTR)out_data,data); break; } @@ -256,13 +286,13 @@ { LPWSTR rest; unsigned long val; - val = strtoulW(data, &rest, (tolowerW(data[1]) == 'x') ? 16 : 10); - if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE) || val > ~0u) { + val = wcstoul(data, &rest, (tolowerW(data[1]) == 'x') ? 16 : 10); + if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE)) { output_message(STRING_MISSING_INTEGER); break; } *reg_count = sizeof(DWORD); - out_data = HeapAlloc(GetProcessHeap(),0,*reg_count); + out_data = heap_xalloc(*reg_count); ((LPDWORD)out_data)[0] = val; break; } @@ -271,7 +301,7 @@ BYTE hex0, hex1; int i = 0, destByteIndex = 0, datalen = lstrlenW(data); *reg_count = ((datalen + datalen % 2) / 2) * sizeof(BYTE); - out_data = HeapAlloc(GetProcessHeap(), 0, *reg_count); + out_data = heap_xalloc(*reg_count); if(datalen % 2) { hex1 = hexchar_to_byte(data[i++]); @@ -290,7 +320,7 @@ break; no_hex_data: /* cleanup, print error */ - HeapFree(GetProcessHeap(), 0, out_data); + heap_free(out_data); output_message(STRING_MISSING_HEXDATA); out_data = NULL; break; @@ -298,7 +328,7 @@ case REG_MULTI_SZ: { int i, destindex, len = strlenW(data); - WCHAR *buffer = HeapAlloc(GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR)); + WCHAR *buffer = heap_xalloc((len + 2) * sizeof(WCHAR));
for (i = 0, destindex = 0; i < len; i++, destindex++) { @@ -314,7 +344,7 @@
if (destindex && !buffer[destindex - 1] && (!buffer[destindex] || destindex == 1)) { - HeapFree(GetProcessHeap(), 0, buffer); + heap_free(buffer); output_message(STRING_INVALID_STRING); return NULL; } @@ -402,7 +432,7 @@ }
RegSetValueExW(key, value_name, 0, reg_type, reg_data, reg_count); - HeapFree(GetProcessHeap(),0,reg_data); + heap_free(reg_data); }
RegCloseKey(key); @@ -454,40 +484,35 @@
if (value_all) { - LPWSTR szValue; - DWORD maxValue; - DWORD count; + DWORD max_value_len = 256, value_len; + WCHAR *value_name; LONG rc;
- rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, &maxValue, NULL, NULL, NULL); - if (rc != ERROR_SUCCESS) - { - RegCloseKey(key); - output_message(STRING_GENERAL_FAILURE); - return 1; - } - maxValue++; - szValue = HeapAlloc(GetProcessHeap(),0,maxValue*sizeof(WCHAR)); + value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
while (1) { - count = maxValue; - rc = RegEnumValueW(key, 0, szValue, &count, NULL, NULL, NULL, NULL); + value_len = max_value_len; + rc = RegEnumValueW(key, 0, value_name, &value_len, NULL, NULL, NULL, NULL); if (rc == ERROR_SUCCESS) { - rc = RegDeleteValueW(key, szValue); + rc = RegDeleteValueW(key, value_name); if (rc != ERROR_SUCCESS) { - HeapFree(GetProcessHeap(), 0, szValue); + heap_free(value_name); RegCloseKey(key); output_message(STRING_VALUEALL_FAILED, key_name); return 1; } } + else if (rc == ERROR_MORE_DATA) + { + max_value_len *= 2; + value_name = heap_xrealloc(value_name, max_value_len * sizeof(WCHAR)); + } else break; } - HeapFree(GetProcessHeap(), 0, szValue); + heap_free(value_name); } else if (value_name || value_empty) { @@ -513,16 +538,16 @@ { case REG_SZ: case REG_EXPAND_SZ: - buffer = HeapAlloc(GetProcessHeap(), 0, size_bytes); + buffer = heap_xalloc(size_bytes); strcpyW(buffer, (WCHAR *)src); break; case REG_NONE: case REG_BINARY: { WCHAR *ptr; - WCHAR fmt[] = {'%','0','2','X',0}; - - buffer = HeapAlloc(GetProcessHeap(), 0, (size_bytes * 2 + 1) * sizeof(WCHAR)); + static const WCHAR fmt[] = {'%','0','2','X',0}; + + buffer = heap_xalloc((size_bytes * 2 + 1) * sizeof(WCHAR)); ptr = buffer; for (i = 0; i < size_bytes; i++) ptr += sprintfW(ptr, fmt, src[i]); @@ -533,9 +558,9 @@ case REG_DWORD_BIG_ENDIAN: { const int zero_x_dword = 10; - WCHAR fmt[] = {'0','x','%','x',0}; - - buffer = HeapAlloc(GetProcessHeap(), 0, (zero_x_dword + 1) * sizeof(WCHAR)); + static const WCHAR fmt[] = {'0','x','%','x',0}; + + buffer = heap_xalloc((zero_x_dword + 1) * sizeof(WCHAR)); sprintfW(buffer, fmt, *(DWORD *)src); break; } @@ -548,13 +573,13 @@
if (size_bytes <= two_wchars) { - buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)); + buffer = heap_xalloc(sizeof(WCHAR)); *buffer = 0; return buffer; }
tmp_size = size_bytes - two_wchars; /* exclude both null terminators */ - buffer = HeapAlloc(GetProcessHeap(), 0, tmp_size * 2 + sizeof(WCHAR)); + buffer = heap_xalloc(tmp_size * 2 + sizeof(WCHAR)); len = tmp_size / sizeof(WCHAR);
for (i = 0, destindex = 0; i < len; i++, destindex++) @@ -588,10 +613,10 @@
static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD data_size) { - WCHAR fmt[] = {' ',' ',' ',' ','%','1',0}; + static const WCHAR fmt[] = {' ',' ',' ',' ','%','1',0}; + static const WCHAR newlineW[] = {'\n',0}; WCHAR defval[32]; WCHAR *reg_data; - WCHAR newlineW[] = {'\n',0};
if (value_name && value_name[0]) output_string(fmt, value_name); @@ -606,7 +631,7 @@ { reg_data = reg_data_to_wchar(type, data, data_size); output_string(fmt, reg_data); - HeapFree(GetProcessHeap(), 0, reg_data); + heap_free(reg_data); } else { @@ -619,25 +644,23 @@ static WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len) { WCHAR *subkey_path; - WCHAR fmt[] = {'%','s','\','%','s',0}; - - subkey_path = HeapAlloc(GetProcessHeap(), 0, (path_len + subkey_len + 2) * sizeof(WCHAR)); - if (!subkey_path) - { - ERR("Failed to allocate memory for subkey_path\n"); - return NULL; - } + static const WCHAR fmt[] = {'%','s','\','%','s',0}; + + subkey_path = heap_xalloc((path_len + subkey_len + 2) * sizeof(WCHAR)); sprintfW(subkey_path, fmt, path, subkey_name); + return subkey_path; }
static unsigned int num_values_found = 0;
+#define MAX_SUBKEY_LEN 257 + static int query_value(HKEY key, WCHAR *value_name, WCHAR *path, BOOL recurse) { LONG rc; - DWORD num_subkeys, max_subkey_len, subkey_len; - DWORD max_data_bytes, data_size; + DWORD max_data_bytes = 2048, data_size; + DWORD subkey_len; DWORD type, path_len, i; BYTE *data; WCHAR fmt[] = {'%','1','\n',0}; @@ -645,23 +668,20 @@ WCHAR *subkey_name, *subkey_path; HKEY subkey;
- rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, &num_subkeys, &max_subkey_len, - NULL, NULL, NULL, &max_data_bytes, NULL, NULL); - if (rc) - { - ERR("RegQueryInfoKey failed: %d\n", rc); - return 1; - } - - data = HeapAlloc(GetProcessHeap(), 0, max_data_bytes); - if (!data) - { - ERR("Failed to allocate memory for data\n"); - return 1; - } - - data_size = max_data_bytes; - rc = RegQueryValueExW(key, value_name, NULL, &type, data, &data_size); + data = heap_xalloc(max_data_bytes); + + for (;;) + { + data_size = max_data_bytes; + rc = RegQueryValueExW(key, value_name, NULL, &type, data, &data_size); + if (rc == ERROR_MORE_DATA) + { + max_data_bytes = data_size; + data = heap_xrealloc(data, max_data_bytes); + } + else break; + } + if (rc == ERROR_SUCCESS) { output_string(fmt, path); @@ -670,7 +690,7 @@ num_values_found++; }
- HeapFree(GetProcessHeap(), 0, data); + heap_free(data);
if (!recurse) { @@ -687,19 +707,14 @@ return 0; }
- max_subkey_len++; - subkey_name = HeapAlloc(GetProcessHeap(), 0, max_subkey_len * sizeof(WCHAR)); - if (!subkey_name) - { - ERR("Failed to allocate memory for subkey_name\n"); - return 1; - } + subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
path_len = strlenW(path);
- for (i = 0; i < num_subkeys; i++) - { - subkey_len = max_subkey_len; + i = 0; + for (;;) + { + subkey_len = MAX_SUBKEY_LEN; rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL); if (rc == ERROR_SUCCESS) { @@ -709,20 +724,22 @@ query_value(subkey, value_name, subkey_path, recurse); RegCloseKey(subkey); } - HeapFree(GetProcessHeap(), 0, subkey_path); - } - } - - HeapFree(GetProcessHeap(), 0, subkey_name); + heap_free(subkey_path); + i++; + } + else break; + } + + heap_free(subkey_name); return 0; }
static int query_all(HKEY key, WCHAR *path, BOOL recurse) { LONG rc; - DWORD num_subkeys, max_subkey_len, subkey_len; - DWORD num_values, max_value_len, value_len; - DWORD max_data_bytes, data_size; + DWORD max_value_len = 256, value_len; + DWORD max_data_bytes = 2048, data_size; + DWORD subkey_len; DWORD i, type, path_len; WCHAR fmt[] = {'%','1','\n',0}; WCHAR fmt_path[] = {'%','1','\','%','2','\n',0}; @@ -731,60 +748,52 @@ BYTE *data; HKEY subkey;
- rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, &num_subkeys, &max_subkey_len, NULL, - &num_values, &max_value_len, &max_data_bytes, NULL, NULL); - if (rc) - { - ERR("RegQueryInfoKey failed: %d\n", rc); - return 1; - } - output_string(fmt, path);
- max_value_len++; - value_name = HeapAlloc(GetProcessHeap(), 0, max_value_len * sizeof(WCHAR)); - if (!value_name) - { - ERR("Failed to allocate memory for value_name\n"); - return 1; - } - - data = HeapAlloc(GetProcessHeap(), 0, max_data_bytes); - if (!data) - { - HeapFree(GetProcessHeap(), 0, value_name); - ERR("Failed to allocate memory for data\n"); - return 1; - } - - for (i = 0; i < num_values; i++) + value_name = heap_xalloc(max_value_len * sizeof(WCHAR)); + data = heap_xalloc(max_data_bytes); + + i = 0; + for (;;) { value_len = max_value_len; data_size = max_data_bytes; rc = RegEnumValueW(key, i, value_name, &value_len, NULL, &type, data, &data_size); if (rc == ERROR_SUCCESS) + { output_value(value_name, type, data, data_size); - } - - HeapFree(GetProcessHeap(), 0, data); - HeapFree(GetProcessHeap(), 0, value_name); - - if (num_values || recurse) + i++; + } + else if (rc == ERROR_MORE_DATA) + { + if (data_size > max_data_bytes) + { + max_data_bytes = data_size; + data = heap_xrealloc(data, max_data_bytes); + } + else + { + max_value_len *= 2; + value_name = heap_xrealloc(value_name, max_value_len * sizeof(WCHAR)); + } + } + else break; + } + + heap_free(data); + heap_free(value_name); + + if (i || recurse) output_string(newlineW);
- max_subkey_len++; - subkey_name = HeapAlloc(GetProcessHeap(), 0, max_subkey_len * sizeof(WCHAR)); - if (!subkey_name) - { - ERR("Failed to allocate memory for subkey_name\n"); - return 1; - } + subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
path_len = strlenW(path);
- for (i = 0; i < num_subkeys; i++) - { - subkey_len = max_subkey_len; + i = 0; + for (;;) + { + subkey_len = MAX_SUBKEY_LEN; rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL); if (rc == ERROR_SUCCESS) { @@ -796,15 +805,17 @@ query_all(subkey, subkey_path, recurse); RegCloseKey(subkey); } - HeapFree(GetProcessHeap(), 0, subkey_path); + heap_free(subkey_path); } else output_string(fmt_path, path, subkey_name); - } - } - - HeapFree(GetProcessHeap(), 0, subkey_name); - - if (num_subkeys && !recurse) + i++; + } + else break; + } + + heap_free(subkey_name); + + if (i && !recurse) output_string(newlineW);
return 0; @@ -855,13 +866,13 @@
if (!path) { - long_key = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + long_key = heap_xalloc((len + 1) * sizeof(WCHAR)); strcpyW(long_key, root_rels[i].long_name); return long_key; }
len += strlenW(path) + 1; /* add one for the backslash */ - long_key = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + long_key = heap_xalloc((len + 1) * sizeof(WCHAR)); sprintfW(long_key, fmt, root_rels[i].long_name, path); return long_key; } @@ -900,32 +911,38 @@ enum operations { REG_ADD, REG_DELETE, + REG_IMPORT, REG_QUERY, REG_INVALID };
-static const WCHAR addW[] = {'a','d','d',0}; -static const WCHAR deleteW[] = {'d','e','l','e','t','e',0}; -static const WCHAR queryW[] = {'q','u','e','r','y',0}; - static enum operations get_operation(const WCHAR *str, int *op_help) { - if (!lstrcmpiW(str, addW)) - { - *op_help = STRING_ADD_USAGE; - return REG_ADD; - } - - if (!lstrcmpiW(str, deleteW)) - { - *op_help = STRING_DELETE_USAGE; - return REG_DELETE; - } - - if (!lstrcmpiW(str, queryW)) - { - *op_help = STRING_QUERY_USAGE; - return REG_QUERY; + struct op_info { const WCHAR *op; int id; int help_id; }; + + static const WCHAR add[] = {'a','d','d',0}; + static const WCHAR delete[] = {'d','e','l','e','t','e',0}; + static const WCHAR import[] = {'i','m','p','o','r','t',0}; + static const WCHAR query[] = {'q','u','e','r','y',0}; + + static const struct op_info op_array[] = + { + { add, REG_ADD, STRING_ADD_USAGE }, + { delete, REG_DELETE, STRING_DELETE_USAGE }, + { import, REG_IMPORT, STRING_IMPORT_USAGE }, + { query, REG_QUERY, STRING_QUERY_USAGE }, + { NULL, -1, 0 } + }; + + const struct op_info *ptr; + + for (ptr = op_array; ptr->op; ptr++) + { + if (!lstrcmpiW(str, ptr->op)) + { + *op_help = ptr->help_id; + return ptr->id; + } }
return REG_INVALID; @@ -966,7 +983,7 @@ if (argc > 2) show_op_help = is_help_switch(argvW[2]);
- if (argc == 2 || (show_op_help && argc > 3)) + if (argc == 2 || ((show_op_help || op == REG_IMPORT) && argc > 3)) { output_message(STRING_INVALID_SYNTAX); output_message(STRING_FUNC_HELP, struprW(argvW[1])); @@ -977,6 +994,9 @@ output_message(op_help); return 0; } + + if (op == REG_IMPORT) + return reg_import(argvW[2]);
if (!parse_registry_key(argvW[2], &root, &path, &key_name)) return 1; @@ -1061,7 +1081,7 @@ ret = reg_add(root, path, value_name, value_empty, type, separator, data, force); else if (op == REG_DELETE) ret = reg_delete(root, path, key_name, value_name, value_empty, value_all, force); - else if (op == REG_QUERY) + else ret = reg_query(root, path, key_name, value_name, value_empty, recurse); return ret; }
Modified: trunk/reactos/base/applications/cmdutils/reg/reg.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/reg.h [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/reg/reg.h [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -1,7 +1,5 @@ /* - * REG.EXE - Wine-compatible reg program. - * - * Copyright 2008 Andrew Riedi + * Copyright 2017 Hugh McMaster * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,39 +16,21 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#pragma once +#ifndef __REG_H__ +#define __REG_H__
-//#include <windef.h> +#include "resource.h"
-/* Translation IDs. */ -#define STRING_USAGE 101 -#define STRING_ADD_USAGE 102 -#define STRING_DELETE_USAGE 103 -#define STRING_QUERY_USAGE 104 -#define STRING_SUCCESS 105 -#define STRING_INVALID_KEY 106 -#define STRING_INVALID_CMDLINE 107 -#define STRING_NO_REMOTE 108 -#define STRING_CANNOT_FIND 109 -#define STRING_UNSUPPORTED_TYPE 110 -#define STRING_MISSING_INTEGER 111 -#define STRING_MISSING_HEXDATA 112 -#define STRING_UNHANDLED_TYPE 113 -#define STRING_OVERWRITE_VALUE 114 -#define STRING_YESNO 115 -#define STRING_YES 116 -#define STRING_NO 117 -#define STRING_CANCELLED 118 -#define STRING_DEFAULT_VALUE 119 -#define STRING_DELETE_VALUE 120 -#define STRING_DELETE_VALUEALL 121 -#define STRING_DELETE_SUBKEY 122 -#define STRING_INVALID_STRING 123 -#define STRING_VALUEALL_FAILED 124 -#define STRING_GENERAL_FAILURE 125 -#define STRING_MATCHES_FOUND 126 -#define STRING_INVALID_SYNTAX 127 -#define STRING_INVALID_OPTION 128 -#define STRING_REG_HELP 129 -#define STRING_FUNC_HELP 130 -#define STRING_VALUE_NOT_SET 131 +#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A)) + +/* reg.c */ +void *heap_xalloc(size_t size); +void *heap_xrealloc(void *buf, size_t size); +BOOL heap_free(void *buf); +void __cdecl output_message(unsigned int id, ...); +HKEY path_get_rootkey(const WCHAR *path); + +/* import.c */ +int reg_import(const WCHAR *filename); + +#endif /* __REG_H__ */
Added: trunk/reactos/base/applications/cmdutils/reg/resource.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/reg/resource.h (added) +++ trunk/reactos/base/applications/cmdutils/reg/resource.h [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -0,0 +1,60 @@ +/* + * REG.EXE - Wine-compatible reg program. + * + * Copyright 2008 Andrew Riedi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +//#include <windef.h> + +/* Translation IDs. */ +#define STRING_USAGE 101 +#define STRING_ADD_USAGE 102 +#define STRING_DELETE_USAGE 103 +#define STRING_QUERY_USAGE 104 +#define STRING_SUCCESS 105 +#define STRING_INVALID_KEY 106 +#define STRING_INVALID_CMDLINE 107 +#define STRING_NO_REMOTE 108 +#define STRING_CANNOT_FIND 109 +#define STRING_UNSUPPORTED_TYPE 110 +#define STRING_MISSING_INTEGER 111 +#define STRING_MISSING_HEXDATA 112 +#define STRING_UNHANDLED_TYPE 113 +#define STRING_OVERWRITE_VALUE 114 +#define STRING_YESNO 115 +#define STRING_YES 116 +#define STRING_NO 117 +#define STRING_CANCELLED 118 +#define STRING_DEFAULT_VALUE 119 +#define STRING_DELETE_VALUE 120 +#define STRING_DELETE_VALUEALL 121 +#define STRING_DELETE_SUBKEY 122 +#define STRING_INVALID_STRING 123 +#define STRING_VALUEALL_FAILED 124 +#define STRING_GENERAL_FAILURE 125 +#define STRING_MATCHES_FOUND 126 +#define STRING_INVALID_SYNTAX 127 +#define STRING_INVALID_OPTION 128 +#define STRING_REG_HELP 129 +#define STRING_FUNC_HELP 130 +#define STRING_VALUE_NOT_SET 131 +#define STRING_IMPORT_USAGE 132 +#define STRING_FILE_NOT_FOUND 133 +#define STRING_OPEN_KEY_FAILED 134 +#define STRING_ESCAPE_SEQUENCE 135
Propchange: trunk/reactos/base/applications/cmdutils/reg/resource.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=7... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Sep 24 11:33:04 2017 @@ -227,7 +227,7 @@ ReactOS shares the following programs with Winehq.
reactos/base/applications/cmdutils/cscript # Synced to WineStaging-2.9 -reactos/base/applications/cmdutils/reg # Synced to WineStaging-2.9 +reactos/base/applications/cmdutils/reg # Synced to WineStaging-2.16 reactos/base/applications/cmdutils/schtasks # Synced to WineStaging-2.9 reactos/base/applications/cmdutils/taskkill # Synced to WineStaging-2.9 reactos/base/applications/cmdutils/wmic # Synced to WineStaging-2.9