[MSI]: Sync to Wine 1.5.19.
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 9 Dec 2012 19:43:59 +0000 (19:43 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 9 Dec 2012 19:43:59 +0000 (19:43 +0000)
svn path=/trunk/; revision=57851

29 files changed:
reactos/dll/win32/msi/action.c
reactos/dll/win32/msi/appsearch.c
reactos/dll/win32/msi/automation.c
reactos/dll/win32/msi/custom.c
reactos/dll/win32/msi/database.c
reactos/dll/win32/msi/dialog.c
reactos/dll/win32/msi/events.c
reactos/dll/win32/msi/files.c
reactos/dll/win32/msi/format.c
reactos/dll/win32/msi/install.c
reactos/dll/win32/msi/msi.c
reactos/dll/win32/msi/msi_main.c
reactos/dll/win32/msi/msipriv.h
reactos/dll/win32/msi/msiquery.c
reactos/dll/win32/msi/package.c
reactos/dll/win32/msi/patch.c
reactos/dll/win32/msi/record.c
reactos/dll/win32/msi/registry.c
reactos/dll/win32/msi/script.c
reactos/dll/win32/msi/select.c
reactos/dll/win32/msi/source.c
reactos/dll/win32/msi/storages.c
reactos/dll/win32/msi/streams.c
reactos/dll/win32/msi/string.c
reactos/dll/win32/msi/table.c
reactos/dll/win32/msi/tokenize.c
reactos/dll/win32/msi/upgrade.c
reactos/dll/win32/msi/where.c
reactos/media/doc/README.WINE

index 1ad3bc2..076d1b3 100644 (file)
@@ -353,7 +353,7 @@ UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine,
         remove_quotes( val );
         TRACE("Found commandline property %s = %s\n", debugstr_w(prop), debugstr_w(val));
 
-        r = msi_set_property( package->db, prop, val );
+        r = msi_set_property( package->db, prop, val, -1 );
         if (r == ERROR_SUCCESS && !strcmpW( prop, szSourceDir ))
             msi_reset_folders( package, TRUE );
 
@@ -462,7 +462,7 @@ UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
     check = msi_dup_property( package->db, szSourceDir );
     if (!check || replace)
     {
-        UINT r = msi_set_property( package->db, szSourceDir, source );
+        UINT r = msi_set_property( package->db, szSourceDir, source, -1 );
         if (r == ERROR_SUCCESS)
             msi_reset_folders( package, TRUE );
     }
@@ -470,7 +470,7 @@ UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
 
     check = msi_dup_property( package->db, szSOURCEDIR );
     if (!check || replace)
-        msi_set_property( package->db, szSOURCEDIR, source );
+        msi_set_property( package->db, szSOURCEDIR, source, -1 );
 
     msi_free( check );
     msi_free( source );
@@ -605,7 +605,7 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
     {
         TRACE("Running the actions\n");
 
-        msi_set_property(package->db, szSourceDir, NULL);
+        msi_set_property( package->db, szSourceDir, NULL, -1 );
         rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, package);
         msiobj_release(&view->hdr);
     }
@@ -809,6 +809,11 @@ INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp )
         return INSTALLSTATE_UNKNOWN;
     }
     if (package->need_rollback) return comp->Installed;
+    if (comp->num_clients > 0 && comp->ActionRequest == INSTALLSTATE_ABSENT)
+    {
+        TRACE("%s has %u clients left\n", debugstr_w(comp->Component), comp->num_clients);
+        return INSTALLSTATE_UNKNOWN;
+    }
     return comp->ActionRequest;
 }
 
@@ -1563,8 +1568,8 @@ static UINT load_all_folders( MSIPACKAGE *package )
 
 static UINT ACTION_CostInitialize(MSIPACKAGE *package)
 {
-    msi_set_property( package->db, szCostingComplete, szZero );
-    msi_set_property( package->db, szRootDrive, szCRoot );
+    msi_set_property( package->db, szCostingComplete, szZero, -1 );
+    msi_set_property( package->db, szRootDrive, szCRoot, -1 );
 
     load_all_folders( package );
     msi_load_all_components( package );
@@ -1620,6 +1625,27 @@ static UINT ACTION_FileCost(MSIPACKAGE *package)
     return ERROR_SUCCESS;
 }
 
+static void get_client_counts( MSIPACKAGE *package )
+{
+    MSICOMPONENT *comp;
+    HKEY hkey;
+
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+    {
+        if (!comp->ComponentId) continue;
+
+        if (MSIREG_OpenUserDataComponentKey( comp->ComponentId, szLocalSid, &hkey, FALSE ) &&
+            MSIREG_OpenUserDataComponentKey( comp->ComponentId, NULL, &hkey, FALSE ))
+        {
+            comp->num_clients = 0;
+            continue;
+        }
+        RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD *)&comp->num_clients,
+                          NULL, NULL, NULL, NULL );
+        RegCloseKey( hkey );
+    }
+}
+
 static void ACTION_GetComponentInstallStates(MSIPACKAGE *package)
 {
     MSICOMPONENT *comp;
@@ -1759,7 +1785,7 @@ static BOOL process_overrides( MSIPACKAGE *package, int level )
     ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED );
 
     if (ret)
-        msi_set_property( package->db, szPreselected, szOne );
+        msi_set_property( package->db, szPreselected, szOne, -1 );
 
     return ret;
 }
@@ -1956,8 +1982,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
             continue;
         }
         TRACE("nobody wants component %s\n", debugstr_w(component->Component));
-        if (component->anyAbsent &&
-            (component->Installed == INSTALLSTATE_LOCAL || component->Installed == INSTALLSTATE_SOURCE))
+        if (component->anyAbsent && component->ComponentId)
         {
             component->Action = INSTALLSTATE_ABSENT;
             component->ActionRequest = INSTALLSTATE_ABSENT;
@@ -1983,6 +2008,11 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
 
         TRACE("component %s (installed %d request %d action %d)\n",
               debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action);
+
+        if (component->Action == INSTALLSTATE_LOCAL || component->Action == INSTALLSTATE_SOURCE)
+            component->num_clients++;
+        else if (component->Action == INSTALLSTATE_ABSENT)
+            component->num_clients--;
     }
 
     return ERROR_SUCCESS;
@@ -2154,7 +2184,7 @@ WCHAR *msi_build_directory_name( DWORD count, ... )
         const WCHAR *str = va_arg( va, const WCHAR * );
         if (!str) continue;
         strcatW( dir, str );
-        if ( i + 1 != count && dir[strlenW( dir ) - 1] != '\\') strcatW( dir, szBackSlash );
+        if ( i + 1 != count && dir[0] && dir[strlenW( dir ) - 1] != '\\') strcatW( dir, szBackSlash );
     }
     va_end( va );
     return dir;
@@ -2281,6 +2311,19 @@ WCHAR *msi_normalize_path( const WCHAR *in )
     return ret;
 }
 
+static WCHAR *get_install_location( MSIPACKAGE *package )
+{
+    HKEY hkey;
+    WCHAR *path;
+
+    if (!package->ProductCode) return NULL;
+    if (MSIREG_OpenInstallProps( package->ProductCode, package->Context, NULL, &hkey, FALSE ))
+        return NULL;
+    path = msi_reg_get_val_str( hkey, szInstallLocation );
+    RegCloseKey( hkey );
+    return path;
+}
+
 void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop )
 {
     FolderList *fl;
@@ -2293,7 +2336,8 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
 
     if (!strcmpW( folder->Directory, szTargetDir )) /* special resolving for target root dir */
     {
-        if (!load_prop || !(path = msi_dup_property( package->db, szTargetDir )))
+        if (!(path = get_install_location( package )) &&
+            (!load_prop || !(path = msi_dup_property( package->db, szTargetDir ))))
         {
             path = msi_dup_property( package->db, szRootDrive );
         }
@@ -2316,7 +2360,7 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
         msi_free( normalized_path );
         return;
     }
-    msi_set_property( package->db, folder->Directory, normalized_path );
+    msi_set_property( package->db, folder->Directory, normalized_path, -1 );
     msi_free( folder->ResolvedTarget );
     folder->ResolvedTarget = normalized_path;
 
@@ -2354,6 +2398,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
         else
             comp->Enabled = TRUE;
     }
+    get_client_counts( package );
 
     /* read components states from the registry */
     ACTION_GetComponentInstallStates(package);
@@ -2376,28 +2421,28 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
     TRACE("Calculating file cost\n");
     calculate_file_cost( package );
 
-    msi_set_property( package->db, szCostingComplete, szOne );
+    msi_set_property( package->db, szCostingComplete, szOne, -1 );
     /* set default run level if not set */
     level = msi_dup_property( package->db, szInstallLevel );
     if (!level)
-        msi_set_property( package->db, szInstallLevel, szOne );
+        msi_set_property( package->db, szInstallLevel, szOne, -1 );
     msi_free(level);
 
     /* FIXME: check volume disk space */
-    msi_set_property( package->db, szOutOfDiskSpace, szZero );
+    msi_set_property( package->db, szOutOfDiskSpace, szZero, -1 );
 
     return MSI_SetFeatureStates(package);
 }
 
-static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, DWORD *size)
+static BYTE *parse_value( MSIPACKAGE *package, const WCHAR *value, DWORD *type, DWORD *size )
 {
-    LPSTR data = NULL;
+    BYTE *data = NULL;
 
     if (!value)
     {
-        data = (LPSTR)strdupW(szEmpty);
-        *size = sizeof(szEmpty);
+        *size = sizeof(WCHAR);
         *type = REG_SZ;
+        if ((data = msi_alloc( *size ))) *(WCHAR *)data = 0;
         return data;
     }
     if (value[0]=='#' && value[1]!='#' && value[1]!='%')
@@ -2479,38 +2524,22 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, DWORD
     }
     else
     {
-        static const WCHAR szMulti[] = {'[','~',']',0};
-        LPCWSTR ptr;
-        *type=REG_SZ;
+        const WCHAR *ptr = value;
+        DWORD len;
 
-        if (value[0]=='#')
+        *type = REG_SZ;
+        if (value[0] == '#')
         {
-            if (value[1]=='%')
+            ptr++;
+            if (value[1] == '%')
             {
-                ptr = &value[2];
-                *type=REG_EXPAND_SZ;
+                ptr++;
+                *type = REG_EXPAND_SZ;
             }
-            else
-                ptr = &value[1];
-         }
-         else
-            ptr=value;
-
-        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 += 2 * sizeof(WCHAR); /* two NULL terminators */
-            data = msi_realloc_zero(data, *size);
         }
+        len = deformat_string( package, ptr, (WCHAR **)&data );
+        if (len > strlenW( (const WCHAR *)data )) *type = REG_MULTI_SZ;
+        *size = (len + 1) * sizeof(WCHAR);
     }
     return data;
 }
@@ -2618,19 +2647,181 @@ static BOOL is_special_entry( const WCHAR *name )
      return (name && (name[0] == '*' || name[0] == '+') && !name[1]);
 }
 
+static WCHAR **split_multi_string_values( const WCHAR *str, DWORD len, DWORD *count )
+{
+    const WCHAR *p = str;
+    WCHAR **ret;
+    int i = 0;
+
+    *count = 0;
+    if (!str) return NULL;
+    while ((p - str) < len)
+    {
+        p += strlenW( p ) + 1;
+        (*count)++;
+    }
+    if (!(ret = msi_alloc( *count * sizeof(WCHAR *) ))) return NULL;
+    p = str;
+    while ((p - str) < len)
+    {
+        if (!(ret[i] = strdupW( p )))
+        {
+            for (; i >= 0; i--) msi_free( ret[i] );
+            msi_free( ret );
+            return NULL;
+        }
+        p += strlenW( p ) + 1;
+        i++;
+    }
+    return ret;
+}
+
+static WCHAR *flatten_multi_string_values( WCHAR **left, DWORD left_count,
+                                           WCHAR **right, DWORD right_count, DWORD *size )
+{
+    WCHAR *ret, *p;
+    unsigned int i;
+
+    *size = sizeof(WCHAR);
+    for (i = 0; i < left_count; i++) *size += (strlenW( left[i] ) + 1) * sizeof(WCHAR);
+    for (i = 0; i < right_count; i++) *size += (strlenW( right[i] ) + 1) * sizeof(WCHAR);
+
+    if (!(ret = p = msi_alloc( *size ))) return NULL;
+
+    for (i = 0; i < left_count; i++)
+    {
+        strcpyW( p, left[i] );
+        p += strlenW( p ) + 1;
+    }
+    for (i = 0; i < right_count; i++)
+    {
+        strcpyW( p, right[i] );
+        p += strlenW( p ) + 1;
+    }
+    *p = 0;
+    return ret;
+}
+
+static DWORD remove_duplicate_values( WCHAR **old, DWORD old_count,
+                                      WCHAR **new, DWORD new_count )
+{
+    DWORD ret = old_count;
+    unsigned int i, j, k;
+
+    for (i = 0; i < new_count; i++)
+    {
+        for (j = 0; j < old_count; j++)
+        {
+            if (old[j] && !strcmpW( new[i], old[j] ))
+            {
+                msi_free( old[j] );
+                for (k = j; k < old_count - 1; k++) { old[k] = old[k + 1]; }
+                old[k] = NULL;
+                ret--;
+            }
+        }
+    }
+    return ret;
+}
+
+enum join_op
+{
+    JOIN_OP_APPEND,
+    JOIN_OP_PREPEND,
+    JOIN_OP_REPLACE
+};
+
+static WCHAR *join_multi_string_values( enum join_op op, WCHAR **old, DWORD old_count,
+                                        WCHAR **new, DWORD new_count, DWORD *size )
+{
+    switch (op)
+    {
+    case JOIN_OP_APPEND:
+        old_count = remove_duplicate_values( old, old_count, new, new_count );
+        return flatten_multi_string_values( old, old_count, new, new_count, size );
+
+    case JOIN_OP_PREPEND:
+        old_count = remove_duplicate_values( old, old_count, new, new_count );
+        return flatten_multi_string_values( new, new_count, old, old_count, size );
+
+    case JOIN_OP_REPLACE:
+        return flatten_multi_string_values( new, new_count, NULL, 0, size );
+
+    default:
+        ERR("unhandled join op %u\n", op);
+        return NULL;
+    }
+}
+
+static BYTE *build_multi_string_value( BYTE *old_value, DWORD old_size,
+                                       BYTE *new_value, DWORD new_size, DWORD *size )
+{
+    DWORD i, old_len = 0, new_len = 0, old_count = 0, new_count = 0;
+    const WCHAR *new_ptr = NULL, *old_ptr = NULL;
+    enum join_op op = JOIN_OP_REPLACE;
+    WCHAR **old = NULL, **new = NULL;
+    BYTE *ret;
+
+    if (new_size / sizeof(WCHAR) - 1 > 1)
+    {
+        new_ptr = (const WCHAR *)new_value;
+        new_len = new_size / sizeof(WCHAR) - 1;
+
+        if (!new_ptr[0] && new_ptr[new_len - 1])
+        {
+            op = JOIN_OP_APPEND;
+            new_len--;
+            new_ptr++;
+        }
+        else if (new_ptr[0] && !new_ptr[new_len - 1])
+        {
+            op = JOIN_OP_PREPEND;
+            new_len--;
+        }
+        else if (new_len > 2 && !new_ptr[0] && !new_ptr[new_len - 1])
+        {
+            op = JOIN_OP_REPLACE;
+            new_len -= 2;
+            new_ptr++;
+        }
+        new = split_multi_string_values( new_ptr, new_len, &new_count );
+    }
+    if (old_size / sizeof(WCHAR) - 1 > 1)
+    {
+        old_ptr = (const WCHAR *)old_value;
+        old_len = old_size / sizeof(WCHAR) - 1;
+        old = split_multi_string_values( old_ptr, old_len, &old_count );
+    }
+    ret = (BYTE *)join_multi_string_values( op, old, old_count, new, new_count, size );
+    for (i = 0; i < old_count; i++) msi_free( old[i] );
+    for (i = 0; i < new_count; i++) msi_free( new[i] );
+    msi_free( old );
+    msi_free( new );
+    return ret;
+}
+
+static BYTE *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type, DWORD *size )
+{
+    BYTE *ret;
+    if (RegQueryValueExW( hkey, name, NULL, NULL, NULL, size )) return NULL;
+    if (!(ret = msi_alloc( *size ))) return NULL;
+    RegQueryValueExW( hkey, name, NULL, type, ret, size );
+    return ret;
+}
+
 static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
-    LPSTR value;
+    BYTE *new_value, *old_value = NULL;
     HKEY  root_key, hkey;
-    DWORD type,size;
+    DWORD type, old_type, new_size, old_size = 0;
     LPWSTR deformated, uikey, keypath;
-    LPCWSTR szRoot, component, name, key;
+    const WCHAR *szRoot, *component, *name, *key, *str;
     MSICOMPONENT *comp;
     MSIRECORD * uirow;
     INT   root;
     BOOL check_first = FALSE;
-    UINT rc;
+    int len;
 
     msi_ui_progress( package, 2, REG_PROGRESS_VALUE, 0, 0 );
 
@@ -2664,8 +2855,7 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
         return ERROR_SUCCESS;
 
     deformat_string(package, key , &deformated);
-    size = strlenW(deformated) + strlenW(szRoot) + 1;
-    uikey = msi_alloc(size*sizeof(WCHAR));
+    uikey = msi_alloc( (strlenW(deformated) + strlenW(szRoot) + 1) * sizeof(WCHAR) );
     strcpyW(uikey,szRoot);
     strcatW(uikey,deformated);
 
@@ -2678,34 +2868,46 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
         msi_free(keypath);
         return ERROR_FUNCTION_FAILED;
     }
-    value = parse_value(package, MSI_RecordGetString(row, 5), &type, &size);
+    str = msi_record_get_string( row, 5, &len );
+    if (str && len > strlenW( str ))
+    {
+        type = REG_MULTI_SZ;
+        new_size = (len + 1) * sizeof(WCHAR);
+        new_value = (BYTE *)msi_strdupW( str, len );
+    }
+    else new_value = parse_value( package, str, &type, &new_size );
     deformat_string(package, name, &deformated);
 
     if (!is_special_entry( name ))
     {
+        old_value = reg_get_value( hkey, deformated, &old_type, &old_size );
+        if (type == REG_MULTI_SZ)
+        {
+            BYTE *new;
+            if (old_value && old_type != REG_MULTI_SZ)
+            {
+                msi_free( old_value );
+                old_value = NULL;
+                old_size = 0;
+            }
+            new = build_multi_string_value( old_value, old_size, new_value, new_size, &new_size );
+            msi_free( new_value );
+            new_value = new;
+        }
         if (!check_first)
         {
-            TRACE("Setting value %s of %s\n", debugstr_w(deformated),
-                  debugstr_w(uikey));
-            RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value, size);
+            TRACE("setting value %s of %s type %u\n", debugstr_w(deformated), debugstr_w(uikey), type);
+            RegSetValueExW( hkey, deformated, 0, type, new_value, new_size );
         }
-        else
+        else if (!old_value)
         {
-            DWORD sz = 0;
-            rc = RegQueryValueExW(hkey, deformated, NULL, NULL, NULL, &sz);
-            if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
+            if (deformated || new_size)
             {
-                TRACE("value %s of %s checked already exists\n", debugstr_w(deformated),
-                      debugstr_w(uikey));
-            }
-            else
-            {
-                TRACE("Checked and setting value %s of %s\n", debugstr_w(deformated),
-                      debugstr_w(uikey));
-                if (deformated || size)
-                    RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value, size);
+                TRACE("setting value %s of %s type %u\n", debugstr_w(deformated), debugstr_w(uikey), type);
+                RegSetValueExW( hkey, deformated, 0, type, new_value, new_size );
             }
         }
+        else TRACE("not overwriting existing value %s of %s\n", debugstr_w(deformated), debugstr_w(uikey));
     }
     RegCloseKey(hkey);
 
@@ -2713,11 +2915,12 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
     MSI_RecordSetStringW(uirow,2,deformated);
     MSI_RecordSetStringW(uirow,1,uikey);
     if (type == REG_SZ || type == REG_EXPAND_SZ)
-        MSI_RecordSetStringW(uirow, 3, (LPWSTR)value);
+        MSI_RecordSetStringW(uirow, 3, (LPWSTR)new_value);
     msi_ui_actiondata( package, szWriteRegistryValues, uirow );
     msiobj_release( &uirow->hdr );
 
-    msi_free(value);
+    msi_free(new_value);
+    msi_free(old_value);
     msi_free(deformated);
     msi_free(uikey);
     msi_free(keypath);
@@ -3293,9 +3496,9 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         if (package->need_rollback) action = comp->Installed;
         else action = comp->ActionRequest;
 
-        TRACE("Component %s (%s), Keypath=%s, RefCount=%u Action=%u\n",
+        TRACE("Component %s (%s) Keypath=%s RefCount=%u Clients=%u Action=%u\n",
                             debugstr_w(comp->Component), debugstr_w(squished_cc),
-                            debugstr_w(comp->FullKeypath), comp->RefCount, action);
+                            debugstr_w(comp->FullKeypath), comp->RefCount, comp->num_clients, action);
 
         if (action == INSTALLSTATE_LOCAL || action == INSTALLSTATE_SOURCE)
         {
@@ -3358,10 +3561,13 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         }
         else if (action == INSTALLSTATE_ABSENT)
         {
-            if (package->Context == MSIINSTALLCONTEXT_MACHINE)
-                MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid);
-            else
-                MSIREG_DeleteUserDataComponentKey(comp->ComponentId, NULL);
+            if (comp->num_clients <= 0)
+            {
+                if (package->Context == MSIINSTALLCONTEXT_MACHINE)
+                    MSIREG_DeleteUserDataComponentKey( comp->ComponentId, szLocalSid );
+                else
+                    MSIREG_DeleteUserDataComponentKey( comp->ComponentId, NULL );
+            }
         }
 
         /* UI stuff */
@@ -4514,27 +4720,27 @@ static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
 
 static void register_dll( const WCHAR *dll, BOOL unregister )
 {
-    HMODULE hmod;
+    static const WCHAR regW[] =
+        {'r','e','g','s','v','r','3','2','.','e','x','e',' ','\"','%','s','\"',0};
+    static const WCHAR unregW[] =
+        {'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','u',' ','\"','%','s','\"',0};
+    PROCESS_INFORMATION pi;
+    STARTUPINFOW si;
+    WCHAR *cmd;
 
-    hmod = LoadLibraryExW( dll, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
-    if (hmod)
-    {
-        HRESULT (WINAPI *func_ptr)( void );
-        const char *func = unregister ? "DllUnregisterServer" : "DllRegisterServer";
+    if (!(cmd = msi_alloc( strlenW(dll) * sizeof(WCHAR) + sizeof(unregW) ))) return;
 
-        func_ptr = (void *)GetProcAddress( hmod, func );
-        if (func_ptr)
-        {
-            HRESULT hr = func_ptr();
-            if (FAILED( hr ))
-                WARN("failed to register dll 0x%08x\n", hr);
-        }
-        else
-            WARN("entry point %s not found\n", func);
-        FreeLibrary( hmod );
-        return;
+    if (unregister) sprintfW( cmd, unregW, dll );
+    else sprintfW( cmd, regW, dll );
+
+    memset( &si, 0, sizeof(STARTUPINFOW) );
+    if (CreateProcessW( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
+    {
+        CloseHandle( pi.hThread );
+        msi_dialog_check_messages( pi.hProcess );
+        CloseHandle( pi.hProcess );
     }
-    WARN("failed to load library %u\n", GetLastError());
+    msi_free( cmd );
 }
 
 static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
@@ -4837,8 +5043,6 @@ static UINT msi_publish_install_properties(MSIPACKAGE *package, HKEY hkey)
         {'H','e','l','p','T','e','l','e','p','h','o','n','e',0};
     static const WCHAR szARPINSTALLLOCATION[] =
         {'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0};
-    static const WCHAR szInstallLocation[] =
-        {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0};
     static const WCHAR szManufacturer[] =
         {'M','a','n','u','f','a','c','t','u','r','e','r',0};
     static const WCHAR szPublisher[] =
@@ -4896,7 +5100,7 @@ static UINT msi_publish_install_properties(MSIPACKAGE *package, HKEY hkey)
     {
         msi_reg_set_val_dword( hkey, szSystemComponent, 1 );
     }
-    size = deformat_string(package, modpath_fmt, &buffer);
+    size = deformat_string(package, modpath_fmt, &buffer) * sizeof(WCHAR);
     RegSetValueExW(hkey, szModifyPath, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size);
     RegSetValueExW(hkey, szUninstallString, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size);
     msi_free(buffer);
@@ -5548,6 +5752,7 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
     LPWSTR depends = NULL, pass = NULL, args = NULL, image_path = NULL;
     DWORD serv_type, start_type, err_control;
     SERVICE_DESCRIPTIONW sd = {NULL};
+    UINT ret = ERROR_SUCCESS;
 
     comp = MSI_RecordGetString( rec, 12 );
     component = msi_get_loaded_component( package, comp );
@@ -5605,7 +5810,10 @@ static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
     {
         int len = strlenW(file->TargetPath) + strlenW(args) + 2;
         if (!(image_path = msi_alloc(len * sizeof(WCHAR))))
-            return ERROR_OUTOFMEMORY;
+        {
+            ret = ERROR_OUTOFMEMORY;
+            goto done;
+        }
 
         strcpyW(image_path, file->TargetPath);
         strcatW(image_path, szSpace);
@@ -5639,7 +5847,7 @@ done:
     msi_free(depends);
     msi_free(args);
 
-    return ERROR_SUCCESS;
+    return ret;
 }
 
 static UINT ACTION_InstallServices( MSIPACKAGE *package )
@@ -5839,6 +6047,7 @@ static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service)
     ENUM_SERVICE_STATUSW *dependencies;
     SERVICE_STATUS ss;
     SC_HANDLE depserv;
+    BOOL stopped, ret = FALSE;
 
     if (EnumDependentServicesW(service, SERVICE_ACTIVE, NULL,
                                0, &needed, &count))
@@ -5853,24 +6062,26 @@ static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service)
 
     if (!EnumDependentServicesW(service, SERVICE_ACTIVE, dependencies,
                                 needed, &needed, &count))
-        goto error;
+        goto done;
 
     for (i = 0; i < count; i++)
     {
         depserv = OpenServiceW(scm, dependencies[i].lpServiceName,
                                SERVICE_STOP | SERVICE_QUERY_STATUS);
         if (!depserv)
-            goto error;
+            goto done;
 
-        if (!ControlService(depserv, SERVICE_CONTROL_STOP, &ss))
-            goto error;
+        stopped = ControlService(depserv, SERVICE_CONTROL_STOP, &ss);
+        CloseServiceHandle(depserv);
+        if (!stopped)
+            goto done;
     }
 
-    return TRUE;
+    ret = TRUE;
 
-error:
+done:
     msi_free(dependencies);
-    return FALSE;
+    return ret;
 }
 
 static UINT stop_service( LPCWSTR name )
@@ -6959,7 +7170,7 @@ UINT msi_validate_product_id( MSIPACKAGE *package )
     if (key && template)
     {
         FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) );
-        r = msi_set_property( package->db, szProductID, key );
+        r = msi_set_property( package->db, szProductID, key, -1 );
     }
     msi_free( template );
     msi_free( key );
@@ -6999,7 +7210,7 @@ static UINT ACTION_DisableRollback( MSIPACKAGE *package )
 {
     TRACE("%p\n", package);
 
-    msi_set_property( package->db, szRollbackDisabled, szOne );
+    msi_set_property( package->db, szRollbackDisabled, szOne, -1 );
     return ERROR_SUCCESS;
 }
 
@@ -7516,11 +7727,11 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
     static const WCHAR szDisableRollback[] = {'D','I','S','A','B','L','E','R','O','L','L','B','A','C','K',0};
     static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
     static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
-    WCHAR *reinstall = NULL;
+    WCHAR *reinstall, *remove, *patch;
     BOOL ui_exists;
     UINT rc;
 
-    msi_set_property( package->db, szAction, szInstall );
+    msi_set_property( package->db, szAction, szInstall, -1 );
 
     package->script->InWhatSequence = SEQUENCE_INSTALL;
 
@@ -7567,10 +7778,13 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
     msi_apply_transforms( package );
     msi_apply_patches( package );
 
-    if (!szCommandLine && msi_get_property_int( package->db, szInstalled, 0 ))
+    patch = msi_dup_property( package->db, szPatch );
+    remove = msi_dup_property( package->db, szRemove );
+    reinstall = msi_dup_property( package->db, szReinstall );
+    if (msi_get_property_int( package->db, szInstalled, 0 ) && !remove && !reinstall && !patch)
     {
-        TRACE("setting reinstall property\n");
-        msi_set_property( package->db, szReinstall, szAll );
+        TRACE("setting REINSTALL property to ALL\n");
+        msi_set_property( package->db, szReinstall, szAll, -1 );
     }
 
     /* properties may have been added by a transform */
@@ -7583,7 +7797,7 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
     if (msi_get_property_int( package->db, szDisableRollback, 0 ))
     {
         TRACE("disabling rollback\n");
-        msi_set_property( package->db, szRollbackDisabled, szOne );
+        msi_set_property( package->db, szRollbackDisabled, szOne, -1 );
     }
 
     if (needs_ui_sequence( package))
@@ -7621,12 +7835,14 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
     /* finish up running custom actions */
     ACTION_FinishCustomActions(package);
 
-    if (package->need_rollback && !(reinstall = msi_dup_property( package->db, szReinstall )))
+    if (package->need_rollback && !reinstall)
     {
         WARN("installation failed, running rollback script\n");
         execute_script( package, SCRIPT_ROLLBACK );
     }
     msi_free( reinstall );
+    msi_free( remove );
+    msi_free( patch );
 
     if (rc == ERROR_SUCCESS && package->need_reboot_at_end)
         return ERROR_SUCCESS_REBOOT_REQUIRED;
index 21daf43..0d9c302 100644 (file)
@@ -1093,7 +1093,7 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
     r = ACTION_AppSearchSigName(package, sigName, &sig, &value);
     if (value)
     {
-        r = msi_set_property( package->db, propName, value );
+        r = msi_set_property( package->db, propName, value, -1 );
         if (r == ERROR_SUCCESS && !strcmpW( propName, szSourceDir ))
             msi_reset_folders( package, TRUE );
 
@@ -1153,7 +1153,7 @@ static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
     if (value)
     {
         TRACE("Found signature %s\n", debugstr_w(signature));
-        msi_set_property(package->db, success, szOne);
+        msi_set_property( package->db, success, szOne, -1 );
         msi_free(value);
         r = ERROR_NO_MORE_ITEMS;
     }
index e55717a..8164463 100644 (file)
@@ -42,36 +42,116 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
 #define REG_INDEX_CLASSES_ROOT 0
 #define REG_INDEX_DYN_DATA 6
 
-/*
- * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
- *                    called from AutomationObject::Invoke.
- */
-
 typedef struct AutomationObject AutomationObject;
 
-typedef HRESULT (*autoInvokeFunc)(AutomationObject* This,
+/* function that is called from AutomationObject::Invoke, specific to this type of object */
+typedef HRESULT (*auto_invoke_func)(AutomationObject* This,
     DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams,
     VARIANT* result, EXCEPINFO* ei, UINT* arg_err);
+/* function that is called from AutomationObject::Release when the object is being freed
+   to free any private data structures (or NULL) */
+typedef void (*auto_free_func)(AutomationObject* This);
+
+typedef struct {
+    REFIID riid;
+    auto_invoke_func fn_invoke;
+    auto_free_func fn_free;
+} tid_id_t;
+
+
+static HRESULT database_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+static HRESULT installer_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+static HRESULT record_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+static HRESULT session_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+static HRESULT list_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+static void    list_free(AutomationObject*);
+static HRESULT summaryinfo_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+static HRESULT view_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+
+static tid_id_t tid_ids[] = {
+    { &DIID_Database,    database_invoke },
+    { &DIID_Installer,   installer_invoke },
+    { &DIID_Record,      record_invoke },
+    { &DIID_Session,     session_invoke },
+    { &DIID_StringList,  list_invoke, list_free },
+    { &DIID_SummaryInfo, summaryinfo_invoke },
+    { &DIID_View,        view_invoke }
+};
+
+static ITypeLib  *typelib;
+static ITypeInfo *typeinfos[LAST_tid];
+
+static const IID *get_riid_from_tid(tid_t tid)
+{
+    return tid_ids[tid].riid;
+}
+
+HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
+{
+    HRESULT hr;
+
+    if (!typelib)
+    {
+        ITypeLib *lib;
+
+        hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, LOCALE_NEUTRAL, &lib);
+        if (FAILED(hr)) {
+            static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
+            hr = LoadTypeLib(msiserverW, &lib);
+            if (FAILED(hr)) {
+                ERR("Could not load msiserver.tlb\n");
+                return hr;
+            }
+        }
+
+        if (InterlockedCompareExchangePointer((void**)&typelib, lib, NULL))
+            ITypeLib_Release(lib);
+    }
+
+    if (!typeinfos[tid])
+    {
+        ITypeInfo *ti;
+
+        hr = ITypeLib_GetTypeInfoOfGuid(typelib, get_riid_from_tid(tid), &ti);
+        if (FAILED(hr)) {
+            ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid)));
+            return hr;
+        }
+
+        if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
+            ITypeInfo_Release(ti);
+    }
+
+    *typeinfo = typeinfos[tid];
+    return S_OK;
+}
+
+void release_typelib(void)
+{
+    unsigned i;
 
-typedef void (*autoFreeFunc)(AutomationObject* This);
+    for (i = 0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
+        if (typeinfos[i])
+            ITypeInfo_Release(typeinfos[i]);
 
+    if (typelib)
+        ITypeLib_Release(typelib);
+}
+
+/*
+ * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
+ *                    called from AutomationObject::Invoke.
+ */
 struct AutomationObject {
     IDispatch IDispatch_iface;
     IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
     LONG ref;
 
-    /* Clsid for this class and it's appropriate ITypeInfo object */
-    LPCLSID clsid;
-    ITypeInfo *iTypeInfo;
+    /* type id for this class */
+    tid_t tid;
 
     /* The MSI handle of the current object */
     MSIHANDLE msiHandle;
-
-    /* A function that is called from AutomationObject::Invoke, specific to this type of object. */
-    autoInvokeFunc funcInvoke;
-    /* A function that is called from AutomationObject::Release when the object is being freed to free any private
-     * data structures (or NULL) */
-    autoFreeFunc funcFree;
 };
 
 typedef struct {
@@ -110,37 +190,6 @@ static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
     return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface);
 }
 
-/* Load type info so we don't have to process GetIDsOfNames */
-HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid)
-{
-    static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
-    ITypeInfo *ti = NULL;
-    ITypeLib *lib = NULL;
-    HRESULT hr;
-
-    TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid);
-
-    /* Load registered type library */
-    hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib);
-    if (FAILED(hr)) {
-        hr = LoadTypeLib(msiserverW, &lib);
-        if (FAILED(hr)) {
-            ERR("Could not load msiserver.tlb\n");
-            return hr;
-        }
-    }
-
-    /* Get type information for object */
-    hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti);
-    ITypeLib_Release(lib);
-    if (FAILED(hr)) {
-        ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid));
-        return hr;
-    }
-    *pptinfo = ti;
-    return S_OK;
-}
-
 /* AutomationObject methods */
 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
 {
@@ -155,7 +204,7 @@ static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID r
 
     if (IsEqualGUID(riid, &IID_IUnknown)  ||
         IsEqualGUID(riid, &IID_IDispatch) ||
-        IsEqualGUID(riid, This->clsid))
+        IsEqualGUID(riid, get_riid_from_tid(This->tid)))
         *ppvObject = &This->IDispatch_iface;
     else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
              IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
@@ -190,8 +239,7 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
 
     if (!ref)
     {
-        if (This->funcFree) This->funcFree(This);
-        ITypeInfo_Release(This->iTypeInfo);
+        if (tid_ids[This->tid].fn_free) tid_ids[This->tid].fn_free(This);
         MsiCloseHandle(This->msiHandle);
         msi_free(This);
     }
@@ -217,11 +265,16 @@ static HRESULT WINAPI AutomationObject_GetTypeInfo(
         ITypeInfo** ppTInfo)
 {
     AutomationObject *This = impl_from_IDispatch(iface);
+    HRESULT hr;
+
     TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
 
-    ITypeInfo_AddRef(This->iTypeInfo);
-    *ppTInfo = This->iTypeInfo;
-    return S_OK;
+    hr = get_typeinfo(This->tid, ppTInfo);
+    if (FAILED(hr))
+        return hr;
+
+    ITypeInfo_AddRef(*ppTInfo);
+    return hr;
 }
 
 static HRESULT WINAPI AutomationObject_GetIDsOfNames(
@@ -233,18 +286,25 @@ static HRESULT WINAPI AutomationObject_GetIDsOfNames(
         DISPID* rgDispId)
 {
     AutomationObject *This = impl_from_IDispatch(iface);
+    ITypeInfo *ti;
     HRESULT hr;
+
     TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId);
 
     if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
-    hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
+
+    hr = get_typeinfo(This->tid, &ti);
+    if (FAILED(hr))
+        return hr;
+
+    hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
     if (hr == DISP_E_UNKNOWNNAME)
     {
         UINT idx;
         for (idx=0; idx<cNames; idx++)
         {
             if (rgDispId[idx] == DISPID_UNKNOWN)
-                FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(This->clsid));
+                FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(get_riid_from_tid(This->tid)));
         }
     }
     return hr;
@@ -270,6 +330,7 @@ static HRESULT WINAPI AutomationObject_Invoke(
     unsigned int uArgErr;
     VARIANT varResultDummy;
     BSTR bstrName = NULL;
+    ITypeInfo *ti;
 
     TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
 
@@ -289,21 +350,26 @@ static HRESULT WINAPI AutomationObject_Invoke(
     if (puArgErr == NULL) puArgErr = &uArgErr;
     if (pVarResult == NULL) pVarResult = &varResultDummy;
 
+    hr = get_typeinfo(This->tid, &ti);
+    if (FAILED(hr))
+        return hr;
+
     /* Assume return type is void unless determined otherwise */
     VariantInit(pVarResult);
 
     /* If we are tracing, we want to see the name of the member we are invoking */
     if (TRACE_ON(msi))
     {
-        ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
+        ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
         TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName));
     }
 
-    hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
+    hr = tid_ids[This->tid].fn_invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
 
     if (hr == DISP_E_MEMBERNOTFOUND) {
-        if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
-        FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid));
+        if (bstrName == NULL) ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
+        FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags,
+            debugstr_guid(get_riid_from_tid(This->tid)));
     }
     else if (pExcepInfo &&
              (hr == DISP_E_PARAMNOTFOUND ||
@@ -315,7 +381,7 @@ static HRESULT WINAPI AutomationObject_Invoke(
         unsigned namesNo, i;
         BOOL bFirst = TRUE;
 
-        if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames,
+        if (FAILED(ITypeInfo_GetNames(ti, dispIdMember, bstrParamNames,
                                       MAX_FUNC_PARAMS, &namesNo)))
         {
             TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember);
@@ -391,8 +457,15 @@ static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo*
 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
 {
     AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
+    HRESULT hr;
+
     TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
-    return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0);
+
+    hr = get_typeinfo(This->tid, ppTI);
+    if (SUCCEEDED(hr))
+        ITypeInfo_AddRef(*ppTI);
+
+    return hr;
 }
 
 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
@@ -403,7 +476,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
     if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
         return E_INVALIDARG;
     else {
-        *pGUID = *This->clsid;
+        *pGUID = *get_riid_from_tid(This->tid);
         return S_OK;
     }
 }
@@ -420,7 +493,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMul
 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
         ULONG iti,
         DWORD dwFlags,
-        ITypeInfo** pptiCoClass,
+        ITypeInfo** ti,
         DWORD* pdwTIFlags,
         ULONG* pcdispidReserved,
         IID* piidPrimary,
@@ -428,13 +501,19 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl
 {
     AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
 
-    TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
+    TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, ti, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
 
     if (iti != 0)
         return E_INVALIDARG;
 
     if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
-        load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0);
+    {
+        HRESULT hr = get_typeinfo(This->tid, ti);
+        if (FAILED(hr))
+            return hr;
+
+        ITypeInfo_AddRef(*ti);
+    }
 
     if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
     {
@@ -442,13 +521,11 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl
         *pcdispidReserved = 0;
     }
 
-    if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){
-        *piidPrimary = *This->clsid;
-    }
+    if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY)
+        *piidPrimary = *get_riid_from_tid(This->tid);
 
-    if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){
-        *piidSource = *This->clsid;
-    }
+    if (dwFlags & MULTICLASSINFO_GETIIDSOURCE)
+        *piidSource = *get_riid_from_tid(This->tid);
 
     return S_OK;
 }
@@ -464,23 +541,18 @@ static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
     ProvideMultipleClassInfo_GetInfoOfIndex
 };
 
-static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid,
-        autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
+static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, tid_t tid)
 {
-    TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc);
+    TRACE("(%p, %d, %s)\n", This, msiHandle, debugstr_guid(get_riid_from_tid(tid)));
 
     This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
     This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
     This->ref = 1;
 
     This->msiHandle = msiHandle;
-    This->clsid = (LPCLSID)clsid;
-    This->funcInvoke = invokeFunc;
-    This->funcFree   = freeFunc;
+    This->tid = tid;
 
-    /* Load our TypeInfo so we don't have to process GetIDsOfNames */
-    This->iTypeInfo = NULL;
-    return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0);
+    return S_OK;
 }
 
 /*
@@ -682,7 +754,7 @@ static HRESULT DispGetParam_CopyOnly(
                         &pdispparams->rgvarg[pos]);
 }
 
-static HRESULT SummaryInfoImpl_Invoke(
+static HRESULT summaryinfo_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -834,7 +906,7 @@ static HRESULT SummaryInfoImpl_Invoke(
     return S_OK;
 }
 
-static HRESULT RecordImpl_Invoke(
+static HRESULT record_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -846,7 +918,7 @@ static HRESULT RecordImpl_Invoke(
         UINT* puArgErr)
 {
     WCHAR *szString;
-    DWORD dwLen;
+    DWORD dwLen = 0;
     UINT ret;
     VARIANTARG varg0, varg1;
     HRESULT hr;
@@ -933,7 +1005,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
     record = msi_alloc(sizeof(*record));
     if (!record) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL);
+    hr = init_automation_object(record, msiHandle, Record_tid);
     if (hr != S_OK)
     {
         msi_free(record);
@@ -945,7 +1017,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
     return hr;
 }
 
-static HRESULT ListImpl_Invoke(
+static HRESULT list_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -1002,7 +1074,7 @@ static HRESULT ListImpl_Invoke(
     return S_OK;
 }
 
-static void ListImpl_Free(AutomationObject *This)
+static void list_free(AutomationObject *This)
 {
     ListObject *list = (ListObject*)This;
     int i;
@@ -1049,7 +1121,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
     list = msi_alloc_zero(sizeof(ListObject));
     if (!list) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free);
+    hr = init_automation_object(&list->autoobj, 0, StringList_tid);
     if (hr != S_OK)
     {
         msi_free(list);
@@ -1092,7 +1164,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
     return S_OK;
 }
 
-static HRESULT ViewImpl_Invoke(
+static HRESULT view_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -1200,7 +1272,7 @@ static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
     return S_OK;
 }
 
-static HRESULT DatabaseImpl_Invoke(
+HRESULT database_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -1285,7 +1357,7 @@ static HRESULT DatabaseImpl_Invoke(
     return S_OK;
 }
 
-static HRESULT SessionImpl_Invoke(
+static HRESULT session_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -2250,7 +2322,7 @@ static HRESULT InstallerImpl_RelatedProducts(WORD flags,
     return hr;
 }
 
-static HRESULT InstallerImpl_Invoke(
+static HRESULT installer_invoke(
         AutomationObject* This,
         DISPID dispIdMember,
         REFIID riid,
@@ -2363,7 +2435,7 @@ HRESULT create_msiserver(IUnknown *outer, void **ppObj)
     installer = msi_alloc(sizeof(AutomationObject));
     if (!installer) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL);
+    hr = init_automation_object(installer, 0, Installer_tid);
     if (hr != S_OK)
     {
         msi_free(installer);
@@ -2383,7 +2455,7 @@ HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **di
     session = msi_alloc(sizeof(SessionObject));
     if (!session) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL);
+    hr = init_automation_object(&session->autoobj, msiHandle, Session_tid);
     if (hr != S_OK)
     {
         msi_free(session);
@@ -2406,7 +2478,7 @@ static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
     database = msi_alloc(sizeof(AutomationObject));
     if (!database) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL);
+    hr = init_automation_object(database, msiHandle, Database_tid);
     if (hr != S_OK)
     {
         msi_free(database);
@@ -2428,7 +2500,7 @@ static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
     view = msi_alloc(sizeof(AutomationObject));
     if (!view) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL);
+    hr = init_automation_object(view, msiHandle, View_tid);
     if (hr != S_OK)
     {
         msi_free(view);
@@ -2448,7 +2520,7 @@ static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
     info = msi_alloc(sizeof(*info));
     if (!info) return E_OUTOFMEMORY;
 
-    hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL);
+    hr = init_automation_object(info, msiHandle, SummaryInfo_tid);
     if (hr != S_OK)
     {
         msi_free(info);
index 8f32e59..a33f19d 100644 (file)
@@ -184,25 +184,21 @@ static LPWSTR msi_get_deferred_action(LPCWSTR action, LPCWSTR actiondata,
     return deferred;
 }
 
-static void set_deferred_action_props(MSIPACKAGE *package, LPWSTR deferred_data)
+static void set_deferred_action_props( MSIPACKAGE *package, const WCHAR *deferred_data )
 {
-    LPWSTR end, beg = deferred_data + 1;
-
     static const WCHAR sep[] = {'<','=','>',0};
+    const WCHAR *end, *beg = deferred_data + 1;
 
     end = strstrW(beg, sep);
-    *end = '\0';
-    msi_set_property(package->db, szCustomActionData, beg);
+    msi_set_property( package->db, szCustomActionData, beg, end - beg );
     beg = end + 3;
 
     end = strstrW(beg, sep);
-    *end = '\0';
-    msi_set_property(package->db, szUserSID, beg);
+    msi_set_property( package->db, szUserSID, beg, end - beg );
     beg = end + 3;
 
     end = strchrW(beg, ']');
-    *end = '\0';
-    msi_set_property(package->db, szProductCode, beg);
+    msi_set_property( package->db, szProductCode, beg, end - beg );
 }
 
 static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll )
@@ -1229,23 +1225,20 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
     UINT rc = ERROR_SUCCESS;
     MSIRECORD *row;
     UINT type;
-    LPCWSTR source, target;
-    LPWSTR ptr, deferred_data = NULL;
-    LPWSTR deformated = NULL, action_copy = strdupW(action);
+    const WCHAR *source, *target, *ptr, *deferred_data = NULL;
+    WCHAR *deformated = NULL;
+    int len;
 
     /* deferred action: [properties]Action */
-    if ((ptr = strrchrW(action_copy, ']')))
+    if ((ptr = strrchrW(action, ']')))
     {
-        deferred_data = action_copy;
+        deferred_data = action;
         action = ptr + 1;
     }
 
     row = MSI_QueryGetRecord( package->db, query, action );
     if (!row)
-    {
-        msi_free(action_copy);
         return ERROR_CALL_NOT_IMPLEMENTED;
-    }
 
     type = MSI_RecordGetInteger(row,2);
     source = MSI_RecordGetString(row,3);
@@ -1284,9 +1277,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
             if (deferred_data)
                 set_deferred_action_props(package, deferred_data);
             else if (actiondata)
-                msi_set_property(package->db, szCustomActionData, actiondata);
+                msi_set_property( package->db, szCustomActionData, actiondata, -1 );
             else
-                msi_set_property(package->db, szCustomActionData, szEmpty);
+                msi_set_property( package->db, szCustomActionData, szEmpty, -1 );
 
             msi_free(actiondata);
         }
@@ -1334,8 +1327,8 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
             if (!source)
                 break;
 
-            deformat_string(package,target,&deformated);
-            rc = msi_set_property( package->db, source, deformated );
+            len = deformat_string( package, target, &deformated );
+            rc = msi_set_property( package->db, source, deformated, len );
             if (rc == ERROR_SUCCESS && !strcmpW( source, szSourceDir ))
                 msi_reset_folders( package, TRUE );
             msi_free(deformated);
@@ -1365,7 +1358,6 @@ end:
     package->scheduled_action_running = FALSE;
     package->commit_action_running = FALSE;
     package->rollback_action_running = FALSE;
-    msi_free(action_copy);
     msiobj_release(&row->hdr);
     return rc;
 }
index 944cf8f..9c0d346 100644 (file)
@@ -130,7 +130,7 @@ UINT msi_clone_open_stream( MSIDATABASE *db, IStorage *stg, LPCWSTR name, IStrea
 UINT msi_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
 {
     HRESULT r;
-    IStorage *stg = 0;
+    IStorage *stg;
     WCHAR decoded[MAX_STREAM_NAME_LEN];
 
     decode_streamname( stname, decoded );
index 66d8786..c0ff204 100644 (file)
@@ -309,7 +309,7 @@ static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
 
     /* create a font and add it to the list */
     name = MSI_RecordGetString( rec, 1 );
-    font = msi_alloc( sizeof *font + strlenW( name )*sizeof (WCHAR) );
+    font = msi_alloc( FIELD_OFFSET( msi_font, name[strlenW( name ) + 1] ));
     strcpyW( font->name, name );
     list_add_head( &dialog->fonts, &font->entry );
 
@@ -414,7 +414,7 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
 
     style |= WS_CHILD;
 
-    control = msi_alloc( sizeof *control + strlenW(name)*sizeof(WCHAR) );
+    control = msi_alloc( FIELD_OFFSET( msi_control, name[strlenW( name ) + 1] ));
     if (!control)
         return NULL;
 
@@ -583,7 +583,7 @@ static void msi_dialog_update_controls( msi_dialog *dialog, LPCWSTR property )
 
 static void msi_dialog_set_property( MSIPACKAGE *package, LPCWSTR property, LPCWSTR value )
 {
-    UINT r = msi_set_property( package->db, property, value );
+    UINT r = msi_set_property( package->db, property, value, -1 );
     if (r == ERROR_SUCCESS && !strcmpW( property, szSourceDir ))
         msi_reset_folders( package, TRUE );
 }
@@ -3939,7 +3939,7 @@ static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event,
     if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) ||
          !strcmpW( argument, error_no ) )
     {
-         msi_set_property( package->db, result_prop, error_abort );
+         msi_set_property( package->db, result_prop, error_abort, -1 );
     }
 
     ControlEvent_CleanupSubscriptions(package);
index d42ac5b..707a4a2 100644 (file)
@@ -173,7 +173,7 @@ static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_di
         if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
         {
             if (feature->ActionRequest != INSTALLSTATE_LOCAL)
-                msi_set_property( package->db, szPreselected, szOne );
+                msi_set_property( package->db, szPreselected, szOne, -1 );
             MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_LOCAL );
         }
     }
@@ -189,7 +189,7 @@ static UINT ControlEvent_Remove( MSIPACKAGE *package, LPCWSTR argument, msi_dial
         if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
         {
             if (feature->ActionRequest != INSTALLSTATE_ABSENT)
-                msi_set_property( package->db, szPreselected, szOne );
+                msi_set_property( package->db, szPreselected, szOne, -1 );
             MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_ABSENT );
         }
     }
@@ -205,7 +205,7 @@ static UINT ControlEvent_AddSource( MSIPACKAGE *package, LPCWSTR argument, msi_d
         if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
         {
             if (feature->ActionRequest != INSTALLSTATE_SOURCE)
-                msi_set_property( package->db, szPreselected, szOne );
+                msi_set_property( package->db, szPreselected, szOne, -1 );
             MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_SOURCE );
         }
     }
@@ -377,13 +377,13 @@ static UINT ControlEvent_DirectoryListUp(MSIPACKAGE *package, LPCWSTR argument,
 static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument,
                                        msi_dialog *dialog)
 {
-    return msi_set_property( package->db, szReinstallMode, argument );
+    return msi_set_property( package->db, szReinstallMode, argument, -1 );
 }
 
 static UINT ControlEvent_Reinstall( MSIPACKAGE *package, LPCWSTR argument,
                                     msi_dialog *dialog )
 {
-    return msi_set_property( package->db, szReinstall, argument );
+    return msi_set_property( package->db, szReinstall, argument, -1 );
 }
 
 static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,
index 11913ef..7202fb6 100644 (file)
@@ -69,7 +69,6 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil
     VS_FIXEDFILEINFO *file_version;
     WCHAR *font_version;
     msi_file_state state;
-    DWORD file_size;
 
     comp->Action = msi_get_component_action( package, comp );
     if (comp->Action != INSTALLSTATE_LOCAL || (comp->assembly && comp->assembly->installed))
@@ -118,7 +117,7 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil
             return state;
         }
     }
-    if ((file_size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize)
+    if (msi_get_disk_file_size( file->TargetPath ) != file->FileSize)
     {
         return msifs_overwrite;
     }
@@ -336,7 +335,8 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
         if (rc != ERROR_SUCCESS)
         {
             ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
-            return ERROR_FUNCTION_FAILED;
+            rc = ERROR_FUNCTION_FAILED;
+            goto done;
         }
         if (!file->Component->Enabled) continue;
 
@@ -513,7 +513,8 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
         if (rc != ERROR_SUCCESS)
         {
             ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
-            return ERROR_FUNCTION_FAILED;
+            rc = ERROR_FUNCTION_FAILED;
+            goto done;
         }
         comp->Action = msi_get_component_action( package, comp );
         if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue;
@@ -779,7 +780,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
     LPWSTR sourcedir, destname = NULL, destdir = NULL, source = NULL, dest = NULL;
     int options;
     DWORD size;
-    BOOL ret, wildcards;
+    BOOL wildcards;
 
     component = MSI_RecordGetString(rec, 2);
     comp = msi_get_loaded_component(package, component);
@@ -861,7 +862,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
 
     if (GetFileAttributesW(destdir) == INVALID_FILE_ATTRIBUTES)
     {
-        if (!(ret = msi_create_full_path(destdir)))
+        if (!msi_create_full_path(destdir))
         {
             WARN("failed to create directory %u\n", GetLastError());
             goto done;
index 8188f13..756c4d1 100644 (file)
@@ -140,130 +140,146 @@ static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str)
     return &format->deformatted[str->n];
 }
 
-static LPWSTR dup_formstr(FORMAT *format, FORMSTR *str)
+static WCHAR *dup_formstr( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR val;
-    LPCWSTR data;
-
-    if (str->len == 0)
-        return NULL;
-
-    val = msi_alloc((str->len + 1) * sizeof(WCHAR));
-    data = get_formstr_data(format, str);
-    lstrcpynW(val, data, str->len + 1);
+    WCHAR *val;
 
+    if (!str->len) return NULL;
+    if ((val = msi_alloc( (str->len + 1) * sizeof(WCHAR) )))
+    {
+        memcpy( val, get_formstr_data(format, str), str->len * sizeof(WCHAR) );
+        val[str->len] = 0;
+        *ret_len = str->len;
+    }
     return val;
 }
 
-static LPWSTR deformat_index(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_index( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR val, ret;
+    WCHAR *val, *ret;
+    DWORD len;
+    int field;
 
-    val = msi_alloc((str->len + 1) * sizeof(WCHAR));
+    if (!(val = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
     lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
+    field = atoiW( val );
+    msi_free( val );
 
-    ret = msi_dup_record_field(format->record, atoiW(val));
+    if (MSI_RecordIsNull( format->record, field ) ||
+        MSI_RecordGetStringW( format->record, field, NULL, &len )) return NULL;
 
-    msi_free(val);
+    len++;
+    if (!(ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL;
+    ret[0] = 0;
+    if (MSI_RecordGetStringW( format->record, field, ret, &len ))
+    {
+        msi_free( ret );
+        return NULL;
+    }
+    *ret_len = len;
     return ret;
 }
 
-static LPWSTR deformat_property(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_property( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR val, ret;
-
-    val = msi_alloc((str->len + 1) * sizeof(WCHAR));
-    lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
+    WCHAR *prop, *ret;
+    DWORD len = 0;
+    UINT r;
 
-    ret = msi_dup_property(format->package->db, val);
+    if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
+    lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 );
 
-    msi_free(val);
+    r = msi_get_property( format->package->db, prop, NULL, &len );
+    if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
+    {
+        msi_free( prop );
+        return NULL;
+    }
+    len++;
+    if ((ret = msi_alloc( len * sizeof(WCHAR) )))
+        msi_get_property( format->package->db, prop, ret, &len );
+    msi_free( prop );
+    *ret_len = len;
     return ret;
 }
 
-static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
+static WCHAR *deformat_component( FORMAT *format, FORMSTR *str, int *ret_len )
 {
-    LPWSTR key, ret = NULL;
+    WCHAR *key, *ret;
     MSICOMPONENT *comp;
 
-    key = msi_alloc((str->len + 1) * sizeof(WCHAR));
+    if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
     lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
 
-    comp = msi_get_loaded_component(format->package, key);
-    if (!comp)
-        goto done;
-
+    if (!(comp = msi_get_loaded_component( format->package, key )))
+    {
+        msi_free( key );
+        return NULL;
+    }
     if (comp->Action == INSTALLSTATE_SOURCE)
         ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
     else
         ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
 
-done:
-    msi_free(key);
+    if (ret) *ret_len = strlenW( ret );
+    else *ret_len = 0;
+    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);
+        if ((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);
+        if ((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 +293,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 +314,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 +505,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 +515,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 +542,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 +559,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 +569,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 +578,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 +638,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 +648,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 +683,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 +695,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 +870,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 +900,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;
 }
 
@@ -934,7 +935,7 @@ UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord,
 
             wstr.unicode = TRUE;
             wstr.str.w = szResult;
-            r = msi_strcpy_to_awstring( value, &wstr, sz );
+            r = msi_strcpy_to_awstring( value, SysStringLen(value), &wstr, sz );
 
 done:
             IWineMsiRemotePackage_Release( remote_package );
@@ -1022,24 +1023,23 @@ done:
 }
 
 /* wrapper to resist a need for a full rewrite right now */
-DWORD deformat_string( MSIPACKAGE *package, const WCHAR *ptr, WCHAR **data )
+DWORD deformat_string( MSIPACKAGE *package, const WCHAR *fmt, WCHAR **data )
 {
-    if (ptr)
-    {
-        DWORD size = 0;
-        MSIRECORD *rec = MSI_CreateRecord( 1 );
-
-        MSI_RecordSetStringW( rec, 0, ptr );
-        MSI_FormatRecordW( package, rec, NULL, &size );
+    DWORD len;
+    MSIRECORD *rec;
 
-        size++;
-        *data = msi_alloc( size * sizeof(WCHAR) );
-        if (size > 1) MSI_FormatRecordW( package, rec, *data, &size );
-        else *data[0] = 0;
+    *data = NULL;
+    if (!fmt) return 0;
+    if (!(rec = MSI_CreateRecord( 1 ))) return 0;
 
+    MSI_RecordSetStringW( rec, 0, fmt );
+    MSI_FormatRecordW( package, rec, NULL, &len );
+    if (!(*data = msi_alloc( ++len * sizeof(WCHAR) )))
+    {
         msiobj_release( &rec->hdr );
-        return size * sizeof(WCHAR);
+        return 0;
     }
-    *data = NULL;
-    return 0;
+    MSI_FormatRecordW( package, rec, *data, &len );
+    msiobj_release( &rec->hdr );
+    return len;
 }
index a6c832a..5810a1e 100644 (file)
@@ -178,32 +178,28 @@ UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode
     return ret;
 }
 
-UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
+UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz )
 {
-    UINT len, r = ERROR_SUCCESS;
+    UINT r = ERROR_SUCCESS;
 
-    if (awbuf->str.w && !sz )
+    if (awbuf->str.w && !sz)
         return ERROR_INVALID_PARAMETER;
-
     if (!sz)
-        return r;
+        return ERROR_SUCCESS;
+
+    if (len < 0) len = strlenW( str );
  
-    if (awbuf->unicode)
-    {
-        len = lstrlenW( str );
-        if (awbuf->str.w) 
-            lstrcpynW( awbuf->str.w, str, *sz );
-    }
+    if (awbuf->unicode && awbuf->str.w)
+        memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
     else
     {
-        len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
-        if (len)
-            len--;
-        WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
-        if ( awbuf->str.a && *sz && (len >= *sz) )
+        int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL );
+        if (lenA) lenA--;
+        WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL );
+        if (awbuf->str.a && *sz && lenA >= *sz)
             awbuf->str.a[*sz - 1] = 0;
+        len = lenA;
     }
-
     if (awbuf->str.w && len >= *sz)
         r = ERROR_MORE_DATA;
     *sz = len;
@@ -277,7 +273,7 @@ static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
         if (FAILED(hr))
             goto done;
 
-        r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
+        r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf );
 
 done:
         IWineMsiRemotePackage_Release( remote_package );
@@ -301,8 +297,7 @@ done:
     if (!path)
         return ERROR_DIRECTORY;
 
-    r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
-    return r;
+    return msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
 }
 
 /***********************************************************************
@@ -447,7 +442,7 @@ static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
         if (FAILED(hr))
             goto done;
 
-        r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
+        r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf );
 
 done:
         IWineMsiRemotePackage_Release( remote_package );
@@ -478,7 +473,7 @@ done:
     if (!path)
         return ERROR_DIRECTORY;
 
-    r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
+    r = msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
     msi_free( path );
     return r;
 }
@@ -558,7 +553,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
     {
         msi_free( folder->ResolvedTarget );
         folder->ResolvedTarget = target_path;
-        msi_set_property( package->db, folder->Directory, folder->ResolvedTarget );
+        msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 );
 
         LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
         {
@@ -1650,6 +1645,7 @@ UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
 {
     static const WCHAR fmt[] = { '%','d',0 };
     WCHAR level[6];
+    int len;
     UINT r;
 
     TRACE("%p %i\n", package, iInstallLevel);
@@ -1660,8 +1656,8 @@ UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
     if (iInstallLevel < 1)
         return MSI_SetFeatureStates( package );
 
-    sprintfW( level, fmt, iInstallLevel );
-    r = msi_set_property( package->db, szInstallLevel, level );
+    len = sprintfW( level, fmt, iInstallLevel );
+    r = msi_set_property( package->db, szInstallLevel, level, len );
     if ( r == ERROR_SUCCESS )
         r = MSI_SetFeatureStates( package );
 
index 68e9f81..92ef52c 100644 (file)
@@ -1101,6 +1101,11 @@ static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
                                awstring *szValue, LPDWORD pcchValueBuf)
 {
+    static WCHAR empty[] = {0};
+    static const WCHAR sourcelist[] = {'S','o','u','r','c','e','L','i','s','t',0};
+    static const WCHAR display_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
+    static const WCHAR display_version[] = {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
+    static const WCHAR assignment[] = {'A','s','s','i','g','n','m','e','n','t',0};
     MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
     UINT r = ERROR_UNKNOWN_PROPERTY;
     HKEY prodkey, userdata, source;
@@ -1111,16 +1116,6 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
     LONG res;
     DWORD type = REG_NONE;
 
-    static WCHAR empty[] = {0};
-    static const WCHAR sourcelist[] = {
-        'S','o','u','r','c','e','L','i','s','t',0};
-    static const WCHAR display_name[] = {
-        'D','i','s','p','l','a','y','N','a','m','e',0};
-    static const WCHAR display_version[] = {
-        'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
-    static const WCHAR assignment[] = {
-        'A','s','s','i','g','n','m','e','n','t',0};
-
     TRACE("%s %s %p %p\n", debugstr_w(szProduct),
           debugstr_w(szAttribute), szValue, pcchValueBuf);
 
@@ -1244,6 +1239,8 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
 
     if (pcchValueBuf)
     {
+        int len = strlenW( val );
+
         /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
          * out.  Also, *pcchValueBuf may be uninitialized in this case, so we
          * can't rely on its value.
@@ -1251,16 +1248,14 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
         if (szValue->str.a || szValue->str.w)
         {
             DWORD size = *pcchValueBuf;
-            if (strlenW(val) < size)
-                r = msi_strcpy_to_awstring(val, szValue, &size);
+            if (len < size)
+                r = msi_strcpy_to_awstring( val, len, szValue, &size );
             else
-            {
                 r = ERROR_MORE_DATA;
-            }
         }
 
         if (!badconfig)
-            *pcchValueBuf = lstrlenW(val);
+            *pcchValueBuf = len;
     }
 
     if (badconfig)
@@ -2220,7 +2215,10 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
 
         if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY;
         if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz)))
+        {
+            msi_free(val);
             return r;
+        }
 
         if (lstrlenW(val) > 2 &&
             val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':')
@@ -2867,7 +2865,7 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
     if (state == INSTALLSTATE_LOCAL && !*path)
         state = INSTALLSTATE_NOTUSED;
 
-    msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
+    msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf);
     msi_free(path);
     return state;
 }
@@ -3521,7 +3519,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
             goto done;
         }
 
-        r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
+        r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf);
         if (r == ERROR_MORE_DATA)
         {
             state = USERINFOSTATE_MOREDATA;
@@ -3534,7 +3532,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
         orgptr = org;
         if (!orgptr) orgptr = szEmpty;
 
-        r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
+        r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf);
         if (r == ERROR_MORE_DATA)
         {
             state = USERINFOSTATE_MOREDATA;
@@ -3550,7 +3548,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
             goto done;
         }
 
-        r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
+        r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf);
         if (r == ERROR_MORE_DATA)
             state = USERINFOSTATE_MOREDATA;
     }
index de0534a..46f9ed8 100644 (file)
@@ -79,6 +79,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
         msi_dialog_unregister_class();
         msi_free_handle_table();
         msi_free( gszLogFile );
+        release_typelib();
         break;
     }
     return TRUE;
index a0657f4..4110ec6 100644 (file)
@@ -118,6 +118,7 @@ typedef struct tagMSIFIELD
         LPWSTR szwVal;
         IStream *stream;
     } u;
+    int len;
 } MSIFIELD;
 
 typedef struct tagMSIRECORD
@@ -481,6 +482,7 @@ typedef struct tagMSICOMPONENT
     LPWSTR FullKeypath;
     LPWSTR AdvertiseString;
     MSIASSEMBLY *assembly;
+    int num_clients;
 
     unsigned int anyAbsent:1;
     unsigned int hasAdvertiseFeature:1;
@@ -722,7 +724,7 @@ typedef struct {
     } str;
 } awcstring;
 
-UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz ) DECLSPEC_HIDDEN;
+UINT msi_strcpy_to_awstring(const WCHAR *, int, awstring *, DWORD *) DECLSPEC_HIDDEN;
 
 /* msi server interface */
 extern HRESULT create_msi_custom_remote( IUnknown *pOuter, LPVOID *ppObj ) DECLSPEC_HIDDEN;
@@ -753,14 +755,15 @@ enum StringPersistence
 };
 
 extern BOOL msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcount, enum StringPersistence persistence ) DECLSPEC_HIDDEN;
-extern UINT msi_string2idW( const string_table *st, LPCWSTR buffer, UINT *id ) DECLSPEC_HIDDEN;
+extern UINT msi_string2id( const string_table *st, const WCHAR *data, int len, UINT *id ) DECLSPEC_HIDDEN;
 extern VOID msi_destroy_stringtable( string_table *st ) DECLSPEC_HIDDEN;
-extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) DECLSPEC_HIDDEN;
+extern const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len ) DECLSPEC_HIDDEN;
 extern HRESULT msi_init_string_table( IStorage *stg ) DECLSPEC_HIDDEN;
 extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref ) DECLSPEC_HIDDEN;
 extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref ) DECLSPEC_HIDDEN;
 extern UINT msi_get_string_table_codepage( const string_table *st ) DECLSPEC_HIDDEN;
 extern UINT msi_set_string_table_codepage( string_table *st, UINT codepage ) DECLSPEC_HIDDEN;
+extern WCHAR *msi_strdupW( const WCHAR *value, int len ) DECLSPEC_HIDDEN;
 
 extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name ) DECLSPEC_HIDDEN;
 extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table ) DECLSPEC_HIDDEN;
@@ -820,6 +823,8 @@ extern UINT MSI_RecordCopyField( MSIRECORD *, UINT, MSIRECORD *, UINT ) DECLSPEC
 extern MSIRECORD *MSI_CloneRecord( MSIRECORD * ) DECLSPEC_HIDDEN;
 extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN;
 extern BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) DECLSPEC_HIDDEN;
+extern UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int) DECLSPEC_HIDDEN;
+extern const WCHAR *msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN;
 
 /* stream internals */
 extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN;
@@ -999,7 +1004,7 @@ extern UINT ACTION_MsiUnpublishAssemblies(MSIPACKAGE *package) DECLSPEC_HIDDEN;
 extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data ) DECLSPEC_HIDDEN;
 extern WCHAR *msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN;
 extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop ) DECLSPEC_HIDDEN;
-extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR ) DECLSPEC_HIDDEN;
+extern UINT msi_set_property( MSIDATABASE *, const WCHAR *, const WCHAR *, int ) DECLSPEC_HIDDEN;
 extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ) DECLSPEC_HIDDEN;
 extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN;
 extern WCHAR *msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder) DECLSPEC_HIDDEN;
@@ -1067,9 +1072,21 @@ extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialo
                                       LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN;
 
 /* OLE automation */
+typedef enum tid_t {
+    Database_tid,
+    Installer_tid,
+    Record_tid,
+    Session_tid,
+    StringList_tid,
+    SummaryInfo_tid,
+    View_tid,
+    LAST_tid
+} tid_t;
+
 extern HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
 extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) DECLSPEC_HIDDEN;
-extern HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid) DECLSPEC_HIDDEN;
+extern HRESULT get_typeinfo(tid_t tid, ITypeInfo **ti) DECLSPEC_HIDDEN;
+extern void release_typelib(void) DECLSPEC_HIDDEN;
 
 /* Scripting */
 extern DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN;
@@ -1177,6 +1194,7 @@ static const WCHAR szRollbackDisabled[] = {'R','o','l','l','b','a','c','k','D','
 static const WCHAR szName[] = {'N','a','m','e',0};
 static const WCHAR szData[] = {'D','a','t','a',0};
 static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0};
+static const WCHAR szInstallLocation[] = {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0};
 
 /* memory allocation macro functions */
 static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
index 433b3c7..451fddd 100644 (file)
@@ -345,10 +345,9 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
 
         if (type & MSITYPE_STRING)
         {
-            LPCWSTR sval;
-
-            sval = msi_string_lookup_id(db->strings, ival);
-            MSI_RecordSetStringW(*rec, i, sval);
+            int len;
+            const WCHAR *sval = msi_string_lookup( db->strings, ival, &len );
+            msi_record_set_string( *rec, i, sval, len );
         }
         else
         {
index a050b2e..3055175 100644 (file)
@@ -483,7 +483,7 @@ static UINT set_installed_prop( MSIPACKAGE *package )
     if (r == ERROR_SUCCESS)
     {
         RegCloseKey( hkey );
-        msi_set_property( package->db, szInstalled, szOne );
+        msi_set_property( package->db, szInstalled, szOne, -1 );
     }
     return r;
 }
@@ -525,7 +525,7 @@ static UINT set_user_sid_prop( MSIPACKAGE *package )
     if (!ConvertSidToStringSidW( psid, &sid_str ))
         goto done;
 
-    r = msi_set_property( package->db, szUserSID, sid_str );
+    r = msi_set_property( package->db, szUserSID, sid_str, -1 );
 
 done:
     LocalFree( sid_str );
@@ -638,10 +638,12 @@ static void set_msi_assembly_prop(MSIPACKAGE *package)
         return;
 
     size = GetFileVersionInfoSizeW(fusion, &handle);
-    if (!size) return;
+    if (!size)
+        goto done;
 
     version = msi_alloc(size);
-    if (!version) return;
+    if (!version)
+        goto done;
 
     if (!GetFileVersionInfoW(fusion, handle, size, version))
         goto done;
@@ -657,7 +659,7 @@ static void set_msi_assembly_prop(MSIPACKAGE *package)
     if (!val_len || !verstr)
         goto done;
 
-    msi_set_property(package->db, netasm, verstr);
+    msi_set_property( package->db, netasm, verstr, -1 );
 
 done:
     msi_free(fusion);
@@ -757,182 +759,182 @@ static VOID set_installer_properties(MSIPACKAGE *package)
 
     SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szCommonAppDataFolder, pth);
+    msi_set_property( package->db, szCommonAppDataFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szFavoritesFolder, pth);
+    msi_set_property( package->db, szFavoritesFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szFontsFolder, pth);
+    msi_set_property( package->db, szFontsFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szSendToFolder, pth);
+    msi_set_property( package->db, szSendToFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szStartMenuFolder, pth);
+    msi_set_property( package->db, szStartMenuFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szStartupFolder, pth);
+    msi_set_property( package->db, szStartupFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szTemplateFolder, pth);
+    msi_set_property( package->db, szTemplateFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szDesktopFolder, pth);
+    msi_set_property( package->db, szDesktopFolder, pth, -1 );
 
     /* FIXME: set to AllUsers profile path if ALLUSERS is set */
     SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szProgramMenuFolder, pth);
+    msi_set_property( package->db, szProgramMenuFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szAdminToolsFolder, pth);
+    msi_set_property( package->db, szAdminToolsFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szAppDataFolder, pth);
+    msi_set_property( package->db, szAppDataFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szSystemFolder, pth);
-    msi_set_property(package->db, szSystem16Folder, pth);
+    msi_set_property( package->db, szSystemFolder, pth, -1 );
+    msi_set_property( package->db, szSystem16Folder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szLocalAppDataFolder, pth);
+    msi_set_property( package->db, szLocalAppDataFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szMyPicturesFolder, pth);
+    msi_set_property( package->db, szMyPicturesFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szPersonalFolder, pth);
+    msi_set_property( package->db, szPersonalFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szWindowsFolder, pth);
+    msi_set_property( package->db, szWindowsFolder, pth, -1 );
     
     SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szPrintHoodFolder, pth);
+    msi_set_property( package->db, szPrintHoodFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szNetHoodFolder, pth);
+    msi_set_property( package->db, szNetHoodFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szRecentFolder, pth);
+    msi_set_property( package->db, szRecentFolder, pth, -1 );
 
     /* Physical Memory is specified in MB. Using total amount. */
     msex.dwLength = sizeof(msex);
     GlobalMemoryStatusEx( &msex );
-    sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
-    msi_set_property(package->db, szPhysicalMemory, bufstr);
+    len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
+    msi_set_property( package->db, szPhysicalMemory, bufstr, len );
 
     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
     ptr = strchrW(pth,'\\');
     if (ptr) *(ptr + 1) = 0;
-    msi_set_property(package->db, szWindowsVolume, pth);
+    msi_set_property( package->db, szWindowsVolume, pth, -1 );
     
-    GetTempPathW(MAX_PATH,pth);
-    msi_set_property(package->db, szTempFolder, pth);
+    len = GetTempPathW(MAX_PATH, pth);
+    msi_set_property( package->db, szTempFolder, pth, len );
 
     /* in a wine environment the user is always admin and privileged */
-    msi_set_property(package->db, szAdminUser, szOne);
-    msi_set_property(package->db, szPrivileged, szOne);
+    msi_set_property( package->db, szAdminUser, szOne, -1 );
+    msi_set_property( package->db, szPrivileged, szOne, -1 );
 
     /* set the os things */
     OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
     GetVersionExW((OSVERSIONINFOW *)&OSVersion);
     verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
-    sprintfW(verstr, szFormat, verval);
+    len = sprintfW( verstr, szFormat, verval );
     switch (OSVersion.dwPlatformId)
     {
         case VER_PLATFORM_WIN32_WINDOWS:    
-            msi_set_property(package->db, szVersion9x, verstr);
+            msi_set_property( package->db, szVersion9x, verstr, len );
             break;
         case VER_PLATFORM_WIN32_NT:
-            msi_set_property(package->db, szVersionNT, verstr);
-            sprintfW(verstr, szFormat,OSVersion.wProductType);
-            msi_set_property(package->db, szMsiNTProductType, verstr);
+            msi_set_property( package->db, szVersionNT, verstr, len );
+            len = sprintfW( verstr, szFormat,OSVersion.wProductType );
+            msi_set_property( package->db, szMsiNTProductType, verstr, len );
             break;
     }
-    sprintfW(verstr, szFormat, OSVersion.dwBuildNumber);
-    msi_set_property(package->db, szWindowsBuild, verstr);
-    sprintfW(verstr, szFormat, OSVersion.wServicePackMajor);
-    msi_set_property(package->db, szServicePackLevel, verstr);
+    len = sprintfW( verstr, szFormat, OSVersion.dwBuildNumber );
+    msi_set_property( package->db, szWindowsBuild, verstr, len );
+    len = sprintfW( verstr, szFormat, OSVersion.wServicePackMajor );
+    msi_set_property( package->db, szServicePackLevel, verstr, len );
 
-    sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
-    msi_set_property( package->db, szVersionMsi, bufstr );
-    sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
-    msi_set_property( package->db, szVersionDatabase, bufstr );
+    len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION );
+    msi_set_property( package->db, szVersionMsi, bufstr, len );
+    len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 );
+    msi_set_property( package->db, szVersionDatabase, bufstr, len );
 
     GetNativeSystemInfo( &sys_info );
-    sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
-    msi_set_property( package->db, szIntel, bufstr );
+    len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
+    msi_set_property( package->db, szIntel, bufstr, len );
     if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
     {
         GetSystemDirectoryW( pth, MAX_PATH );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szSystemFolder, pth );
+        msi_set_property( package->db, szSystemFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szProgramFilesFolder, pth );
+        msi_set_property( package->db, szProgramFilesFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szCommonFilesFolder, pth );
+        msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
     }
     else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
     {
-        msi_set_property( package->db, szMsiAMD64, bufstr );
-        msi_set_property( package->db, szMsix64, bufstr );
-        msi_set_property( package->db, szVersionNT64, verstr );
+        msi_set_property( package->db, szMsiAMD64, bufstr, -1 );
+        msi_set_property( package->db, szMsix64, bufstr, -1 );
+        msi_set_property( package->db, szVersionNT64, verstr, -1 );
 
         GetSystemDirectoryW( pth, MAX_PATH );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szSystem64Folder, pth );
+        msi_set_property( package->db, szSystem64Folder, pth, -1 );
 
         GetSystemWow64DirectoryW( pth, MAX_PATH );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szSystemFolder, pth );
+        msi_set_property( package->db, szSystemFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szProgramFiles64Folder, pth );
+        msi_set_property( package->db, szProgramFiles64Folder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szProgramFilesFolder, pth );
+        msi_set_property( package->db, szProgramFilesFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szCommonFiles64Folder, pth );
+        msi_set_property( package->db, szCommonFiles64Folder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szCommonFilesFolder, pth );
+        msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
     }
 
     /* Screen properties. */
     dc = GetDC(0);
-    sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
-    msi_set_property( package->db, szScreenX, bufstr );
-    sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
-    msi_set_property( package->db, szScreenY, bufstr );
-    sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
-    msi_set_property( package->db, szColorBits, bufstr );
+    len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) );
+    msi_set_property( package->db, szScreenX, bufstr, len );
+    len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) );
+    msi_set_property( package->db, szScreenY, bufstr, len );
+    len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) );
+    msi_set_property( package->db, szColorBits, bufstr, len );
     ReleaseDC(0, dc);
 
     /* USERNAME and COMPANYNAME */
@@ -944,10 +946,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     {
         if (!username &&
             (username = msi_reg_get_val_str( hkey, szDefName )))
-            msi_set_property( package->db, szUSERNAME, username );
+            msi_set_property( package->db, szUSERNAME, username, -1 );
         if (!companyname &&
             (companyname = msi_reg_get_val_str( hkey, szDefCompany )))
-            msi_set_property( package->db, szCOMPANYNAME, companyname );
+            msi_set_property( package->db, szCOMPANYNAME, companyname, -1 );
         CloseHandle( hkey );
     }
     if ((!username || !companyname) &&
@@ -955,10 +957,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     {
         if (!username &&
             (username = msi_reg_get_val_str( hkey, szRegisteredUser )))
-            msi_set_property( package->db, szUSERNAME, username );
+            msi_set_property( package->db, szUSERNAME, username, -1 );
         if (!companyname &&
             (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization )))
-            msi_set_property( package->db, szCOMPANYNAME, companyname );
+            msi_set_property( package->db, szCOMPANYNAME, companyname, -1 );
         CloseHandle( hkey );
     }
     msi_free( username );
@@ -971,7 +973,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     GetSystemTime( &systemtime );
     if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
                         NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
-        msi_set_property( package->db, szDate, bufstr );
+        msi_set_property( package->db, szDate, bufstr, -1 );
     else
         ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError());
 
@@ -979,22 +981,22 @@ static VOID set_installer_properties(MSIPACKAGE *package)
                         TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
                         &systemtime, NULL, bufstr,
                         sizeof(bufstr)/sizeof(bufstr[0]) ))
-        msi_set_property( package->db, szTime, bufstr );
+        msi_set_property( package->db, szTime, bufstr, -1 );
     else
         ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
 
     set_msi_assembly_prop( package );
 
     langid = GetUserDefaultLangID();
-    sprintfW(bufstr, szIntFormat, langid);
-    msi_set_property( package->db, szUserLanguageID, bufstr );
+    len = sprintfW( bufstr, szIntFormat, langid );
+    msi_set_property( package->db, szUserLanguageID, bufstr, len );
 
     langid = GetSystemDefaultLangID();
-    sprintfW(bufstr, szIntFormat, langid);
-    msi_set_property( package->db, szSystemLangID, bufstr );
+    len = sprintfW( bufstr, szIntFormat, langid );
+    msi_set_property( package->db, szSystemLangID, bufstr, len );
 
-    sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode));
-    msi_set_property( package->db, szProductState, bufstr );
+    len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) );
+    msi_set_property( package->db, szProductState, bufstr, len );
 
     len = 0;
     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
@@ -1003,7 +1005,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
         if ((username = msi_alloc( len * sizeof(WCHAR) )))
         {
             if (GetUserNameW( username, &len ))
-                msi_set_property( package->db, szLogonUser, username );
+                msi_set_property( package->db, szLogonUser, username, len - 1 );
             msi_free( username );
         }
     }
@@ -1014,7 +1016,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
         if ((computername = msi_alloc( len * sizeof(WCHAR) )))
         {
             if (GetComputerNameW( computername, &len ))
-                msi_set_property( package->db, szComputerName, computername );
+                msi_set_property( package->db, szComputerName, computername, len - 1 );
             msi_free( computername );
         }
     }
@@ -1073,7 +1075,7 @@ static UINT msi_load_summary_properties( MSIPACKAGE *package )
         goto done;
     }
 
-    msi_set_property( package->db, szPackageCode, package_code );
+    msi_set_property( package->db, szPackageCode, package_code, len );
     msi_free( package_code );
 
     /* load package attributes */
@@ -1141,9 +1143,9 @@ void msi_adjust_privilege_properties( MSIPACKAGE *package )
     if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
     {
         TRACE("resetting ALLUSERS property from 2 to 1\n");
-        msi_set_property( package->db, szAllUsers, szOne );
+        msi_set_property( package->db, szAllUsers, szOne, -1 );
     }
-    msi_set_property( package->db, szAdminUser, szOne );
+    msi_set_property( package->db, szAdminUser, szOne, -1 );
 }
 
 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
@@ -1151,6 +1153,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
     static const WCHAR fmtW[] = {'%','u',0};
     MSIPACKAGE *package;
     WCHAR uilevel[11];
+    int len;
     UINT r;
 
     TRACE("%p\n", db);
@@ -1176,8 +1179,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
         set_installer_properties( package );
 
         package->ui_level = gUILevel;
-        sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
-        msi_set_property(package->db, szUILevel, uilevel);
+        len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
+        msi_set_property( package->db, szUILevel, uilevel, len );
 
         r = msi_load_summary_properties( package );
         if (r != ERROR_SUCCESS)
@@ -1564,13 +1567,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         {
             r = msi_create_empty_local_file( localfile, dotmsi );
             if (r != ERROR_SUCCESS)
+            {
+                msi_free ( base_url );
                 return r;
+            }
 
             if (!CopyFileW( file, localfile, FALSE ))
             {
                 r = GetLastError();
                 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
                 DeleteFileW( localfile );
+                msi_free ( base_url );
                 return r;
             }
             delete_on_close = TRUE;
@@ -1578,7 +1585,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         TRACE("opening package %s\n", debugstr_w( localfile ));
         r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
         if (r != ERROR_SUCCESS)
+        {
+            msi_free ( base_url );
             return r;
+        }
     }
     package = MSI_CreatePackage( db, base_url );
     msi_free( base_url );
@@ -1608,18 +1618,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         msiobj_release( &package->hdr );
         return r;
     }
-    msi_set_property( package->db, szDatabase, db->path );
+    msi_set_property( package->db, szDatabase, db->path, -1 );
 
     if( UrlIsW( szPackage, URLIS_URL ) )
-        msi_set_property( package->db, szOriginalDatabase, szPackage );
+        msi_set_property( package->db, szOriginalDatabase, szPackage, -1 );
     else if( szPackage[0] == '#' )
-        msi_set_property( package->db, szOriginalDatabase, db->path );
+        msi_set_property( package->db, szOriginalDatabase, db->path, -1 );
     else
     {
         WCHAR fullpath[MAX_PATH];
-
-        GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
-        msi_set_property( package->db, szOriginalDatabase, fullpath );
+        DWORD len = GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
+        msi_set_property( package->db, szOriginalDatabase, fullpath, len );
     }
     msi_set_context( package );
 
@@ -2018,7 +2027,7 @@ void msi_reset_folders( MSIPACKAGE *package, BOOL source )
     }
 }
 
-UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
+UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len )
 {
     static const WCHAR insert_query[] = {
         'I','N','S','E','R','T',' ','I','N','T','O',' ',
@@ -2039,34 +2048,34 @@ UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
     WCHAR query[1024];
     UINT rc;
 
-    TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue));
+    TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len);
 
-    if (!szName)
+    if (!name)
         return ERROR_INVALID_PARAMETER;
 
     /* this one is weird... */
-    if (!szName[0])
-        return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
+    if (!name[0])
+        return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
+
+    if (value && len < 0) len = strlenW( value );
 
-    rc = msi_get_property(db, szName, 0, &sz);
-    if (!szValue || !*szValue)
+    rc = msi_get_property( db, name, 0, &sz );
+    if (!value || (!*value && !len))
     {
-        sprintfW(query, delete_query, szName);
+        sprintfW( query, delete_query, name );
     }
     else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
     {
-        sprintfW(query, update_query, szName);
-
+        sprintfW( query, update_query, name );
         row = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(row, 1, szValue);
+        msi_record_set_string( row, 1, value, len );
     }
     else
     {
-        strcpyW(query, insert_query);
-
+        strcpyW( query, insert_query );
         row = MSI_CreateRecord(2);
-        MSI_RecordSetStringW(row, 1, szName);
-        MSI_RecordSetStringW(row, 2, szValue);
+        msi_record_set_string( row, 1, name, -1 );
+        msi_record_set_string( row, 2, value, len );
     }
 
     rc = MSI_DatabaseOpenViewW(db, query, &view);
@@ -2123,7 +2132,7 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
         return ERROR_SUCCESS;
     }
 
-    ret = msi_set_property( package->db, szName, szValue );
+    ret = msi_set_property( package->db, szName, szValue, -1 );
     if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir ))
         msi_reset_folders( package, TRUE );
 
@@ -2181,7 +2190,7 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
     }
 
     if (rc == ERROR_SUCCESS)
-        TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
+        TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf),
             debugstr_w(szName));
     else if (rc == ERROR_MORE_DATA)
         TRACE("need %d sized buffer for %s\n", *pchValueBuf,
@@ -2232,6 +2241,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
     MSIRECORD *row = NULL;
     UINT r = ERROR_FUNCTION_FAILED;
     LPCWSTR val = NULL;
+    DWORD len = 0;
 
     TRACE("%u %s %p %p\n", handle, debugstr_w(name),
           szValueBuf->str.w, pchValueBuf );
@@ -2246,7 +2256,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
         IWineMsiRemotePackage *remote_package;
         LPWSTR value = NULL;
         BSTR bname;
-        DWORD len;
 
         remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
         if (!remote_package)
@@ -2259,7 +2268,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
             return ERROR_OUTOFMEMORY;
         }
 
-        len = 0;
         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
         if (FAILED(hr))
             goto done;
@@ -2276,7 +2284,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
         if (FAILED(hr))
             goto done;
 
-        r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf );
+        r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf );
 
         /* Bug required by Adobe installers */
         if (!szValueBuf->unicode && !szValueBuf->str.a)
@@ -2300,12 +2308,12 @@ done:
 
     row = msi_get_property_row( package->db, name );
     if (row)
-        val = MSI_RecordGetString( row, 1 );
+        val = msi_record_get_string( row, 1, (int *)&len );
 
     if (!val)
         val = szEmpty;
 
-    r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
+    r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf );
 
     if (row)
         msiobj_release( &row->hdr );
index 4801872..59785a6 100644 (file)
@@ -225,7 +225,7 @@ static UINT patch_set_media_source_prop( MSIPACKAGE *package )
     {
         property = MSI_RecordGetString( rec, 1 );
         patch = msi_dup_property( package->db, szPatch );
-        msi_set_property( package->db, property, patch );
+        msi_set_property( package->db, property, patch, -1 );
         msi_free( patch );
         msiobj_release( &rec->hdr );
     }
index 1dace78..dd097ea 100644 (file)
@@ -156,6 +156,17 @@ static BOOL string2intW( LPCWSTR str, int *out )
     return TRUE;
 }
 
+WCHAR *msi_strdupW( const WCHAR *value, int len )
+{
+    WCHAR *ret;
+
+    if (!value) return NULL;
+    if (!(ret = msi_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
+    memcpy( ret, value, len * sizeof(WCHAR) );
+    ret[len] = 0;
+    return ret;
+}
+
 UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
                           MSIRECORD *out_rec, UINT out_n )
 {
@@ -184,11 +195,12 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
             out->u.pVal = in->u.pVal;
             break;
         case MSIFIELD_WSTR:
-            str = strdupW( in->u.szwVal );
-            if ( !str )
-                r = ERROR_OUTOFMEMORY;
-            else
+            if ((str = msi_strdupW( in->u.szwVal, in->len )))
+            {
                 out->u.szwVal = str;
+                out->len = in->len;
+            }
+            else r = ERROR_OUTOFMEMORY;
             break;
         case MSIFIELD_STREAM:
             IStream_AddRef( in->u.stream );
@@ -202,7 +214,6 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
     }
 
     msiobj_unlock( &in_rec->hdr );
-
     return r;
 }
 
@@ -380,7 +391,7 @@ BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField )
 UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
                LPSTR szValue, LPDWORD pcchValue)
 {
-    UINT len=0, ret;
+    UINT len = 0, ret = ERROR_SUCCESS;
     CHAR buffer[16];
 
     TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
@@ -394,7 +405,6 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
         return ERROR_SUCCESS;
     }
 
-    ret = ERROR_SUCCESS;
     switch( rec->fields[iField].type )
     {
     case MSIFIELD_INT:
@@ -404,11 +414,11 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
             lstrcpynA(szValue, buffer, *pcchValue);
         break;
     case MSIFIELD_WSTR:
-        len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
-                             NULL, 0 , NULL, NULL);
+        len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
+                                   rec->fields[iField].len + 1, NULL, 0 , NULL, NULL );
         if (szValue)
-            WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
-                                 szValue, *pcchValue, NULL, NULL);
+            WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
+                                 rec->fields[iField].len + 1, szValue, *pcchValue, NULL, NULL );
         if( szValue && *pcchValue && len>*pcchValue )
             szValue[*pcchValue-1] = 0;
         if( len )
@@ -448,23 +458,30 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField,
     return ret;
 }
 
-const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
+const WCHAR *msi_record_get_string( const MSIRECORD *rec, UINT field, int *len )
 {
-    if( iField > rec->count )
+    if (field > rec->count)
         return NULL;
 
-    if( rec->fields[iField].type != MSIFIELD_WSTR )
+    if (rec->fields[field].type != MSIFIELD_WSTR)
         return NULL;
 
-    return rec->fields[iField].u.szwVal;
+    if (len) *len = rec->fields[field].len;
+
+    return rec->fields[field].u.szwVal;
+}
+
+const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
+{
+    return msi_record_get_string( rec, iField, NULL );
 }
 
 UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
                LPWSTR szValue, LPDWORD pcchValue)
 {
-    UINT len=0, ret;
+    static const WCHAR szFormat[] = {'%','d',0};
+    UINT len = 0, ret = ERROR_SUCCESS;
     WCHAR buffer[16];
-    static const WCHAR szFormat[] = { '%','d',0 };
 
     TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
 
@@ -477,7 +494,6 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
         return ERROR_SUCCESS;
     }
 
-    ret = ERROR_SUCCESS;
     switch( rec->fields[iField].type )
     {
     case MSIFIELD_INT:
@@ -487,9 +503,9 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
             lstrcpynW(szValue, buffer, *pcchValue);
         break;
     case MSIFIELD_WSTR:
-        len = lstrlenW( rec->fields[iField].u.szwVal );
+        len = rec->fields[iField].len;
         if (szValue)
-            lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue);
+            memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) );
         break;
     case MSIFIELD_NULL:
         if( szValue && *pcchValue > 0 )
@@ -548,7 +564,7 @@ static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField)
     case MSIFIELD_INT:
         return sizeof (INT);
     case MSIFIELD_WSTR:
-        return lstrlenW( rec->fields[iField].u.szwVal );
+        return rec->fields[iField].len;
     case MSIFIELD_NULL:
         break;
     case MSIFIELD_STREAM:
@@ -574,74 +590,61 @@ UINT WINAPI MsiRecordDataSize(MSIHANDLE handle, UINT iField)
     return ret;
 }
 
-static UINT MSI_RecordSetStringA( MSIRECORD *rec, UINT iField, LPCSTR szValue )
-{
-    LPWSTR str;
-
-    TRACE("%p %d %s\n", rec, iField, debugstr_a(szValue));
-
-    if( iField > rec->count )
-        return ERROR_INVALID_FIELD;
-
-    MSI_FreeField( &rec->fields[iField] );
-    if( szValue && szValue[0] )
-    {
-        str = strdupAtoW( szValue );
-        rec->fields[iField].type = MSIFIELD_WSTR;
-        rec->fields[iField].u.szwVal = str;
-    }
-    else
-    {
-        rec->fields[iField].type = MSIFIELD_NULL;
-        rec->fields[iField].u.szwVal = NULL;
-    }
-
-    return 0;
-}
-
 UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, LPCSTR szValue )
 {
+    WCHAR *valueW = NULL;
     MSIRECORD *rec;
     UINT ret;
 
     TRACE("%d %d %s\n", handle, iField, debugstr_a(szValue));
 
+    if (szValue && !(valueW = strdupAtoW( szValue ))) return ERROR_OUTOFMEMORY;
+
     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
     if( !rec )
+    {
+        msi_free( valueW );
         return ERROR_INVALID_HANDLE;
+    }
     msiobj_lock( &rec->hdr );
-    ret = MSI_RecordSetStringA( rec, iField, szValue );
+    ret = MSI_RecordSetStringW( rec, iField, valueW );
     msiobj_unlock( &rec->hdr );
     msiobj_release( &rec->hdr );
+    msi_free( valueW );
     return ret;
 }
 
-UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue )
+UINT msi_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len )
 {
-    LPWSTR str;
-
-    TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue));
-
-    if( iField > rec->count )
+    if (field > rec->count)
         return ERROR_INVALID_FIELD;
 
-    MSI_FreeField( &rec->fields[iField] );
+    MSI_FreeField( &rec->fields[field] );
 
-    if( szValue && szValue[0] )
+    if (value && len < 0) len = strlenW( value );
+
+    if (value && len)
     {
-        str = strdupW( szValue );
-        rec->fields[iField].type = MSIFIELD_WSTR;
-        rec->fields[iField].u.szwVal = str;
+        rec->fields[field].type = MSIFIELD_WSTR;
+        rec->fields[field].u.szwVal = msi_strdupW( value, len );
+        rec->fields[field].len = len;
     }
     else
     {
-        rec->fields[iField].type = MSIFIELD_NULL;
-        rec->fields[iField].u.szwVal = NULL;
+        rec->fields[field].type = MSIFIELD_NULL;
+        rec->fields[field].u.szwVal = NULL;
+        rec->fields[field].len = 0;
     }
-
     return 0;
 }
 
+UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue )
+{
+    TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue));
+
+    return msi_record_set_string( rec, iField, szValue, -1 );
+}
+
 UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, LPCWSTR szValue )
 {
     MSIRECORD *rec;
@@ -1011,8 +1014,9 @@ BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field)
             break;
 
         case MSIFIELD_WSTR:
-            if (strcmpW(a->fields[field].u.szwVal, b->fields[field].u.szwVal))
-                return FALSE;
+            if (a->fields[field].len != b->fields[field].len) return FALSE;
+            if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal,
+                        a->fields[field].len * sizeof(WCHAR) )) return FALSE;
             break;
 
         case MSIFIELD_STREAM:
index 4143a79..388c077 100644 (file)
@@ -1557,7 +1557,7 @@ static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
         }
 
         r = ERROR_OUTOFMEMORY;
-        if ((name_sz+1) >= name_max)
+        if (name_sz + 1 >= name_max)
         {
             name_max *= 2;
             msi_free( name );
@@ -1586,8 +1586,8 @@ static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
 
     TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
 
-    r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
-    r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
+    r = msi_strcpy_to_awstring( name, -1, lpQualBuf, pcchQual );
+    r2 = msi_strcpy_to_awstring( val+ofs, -1, lpAppBuf, pcchAppBuf );
 
     if (r2 != ERROR_SUCCESS)
         r = r2;
@@ -1596,7 +1596,6 @@ end:
     msi_free(val);
     msi_free(name);
     RegCloseKey(key);
-
     return r;
 }
 
index 94577ba..8d48a94 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
+#ifdef _WIN64
+
+#define IActiveScriptParse_Release IActiveScriptParse64_Release
+#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
+#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
+
+#else
+
+#define IActiveScriptParse_Release IActiveScriptParse32_Release
+#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
+#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
+
+#endif
+
 static const WCHAR szJScript[] = { 'J','S','c','r','i','p','t',0};
 static const WCHAR szVBScript[] = { 'V','B','S','c','r','i','p','t',0};
 static const WCHAR szSession[] = {'S','e','s','s','i','o','n',0};
@@ -43,207 +57,54 @@ static const WCHAR szSession[] = {'S','e','s','s','i','o','n',0};
 /*
  * MsiActiveScriptSite - Our IActiveScriptSite implementation.
  */
-
 typedef struct {
-    IActiveScriptSite lpVtbl;
-    IDispatch *pInstaller;
-    IDispatch *pSession;
+    IActiveScriptSite IActiveScriptSite_iface;
+    IDispatch *installer;
+    IDispatch *session;
     LONG ref;
 } MsiActiveScriptSite;
 
-static const struct IActiveScriptSiteVtbl ASS_Vtbl;
-
-static HRESULT create_ActiveScriptSite(IUnknown *pUnkOuter, LPVOID *ppObj)
+static inline MsiActiveScriptSite *impl_from_IActiveScriptSite( IActiveScriptSite *iface )
 {
-    MsiActiveScriptSite* object;
-
-    TRACE("(%p,%p)\n", pUnkOuter, ppObj);
-
-    if( pUnkOuter )
-        return CLASS_E_NOAGGREGATION;
-
-    object = msi_alloc_zero( sizeof(MsiActiveScriptSite) );
-
-    object->lpVtbl.lpVtbl = &ASS_Vtbl;
-    object->ref = 1;
-    object->pInstaller = NULL;
-    object->pSession = NULL;
-
-    *ppObj = object;
-
-    return S_OK;
-}
-
-/*
- * Call a script.
- */
-DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action)
-{
-    HRESULT hr;
-    IActiveScript *pActiveScript = NULL;
-    IActiveScriptParse32 *pActiveScriptParse32 = NULL;
-    IActiveScriptParse64 *pActiveScriptParse64 = NULL;
-    MsiActiveScriptSite *pActiveScriptSite = NULL;
-    IDispatch *pDispatch = NULL;
-    DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
-    DISPID dispid;
-    CLSID clsid;
-    VARIANT var;
-    DWORD ret = ERROR_INSTALL_FAILURE;
-
-    CoInitialize(NULL);
-
-    /* Create MsiActiveScriptSite object */
-    hr = create_ActiveScriptSite(NULL, (void **)&pActiveScriptSite);
-    if (hr != S_OK) goto done;
-
-    /* Create an installer object */
-    hr = create_msiserver(NULL, (LPVOID *)&pActiveScriptSite->pInstaller);
-    if (hr != S_OK) goto done;
-
-    /* Create a session object */
-    hr = create_session(hPackage, pActiveScriptSite->pInstaller, &pActiveScriptSite->pSession);
-    if (hr != S_OK) goto done;
-
-    /* Create the scripting engine */
-    if ((type & 7) == msidbCustomActionTypeJScript)
-        hr = CLSIDFromProgID(szJScript, &clsid);
-    else if ((type & 7) == msidbCustomActionTypeVBScript)
-        hr = CLSIDFromProgID(szVBScript, &clsid);
-    else {
-        ERR("Unknown script type %d\n", type);
-        goto done;
-    }
-    if (FAILED(hr)) {
-        ERR("Could not find CLSID for Windows Script\n");
-        goto done;
-    }
-    hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IActiveScript, (void **)&pActiveScript);
-    if (FAILED(hr)) {
-        ERR("Could not instantiate class for Windows Script\n");
-        goto done;
-    }
-
-    if (type & msidbCustomActionType64BitScript)
-    {
-        hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse64, (void **)&pActiveScriptParse64);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScript_SetScriptSite(pActiveScript, (IActiveScriptSite *)pActiveScriptSite);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScriptParse64_InitNew(pActiveScriptParse64);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScriptParse64_ParseScriptText(pActiveScriptParse64, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
-        if (FAILED(hr)) goto done;
-    }
-    else
-    {
-        hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse32, (void **)&pActiveScriptParse32);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScript_SetScriptSite(pActiveScript, (IActiveScriptSite *)pActiveScriptSite);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScriptParse32_InitNew(pActiveScriptParse32);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS);
-        if (FAILED(hr)) goto done;
-
-        hr = IActiveScriptParse32_ParseScriptText(pActiveScriptParse32, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
-        if (FAILED(hr)) goto done;
-    }
-
-    hr = IActiveScript_SetScriptState(pActiveScript, SCRIPTSTATE_CONNECTED);
-    if (FAILED(hr)) goto done;
-
-    /* Call a function if necessary through the IDispatch interface */
-    if (function != NULL && strlenW(function) > 0) {
-        TRACE("Calling function %s\n", debugstr_w(function));
-
-        hr = IActiveScript_GetScriptDispatch(pActiveScript, NULL, &pDispatch);
-        if (FAILED(hr)) goto done;
-
-        hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, (WCHAR **)&function, 1,LOCALE_USER_DEFAULT, &dispid);
-        if (FAILED(hr)) goto done;
-
-        hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &var, NULL, NULL);
-        if (FAILED(hr)) goto done;
-
-        /* Check return value, if it's not IDOK we failed */
-        hr = VariantChangeType(&var, &var, 0, VT_I4);
-        if (FAILED(hr)) goto done;
-
-        if (V_I4(&var) == IDOK)
-            ret = ERROR_SUCCESS;
-        else ret = ERROR_INSTALL_FAILURE;
-
-        VariantClear(&var);
-    } else {
-        /* If no function to be called, MSI behavior is to succeed */
-        ret = ERROR_SUCCESS;
-    }
-
-done:
-
-    if (pDispatch) IDispatch_Release(pDispatch);
-    if (pActiveScript) IActiveScript_Release(pActiveScript);
-    if (pActiveScriptParse32) IActiveScriptParse32_Release(pActiveScriptParse32);
-    if (pActiveScriptParse64) IActiveScriptParse64_Release(pActiveScriptParse64);
-    if (pActiveScriptSite)
-    {
-        if (pActiveScriptSite->pSession) IDispatch_Release(pActiveScriptSite->pSession);
-        if (pActiveScriptSite->pInstaller) IDispatch_Release(pActiveScriptSite->pInstaller);
-        IActiveScriptSite_Release((IActiveScriptSite *)pActiveScriptSite);
-    }
-    CoUninitialize();    /* must call even if CoInitialize failed */
-    return ret;
+    return CONTAINING_RECORD(iface, MsiActiveScriptSite, IActiveScriptSite_iface);
 }
 
 /*
  * MsiActiveScriptSite
  */
-
-/*** IUnknown methods ***/
-static HRESULT WINAPI MsiActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** ppvObject)
+static HRESULT WINAPI MsiActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** obj)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
 
-    TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
+    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
 
     if (IsEqualGUID(riid, &IID_IUnknown) ||
         IsEqualGUID(riid, &IID_IActiveScriptSite))
     {
         IActiveScriptSite_AddRef(iface);
-        *ppvObject = This;
+        *obj = iface;
         return S_OK;
     }
 
-    TRACE("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
+    *obj = NULL;
 
     return E_NOINTERFACE;
 }
 
 static ULONG WINAPI MsiActiveScriptSite_AddRef(IActiveScriptSite* iface)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-
-    TRACE("(%p/%p)\n", iface, This);
-
-    return InterlockedIncrement(&This->ref);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p)->(%d)\n", This, ref);
+    return ref;
 }
 
 static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
 
-    TRACE("(%p/%p)\n", iface, This);
+    TRACE("(%p)->(%d)\n", This, ref);
 
     if (!ref)
         msi_free(This);
@@ -251,18 +112,18 @@ static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface)
     return ref;
 }
 
-/*** IActiveScriptSite methods **/
 static HRESULT WINAPI MsiActiveScriptSite_GetLCID(IActiveScriptSite* iface, LCID* plcid)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-    TRACE("(%p/%p)->(%p)\n", This, iface, plcid);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+    TRACE("(%p)->(%p)\n", This, plcid);
     return E_NOTIMPL;  /* Script will use system-defined locale */
 }
 
 static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppiunkItem, ITypeInfo** ppti)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-    TRACE("(%p/%p)->(%p,%d,%p,%p)\n", This, iface, pstrName, dwReturnMask, ppiunkItem, ppti);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+
+    TRACE("(%p)->(%p, %d, %p, %p)\n", This, pstrName, dwReturnMask, ppiunkItem, ppti);
 
     /* Determine the kind of pointer that is requested, and make sure placeholder is valid */
     if (dwReturnMask & SCRIPTINFO_ITYPEINFO) {
@@ -276,10 +137,14 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface,
 
     /* Are we looking for the session object? */
     if (!strcmpW(szSession, pstrName)) {
-        if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
-            return load_type_info(This->pSession, ppti, &DIID_Session, 0);
+        if (dwReturnMask & SCRIPTINFO_ITYPEINFO) {
+            HRESULT hr = get_typeinfo(Session_tid, ppti);
+            if (SUCCEEDED(hr))
+                ITypeInfo_AddRef(*ppti);
+            return hr;
+        }
         else if (dwReturnMask & SCRIPTINFO_IUNKNOWN) {
-            IDispatch_QueryInterface(This->pSession, &IID_IUnknown, (void **)ppiunkItem);
+            IDispatch_QueryInterface(This->session, &IID_IUnknown, (void **)ppiunkItem);
             return S_OK;
         }
     }
@@ -289,15 +154,15 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface,
 
 static HRESULT WINAPI MsiActiveScriptSite_GetDocVersionString(IActiveScriptSite* iface, BSTR* pbstrVersion)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-    TRACE("(%p/%p)->(%p)\n", This, iface, pbstrVersion);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+    TRACE("(%p)->(%p)\n", This, pbstrVersion);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI MsiActiveScriptSite_OnScriptTerminate(IActiveScriptSite* iface, const VARIANT* pvarResult, const EXCEPINFO* pexcepinfo)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-    TRACE("(%p/%p)->(%p,%p)\n", This, iface, pvarResult, pexcepinfo);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+    TRACE("(%p)->(%p, %p)\n", This, pvarResult, pexcepinfo);
     return S_OK;
 }
 
@@ -338,11 +203,11 @@ static HRESULT WINAPI MsiActiveScriptSite_OnStateChange(IActiveScriptSite* iface
 
 static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface, IActiveScriptError* pscripterror)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
     EXCEPINFO exception;
     HRESULT hr;
 
-    TRACE("(%p/%p)->(%p)\n", This, iface, pscripterror);
+    TRACE("(%p)->(%p)\n", This, pscripterror);
 
     memset(&exception, 0, sizeof(EXCEPINFO));
     hr = IActiveScriptError_GetExceptionInfo(pscripterror, &exception);
@@ -359,19 +224,19 @@ static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface
 
 static HRESULT WINAPI MsiActiveScriptSite_OnEnterScript(IActiveScriptSite* iface)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-    TRACE("(%p/%p)\n", This, iface);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+    TRACE("(%p)\n", This);
     return S_OK;
 }
 
 static HRESULT WINAPI MsiActiveScriptSite_OnLeaveScript(IActiveScriptSite* iface)
 {
-    MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface;
-    TRACE("(%p/%p)\n", This, iface);
+    MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
+    TRACE("(%p)\n", This);
     return S_OK;
 }
 
-static const struct IActiveScriptSiteVtbl ASS_Vtbl =
+static const struct IActiveScriptSiteVtbl activescriptsitevtbl =
 {
     MsiActiveScriptSite_QueryInterface,
     MsiActiveScriptSite_AddRef,
@@ -385,3 +250,135 @@ static const struct IActiveScriptSiteVtbl ASS_Vtbl =
     MsiActiveScriptSite_OnEnterScript,
     MsiActiveScriptSite_OnLeaveScript
 };
+
+static HRESULT create_activescriptsite(MsiActiveScriptSite **obj)
+{
+    MsiActiveScriptSite* object;
+
+    TRACE("(%p)\n", obj);
+
+    *obj = NULL;
+
+    object = msi_alloc( sizeof(MsiActiveScriptSite) );
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    object->IActiveScriptSite_iface.lpVtbl = &activescriptsitevtbl;
+    object->ref = 1;
+    object->installer = NULL;
+    object->session = NULL;
+
+    *obj = object;
+
+    return S_OK;
+}
+
+/*
+ * Call a script.
+ */
+DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action)
+{
+    HRESULT hr;
+    IActiveScript *pActiveScript = NULL;
+    IActiveScriptParse *pActiveScriptParse = NULL;
+    MsiActiveScriptSite *scriptsite;
+    IDispatch *pDispatch = NULL;
+    DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
+    DISPID dispid;
+    CLSID clsid;
+    VARIANT var;
+    DWORD ret = ERROR_INSTALL_FAILURE;
+
+    CoInitialize(NULL);
+
+    /* Create MsiActiveScriptSite object */
+    hr = create_activescriptsite(&scriptsite);
+    if (hr != S_OK) goto done;
+
+    /* Create an installer object */
+    hr = create_msiserver(NULL, (void**)&scriptsite->installer);
+    if (hr != S_OK) goto done;
+
+    /* Create a session object */
+    hr = create_session(hPackage, scriptsite->installer, &scriptsite->session);
+    if (hr != S_OK) goto done;
+
+    /* Create the scripting engine */
+    type &= msidbCustomActionTypeJScript|msidbCustomActionTypeVBScript;
+    if (type == msidbCustomActionTypeJScript)
+        hr = CLSIDFromProgID(szJScript, &clsid);
+    else if (type == msidbCustomActionTypeVBScript)
+        hr = CLSIDFromProgID(szVBScript, &clsid);
+    else {
+        ERR("Unknown script type %d\n", type);
+        goto done;
+    }
+    if (FAILED(hr)) {
+        ERR("Could not find CLSID for Windows Script\n");
+        goto done;
+    }
+    hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IActiveScript, (void **)&pActiveScript);
+    if (FAILED(hr)) {
+        ERR("Could not instantiate class for Windows Script\n");
+        goto done;
+    }
+
+    hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse, (void **)&pActiveScriptParse);
+    if (FAILED(hr)) goto done;
+
+    hr = IActiveScript_SetScriptSite(pActiveScript, &scriptsite->IActiveScriptSite_iface);
+    if (FAILED(hr)) goto done;
+
+    hr = IActiveScriptParse_InitNew(pActiveScriptParse);
+    if (FAILED(hr)) goto done;
+
+    hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS|SCRIPTITEM_ISVISIBLE);
+    if (FAILED(hr)) goto done;
+
+    hr = IActiveScriptParse_ParseScriptText(pActiveScriptParse, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
+    if (FAILED(hr)) goto done;
+
+    hr = IActiveScript_SetScriptState(pActiveScript, SCRIPTSTATE_CONNECTED);
+    if (FAILED(hr)) goto done;
+
+    /* Call a function if necessary through the IDispatch interface */
+    if (function != NULL && strlenW(function) > 0) {
+        TRACE("Calling function %s\n", debugstr_w(function));
+
+        hr = IActiveScript_GetScriptDispatch(pActiveScript, NULL, &pDispatch);
+        if (FAILED(hr)) goto done;
+
+        hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, (WCHAR **)&function, 1,LOCALE_USER_DEFAULT, &dispid);
+        if (FAILED(hr)) goto done;
+
+        hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &var, NULL, NULL);
+        if (FAILED(hr)) goto done;
+
+        /* Check return value, if it's not IDOK we failed */
+        hr = VariantChangeType(&var, &var, 0, VT_I4);
+        if (FAILED(hr)) goto done;
+
+        if (V_I4(&var) == IDOK)
+            ret = ERROR_SUCCESS;
+        else ret = ERROR_INSTALL_FAILURE;
+
+        VariantClear(&var);
+    } else {
+        /* If no function to be called, MSI behavior is to succeed */
+        ret = ERROR_SUCCESS;
+    }
+
+done:
+
+    if (pDispatch) IDispatch_Release(pDispatch);
+    if (pActiveScript) IActiveScript_Release(pActiveScript);
+    if (pActiveScriptParse) IActiveScriptParse_Release(pActiveScriptParse);
+    if (scriptsite)
+    {
+        if (scriptsite->session) IDispatch_Release(scriptsite->session);
+        if (scriptsite->installer) IDispatch_Release(scriptsite->installer);
+        IActiveScriptSite_Release(&scriptsite->IActiveScriptSite_iface);
+    }
+    CoUninitialize();    /* must call even if CoInitialize failed */
+    return ret;
+}
index 982cf6a..e8f3885 100644 (file)
@@ -276,8 +276,9 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
         }
         else if (type & MSITYPE_STRING)
         {
-            str = MSI_RecordGetString(rec, i + 1);
-            r = MSI_RecordSetStringW(mod, col, str);
+            int len;
+            str = msi_record_get_string( rec, i + 1, &len );
+            r = msi_record_set_string( mod, col, str, len );
         }
         else
         {
@@ -430,7 +431,7 @@ UINT SELECT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
 
     count = select_count_columns( columns );
 
-    sv = msi_alloc_zero( sizeof *sv + count*sizeof (UINT) );
+    sv = msi_alloc_zero( FIELD_OFFSET( MSISELECTVIEW, cols[count] ));
     if( !sv )
         return ERROR_FUNCTION_FAILED;
     
index 881f3d2..ab8541c 100644 (file)
@@ -763,7 +763,10 @@ UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
 
     r = OpenSourceKey(product, &source, MSICODE_PRODUCT, context, FALSE);
     if (r != ERROR_SUCCESS)
+    {
+        msi_free(buffer);
         return r;
+    }
 
     sprintfW(buffer, format, typechar, index, value);
 
index c980df8..35c1de5 100644 (file)
@@ -312,7 +312,7 @@ static UINT storages_find_row(MSISTORAGESVIEW *sv, MSIRECORD *rec, UINT *row)
     UINT r, i, id, data;
 
     str = MSI_RecordGetString(rec, 1);
-    r = msi_string2idW(sv->db->strings, str, &id);
+    r = msi_string2id(sv->db->strings, str, -1, &id);
     if (r != ERROR_SUCCESS)
         return r;
 
index 71616e9..d9d632f 100644 (file)
@@ -299,7 +299,7 @@ static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row)
     UINT r, i, id, data;
 
     str = MSI_RecordGetString(rec, 1);
-    r = msi_string2idW(sv->db->strings, str, &id);
+    r = msi_string2id(sv->db->strings, str, -1, &id);
     if (r != ERROR_SUCCESS)
         return r;
 
index 065c04a..8e3e575 100644 (file)
@@ -45,7 +45,8 @@ struct msistring
 {
     USHORT persistent_refcount;
     USHORT nonpersistent_refcount;
-    LPWSTR str;
+    WCHAR *data;
+    int    len;
 };
 
 struct string_table
@@ -112,7 +113,7 @@ VOID msi_destroy_stringtable( string_table *st )
     {
         if( st->strings[i].persistent_refcount ||
             st->strings[i].nonpersistent_refcount )
-            msi_free( st->strings[i].str );
+            msi_free( st->strings[i].data );
     }
     msi_free( st->strings );
     msi_free( st->sorted );
@@ -162,6 +163,19 @@ static int st_find_free_entry( string_table *st )
     return st->freeslot;
 }
 
+static inline int cmp_string( const WCHAR *str1, int len1, const WCHAR *str2, int len2 )
+{
+    if (len1 < len2) return -1;
+    else if (len1 > len2) return 1;
+    while (len1)
+    {
+        if (*str1 == *str2) { str1++; str2++; }
+        else return *str1 - *str2;
+        len1--;
+    }
+    return 0;
+}
+
 static int find_insert_index( const string_table *st, UINT string_id )
 {
     int i, c, low = 0, high = st->sortcount - 1;
@@ -169,8 +183,8 @@ static int find_insert_index( const string_table *st, UINT string_id )
     while (low <= high)
     {
         i = (low + high) / 2;
-        c = strcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str );
-
+        c = cmp_string( st->strings[string_id].data, st->strings[string_id].len,
+                        st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len );
         if (c < 0)
             high = i - 1;
         else if (c > 0)
@@ -194,7 +208,8 @@ static void insert_string_sorted( string_table *st, UINT string_id )
     st->sortcount++;
 }
 
-static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount, enum StringPersistence persistence )
+static void set_st_entry( string_table *st, UINT n, WCHAR *str, int len, USHORT refcount,
+                          enum StringPersistence persistence )
 {
     if (persistence == StringPersistent)
     {
@@ -207,7 +222,8 @@ static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount,
         st->strings[n].nonpersistent_refcount = refcount;
     }
 
-    st->strings[n].str = str;
+    st->strings[n].data = str;
+    st->strings[n].len  = len;
 
     insert_string_sorted( st, n );
 
@@ -237,20 +253,17 @@ static UINT msi_string2idA( const string_table *st, LPCSTR buffer, UINT *id )
         return ERROR_NOT_ENOUGH_MEMORY;
     MultiByteToWideChar( st->codepage, 0, buffer, -1, str, sz );
 
-    r = msi_string2idW( st, str, id );
+    r = msi_string2id( st, str, sz - 1, id );
     msi_free( str );
-
     return r;
 }
 
-static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, USHORT refcount, enum StringPersistence persistence )
+static int msi_addstring( string_table *st, UINT n, const char *data, UINT len, USHORT refcount, enum StringPersistence persistence )
 {
     LPWSTR str;
     int sz;
 
-    if( !data )
-        return 0;
-    if( !data[0] )
+    if( !data || !len )
         return 0;
     if( n > 0 )
     {
@@ -280,8 +293,6 @@ static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, U
     }
 
     /* allocate a new string */
-    if( len < 0 )
-        len = strlen(data);
     sz = MultiByteToWideChar( st->codepage, 0, data, len, NULL, 0 );
     str = msi_alloc( (sz+1)*sizeof(WCHAR) );
     if( !str )
@@ -289,8 +300,7 @@ static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, U
     MultiByteToWideChar( st->codepage, 0, data, len, str, sz );
     str[sz] = 0;
 
-    set_st_entry( st, n, str, refcount, persistence );
-
+    set_st_entry( st, n, str, sz, refcount, persistence );
     return n;
 }
 
@@ -301,10 +311,13 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun
 
     if( !data )
         return 0;
-    if( !data[0] )
+
+    if (len < 0) len = strlenW( data );
+
+    if( !data[0] && !len )
         return 0;
 
-    if( msi_string2idW( st, data, &n ) == ERROR_SUCCESS )
+    if (msi_string2id( st, data, len, &n) == ERROR_SUCCESS )
     {
         if (persistence == StringPersistent)
             st->strings[n].persistent_refcount += refcount;
@@ -318,9 +331,7 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun
         return -1;
 
     /* allocate a new string */
-    if(len<0)
-        len = strlenW(data);
-    TRACE("%s, n = %d len = %d\n", debugstr_w(data), n, len );
+    TRACE( "%s, n = %d len = %d\n", debugstr_wn(data, len), n, len );
 
     str = msi_alloc( (len+1)*sizeof(WCHAR) );
     if( !str )
@@ -328,24 +339,27 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun
     memcpy( str, data, len*sizeof(WCHAR) );
     str[len] = 0;
 
-    set_st_entry( st, n, str, refcount, persistence );
-
+    set_st_entry( st, n, str, len, refcount, persistence );
     return n;
 }
 
 /* find the string identified by an id - return null if there's none */
-const WCHAR *msi_string_lookup_id( const string_table *st, UINT id )
+const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len )
 {
     if( id == 0 )
+    {
+        if (len) *len = 0;
         return szEmpty;
-
+    }
     if( id >= st->maxcount )
         return NULL;
 
     if( id && !st->strings[id].persistent_refcount && !st->strings[id].nonpersistent_refcount)
         return NULL;
 
-    return st->strings[id].str;
+    if (len) *len = st->strings[id].len;
+
+    return st->strings[id].data;
 }
 
 /*
@@ -361,16 +375,15 @@ const WCHAR *msi_string_lookup_id( const string_table *st, UINT id )
  */
 static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT *sz )
 {
-    UINT len, lenW;
+    int len, lenW;
     const WCHAR *str;
 
     TRACE("Finding string %d of %d\n", id, st->maxcount);
 
-    str = msi_string_lookup_id( st, id );
+    str = msi_string_lookup( st, id, &lenW );
     if( !str )
         return ERROR_FUNCTION_FAILED;
 
-    lenW = strlenW( str );
     len = WideCharToMultiByte( st->codepage, 0, str, lenW, NULL, 0, NULL, NULL );
     if( *sz < len )
     {
@@ -382,20 +395,22 @@ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT
 }
 
 /*
- *  msi_string2idW
+ *  msi_string2id
  *
  *  [in] st         - pointer to the string table
  *  [in] str        - string to find in the string table
  *  [out] id        - id of the string, if found
  */
-UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
+UINT msi_string2id( const string_table *st, const WCHAR *str, int len, UINT *id )
 {
     int i, c, low = 0, high = st->sortcount - 1;
 
+    if (len < 0) len = strlenW( str );
+
     while (low <= high)
     {
         i = (low + high) / 2;
-        c = strcmpW( str, st->strings[st->sorted[i]].str );
+        c = cmp_string( str, len, st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len );
 
         if (c < 0)
             high = i - 1;
@@ -407,7 +422,6 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
             return ERROR_SUCCESS;
         }
     }
-
     return ERROR_INVALID_PARAMETER;
 }
 
@@ -415,7 +429,7 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool
 {
     UINT i, len, holesize;
 
-    if( st->strings[0].str || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount)
+    if( st->strings[0].data || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount)
         ERR("oops. element 0 has a string\n");
 
     *poolsize = 4;
@@ -425,14 +439,14 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool
     {
         if( !st->strings[i].persistent_refcount )
         {
-            TRACE("[%u] nonpersistent = %s\n", i, debugstr_w(st->strings[i].str));
+            TRACE("[%u] nonpersistent = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len));
             (*poolsize) += 4;
         }
-        else if( st->strings[i].str )
+        else if( st->strings[i].data )
         {
-            TRACE("[%u] = %s\n", i, debugstr_w(st->strings[i].str));
-            len = WideCharToMultiByte( st->codepage, 0,
-                     st->strings[i].str, -1, NULL, 0, NULL, NULL);
+            TRACE("[%u] = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len));
+            len = WideCharToMultiByte( st->codepage, 0, st->strings[i].data, st->strings[i].len + 1,
+                                       NULL, 0, NULL, NULL);
             if( len )
                 len--;
             (*datasize) += len;
index dd25fbb..e2186fc 100644 (file)
@@ -660,7 +660,7 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF
     }
 
     /* convert table and column names to IDs from the string table */
-    r = msi_string2idW( db->strings, szTableName, &table_id );
+    r = msi_string2id( db->strings, szTableName, -1, &table_id );
     if (r != ERROR_SUCCESS)
     {
         WARN("Couldn't find id for %s\n", debugstr_w(szTableName));
@@ -693,9 +693,9 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF
                 ERR("duplicate column %d\n", col);
                 continue;
             }
-            colinfo[col - 1].tablename = msi_string_lookup_id( db->strings, table_id );
+            colinfo[col - 1].tablename = msi_string_lookup( db->strings, table_id, NULL );
             colinfo[col - 1].number = col;
-            colinfo[col - 1].colname = msi_string_lookup_id( db->strings, id );
+            colinfo[col - 1].colname = msi_string_lookup( db->strings, id, NULL );
             colinfo[col - 1].type = read_table_int( table->data, i, table->colinfo[3].offset,
                                                     sizeof(USHORT) ) - (1 << 15);
             colinfo[col - 1].offset = 0;
@@ -763,9 +763,9 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
         UINT table_id = msi_addstringW( db->strings, col->table, -1, 1, string_persistence );
         UINT col_id = msi_addstringW( db->strings, col->column, -1, 1, string_persistence );
 
-        table->colinfo[ i ].tablename = msi_string_lookup_id( db->strings, table_id );
+        table->colinfo[ i ].tablename = msi_string_lookup( db->strings, table_id, NULL );
         table->colinfo[ i ].number = i + 1;
-        table->colinfo[ i ].colname = msi_string_lookup_id( db->strings, col_id );
+        table->colinfo[ i ].colname = msi_string_lookup( db->strings, col_id, NULL );
         table->colinfo[ i ].type = col->type;
         table->colinfo[ i ].offset = 0;
         table->colinfo[ i ].ref_count = 0;
@@ -981,7 +981,7 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
         !strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) )
         return TRUE;
 
-    r = msi_string2idW( db->strings, name, &table_id );
+    r = msi_string2id( db->strings, name, -1, &table_id );
     if( r != ERROR_SUCCESS )
     {
         TRACE("Couldn't find id for %s\n", debugstr_w(name));
@@ -1087,7 +1087,7 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname )
 
             if ( tv->columns[i].type & MSITYPE_STRING )
             {
-                sval = msi_string_lookup_id( tv->db->strings, ival );
+                sval = msi_string_lookup( tv->db->strings, ival, NULL );
                 if ( !sval )
                 {
                     r = ERROR_INVALID_PARAMETER;
@@ -1273,10 +1273,11 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
     }
     else if ( columninfo.type & MSITYPE_STRING )
     {
-        LPCWSTR sval = MSI_RecordGetString( rec, iField );
+        int len;
+        const WCHAR *sval = msi_record_get_string( rec, iField, &len );
         if (sval)
         {
-            r = msi_string2idW(tv->db->strings, sval, pvalue);
+            r = msi_string2id( tv->db->strings, sval, len, pvalue );
             if (r != ERROR_SUCCESS)
                 return ERROR_NOT_FOUND;
         }
@@ -1360,8 +1361,9 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
 
                 if ( r != ERROR_SUCCESS )
                 {
-                    LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
-                    val = msi_addstringW( tv->db->strings, sval, -1, 1,
+                    int len;
+                    const WCHAR *sval = msi_record_get_string( rec, i + 1, &len );
+                    val = msi_addstringW( tv->db->strings, sval, len, 1,
                       persistent ? StringPersistent : StringNonPersistent );
                 }
                 else
@@ -1530,10 +1532,10 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *column )
             TRACE("skipping binary column\n");
         else if ( tv->columns[i].type & MSITYPE_STRING )
         {
-            LPCWSTR str;
+            int len;
+            const WCHAR *str = msi_record_get_string( rec, i+1, &len );
 
-            str = MSI_RecordGetString( rec, i+1 );
-            if (str == NULL || str[0] == 0)
+            if (!str || (!str[0] && !len))
             {
                 if (column) *column = i;
                 return ERROR_INVALID_DATA;
@@ -2139,7 +2141,7 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
     else if ( !strcmpW( name, szStorages ) )
         return STORAGES_CreateView( db, view );
 
-    sz = sizeof *tv + lstrlenW(name)*sizeof name[0] ;
+    sz = FIELD_OFFSET( MSITABLEVIEW, name[lstrlenW( name ) + 1] );
     tv = msi_alloc_zero( sz );
     if( !tv )
         return ERROR_FUNCTION_FAILED;
@@ -2265,6 +2267,7 @@ static UINT msi_record_encoded_stream_name( const MSITABLEVIEW *tv, MSIRECORD *r
             if ( !p )
             {
                 r = ERROR_OUTOFMEMORY;
+                msi_free(sval);
                 goto err;
             }
             stname = p;
@@ -2328,21 +2331,25 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
 
             r = IStorage_OpenStream( stg, encname, NULL,
                      STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
-            msi_free( encname );
             if ( r != ERROR_SUCCESS )
+            {
+                msi_free( encname );
                 return NULL;
+            }
 
             MSI_RecordSetStream( rec, i+1, stm );
             TRACE(" field %d [%s]\n", i+1, debugstr_w(encname));
+            msi_free( encname );
         }
         else if( columns[i].type & MSITYPE_STRING )
         {
-            LPCWSTR sval;
+            int len;
+            const WCHAR *sval;
 
             val = read_raw_int(rawdata, ofs, bytes_per_strref);
-            sval = msi_string_lookup_id( st, val );
-            MSI_RecordSetStringW( rec, i+1, sval );
-            TRACE(" field %d [%s]\n", i+1, debugstr_w(sval));
+            sval = msi_string_lookup( st, val, &len );
+            msi_record_set_string( rec, i+1, sval, len );
+            TRACE(" field %d [%s]\n", i+1, debugstr_wn(sval, len));
             ofs += bytes_per_strref;
         }
         else
@@ -2379,12 +2386,13 @@ static void dump_record( MSIRECORD *rec )
     n = MSI_RecordGetFieldCount( rec );
     for( i=1; i<=n; i++ )
     {
-        LPCWSTR sval;
+        int len;
+        const WCHAR *sval;
 
         if( MSI_RecordIsNull( rec, i ) )
             TRACE("row -> []\n");
-        else if( (sval = MSI_RecordGetString( rec, i )) )
-            TRACE("row -> [%s]\n", debugstr_w(sval));
+        else if( (sval = msi_record_get_string( rec, i, &len )) )
+            TRACE("row -> [%s]\n", debugstr_wn(sval, len));
         else
             TRACE("row -> [0x%08x]\n", MSI_RecordGetInteger( rec, i ) );
     }
@@ -2392,19 +2400,17 @@ static void dump_record( MSIRECORD *rec )
 
 static void dump_table( const string_table *st, const USHORT *rawdata, UINT rawsize )
 {
-    LPCWSTR sval;
     UINT i;
-
-    for( i=0; i<(rawsize/2); i++ )
+    for (i = 0; i < rawsize / 2; i++)
     {
-        sval = msi_string_lookup_id( st, rawdata[i] );
-        MESSAGE(" %04x %s\n", rawdata[i], debugstr_w(sval) );
+        int len;
+        const WCHAR *sval = msi_string_lookup( st, rawdata[i], &len );
+        MESSAGE(" %04x %s\n", rawdata[i], debugstr_wn(sval, len) );
     }
 }
 
 static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
 {
-    LPCWSTR str;
     UINT i, r, *data;
 
     data = msi_alloc( tv->num_cols *sizeof (UINT) );
@@ -2419,10 +2425,11 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
         if ( ( tv->columns[i].type & MSITYPE_STRING ) &&
              ! MSITYPE_IS_BINARY(tv->columns[i].type) )
         {
-            str = MSI_RecordGetString( rec, i+1 );
+            int len;
+            const WCHAR *str = msi_record_get_string( rec, i+1, &len );
             if (str)
             {
-                r = msi_string2idW( tv->db->strings, str, &data[i] );
+                r = msi_string2id( tv->db->strings, str, len, &data[i] );
 
                 /* if there's no matching string in the string table,
                    these keys can't match any record, so fail now. */
index 4798917..441a54a 100644 (file)
 */
 typedef struct Keyword Keyword;
 struct Keyword {
-  const WCHAR *zName;             /* The keyword name */
+  const WCHAR *name;             /* The keyword name */
+  unsigned int len;
   int tokenType;           /* The token value for this keyword */
 };
 
 #define MAX_TOKEN_LEN 11
 
-static const WCHAR ADD_W[] = { 'A','D','D',0 };
-static const WCHAR ALTER_W[] = { 'A','L','T','E','R',0 };
-static const WCHAR AND_W[] = { 'A','N','D',0 };
-static const WCHAR BY_W[] = { 'B','Y',0 };
-static const WCHAR CHAR_W[] = { 'C','H','A','R',0 };
-static const WCHAR CHARACTER_W[] = { 'C','H','A','R','A','C','T','E','R',0 };
-static const WCHAR CREATE_W[] = { 'C','R','E','A','T','E',0 };
-static const WCHAR DELETE_W[] = { 'D','E','L','E','T','E',0 };
-static const WCHAR DISTINCT_W[] = { 'D','I','S','T','I','N','C','T',0 };
-static const WCHAR DROP_W[] = { 'D','R','O','P',0 };
-static const WCHAR FREE_W[] = { 'F','R','E','E',0 };
-static const WCHAR FROM_W[] = { 'F','R','O','M',0 };
-static const WCHAR HOLD_W[] = { 'H','O','L','D',0 };
-static const WCHAR INSERT_W[] = { 'I','N','S','E','R','T',0 };
-static const WCHAR INT_W[] = { 'I','N','T',0 };
-static const WCHAR INTEGER_W[] = { 'I','N','T','E','G','E','R',0 };
-static const WCHAR INTO_W[] = { 'I','N','T','O',0 };
-static const WCHAR IS_W[] = { 'I','S',0 };
-static const WCHAR KEY_W[] = { 'K','E','Y',0 };
-static const WCHAR LIKE_W[] = { 'L','I','K','E',0 };
-static const WCHAR LOCALIZABLE_W[] = { 'L','O','C','A','L','I','Z','A','B','L','E',0 };
-static const WCHAR LONG_W[] = { 'L','O','N','G',0 };
-static const WCHAR LONGCHAR_W[] = { 'L','O','N','G','C','H','A','R',0 };
-static const WCHAR NOT_W[] = { 'N','O','T',0 };
-static const WCHAR NULL_W[] = { 'N','U','L','L',0 };
-static const WCHAR OBJECT_W[] = { 'O','B','J','E','C','T',0 };
-static const WCHAR OR_W[] = { 'O','R',0 };
-static const WCHAR ORDER_W[] = { 'O','R','D','E','R',0 };
-static const WCHAR PRIMARY_W[] = { 'P','R','I','M','A','R','Y',0 };
-static const WCHAR SELECT_W[] = { 'S','E','L','E','C','T',0 };
-static const WCHAR SET_W[] = { 'S','E','T',0 };
-static const WCHAR SHORT_W[] = { 'S','H','O','R','T',0 };
-static const WCHAR TABLE_W[] = { 'T','A','B','L','E',0 };
-static const WCHAR TEMPORARY_W[] = { 'T','E','M','P','O','R','A','R','Y',0 };
-static const WCHAR UPDATE_W[] = { 'U','P','D','A','T','E',0 };
-static const WCHAR VALUES_W[] = { 'V','A','L','U','E','S',0 };
-static const WCHAR WHERE_W[] = { 'W','H','E','R','E',0 };
+static const WCHAR addW[] = {'A','D','D'};
+static const WCHAR alterW[] = {'A','L','T','E','R'};
+static const WCHAR andW[] = {'A','N','D'};
+static const WCHAR byW[] = {'B','Y'};
+static const WCHAR charW[] = {'C','H','A','R'};
+static const WCHAR characterW[] = {'C','H','A','R','A','C','T','E','R'};
+static const WCHAR createW[] = {'C','R','E','A','T','E'};
+static const WCHAR deleteW[] = {'D','E','L','E','T','E'};
+static const WCHAR distinctW[] = {'D','I','S','T','I','N','C','T'};
+static const WCHAR dropW[] = {'D','R','O','P'};
+static const WCHAR freeW[] = {'F','R','E','E'};
+static const WCHAR fromW[] = {'F','R','O','M'};
+static const WCHAR holdW[] = {'H','O','L','D'};
+static const WCHAR insertW[] = {'I','N','S','E','R','T'};
+static const WCHAR intW[] = {'I','N','T'};
+static const WCHAR integerW[] = {'I','N','T','E','G','E','R'};
+static const WCHAR intoW[] = {'I','N','T','O'};
+static const WCHAR isW[] = {'I','S'};
+static const WCHAR keyW[] = {'K','E','Y'};
+static const WCHAR likeW[] = {'L','I','K','E'};
+static const WCHAR localizableW[] = {'L','O','C','A','L','I','Z','A','B','L','E'};
+static const WCHAR longW[] = {'L','O','N','G'};
+static const WCHAR longcharW[] = {'L','O','N','G','C','H','A','R'};
+static const WCHAR notW[] = {'N','O','T'};
+static const WCHAR nullW[] = {'N','U','L','L'};
+static const WCHAR objectW[] = {'O','B','J','E','C','T'};
+static const WCHAR orW[] = {'O','R'};
+static const WCHAR orderW[] = {'O','R','D','E','R'};
+static const WCHAR primaryW[] = {'P','R','I','M','A','R','Y'};
+static const WCHAR selectW[] = {'S','E','L','E','C','T'};
+static const WCHAR setW[] = {'S','E','T'};
+static const WCHAR shortW[] = {'S','H','O','R','T'};
+static const WCHAR tableW[] = {'T','A','B','L','E'};
+static const WCHAR temporaryW[] = {'T','E','M','P','O','R','A','R','Y'};
+static const WCHAR updateW[] = {'U','P','D','A','T','E'};
+static const WCHAR valuesW[] = {'V','A','L','U','E','S'};
+static const WCHAR whereW[] = {'W','H','E','R','E'};
+
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
 
 /*
 ** These are the keywords
 ** They MUST be in alphabetical order
 */
 static const Keyword aKeywordTable[] = {
-  { ADD_W, TK_ADD },
-  { ALTER_W, TK_ALTER },
-  { AND_W, TK_AND },
-  { BY_W, TK_BY },
-  { CHAR_W, TK_CHAR },
-  { CHARACTER_W, TK_CHAR },
-  { CREATE_W, TK_CREATE },
-  { DELETE_W, TK_DELETE },
-  { DISTINCT_W, TK_DISTINCT },
-  { DROP_W, TK_DROP },
-  { FREE_W, TK_FREE },
-  { FROM_W, TK_FROM },
-  { HOLD_W, TK_HOLD },
-  { INSERT_W, TK_INSERT },
-  { INT_W, TK_INT },
-  { INTEGER_W, TK_INT },
-  { INTO_W, TK_INTO },
-  { IS_W, TK_IS },
-  { KEY_W, TK_KEY },
-  { LIKE_W, TK_LIKE },
-  { LOCALIZABLE_W, TK_LOCALIZABLE },
-  { LONG_W, TK_LONG },
-  { LONGCHAR_W, TK_LONGCHAR },
-  { NOT_W, TK_NOT },
-  { NULL_W, TK_NULL },
-  { OBJECT_W, TK_OBJECT },
-  { OR_W, TK_OR },
-  { ORDER_W, TK_ORDER },
-  { PRIMARY_W, TK_PRIMARY },
-  { SELECT_W, TK_SELECT },
-  { SET_W, TK_SET },
-  { SHORT_W, TK_SHORT },
-  { TABLE_W, TK_TABLE },
-  { TEMPORARY_W, TK_TEMPORARY },
-  { UPDATE_W, TK_UPDATE },
-  { VALUES_W, TK_VALUES },
-  { WHERE_W, TK_WHERE },
+  { addW,         ARRAY_SIZE(addW),         TK_ADD },
+  { alterW,       ARRAY_SIZE(alterW),       TK_ALTER },
+  { andW,         ARRAY_SIZE(andW),         TK_AND },
+  { byW,          ARRAY_SIZE(byW),          TK_BY },
+  { charW,        ARRAY_SIZE(charW),        TK_CHAR },
+  { characterW,   ARRAY_SIZE(characterW),   TK_CHAR },
+  { createW,      ARRAY_SIZE(createW),      TK_CREATE },
+  { deleteW,      ARRAY_SIZE(deleteW),      TK_DELETE },
+  { distinctW,    ARRAY_SIZE(distinctW),    TK_DISTINCT },
+  { dropW,        ARRAY_SIZE(dropW),        TK_DROP },
+  { freeW,        ARRAY_SIZE(freeW),        TK_FREE },
+  { fromW,        ARRAY_SIZE(fromW),        TK_FROM },
+  { holdW,        ARRAY_SIZE(holdW),        TK_HOLD },
+  { insertW,      ARRAY_SIZE(insertW),      TK_INSERT },
+  { intW,         ARRAY_SIZE(intW),         TK_INT },
+  { integerW,     ARRAY_SIZE(integerW),     TK_INT },
+  { intoW,        ARRAY_SIZE(intoW),        TK_INTO },
+  { isW,          ARRAY_SIZE(isW),          TK_IS },
+  { keyW,         ARRAY_SIZE(keyW),         TK_KEY },
+  { likeW,        ARRAY_SIZE(likeW),        TK_LIKE },
+  { localizableW, ARRAY_SIZE(localizableW), TK_LOCALIZABLE },
+  { longW,        ARRAY_SIZE(longW),        TK_LONG },
+  { longcharW,    ARRAY_SIZE(longcharW),    TK_LONGCHAR },
+  { notW,         ARRAY_SIZE(notW),         TK_NOT },
+  { nullW,        ARRAY_SIZE(nullW),        TK_NULL },
+  { objectW,      ARRAY_SIZE(objectW),      TK_OBJECT },
+  { orW,          ARRAY_SIZE(orW),          TK_OR },
+  { orderW,       ARRAY_SIZE(orderW),       TK_ORDER },
+  { primaryW,     ARRAY_SIZE(primaryW),     TK_PRIMARY },
+  { selectW,      ARRAY_SIZE(selectW),      TK_SELECT },
+  { setW,         ARRAY_SIZE(setW),         TK_SET },
+  { shortW,       ARRAY_SIZE(shortW),       TK_SHORT },
+  { tableW,       ARRAY_SIZE(tableW),       TK_TABLE },
+  { temporaryW,   ARRAY_SIZE(temporaryW),   TK_TEMPORARY },
+  { updateW,      ARRAY_SIZE(updateW),      TK_UPDATE },
+  { valuesW,      ARRAY_SIZE(valuesW),      TK_VALUES },
+  { whereW,       ARRAY_SIZE(whereW),       TK_WHERE },
 };
 
-#define KEYWORD_COUNT ( sizeof aKeywordTable/sizeof (Keyword) )
-
 /*
 ** Comparison function for binary search.
 */
 static int compKeyword(const void *m1, const void *m2){
   const Keyword *k1 = m1, *k2 = m2;
+  int ret, len = min( k1->len, k2->len );
 
-  return strcmpiW( k1->zName, k2->zName );
+  if ((ret = memicmpW( k1->name, k2->name, len ))) return ret;
+  if (k1->len < k2->len) return -1;
+  else if (k1->len > k2->len) return 1;
+  return 0;
 }
 
 /*
@@ -137,17 +142,15 @@ static int compKeyword(const void *m1, const void *m2){
 ** returned.  If the input is not a keyword, TK_ID is returned.
 */
 static int sqliteKeywordCode(const WCHAR *z, int n){
-  WCHAR str[MAX_TOKEN_LEN+1];
   Keyword key, *r;
 
   if( n>MAX_TOKEN_LEN )
     return TK_ID;
 
-  memcpy( str, z, n*sizeof (WCHAR) );
-  str[n] = 0;
   key.tokenType = 0;
-  key.zName = str;
-  r = bsearch( &key, aKeywordTable, KEYWORD_COUNT, sizeof (Keyword), compKeyword );
+  key.name = z;
+  key.len = n;
+  r = bsearch( &key, aKeywordTable, ARRAY_SIZE(aKeywordTable), sizeof(Keyword), compKeyword );
   if( r )
     return r->tokenType;
   return TK_ID;
index 9480661..cd0ec06 100644 (file)
@@ -88,7 +88,7 @@ static void append_productcode(MSIPACKAGE* package, LPCWSTR action_property,
         newprop[0] = 0;
     strcatW(newprop,productid);
 
-    r = msi_set_property( package->db, action_property, newprop );
+    r = msi_set_property( package->db, action_property, newprop, -1 );
     if (r == ERROR_SUCCESS && !strcmpW( action_property, szSourceDir ))
         msi_reset_folders( package, TRUE );
 
index 36c8ec8..1bf7788 100644 (file)
@@ -494,7 +494,7 @@ static UINT STRING_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
     case EXPR_COL_NUMBER_STRING:
         r = expr_fetch_value(&expr->u.column, rows, &val);
         if (r == ERROR_SUCCESS)
-            *str =  msi_string_lookup_id(wv->db->strings, val);
+            *str =  msi_string_lookup(wv->db->strings, val, NULL);
         else
             *str = NULL;
         break;
@@ -883,7 +883,7 @@ static UINT join_find_row( MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row )
     UINT r, i, id, data;
 
     str = MSI_RecordGetString( rec, 1 );
-    r = msi_string2idW( wv->db->strings, str, &id );
+    r = msi_string2id( wv->db->strings, str, -1, &id );
     if (r != ERROR_SUCCESS)
         return r;
 
@@ -1253,6 +1253,8 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables,
         if (r != ERROR_SUCCESS)
         {
             ERR("can't get table dimensions\n");
+            table->view->ops->delete(table->view);
+            msi_free(table);
             goto end;
         }
 
index f99e2dd..102df89 100644 (file)
@@ -103,7 +103,7 @@ reactos/dll/win32/msg711.acm      # Synced to Wine-1.5.4
 reactos/dll/win32/msgsm32.acm     # Synced to Wine-1.5.4
 reactos/dll/win32/mshtml          # Autosync
 reactos/dll/win32/mshtml.tlb      # Autosync
-reactos/dll/win32/msi             # Synced to Wine-1.5.10
+reactos/dll/win32/msi             # Synced to Wine-1.5.19
 reactos/dll/win32/msimg32         # Synced to Wine-1.5.4
 reactos/dll/win32/msimtf          # Synced to Wine-1.5.4
 reactos/dll/win32/msisip          # Synced to Wine-1.5.4