Commit 57032206 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Preserve strings with embedded nulls in the record formatting implementation.

parent 8d21f998
...@@ -140,130 +140,147 @@ static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str) ...@@ -140,130 +140,147 @@ static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str)
return &format->deformatted[str->n]; 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; WCHAR *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);
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; 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); 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; return ret;
} }
static LPWSTR deformat_property(FORMAT *format, FORMSTR *str) static WCHAR *deformat_property( FORMAT *format, FORMSTR *str, int *ret_len )
{ {
LPWSTR val, ret; WCHAR *prop, *ret;
DWORD len = 0;
val = msi_alloc((str->len + 1) * sizeof(WCHAR)); UINT r;
lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
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; 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; 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); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
comp = msi_get_loaded_component(format->package, key); if (!(comp = msi_get_loaded_component( format->package, key )))
if (!comp) {
goto done; msi_free( key );
return NULL;
}
if (comp->Action == INSTALLSTATE_SOURCE) if (comp->Action == INSTALLSTATE_SOURCE)
ret = msi_resolve_source_folder( format->package, comp->Directory, NULL ); ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
else else
ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) ); ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
done: *ret_len = strlenW( ret );
msi_free(key); msi_free( key );
return ret; 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; WCHAR *key, *ret = NULL;
MSIFILE *file; const MSIFILE *file;
DWORD size; 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); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
file = msi_get_loaded_file(format->package, key); if (!(file = msi_get_loaded_file( format->package, key ))) goto done;
if (!file)
goto done;
if (!shortname) if (!shortname)
{ {
ret = strdupW(file->TargetPath); ret = strdupW( file->TargetPath );
len = strlenW( ret );
goto done; goto done;
} }
if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0)
size = GetShortPathNameW(file->TargetPath, NULL, 0);
if (size <= 0)
{ {
ret = strdupW(file->TargetPath); ret = strdupW( file->TargetPath );
len = strlenW( ret );
goto done; goto done;
} }
len++;
size++; if ((ret = msi_alloc( len * sizeof(WCHAR) )))
ret = msi_alloc(size * sizeof(WCHAR)); len = GetShortPathNameW( file->TargetPath, ret, len );
GetShortPathNameW(file->TargetPath, ret, size);
done: done:
msi_free(key); msi_free( key );
*ret_len = len;
return ret; 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; WCHAR *key, *ret = NULL;
DWORD sz; 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); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
sz = GetEnvironmentVariableW(key, NULL ,0); if ((len = GetEnvironmentVariableW( key, NULL, 0 )))
if (sz <= 0) {
goto done; len++;
if ((ret = msi_alloc( len * sizeof(WCHAR) )))
sz++; *ret_len = GetEnvironmentVariableW( key, ret, len );
ret = msi_alloc(sz * sizeof(WCHAR)); }
GetEnvironmentVariableW(key, ret, sz); msi_free( key );
done:
msi_free(key);
return ret; return ret;
} }
static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, static WCHAR *deformat_literal( FORMAT *format, FORMSTR *str, BOOL *propfound,
BOOL *nonprop, int *type) BOOL *nonprop, int *type, int *len )
{ {
LPCWSTR data = get_formstr_data(format, str); LPCWSTR data = get_formstr_data(format, str);
LPWSTR replaced = NULL; WCHAR *replaced = NULL;
char ch = data[0]; char ch = data[0];
if (ch == '\\') if (ch == '\\')
...@@ -277,17 +294,17 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, ...@@ -277,17 +294,17 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
else else
{ {
str->len = 1; str->len = 1;
replaced = dup_formstr(format, str); replaced = dup_formstr( format, str, len );
} }
} }
else if (ch == '~') else if (ch == '~')
{ {
if (str->len != 1) if (str->len != 1)
replaced = NULL; 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 == '$') else if (ch == '%' || ch == '#' || ch == '!' || ch == '$')
...@@ -298,20 +315,20 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, ...@@ -298,20 +315,20 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
switch (ch) switch (ch)
{ {
case '%': case '%':
replaced = deformat_environment(format, str); break; replaced = deformat_environment( format, str, len ); break;
case '#': case '#':
replaced = deformat_file(format, str, FALSE); break; replaced = deformat_file( format, str, FALSE, len ); break;
case '!': case '!':
replaced = deformat_file(format, str, TRUE); break; replaced = deformat_file( format, str, TRUE, len ); break;
case '$': case '$':
replaced = deformat_component(format, str); break; replaced = deformat_component( format, str, len ); break;
} }
*type = FORMAT_LITERAL; *type = FORMAT_LITERAL;
} }
else else
{ {
replaced = deformat_property(format, str); replaced = deformat_property( format, str, len );
*type = FORMAT_LITERAL; *type = FORMAT_LITERAL;
if (replaced) if (replaced)
...@@ -489,8 +506,8 @@ static int format_lex(FORMAT *format, FORMSTR **out) ...@@ -489,8 +506,8 @@ static int format_lex(FORMAT *format, FORMSTR **out)
return type; return type;
} }
static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, static FORMSTR *format_replace( FORMAT *format, BOOL propfound, BOOL nonprop,
int oldsize, int type, LPWSTR replace) int oldsize, int type, WCHAR *replace, int len )
{ {
FORMSTR *ret; FORMSTR *ret;
LPWSTR str, ptr; LPWSTR str, ptr;
...@@ -499,10 +516,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, ...@@ -499,10 +516,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
if (replace) if (replace)
{ {
if (!*replace) if (!len)
size = 1; size = 1;
else else
size = lstrlenW(replace); size = len;
} }
size -= oldsize; size -= oldsize;
...@@ -526,15 +543,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, ...@@ -526,15 +543,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
if (replace) if (replace)
{ {
if (!*replace) if (!len) str[n++] = 0;
{
str[n] = '\0';
n++;
}
else else
{ {
lstrcpyW(&str[n], replace); memcpy( str + n, replace, len * sizeof(WCHAR) );
n += lstrlenW(replace); n += len;
str[n] = 0;
} }
} }
...@@ -546,7 +560,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, ...@@ -546,7 +560,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
format->len = size - 1; format->len = size - 1;
/* don't reformat the NULL */ /* don't reformat the NULL */
if (replace && !*replace) if (replace && !len)
format->n++; format->n++;
if (!replace) if (!replace)
...@@ -556,7 +570,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, ...@@ -556,7 +570,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
if (!ret) if (!ret)
return NULL; return NULL;
ret->len = lstrlenW(replace); ret->len = len;
ret->type = type; ret->type = type;
ret->n = format->n; ret->n = format->n;
ret->propfound = propfound; ret->propfound = propfound;
...@@ -565,13 +579,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, ...@@ -565,13 +579,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
return ret; return ret;
} }
static LPWSTR replace_stack_group(FORMAT *format, STACK *values, static WCHAR *replace_stack_group( FORMAT *format, STACK *values,
BOOL *propfound, BOOL *nonprop, BOOL *propfound, BOOL *nonprop,
int *oldsize, int *type) int *oldsize, int *type, int *len )
{ {
LPWSTR replaced = NULL; WCHAR *replaced;
FORMSTR *content; FORMSTR *content, *node;
FORMSTR *node;
int n; int n;
*nonprop = FALSE; *nonprop = FALSE;
...@@ -626,7 +639,7 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values, ...@@ -626,7 +639,7 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
*nonprop = TRUE; *nonprop = TRUE;
} }
replaced = dup_formstr(format, content); replaced = dup_formstr( format, content, len );
*type = content->type; *type = content->type;
msi_free(content); msi_free(content);
...@@ -636,13 +649,12 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values, ...@@ -636,13 +649,12 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
return replaced; return replaced;
} }
static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, static WCHAR *replace_stack_prop( FORMAT *format, STACK *values,
BOOL *propfound, BOOL *nonprop, BOOL *propfound, BOOL *nonprop,
int *oldsize, int *type) int *oldsize, int *type, int *len )
{ {
LPWSTR replaced = NULL; WCHAR *replaced;
FORMSTR *content; FORMSTR *content, *node;
FORMSTR *node;
int n; int n;
*propfound = FALSE; *propfound = FALSE;
...@@ -672,7 +684,7 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, ...@@ -672,7 +684,7 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
if (*type == FORMAT_NUMBER) if (*type == FORMAT_NUMBER)
{ {
replaced = deformat_index(format, content); replaced = deformat_index( format, content, len );
if (replaced) if (replaced)
*propfound = TRUE; *propfound = TRUE;
else else
...@@ -684,48 +696,42 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, ...@@ -684,48 +696,42 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
} }
else if (format->package) else if (format->package)
{ {
replaced = deformat_literal(format, content, propfound, nonprop, type); replaced = deformat_literal( format, content, propfound, nonprop, type, len );
} }
else else
{ {
*nonprop = TRUE; *nonprop = TRUE;
content->n--; content->n--;
content->len += 2; content->len += 2;
replaced = dup_formstr(format, content); replaced = dup_formstr( format, content, len );
} }
msi_free(content); msi_free(content);
return replaced; return replaced;
} }
static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values) static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
{ {
LPWSTR replaced = NULL; WCHAR *replaced = NULL;
FORMSTR *beg; FORMSTR *beg, *top, *node;
FORMSTR *top; BOOL propfound = FALSE, nonprop = FALSE, group = FALSE;
FORMSTR *node; int type, n, len = 0, oldsize = 0;
BOOL propfound = FALSE;
BOOL nonprop = FALSE;
BOOL group = FALSE;
int oldsize = 0;
int type, n;
node = stack_peek(values); node = stack_peek(values);
type = node->type; type = node->type;
n = node->n; n = node->n;
if (type == FORMAT_LBRACK) if (type == FORMAT_LBRACK)
replaced = replace_stack_prop(format, values, &propfound, replaced = replace_stack_prop( format, values, &propfound,
&nonprop, &oldsize, &type); &nonprop, &oldsize, &type, &len );
else if (type == FORMAT_LBRACE) else if (type == FORMAT_LBRACE)
{ {
replaced = replace_stack_group(format, values, &propfound, replaced = replace_stack_group( format, values, &propfound,
&nonprop, &oldsize, &type); &nonprop, &oldsize, &type, &len );
group = TRUE; group = TRUE;
} }
format->n = n; format->n = n;
beg = format_replace(format, propfound, nonprop, oldsize, type, replaced); beg = format_replace( format, propfound, nonprop, oldsize, type, replaced, len );
if (!beg) if (!beg)
return ERROR_SUCCESS; return ERROR_SUCCESS;
...@@ -865,20 +871,18 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, ...@@ -865,20 +871,18 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
LPDWORD size ) LPDWORD size )
{ {
LPWSTR deformated; WCHAR *format, *deformated;
LPWSTR rec;
DWORD len;
UINT rc = ERROR_INVALID_PARAMETER; UINT rc = ERROR_INVALID_PARAMETER;
DWORD len;
TRACE("%p %p %p %p\n", package, record, buffer, size); TRACE("%p %p %p %p\n", package, record, buffer, size);
rec = msi_dup_record_field(record,0); if (!(format = msi_dup_record_field( record, 0 )))
if (!rec) format = build_default_format( record );
rec = 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 (buffer)
{ {
if (*size>len) if (*size>len)
...@@ -897,13 +901,11 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, ...@@ -897,13 +901,11 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
rc = ERROR_MORE_DATA; rc = ERROR_MORE_DATA;
} }
} }
else else rc = ERROR_SUCCESS;
rc = ERROR_SUCCESS;
*size = len; *size = len;
msi_free( format );
msi_free(rec); msi_free( deformated );
msi_free(deformated);
return rc; return rc;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment