From 570322069c98c8cddd98e67152f54a1ba0ec2fe5 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 5 Nov 2012 16:29:50 +0100 Subject: [PATCH] msi: Preserve strings with embedded nulls in the record formatting implementation. --- 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 15367e5597b..0bfd56631da 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; + WCHAR *prop, *ret; + DWORD len = 0; + UINT r; - val = msi_alloc((str->len + 1) * sizeof(WCHAR)); - lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL; + lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 ); - ret = msi_dup_property(format->package->db, val); - - 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; }