Author: fireball Date: Sun Feb 10 16:16:32 2008 New Revision: 32261
URL: http://svn.reactos.org/svn/reactos?rev=32261&view=rev Log: Winesync to Wine-0.9.55.
Modified: trunk/reactos/dll/win32/msi/action.c trunk/reactos/dll/win32/msi/database.c trunk/reactos/dll/win32/msi/files.c trunk/reactos/dll/win32/msi/format.c trunk/reactos/dll/win32/msi/msi.c trunk/reactos/dll/win32/msi/registry.c trunk/reactos/dll/win32/msi/streams.c
Modified: trunk/reactos/dll/win32/msi/action.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/action.c?rev=... ============================================================================== --- trunk/reactos/dll/win32/msi/action.c (original) +++ trunk/reactos/dll/win32/msi/action.c Sun Feb 10 16:16:32 2008 @@ -2240,6 +2240,7 @@ DWORD *size) { LPSTR data = NULL; + if (value[0]=='#' && value[1]!='#' && value[1]!='%') { if (value[1]=='x') @@ -2321,6 +2322,7 @@ { static const WCHAR szMulti[] = {'[','~',']',0}; LPCWSTR ptr; + LPWSTR newdata; *type=REG_SZ;
if (value[0]=='#') @@ -2339,7 +2341,29 @@ if (strstrW(value,szMulti)) *type = REG_MULTI_SZ;
+ /* remove initial delimiter */ + if (!strncmpW(value, szMulti, 3)) + ptr = value + 3; + *size = deformat_string(package, ptr,(LPWSTR*)&data); + + /* add double NULL terminator */ + if (*type == REG_MULTI_SZ) + { + *size += sizeof(WCHAR); + newdata = msi_alloc(*size); + if (!newdata) + { + msi_free(data); + return NULL; + } + + memcpy(newdata, data, *size - 1); + newdata[*size] = '\0'; + + msi_free(data); + data = (LPSTR)newdata; + } } return data; }
Modified: trunk/reactos/dll/win32/msi/database.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/database.c?re... ============================================================================== --- trunk/reactos/dll/win32/msi/database.c (original) +++ trunk/reactos/dll/win32/msi/database.c Sun Feb 10 16:16:32 2008 @@ -408,6 +408,10 @@ else type = type_long; break; + default: + ERR("Unknown type: %c\n", types[i][0]); + msi_free(columns); + return NULL; }
sprintfW(expanded, column_fmt, columns_data[i], type, size, extra, comma);
Modified: trunk/reactos/dll/win32/msi/files.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/files.c?rev=3... ============================================================================== --- trunk/reactos/dll/win32/msi/files.c (original) +++ trunk/reactos/dll/win32/msi/files.c Sun Feb 10 16:16:32 2008 @@ -901,12 +901,10 @@ }
dest = build_directory_name(2, dest_path, dest_name); - create_full_pathW(dest); + create_full_pathW(dest_path);
TRACE("Duplicating file %s to %s\n",debugstr_w(file->TargetPath), debugstr_w(dest)); - - CreateDirectoryW(dest_path, NULL);
if (strcmpW(file->TargetPath,dest)) rc = !CopyFileW(file->TargetPath,dest,TRUE);
Modified: trunk/reactos/dll/win32/msi/format.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/format.c?rev=... ============================================================================== --- trunk/reactos/dll/win32/msi/format.c (original) +++ trunk/reactos/dll/win32/msi/format.c Sun Feb 10 16:16:32 2008 @@ -19,10 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-/* -http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/m... - */ - #include <stdarg.h> #include <stdio.h>
@@ -43,11 +39,288 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi);
- -static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, - WCHAR** data, DWORD len, MSIRECORD* record, - BOOL* in_group); - +/* types arranged by precedence */ +#define FORMAT_NULL 0x0001 +#define FORMAT_LITERAL 0x0002 +#define FORMAT_NUMBER 0x0004 +#define FORMAT_LBRACK 0x0010 +#define FORMAT_LBRACE 0x0020 +#define FORMAT_RBRACK 0x0011 +#define FORMAT_RBRACE 0x0021 +#define FORMAT_ESCAPE 0x0040 +#define FORMAT_PROPNULL 0x0080 +#define FORMAT_ERROR 0x1000 +#define FORMAT_FAIL 0x2000 + +#define left_type(x) (x & 0xF0) + +typedef struct _tagFORMAT +{ + MSIPACKAGE *package; + MSIRECORD *record; + LPWSTR deformatted; + int len; + int n; + BOOL propfailed; + BOOL groupfailed; + int groups; +} FORMAT; + +typedef struct _tagFORMSTR +{ + struct list entry; + int n; + int len; + int type; + BOOL propfound; + BOOL nonprop; +} FORMSTR; + +typedef struct _tagSTACK +{ + struct list items; +} STACK; + +static STACK *create_stack(void) +{ + STACK *stack = msi_alloc(sizeof(STACK)); + list_init(&stack->items); + return stack; +} + +static void free_stack(STACK *stack) +{ + while (!list_empty(&stack->items)) + { + FORMSTR *str = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); + list_remove(&str->entry); + msi_free(str); + } + + msi_free(stack); +} + +static void stack_push(STACK *stack, FORMSTR *str) +{ + list_add_head(&stack->items, &str->entry); +} + +static FORMSTR *stack_pop(STACK *stack) +{ + FORMSTR *ret; + + if (list_empty(&stack->items)) + return NULL; + + ret = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); + list_remove(&ret->entry); + return ret; +} + +static FORMSTR *stack_find(STACK *stack, int type) +{ + FORMSTR *str; + + LIST_FOR_EACH_ENTRY(str, &stack->items, FORMSTR, entry) + { + if (str->type == type) + return str; + } + + return NULL; +} + +static FORMSTR *stack_peek(STACK *stack) +{ + return LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); +} + +static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str) +{ + return &format->deformatted[str->n]; +} + +static LPWSTR dup_formstr(FORMAT *format, FORMSTR *str) +{ + 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); + + return val; +} + +static LPWSTR deformat_index(FORMAT *format, FORMSTR *str) +{ + LPWSTR val, ret; + + val = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + + ret = msi_dup_record_field(format->record, atoiW(val)); + + msi_free(val); + return ret; +} + +static LPWSTR deformat_property(FORMAT *format, FORMSTR *str) +{ + LPWSTR val, ret; + + val = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + + ret = msi_dup_property(format->package, val); + + msi_free(val); + return ret; +} + +static LPWSTR deformat_component(FORMAT *format, FORMSTR *str) +{ + LPWSTR key, ret = NULL; + MSICOMPONENT *comp; + BOOL source; + + key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(key, get_formstr_data(format, str), str->len + 1); + + comp = get_loaded_component(format->package, key); + if (!comp) + goto done; + + source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE; + ret = resolve_folder(format->package, comp->Directory, source, FALSE, TRUE, NULL); + +done: + msi_free(key); + return ret; +} + +static LPWSTR deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname) +{ + LPWSTR key, ret = NULL; + MSIFILE *file; + DWORD size; + + key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(key, get_formstr_data(format, str), str->len + 1); + + file = get_loaded_file(format->package, key); + if (!file) + goto done; + + if (!shortname) + { + ret = strdupW(file->TargetPath); + goto done; + } + + size = GetShortPathNameW(file->TargetPath, NULL, 0); + if (size <= 0) + { + ret = strdupW(file->TargetPath); + goto done; + } + + size++; + ret = msi_alloc(size * sizeof(WCHAR)); + GetShortPathNameW(file->TargetPath, ret, size); + +done: + msi_free(key); + return ret; +} + +static LPWSTR deformat_environment(FORMAT *format, FORMSTR *str) +{ + LPWSTR key, ret = NULL; + DWORD sz; + + key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + 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); + return ret; +} + +static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, + BOOL *nonprop, int *type) +{ + LPCWSTR data = get_formstr_data(format, str); + LPWSTR replaced = NULL; + char ch = data[0]; + + if (ch == '\') + { + str->n++; + if (str->len == 1) + { + str->len = 0; + replaced = NULL; + } + else + { + str->len = 1; + replaced = dup_formstr(format, str); + } + } + else if (ch == '~') + { + if (str->len != 1) + replaced = NULL; + else + { + replaced = msi_alloc(sizeof(WCHAR)); + *replaced = '\0'; + } + } + else if (ch == '%' || ch == '#' || ch == '!' || ch == '$') + { + str->n++; + str->len--; + + switch (ch) + { + case '%': + replaced = deformat_environment(format, str); break; + case '#': + replaced = deformat_file(format, str, FALSE); break; + case '!': + replaced = deformat_file(format, str, TRUE); break; + case '$': + replaced = deformat_component(format, str); break; + } + + *type = FORMAT_LITERAL; + } + else + { + replaced = deformat_property(format, str); + *type = FORMAT_LITERAL; + + if (replaced) + *propfound = TRUE; + else + format->propfailed = TRUE; + } + + return replaced; +}
static LPWSTR build_default_format(const MSIRECORD* record) { @@ -70,7 +343,7 @@ size = 1; for (i = 1; i <= count; i++) { - sprintfW(index,fmt_index,i); + sprintfW(index, fmt_index, i); str = MSI_RecordGetString(record, i); len = (str) ? lstrlenW(str) : 0; len += (sizeof(fmt_null) - 3) + lstrlenW(index); @@ -84,9 +357,9 @@ }
if (str) - sprintfW(buf,fmt,i,str); + sprintfW(buf, fmt, i, str); else - sprintfW(buf,fmt_null,i); + sprintfW(buf, fmt_null, i);
if (!rc) { @@ -99,516 +372,493 @@ lstrcatW(rc, buf); } } + msi_free(buf); return rc; }
-static const WCHAR* scanW(LPCWSTR buf, WCHAR token, DWORD len) -{ - DWORD i; - for (i = 0; i < len; i++) - if (buf[i] == token) - return &buf[i]; - return NULL; -} - -/* break out helper functions for deformating */ -static LPWSTR deformat_component(MSIPACKAGE* package, LPCWSTR key, DWORD* sz) -{ - LPWSTR value = NULL; - MSICOMPONENT *comp; - BOOL source; - - *sz = 0; - if (!package) +static BOOL format_is_number(WCHAR x) +{ + return ((x >= '0') && (x <= '9')); +} + +static BOOL format_str_is_number(LPWSTR str) +{ + LPWSTR ptr; + + for (ptr = str; *ptr; ptr++) + if (!format_is_number(*ptr)) + return FALSE; + + return TRUE; +} + +static BOOL format_is_alpha(WCHAR x) +{ + return (!format_is_number(x) && x != '\0' && + x != '[' && x != ']' && x != '{' && x != '}'); +} + +static BOOL format_is_literal(WCHAR x) +{ + return (format_is_alpha(x) || format_is_number(x)); +} + +static int format_lex(FORMAT *format, FORMSTR **out) +{ + int type, len = 1; + FORMSTR *str; + LPCWSTR data; + WCHAR ch; + + *out = NULL; + + if (!format->deformatted) + return FORMAT_NULL; + + *out = msi_alloc_zero(sizeof(FORMSTR)); + if (!*out) + return FORMAT_FAIL; + + str = *out; + str->n = format->n; + str->len = 1; + data = get_formstr_data(format, str); + + ch = data[0]; + switch (ch) + { + case '{': type = FORMAT_LBRACE; break; + case '}': type = FORMAT_RBRACE; break; + case '[': type = FORMAT_LBRACK; break; + case ']': type = FORMAT_RBRACK; break; + case '~': type = FORMAT_PROPNULL; break; + case '\0': type = FORMAT_NULL; break; + + default: + type = 0; + } + + if (type) + { + str->type = type; + format->n++; + return type; + } + + if (ch == '\') + { + while (data[len] && data[len] != ']') + len++; + + type = FORMAT_ESCAPE; + } + else if (format_is_alpha(ch)) + { + while (format_is_literal(data[len])) + len++; + + type = FORMAT_LITERAL; + } + else if (format_is_number(ch)) + { + while (format_is_number(data[len])) + len++; + + type = FORMAT_NUMBER; + + if (data[len] != ']') + { + while (format_is_literal(data[len])) + len++; + + type = FORMAT_LITERAL; + } + } + else + { + ERR("Got unknown character %c(%x)\n", ch, ch); + return FORMAT_ERROR; + } + + format->n += len; + str->len = len; + str->type = type; + + return type; +} + +static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, + int oldsize, int type, LPWSTR replace) +{ + FORMSTR *ret; + LPWSTR str, ptr; + DWORD size = 0; + int n; + + if (replace) + { + if (!*replace) + size = 1; + else + size = lstrlenW(replace); + } + + size -= oldsize; + size = format->len + size + 1; + + if (size <= 1) + { + msi_free(format->deformatted); + format->deformatted = NULL; + format->len = 0; return NULL; - - comp = get_loaded_component(package,key); - if (comp) - { - source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE; - value = resolve_folder(package, comp->Directory, source, FALSE, TRUE, NULL); - *sz = (strlenW(value)) * sizeof(WCHAR); - } - - return value; -} - -static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz, - BOOL shortname) -{ - LPWSTR value = NULL; - MSIFILE *file; - - *sz = 0; - - if (!package) + } + + str = msi_alloc(size * sizeof(WCHAR)); + if (!str) return NULL;
- file = get_loaded_file( package, key ); - if (file) - { - if (!shortname) - { - value = strdupW( file->TargetPath ); - *sz = (strlenW(value)) * sizeof(WCHAR); + str[0] = '\0'; + memcpy(str, format->deformatted, format->n * sizeof(WCHAR)); + n = format->n; + + if (replace) + { + if (!*replace) + { + str[n] = '\0'; + n++; } else { - DWORD size = 0; - size = GetShortPathNameW( file->TargetPath, NULL, 0 ); - - if (size > 0) - { - *sz = (size-1) * sizeof (WCHAR); - size ++; - value = msi_alloc(size * sizeof(WCHAR)); - GetShortPathNameW( file->TargetPath, value, size ); - } - else - { - value = strdupW( file->TargetPath ); - *sz = (lstrlenW(value)) * sizeof(WCHAR); - } - } - } - - return value; -} - -static LPWSTR deformat_environment(MSIPACKAGE* package, LPCWSTR key, - DWORD* chunk) -{ - LPWSTR value = NULL; - DWORD sz; - - sz = GetEnvironmentVariableW(key,NULL,0); - if (sz > 0) - { - sz++; - value = msi_alloc(sz * sizeof(WCHAR)); - GetEnvironmentVariableW(key,value,sz); - *chunk = (strlenW(value)) * sizeof(WCHAR); + lstrcpyW(&str[n], replace); + n += lstrlenW(replace); + } + } + + ptr = &format->deformatted[format->n + oldsize]; + memcpy(&str[n], ptr, (lstrlenW(ptr) + 1) * sizeof(WCHAR)); + + msi_free(format->deformatted); + format->deformatted = str; + format->len = size - 1; + + if (!replace) + return NULL; + + ret = msi_alloc_zero(sizeof(FORMSTR)); + if (!ret) + return NULL; + + ret->len = lstrlenW(replace); + ret->type = type; + ret->n = format->n; + ret->propfound = propfound; + ret->nonprop = nonprop; + + return ret; +} + +static LPWSTR replace_stack_group(FORMAT *format, STACK *values, + BOOL *propfound, BOOL *nonprop, + int *oldsize, int *type) +{ + LPWSTR replaced = NULL; + FORMSTR *content; + FORMSTR *node; + int n; + + *nonprop = FALSE; + *propfound = FALSE; + + node = stack_pop(values); + n = node->n; + *oldsize = node->len; + msi_free(node); + + while ((node = stack_pop(values))) + { + *oldsize += node->len; + + if (node->nonprop) + *nonprop = TRUE; + + if (node->propfound) + *propfound = TRUE; + + msi_free(node); + } + + content = msi_alloc_zero(sizeof(FORMSTR)); + content->n = n; + content->len = *oldsize; + content->type = FORMAT_LITERAL; + + if (!format->groupfailed && (*oldsize == 2 || + (format->propfailed && !*nonprop))) + { + msi_free(content); + return NULL; + } + else if (format->deformatted[content->n + 1] == '{' && + format->deformatted[content->n + content->len - 2] == '}') + { + format->groupfailed = FALSE; + content->len = 0; + } + else if (*propfound && !*nonprop && + !format->groupfailed && format->groups == 0) + { + content->n++; + content->len -= 2; } else { - WARN("Unknown environment variable %s\n", debugstr_w(key)); - *chunk = 0; - value = NULL; - } - return value; -} - - -static LPWSTR deformat_NULL(DWORD* chunk) -{ - LPWSTR value; - - value = msi_alloc(sizeof(WCHAR)*2); - value[0] = 0; - *chunk = sizeof(WCHAR); - return value; -} - -static LPWSTR deformat_escape(LPCWSTR key, DWORD* chunk) -{ - LPWSTR value; - - value = msi_alloc(sizeof(WCHAR)*2); - value[0] = key[0]; - *chunk = sizeof(WCHAR); - - return value; -} - - -static BOOL is_key_number(LPCWSTR key) -{ - INT index = 0; - if (key[0] == 0) - return FALSE; - - while (isdigitW(key[index])) index++; - if (key[index] == 0) - return TRUE; + if (format->groups != 0) + format->groupfailed = TRUE; + + *nonprop = TRUE; + } + + replaced = dup_formstr(format, content); + *type = content->type; + msi_free(content); + + if (format->groups == 0) + format->propfailed = FALSE; + + return replaced; +} + +static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, + BOOL *propfound, BOOL *nonprop, + int *oldsize, int *type) +{ + LPWSTR replaced = NULL; + FORMSTR *content; + FORMSTR *node; + int n; + + *propfound = FALSE; + *nonprop = FALSE; + + node = stack_pop(values); + n = node->n; + *oldsize = node->len; + *type = stack_peek(values)->type; + msi_free(node); + + while ((node = stack_pop(values))) + { + *oldsize += node->len; + + if (*type != FORMAT_ESCAPE && + stack_peek(values) && node->type != *type) + *type = FORMAT_LITERAL; + + msi_free(node); + } + + content = msi_alloc_zero(sizeof(FORMSTR)); + content->n = n + 1; + content->len = *oldsize - 2; + content->type = *type; + + if (*type == FORMAT_NUMBER) + { + replaced = deformat_index(format, content); + if (replaced) + *propfound = TRUE; + else + format->propfailed = TRUE; + + if (replaced) + *type = format_str_is_number(replaced) ? + FORMAT_NUMBER : FORMAT_LITERAL; + } + else if (format->package) + { + replaced = deformat_literal(format, content, propfound, nonprop, type); + } else - return FALSE; -} - -static LPWSTR deformat_index(MSIRECORD* record, LPCWSTR key, DWORD* chunk ) -{ - INT index; - LPWSTR value; - - index = atoiW(key); - TRACE("record index %i\n",index); - value = msi_dup_record_field(record,index); - if (value) - *chunk = strlenW(value) * sizeof(WCHAR); - else - { - value = NULL; - *chunk = 0; - } - return value; -} - -static LPWSTR deformat_property(MSIPACKAGE* package, LPCWSTR key, DWORD* chunk) -{ - LPWSTR value; - - if (!package) - return NULL; - - value = msi_dup_property( package, key ); - - if (value) - *chunk = (strlenW(value)) * sizeof(WCHAR); - - return value; -} - -/* - * Groups cannot be nested. They are just treated as from { to next } - */ -static BOOL find_next_group(LPCWSTR source, DWORD len_remaining, - LPWSTR *group, LPCWSTR *mark, - LPCWSTR* mark2) -{ - int i; - BOOL found = FALSE; - - *mark = scanW(source,'{',len_remaining); - if (!*mark) - return FALSE; - - for (i = 1; (*mark - source) + i < len_remaining; i++) - { - if ((*mark)[i] == '}') - { - found = TRUE; - break; - } - } - if (! found) - return FALSE; - - *mark2 = &(*mark)[i]; - - i = *mark2 - *mark; - *group = msi_alloc(i*sizeof(WCHAR)); - - i -= 1; - memcpy(*group,&(*mark)[1],i*sizeof(WCHAR)); - (*group)[i] = 0; - - TRACE("Found group %s\n",debugstr_w(*group)); - return TRUE; -} - - -static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining, - LPWSTR *key, LPCWSTR *mark, LPCWSTR* mark2, - BOOL *nested) -{ - INT count = 0; - INT total_count = 0; - int i; - - *nested = FALSE; - *mark = scanW(source,'[',len_remaining); - if (!*mark) - return FALSE; - - count = 1; - total_count = 1; - for (i = 1; (*mark - source) + i < len_remaining && count > 0; i++) - { - if ((*mark)[i] == '[' && (*mark)[i-1] != '\') - { - count ++; - total_count ++; - *nested = TRUE; - } - else if ((*mark)[i] == ']' && (*mark)[i-1] != '\') - { - count --; - } + { + *nonprop = TRUE; + content->n--; + content->len += 2; + replaced = dup_formstr(format, content); + } + + 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; + + node = stack_peek(values); + type = node->type; + n = node->n; + + if (type == FORMAT_LBRACK) + replaced = replace_stack_prop(format, values, &propfound, + &nonprop, &oldsize, &type); + else if (type == FORMAT_LBRACE) + { + replaced = replace_stack_group(format, values, &propfound, + &nonprop, &oldsize, &type); + group = TRUE; + } + + format->n = n; + beg = format_replace(format, propfound, nonprop, oldsize, type, replaced); + if (!beg) + return ERROR_SUCCESS; + + msi_free(replaced); + format->n = beg->n + beg->len; + + if (type == FORMAT_PROPNULL) + format->n++; + + top = stack_peek(stack); + if (top) + { + type = top->type; + + if ((type == FORMAT_LITERAL || type == FORMAT_NUMBER) && + type == beg->type) + { + top->len += beg->len; + + if (group) + top->nonprop = FALSE; + + if (type == FORMAT_LITERAL) + top->nonprop = beg->nonprop; + + if (beg->propfound) + top->propfound = TRUE; + + msi_free(beg); + return ERROR_SUCCESS; + } + } + + stack_push(stack, beg); + return ERROR_SUCCESS; +} + +static BOOL verify_format(LPWSTR data) +{ + int count = 0; + + while (*data) + { + if (*data == '[' && *(data - 1) != '\') + count++; + else if (*data == ']') + count--; + + data++; }
if (count > 0) return FALSE;
- *mark2 = &(*mark)[i-1]; - - i = *mark2 - *mark; - *key = msi_alloc(i*sizeof(WCHAR)); - /* do not have the [] in the key */ - i -= 1; - memcpy(*key,&(*mark)[1],i*sizeof(WCHAR)); - (*key)[i] = 0; - - TRACE("Found Key %s\n",debugstr_w(*key)); return TRUE; }
-static LPWSTR deformat_group(MSIPACKAGE* package, LPWSTR group, DWORD len, - MSIRECORD* record, DWORD* size) -{ - LPWSTR value = NULL; - LPCWSTR mark, mark2; - LPWSTR key; - BOOL nested; - INT failcount; - static const WCHAR fmt[] = {'{','%','s','}',0}; - UINT sz; - - if (!group || group[0] == 0) - { - *size = 0; - return NULL; - } - /* if no [] then group is returned as is */ - - if (!find_next_outermost_key(group, len, &key, &mark, &mark2, &nested)) - { - *size = (len+2)*sizeof(WCHAR); - value = msi_alloc(*size); - sprintfW(value,fmt,group); - /* do not return size of the null at the end */ - *size = (len+1)*sizeof(WCHAR); - return value; - } - - msi_free(key); - failcount = 0; - sz = deformat_string_internal(package, group, &value, strlenW(group), - record, &failcount); - if (failcount==0) - { - *size = sz * sizeof(WCHAR); - return value; - } - else if (failcount < 0) - { - LPWSTR v2; - - v2 = msi_alloc((sz+2)*sizeof(WCHAR)); - v2[0] = '{'; - memcpy(&v2[1],value,sz*sizeof(WCHAR)); - v2[sz+1]='}'; - msi_free(value); - - *size = (sz+2)*sizeof(WCHAR); - return v2; - } - else - { - msi_free(value); - *size = 0; - return NULL; - } -} - - -/* - * len is in WCHARs - * return is also in WCHARs - */ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, - WCHAR** data, DWORD len, MSIRECORD* record, - INT* failcount) -{ - LPCWSTR mark = NULL; - LPCWSTR mark2 = NULL; - DWORD size=0; - DWORD chunk=0; - LPWSTR key; - LPWSTR value = NULL; - DWORD sz; - LPBYTE newdata = NULL; - const WCHAR* progress = NULL; - BOOL nested = FALSE; - - if (ptr==NULL) - { - TRACE("Deformatting NULL string\n"); + WCHAR** data, DWORD *len, + MSIRECORD* record, INT* failcount) +{ + FORMAT format; + FORMSTR *str = NULL; + STACK *stack, *temp; + FORMSTR *node; + int type; + + if (!ptr) + { *data = NULL; - return 0; - } - - TRACE("Starting with %s\n",debugstr_wn(ptr,len)); - - /* scan for special characters... fast exit */ - if ((!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) && - (scanW(ptr,'{',len) && !scanW(ptr,'}',len))) - { - /* not formatted */ - *data = msi_alloc((len*sizeof(WCHAR))); - memcpy(*data,ptr,len*sizeof(WCHAR)); - TRACE("Returning %s\n",debugstr_wn(*data,len)); - return len; - } - - progress = ptr; - - while (progress - ptr < len) - { - /* seek out first group if existing */ - if (find_next_group(progress, len - (progress - ptr), &key, - &mark, &mark2)) - { - value = deformat_group(package, key, strlenW(key)+1, record, - &chunk); - msi_free( key ); - key = NULL; - nested = FALSE; - } - /* formatted string located */ - else if (!find_next_outermost_key(progress, len - (progress - ptr), - &key, &mark, &mark2, &nested)) - { - LPBYTE nd2; - - TRACE("after value %s\n", debugstr_wn((LPWSTR)newdata, - size/sizeof(WCHAR))); - chunk = (len - (progress - ptr)) * sizeof(WCHAR); - TRACE("after chunk is %i + %i\n",size,chunk); - if (size) - nd2 = msi_realloc(newdata,(size+chunk)); - else - nd2 = msi_alloc(chunk); - - newdata = nd2; - memcpy(&newdata[size],progress,chunk); - size+=chunk; - break; - } - - if (mark != progress) - { - LPBYTE tgt; - DWORD old_size = size; - INT cnt = (mark - progress); - TRACE("%i (%i) characters before marker\n",cnt,(mark-progress)); - size += cnt * sizeof(WCHAR); - if (!old_size) - tgt = msi_alloc(size); - else - tgt = msi_realloc(newdata,size); - newdata = tgt; - memcpy(&newdata[old_size],progress,(cnt * sizeof(WCHAR))); - } - - progress = mark; - - if (nested) - { - TRACE("Nested key... %s\n",debugstr_w(key)); - deformat_string_internal(package, key, &value, strlenW(key)+1, - record, failcount); - - msi_free(key); - key = value; - } - - TRACE("Current %s .. %s\n",debugstr_wn((LPWSTR)newdata, - size/sizeof(WCHAR)),debugstr_w(key)); - - if (!package) - { - /* only deformat number indexs */ - if (key && is_key_number(key)) + *len = 0; + return ERROR_SUCCESS; + } + + *data = strdupW(ptr); + *len = lstrlenW(ptr); + + ZeroMemory(&format, sizeof(FORMAT)); + format.package = package; + format.record = record; + format.deformatted = *data; + format.len = *len; + + stack = create_stack(); + temp = create_stack(); + + if (!verify_format(*data)) + return ERROR_SUCCESS; + + while ((type = format_lex(&format, &str)) != FORMAT_NULL) + { + if (type == FORMAT_LBRACK || type == FORMAT_LBRACE || + type == FORMAT_LITERAL || type == FORMAT_NUMBER || + type == FORMAT_ESCAPE || type == FORMAT_PROPNULL) + { + if (type == FORMAT_LBRACE) { - value = deformat_index(record,key,&chunk); - if (!chunk && failcount && *failcount >= 0) - (*failcount)++; + format.propfailed = FALSE; + format.groups++; } - else + else if (type == FORMAT_ESCAPE && + !stack_find(stack, FORMAT_LBRACK)) { - if (failcount) - *failcount = -1; - if(key) + format.n -= str->len - 1; + str->len = 1; + } + + stack_push(stack, str); + } + else if (type == FORMAT_RBRACK || type == FORMAT_RBRACE) + { + if (type == FORMAT_RBRACE) + format.groups--; + + stack_push(stack, str); + + if (stack_find(stack, left_type(type))) + { + do { - DWORD keylen = strlenW(key); - chunk = (keylen + 2)*sizeof(WCHAR); - value = msi_alloc(chunk); - value[0] = '['; - memcpy(&value[1],key,keylen*sizeof(WCHAR)); - value[1+keylen] = ']'; - } + node = stack_pop(stack); + stack_push(temp, node); + } while (node->type != left_type(type)); + + replace_stack(&format, stack, temp); } } - else - { - sz = 0; - if (key) switch (key[0]) - { - case '~': - value = deformat_NULL(&chunk); - break; - case '$': - value = deformat_component(package,&key[1],&chunk); - break; - case '#': - value = deformat_file(package,&key[1], &chunk, FALSE); - break; - case '!': /* should be short path */ - value = deformat_file(package,&key[1], &chunk, TRUE); - break; - case '\': - value = deformat_escape(&key[1],&chunk); - break; - case '%': - value = deformat_environment(package,&key[1],&chunk); - break; - default: - /* index keys cannot be nested */ - if (is_key_number(key)) - if (!nested) - value = deformat_index(record,key,&chunk); - else - { - static const WCHAR fmt[] = {'[','%','s',']',0}; - value = msi_alloc(10); - sprintfW(value,fmt,key); - chunk = strlenW(value)*sizeof(WCHAR); - } - else - value = deformat_property(package,key,&chunk); - break; - } - } - - msi_free(key); - - if (value!=NULL) - { - LPBYTE nd2; - TRACE("value %s, chunk %i size %i\n",debugstr_w(value), - chunk, size); - if (size) - nd2= msi_realloc(newdata,(size + chunk)); - else - nd2= msi_alloc(chunk); - newdata = nd2; - memcpy(&newdata[size],value,chunk); - size+=chunk; - msi_free(value); - } - else if (failcount && *failcount >=0 ) - (*failcount)++; - - progress = mark2+1; - } - - TRACE("after everything %s\n",debugstr_wn((LPWSTR)newdata, - size/sizeof(WCHAR))); - - *data = (LPWSTR)newdata; - return size / sizeof(WCHAR); -} - + } + + *data = format.deformatted; + *len = format.len; + + msi_free(str); + free_stack(stack); + free_stack(temp); + + return ERROR_SUCCESS; +}
UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, LPDWORD size ) @@ -626,9 +876,7 @@
TRACE("(%s)\n",debugstr_w(rec));
- len = deformat_string_internal(package,rec,&deformated, - rec ? strlenW(rec) : 0, record, NULL); - + deformat_string_internal(package, rec, &deformated, &len, record, NULL); if (buffer) { if (*size>len) @@ -770,8 +1018,8 @@ goto done;
save = len + 1; - len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL); - WideCharToMultiByte(CP_ACP, 0, value, -1, szResult, *sz, NULL, NULL); + len = WideCharToMultiByte(CP_ACP, 0, value, len + 1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, value, len, szResult, *sz, NULL, NULL);
if (szResult && len > *sz) {
Modified: trunk/reactos/dll/win32/msi/msi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.c?rev=322... ============================================================================== --- trunk/reactos/dll/win32/msi/msi.c (original) +++ trunk/reactos/dll/win32/msi/msi.c Sun Feb 10 16:16:32 2008 @@ -1519,6 +1519,10 @@ LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; UINT ret = ERROR_OUTOFMEMORY;
+ if ((lpVersionBuf && !pcchVersionBuf) || + (lpLangBuf && !pcchLangBuf)) + return ERROR_INVALID_PARAMETER; + if( szFilePath ) { szwFilePath = strdupAtoW( szFilePath ); @@ -1543,12 +1547,12 @@ ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, lpwLangBuff, pcchLangBuf);
- if( lpwVersionBuff ) + if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff ) WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, - lpVersionBuf, *pcchVersionBuf, NULL, NULL); - if( lpwLangBuff ) + lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL); + if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff ) WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, - lpLangBuf, *pcchLangBuf, NULL, NULL); + lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
end: msi_free(szwFilePath); @@ -1569,7 +1573,7 @@ '%','d','.','%','d','.','%','d','.','%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0}; UINT ret = 0; - DWORD dwVerLen; + DWORD dwVerLen, gle; LPVOID lpVer = NULL; VS_FIXEDFILEINFO *ffi; UINT puLen; @@ -1579,9 +1583,21 @@ lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0, lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
+ if ((lpVersionBuf && !pcchVersionBuf) || + (lpLangBuf && !pcchLangBuf)) + return ERROR_INVALID_PARAMETER; + dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL); if( !dwVerLen ) - return GetLastError(); + { + gle = GetLastError(); + if (gle == ERROR_BAD_PATHNAME) + return ERROR_FILE_NOT_FOUND; + else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND) + return ERROR_FILE_INVALID; + + return gle; + }
lpVer = msi_alloc(dwVerLen); if( !lpVer ) @@ -1595,7 +1611,8 @@ ret = GetLastError(); goto end; } - if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) + + if (pcchVersionBuf) { if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) && (puLen > 0) ) @@ -1603,24 +1620,32 @@ wsprintfW(tmp, szVersionFormat, HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS)); - lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf); - *pcchVersionBuf = lstrlenW(lpVersionBuf); + if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf); + + if (lstrlenW(tmp) >= *pcchVersionBuf) + ret = ERROR_MORE_DATA; + + *pcchVersionBuf = lstrlenW(tmp); } else { - *lpVersionBuf = 0; + if (lpVersionBuf) *lpVersionBuf = 0; *pcchVersionBuf = 0; } }
- if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) + if (pcchLangBuf) { DWORD lang = GetUserDefaultLangID();
FIXME("Retrieve language from file\n"); wsprintfW(tmp, szLangFormat, lang); - lstrcpynW(lpLangBuf, tmp, *pcchLangBuf); - *pcchLangBuf = lstrlenW(lpLangBuf); + if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf); + + if (lstrlenW(tmp) >= *pcchLangBuf) + ret = ERROR_MORE_DATA; + + *pcchLangBuf = lstrlenW(tmp); }
end:
Modified: trunk/reactos/dll/win32/msi/registry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/registry.c?re... ============================================================================== --- trunk/reactos/dll/win32/msi/registry.c (original) +++ trunk/reactos/dll/win32/msi/registry.c Sun Feb 10 16:16:32 2008 @@ -478,21 +478,17 @@ return ERROR_FUNCTION_FAILED;
size = sizeof(buf); - if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size)) - { + if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size)) { CloseHandle(token); return ERROR_FUNCTION_FAILED; }
user = (PTOKEN_USER)buf; - if (!ConvertSidToStringSidW(user->User.Sid, usersid)) - { + if (!ConvertSidToStringSidW(user->User.Sid, usersid)) { CloseHandle(token); return ERROR_FUNCTION_FAILED; } - CloseHandle(token); - return ERROR_SUCCESS; }
@@ -666,7 +662,7 @@ else rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
- msi_free(usersid); + LocalFree(usersid); return rc; }
@@ -743,7 +739,7 @@ else rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
- msi_free(usersid); + LocalFree(usersid); return rc; }
@@ -768,7 +764,7 @@
sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
- msi_free(usersid); + LocalFree(usersid); return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); }
@@ -798,7 +794,7 @@ else rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
- msi_free(usersid); + LocalFree(usersid); return rc; }
@@ -828,7 +824,7 @@ else rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
- msi_free(usersid); + LocalFree(usersid); return rc; }
@@ -853,7 +849,7 @@
sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
- msi_free(usersid); + LocalFree(usersid); return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); }
@@ -1043,7 +1039,7 @@ }
sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc); - msi_free(usersid); + LocalFree(usersid);
if (create) return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
Modified: trunk/reactos/dll/win32/msi/streams.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/streams.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msi/streams.c (original) +++ trunk/reactos/dll/win32/msi/streams.c Sun Feb 10 16:16:32 2008 @@ -54,9 +54,9 @@ UINT row_size; } MSISTREAMSVIEW;
-static BOOL add_stream_to_table(MSISTREAMSVIEW *sv, STREAM *stream, int index) -{ - if (index >= sv->max_streams) +static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, int size) +{ + if (size >= sv->max_streams) { sv->max_streams *= 2; sv->streams = msi_realloc(sv->streams, sv->max_streams * sizeof(STREAM *)); @@ -64,7 +64,6 @@ return FALSE; }
- sv->streams[index] = stream; return TRUE; }
@@ -139,12 +138,6 @@ }
static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) -{ - FIXME("(%p, %d, %p, %d): stub!\n", view, row, rec, mask); - return ERROR_SUCCESS; -} - -static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary) { MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; STREAM *stream; @@ -156,7 +149,10 @@ ULONG count; UINT r = ERROR_FUNCTION_FAILED;
- TRACE("(%p, %p, %d)\n", view, rec, temporary); + TRACE("(%p, %p)\n", view, rec); + + if (row > sv->num_rows) + return ERROR_FUNCTION_FAILED;
r = MSI_RecordGetIStream(rec, 2, &stm); if (r != ERROR_SUCCESS) @@ -201,8 +197,7 @@ IStorage_OpenStream(sv->db->storage, name, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
- if (!add_stream_to_table(sv, stream, sv->num_rows++)) - goto done; + sv->streams[row] = stream;
done: msi_free(name); @@ -211,6 +206,16 @@ IStream_Release(stm);
return r; +} + +static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + + if (!streams_set_table_size(sv, ++sv->num_rows)) + return ERROR_FUNCTION_FAILED; + + return STREAMS_set_row(view, sv->num_rows - 1, rec, 0); }
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row) @@ -278,6 +283,52 @@ return ERROR_SUCCESS; }
+static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row) +{ + LPCWSTR str; + UINT i, id, data; + + str = MSI_RecordGetString(rec, 1); + msi_string2idW(sv->db->strings, str, &id); + + for (i = 0; i < sv->num_rows; i++) + { + STREAMS_fetch_int(&sv->view, i, 1, &data); + + if (data == id) + { + *row = i; + return ERROR_SUCCESS; + } + } + + return ERROR_FUNCTION_FAILED; +} + +static UINT streams_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + UINT r, row; + + r = streams_find_row(sv, rec, &row); + if (r != ERROR_SUCCESS) + return ERROR_FUNCTION_FAILED; + + return STREAMS_set_row(view, row, rec, 0); +} + +static UINT streams_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + UINT r, row; + + r = streams_find_row(sv, rec, &row); + if (r == ERROR_SUCCESS) + return streams_modify_update(view, rec); + + return STREAMS_insert_row(view, rec, FALSE); +} + static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row) { UINT r; @@ -286,15 +337,21 @@
switch (eModifyMode) { + case MSIMODIFY_ASSIGN: + r = streams_modify_assign(view, rec); + break; + case MSIMODIFY_INSERT: r = STREAMS_insert_row(view, rec, FALSE); break;
+ case MSIMODIFY_UPDATE: + r = streams_modify_update(view, rec); + break; + case MSIMODIFY_VALIDATE_NEW: case MSIMODIFY_INSERT_TEMPORARY: - case MSIMODIFY_UPDATE: case MSIMODIFY_REFRESH: - case MSIMODIFY_ASSIGN: case MSIMODIFY_REPLACE: case MSIMODIFY_MERGE: case MSIMODIFY_DELETE: @@ -425,11 +482,13 @@ STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); CoTaskMemFree(stat.pwcsName);
- if (!add_stream_to_table(sv, stream, count++)) + if (!streams_set_table_size(sv, ++count)) { count = -1; break; } + + sv->streams[count - 1] = stream; }
IEnumSTATSTG_Release(stgenum);