mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 20:53:35 +00:00
reg: Import hex data via the state machine.
Signed-off-by: Hugh McMaster <hugh.mcmaster@outlook.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f1874c1667
commit
32d53681b9
|
@ -42,6 +42,21 @@ static WCHAR *GetWideString(const char *strA)
|
||||||
return NULL;
|
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 *);
|
static WCHAR *(*get_line)(FILE *);
|
||||||
|
|
||||||
/* parser definitions */
|
/* parser definitions */
|
||||||
|
@ -57,6 +72,9 @@ enum parser_state
|
||||||
DATA_TYPE, /* parsing the registry data type */
|
DATA_TYPE, /* parsing the registry data type */
|
||||||
STRING_DATA, /* parsing REG_SZ data */
|
STRING_DATA, /* parsing REG_SZ data */
|
||||||
DWORD_DATA, /* parsing DWORD 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 */
|
||||||
SET_VALUE, /* adding a value to the registry */
|
SET_VALUE, /* adding a value to the registry */
|
||||||
NB_PARSER_STATES
|
NB_PARSER_STATES
|
||||||
};
|
};
|
||||||
|
@ -74,6 +92,7 @@ struct parser
|
||||||
DWORD data_type; /* data type */
|
DWORD data_type; /* data type */
|
||||||
void *data; /* value data */
|
void *data; /* value data */
|
||||||
DWORD data_size; /* size of the data (in bytes) */
|
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 */
|
enum parser_state state; /* current parser state */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,6 +109,9 @@ static WCHAR *data_start_state(struct parser *parser, WCHAR *pos);
|
||||||
static WCHAR *data_type_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 *string_data_state(struct parser *parser, WCHAR *pos);
|
||||||
static WCHAR *dword_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 *set_value_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] =
|
static const parser_state_func parser_funcs[NB_PARSER_STATES] =
|
||||||
|
@ -104,6 +126,9 @@ static const parser_state_func parser_funcs[NB_PARSER_STATES] =
|
||||||
data_type_state, /* DATA_TYPE */
|
data_type_state, /* DATA_TYPE */
|
||||||
string_data_state, /* STRING_DATA */
|
string_data_state, /* STRING_DATA */
|
||||||
dword_data_state, /* DWORD_DATA */
|
dword_data_state, /* DWORD_DATA */
|
||||||
|
hex_data_state, /* HEX_DATA */
|
||||||
|
eol_backslash_state, /* EOL_BACKSLASH */
|
||||||
|
hex_multiline_state, /* HEX_MULTILINE */
|
||||||
set_value_state, /* SET_VALUE */
|
set_value_state, /* SET_VALUE */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,6 +171,66 @@ error:
|
||||||
return FALSE;
|
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
|
* Parses the data type of the registry value being imported and modifies
|
||||||
* the input parameter to skip the string representation of the data type.
|
* the input parameter to skip the string representation of the data type.
|
||||||
|
@ -305,13 +390,34 @@ static LONG open_key(struct parser *parser, WCHAR *path)
|
||||||
|
|
||||||
static void free_parser_data(struct parser *parser)
|
static void free_parser_data(struct parser *parser)
|
||||||
{
|
{
|
||||||
if (parser->parse_type == REG_DWORD)
|
if (parser->parse_type == REG_DWORD || parser->parse_type == REG_BINARY)
|
||||||
heap_free(parser->data);
|
heap_free(parser->data);
|
||||||
|
|
||||||
parser->data = NULL;
|
parser->data = NULL;
|
||||||
parser->data_size = 0;
|
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)
|
||||||
|
{
|
||||||
|
BYTE *data = parser->data;
|
||||||
|
|
||||||
|
if (data[parser->data_size - 1] != 0)
|
||||||
|
{
|
||||||
|
data[parser->data_size] = 0;
|
||||||
|
parser->data_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser->is_unicode)
|
||||||
|
{
|
||||||
|
parser->data = GetWideStringN(parser->data, parser->data_size, &parser->data_size);
|
||||||
|
parser->data_size *= sizeof(WCHAR);
|
||||||
|
heap_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum reg_versions {
|
enum reg_versions {
|
||||||
REG_VERSION_31,
|
REG_VERSION_31,
|
||||||
REG_VERSION_40,
|
REG_VERSION_40,
|
||||||
|
@ -566,6 +672,8 @@ static WCHAR *data_type_state(struct parser *parser, WCHAR *pos)
|
||||||
set_state(parser, DWORD_DATA);
|
set_state(parser, DWORD_DATA);
|
||||||
break;
|
break;
|
||||||
case REG_BINARY: /* all hex data types, including undefined */
|
case REG_BINARY: /* all hex data types, including undefined */
|
||||||
|
set_state(parser, HEX_DATA);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
set_state(parser, LINE_START);
|
set_state(parser, LINE_START);
|
||||||
}
|
}
|
||||||
|
@ -618,6 +726,74 @@ invalid:
|
||||||
return line;
|
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 SET_VALUE state */
|
/* handler for parser SET_VALUE state */
|
||||||
static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
|
static WCHAR *set_value_state(struct parser *parser, WCHAR *pos)
|
||||||
{
|
{
|
||||||
|
@ -779,6 +955,7 @@ int reg_import(const WCHAR *filename)
|
||||||
parser.data_type = 0;
|
parser.data_type = 0;
|
||||||
parser.data = NULL;
|
parser.data = NULL;
|
||||||
parser.data_size = 0;
|
parser.data_size = 0;
|
||||||
|
parser.backslash = FALSE;
|
||||||
parser.state = HEADER;
|
parser.state = HEADER;
|
||||||
|
|
||||||
pos = parser.two_wchars;
|
pos = parser.two_wchars;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue