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?r…
==============================================================================
--- 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=…
==============================================================================
--- 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/msiformatrecord.asp
- */
-
#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=32…
==============================================================================
--- 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?r…
==============================================================================
--- 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?re…
==============================================================================
--- 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);