Francois Gouget : regedit: Fix exporting of REG_EXPAND_SZ and other 'weird' strings.

Alexandre Julliard julliard at winehq.org
Fri Nov 21 06:54:43 CST 2008


Module: wine
Branch: master
Commit: a81bb704df0438870d9cc0f024ed8777831eba1e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a81bb704df0438870d9cc0f024ed8777831eba1e

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Thu Nov 20 20:43:25 2008 +0100

regedit: Fix exporting of REG_EXPAND_SZ and other 'weird' strings.

REG_EXPAND_SZ must be exported as hexadecimal to preserve the string type.
0-byte strings and those missing a trailing '\0' or with odd sizes must 
be saved as hexadecimal too so they are restored as is.
Move the binary-value export code to the new REGPROC_export_binary() 
function.

---

 programs/regedit/regproc.c |  171 ++++++++++++++++++++++++--------------------
 1 files changed, 92 insertions(+), 79 deletions(-)

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index 957f87c..509a36f 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -925,6 +925,75 @@ static void REGPROC_export_string(WCHAR **line_buf, DWORD *line_buf_size, DWORD
     *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 i, hex_pos, data_pos, column;
+    const WCHAR *hex_prefix;
+    const WCHAR hex[] = {'h','e','x',':',0};
+    WCHAR hex_buf[17];
+    const WCHAR format[] = {'%','0','2','x',0};
+    const WCHAR comma[] = {',',0};
+    const WCHAR concat[] = {'\\','\n',' ',' ',0};
+    DWORD concat_prefix, concat_len;
+    const WCHAR newline[] = {'\n',0};
+    CHAR* value_multibyte = NULL;
+
+    if (type == REG_BINARY) {
+        hex_prefix = hex;
+    } else {
+        const WCHAR hex_format[] = {'h','e','x','(','%','u',')',':',0};
+        hex_prefix = hex_buf;
+        wsprintfW(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) then we may overestimate
+     *   the needed number of lines by one. But that's ok.
+     * - The trailing linefeed takes the place of a comma so
+     *   it's accounted for already.
+     */
+    *line_len += *line_len / (REG_FILE_HEX_LINE_LEN - concat_prefix) * concat_len;
+    REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len);
+    lstrcpyW(*line_buf + hex_pos, hex_prefix);
+    column = data_pos; /* no line wrap yet */
+    i = 0;
+    while (1)
+    {
+        wsprintfW(*line_buf + data_pos, format, (unsigned int)value[i]);
+        data_pos += 2;
+        if (++i == value_size)
+            break;
+
+        lstrcpyW(*line_buf + data_pos, comma);
+        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);
+    if (value_multibyte)
+        HeapFree(GetProcessHeap(), 0, value_multibyte);
+}
+
 /******************************************************************************
  * Writes the given line to a file, in multi-byte or wide characters
  */
@@ -1030,22 +1099,30 @@ static void export_hkey(FILE *file, HKEY key,
 
             switch (value_type) {
             case REG_SZ:
-            case REG_EXPAND_SZ:
             {
-                const WCHAR start[] = {'"',0};
-                const WCHAR end[] = {'"','\n',0};
-                DWORD len;
+                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[] = {'"','\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;
+                    len = lstrlenW(start);
+                    REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + len);
+                    lstrcpyW(*line_buf + line_len, start);
+                    line_len += len;
 
-                if (val_size1)
-                    REGPROC_export_string(line_buf, line_buf_size, &line_len, (WCHAR*)*val_buf, val_size1 / sizeof(WCHAR) - 1);
+                    /* At this point we know wstr is '\0'-terminated
+                     * so we can substract 1 from the size
+                     */
+                    REGPROC_export_string(line_buf, line_buf_size, &line_len, wstr, val_size1 / sizeof(WCHAR) - 1);
 
-                REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end));
-                lstrcpyW(*line_buf + line_len, end);
+                    REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end));
+                    lstrcpyW(*line_buf + line_len, end);
+                }
                 break;
             }
 
@@ -1071,75 +1148,11 @@ static void export_hkey(FILE *file, HKEY key,
                 HeapFree(GetProcessHeap(), 0, value_nameA);
             }
                 /* falls through */
+            case REG_EXPAND_SZ:
             case REG_MULTI_SZ:
                 /* falls through */
-            case REG_BINARY: {
-                    DWORD i1;
-                    const WCHAR *hex_prefix;
-                    WCHAR buf[20];
-                    int hex_pos, data_pos, column;
-                    const WCHAR hex[] = {'h','e','x',':',0};
-                    const WCHAR format[] = {'%','0','2','x',0};
-                    const WCHAR comma[] = {',',0};
-                    const WCHAR concat[] = {'\\','\n',' ',' ',0};
-                    int concat_prefix, concat_len;
-                    const WCHAR newline[] = {'\n',0};
-                    BYTE* val_buf1 = *val_buf;
-                    DWORD val_buf1_size = val_size1;
-
-                    if (value_type == REG_BINARY) {
-                        hex_prefix = hex;
-                    } else {
-                        const WCHAR hex_format[] = {'h','e','x','(','%','d',')',':',0};
-                        hex_prefix = buf;
-                        wsprintfW(buf, hex_format, value_type);
-                        if(value_type == REG_MULTI_SZ && !unicode)
-                            val_buf1 = (BYTE*)GetMultiByteStringN((WCHAR*)*val_buf, val_size1 / sizeof(WCHAR), &val_buf1_size);
-                    }
-
-                    concat_len=lstrlenW(concat);
-                    concat_prefix=2;
-
-                    hex_pos = line_len;
-                    line_len += lstrlenW(hex_prefix);
-                    data_pos = line_len;
-                    line_len += val_buf1_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) then we may overestimate
-                     *   the needed number of lines by one. But that's ok.
-                     * - The trailing linefeed takes the place of a comma so
-                     *   it's accounted for already.
-                     */
-                    line_len += line_len / (REG_FILE_HEX_LINE_LEN - concat_prefix) * concat_len;
-                    REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len);
-                    lstrcpyW(*line_buf + hex_pos, hex_prefix);
-                    column = data_pos; /* no line wrap yet */
-                    i1 = 0;
-                    while (1)
-                    {
-                        wsprintfW(*line_buf + data_pos, format, (unsigned int)(val_buf1)[i1]);
-                        data_pos += 2;
-                        if (++i1 == val_buf1_size)
-                            break;
-
-                        lstrcpyW(*line_buf + data_pos, comma);
-                        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);
-                    if(value_type == REG_MULTI_SZ && !unicode)
-                        HeapFree(GetProcessHeap(), 0, val_buf1);
-                    break;
-                }
+            case REG_BINARY:
+                REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode);
             }
             REGPROC_write_line(file, *line_buf, unicode);
         }




More information about the wine-cvs mailing list