[2/3] msi: Preserve strings with embedded nulls in the record formatting implementation.

Hans Leidekker hans at codeweavers.com
Mon Nov 5 09:29:50 CST 2012


---
 dlls/msi/format.c |  268 +++++++++++++++++++++++++++--------------------------
 1 file changed, 135 insertions(+), 133 deletions(-)

diff --git a/dlls/msi/format.c b/dlls/msi/format.c
index 15367e5..0bfd566 100644
--- a/dlls/msi/format.c
+++ b/dlls/msi/format.c
@@ -140,130 +140,147 @@ static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str)
     return &format->deformatted[str->n];
 }
 
-static LPWSTR dup_formstr(FORMAT *format, FORMSTR *str)
+static WCHAR *dup_formstr( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR val;
-    LPCWSTR data;
-
-    if (str->len == 0)
-        return NULL;
-
-    val = msi_alloc((str->len + 1) * sizeof(WCHAR));
-    data = get_formstr_data(format, str);
-    lstrcpynW(val, data, str->len + 1);
+    WCHAR *val;
 
+    if (!str->len) return NULL;
+    if ((val = msi_alloc( (str->len + 1) * sizeof(WCHAR) )))
+    {
+        memcpy( val, get_formstr_data(format, str), str->len * sizeof(WCHAR) );
+        val[str->len] = 0;
+        *ret_len = str->len;
+    }
     return val;
 }
 
-static LPWSTR deformat_index(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_index( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR val, ret;
+    WCHAR *val, *ret;
+    DWORD len;
+    int field;
 
-    val = msi_alloc((str->len + 1) * sizeof(WCHAR));
+    if (!(val = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
     lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
+    field = atoiW( val );
+    msi_free( val );
 
-    ret = msi_dup_record_field(format->record, atoiW(val));
+    if (MSI_RecordIsNull( format->record, field ) ||
+        MSI_RecordGetStringW( format->record, field, NULL, &len )) return NULL;
 
-    msi_free(val);
+    len++;
+    if (!(ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL;
+    ret[0] = 0;
+    if (MSI_RecordGetStringW( format->record, field, ret, &len ))
+    {
+        msi_free( ret );
+        return NULL;
+    }
+    *ret_len = len;
     return ret;
 }
 
-static LPWSTR deformat_property(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_property( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR val, ret;
-
-    val = msi_alloc((str->len + 1) * sizeof(WCHAR));
-    lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
+    WCHAR *prop, *ret;
+    DWORD len = 0;
+    UINT r;
 
-    ret = msi_dup_property(format->package->db, val);
+    if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
+    lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 );
 
-    msi_free(val);
+    r = msi_get_property( format->package->db, prop, NULL, &len );
+    if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
+    {
+        msi_free( prop );
+        return NULL;
+    }
+    len++;
+    if ((ret = msi_alloc( len * sizeof(WCHAR) )))
+        msi_get_property( format->package->db, prop, ret, &len );
+    msi_free( prop );
+    *ret_len = len;
     return ret;
 }
 
-static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_component( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR key, ret = NULL;
+    WCHAR *key, *ret;
     MSICOMPONENT *comp;
 
-    key = msi_alloc((str->len + 1) * sizeof(WCHAR));
+    if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
     lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
 
-    comp = msi_get_loaded_component(format->package, key);
-    if (!comp)
-        goto done;
-
+    if (!(comp = msi_get_loaded_component( format->package, key )))
+    {
+        msi_free( key );
+        return NULL;
+    }
     if (comp->Action == INSTALLSTATE_SOURCE)
         ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
     else
         ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
 
-done:
-    msi_free(key);
+    *ret_len = strlenW( ret );
+    msi_free( key );
     return ret;
 }
 
-static LPWSTR deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname)
+static WCHAR *deformat_file( FORMAT *format, FORMSTR *str, BOOL shortname, int *ret_len )
 {
-    LPWSTR key, ret = NULL;
-    MSIFILE *file;
-    DWORD size;
+    WCHAR *key, *ret = NULL;
+    const MSIFILE *file;
+    DWORD len = 0;
 
-    key = msi_alloc((str->len + 1) * sizeof(WCHAR));
+    if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
     lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
 
-    file = msi_get_loaded_file(format->package, key);
-    if (!file)
-        goto done;
-
+    if (!(file = msi_get_loaded_file( format->package, key ))) goto done;
     if (!shortname)
     {
-        ret = strdupW(file->TargetPath);
+        ret = strdupW( file->TargetPath );
+        len = strlenW( ret );
         goto done;
     }
-
-    size = GetShortPathNameW(file->TargetPath, NULL, 0);
-    if (size <= 0)
+    if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0)
     {
-        ret = strdupW(file->TargetPath);
+        ret = strdupW( file->TargetPath );
+        len = strlenW( ret );
         goto done;
     }
-
-    size++;
-    ret = msi_alloc(size * sizeof(WCHAR));
-    GetShortPathNameW(file->TargetPath, ret, size);
+    len++;
+    if ((ret = msi_alloc( len * sizeof(WCHAR) )))
+        len = GetShortPathNameW( file->TargetPath, ret, len );
 
 done:
-    msi_free(key);
+    msi_free( key );
+    *ret_len = len;
     return ret;
 }
 
-static LPWSTR deformat_environment(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_environment( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR key, ret = NULL;
-    DWORD sz;
+    WCHAR *key, *ret = NULL;
+    DWORD len;
 
-    key = msi_alloc((str->len + 1) * sizeof(WCHAR));
+    if (!(key = msi_alloc((str->len + 1) * sizeof(WCHAR)))) return NULL;
     lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
 
-    sz  = GetEnvironmentVariableW(key, NULL ,0);
-    if (sz <= 0)
-        goto done;
-
-    sz++;
-    ret = msi_alloc(sz * sizeof(WCHAR));
-    GetEnvironmentVariableW(key, ret, sz);
-
-done:
-    msi_free(key);
+    if ((len = GetEnvironmentVariableW( key, NULL, 0 )))
+    {
+        len++;
+        if ((ret = msi_alloc( len * sizeof(WCHAR) )))
+            *ret_len = GetEnvironmentVariableW( key, ret, len );
+    }
+    msi_free( key );
     return ret;
 }
 
-static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
-                               BOOL *nonprop, int *type)
+static WCHAR *deformat_literal( FORMAT *format, FORMSTR *str, BOOL *propfound,
+                                BOOL *nonprop, int *type, int *len )
 {
     LPCWSTR data = get_formstr_data(format, str);
-    LPWSTR replaced = NULL;
+    WCHAR *replaced = NULL;
     char ch = data[0];
 
     if (ch == '\\')
@@ -277,17 +294,17 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
         else
         {
             str->len = 1;
-            replaced = dup_formstr(format, str);
+            replaced = dup_formstr( format, str, len );
         }
     }
     else if (ch == '~')
     {
         if (str->len != 1)
             replaced = NULL;
-        else
+        else if ((replaced = msi_alloc( sizeof(WCHAR) )))
         {
-            replaced = msi_alloc(sizeof(WCHAR));
-            *replaced = '\0';
+            *replaced = 0;
+            *len = 0;
         }
     }
     else if (ch == '%' || ch == '#' || ch == '!' || ch == '$')
@@ -298,20 +315,20 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
         switch (ch)
         {
         case '%':
-            replaced = deformat_environment(format, str); break;
+            replaced = deformat_environment( format, str, len ); break;
         case '#':
-            replaced = deformat_file(format, str, FALSE); break;
+            replaced = deformat_file( format, str, FALSE, len ); break;
         case '!':
-            replaced = deformat_file(format, str, TRUE); break;
+            replaced = deformat_file( format, str, TRUE, len ); break;
         case '$':
-            replaced = deformat_component(format, str); break;
+            replaced = deformat_component( format, str, len ); break;
         }
 
         *type = FORMAT_LITERAL;
     }
     else
     {
-        replaced = deformat_property(format, str);
+        replaced = deformat_property( format, str, len );
         *type = FORMAT_LITERAL;
 
         if (replaced)
@@ -489,8 +506,8 @@ static int format_lex(FORMAT *format, FORMSTR **out)
     return type;
 }
 
-static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
-                               int oldsize, int type, LPWSTR replace)
+static FORMSTR *format_replace( FORMAT *format, BOOL propfound, BOOL nonprop,
+                                int oldsize, int type, WCHAR *replace, int len )
 {
     FORMSTR *ret;
     LPWSTR str, ptr;
@@ -499,10 +516,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
 
     if (replace)
     {
-        if (!*replace)
+        if (!len)
             size = 1;
         else
-            size = lstrlenW(replace);
+            size = len;
     }
 
     size -= oldsize;
@@ -526,15 +543,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
 
     if (replace)
     {
-        if (!*replace)
-        {
-            str[n] = '\0';
-            n++;
-        }
+        if (!len) str[n++] = 0;
         else
         {
-            lstrcpyW(&str[n], replace);
-            n += lstrlenW(replace);
+            memcpy( str + n, replace, len * sizeof(WCHAR) );
+            n += len;
+            str[n] = 0;
         }
     }
 
@@ -546,7 +560,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
     format->len = size - 1;
 
     /* don't reformat the NULL */
-    if (replace && !*replace)
+    if (replace && !len)
         format->n++;
 
     if (!replace)
@@ -556,7 +570,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
     if (!ret)
         return NULL;
 
-    ret->len = lstrlenW(replace);
+    ret->len = len;
     ret->type = type;
     ret->n = format->n;
     ret->propfound = propfound;
@@ -565,13 +579,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
     return ret;
 }
 
-static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
-                                  BOOL *propfound, BOOL *nonprop,
-                                  int *oldsize, int *type)
+static WCHAR *replace_stack_group( FORMAT *format, STACK *values,
+                                   BOOL *propfound, BOOL *nonprop,
+                                   int *oldsize, int *type, int *len )
 {
-    LPWSTR replaced = NULL;
-    FORMSTR *content;
-    FORMSTR *node;
+    WCHAR *replaced;
+    FORMSTR *content, *node;
     int n;
 
     *nonprop = FALSE;
@@ -626,7 +639,7 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
         *nonprop = TRUE;
     }
 
-    replaced = dup_formstr(format, content);
+    replaced = dup_formstr( format, content, len );
     *type = content->type;
     msi_free(content);
 
@@ -636,13 +649,12 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
     return replaced;
 }
 
-static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
-                                 BOOL *propfound, BOOL *nonprop,
-                                 int *oldsize, int *type)
+static WCHAR *replace_stack_prop( FORMAT *format, STACK *values,
+                                  BOOL *propfound, BOOL *nonprop,
+                                  int *oldsize, int *type, int *len )
 {
-    LPWSTR replaced = NULL;
-    FORMSTR *content;
-    FORMSTR *node;
+    WCHAR *replaced;
+    FORMSTR *content, *node;
     int n;
 
     *propfound = FALSE;
@@ -672,7 +684,7 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
 
     if (*type == FORMAT_NUMBER)
     {
-        replaced = deformat_index(format, content);
+        replaced = deformat_index( format, content, len );
         if (replaced)
             *propfound = TRUE;
         else
@@ -684,48 +696,42 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
     }
     else if (format->package)
     {
-        replaced = deformat_literal(format, content, propfound, nonprop, type);
+        replaced = deformat_literal( format, content, propfound, nonprop, type, len );
     }
     else
     {
         *nonprop = TRUE;
         content->n--;
         content->len += 2;
-        replaced = dup_formstr(format, content);
+        replaced = dup_formstr( format, content, len );
     }
-
     msi_free(content);
     return replaced;
 }
 
 static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
 {
-    LPWSTR replaced = NULL;
-    FORMSTR *beg;
-    FORMSTR *top;
-    FORMSTR *node;
-    BOOL propfound = FALSE;
-    BOOL nonprop = FALSE;
-    BOOL group = FALSE;
-    int oldsize = 0;
-    int type, n;
+    WCHAR *replaced = NULL;
+    FORMSTR *beg, *top, *node;
+    BOOL propfound = FALSE, nonprop = FALSE, group = FALSE;
+    int type, n, len = 0, oldsize = 0;
 
     node = stack_peek(values);
     type = node->type;
     n = node->n;
 
     if (type == FORMAT_LBRACK)
-        replaced = replace_stack_prop(format, values, &propfound,
-                                      &nonprop, &oldsize, &type);
+        replaced = replace_stack_prop( format, values, &propfound,
+                                       &nonprop, &oldsize, &type, &len );
     else if (type == FORMAT_LBRACE)
     {
-        replaced = replace_stack_group(format, values, &propfound,
-                                       &nonprop, &oldsize, &type);
+        replaced = replace_stack_group( format, values, &propfound,
+                                        &nonprop, &oldsize, &type, &len );
         group = TRUE;
     }
 
     format->n = n;
-    beg = format_replace(format, propfound, nonprop, oldsize, type, replaced);
+    beg = format_replace( format, propfound, nonprop, oldsize, type, replaced, len );
     if (!beg)
         return ERROR_SUCCESS;
 
@@ -865,20 +871,18 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
 UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
                         LPDWORD size )
 {
-    LPWSTR deformated;
-    LPWSTR rec;
-    DWORD len;
+    WCHAR *format, *deformated;
     UINT rc = ERROR_INVALID_PARAMETER;
+    DWORD len;
 
     TRACE("%p %p %p %p\n", package, record, buffer, size);
 
-    rec = msi_dup_record_field(record,0);
-    if (!rec)
-        rec = build_default_format(record);
+    if (!(format = msi_dup_record_field( record, 0 )))
+        format = build_default_format( record );
 
-    TRACE("(%s)\n",debugstr_w(rec));
+    TRACE("%s\n", debugstr_w(format));
 
-    deformat_string_internal(package, rec, &deformated, &len, record, NULL);
+    deformat_string_internal( package, format, &deformated, &len, record, NULL );
     if (buffer)
     {
         if (*size>len)
@@ -897,13 +901,11 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
             rc = ERROR_MORE_DATA;
         }
     }
-    else
-        rc = ERROR_SUCCESS;
+    else rc = ERROR_SUCCESS;
 
     *size = len;
-
-    msi_free(rec);
-    msi_free(deformated);
+    msi_free( format );
+    msi_free( deformated );
     return rc;
 }
 
-- 
1.7.10.4







More information about the wine-patches mailing list