mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[MSI]: Sync to Wine 1.5.19.
svn path=/trunk/; revision=57851
This commit is contained in:
parent
8d198a629b
commit
13d789dd50
29 changed files with 1328 additions and 997 deletions
|
@ -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)
|
||||
if (!(cmd = msi_alloc( strlenW(dll) * sizeof(WCHAR) + sizeof(unregW) ))) 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 ))
|
||||
{
|
||||
HRESULT (WINAPI *func_ptr)( void );
|
||||
const char *func = unregister ? "DllUnregisterServer" : "DllRegisterServer";
|
||||
|
||||
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;
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -42,36 +42,116 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|||
#define REG_INDEX_CLASSES_ROOT 0
|
||||
#define REG_INDEX_DYN_DATA 6
|
||||
|
||||
typedef struct AutomationObject AutomationObject;
|
||||
|
||||
/* 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;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
typedef struct AutomationObject AutomationObject;
|
||||
|
||||
typedef HRESULT (*autoInvokeFunc)(AutomationObject* This,
|
||||
DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams,
|
||||
VARIANT* result, EXCEPINFO* ei, UINT* arg_err);
|
||||
|
||||
typedef void (*autoFreeFunc)(AutomationObject* This);
|
||||
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
WCHAR *prop, *ret;
|
||||
DWORD len = 0;
|
||||
UINT r;
|
||||
|
||||
val = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
||||
lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
|
||||
if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
|
||||
lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 );
|
||||
|
||||
ret = msi_dup_property(format->package->db, val);
|
||||
|
||||
msi_free(val);
|
||||
r = msi_get_property( format->package->db, prop, NULL, &len );
|
||||
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
|
||||
{
|
||||
msi_free( prop );
|
||||
return NULL;
|
||||
}
|
||||
len++;
|
||||
if ((ret = msi_alloc( len * sizeof(WCHAR) )))
|
||||
msi_get_property( format->package->db, prop, ret, &len );
|
||||
msi_free( prop );
|
||||
*ret_len = len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
|
||||
static WCHAR *deformat_component( FORMAT *format, FORMSTR *str, int *ret_len )
|
||||
{
|
||||
LPWSTR key, ret = NULL;
|
||||
WCHAR *key, *ret;
|
||||
MSICOMPONENT *comp;
|
||||
|
||||
key = msi_alloc((str->len + 1) * sizeof(WCHAR));
|
||||
if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
|
||||
lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
|
||||
|
||||
comp = msi_get_loaded_component(format->package, key);
|
||||
if (!comp)
|
||||
goto done;
|
||||
|
||||
if (!(comp = msi_get_loaded_component( format->package, key )))
|
||||
{
|
||||
msi_free( key );
|
||||
return NULL;
|
||||
}
|
||||
if (comp->Action == INSTALLSTATE_SOURCE)
|
||||
ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
|
||||
else
|
||||
ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
|
||||
|
||||
done:
|
||||
msi_free(key);
|
||||
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 );
|
||||
DWORD len;
|
||||
MSIRECORD *rec;
|
||||
|
||||
MSI_RecordSetStringW( rec, 0, ptr );
|
||||
MSI_FormatRecordW( package, rec, NULL, &size );
|
||||
|
||||
size++;
|
||||
*data = msi_alloc( size * sizeof(WCHAR) );
|
||||
if (size > 1) MSI_FormatRecordW( package, rec, *data, &size );
|
||||
else *data[0] = 0;
|
||||
|
||||
msiobj_release( &rec->hdr );
|
||||
return size * sizeof(WCHAR);
|
||||
}
|
||||
*data = NULL;
|
||||
return 0;
|
||||
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 0;
|
||||
}
|
||||
MSI_FormatRecordW( package, rec, *data, &len );
|
||||
msiobj_release( &rec->hdr );
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
rc = msi_get_property(db, szName, 0, &sz);
|
||||
if (!szValue || !*szValue)
|
||||
if (value && len < 0) len = strlenW( value );
|
||||
|
||||
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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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_record_get_string( const MSIRECORD *rec, UINT field, int *len )
|
||||
{
|
||||
if (field > rec->count)
|
||||
return NULL;
|
||||
|
||||
if (rec->fields[field].type != MSIFIELD_WSTR)
|
||||
return NULL;
|
||||
|
||||
if (len) *len = rec->fields[field].len;
|
||||
|
||||
return rec->fields[field].u.szwVal;
|
||||
}
|
||||
|
||||
const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
|
||||
{
|
||||
if( iField > rec->count )
|
||||
return NULL;
|
||||
|
||||
if( rec->fields[iField].type != MSIFIELD_WSTR )
|
||||
return NULL;
|
||||
|
||||
return rec->fields[iField].u.szwVal;
|
||||
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,72 +590,59 @@ 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_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len )
|
||||
{
|
||||
if (field > rec->count)
|
||||
return ERROR_INVALID_FIELD;
|
||||
|
||||
MSI_FreeField( &rec->fields[field] );
|
||||
|
||||
if (value && len < 0) len = strlenW( value );
|
||||
|
||||
if (value && len)
|
||||
{
|
||||
rec->fields[field].type = MSIFIELD_WSTR;
|
||||
rec->fields[field].u.szwVal = msi_strdupW( value, len );
|
||||
rec->fields[field].len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 )
|
||||
{
|
||||
LPWSTR str;
|
||||
|
||||
TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue));
|
||||
|
||||
if( iField > rec->count )
|
||||
return ERROR_INVALID_FIELD;
|
||||
|
||||
MSI_FreeField( &rec->fields[iField] );
|
||||
|
||||
if( szValue && szValue[0] )
|
||||
{
|
||||
str = strdupW( 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;
|
||||
return msi_record_set_string( rec, iField, szValue, -1 );
|
||||
}
|
||||
|
||||
UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, LPCWSTR szValue )
|
||||
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,20 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -32,103 +32,108 @@
|
|||
*/
|
||||
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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue