[MSI]: Sync to Wine 1.5.19.

svn path=/trunk/; revision=57851
This commit is contained in:
Amine Khaldi 2012-12-09 19:43:59 +00:00
parent 8d198a629b
commit 13d789dd50
29 changed files with 1328 additions and 997 deletions

View file

@ -353,7 +353,7 @@ UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine,
remove_quotes( val ); remove_quotes( val );
TRACE("Found commandline property %s = %s\n", debugstr_w(prop), debugstr_w(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 )) if (r == ERROR_SUCCESS && !strcmpW( prop, szSourceDir ))
msi_reset_folders( package, TRUE ); 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 ); check = msi_dup_property( package->db, szSourceDir );
if (!check || replace) 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) if (r == ERROR_SUCCESS)
msi_reset_folders( package, TRUE ); 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 ); check = msi_dup_property( package->db, szSOURCEDIR );
if (!check || replace) if (!check || replace)
msi_set_property( package->db, szSOURCEDIR, source ); msi_set_property( package->db, szSOURCEDIR, source, -1 );
msi_free( check ); msi_free( check );
msi_free( source ); msi_free( source );
@ -605,7 +605,7 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
{ {
TRACE("Running the actions\n"); 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); rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, package);
msiobj_release(&view->hdr); msiobj_release(&view->hdr);
} }
@ -809,6 +809,11 @@ INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp )
return INSTALLSTATE_UNKNOWN; return INSTALLSTATE_UNKNOWN;
} }
if (package->need_rollback) return comp->Installed; 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; return comp->ActionRequest;
} }
@ -1563,8 +1568,8 @@ static UINT load_all_folders( MSIPACKAGE *package )
static UINT ACTION_CostInitialize(MSIPACKAGE *package) static UINT ACTION_CostInitialize(MSIPACKAGE *package)
{ {
msi_set_property( package->db, szCostingComplete, szZero ); msi_set_property( package->db, szCostingComplete, szZero, -1 );
msi_set_property( package->db, szRootDrive, szCRoot ); msi_set_property( package->db, szRootDrive, szCRoot, -1 );
load_all_folders( package ); load_all_folders( package );
msi_load_all_components( package ); msi_load_all_components( package );
@ -1620,6 +1625,27 @@ static UINT ACTION_FileCost(MSIPACKAGE *package)
return ERROR_SUCCESS; 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) static void ACTION_GetComponentInstallStates(MSIPACKAGE *package)
{ {
MSICOMPONENT *comp; MSICOMPONENT *comp;
@ -1759,7 +1785,7 @@ static BOOL process_overrides( MSIPACKAGE *package, int level )
ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED ); ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED );
if (ret) if (ret)
msi_set_property( package->db, szPreselected, szOne ); msi_set_property( package->db, szPreselected, szOne, -1 );
return ret; return ret;
} }
@ -1956,8 +1982,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
continue; continue;
} }
TRACE("nobody wants component %s\n", debugstr_w(component->Component)); TRACE("nobody wants component %s\n", debugstr_w(component->Component));
if (component->anyAbsent && if (component->anyAbsent && component->ComponentId)
(component->Installed == INSTALLSTATE_LOCAL || component->Installed == INSTALLSTATE_SOURCE))
{ {
component->Action = INSTALLSTATE_ABSENT; component->Action = INSTALLSTATE_ABSENT;
component->ActionRequest = 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", TRACE("component %s (installed %d request %d action %d)\n",
debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action); 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; return ERROR_SUCCESS;
@ -2154,7 +2184,7 @@ WCHAR *msi_build_directory_name( DWORD count, ... )
const WCHAR *str = va_arg( va, const WCHAR * ); const WCHAR *str = va_arg( va, const WCHAR * );
if (!str) continue; if (!str) continue;
strcatW( dir, str ); 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 ); va_end( va );
return dir; return dir;
@ -2281,6 +2311,19 @@ WCHAR *msi_normalize_path( const WCHAR *in )
return ret; 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 ) void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop )
{ {
FolderList *fl; 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 (!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 ); 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 ); msi_free( normalized_path );
return; return;
} }
msi_set_property( package->db, folder->Directory, normalized_path ); msi_set_property( package->db, folder->Directory, normalized_path, -1 );
msi_free( folder->ResolvedTarget ); msi_free( folder->ResolvedTarget );
folder->ResolvedTarget = normalized_path; folder->ResolvedTarget = normalized_path;
@ -2354,6 +2398,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
else else
comp->Enabled = TRUE; comp->Enabled = TRUE;
} }
get_client_counts( package );
/* read components states from the registry */ /* read components states from the registry */
ACTION_GetComponentInstallStates(package); ACTION_GetComponentInstallStates(package);
@ -2376,28 +2421,28 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
TRACE("Calculating file cost\n"); TRACE("Calculating file cost\n");
calculate_file_cost( package ); 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 */ /* set default run level if not set */
level = msi_dup_property( package->db, szInstallLevel ); level = msi_dup_property( package->db, szInstallLevel );
if (!level) if (!level)
msi_set_property( package->db, szInstallLevel, szOne ); msi_set_property( package->db, szInstallLevel, szOne, -1 );
msi_free(level); msi_free(level);
/* FIXME: check volume disk space */ /* FIXME: check volume disk space */
msi_set_property( package->db, szOutOfDiskSpace, szZero ); msi_set_property( package->db, szOutOfDiskSpace, szZero, -1 );
return MSI_SetFeatureStates(package); 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) if (!value)
{ {
data = (LPSTR)strdupW(szEmpty); *size = sizeof(WCHAR);
*size = sizeof(szEmpty);
*type = REG_SZ; *type = REG_SZ;
if ((data = msi_alloc( *size ))) *(WCHAR *)data = 0;
return data; return data;
} }
if (value[0]=='#' && value[1]!='#' && value[1]!='%') if (value[0]=='#' && value[1]!='#' && value[1]!='%')
@ -2479,38 +2524,22 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, DWORD
} }
else else
{ {
static const WCHAR szMulti[] = {'[','~',']',0}; const WCHAR *ptr = value;
LPCWSTR ptr; DWORD len;
*type=REG_SZ;
if (value[0]=='#') *type = REG_SZ;
if (value[0] == '#')
{ {
if (value[1]=='%') ptr++;
if (value[1] == '%')
{ {
ptr = &value[2]; ptr++;
*type=REG_EXPAND_SZ; *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; return data;
} }
@ -2618,19 +2647,181 @@ static BOOL is_special_entry( const WCHAR *name )
return (name && (name[0] == '*' || name[0] == '+') && !name[1]); 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) static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
{ {
MSIPACKAGE *package = param; MSIPACKAGE *package = param;
LPSTR value; BYTE *new_value, *old_value = NULL;
HKEY root_key, hkey; HKEY root_key, hkey;
DWORD type,size; DWORD type, old_type, new_size, old_size = 0;
LPWSTR deformated, uikey, keypath; LPWSTR deformated, uikey, keypath;
LPCWSTR szRoot, component, name, key; const WCHAR *szRoot, *component, *name, *key, *str;
MSICOMPONENT *comp; MSICOMPONENT *comp;
MSIRECORD * uirow; MSIRECORD * uirow;
INT root; INT root;
BOOL check_first = FALSE; BOOL check_first = FALSE;
UINT rc; int len;
msi_ui_progress( package, 2, REG_PROGRESS_VALUE, 0, 0 ); 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; return ERROR_SUCCESS;
deformat_string(package, key , &deformated); deformat_string(package, key , &deformated);
size = strlenW(deformated) + strlenW(szRoot) + 1; uikey = msi_alloc( (strlenW(deformated) + strlenW(szRoot) + 1) * sizeof(WCHAR) );
uikey = msi_alloc(size*sizeof(WCHAR));
strcpyW(uikey,szRoot); strcpyW(uikey,szRoot);
strcatW(uikey,deformated); strcatW(uikey,deformated);
@ -2678,34 +2868,46 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
msi_free(keypath); msi_free(keypath);
return ERROR_FUNCTION_FAILED; 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); deformat_string(package, name, &deformated);
if (!is_special_entry( name )) 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) if (!check_first)
{ {
TRACE("Setting value %s of %s\n", debugstr_w(deformated), TRACE("setting value %s of %s type %u\n", debugstr_w(deformated), debugstr_w(uikey), type);
debugstr_w(uikey)); RegSetValueExW( hkey, deformated, 0, type, new_value, new_size );
RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value, size);
} }
else else if (!old_value)
{ {
DWORD sz = 0; if (deformated || new_size)
rc = RegQueryValueExW(hkey, deformated, NULL, NULL, NULL, &sz);
if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
{ {
TRACE("value %s of %s checked already exists\n", debugstr_w(deformated), TRACE("setting value %s of %s type %u\n", debugstr_w(deformated), debugstr_w(uikey), type);
debugstr_w(uikey)); RegSetValueExW( hkey, deformated, 0, type, new_value, new_size );
}
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);
} }
} }
else TRACE("not overwriting existing value %s of %s\n", debugstr_w(deformated), debugstr_w(uikey));
} }
RegCloseKey(hkey); RegCloseKey(hkey);
@ -2713,11 +2915,12 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
MSI_RecordSetStringW(uirow,2,deformated); MSI_RecordSetStringW(uirow,2,deformated);
MSI_RecordSetStringW(uirow,1,uikey); MSI_RecordSetStringW(uirow,1,uikey);
if (type == REG_SZ || type == REG_EXPAND_SZ) 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 ); msi_ui_actiondata( package, szWriteRegistryValues, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
msi_free(value); msi_free(new_value);
msi_free(old_value);
msi_free(deformated); msi_free(deformated);
msi_free(uikey); msi_free(uikey);
msi_free(keypath); msi_free(keypath);
@ -3293,9 +3496,9 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
if (package->need_rollback) action = comp->Installed; if (package->need_rollback) action = comp->Installed;
else action = comp->ActionRequest; 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->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) if (action == INSTALLSTATE_LOCAL || action == INSTALLSTATE_SOURCE)
{ {
@ -3357,11 +3560,14 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
RegCloseKey(hkey); RegCloseKey(hkey);
} }
else if (action == INSTALLSTATE_ABSENT) else if (action == INSTALLSTATE_ABSENT)
{
if (comp->num_clients <= 0)
{ {
if (package->Context == MSIINSTALLCONTEXT_MACHINE) if (package->Context == MSIINSTALLCONTEXT_MACHINE)
MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid); MSIREG_DeleteUserDataComponentKey( comp->ComponentId, szLocalSid );
else else
MSIREG_DeleteUserDataComponentKey(comp->ComponentId, NULL); MSIREG_DeleteUserDataComponentKey( comp->ComponentId, NULL );
}
} }
/* UI stuff */ /* UI stuff */
@ -4514,27 +4720,27 @@ static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
static void register_dll( const WCHAR *dll, BOOL unregister ) 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 (!(cmd = msi_alloc( strlenW(dll) * sizeof(WCHAR) + sizeof(unregW) ))) return;
if (hmod)
{
HRESULT (WINAPI *func_ptr)( void );
const char *func = unregister ? "DllUnregisterServer" : "DllRegisterServer";
func_ptr = (void *)GetProcAddress( hmod, func ); if (unregister) sprintfW( cmd, unregW, dll );
if (func_ptr) else sprintfW( cmd, regW, dll );
memset( &si, 0, sizeof(STARTUPINFOW) );
if (CreateProcessW( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
{ {
HRESULT hr = func_ptr(); CloseHandle( pi.hThread );
if (FAILED( hr )) msi_dialog_check_messages( pi.hProcess );
WARN("failed to register dll 0x%08x\n", hr); CloseHandle( pi.hProcess );
} }
else msi_free( cmd );
WARN("entry point %s not found\n", func);
FreeLibrary( hmod );
return;
}
WARN("failed to load library %u\n", GetLastError());
} }
static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param) 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}; {'H','e','l','p','T','e','l','e','p','h','o','n','e',0};
static const WCHAR szARPINSTALLLOCATION[] = static const WCHAR szARPINSTALLLOCATION[] =
{'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0}; {'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[] = static const WCHAR szManufacturer[] =
{'M','a','n','u','f','a','c','t','u','r','e','r',0}; {'M','a','n','u','f','a','c','t','u','r','e','r',0};
static const WCHAR szPublisher[] = 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 ); 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, szModifyPath, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size);
RegSetValueExW(hkey, szUninstallString, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size); RegSetValueExW(hkey, szUninstallString, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size);
msi_free(buffer); 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; LPWSTR depends = NULL, pass = NULL, args = NULL, image_path = NULL;
DWORD serv_type, start_type, err_control; DWORD serv_type, start_type, err_control;
SERVICE_DESCRIPTIONW sd = {NULL}; SERVICE_DESCRIPTIONW sd = {NULL};
UINT ret = ERROR_SUCCESS;
comp = MSI_RecordGetString( rec, 12 ); comp = MSI_RecordGetString( rec, 12 );
component = msi_get_loaded_component( package, comp ); 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; int len = strlenW(file->TargetPath) + strlenW(args) + 2;
if (!(image_path = msi_alloc(len * sizeof(WCHAR)))) if (!(image_path = msi_alloc(len * sizeof(WCHAR))))
return ERROR_OUTOFMEMORY; {
ret = ERROR_OUTOFMEMORY;
goto done;
}
strcpyW(image_path, file->TargetPath); strcpyW(image_path, file->TargetPath);
strcatW(image_path, szSpace); strcatW(image_path, szSpace);
@ -5639,7 +5847,7 @@ done:
msi_free(depends); msi_free(depends);
msi_free(args); msi_free(args);
return ERROR_SUCCESS; return ret;
} }
static UINT ACTION_InstallServices( MSIPACKAGE *package ) 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; ENUM_SERVICE_STATUSW *dependencies;
SERVICE_STATUS ss; SERVICE_STATUS ss;
SC_HANDLE depserv; SC_HANDLE depserv;
BOOL stopped, ret = FALSE;
if (EnumDependentServicesW(service, SERVICE_ACTIVE, NULL, if (EnumDependentServicesW(service, SERVICE_ACTIVE, NULL,
0, &needed, &count)) 0, &needed, &count))
@ -5853,24 +6062,26 @@ static BOOL stop_service_dependents(SC_HANDLE scm, SC_HANDLE service)
if (!EnumDependentServicesW(service, SERVICE_ACTIVE, dependencies, if (!EnumDependentServicesW(service, SERVICE_ACTIVE, dependencies,
needed, &needed, &count)) needed, &needed, &count))
goto error; goto done;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
depserv = OpenServiceW(scm, dependencies[i].lpServiceName, depserv = OpenServiceW(scm, dependencies[i].lpServiceName,
SERVICE_STOP | SERVICE_QUERY_STATUS); SERVICE_STOP | SERVICE_QUERY_STATUS);
if (!depserv) if (!depserv)
goto error; goto done;
if (!ControlService(depserv, SERVICE_CONTROL_STOP, &ss)) stopped = ControlService(depserv, SERVICE_CONTROL_STOP, &ss);
goto error; CloseServiceHandle(depserv);
if (!stopped)
goto done;
} }
return TRUE; ret = TRUE;
error: done:
msi_free(dependencies); msi_free(dependencies);
return FALSE; return ret;
} }
static UINT stop_service( LPCWSTR name ) static UINT stop_service( LPCWSTR name )
@ -6959,7 +7170,7 @@ UINT msi_validate_product_id( MSIPACKAGE *package )
if (key && template) if (key && template)
{ {
FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) ); 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( template );
msi_free( key ); msi_free( key );
@ -6999,7 +7210,7 @@ static UINT ACTION_DisableRollback( MSIPACKAGE *package )
{ {
TRACE("%p\n", package); TRACE("%p\n", package);
msi_set_property( package->db, szRollbackDisabled, szOne ); msi_set_property( package->db, szRollbackDisabled, szOne, -1 );
return ERROR_SUCCESS; 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 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 szAction[] = {'A','C','T','I','O','N',0};
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0}; static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
WCHAR *reinstall = NULL; WCHAR *reinstall, *remove, *patch;
BOOL ui_exists; BOOL ui_exists;
UINT rc; UINT rc;
msi_set_property( package->db, szAction, szInstall ); msi_set_property( package->db, szAction, szInstall, -1 );
package->script->InWhatSequence = SEQUENCE_INSTALL; package->script->InWhatSequence = SEQUENCE_INSTALL;
@ -7567,10 +7778,13 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
msi_apply_transforms( package ); msi_apply_transforms( package );
msi_apply_patches( 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"); TRACE("setting REINSTALL property to ALL\n");
msi_set_property( package->db, szReinstall, szAll ); msi_set_property( package->db, szReinstall, szAll, -1 );
} }
/* properties may have been added by a transform */ /* 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 )) if (msi_get_property_int( package->db, szDisableRollback, 0 ))
{ {
TRACE("disabling rollback\n"); TRACE("disabling rollback\n");
msi_set_property( package->db, szRollbackDisabled, szOne ); msi_set_property( package->db, szRollbackDisabled, szOne, -1 );
} }
if (needs_ui_sequence( package)) if (needs_ui_sequence( package))
@ -7621,12 +7835,14 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
/* finish up running custom actions */ /* finish up running custom actions */
ACTION_FinishCustomActions(package); 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"); WARN("installation failed, running rollback script\n");
execute_script( package, SCRIPT_ROLLBACK ); execute_script( package, SCRIPT_ROLLBACK );
} }
msi_free( reinstall ); msi_free( reinstall );
msi_free( remove );
msi_free( patch );
if (rc == ERROR_SUCCESS && package->need_reboot_at_end) if (rc == ERROR_SUCCESS && package->need_reboot_at_end)
return ERROR_SUCCESS_REBOOT_REQUIRED; return ERROR_SUCCESS_REBOOT_REQUIRED;

View file

@ -1093,7 +1093,7 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
r = ACTION_AppSearchSigName(package, sigName, &sig, &value); r = ACTION_AppSearchSigName(package, sigName, &sig, &value);
if (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 )) if (r == ERROR_SUCCESS && !strcmpW( propName, szSourceDir ))
msi_reset_folders( package, TRUE ); msi_reset_folders( package, TRUE );
@ -1153,7 +1153,7 @@ static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
if (value) if (value)
{ {
TRACE("Found signature %s\n", debugstr_w(signature)); 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); msi_free(value);
r = ERROR_NO_MORE_ITEMS; r = ERROR_NO_MORE_ITEMS;
} }

View file

@ -42,36 +42,116 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
#define REG_INDEX_CLASSES_ROOT 0 #define REG_INDEX_CLASSES_ROOT 0
#define REG_INDEX_DYN_DATA 6 #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 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
* called from AutomationObject::Invoke. * 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 { struct AutomationObject {
IDispatch IDispatch_iface; IDispatch IDispatch_iface;
IProvideMultipleClassInfo IProvideMultipleClassInfo_iface; IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
LONG ref; LONG ref;
/* Clsid for this class and it's appropriate ITypeInfo object */ /* type id for this class */
LPCLSID clsid; tid_t tid;
ITypeInfo *iTypeInfo;
/* The MSI handle of the current object */ /* The MSI handle of the current object */
MSIHANDLE msiHandle; 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 { typedef struct {
@ -110,37 +190,6 @@ static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
return CONTAINING_RECORD(iface, AutomationObject, 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 */ /* AutomationObject methods */
static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject) 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) || if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IDispatch) ||
IsEqualGUID(riid, This->clsid)) IsEqualGUID(riid, get_riid_from_tid(This->tid)))
*ppvObject = &This->IDispatch_iface; *ppvObject = &This->IDispatch_iface;
else if (IsEqualGUID(riid, &IID_IProvideClassInfo) || else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
IsEqualGUID(riid, &IID_IProvideClassInfo2) || IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
@ -190,8 +239,7 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
if (!ref) if (!ref)
{ {
if (This->funcFree) This->funcFree(This); if (tid_ids[This->tid].fn_free) tid_ids[This->tid].fn_free(This);
ITypeInfo_Release(This->iTypeInfo);
MsiCloseHandle(This->msiHandle); MsiCloseHandle(This->msiHandle);
msi_free(This); msi_free(This);
} }
@ -217,11 +265,16 @@ static HRESULT WINAPI AutomationObject_GetTypeInfo(
ITypeInfo** ppTInfo) ITypeInfo** ppTInfo)
{ {
AutomationObject *This = impl_from_IDispatch(iface); AutomationObject *This = impl_from_IDispatch(iface);
HRESULT hr;
TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo); TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
ITypeInfo_AddRef(This->iTypeInfo); hr = get_typeinfo(This->tid, ppTInfo);
*ppTInfo = This->iTypeInfo; if (FAILED(hr))
return S_OK; return hr;
ITypeInfo_AddRef(*ppTInfo);
return hr;
} }
static HRESULT WINAPI AutomationObject_GetIDsOfNames( static HRESULT WINAPI AutomationObject_GetIDsOfNames(
@ -233,18 +286,25 @@ static HRESULT WINAPI AutomationObject_GetIDsOfNames(
DISPID* rgDispId) DISPID* rgDispId)
{ {
AutomationObject *This = impl_from_IDispatch(iface); AutomationObject *This = impl_from_IDispatch(iface);
ITypeInfo *ti;
HRESULT hr; HRESULT hr;
TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId); TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId);
if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG; 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) if (hr == DISP_E_UNKNOWNNAME)
{ {
UINT idx; UINT idx;
for (idx=0; idx<cNames; idx++) for (idx=0; idx<cNames; idx++)
{ {
if (rgDispId[idx] == DISPID_UNKNOWN) 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; return hr;
@ -270,6 +330,7 @@ static HRESULT WINAPI AutomationObject_Invoke(
unsigned int uArgErr; unsigned int uArgErr;
VARIANT varResultDummy; VARIANT varResultDummy;
BSTR bstrName = NULL; 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); 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 (puArgErr == NULL) puArgErr = &uArgErr;
if (pVarResult == NULL) pVarResult = &varResultDummy; if (pVarResult == NULL) pVarResult = &varResultDummy;
hr = get_typeinfo(This->tid, &ti);
if (FAILED(hr))
return hr;
/* Assume return type is void unless determined otherwise */ /* Assume return type is void unless determined otherwise */
VariantInit(pVarResult); VariantInit(pVarResult);
/* If we are tracing, we want to see the name of the member we are invoking */ /* If we are tracing, we want to see the name of the member we are invoking */
if (TRACE_ON(msi)) 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)); 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 (hr == DISP_E_MEMBERNOTFOUND) {
if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); 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(This->clsid)); 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 && else if (pExcepInfo &&
(hr == DISP_E_PARAMNOTFOUND || (hr == DISP_E_PARAMNOTFOUND ||
@ -315,7 +381,7 @@ static HRESULT WINAPI AutomationObject_Invoke(
unsigned namesNo, i; unsigned namesNo, i;
BOOL bFirst = TRUE; BOOL bFirst = TRUE;
if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames, if (FAILED(ITypeInfo_GetNames(ti, dispIdMember, bstrParamNames,
MAX_FUNC_PARAMS, &namesNo))) MAX_FUNC_PARAMS, &namesNo)))
{ {
TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember); 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) static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
{ {
AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
HRESULT hr;
TRACE("(%p/%p)->(%p)\n", iface, This, ppTI); 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) 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) if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
return E_INVALIDARG; return E_INVALIDARG;
else { else {
*pGUID = *This->clsid; *pGUID = *get_riid_from_tid(This->tid);
return S_OK; return S_OK;
} }
} }
@ -420,7 +493,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMul
static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface, static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
ULONG iti, ULONG iti,
DWORD dwFlags, DWORD dwFlags,
ITypeInfo** pptiCoClass, ITypeInfo** ti,
DWORD* pdwTIFlags, DWORD* pdwTIFlags,
ULONG* pcdispidReserved, ULONG* pcdispidReserved,
IID* piidPrimary, IID* piidPrimary,
@ -428,13 +501,19 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl
{ {
AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 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) if (iti != 0)
return E_INVALIDARG; return E_INVALIDARG;
if (dwFlags & MULTICLASSINFO_GETTYPEINFO) 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) if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
{ {
@ -442,13 +521,11 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl
*pcdispidReserved = 0; *pcdispidReserved = 0;
} }
if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){ if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY)
*piidPrimary = *This->clsid; *piidPrimary = *get_riid_from_tid(This->tid);
}
if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){ if (dwFlags & MULTICLASSINFO_GETIIDSOURCE)
*piidSource = *This->clsid; *piidSource = *get_riid_from_tid(This->tid);
}
return S_OK; return S_OK;
} }
@ -464,23 +541,18 @@ static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
ProvideMultipleClassInfo_GetInfoOfIndex ProvideMultipleClassInfo_GetInfoOfIndex
}; };
static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid, static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, tid_t tid)
autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
{ {
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->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl; This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
This->ref = 1; This->ref = 1;
This->msiHandle = msiHandle; This->msiHandle = msiHandle;
This->clsid = (LPCLSID)clsid; This->tid = tid;
This->funcInvoke = invokeFunc;
This->funcFree = freeFunc;
/* Load our TypeInfo so we don't have to process GetIDsOfNames */ return S_OK;
This->iTypeInfo = NULL;
return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0);
} }
/* /*
@ -682,7 +754,7 @@ static HRESULT DispGetParam_CopyOnly(
&pdispparams->rgvarg[pos]); &pdispparams->rgvarg[pos]);
} }
static HRESULT SummaryInfoImpl_Invoke( static HRESULT summaryinfo_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -834,7 +906,7 @@ static HRESULT SummaryInfoImpl_Invoke(
return S_OK; return S_OK;
} }
static HRESULT RecordImpl_Invoke( static HRESULT record_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -846,7 +918,7 @@ static HRESULT RecordImpl_Invoke(
UINT* puArgErr) UINT* puArgErr)
{ {
WCHAR *szString; WCHAR *szString;
DWORD dwLen; DWORD dwLen = 0;
UINT ret; UINT ret;
VARIANTARG varg0, varg1; VARIANTARG varg0, varg1;
HRESULT hr; HRESULT hr;
@ -933,7 +1005,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
record = msi_alloc(sizeof(*record)); record = msi_alloc(sizeof(*record));
if (!record) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(record); msi_free(record);
@ -945,7 +1017,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
return hr; return hr;
} }
static HRESULT ListImpl_Invoke( static HRESULT list_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -1002,7 +1074,7 @@ static HRESULT ListImpl_Invoke(
return S_OK; return S_OK;
} }
static void ListImpl_Free(AutomationObject *This) static void list_free(AutomationObject *This)
{ {
ListObject *list = (ListObject*)This; ListObject *list = (ListObject*)This;
int i; int i;
@ -1049,7 +1121,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
list = msi_alloc_zero(sizeof(ListObject)); list = msi_alloc_zero(sizeof(ListObject));
if (!list) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(list); msi_free(list);
@ -1092,7 +1164,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
return S_OK; return S_OK;
} }
static HRESULT ViewImpl_Invoke( static HRESULT view_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -1200,7 +1272,7 @@ static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
return S_OK; return S_OK;
} }
static HRESULT DatabaseImpl_Invoke( HRESULT database_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -1285,7 +1357,7 @@ static HRESULT DatabaseImpl_Invoke(
return S_OK; return S_OK;
} }
static HRESULT SessionImpl_Invoke( static HRESULT session_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -2250,7 +2322,7 @@ static HRESULT InstallerImpl_RelatedProducts(WORD flags,
return hr; return hr;
} }
static HRESULT InstallerImpl_Invoke( static HRESULT installer_invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
REFIID riid, REFIID riid,
@ -2363,7 +2435,7 @@ HRESULT create_msiserver(IUnknown *outer, void **ppObj)
installer = msi_alloc(sizeof(AutomationObject)); installer = msi_alloc(sizeof(AutomationObject));
if (!installer) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(installer); msi_free(installer);
@ -2383,7 +2455,7 @@ HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **di
session = msi_alloc(sizeof(SessionObject)); session = msi_alloc(sizeof(SessionObject));
if (!session) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(session); msi_free(session);
@ -2406,7 +2478,7 @@ static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
database = msi_alloc(sizeof(AutomationObject)); database = msi_alloc(sizeof(AutomationObject));
if (!database) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(database); msi_free(database);
@ -2428,7 +2500,7 @@ static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
view = msi_alloc(sizeof(AutomationObject)); view = msi_alloc(sizeof(AutomationObject));
if (!view) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(view); msi_free(view);
@ -2448,7 +2520,7 @@ static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
info = msi_alloc(sizeof(*info)); info = msi_alloc(sizeof(*info));
if (!info) return E_OUTOFMEMORY; 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) if (hr != S_OK)
{ {
msi_free(info); msi_free(info);

View file

@ -184,25 +184,21 @@ static LPWSTR msi_get_deferred_action(LPCWSTR action, LPCWSTR actiondata,
return deferred; 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}; static const WCHAR sep[] = {'<','=','>',0};
const WCHAR *end, *beg = deferred_data + 1;
end = strstrW(beg, sep); end = strstrW(beg, sep);
*end = '\0'; msi_set_property( package->db, szCustomActionData, beg, end - beg );
msi_set_property(package->db, szCustomActionData, beg);
beg = end + 3; beg = end + 3;
end = strstrW(beg, sep); end = strstrW(beg, sep);
*end = '\0'; msi_set_property( package->db, szUserSID, beg, end - beg );
msi_set_property(package->db, szUserSID, beg);
beg = end + 3; beg = end + 3;
end = strchrW(beg, ']'); end = strchrW(beg, ']');
*end = '\0'; msi_set_property( package->db, szProductCode, beg, end - beg );
msi_set_property(package->db, szProductCode, beg);
} }
static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL dll ) 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; UINT rc = ERROR_SUCCESS;
MSIRECORD *row; MSIRECORD *row;
UINT type; UINT type;
LPCWSTR source, target; const WCHAR *source, *target, *ptr, *deferred_data = NULL;
LPWSTR ptr, deferred_data = NULL; WCHAR *deformated = NULL;
LPWSTR deformated = NULL, action_copy = strdupW(action); int len;
/* deferred action: [properties]Action */ /* deferred action: [properties]Action */
if ((ptr = strrchrW(action_copy, ']'))) if ((ptr = strrchrW(action, ']')))
{ {
deferred_data = action_copy; deferred_data = action;
action = ptr + 1; action = ptr + 1;
} }
row = MSI_QueryGetRecord( package->db, query, action ); row = MSI_QueryGetRecord( package->db, query, action );
if (!row) if (!row)
{
msi_free(action_copy);
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
}
type = MSI_RecordGetInteger(row,2); type = MSI_RecordGetInteger(row,2);
source = MSI_RecordGetString(row,3); source = MSI_RecordGetString(row,3);
@ -1284,9 +1277,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
if (deferred_data) if (deferred_data)
set_deferred_action_props(package, deferred_data); set_deferred_action_props(package, deferred_data);
else if (actiondata) else if (actiondata)
msi_set_property(package->db, szCustomActionData, actiondata); msi_set_property( package->db, szCustomActionData, actiondata, -1 );
else else
msi_set_property(package->db, szCustomActionData, szEmpty); msi_set_property( package->db, szCustomActionData, szEmpty, -1 );
msi_free(actiondata); msi_free(actiondata);
} }
@ -1334,8 +1327,8 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL
if (!source) if (!source)
break; break;
deformat_string(package,target,&deformated); len = deformat_string( package, target, &deformated );
rc = msi_set_property( package->db, source, deformated ); rc = msi_set_property( package->db, source, deformated, len );
if (rc == ERROR_SUCCESS && !strcmpW( source, szSourceDir )) if (rc == ERROR_SUCCESS && !strcmpW( source, szSourceDir ))
msi_reset_folders( package, TRUE ); msi_reset_folders( package, TRUE );
msi_free(deformated); msi_free(deformated);
@ -1365,7 +1358,6 @@ end:
package->scheduled_action_running = FALSE; package->scheduled_action_running = FALSE;
package->commit_action_running = FALSE; package->commit_action_running = FALSE;
package->rollback_action_running = FALSE; package->rollback_action_running = FALSE;
msi_free(action_copy);
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
return rc; return rc;
} }

View file

@ -130,7 +130,7 @@ UINT msi_clone_open_stream( MSIDATABASE *db, IStorage *stg, LPCWSTR name, IStrea
UINT msi_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) UINT msi_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
{ {
HRESULT r; HRESULT r;
IStorage *stg = 0; IStorage *stg;
WCHAR decoded[MAX_STREAM_NAME_LEN]; WCHAR decoded[MAX_STREAM_NAME_LEN];
decode_streamname( stname, decoded ); decode_streamname( stname, decoded );

View file

@ -309,7 +309,7 @@ static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
/* create a font and add it to the list */ /* create a font and add it to the list */
name = MSI_RecordGetString( rec, 1 ); 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 ); strcpyW( font->name, name );
list_add_head( &dialog->fonts, &font->entry ); list_add_head( &dialog->fonts, &font->entry );
@ -414,7 +414,7 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
style |= WS_CHILD; 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) if (!control)
return NULL; 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 ) 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 )) if (r == ERROR_SUCCESS && !strcmpW( property, szSourceDir ))
msi_reset_folders( package, TRUE ); 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 ) || if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) ||
!strcmpW( argument, error_no ) ) !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); ControlEvent_CleanupSubscriptions(package);

View file

@ -173,7 +173,7 @@ static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_di
if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
{ {
if (feature->ActionRequest != INSTALLSTATE_LOCAL) 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 ); 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 (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
{ {
if (feature->ActionRequest != INSTALLSTATE_ABSENT) 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 ); 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 (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll ))
{ {
if (feature->ActionRequest != INSTALLSTATE_SOURCE) 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 ); 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, static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument,
msi_dialog *dialog) 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, static UINT ControlEvent_Reinstall( MSIPACKAGE *package, LPCWSTR argument,
msi_dialog *dialog ) 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, static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,

View file

@ -69,7 +69,6 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil
VS_FIXEDFILEINFO *file_version; VS_FIXEDFILEINFO *file_version;
WCHAR *font_version; WCHAR *font_version;
msi_file_state state; msi_file_state state;
DWORD file_size;
comp->Action = msi_get_component_action( package, comp ); comp->Action = msi_get_component_action( package, comp );
if (comp->Action != INSTALLSTATE_LOCAL || (comp->assembly && comp->assembly->installed)) 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; 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; return msifs_overwrite;
} }
@ -336,7 +335,8 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc); 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; if (!file->Component->Enabled) continue;
@ -513,7 +513,8 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc); 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 ); comp->Action = msi_get_component_action( package, comp );
if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue; 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; LPWSTR sourcedir, destname = NULL, destdir = NULL, source = NULL, dest = NULL;
int options; int options;
DWORD size; DWORD size;
BOOL ret, wildcards; BOOL wildcards;
component = MSI_RecordGetString(rec, 2); component = MSI_RecordGetString(rec, 2);
comp = msi_get_loaded_component(package, component); 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 (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()); WARN("failed to create directory %u\n", GetLastError());
goto done; goto done;

View file

@ -140,130 +140,146 @@ static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str)
return &format->deformatted[str->n]; 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; WCHAR *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);
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; 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); 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; 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)); if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
lstrcpynW(val, get_formstr_data(format, str), str->len + 1); lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 );
ret = msi_dup_property(format->package->db, val); r = msi_get_property( format->package->db, prop, NULL, &len );
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
msi_free(val); {
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; 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; 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); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
comp = msi_get_loaded_component(format->package, key); if (!(comp = msi_get_loaded_component( format->package, key )))
if (!comp) {
goto done; msi_free( key );
return NULL;
}
if (comp->Action == INSTALLSTATE_SOURCE) if (comp->Action == INSTALLSTATE_SOURCE)
ret = msi_resolve_source_folder( format->package, comp->Directory, NULL ); ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
else else
ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) ); ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
done: if (ret) *ret_len = strlenW( ret );
msi_free(key); else *ret_len = 0;
msi_free( key );
return ret; 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; WCHAR *key, *ret = NULL;
MSIFILE *file; const MSIFILE *file;
DWORD size; 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); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
file = msi_get_loaded_file(format->package, key); if (!(file = msi_get_loaded_file( format->package, key ))) goto done;
if (!file)
goto done;
if (!shortname) if (!shortname)
{ {
ret = strdupW(file->TargetPath); if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
goto done; goto done;
} }
if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0)
size = GetShortPathNameW(file->TargetPath, NULL, 0);
if (size <= 0)
{ {
ret = strdupW(file->TargetPath); if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
goto done; goto done;
} }
len++;
size++; if ((ret = msi_alloc( len * sizeof(WCHAR) )))
ret = msi_alloc(size * sizeof(WCHAR)); len = GetShortPathNameW( file->TargetPath, ret, len );
GetShortPathNameW(file->TargetPath, ret, size);
done: done:
msi_free(key); msi_free( key );
*ret_len = len;
return ret; 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; WCHAR *key, *ret = NULL;
DWORD sz; 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); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
sz = GetEnvironmentVariableW(key, NULL ,0); if ((len = GetEnvironmentVariableW( key, NULL, 0 )))
if (sz <= 0) {
goto done; len++;
if ((ret = msi_alloc( len * sizeof(WCHAR) )))
sz++; *ret_len = GetEnvironmentVariableW( key, ret, len );
ret = msi_alloc(sz * sizeof(WCHAR)); }
GetEnvironmentVariableW(key, ret, sz); msi_free( key );
done:
msi_free(key);
return ret; return ret;
} }
static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, static WCHAR *deformat_literal( FORMAT *format, FORMSTR *str, BOOL *propfound,
BOOL *nonprop, int *type) BOOL *nonprop, int *type, int *len )
{ {
LPCWSTR data = get_formstr_data(format, str); LPCWSTR data = get_formstr_data(format, str);
LPWSTR replaced = NULL; WCHAR *replaced = NULL;
char ch = data[0]; char ch = data[0];
if (ch == '\\') if (ch == '\\')
@ -277,17 +293,17 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
else else
{ {
str->len = 1; str->len = 1;
replaced = dup_formstr(format, str); replaced = dup_formstr( format, str, len );
} }
} }
else if (ch == '~') else if (ch == '~')
{ {
if (str->len != 1) if (str->len != 1)
replaced = NULL; 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 == '$') else if (ch == '%' || ch == '#' || ch == '!' || ch == '$')
@ -298,20 +314,20 @@ static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound,
switch (ch) switch (ch)
{ {
case '%': case '%':
replaced = deformat_environment(format, str); break; replaced = deformat_environment( format, str, len ); break;
case '#': case '#':
replaced = deformat_file(format, str, FALSE); break; replaced = deformat_file( format, str, FALSE, len ); break;
case '!': case '!':
replaced = deformat_file(format, str, TRUE); break; replaced = deformat_file( format, str, TRUE, len ); break;
case '$': case '$':
replaced = deformat_component(format, str); break; replaced = deformat_component( format, str, len ); break;
} }
*type = FORMAT_LITERAL; *type = FORMAT_LITERAL;
} }
else else
{ {
replaced = deformat_property(format, str); replaced = deformat_property( format, str, len );
*type = FORMAT_LITERAL; *type = FORMAT_LITERAL;
if (replaced) if (replaced)
@ -489,8 +505,8 @@ static int format_lex(FORMAT *format, FORMSTR **out)
return type; return type;
} }
static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, static FORMSTR *format_replace( FORMAT *format, BOOL propfound, BOOL nonprop,
int oldsize, int type, LPWSTR replace) int oldsize, int type, WCHAR *replace, int len )
{ {
FORMSTR *ret; FORMSTR *ret;
LPWSTR str, ptr; LPWSTR str, ptr;
@ -499,10 +515,10 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
if (replace) if (replace)
{ {
if (!*replace) if (!len)
size = 1; size = 1;
else else
size = lstrlenW(replace); size = len;
} }
size -= oldsize; size -= oldsize;
@ -526,15 +542,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
if (replace) if (replace)
{ {
if (!*replace) if (!len) str[n++] = 0;
{
str[n] = '\0';
n++;
}
else else
{ {
lstrcpyW(&str[n], replace); memcpy( str + n, replace, len * sizeof(WCHAR) );
n += lstrlenW(replace); n += len;
str[n] = 0;
} }
} }
@ -546,7 +559,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
format->len = size - 1; format->len = size - 1;
/* don't reformat the NULL */ /* don't reformat the NULL */
if (replace && !*replace) if (replace && !len)
format->n++; format->n++;
if (!replace) if (!replace)
@ -556,7 +569,7 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
if (!ret) if (!ret)
return NULL; return NULL;
ret->len = lstrlenW(replace); ret->len = len;
ret->type = type; ret->type = type;
ret->n = format->n; ret->n = format->n;
ret->propfound = propfound; ret->propfound = propfound;
@ -565,13 +578,12 @@ static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop,
return ret; return ret;
} }
static LPWSTR replace_stack_group(FORMAT *format, STACK *values, static WCHAR *replace_stack_group( FORMAT *format, STACK *values,
BOOL *propfound, BOOL *nonprop, BOOL *propfound, BOOL *nonprop,
int *oldsize, int *type) int *oldsize, int *type, int *len )
{ {
LPWSTR replaced = NULL; WCHAR *replaced;
FORMSTR *content; FORMSTR *content, *node;
FORMSTR *node;
int n; int n;
*nonprop = FALSE; *nonprop = FALSE;
@ -626,7 +638,7 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
*nonprop = TRUE; *nonprop = TRUE;
} }
replaced = dup_formstr(format, content); replaced = dup_formstr( format, content, len );
*type = content->type; *type = content->type;
msi_free(content); msi_free(content);
@ -636,13 +648,12 @@ static LPWSTR replace_stack_group(FORMAT *format, STACK *values,
return replaced; return replaced;
} }
static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, static WCHAR *replace_stack_prop( FORMAT *format, STACK *values,
BOOL *propfound, BOOL *nonprop, BOOL *propfound, BOOL *nonprop,
int *oldsize, int *type) int *oldsize, int *type, int *len )
{ {
LPWSTR replaced = NULL; WCHAR *replaced;
FORMSTR *content; FORMSTR *content, *node;
FORMSTR *node;
int n; int n;
*propfound = FALSE; *propfound = FALSE;
@ -672,7 +683,7 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
if (*type == FORMAT_NUMBER) if (*type == FORMAT_NUMBER)
{ {
replaced = deformat_index(format, content); replaced = deformat_index( format, content, len );
if (replaced) if (replaced)
*propfound = TRUE; *propfound = TRUE;
else else
@ -684,48 +695,42 @@ static LPWSTR replace_stack_prop(FORMAT *format, STACK *values,
} }
else if (format->package) else if (format->package)
{ {
replaced = deformat_literal(format, content, propfound, nonprop, type); replaced = deformat_literal( format, content, propfound, nonprop, type, len );
} }
else else
{ {
*nonprop = TRUE; *nonprop = TRUE;
content->n--; content->n--;
content->len += 2; content->len += 2;
replaced = dup_formstr(format, content); replaced = dup_formstr( format, content, len );
} }
msi_free(content); msi_free(content);
return replaced; return replaced;
} }
static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values) static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
{ {
LPWSTR replaced = NULL; WCHAR *replaced = NULL;
FORMSTR *beg; FORMSTR *beg, *top, *node;
FORMSTR *top; BOOL propfound = FALSE, nonprop = FALSE, group = FALSE;
FORMSTR *node; int type, n, len = 0, oldsize = 0;
BOOL propfound = FALSE;
BOOL nonprop = FALSE;
BOOL group = FALSE;
int oldsize = 0;
int type, n;
node = stack_peek(values); node = stack_peek(values);
type = node->type; type = node->type;
n = node->n; n = node->n;
if (type == FORMAT_LBRACK) if (type == FORMAT_LBRACK)
replaced = replace_stack_prop(format, values, &propfound, replaced = replace_stack_prop( format, values, &propfound,
&nonprop, &oldsize, &type); &nonprop, &oldsize, &type, &len );
else if (type == FORMAT_LBRACE) else if (type == FORMAT_LBRACE)
{ {
replaced = replace_stack_group(format, values, &propfound, replaced = replace_stack_group( format, values, &propfound,
&nonprop, &oldsize, &type); &nonprop, &oldsize, &type, &len );
group = TRUE; group = TRUE;
} }
format->n = n; format->n = n;
beg = format_replace(format, propfound, nonprop, oldsize, type, replaced); beg = format_replace( format, propfound, nonprop, oldsize, type, replaced, len );
if (!beg) if (!beg)
return ERROR_SUCCESS; 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, UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
LPDWORD size ) LPDWORD size )
{ {
LPWSTR deformated; WCHAR *format, *deformated;
LPWSTR rec;
DWORD len;
UINT rc = ERROR_INVALID_PARAMETER; UINT rc = ERROR_INVALID_PARAMETER;
DWORD len;
TRACE("%p %p %p %p\n", package, record, buffer, size); TRACE("%p %p %p %p\n", package, record, buffer, size);
rec = msi_dup_record_field(record,0); if (!(format = msi_dup_record_field( record, 0 )))
if (!rec) format = build_default_format( record );
rec = 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 (buffer)
{ {
if (*size>len) if (*size>len)
@ -897,13 +900,11 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
rc = ERROR_MORE_DATA; rc = ERROR_MORE_DATA;
} }
} }
else else rc = ERROR_SUCCESS;
rc = ERROR_SUCCESS;
*size = len; *size = len;
msi_free( format );
msi_free(rec); msi_free( deformated );
msi_free(deformated);
return rc; return rc;
} }
@ -934,7 +935,7 @@ UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord,
wstr.unicode = TRUE; wstr.unicode = TRUE;
wstr.str.w = szResult; wstr.str.w = szResult;
r = msi_strcpy_to_awstring( value, &wstr, sz ); r = msi_strcpy_to_awstring( value, SysStringLen(value), &wstr, sz );
done: done:
IWineMsiRemotePackage_Release( remote_package ); IWineMsiRemotePackage_Release( remote_package );
@ -1022,24 +1023,23 @@ done:
} }
/* wrapper to resist a need for a full rewrite right now */ /* 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 len;
{ MSIRECORD *rec;
DWORD size = 0;
MSIRECORD *rec = MSI_CreateRecord( 1 );
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; *data = NULL;
if (!fmt) return 0;
if (!(rec = MSI_CreateRecord( 1 ))) return 0;
MSI_RecordSetStringW( rec, 0, fmt );
MSI_FormatRecordW( package, rec, NULL, &len );
if (!(*data = msi_alloc( ++len * sizeof(WCHAR) )))
{
msiobj_release( &rec->hdr );
return 0; return 0;
}
MSI_FormatRecordW( package, rec, *data, &len );
msiobj_release( &rec->hdr );
return len;
} }

View file

@ -178,32 +178,28 @@ UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode
return ret; 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; return ERROR_INVALID_PARAMETER;
if (!sz) if (!sz)
return r; return ERROR_SUCCESS;
if (awbuf->unicode) if (len < 0) len = strlenW( str );
{
len = lstrlenW( str ); if (awbuf->unicode && awbuf->str.w)
if (awbuf->str.w) memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
lstrcpynW( awbuf->str.w, str, *sz );
}
else else
{ {
len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL );
if (len) if (lenA) lenA--;
len--; WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL ); if (awbuf->str.a && *sz && lenA >= *sz)
if ( awbuf->str.a && *sz && (len >= *sz) )
awbuf->str.a[*sz - 1] = 0; awbuf->str.a[*sz - 1] = 0;
len = lenA;
} }
if (awbuf->str.w && len >= *sz) if (awbuf->str.w && len >= *sz)
r = ERROR_MORE_DATA; r = ERROR_MORE_DATA;
*sz = len; *sz = len;
@ -277,7 +273,7 @@ static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
if (FAILED(hr)) if (FAILED(hr))
goto done; goto done;
r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf ); r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf );
done: done:
IWineMsiRemotePackage_Release( remote_package ); IWineMsiRemotePackage_Release( remote_package );
@ -301,8 +297,7 @@ done:
if (!path) if (!path)
return ERROR_DIRECTORY; return ERROR_DIRECTORY;
r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf ); return msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
return r;
} }
/*********************************************************************** /***********************************************************************
@ -447,7 +442,7 @@ static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
if (FAILED(hr)) if (FAILED(hr))
goto done; goto done;
r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf ); r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf );
done: done:
IWineMsiRemotePackage_Release( remote_package ); IWineMsiRemotePackage_Release( remote_package );
@ -478,7 +473,7 @@ done:
if (!path) if (!path)
return ERROR_DIRECTORY; return ERROR_DIRECTORY;
r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf ); r = msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
msi_free( path ); msi_free( path );
return r; return r;
} }
@ -558,7 +553,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
{ {
msi_free( folder->ResolvedTarget ); msi_free( folder->ResolvedTarget );
folder->ResolvedTarget = target_path; 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 ) 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 }; static const WCHAR fmt[] = { '%','d',0 };
WCHAR level[6]; WCHAR level[6];
int len;
UINT r; UINT r;
TRACE("%p %i\n", package, iInstallLevel); TRACE("%p %i\n", package, iInstallLevel);
@ -1660,8 +1656,8 @@ UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
if (iInstallLevel < 1) if (iInstallLevel < 1)
return MSI_SetFeatureStates( package ); return MSI_SetFeatureStates( package );
sprintfW( level, fmt, iInstallLevel ); len = sprintfW( level, fmt, iInstallLevel );
r = msi_set_property( package->db, szInstallLevel, level ); r = msi_set_property( package->db, szInstallLevel, level, len );
if ( r == ERROR_SUCCESS ) if ( r == ERROR_SUCCESS )
r = MSI_SetFeatureStates( package ); r = MSI_SetFeatureStates( package );

View file

@ -1101,6 +1101,11 @@ static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
awstring *szValue, LPDWORD pcchValueBuf) 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; MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
UINT r = ERROR_UNKNOWN_PROPERTY; UINT r = ERROR_UNKNOWN_PROPERTY;
HKEY prodkey, userdata, source; HKEY prodkey, userdata, source;
@ -1111,16 +1116,6 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
LONG res; LONG res;
DWORD type = REG_NONE; 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), TRACE("%s %s %p %p\n", debugstr_w(szProduct),
debugstr_w(szAttribute), szValue, pcchValueBuf); debugstr_w(szAttribute), szValue, pcchValueBuf);
@ -1244,6 +1239,8 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
if (pcchValueBuf) if (pcchValueBuf)
{ {
int len = strlenW( val );
/* If szBuffer (szValue->str) is NULL, there's no need to copy the value /* 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 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
* can't rely on its value. * 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) if (szValue->str.a || szValue->str.w)
{ {
DWORD size = *pcchValueBuf; DWORD size = *pcchValueBuf;
if (strlenW(val) < size) if (len < size)
r = msi_strcpy_to_awstring(val, szValue, &size); r = msi_strcpy_to_awstring( val, len, szValue, &size );
else else
{
r = ERROR_MORE_DATA; r = ERROR_MORE_DATA;
} }
}
if (!badconfig) if (!badconfig)
*pcchValueBuf = lstrlenW(val); *pcchValueBuf = len;
} }
if (badconfig) if (badconfig)
@ -2220,7 +2215,10 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY; if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY;
if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))) if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz)))
{
msi_free(val);
return r; return r;
}
if (lstrlenW(val) > 2 && if (lstrlenW(val) > 2 &&
val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && 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) if (state == INSTALLSTATE_LOCAL && !*path)
state = INSTALLSTATE_NOTUSED; state = INSTALLSTATE_NOTUSED;
msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf); msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf);
msi_free(path); msi_free(path);
return state; return state;
} }
@ -3521,7 +3519,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
goto done; goto done;
} }
r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf); r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf);
if (r == ERROR_MORE_DATA) if (r == ERROR_MORE_DATA)
{ {
state = USERINFOSTATE_MOREDATA; state = USERINFOSTATE_MOREDATA;
@ -3534,7 +3532,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
orgptr = org; orgptr = org;
if (!orgptr) orgptr = szEmpty; 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) if (r == ERROR_MORE_DATA)
{ {
state = USERINFOSTATE_MOREDATA; state = USERINFOSTATE_MOREDATA;
@ -3550,7 +3548,7 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
goto done; goto done;
} }
r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf); r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf);
if (r == ERROR_MORE_DATA) if (r == ERROR_MORE_DATA)
state = USERINFOSTATE_MOREDATA; state = USERINFOSTATE_MOREDATA;
} }

View file

@ -79,6 +79,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
msi_dialog_unregister_class(); msi_dialog_unregister_class();
msi_free_handle_table(); msi_free_handle_table();
msi_free( gszLogFile ); msi_free( gszLogFile );
release_typelib();
break; break;
} }
return TRUE; return TRUE;

View file

@ -118,6 +118,7 @@ typedef struct tagMSIFIELD
LPWSTR szwVal; LPWSTR szwVal;
IStream *stream; IStream *stream;
} u; } u;
int len;
} MSIFIELD; } MSIFIELD;
typedef struct tagMSIRECORD typedef struct tagMSIRECORD
@ -481,6 +482,7 @@ typedef struct tagMSICOMPONENT
LPWSTR FullKeypath; LPWSTR FullKeypath;
LPWSTR AdvertiseString; LPWSTR AdvertiseString;
MSIASSEMBLY *assembly; MSIASSEMBLY *assembly;
int num_clients;
unsigned int anyAbsent:1; unsigned int anyAbsent:1;
unsigned int hasAdvertiseFeature:1; unsigned int hasAdvertiseFeature:1;
@ -722,7 +724,7 @@ typedef struct {
} str; } str;
} awcstring; } 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 */ /* msi server interface */
extern HRESULT create_msi_custom_remote( IUnknown *pOuter, LPVOID *ppObj ) DECLSPEC_HIDDEN; 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 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 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 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 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_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_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 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 BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name ) DECLSPEC_HIDDEN;
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table ) 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 MSIRECORD *MSI_CloneRecord( MSIRECORD * ) DECLSPEC_HIDDEN;
extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN; extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN;
extern BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) 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 */ /* stream internals */
extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN; 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 DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data ) DECLSPEC_HIDDEN;
extern WCHAR *msi_dup_record_field(MSIRECORD *row, INT index) 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 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 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 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; 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; LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN;
/* OLE automation */ /* 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_msiserver(IUnknown *pOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) 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 */ /* Scripting */
extern DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN; 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 szName[] = {'N','a','m','e',0};
static const WCHAR szData[] = {'D','a','t','a',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 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 */ /* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);

View file

@ -345,10 +345,9 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
if (type & MSITYPE_STRING) if (type & MSITYPE_STRING)
{ {
LPCWSTR sval; int len;
const WCHAR *sval = msi_string_lookup( db->strings, ival, &len );
sval = msi_string_lookup_id(db->strings, ival); msi_record_set_string( *rec, i, sval, len );
MSI_RecordSetStringW(*rec, i, sval);
} }
else else
{ {

View file

@ -483,7 +483,7 @@ static UINT set_installed_prop( MSIPACKAGE *package )
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
{ {
RegCloseKey( hkey ); RegCloseKey( hkey );
msi_set_property( package->db, szInstalled, szOne ); msi_set_property( package->db, szInstalled, szOne, -1 );
} }
return r; return r;
} }
@ -525,7 +525,7 @@ static UINT set_user_sid_prop( MSIPACKAGE *package )
if (!ConvertSidToStringSidW( psid, &sid_str )) if (!ConvertSidToStringSidW( psid, &sid_str ))
goto done; goto done;
r = msi_set_property( package->db, szUserSID, sid_str ); r = msi_set_property( package->db, szUserSID, sid_str, -1 );
done: done:
LocalFree( sid_str ); LocalFree( sid_str );
@ -638,10 +638,12 @@ static void set_msi_assembly_prop(MSIPACKAGE *package)
return; return;
size = GetFileVersionInfoSizeW(fusion, &handle); size = GetFileVersionInfoSizeW(fusion, &handle);
if (!size) return; if (!size)
goto done;
version = msi_alloc(size); version = msi_alloc(size);
if (!version) return; if (!version)
goto done;
if (!GetFileVersionInfoW(fusion, handle, size, version)) if (!GetFileVersionInfoW(fusion, handle, size, version))
goto done; goto done;
@ -657,7 +659,7 @@ static void set_msi_assembly_prop(MSIPACKAGE *package)
if (!val_len || !verstr) if (!val_len || !verstr)
goto done; goto done;
msi_set_property(package->db, netasm, verstr); msi_set_property( package->db, netasm, verstr, -1 );
done: done:
msi_free(fusion); msi_free(fusion);
@ -757,182 +759,182 @@ static VOID set_installer_properties(MSIPACKAGE *package)
SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
strcatW(pth, szBackSlash); 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 */ /* FIXME: set to AllUsers profile path if ALLUSERS is set */
SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
strcatW(pth, szBackSlash); strcatW(pth, szBackSlash);
msi_set_property(package->db, szSystemFolder, pth); msi_set_property( package->db, szSystemFolder, pth, -1 );
msi_set_property(package->db, szSystem16Folder, pth); msi_set_property( package->db, szSystem16Folder, pth, -1 );
SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
strcatW(pth, szBackSlash); 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); SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
strcatW(pth, szBackSlash); 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. */ /* Physical Memory is specified in MB. Using total amount. */
msex.dwLength = sizeof(msex); msex.dwLength = sizeof(msex);
GlobalMemoryStatusEx( &msex ); GlobalMemoryStatusEx( &msex );
sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
msi_set_property(package->db, szPhysicalMemory, bufstr); msi_set_property( package->db, szPhysicalMemory, bufstr, len );
SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
ptr = strchrW(pth,'\\'); ptr = strchrW(pth,'\\');
if (ptr) *(ptr + 1) = 0; if (ptr) *(ptr + 1) = 0;
msi_set_property(package->db, szWindowsVolume, pth); msi_set_property( package->db, szWindowsVolume, pth, -1 );
GetTempPathW(MAX_PATH,pth); len = GetTempPathW(MAX_PATH, pth);
msi_set_property(package->db, szTempFolder, pth); msi_set_property( package->db, szTempFolder, pth, len );
/* in a wine environment the user is always admin and privileged */ /* in a wine environment the user is always admin and privileged */
msi_set_property(package->db, szAdminUser, szOne); msi_set_property( package->db, szAdminUser, szOne, -1 );
msi_set_property(package->db, szPrivileged, szOne); msi_set_property( package->db, szPrivileged, szOne, -1 );
/* set the os things */ /* set the os things */
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
GetVersionExW((OSVERSIONINFOW *)&OSVersion); GetVersionExW((OSVERSIONINFOW *)&OSVersion);
verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
sprintfW(verstr, szFormat, verval); len = sprintfW( verstr, szFormat, verval );
switch (OSVersion.dwPlatformId) switch (OSVersion.dwPlatformId)
{ {
case VER_PLATFORM_WIN32_WINDOWS: case VER_PLATFORM_WIN32_WINDOWS:
msi_set_property(package->db, szVersion9x, verstr); msi_set_property( package->db, szVersion9x, verstr, len );
break; break;
case VER_PLATFORM_WIN32_NT: case VER_PLATFORM_WIN32_NT:
msi_set_property(package->db, szVersionNT, verstr); msi_set_property( package->db, szVersionNT, verstr, len );
sprintfW(verstr, szFormat,OSVersion.wProductType); len = sprintfW( verstr, szFormat,OSVersion.wProductType );
msi_set_property(package->db, szMsiNTProductType, verstr); msi_set_property( package->db, szMsiNTProductType, verstr, len );
break; break;
} }
sprintfW(verstr, szFormat, OSVersion.dwBuildNumber); len = sprintfW( verstr, szFormat, OSVersion.dwBuildNumber );
msi_set_property(package->db, szWindowsBuild, verstr); msi_set_property( package->db, szWindowsBuild, verstr, len );
sprintfW(verstr, szFormat, OSVersion.wServicePackMajor); len = sprintfW( verstr, szFormat, OSVersion.wServicePackMajor );
msi_set_property(package->db, szServicePackLevel, verstr); msi_set_property( package->db, szServicePackLevel, verstr, len );
sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION); len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION );
msi_set_property( package->db, szVersionMsi, bufstr ); msi_set_property( package->db, szVersionMsi, bufstr, len );
sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100); len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 );
msi_set_property( package->db, szVersionDatabase, bufstr ); msi_set_property( package->db, szVersionDatabase, bufstr, len );
GetNativeSystemInfo( &sys_info ); GetNativeSystemInfo( &sys_info );
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
msi_set_property( package->db, szIntel, bufstr ); msi_set_property( package->db, szIntel, bufstr, len );
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{ {
GetSystemDirectoryW( pth, MAX_PATH ); GetSystemDirectoryW( pth, MAX_PATH );
PathAddBackslashW( pth ); 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 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
PathAddBackslashW( 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 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
PathAddBackslashW( 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) else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{ {
msi_set_property( package->db, szMsiAMD64, bufstr ); msi_set_property( package->db, szMsiAMD64, bufstr, -1 );
msi_set_property( package->db, szMsix64, bufstr ); msi_set_property( package->db, szMsix64, bufstr, -1 );
msi_set_property( package->db, szVersionNT64, verstr ); msi_set_property( package->db, szVersionNT64, verstr, -1 );
GetSystemDirectoryW( pth, MAX_PATH ); GetSystemDirectoryW( pth, MAX_PATH );
PathAddBackslashW( pth ); PathAddBackslashW( pth );
msi_set_property( package->db, szSystem64Folder, pth ); msi_set_property( package->db, szSystem64Folder, pth, -1 );
GetSystemWow64DirectoryW( pth, MAX_PATH ); GetSystemWow64DirectoryW( pth, MAX_PATH );
PathAddBackslashW( pth ); 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 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
PathAddBackslashW( 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 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth );
PathAddBackslashW( 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 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
PathAddBackslashW( 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 ); SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth );
PathAddBackslashW( pth ); PathAddBackslashW( pth );
msi_set_property( package->db, szCommonFilesFolder, pth ); msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
} }
/* Screen properties. */ /* Screen properties. */
dc = GetDC(0); dc = GetDC(0);
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) ); len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) );
msi_set_property( package->db, szScreenX, bufstr ); msi_set_property( package->db, szScreenX, bufstr, len );
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES )); len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) );
msi_set_property( package->db, szScreenY, bufstr ); msi_set_property( package->db, szScreenY, bufstr, len );
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL )); len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) );
msi_set_property( package->db, szColorBits, bufstr ); msi_set_property( package->db, szColorBits, bufstr, len );
ReleaseDC(0, dc); ReleaseDC(0, dc);
/* USERNAME and COMPANYNAME */ /* USERNAME and COMPANYNAME */
@ -944,10 +946,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
{ {
if (!username && if (!username &&
(username = msi_reg_get_val_str( hkey, szDefName ))) (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 && if (!companyname &&
(companyname = msi_reg_get_val_str( hkey, szDefCompany ))) (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 ); CloseHandle( hkey );
} }
if ((!username || !companyname) && if ((!username || !companyname) &&
@ -955,10 +957,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
{ {
if (!username && if (!username &&
(username = msi_reg_get_val_str( hkey, szRegisteredUser ))) (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 && if (!companyname &&
(companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) (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 ); CloseHandle( hkey );
} }
msi_free( username ); msi_free( username );
@ -971,7 +973,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
GetSystemTime( &systemtime ); GetSystemTime( &systemtime );
if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime, if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) )) NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
msi_set_property( package->db, szDate, bufstr ); msi_set_property( package->db, szDate, bufstr, -1 );
else else
ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError()); 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, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
&systemtime, NULL, bufstr, &systemtime, NULL, bufstr,
sizeof(bufstr)/sizeof(bufstr[0]) )) sizeof(bufstr)/sizeof(bufstr[0]) ))
msi_set_property( package->db, szTime, bufstr ); msi_set_property( package->db, szTime, bufstr, -1 );
else else
ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError()); ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
set_msi_assembly_prop( package ); set_msi_assembly_prop( package );
langid = GetUserDefaultLangID(); langid = GetUserDefaultLangID();
sprintfW(bufstr, szIntFormat, langid); len = sprintfW( bufstr, szIntFormat, langid );
msi_set_property( package->db, szUserLanguageID, bufstr ); msi_set_property( package->db, szUserLanguageID, bufstr, len );
langid = GetSystemDefaultLangID(); langid = GetSystemDefaultLangID();
sprintfW(bufstr, szIntFormat, langid); len = sprintfW( bufstr, szIntFormat, langid );
msi_set_property( package->db, szSystemLangID, bufstr ); msi_set_property( package->db, szSystemLangID, bufstr, len );
sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode)); len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) );
msi_set_property( package->db, szProductState, bufstr ); msi_set_property( package->db, szProductState, bufstr, len );
len = 0; len = 0;
if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 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 ((username = msi_alloc( len * sizeof(WCHAR) )))
{ {
if (GetUserNameW( username, &len )) if (GetUserNameW( username, &len ))
msi_set_property( package->db, szLogonUser, username ); msi_set_property( package->db, szLogonUser, username, len - 1 );
msi_free( username ); msi_free( username );
} }
} }
@ -1014,7 +1016,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
if ((computername = msi_alloc( len * sizeof(WCHAR) ))) if ((computername = msi_alloc( len * sizeof(WCHAR) )))
{ {
if (GetComputerNameW( computername, &len )) if (GetComputerNameW( computername, &len ))
msi_set_property( package->db, szComputerName, computername ); msi_set_property( package->db, szComputerName, computername, len - 1 );
msi_free( computername ); msi_free( computername );
} }
} }
@ -1073,7 +1075,7 @@ static UINT msi_load_summary_properties( MSIPACKAGE *package )
goto done; goto done;
} }
msi_set_property( package->db, szPackageCode, package_code ); msi_set_property( package->db, szPackageCode, package_code, len );
msi_free( package_code ); msi_free( package_code );
/* load package attributes */ /* load package attributes */
@ -1141,9 +1143,9 @@ void msi_adjust_privilege_properties( MSIPACKAGE *package )
if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
{ {
TRACE("resetting ALLUSERS property from 2 to 1\n"); 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 ) 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}; static const WCHAR fmtW[] = {'%','u',0};
MSIPACKAGE *package; MSIPACKAGE *package;
WCHAR uilevel[11]; WCHAR uilevel[11];
int len;
UINT r; UINT r;
TRACE("%p\n", db); TRACE("%p\n", db);
@ -1176,8 +1179,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
set_installer_properties( package ); set_installer_properties( package );
package->ui_level = gUILevel; package->ui_level = gUILevel;
sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
msi_set_property(package->db, szUILevel, uilevel); msi_set_property( package->db, szUILevel, uilevel, len );
r = msi_load_summary_properties( package ); r = msi_load_summary_properties( package );
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
@ -1564,13 +1567,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
{ {
r = msi_create_empty_local_file( localfile, dotmsi ); r = msi_create_empty_local_file( localfile, dotmsi );
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
{
msi_free ( base_url );
return r; return r;
}
if (!CopyFileW( file, localfile, FALSE )) if (!CopyFileW( file, localfile, FALSE ))
{ {
r = GetLastError(); r = GetLastError();
WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
DeleteFileW( localfile ); DeleteFileW( localfile );
msi_free ( base_url );
return r; return r;
} }
delete_on_close = TRUE; delete_on_close = TRUE;
@ -1578,8 +1585,11 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
TRACE("opening package %s\n", debugstr_w( localfile )); TRACE("opening package %s\n", debugstr_w( localfile ));
r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
{
msi_free ( base_url );
return r; return r;
} }
}
package = MSI_CreatePackage( db, base_url ); package = MSI_CreatePackage( db, base_url );
msi_free( base_url ); msi_free( base_url );
msiobj_release( &db->hdr ); msiobj_release( &db->hdr );
@ -1608,18 +1618,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
msiobj_release( &package->hdr ); msiobj_release( &package->hdr );
return r; return r;
} }
msi_set_property( package->db, szDatabase, db->path ); msi_set_property( package->db, szDatabase, db->path, -1 );
if( UrlIsW( szPackage, URLIS_URL ) ) if( UrlIsW( szPackage, URLIS_URL ) )
msi_set_property( package->db, szOriginalDatabase, szPackage ); msi_set_property( package->db, szOriginalDatabase, szPackage, -1 );
else if( szPackage[0] == '#' ) else if( szPackage[0] == '#' )
msi_set_property( package->db, szOriginalDatabase, db->path ); msi_set_property( package->db, szOriginalDatabase, db->path, -1 );
else else
{ {
WCHAR fullpath[MAX_PATH]; WCHAR fullpath[MAX_PATH];
DWORD len = GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL ); msi_set_property( package->db, szOriginalDatabase, fullpath, len );
msi_set_property( package->db, szOriginalDatabase, fullpath );
} }
msi_set_context( package ); 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[] = { static const WCHAR insert_query[] = {
'I','N','S','E','R','T',' ','I','N','T','O',' ', '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]; WCHAR query[1024];
UINT rc; 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; return ERROR_INVALID_PARAMETER;
/* this one is weird... */ /* this one is weird... */
if (!szName[0]) if (!name[0])
return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
rc = msi_get_property(db, szName, 0, &sz); if (value && len < 0) len = strlenW( value );
if (!szValue || !*szValue)
rc = msi_get_property( db, name, 0, &sz );
if (!value || (!*value && !len))
{ {
sprintfW(query, delete_query, szName); sprintfW( query, delete_query, name );
} }
else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
{ {
sprintfW(query, update_query, szName); sprintfW( query, update_query, name );
row = MSI_CreateRecord(1); row = MSI_CreateRecord(1);
MSI_RecordSetStringW(row, 1, szValue); msi_record_set_string( row, 1, value, len );
} }
else else
{ {
strcpyW(query, insert_query); strcpyW( query, insert_query );
row = MSI_CreateRecord(2); row = MSI_CreateRecord(2);
MSI_RecordSetStringW(row, 1, szName); msi_record_set_string( row, 1, name, -1 );
MSI_RecordSetStringW(row, 2, szValue); msi_record_set_string( row, 2, value, len );
} }
rc = MSI_DatabaseOpenViewW(db, query, &view); rc = MSI_DatabaseOpenViewW(db, query, &view);
@ -2123,7 +2132,7 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
return ERROR_SUCCESS; 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 )) if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir ))
msi_reset_folders( package, TRUE ); msi_reset_folders( package, TRUE );
@ -2181,7 +2190,7 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
} }
if (rc == ERROR_SUCCESS) 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)); debugstr_w(szName));
else if (rc == ERROR_MORE_DATA) else if (rc == ERROR_MORE_DATA)
TRACE("need %d sized buffer for %s\n", *pchValueBuf, TRACE("need %d sized buffer for %s\n", *pchValueBuf,
@ -2232,6 +2241,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
MSIRECORD *row = NULL; MSIRECORD *row = NULL;
UINT r = ERROR_FUNCTION_FAILED; UINT r = ERROR_FUNCTION_FAILED;
LPCWSTR val = NULL; LPCWSTR val = NULL;
DWORD len = 0;
TRACE("%u %s %p %p\n", handle, debugstr_w(name), TRACE("%u %s %p %p\n", handle, debugstr_w(name),
szValueBuf->str.w, pchValueBuf ); szValueBuf->str.w, pchValueBuf );
@ -2246,7 +2256,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
IWineMsiRemotePackage *remote_package; IWineMsiRemotePackage *remote_package;
LPWSTR value = NULL; LPWSTR value = NULL;
BSTR bname; BSTR bname;
DWORD len;
remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle ); remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
if (!remote_package) if (!remote_package)
@ -2259,7 +2268,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
return ERROR_OUTOFMEMORY; return ERROR_OUTOFMEMORY;
} }
len = 0;
hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len ); hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
if (FAILED(hr)) if (FAILED(hr))
goto done; goto done;
@ -2276,7 +2284,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
if (FAILED(hr)) if (FAILED(hr))
goto done; goto done;
r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf ); r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf );
/* Bug required by Adobe installers */ /* Bug required by Adobe installers */
if (!szValueBuf->unicode && !szValueBuf->str.a) if (!szValueBuf->unicode && !szValueBuf->str.a)
@ -2300,12 +2308,12 @@ done:
row = msi_get_property_row( package->db, name ); row = msi_get_property_row( package->db, name );
if (row) if (row)
val = MSI_RecordGetString( row, 1 ); val = msi_record_get_string( row, 1, (int *)&len );
if (!val) if (!val)
val = szEmpty; val = szEmpty;
r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf ); r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf );
if (row) if (row)
msiobj_release( &row->hdr ); msiobj_release( &row->hdr );

View file

@ -225,7 +225,7 @@ static UINT patch_set_media_source_prop( MSIPACKAGE *package )
{ {
property = MSI_RecordGetString( rec, 1 ); property = MSI_RecordGetString( rec, 1 );
patch = msi_dup_property( package->db, szPatch ); 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 ); msi_free( patch );
msiobj_release( &rec->hdr ); msiobj_release( &rec->hdr );
} }

View file

@ -156,6 +156,17 @@ static BOOL string2intW( LPCWSTR str, int *out )
return TRUE; 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, UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
MSIRECORD *out_rec, UINT out_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; out->u.pVal = in->u.pVal;
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
str = strdupW( in->u.szwVal ); if ((str = msi_strdupW( in->u.szwVal, in->len )))
if ( !str ) {
r = ERROR_OUTOFMEMORY;
else
out->u.szwVal = str; out->u.szwVal = str;
out->len = in->len;
}
else r = ERROR_OUTOFMEMORY;
break; break;
case MSIFIELD_STREAM: case MSIFIELD_STREAM:
IStream_AddRef( in->u.stream ); IStream_AddRef( in->u.stream );
@ -202,7 +214,6 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
} }
msiobj_unlock( &in_rec->hdr ); msiobj_unlock( &in_rec->hdr );
return r; return r;
} }
@ -380,7 +391,7 @@ BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField )
UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField, UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
LPSTR szValue, LPDWORD pcchValue) LPSTR szValue, LPDWORD pcchValue)
{ {
UINT len=0, ret; UINT len = 0, ret = ERROR_SUCCESS;
CHAR buffer[16]; CHAR buffer[16];
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
@ -394,7 +405,6 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
ret = ERROR_SUCCESS;
switch( rec->fields[iField].type ) switch( rec->fields[iField].type )
{ {
case MSIFIELD_INT: case MSIFIELD_INT:
@ -404,11 +414,11 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
lstrcpynA(szValue, buffer, *pcchValue); lstrcpynA(szValue, buffer, *pcchValue);
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
NULL, 0 , NULL, NULL); rec->fields[iField].len + 1, NULL, 0 , NULL, NULL );
if (szValue) if (szValue)
WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
szValue, *pcchValue, NULL, NULL); rec->fields[iField].len + 1, szValue, *pcchValue, NULL, NULL );
if( szValue && *pcchValue && len>*pcchValue ) if( szValue && *pcchValue && len>*pcchValue )
szValue[*pcchValue-1] = 0; szValue[*pcchValue-1] = 0;
if( len ) if( len )
@ -448,23 +458,30 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField,
return ret; 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 ) const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
{ {
if( iField > rec->count ) return msi_record_get_string( rec, iField, NULL );
return NULL;
if( rec->fields[iField].type != MSIFIELD_WSTR )
return NULL;
return rec->fields[iField].u.szwVal;
} }
UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField, UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
LPWSTR szValue, LPDWORD pcchValue) LPWSTR szValue, LPDWORD pcchValue)
{ {
UINT len=0, ret; static const WCHAR szFormat[] = {'%','d',0};
UINT len = 0, ret = ERROR_SUCCESS;
WCHAR buffer[16]; WCHAR buffer[16];
static const WCHAR szFormat[] = { '%','d',0 };
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
@ -477,7 +494,6 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
ret = ERROR_SUCCESS;
switch( rec->fields[iField].type ) switch( rec->fields[iField].type )
{ {
case MSIFIELD_INT: case MSIFIELD_INT:
@ -487,9 +503,9 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
lstrcpynW(szValue, buffer, *pcchValue); lstrcpynW(szValue, buffer, *pcchValue);
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
len = lstrlenW( rec->fields[iField].u.szwVal ); len = rec->fields[iField].len;
if (szValue) if (szValue)
lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue); memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) );
break; break;
case MSIFIELD_NULL: case MSIFIELD_NULL:
if( szValue && *pcchValue > 0 ) if( szValue && *pcchValue > 0 )
@ -548,7 +564,7 @@ static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField)
case MSIFIELD_INT: case MSIFIELD_INT:
return sizeof (INT); return sizeof (INT);
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
return lstrlenW( rec->fields[iField].u.szwVal ); return rec->fields[iField].len;
case MSIFIELD_NULL: case MSIFIELD_NULL:
break; break;
case MSIFIELD_STREAM: case MSIFIELD_STREAM:
@ -574,72 +590,59 @@ UINT WINAPI MsiRecordDataSize(MSIHANDLE handle, UINT iField)
return ret; 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 ) UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, LPCSTR szValue )
{ {
WCHAR *valueW = NULL;
MSIRECORD *rec; MSIRECORD *rec;
UINT ret; UINT ret;
TRACE("%d %d %s\n", handle, iField, debugstr_a(szValue)); TRACE("%d %d %s\n", handle, iField, debugstr_a(szValue));
if (szValue && !(valueW = strdupAtoW( szValue ))) return ERROR_OUTOFMEMORY;
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
if( !rec ) if( !rec )
{
msi_free( valueW );
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
}
msiobj_lock( &rec->hdr ); msiobj_lock( &rec->hdr );
ret = MSI_RecordSetStringA( rec, iField, szValue ); ret = MSI_RecordSetStringW( rec, iField, valueW );
msiobj_unlock( &rec->hdr ); msiobj_unlock( &rec->hdr );
msiobj_release( &rec->hdr ); msiobj_release( &rec->hdr );
msi_free( valueW );
return ret; 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 ) UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue )
{ {
LPWSTR str;
TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue)); TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue));
if( iField > rec->count ) return msi_record_set_string( rec, iField, szValue, -1 );
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;
} }
UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, LPCWSTR szValue ) UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, LPCWSTR szValue )
@ -1011,8 +1014,9 @@ BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field)
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
if (strcmpW(a->fields[field].u.szwVal, b->fields[field].u.szwVal)) if (a->fields[field].len != b->fields[field].len) return FALSE;
return FALSE; if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal,
a->fields[field].len * sizeof(WCHAR) )) return FALSE;
break; break;
case MSIFIELD_STREAM: case MSIFIELD_STREAM:

View file

@ -1557,7 +1557,7 @@ static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
} }
r = ERROR_OUTOFMEMORY; r = ERROR_OUTOFMEMORY;
if ((name_sz+1) >= name_max) if (name_sz + 1 >= name_max)
{ {
name_max *= 2; name_max *= 2;
msi_free( name ); 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)); TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual ); r = msi_strcpy_to_awstring( name, -1, lpQualBuf, pcchQual );
r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf ); r2 = msi_strcpy_to_awstring( val+ofs, -1, lpAppBuf, pcchAppBuf );
if (r2 != ERROR_SUCCESS) if (r2 != ERROR_SUCCESS)
r = r2; r = r2;
@ -1596,7 +1596,6 @@ end:
msi_free(val); msi_free(val);
msi_free(name); msi_free(name);
RegCloseKey(key); RegCloseKey(key);
return r; return r;
} }

View file

@ -36,6 +36,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi); 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 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 szVBScript[] = { 'V','B','S','c','r','i','p','t',0};
static const WCHAR szSession[] = {'S','e','s','s','i','o','n',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. * MsiActiveScriptSite - Our IActiveScriptSite implementation.
*/ */
typedef struct { typedef struct {
IActiveScriptSite lpVtbl; IActiveScriptSite IActiveScriptSite_iface;
IDispatch *pInstaller; IDispatch *installer;
IDispatch *pSession; IDispatch *session;
LONG ref; LONG ref;
} MsiActiveScriptSite; } MsiActiveScriptSite;
static const struct IActiveScriptSiteVtbl ASS_Vtbl; static inline MsiActiveScriptSite *impl_from_IActiveScriptSite( IActiveScriptSite *iface )
static HRESULT create_ActiveScriptSite(IUnknown *pUnkOuter, LPVOID *ppObj)
{ {
MsiActiveScriptSite* object; return CONTAINING_RECORD(iface, MsiActiveScriptSite, IActiveScriptSite_iface);
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;
} }
/* /*
* MsiActiveScriptSite * MsiActiveScriptSite
*/ */
static HRESULT WINAPI MsiActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** obj)
/*** IUnknown methods ***/
static HRESULT WINAPI MsiActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** ppvObject)
{ {
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) || if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IActiveScriptSite)) IsEqualGUID(riid, &IID_IActiveScriptSite))
{ {
IActiveScriptSite_AddRef(iface); IActiveScriptSite_AddRef(iface);
*ppvObject = This; *obj = iface;
return S_OK; return S_OK;
} }
TRACE("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); *obj = NULL;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
static ULONG WINAPI MsiActiveScriptSite_AddRef(IActiveScriptSite* iface) static ULONG WINAPI MsiActiveScriptSite_AddRef(IActiveScriptSite* iface)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p/%p)\n", iface, This); TRACE("(%p)->(%d)\n", This, ref);
return ref;
return InterlockedIncrement(&This->ref);
} }
static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface) static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
ULONG ref = InterlockedDecrement(&This->ref); ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p/%p)\n", iface, This); TRACE("(%p)->(%d)\n", This, ref);
if (!ref) if (!ref)
msi_free(This); msi_free(This);
@ -251,18 +112,18 @@ static ULONG WINAPI MsiActiveScriptSite_Release(IActiveScriptSite* iface)
return ref; return ref;
} }
/*** IActiveScriptSite methods **/
static HRESULT WINAPI MsiActiveScriptSite_GetLCID(IActiveScriptSite* iface, LCID* plcid) static HRESULT WINAPI MsiActiveScriptSite_GetLCID(IActiveScriptSite* iface, LCID* plcid)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
TRACE("(%p/%p)->(%p)\n", This, iface, plcid); TRACE("(%p)->(%p)\n", This, plcid);
return E_NOTIMPL; /* Script will use system-defined locale */ return E_NOTIMPL; /* Script will use system-defined locale */
} }
static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppiunkItem, ITypeInfo** ppti) static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppiunkItem, ITypeInfo** ppti)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
TRACE("(%p/%p)->(%p,%d,%p,%p)\n", This, iface, pstrName, dwReturnMask, ppiunkItem, ppti);
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 */ /* Determine the kind of pointer that is requested, and make sure placeholder is valid */
if (dwReturnMask & SCRIPTINFO_ITYPEINFO) { if (dwReturnMask & SCRIPTINFO_ITYPEINFO) {
@ -276,10 +137,14 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface,
/* Are we looking for the session object? */ /* Are we looking for the session object? */
if (!strcmpW(szSession, pstrName)) { if (!strcmpW(szSession, pstrName)) {
if (dwReturnMask & SCRIPTINFO_ITYPEINFO) if (dwReturnMask & SCRIPTINFO_ITYPEINFO) {
return load_type_info(This->pSession, ppti, &DIID_Session, 0); HRESULT hr = get_typeinfo(Session_tid, ppti);
if (SUCCEEDED(hr))
ITypeInfo_AddRef(*ppti);
return hr;
}
else if (dwReturnMask & SCRIPTINFO_IUNKNOWN) { else if (dwReturnMask & SCRIPTINFO_IUNKNOWN) {
IDispatch_QueryInterface(This->pSession, &IID_IUnknown, (void **)ppiunkItem); IDispatch_QueryInterface(This->session, &IID_IUnknown, (void **)ppiunkItem);
return S_OK; return S_OK;
} }
} }
@ -289,15 +154,15 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface,
static HRESULT WINAPI MsiActiveScriptSite_GetDocVersionString(IActiveScriptSite* iface, BSTR* pbstrVersion) static HRESULT WINAPI MsiActiveScriptSite_GetDocVersionString(IActiveScriptSite* iface, BSTR* pbstrVersion)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
TRACE("(%p/%p)->(%p)\n", This, iface, pbstrVersion); TRACE("(%p)->(%p)\n", This, pbstrVersion);
return E_NOTIMPL; return E_NOTIMPL;
} }
static HRESULT WINAPI MsiActiveScriptSite_OnScriptTerminate(IActiveScriptSite* iface, const VARIANT* pvarResult, const EXCEPINFO* pexcepinfo) static HRESULT WINAPI MsiActiveScriptSite_OnScriptTerminate(IActiveScriptSite* iface, const VARIANT* pvarResult, const EXCEPINFO* pexcepinfo)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
TRACE("(%p/%p)->(%p,%p)\n", This, iface, pvarResult, pexcepinfo); TRACE("(%p)->(%p, %p)\n", This, pvarResult, pexcepinfo);
return S_OK; return S_OK;
} }
@ -338,11 +203,11 @@ static HRESULT WINAPI MsiActiveScriptSite_OnStateChange(IActiveScriptSite* iface
static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface, IActiveScriptError* pscripterror) static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface, IActiveScriptError* pscripterror)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
EXCEPINFO exception; EXCEPINFO exception;
HRESULT hr; HRESULT hr;
TRACE("(%p/%p)->(%p)\n", This, iface, pscripterror); TRACE("(%p)->(%p)\n", This, pscripterror);
memset(&exception, 0, sizeof(EXCEPINFO)); memset(&exception, 0, sizeof(EXCEPINFO));
hr = IActiveScriptError_GetExceptionInfo(pscripterror, &exception); hr = IActiveScriptError_GetExceptionInfo(pscripterror, &exception);
@ -359,19 +224,19 @@ static HRESULT WINAPI MsiActiveScriptSite_OnScriptError(IActiveScriptSite* iface
static HRESULT WINAPI MsiActiveScriptSite_OnEnterScript(IActiveScriptSite* iface) static HRESULT WINAPI MsiActiveScriptSite_OnEnterScript(IActiveScriptSite* iface)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
TRACE("(%p/%p)\n", This, iface); TRACE("(%p)\n", This);
return S_OK; return S_OK;
} }
static HRESULT WINAPI MsiActiveScriptSite_OnLeaveScript(IActiveScriptSite* iface) static HRESULT WINAPI MsiActiveScriptSite_OnLeaveScript(IActiveScriptSite* iface)
{ {
MsiActiveScriptSite *This = (MsiActiveScriptSite *)iface; MsiActiveScriptSite *This = impl_from_IActiveScriptSite(iface);
TRACE("(%p/%p)\n", This, iface); TRACE("(%p)\n", This);
return S_OK; return S_OK;
} }
static const struct IActiveScriptSiteVtbl ASS_Vtbl = static const struct IActiveScriptSiteVtbl activescriptsitevtbl =
{ {
MsiActiveScriptSite_QueryInterface, MsiActiveScriptSite_QueryInterface,
MsiActiveScriptSite_AddRef, MsiActiveScriptSite_AddRef,
@ -385,3 +250,135 @@ static const struct IActiveScriptSiteVtbl ASS_Vtbl =
MsiActiveScriptSite_OnEnterScript, MsiActiveScriptSite_OnEnterScript,
MsiActiveScriptSite_OnLeaveScript 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;
}

View file

@ -276,8 +276,9 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
} }
else if (type & MSITYPE_STRING) else if (type & MSITYPE_STRING)
{ {
str = MSI_RecordGetString(rec, i + 1); int len;
r = MSI_RecordSetStringW(mod, col, str); str = msi_record_get_string( rec, i + 1, &len );
r = msi_record_set_string( mod, col, str, len );
} }
else else
{ {
@ -430,7 +431,7 @@ UINT SELECT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
count = select_count_columns( columns ); 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 ) if( !sv )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;

View file

@ -763,7 +763,10 @@ UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
r = OpenSourceKey(product, &source, MSICODE_PRODUCT, context, FALSE); r = OpenSourceKey(product, &source, MSICODE_PRODUCT, context, FALSE);
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
{
msi_free(buffer);
return r; return r;
}
sprintfW(buffer, format, typechar, index, value); sprintfW(buffer, format, typechar, index, value);

View file

@ -312,7 +312,7 @@ static UINT storages_find_row(MSISTORAGESVIEW *sv, MSIRECORD *rec, UINT *row)
UINT r, i, id, data; UINT r, i, id, data;
str = MSI_RecordGetString(rec, 1); 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) if (r != ERROR_SUCCESS)
return r; return r;

View file

@ -299,7 +299,7 @@ static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row)
UINT r, i, id, data; UINT r, i, id, data;
str = MSI_RecordGetString(rec, 1); 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) if (r != ERROR_SUCCESS)
return r; return r;

View file

@ -45,7 +45,8 @@ struct msistring
{ {
USHORT persistent_refcount; USHORT persistent_refcount;
USHORT nonpersistent_refcount; USHORT nonpersistent_refcount;
LPWSTR str; WCHAR *data;
int len;
}; };
struct string_table struct string_table
@ -112,7 +113,7 @@ VOID msi_destroy_stringtable( string_table *st )
{ {
if( st->strings[i].persistent_refcount || if( st->strings[i].persistent_refcount ||
st->strings[i].nonpersistent_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->strings );
msi_free( st->sorted ); msi_free( st->sorted );
@ -162,6 +163,19 @@ static int st_find_free_entry( string_table *st )
return st->freeslot; 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 ) static int find_insert_index( const string_table *st, UINT string_id )
{ {
int i, c, low = 0, high = st->sortcount - 1; 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) while (low <= high)
{ {
i = (low + high) / 2; 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) if (c < 0)
high = i - 1; high = i - 1;
else if (c > 0) else if (c > 0)
@ -194,7 +208,8 @@ static void insert_string_sorted( string_table *st, UINT string_id )
st->sortcount++; 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) 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].nonpersistent_refcount = refcount;
} }
st->strings[n].str = str; st->strings[n].data = str;
st->strings[n].len = len;
insert_string_sorted( st, n ); 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; return ERROR_NOT_ENOUGH_MEMORY;
MultiByteToWideChar( st->codepage, 0, buffer, -1, str, sz ); 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 ); msi_free( str );
return r; 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; LPWSTR str;
int sz; int sz;
if( !data ) if( !data || !len )
return 0;
if( !data[0] )
return 0; return 0;
if( n > 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 */ /* allocate a new string */
if( len < 0 )
len = strlen(data);
sz = MultiByteToWideChar( st->codepage, 0, data, len, NULL, 0 ); sz = MultiByteToWideChar( st->codepage, 0, data, len, NULL, 0 );
str = msi_alloc( (sz+1)*sizeof(WCHAR) ); str = msi_alloc( (sz+1)*sizeof(WCHAR) );
if( !str ) 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 ); MultiByteToWideChar( st->codepage, 0, data, len, str, sz );
str[sz] = 0; str[sz] = 0;
set_st_entry( st, n, str, refcount, persistence ); set_st_entry( st, n, str, sz, refcount, persistence );
return n; return n;
} }
@ -301,10 +311,13 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun
if( !data ) if( !data )
return 0; return 0;
if( !data[0] )
if (len < 0) len = strlenW( data );
if( !data[0] && !len )
return 0; return 0;
if( msi_string2idW( st, data, &n ) == ERROR_SUCCESS ) if (msi_string2id( st, data, len, &n) == ERROR_SUCCESS )
{ {
if (persistence == StringPersistent) if (persistence == StringPersistent)
st->strings[n].persistent_refcount += refcount; 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; return -1;
/* allocate a new string */ /* allocate a new string */
if(len<0) TRACE( "%s, n = %d len = %d\n", debugstr_wn(data, len), n, len );
len = strlenW(data);
TRACE("%s, n = %d len = %d\n", debugstr_w(data), n, len );
str = msi_alloc( (len+1)*sizeof(WCHAR) ); str = msi_alloc( (len+1)*sizeof(WCHAR) );
if( !str ) 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) ); memcpy( str, data, len*sizeof(WCHAR) );
str[len] = 0; str[len] = 0;
set_st_entry( st, n, str, refcount, persistence ); set_st_entry( st, n, str, len, refcount, persistence );
return n; return n;
} }
/* find the string identified by an id - return null if there's none */ /* 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( id == 0 )
{
if (len) *len = 0;
return szEmpty; return szEmpty;
}
if( id >= st->maxcount ) if( id >= st->maxcount )
return NULL; return NULL;
if( id && !st->strings[id].persistent_refcount && !st->strings[id].nonpersistent_refcount) if( id && !st->strings[id].persistent_refcount && !st->strings[id].nonpersistent_refcount)
return NULL; 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 ) static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT *sz )
{ {
UINT len, lenW; int len, lenW;
const WCHAR *str; const WCHAR *str;
TRACE("Finding string %d of %d\n", id, st->maxcount); 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 ) if( !str )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
lenW = strlenW( str );
len = WideCharToMultiByte( st->codepage, 0, str, lenW, NULL, 0, NULL, NULL ); len = WideCharToMultiByte( st->codepage, 0, str, lenW, NULL, 0, NULL, NULL );
if( *sz < len ) 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] st - pointer to the string table
* [in] str - string to find in the string table * [in] str - string to find in the string table
* [out] id - id of the string, if found * [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; int i, c, low = 0, high = st->sortcount - 1;
if (len < 0) len = strlenW( str );
while (low <= high) while (low <= high)
{ {
i = (low + high) / 2; 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) if (c < 0)
high = i - 1; high = i - 1;
@ -407,7 +422,6 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
} }
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
} }
@ -415,7 +429,7 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool
{ {
UINT i, len, holesize; 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"); ERR("oops. element 0 has a string\n");
*poolsize = 4; *poolsize = 4;
@ -425,14 +439,14 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool
{ {
if( !st->strings[i].persistent_refcount ) 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; (*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)); TRACE("[%u] = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len));
len = WideCharToMultiByte( st->codepage, 0, len = WideCharToMultiByte( st->codepage, 0, st->strings[i].data, st->strings[i].len + 1,
st->strings[i].str, -1, NULL, 0, NULL, NULL); NULL, 0, NULL, NULL);
if( len ) if( len )
len--; len--;
(*datasize) += len; (*datasize) += len;

View file

@ -660,7 +660,7 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF
} }
/* convert table and column names to IDs from the string table */ /* 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) if (r != ERROR_SUCCESS)
{ {
WARN("Couldn't find id for %s\n", debugstr_w(szTableName)); 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); ERR("duplicate column %d\n", col);
continue; 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].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, colinfo[col - 1].type = read_table_int( table->data, i, table->colinfo[3].offset,
sizeof(USHORT) ) - (1 << 15); sizeof(USHORT) ) - (1 << 15);
colinfo[col - 1].offset = 0; 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 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 ); 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 ].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 ].type = col->type;
table->colinfo[ i ].offset = 0; table->colinfo[ i ].offset = 0;
table->colinfo[ i ].ref_count = 0; table->colinfo[ i ].ref_count = 0;
@ -981,7 +981,7 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
!strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) ) !strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) )
return TRUE; return TRUE;
r = msi_string2idW( db->strings, name, &table_id ); r = msi_string2id( db->strings, name, -1, &table_id );
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
{ {
TRACE("Couldn't find id for %s\n", debugstr_w(name)); 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 ) 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 ) if ( !sval )
{ {
r = ERROR_INVALID_PARAMETER; 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 ) 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) if (sval)
{ {
r = msi_string2idW(tv->db->strings, sval, pvalue); r = msi_string2id( tv->db->strings, sval, len, pvalue );
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
return ERROR_NOT_FOUND; 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 ) if ( r != ERROR_SUCCESS )
{ {
LPCWSTR sval = MSI_RecordGetString( rec, i + 1 ); int len;
val = msi_addstringW( tv->db->strings, sval, -1, 1, const WCHAR *sval = msi_record_get_string( rec, i + 1, &len );
val = msi_addstringW( tv->db->strings, sval, len, 1,
persistent ? StringPersistent : StringNonPersistent ); persistent ? StringPersistent : StringNonPersistent );
} }
else else
@ -1530,10 +1532,10 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *column )
TRACE("skipping binary column\n"); TRACE("skipping binary column\n");
else if ( tv->columns[i].type & MSITYPE_STRING ) 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 || (!str[0] && !len))
if (str == NULL || str[0] == 0)
{ {
if (column) *column = i; if (column) *column = i;
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
@ -2139,7 +2141,7 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
else if ( !strcmpW( name, szStorages ) ) else if ( !strcmpW( name, szStorages ) )
return STORAGES_CreateView( db, view ); 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 ); tv = msi_alloc_zero( sz );
if( !tv ) if( !tv )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
@ -2265,6 +2267,7 @@ static UINT msi_record_encoded_stream_name( const MSITABLEVIEW *tv, MSIRECORD *r
if ( !p ) if ( !p )
{ {
r = ERROR_OUTOFMEMORY; r = ERROR_OUTOFMEMORY;
msi_free(sval);
goto err; goto err;
} }
stname = p; stname = p;
@ -2328,21 +2331,25 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
r = IStorage_OpenStream( stg, encname, NULL, r = IStorage_OpenStream( stg, encname, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm ); STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
msi_free( encname );
if ( r != ERROR_SUCCESS ) if ( r != ERROR_SUCCESS )
{
msi_free( encname );
return NULL; return NULL;
}
MSI_RecordSetStream( rec, i+1, stm ); MSI_RecordSetStream( rec, i+1, stm );
TRACE(" field %d [%s]\n", i+1, debugstr_w(encname)); TRACE(" field %d [%s]\n", i+1, debugstr_w(encname));
msi_free( encname );
} }
else if( columns[i].type & MSITYPE_STRING ) else if( columns[i].type & MSITYPE_STRING )
{ {
LPCWSTR sval; int len;
const WCHAR *sval;
val = read_raw_int(rawdata, ofs, bytes_per_strref); val = read_raw_int(rawdata, ofs, bytes_per_strref);
sval = msi_string_lookup_id( st, val ); sval = msi_string_lookup( st, val, &len );
MSI_RecordSetStringW( rec, i+1, sval ); msi_record_set_string( rec, i+1, sval, len );
TRACE(" field %d [%s]\n", i+1, debugstr_w(sval)); TRACE(" field %d [%s]\n", i+1, debugstr_wn(sval, len));
ofs += bytes_per_strref; ofs += bytes_per_strref;
} }
else else
@ -2379,12 +2386,13 @@ static void dump_record( MSIRECORD *rec )
n = MSI_RecordGetFieldCount( rec ); n = MSI_RecordGetFieldCount( rec );
for( i=1; i<=n; i++ ) for( i=1; i<=n; i++ )
{ {
LPCWSTR sval; int len;
const WCHAR *sval;
if( MSI_RecordIsNull( rec, i ) ) if( MSI_RecordIsNull( rec, i ) )
TRACE("row -> []\n"); TRACE("row -> []\n");
else if( (sval = MSI_RecordGetString( rec, i )) ) else if( (sval = msi_record_get_string( rec, i, &len )) )
TRACE("row -> [%s]\n", debugstr_w(sval)); TRACE("row -> [%s]\n", debugstr_wn(sval, len));
else else
TRACE("row -> [0x%08x]\n", MSI_RecordGetInteger( rec, i ) ); 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 ) static void dump_table( const string_table *st, const USHORT *rawdata, UINT rawsize )
{ {
LPCWSTR sval;
UINT i; UINT i;
for (i = 0; i < rawsize / 2; i++)
for( i=0; i<(rawsize/2); i++ )
{ {
sval = msi_string_lookup_id( st, rawdata[i] ); int len;
MESSAGE(" %04x %s\n", rawdata[i], debugstr_w(sval) ); 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 ) static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
{ {
LPCWSTR str;
UINT i, r, *data; UINT i, r, *data;
data = msi_alloc( tv->num_cols *sizeof (UINT) ); 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 ) && if ( ( tv->columns[i].type & MSITYPE_STRING ) &&
! MSITYPE_IS_BINARY(tv->columns[i].type) ) ! 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) 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, /* if there's no matching string in the string table,
these keys can't match any record, so fail now. */ these keys can't match any record, so fail now. */

View file

@ -32,103 +32,108 @@
*/ */
typedef struct Keyword Keyword; typedef struct Keyword Keyword;
struct 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 */ int tokenType; /* The token value for this keyword */
}; };
#define MAX_TOKEN_LEN 11 #define MAX_TOKEN_LEN 11
static const WCHAR ADD_W[] = { 'A','D','D',0 }; static const WCHAR addW[] = {'A','D','D'};
static const WCHAR ALTER_W[] = { 'A','L','T','E','R',0 }; static const WCHAR alterW[] = {'A','L','T','E','R'};
static const WCHAR AND_W[] = { 'A','N','D',0 }; static const WCHAR andW[] = {'A','N','D'};
static const WCHAR BY_W[] = { 'B','Y',0 }; static const WCHAR byW[] = {'B','Y'};
static const WCHAR CHAR_W[] = { 'C','H','A','R',0 }; static const WCHAR charW[] = {'C','H','A','R'};
static const WCHAR CHARACTER_W[] = { 'C','H','A','R','A','C','T','E','R',0 }; static const WCHAR characterW[] = {'C','H','A','R','A','C','T','E','R'};
static const WCHAR CREATE_W[] = { 'C','R','E','A','T','E',0 }; static const WCHAR createW[] = {'C','R','E','A','T','E'};
static const WCHAR DELETE_W[] = { 'D','E','L','E','T','E',0 }; static const WCHAR deleteW[] = {'D','E','L','E','T','E'};
static const WCHAR DISTINCT_W[] = { 'D','I','S','T','I','N','C','T',0 }; static const WCHAR distinctW[] = {'D','I','S','T','I','N','C','T'};
static const WCHAR DROP_W[] = { 'D','R','O','P',0 }; static const WCHAR dropW[] = {'D','R','O','P'};
static const WCHAR FREE_W[] = { 'F','R','E','E',0 }; static const WCHAR freeW[] = {'F','R','E','E'};
static const WCHAR FROM_W[] = { 'F','R','O','M',0 }; static const WCHAR fromW[] = {'F','R','O','M'};
static const WCHAR HOLD_W[] = { 'H','O','L','D',0 }; static const WCHAR holdW[] = {'H','O','L','D'};
static const WCHAR INSERT_W[] = { 'I','N','S','E','R','T',0 }; static const WCHAR insertW[] = {'I','N','S','E','R','T'};
static const WCHAR INT_W[] = { 'I','N','T',0 }; static const WCHAR intW[] = {'I','N','T'};
static const WCHAR INTEGER_W[] = { 'I','N','T','E','G','E','R',0 }; static const WCHAR integerW[] = {'I','N','T','E','G','E','R'};
static const WCHAR INTO_W[] = { 'I','N','T','O',0 }; static const WCHAR intoW[] = {'I','N','T','O'};
static const WCHAR IS_W[] = { 'I','S',0 }; static const WCHAR isW[] = {'I','S'};
static const WCHAR KEY_W[] = { 'K','E','Y',0 }; static const WCHAR keyW[] = {'K','E','Y'};
static const WCHAR LIKE_W[] = { 'L','I','K','E',0 }; static const WCHAR likeW[] = {'L','I','K','E'};
static const WCHAR LOCALIZABLE_W[] = { 'L','O','C','A','L','I','Z','A','B','L','E',0 }; static const WCHAR localizableW[] = {'L','O','C','A','L','I','Z','A','B','L','E'};
static const WCHAR LONG_W[] = { 'L','O','N','G',0 }; static const WCHAR longW[] = {'L','O','N','G'};
static const WCHAR LONGCHAR_W[] = { 'L','O','N','G','C','H','A','R',0 }; static const WCHAR longcharW[] = {'L','O','N','G','C','H','A','R'};
static const WCHAR NOT_W[] = { 'N','O','T',0 }; static const WCHAR notW[] = {'N','O','T'};
static const WCHAR NULL_W[] = { 'N','U','L','L',0 }; static const WCHAR nullW[] = {'N','U','L','L'};
static const WCHAR OBJECT_W[] = { 'O','B','J','E','C','T',0 }; static const WCHAR objectW[] = {'O','B','J','E','C','T'};
static const WCHAR OR_W[] = { 'O','R',0 }; static const WCHAR orW[] = {'O','R'};
static const WCHAR ORDER_W[] = { 'O','R','D','E','R',0 }; static const WCHAR orderW[] = {'O','R','D','E','R'};
static const WCHAR PRIMARY_W[] = { 'P','R','I','M','A','R','Y',0 }; static const WCHAR primaryW[] = {'P','R','I','M','A','R','Y'};
static const WCHAR SELECT_W[] = { 'S','E','L','E','C','T',0 }; static const WCHAR selectW[] = {'S','E','L','E','C','T'};
static const WCHAR SET_W[] = { 'S','E','T',0 }; static const WCHAR setW[] = {'S','E','T'};
static const WCHAR SHORT_W[] = { 'S','H','O','R','T',0 }; static const WCHAR shortW[] = {'S','H','O','R','T'};
static const WCHAR TABLE_W[] = { 'T','A','B','L','E',0 }; static const WCHAR tableW[] = {'T','A','B','L','E'};
static const WCHAR TEMPORARY_W[] = { 'T','E','M','P','O','R','A','R','Y',0 }; static const WCHAR temporaryW[] = {'T','E','M','P','O','R','A','R','Y'};
static const WCHAR UPDATE_W[] = { 'U','P','D','A','T','E',0 }; static const WCHAR updateW[] = {'U','P','D','A','T','E'};
static const WCHAR VALUES_W[] = { 'V','A','L','U','E','S',0 }; static const WCHAR valuesW[] = {'V','A','L','U','E','S'};
static const WCHAR WHERE_W[] = { 'W','H','E','R','E',0 }; static const WCHAR whereW[] = {'W','H','E','R','E'};
#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
/* /*
** These are the keywords ** These are the keywords
** They MUST be in alphabetical order ** They MUST be in alphabetical order
*/ */
static const Keyword aKeywordTable[] = { static const Keyword aKeywordTable[] = {
{ ADD_W, TK_ADD }, { addW, ARRAY_SIZE(addW), TK_ADD },
{ ALTER_W, TK_ALTER }, { alterW, ARRAY_SIZE(alterW), TK_ALTER },
{ AND_W, TK_AND }, { andW, ARRAY_SIZE(andW), TK_AND },
{ BY_W, TK_BY }, { byW, ARRAY_SIZE(byW), TK_BY },
{ CHAR_W, TK_CHAR }, { charW, ARRAY_SIZE(charW), TK_CHAR },
{ CHARACTER_W, TK_CHAR }, { characterW, ARRAY_SIZE(characterW), TK_CHAR },
{ CREATE_W, TK_CREATE }, { createW, ARRAY_SIZE(createW), TK_CREATE },
{ DELETE_W, TK_DELETE }, { deleteW, ARRAY_SIZE(deleteW), TK_DELETE },
{ DISTINCT_W, TK_DISTINCT }, { distinctW, ARRAY_SIZE(distinctW), TK_DISTINCT },
{ DROP_W, TK_DROP }, { dropW, ARRAY_SIZE(dropW), TK_DROP },
{ FREE_W, TK_FREE }, { freeW, ARRAY_SIZE(freeW), TK_FREE },
{ FROM_W, TK_FROM }, { fromW, ARRAY_SIZE(fromW), TK_FROM },
{ HOLD_W, TK_HOLD }, { holdW, ARRAY_SIZE(holdW), TK_HOLD },
{ INSERT_W, TK_INSERT }, { insertW, ARRAY_SIZE(insertW), TK_INSERT },
{ INT_W, TK_INT }, { intW, ARRAY_SIZE(intW), TK_INT },
{ INTEGER_W, TK_INT }, { integerW, ARRAY_SIZE(integerW), TK_INT },
{ INTO_W, TK_INTO }, { intoW, ARRAY_SIZE(intoW), TK_INTO },
{ IS_W, TK_IS }, { isW, ARRAY_SIZE(isW), TK_IS },
{ KEY_W, TK_KEY }, { keyW, ARRAY_SIZE(keyW), TK_KEY },
{ LIKE_W, TK_LIKE }, { likeW, ARRAY_SIZE(likeW), TK_LIKE },
{ LOCALIZABLE_W, TK_LOCALIZABLE }, { localizableW, ARRAY_SIZE(localizableW), TK_LOCALIZABLE },
{ LONG_W, TK_LONG }, { longW, ARRAY_SIZE(longW), TK_LONG },
{ LONGCHAR_W, TK_LONGCHAR }, { longcharW, ARRAY_SIZE(longcharW), TK_LONGCHAR },
{ NOT_W, TK_NOT }, { notW, ARRAY_SIZE(notW), TK_NOT },
{ NULL_W, TK_NULL }, { nullW, ARRAY_SIZE(nullW), TK_NULL },
{ OBJECT_W, TK_OBJECT }, { objectW, ARRAY_SIZE(objectW), TK_OBJECT },
{ OR_W, TK_OR }, { orW, ARRAY_SIZE(orW), TK_OR },
{ ORDER_W, TK_ORDER }, { orderW, ARRAY_SIZE(orderW), TK_ORDER },
{ PRIMARY_W, TK_PRIMARY }, { primaryW, ARRAY_SIZE(primaryW), TK_PRIMARY },
{ SELECT_W, TK_SELECT }, { selectW, ARRAY_SIZE(selectW), TK_SELECT },
{ SET_W, TK_SET }, { setW, ARRAY_SIZE(setW), TK_SET },
{ SHORT_W, TK_SHORT }, { shortW, ARRAY_SIZE(shortW), TK_SHORT },
{ TABLE_W, TK_TABLE }, { tableW, ARRAY_SIZE(tableW), TK_TABLE },
{ TEMPORARY_W, TK_TEMPORARY }, { temporaryW, ARRAY_SIZE(temporaryW), TK_TEMPORARY },
{ UPDATE_W, TK_UPDATE }, { updateW, ARRAY_SIZE(updateW), TK_UPDATE },
{ VALUES_W, TK_VALUES }, { valuesW, ARRAY_SIZE(valuesW), TK_VALUES },
{ WHERE_W, TK_WHERE }, { whereW, ARRAY_SIZE(whereW), TK_WHERE },
}; };
#define KEYWORD_COUNT ( sizeof aKeywordTable/sizeof (Keyword) )
/* /*
** Comparison function for binary search. ** Comparison function for binary search.
*/ */
static int compKeyword(const void *m1, const void *m2){ static int compKeyword(const void *m1, const void *m2){
const Keyword *k1 = m1, *k2 = 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. ** returned. If the input is not a keyword, TK_ID is returned.
*/ */
static int sqliteKeywordCode(const WCHAR *z, int n){ static int sqliteKeywordCode(const WCHAR *z, int n){
WCHAR str[MAX_TOKEN_LEN+1];
Keyword key, *r; Keyword key, *r;
if( n>MAX_TOKEN_LEN ) if( n>MAX_TOKEN_LEN )
return TK_ID; return TK_ID;
memcpy( str, z, n*sizeof (WCHAR) );
str[n] = 0;
key.tokenType = 0; key.tokenType = 0;
key.zName = str; key.name = z;
r = bsearch( &key, aKeywordTable, KEYWORD_COUNT, sizeof (Keyword), compKeyword ); key.len = n;
r = bsearch( &key, aKeywordTable, ARRAY_SIZE(aKeywordTable), sizeof(Keyword), compKeyword );
if( r ) if( r )
return r->tokenType; return r->tokenType;
return TK_ID; return TK_ID;

View file

@ -88,7 +88,7 @@ static void append_productcode(MSIPACKAGE* package, LPCWSTR action_property,
newprop[0] = 0; newprop[0] = 0;
strcatW(newprop,productid); 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 )) if (r == ERROR_SUCCESS && !strcmpW( action_property, szSourceDir ))
msi_reset_folders( package, TRUE ); msi_reset_folders( package, TRUE );

View file

@ -494,7 +494,7 @@ static UINT STRING_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
case EXPR_COL_NUMBER_STRING: case EXPR_COL_NUMBER_STRING:
r = expr_fetch_value(&expr->u.column, rows, &val); r = expr_fetch_value(&expr->u.column, rows, &val);
if (r == ERROR_SUCCESS) if (r == ERROR_SUCCESS)
*str = msi_string_lookup_id(wv->db->strings, val); *str = msi_string_lookup(wv->db->strings, val, NULL);
else else
*str = NULL; *str = NULL;
break; break;
@ -883,7 +883,7 @@ static UINT join_find_row( MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row )
UINT r, i, id, data; UINT r, i, id, data;
str = MSI_RecordGetString( rec, 1 ); 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) if (r != ERROR_SUCCESS)
return r; return r;
@ -1253,6 +1253,8 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables,
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
{ {
ERR("can't get table dimensions\n"); ERR("can't get table dimensions\n");
table->view->ops->delete(table->view);
msi_free(table);
goto end; goto end;
} }

View file

@ -103,7 +103,7 @@ reactos/dll/win32/msg711.acm # Synced to Wine-1.5.4
reactos/dll/win32/msgsm32.acm # Synced to Wine-1.5.4 reactos/dll/win32/msgsm32.acm # Synced to Wine-1.5.4
reactos/dll/win32/mshtml # Autosync reactos/dll/win32/mshtml # Autosync
reactos/dll/win32/mshtml.tlb # 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/msimg32 # Synced to Wine-1.5.4
reactos/dll/win32/msimtf # 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 reactos/dll/win32/msisip # Synced to Wine-1.5.4