regedit: Export REG_SZ data via the export_data() function.
Signed-off-by: Hugh McMaster <hugh.mcmaster@outlook.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6515837ada
commit
37b5607ff6
|
@ -1069,206 +1069,6 @@ cleanup:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Checks whether the buffer has enough room for the string or required size.
|
||||
* Resizes the buffer if necessary.
|
||||
*
|
||||
* Parameters:
|
||||
* buffer - pointer to a buffer for string
|
||||
* len - current length of the buffer in characters.
|
||||
* required_len - length of the string to place to the buffer in characters.
|
||||
* The length does not include the terminating null character.
|
||||
*/
|
||||
static void REGPROC_resize_char_buffer(WCHAR **buffer, DWORD *len, DWORD required_len)
|
||||
{
|
||||
required_len++;
|
||||
if (required_len > *len) {
|
||||
*len = required_len;
|
||||
if (!*buffer)
|
||||
*buffer = HeapAlloc(GetProcessHeap(), 0, *len * sizeof(**buffer));
|
||||
else
|
||||
*buffer = HeapReAlloc(GetProcessHeap(), 0, *buffer, *len * sizeof(**buffer));
|
||||
CHECK_ENOUGH_MEMORY(*buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Prints string str to file
|
||||
*/
|
||||
static void REGPROC_export_string(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, WCHAR *str, DWORD str_len)
|
||||
{
|
||||
DWORD i, pos;
|
||||
DWORD extra = 0;
|
||||
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + 10);
|
||||
|
||||
/* escaping characters */
|
||||
pos = *line_len;
|
||||
for (i = 0; i < str_len; i++) {
|
||||
WCHAR c = str[i];
|
||||
switch (c) {
|
||||
case '\n':
|
||||
extra++;
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra);
|
||||
(*line_buf)[pos++] = '\\';
|
||||
(*line_buf)[pos++] = 'n';
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
extra++;
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra);
|
||||
(*line_buf)[pos++] = '\\';
|
||||
(*line_buf)[pos++] = 'r';
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
case '"':
|
||||
extra++;
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra);
|
||||
(*line_buf)[pos++] = '\\';
|
||||
/* Fall through */
|
||||
|
||||
default:
|
||||
(*line_buf)[pos++] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*line_buf)[pos] = '\0';
|
||||
*line_len = pos;
|
||||
}
|
||||
|
||||
static void REGPROC_export_binary(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, DWORD type, BYTE *value, DWORD value_size, BOOL unicode)
|
||||
{
|
||||
DWORD hex_pos, data_pos;
|
||||
const WCHAR *hex_prefix;
|
||||
const WCHAR hex[] = {'h','e','x',':',0};
|
||||
WCHAR hex_buf[17];
|
||||
const WCHAR concat[] = {'\\','\r','\n',' ',' ',0};
|
||||
DWORD concat_prefix, concat_len;
|
||||
const WCHAR newline[] = {'\r','\n',0};
|
||||
CHAR* value_multibyte = NULL;
|
||||
|
||||
if (type == REG_BINARY) {
|
||||
hex_prefix = hex;
|
||||
} else {
|
||||
const WCHAR hex_format[] = {'h','e','x','(','%','x',')',':',0};
|
||||
hex_prefix = hex_buf;
|
||||
sprintfW(hex_buf, hex_format, type);
|
||||
if ((type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ) && !unicode)
|
||||
{
|
||||
value_multibyte = GetMultiByteStringN((WCHAR*)value, value_size / sizeof(WCHAR), &value_size);
|
||||
value = (BYTE*)value_multibyte;
|
||||
}
|
||||
}
|
||||
|
||||
concat_len = lstrlenW(concat);
|
||||
concat_prefix = 2;
|
||||
|
||||
hex_pos = *line_len;
|
||||
*line_len += lstrlenW(hex_prefix);
|
||||
data_pos = *line_len;
|
||||
*line_len += value_size * 3;
|
||||
/* - The 2 spaces that concat places at the start of the
|
||||
* line effectively reduce the space available for data.
|
||||
* - If the value name and hex prefix are very long
|
||||
* ( > REG_FILE_HEX_LINE_LEN) or *line_len divides
|
||||
* without a remainder then we may overestimate
|
||||
* the needed number of lines by one. But that's ok.
|
||||
* - The trailing '\r' takes the place of a comma so
|
||||
* we only need to add 1 for the trailing '\n'
|
||||
*/
|
||||
*line_len += *line_len / (REG_FILE_HEX_LINE_LEN - concat_prefix) * concat_len + 1;
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len);
|
||||
lstrcpyW(*line_buf + hex_pos, hex_prefix);
|
||||
if (value_size)
|
||||
{
|
||||
const WCHAR format[] = {'%','0','2','x',0};
|
||||
DWORD i, column;
|
||||
|
||||
column = data_pos; /* no line wrap yet */
|
||||
i = 0;
|
||||
while (1)
|
||||
{
|
||||
sprintfW(*line_buf + data_pos, format, (unsigned int)value[i]);
|
||||
data_pos += 2;
|
||||
if (++i == value_size)
|
||||
break;
|
||||
|
||||
(*line_buf)[data_pos++] = ',';
|
||||
column += 3;
|
||||
|
||||
/* wrap the line */
|
||||
if (column >= REG_FILE_HEX_LINE_LEN) {
|
||||
lstrcpyW(*line_buf + data_pos, concat);
|
||||
data_pos += concat_len;
|
||||
column = concat_prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
lstrcpyW(*line_buf + data_pos, newline);
|
||||
HeapFree(GetProcessHeap(), 0, value_multibyte);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Writes the given line to a file, in multi-byte or wide characters
|
||||
*/
|
||||
static void REGPROC_write_line(FILE *file, const WCHAR* str, BOOL unicode)
|
||||
{
|
||||
if(unicode)
|
||||
{
|
||||
fwrite(str, sizeof(WCHAR), lstrlenW(str), file);
|
||||
} else
|
||||
{
|
||||
char* strA = GetMultiByteString(str);
|
||||
fputs(strA, file);
|
||||
HeapFree(GetProcessHeap(), 0, strA);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Writes contents of the registry key to the specified file stream.
|
||||
*
|
||||
* Parameters:
|
||||
* file - writable file stream to export registry branch to.
|
||||
* key - registry branch to export.
|
||||
* reg_key_name_buf - name of the key with registry class.
|
||||
* Is resized if necessary.
|
||||
* reg_key_name_size - length of the buffer for the registry class in characters.
|
||||
* val_name_buf - buffer for storing value name.
|
||||
* Is resized if necessary.
|
||||
* val_name_size - length of the buffer for storing value names in characters.
|
||||
* val_buf - buffer for storing values while extracting.
|
||||
* Is resized if necessary.
|
||||
* val_size - size of the buffer for storing values in bytes.
|
||||
*/
|
||||
static void export_hkey(FILE *file, DWORD value_type, BYTE **val_buf, DWORD *val_size,
|
||||
WCHAR **line_buf, DWORD *line_buf_size, BOOL unicode)
|
||||
{
|
||||
DWORD line_len = 0;
|
||||
DWORD val_size1 = *val_size;
|
||||
WCHAR *wstr = (WCHAR *)*val_buf;
|
||||
|
||||
if (val_size1 < sizeof(WCHAR) || val_size1 % sizeof(WCHAR) ||
|
||||
wstr[val_size1 / sizeof(WCHAR) - 1]) {
|
||||
REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode);
|
||||
} else {
|
||||
const WCHAR start[] = {'"',0};
|
||||
const WCHAR end[] = {'"','\r','\n',0};
|
||||
DWORD len;
|
||||
|
||||
len = lstrlenW(start);
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + len);
|
||||
lstrcpyW(*line_buf + line_len, start);
|
||||
line_len += len;
|
||||
|
||||
REGPROC_export_string(line_buf, line_buf_size, &line_len, wstr, lstrlenW(wstr));
|
||||
|
||||
REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end));
|
||||
lstrcpyW(*line_buf + line_len, end);
|
||||
}
|
||||
REGPROC_write_line(file, *line_buf, unicode);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Reads contents of the specified file into the registry.
|
||||
*/
|
||||
|
@ -1340,6 +1140,18 @@ void delete_registry_key(WCHAR *reg_key_name)
|
|||
RegDeleteTreeW(key_class, key_name);
|
||||
}
|
||||
|
||||
static void REGPROC_write_line(FILE *fp, const WCHAR *str, BOOL unicode)
|
||||
{
|
||||
if (unicode)
|
||||
fwrite(str, sizeof(WCHAR), lstrlenW(str), fp);
|
||||
else
|
||||
{
|
||||
char *strA = GetMultiByteString(str);
|
||||
fputs(strA, fp);
|
||||
HeapFree(GetProcessHeap(), 0, strA);
|
||||
}
|
||||
}
|
||||
|
||||
static WCHAR *REGPROC_escape_string(WCHAR *str, size_t str_len, size_t *line_len)
|
||||
{
|
||||
size_t i, escape_count, pos;
|
||||
|
@ -1414,6 +1226,19 @@ static size_t export_value_name(FILE *fp, WCHAR *name, size_t len, BOOL unicode)
|
|||
return line_len;
|
||||
}
|
||||
|
||||
static void export_string_data(WCHAR **buf, WCHAR *data, size_t size)
|
||||
{
|
||||
size_t len, line_len;
|
||||
WCHAR *str;
|
||||
static const WCHAR fmt[] = {'"','%','s','"',0};
|
||||
|
||||
len = size / sizeof(WCHAR) - 1;
|
||||
str = REGPROC_escape_string(data, len, &line_len);
|
||||
*buf = resize_buffer(NULL, (line_len + 3) * sizeof(WCHAR));
|
||||
sprintfW(*buf, fmt, str);
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
|
||||
static void export_dword_data(WCHAR **buf, DWORD *data)
|
||||
{
|
||||
static const WCHAR fmt[] = {'d','w','o','r','d',':','%','0','8','x',0};
|
||||
|
@ -1486,6 +1311,9 @@ static void export_data(FILE *fp, DWORD type, size_t line_len, void *data, size_
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case REG_SZ:
|
||||
export_string_data(&buf, data, size);
|
||||
break;
|
||||
case REG_DWORD:
|
||||
export_dword_data(&buf, data);
|
||||
break;
|
||||
|
@ -1529,8 +1357,6 @@ static void export_key_name(FILE *fp, WCHAR *name, BOOL unicode)
|
|||
|
||||
static int export_registry_data(FILE *fp, HKEY key, WCHAR *path, BOOL unicode)
|
||||
{
|
||||
WCHAR *line_buf;
|
||||
DWORD line_buf_size = KEY_MAX_LEN + REG_VAL_BUF_SIZE;
|
||||
LONG rc;
|
||||
DWORD max_value_len = 256, value_len;
|
||||
DWORD max_data_bytes = 2048, data_size;
|
||||
|
@ -1540,9 +1366,6 @@ static int export_registry_data(FILE *fp, HKEY key, WCHAR *path, BOOL unicode)
|
|||
BYTE *data;
|
||||
HKEY subkey;
|
||||
|
||||
line_buf = HeapAlloc(GetProcessHeap(), 0, line_buf_size * sizeof(WCHAR));
|
||||
CHECK_ENOUGH_MEMORY(line_buf);
|
||||
|
||||
export_key_name(fp, path, unicode);
|
||||
|
||||
value_name = resize_buffer(NULL, max_value_len * sizeof(WCHAR));
|
||||
|
@ -1557,10 +1380,7 @@ static int export_registry_data(FILE *fp, HKEY key, WCHAR *path, BOOL unicode)
|
|||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
size_t line_len = export_value_name(fp, value_name, value_len, unicode);
|
||||
if (type != REG_SZ)
|
||||
export_data(fp, type, line_len, data, data_size, unicode);
|
||||
else
|
||||
export_hkey(fp, type, &data, &data_size, &line_buf, &line_buf_size, unicode);
|
||||
i++;
|
||||
}
|
||||
else if (rc == ERROR_MORE_DATA)
|
||||
|
@ -1581,7 +1401,6 @@ static int export_registry_data(FILE *fp, HKEY key, WCHAR *path, BOOL unicode)
|
|||
|
||||
HeapFree(GetProcessHeap(), 0, data);
|
||||
HeapFree(GetProcessHeap(), 0, value_name);
|
||||
HeapFree(GetProcessHeap(), 0, line_buf);
|
||||
|
||||
subkey_name = resize_buffer(NULL, MAX_SUBKEY_LEN * sizeof(WCHAR));
|
||||
|
||||
|
|
Loading…
Reference in New Issue