[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