sync msi to wine 1.1.38

svn path=/trunk/; revision=45468
This commit is contained in:
Christoph von Wittich 2010-02-06 21:28:28 +00:00
parent a5996ad2bf
commit a1608caf31
21 changed files with 1160 additions and 530 deletions

View file

@ -959,10 +959,6 @@ UINT msi_create_component_directories( MSIPACKAGE *package )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
/*
* Also we cannot enable/disable components either, so for now I am just going
* to do all the directories for all the components.
*/
static UINT ACTION_CreateFolders(MSIPACKAGE *package) static UINT ACTION_CreateFolders(MSIPACKAGE *package)
{ {
static const WCHAR ExecSeqQuery[] = static const WCHAR ExecSeqQuery[] =
@ -981,7 +977,60 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package)
rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package); rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package);
msiobj_release(&view->hdr); msiobj_release(&view->hdr);
msi_create_component_directories( package ); return rc;
}
static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
{
MSIPACKAGE *package = param;
LPCWSTR dir;
LPWSTR full_path;
MSIRECORD *uirow;
MSIFOLDER *folder;
dir = MSI_RecordGetString( row, 1 );
if (!dir)
{
ERR("Unable to get folder id\n");
return ERROR_SUCCESS;
}
full_path = resolve_folder( package, dir, FALSE, FALSE, TRUE, &folder );
if (!full_path)
{
ERR("Unable to resolve folder id %s\n", debugstr_w(dir));
return ERROR_SUCCESS;
}
TRACE("folder is %s\n", debugstr_w(full_path));
uirow = MSI_CreateRecord( 1 );
MSI_RecordSetStringW( uirow, 1, full_path );
ui_actiondata( package, szRemoveFolders, uirow );
msiobj_release( &uirow->hdr );
RemoveDirectoryW( full_path );
folder->State = 0;
msi_free( full_path );
return ERROR_SUCCESS;
}
static UINT ACTION_RemoveFolders( MSIPACKAGE *package )
{
static const WCHAR query[] =
{'S','E','L','E','C','T',' ', '`','D','i','r','e','c','t','o','r','y','_','`',
' ','F','R','O','M',' ', '`','C','r','e','a','t','e','F','o','l','d','e','r','`',0};
MSIQUERY *view;
UINT rc;
rc = MSI_DatabaseOpenViewW( package->db, query, &view );
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveFolders, package );
msiobj_release( &view->hdr );
return rc; return rc;
} }
@ -1562,8 +1611,10 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
while (ptr) while (ptr)
{ {
if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0) int len = ptr2 - ptr;
|| (!ptr2 && strcmpW(ptr,feature->Feature)==0))
if ((ptr2 && strlenW(feature->Feature) == len && !strncmpW(ptr, feature->Feature, len))
|| (!ptr2 && !strcmpW(ptr, feature->Feature)))
{ {
msi_feature_set_state(package, feature, state); msi_feature_set_state(package, feature, state);
break; break;
@ -1583,55 +1634,57 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
return TRUE; return TRUE;
} }
UINT MSI_SetFeatureStates(MSIPACKAGE *package) static BOOL process_overrides( MSIPACKAGE *package, int level )
{ {
int level;
static const WCHAR szlevel[] =
{'I','N','S','T','A','L','L','L','E','V','E','L',0};
static const WCHAR szAddLocal[] = static const WCHAR szAddLocal[] =
{'A','D','D','L','O','C','A','L',0}; {'A','D','D','L','O','C','A','L',0};
static const WCHAR szAddSource[] = static const WCHAR szAddSource[] =
{'A','D','D','S','O','U','R','C','E',0}; {'A','D','D','S','O','U','R','C','E',0};
static const WCHAR szAdvertise[] = static const WCHAR szAdvertise[] =
{'A','D','V','E','R','T','I','S','E',0}; {'A','D','V','E','R','T','I','S','E',0};
BOOL override = FALSE; BOOL ret = FALSE;
/* all these activation/deactivation things happen in order and things
* later on the list override things earlier on the list.
*
* 0 INSTALLLEVEL processing
* 1 ADDLOCAL
* 2 REMOVE
* 3 ADDSOURCE
* 4 ADDDEFAULT
* 5 REINSTALL
* 6 ADVERTISE
* 7 COMPADDLOCAL
* 8 COMPADDSOURCE
* 9 FILEADDLOCAL
* 10 FILEADDSOURCE
* 11 FILEADDDEFAULT
*/
ret |= process_state_property( package, level, szAddLocal, INSTALLSTATE_LOCAL );
ret |= process_state_property( package, level, szRemove, INSTALLSTATE_ABSENT );
ret |= process_state_property( package, level, szAddSource, INSTALLSTATE_SOURCE );
ret |= process_state_property( package, level, szReinstall, INSTALLSTATE_UNKNOWN );
ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED );
if (ret)
MSI_SetPropertyW( package, szPreselected, szOne );
return ret;
}
UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{
int level;
static const WCHAR szlevel[] =
{'I','N','S','T','A','L','L','L','E','V','E','L',0};
MSICOMPONENT* component; MSICOMPONENT* component;
MSIFEATURE *feature; MSIFEATURE *feature;
/* I do not know if this is where it should happen.. but */
TRACE("Checking Install Level\n"); TRACE("Checking Install Level\n");
level = msi_get_property_int(package, szlevel, 1); level = msi_get_property_int(package, szlevel, 1);
/* ok here is the _real_ rub if (!msi_get_property_int( package, szPreselected, 0 ))
* all these activation/deactivation things happen in order and things
* later on the list override things earlier on the list.
* 0) INSTALLLEVEL processing
* 1) ADDLOCAL
* 2) REMOVE
* 3) ADDSOURCE
* 4) ADDDEFAULT
* 5) REINSTALL
* 6) ADVERTISE
* 7) COMPADDLOCAL
* 8) COMPADDSOURCE
* 9) FILEADDLOCAL
* 10) FILEADDSOURCE
* 11) FILEADDDEFAULT
*
* I am still ignoring a lot of these. But that is ok for now, ADDLOCAL and
* REMOVE are the big ones, since we don't handle administrative installs
* yet anyway.
*/
override |= process_state_property(package, level, szAddLocal, INSTALLSTATE_LOCAL);
override |= process_state_property(package, level, szRemove, INSTALLSTATE_ABSENT);
override |= process_state_property(package, level, szAddSource, INSTALLSTATE_SOURCE);
override |= process_state_property(package, level, szReinstall, INSTALLSTATE_UNKNOWN);
override |= process_state_property(package, level, szAdvertise, INSTALLSTATE_ADVERTISED);
if (!override)
{ {
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
@ -1661,8 +1714,6 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
msi_feature_set_state(package, fl->feature, INSTALLSTATE_UNKNOWN); msi_feature_set_state(package, fl->feature, INSTALLSTATE_UNKNOWN);
} }
} }
else
MSI_SetPropertyW(package, szPreselected, szOne);
/* /*
* now we want to enable or disable components base on feature * now we want to enable or disable components base on feature
@ -1961,7 +2012,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
static const WCHAR szOutOfDiskSpace[] = static const WCHAR szOutOfDiskSpace[] =
{'O','u','t','O','f','D','i','s','k','S','p','a','c','e',0}; {'O','u','t','O','f','D','i','s','k','S','p','a','c','e',0};
MSICOMPONENT *comp; MSICOMPONENT *comp;
UINT rc; UINT rc = ERROR_SUCCESS;
MSIQUERY * view; MSIQUERY * view;
LPWSTR level; LPWSTR level;
@ -1982,13 +2033,14 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
TRACE("File calculations\n"); TRACE("File calculations\n");
msi_check_file_install_states( package ); msi_check_file_install_states( package );
if (!process_overrides( package, msi_get_property_int( package, szlevel, 1 ) ))
{
TRACE("Evaluating Condition Table\n"); TRACE("Evaluating Condition Table\n");
rc = MSI_DatabaseOpenViewW( package->db, ConditionQuery, &view ); rc = MSI_DatabaseOpenViewW( package->db, ConditionQuery, &view );
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
{ {
rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeConditions, rc = MSI_IterateRecords( view, NULL, ITERATE_CostFinalizeConditions, package );
package);
msiobj_release( &view->hdr ); msiobj_release( &view->hdr );
} }
@ -2003,6 +2055,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
else else
comp->Enabled = TRUE; comp->Enabled = TRUE;
} }
}
MSI_SetPropertyW(package,szCosting,szOne); MSI_SetPropertyW(package,szCosting,szOne);
/* set default run level if not set */ /* set default run level if not set */
@ -3652,6 +3705,89 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT ITERATE_SelfUnregModules( MSIRECORD *row, LPVOID param )
{
static const WCHAR regsvr32[] =
{'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','u',' ','\"',0};
static const WCHAR close[] = {'\"',0};
MSIPACKAGE *package = param;
LPCWSTR filename;
LPWSTR cmdline;
MSIFILE *file;
DWORD len;
STARTUPINFOW si;
PROCESS_INFORMATION pi;
BOOL ret;
MSIRECORD *uirow;
LPWSTR uipath, p;
memset( &si, 0, sizeof(STARTUPINFOW) );
filename = MSI_RecordGetString( row, 1 );
file = get_loaded_file( package, filename );
if (!file)
{
ERR("Unable to find file id %s\n", debugstr_w(filename));
return ERROR_SUCCESS;
}
len = strlenW( regsvr32 ) + strlenW( file->TargetPath ) + 2;
cmdline = msi_alloc( len * sizeof(WCHAR) );
strcpyW( cmdline, regsvr32 );
strcatW( cmdline, file->TargetPath );
strcatW( cmdline, close );
TRACE("Unregistering %s\n", debugstr_w(cmdline));
ret = CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, c_colon, &si, &pi );
if (ret)
{
CloseHandle( pi.hThread );
msi_dialog_check_messages( pi.hProcess );
CloseHandle( pi.hProcess );
}
msi_free( cmdline );
uirow = MSI_CreateRecord( 2 );
uipath = strdupW( file->TargetPath );
if ((p = strrchrW( uipath, '\\' )))
{
*p = 0;
MSI_RecordSetStringW( uirow, 1, ++p );
}
MSI_RecordSetStringW( uirow, 2, uipath );
ui_actiondata( package, szSelfUnregModules, uirow );
msiobj_release( &uirow->hdr );
msi_free( uipath );
/* FIXME call ui_progress? */
return ERROR_SUCCESS;
}
static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
{
UINT rc;
MSIQUERY *view;
static const WCHAR query[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','S','e','l','f','R','e','g','`',0};
rc = MSI_DatabaseOpenViewW( package->db, query, &view );
if (rc != ERROR_SUCCESS)
{
TRACE("no SelfReg table\n");
return ERROR_SUCCESS;
}
MSI_IterateRecords( view, NULL, ITERATE_SelfUnregModules, package );
msiobj_release( &view->hdr );
return ERROR_SUCCESS;
}
static UINT ACTION_PublishFeatures(MSIPACKAGE *package) static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
{ {
MSIFEATURE *feature; MSIFEATURE *feature;
@ -4462,8 +4598,8 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
MSIPACKAGE *package = param; MSIPACKAGE *package = param;
MSICOMPONENT *comp; MSICOMPONENT *comp;
SC_HANDLE scm, service = NULL; SC_HANDLE scm, service = NULL;
LPCWSTR name, *vector = NULL; LPCWSTR *vector = NULL;
LPWSTR args; LPWSTR name, args;
DWORD event, numargs; DWORD event, numargs;
UINT r = ERROR_FUNCTION_FAILED; UINT r = ERROR_FUNCTION_FAILED;
@ -4471,9 +4607,9 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT) if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
return ERROR_SUCCESS; return ERROR_SUCCESS;
name = MSI_RecordGetString(rec, 2); deformat_string(package, MSI_RecordGetString(rec, 2), &name);
deformat_string(package, MSI_RecordGetString(rec, 4), &args);
event = MSI_RecordGetInteger(rec, 3); event = MSI_RecordGetInteger(rec, 3);
args = strdupW(MSI_RecordGetString(rec, 4));
if (!(event & msidbServiceControlEventStart)) if (!(event & msidbServiceControlEventStart))
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -4488,15 +4624,16 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
service = OpenServiceW(scm, name, SERVICE_START); service = OpenServiceW(scm, name, SERVICE_START);
if (!service) if (!service)
{ {
ERR("Failed to open service %s\n", debugstr_w(name)); ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError());
goto done; goto done;
} }
vector = msi_service_args_to_vector(args, &numargs); vector = msi_service_args_to_vector(args, &numargs);
if (!StartServiceW(service, numargs, vector)) if (!StartServiceW(service, numargs, vector) &&
GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
{ {
ERR("Failed to start service %s\n", debugstr_w(name)); ERR("Failed to start service %s (%u)\n", debugstr_w(name), GetLastError());
goto done; goto done;
} }
@ -4506,6 +4643,7 @@ done:
CloseServiceHandle(service); CloseServiceHandle(service);
CloseServiceHandle(scm); CloseServiceHandle(scm);
msi_free(name);
msi_free(args); msi_free(args);
msi_free(vector); msi_free(vector);
return r; return r;
@ -4570,27 +4708,12 @@ error:
return FALSE; return FALSE;
} }
static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param) static UINT stop_service( LPCWSTR name )
{ {
MSIPACKAGE *package = param; SC_HANDLE scm = NULL, service = NULL;
MSICOMPONENT *comp;
SERVICE_STATUS status; SERVICE_STATUS status;
SERVICE_STATUS_PROCESS ssp; SERVICE_STATUS_PROCESS ssp;
SC_HANDLE scm = NULL, service = NULL; DWORD needed;
LPWSTR name, args;
DWORD event, needed;
event = MSI_RecordGetInteger(rec, 3);
if (!(event & msidbServiceControlEventStop))
return ERROR_SUCCESS;
comp = get_loaded_component(package, MSI_RecordGetString(rec, 6));
if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
return ERROR_SUCCESS;
deformat_string(package, MSI_RecordGetString(rec, 2), &name);
deformat_string(package, MSI_RecordGetString(rec, 4), &args);
args = strdupW(MSI_RecordGetString(rec, 4));
scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!scm) if (!scm)
@ -4605,16 +4728,14 @@ static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
SERVICE_ENUMERATE_DEPENDENTS); SERVICE_ENUMERATE_DEPENDENTS);
if (!service) if (!service)
{ {
WARN("Failed to open service (%s): %d\n", WARN("Failed to open service (%s): %d\n", debugstr_w(name), GetLastError());
debugstr_w(name), GetLastError());
goto done; goto done;
} }
if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS), &needed)) sizeof(SERVICE_STATUS_PROCESS), &needed))
{ {
WARN("Failed to query service status (%s): %d\n", WARN("Failed to query service status (%s): %d\n", debugstr_w(name), GetLastError());
debugstr_w(name), GetLastError());
goto done; goto done;
} }
@ -4629,8 +4750,28 @@ static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
done: done:
CloseServiceHandle(service); CloseServiceHandle(service);
CloseServiceHandle(scm); CloseServiceHandle(scm);
return ERROR_SUCCESS;
}
static UINT ITERATE_StopService( MSIRECORD *rec, LPVOID param )
{
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
LPWSTR name;
DWORD event;
event = MSI_RecordGetInteger( rec, 3 );
if (!(event & msidbServiceControlEventStop))
return ERROR_SUCCESS;
comp = get_loaded_component( package, MSI_RecordGetString( rec, 6 ) );
if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
return ERROR_SUCCESS;
deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
stop_service( name );
msi_free( name ); msi_free( name );
msi_free(args);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -4654,6 +4795,69 @@ static UINT ACTION_StopServices( MSIPACKAGE *package )
return rc; return rc;
} }
static UINT ITERATE_DeleteService( MSIRECORD *rec, LPVOID param )
{
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
LPWSTR name = NULL;
DWORD event;
SC_HANDLE scm = NULL, service = NULL;
event = MSI_RecordGetInteger( rec, 3 );
if (!(event & msidbServiceControlEventDelete))
return ERROR_SUCCESS;
comp = get_loaded_component( package, MSI_RecordGetString(rec, 6) );
if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
return ERROR_SUCCESS;
deformat_string( package, MSI_RecordGetString(rec, 2), &name );
stop_service( name );
scm = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if (!scm)
{
WARN("Failed to open the SCM: %d\n", GetLastError());
goto done;
}
service = OpenServiceW( scm, name, DELETE );
if (!service)
{
WARN("Failed to open service (%s): %u\n", debugstr_w(name), GetLastError());
goto done;
}
if (!DeleteService( service ))
WARN("Failed to delete service (%s): %u\n", debugstr_w(name), GetLastError());
done:
CloseServiceHandle( service );
CloseServiceHandle( scm );
msi_free( name );
return ERROR_SUCCESS;
}
static UINT ACTION_DeleteServices( MSIPACKAGE *package )
{
UINT rc;
MSIQUERY *view;
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
rc = MSI_DatabaseOpenViewW( package->db, query, &view );
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords( view, NULL, ITERATE_DeleteService, package );
msiobj_release( &view->hdr );
return rc;
}
static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename ) static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename )
{ {
MSIFILE *file; MSIFILE *file;
@ -4921,18 +5125,32 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
{ {
LPCWSTR ptr = *value; LPCWSTR ptr = *value;
if (!strncmpW(ptr, prefix, prefix_len)) if (!strncmpW(ptr, prefix, prefix_len))
{
if (ptr[prefix_len] == szSemiColon[0])
{ {
*flags |= ENV_MOD_APPEND; *flags |= ENV_MOD_APPEND;
*value += lstrlenW(prefix); *value += lstrlenW(prefix);
} }
else
{
*value = NULL;
}
}
else if (lstrlenW(*value) >= prefix_len) else if (lstrlenW(*value) >= prefix_len)
{ {
ptr += lstrlenW(ptr) - prefix_len; ptr += lstrlenW(ptr) - prefix_len;
if (!lstrcmpW(ptr, prefix)) if (!lstrcmpW(ptr, prefix))
{
if ((ptr-1) > *value && *(ptr-1) == szSemiColon[0])
{ {
*flags |= ENV_MOD_PREFIX; *flags |= ENV_MOD_PREFIX;
/* the "[~]" will be removed by deformat_string */; /* the "[~]" will be removed by deformat_string */;
} }
else
{
*value = NULL;
}
}
} }
} }
@ -4977,7 +5195,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value)); TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
res = env_set_flags(&name, &value, &flags); res = env_set_flags(&name, &value, &flags);
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS || !value)
goto done; goto done;
if (value && !deformat_string(package, value, &deformatted)) if (value && !deformat_string(package, value, &deformatted))
@ -5023,6 +5241,9 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; goto done;
} }
/* If we are appending but the string was empty, strip ; */
if ((flags & ENV_MOD_APPEND) && (value[0] == szSemiColon[0])) value++;
size = (lstrlenW(value) + 1) * sizeof(WCHAR); size = (lstrlenW(value) + 1) * sizeof(WCHAR);
newval = strdupW(value); newval = strdupW(value);
if (!newval) if (!newval)
@ -5033,7 +5254,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
} }
else else
{ {
if (flags & ENV_ACT_SETABSENT) /* Contrary to MSDN, +-variable to [~];path works */
if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK))
{ {
res = ERROR_SUCCESS; res = ERROR_SUCCESS;
goto done; goto done;
@ -5063,7 +5285,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
int multiplier = 0; int multiplier = 0;
if (flags & ENV_MOD_APPEND) multiplier++; if (flags & ENV_MOD_APPEND) multiplier++;
if (flags & ENV_MOD_PREFIX) multiplier++; if (flags & ENV_MOD_PREFIX) multiplier++;
mod_size = (lstrlenW(value) + 1) * multiplier; mod_size = lstrlenW(value) * multiplier;
size += mod_size * sizeof(WCHAR); size += mod_size * sizeof(WCHAR);
} }
@ -5078,26 +5300,18 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_PREFIX) if (flags & ENV_MOD_PREFIX)
{ {
lstrcpyW(newval, value); lstrcpyW(newval, value);
lstrcatW(newval, szSemiColon); ptr = newval + lstrlenW(value);
ptr = newval + lstrlenW(value) + 1;
} }
lstrcpyW(ptr, data); lstrcpyW(ptr, data);
if (flags & ENV_MOD_APPEND) if (flags & ENV_MOD_APPEND)
{ {
lstrcatW(newval, szSemiColon);
lstrcatW(newval, value); lstrcatW(newval, value);
} }
} }
if (newval)
{
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval)); TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size); res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
}
else
res = ERROR_SUCCESS;
done: done:
if (env) RegCloseKey(env); if (env) RegCloseKey(env);
@ -5911,6 +6125,13 @@ done:
return r; return r;
} }
static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
{
TRACE("\n");
package->need_reboot = 1;
return ERROR_SUCCESS;
}
static UINT msi_unimplemented_action_stub( MSIPACKAGE *package, static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
LPCSTR action, LPCWSTR table ) LPCSTR action, LPCWSTR table )
{ {
@ -5973,18 +6194,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table ); return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
} }
static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
{
static const WCHAR table[] = { 'S','e','l','f','R','e','g',0 };
return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
}
static UINT ACTION_DeleteServices( MSIPACKAGE *package )
{
static const WCHAR table[] = {
'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
return msi_unimplemented_action_stub( package, "DeleteServices", table );
}
static UINT ACTION_ValidateProductID( MSIPACKAGE *package ) static UINT ACTION_ValidateProductID( MSIPACKAGE *package )
{ {
static const WCHAR table[] = { static const WCHAR table[] = {
@ -6048,12 +6257,6 @@ static UINT ACTION_RemoveExistingProducts( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table ); return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table );
} }
static UINT ACTION_RemoveFolders( MSIPACKAGE *package )
{
static const WCHAR table[] = { 'C','r','e','a','t','e','F','o','l','d','e','r',0 };
return msi_unimplemented_action_stub( package, "RemoveFolders", table );
}
static UINT ACTION_RemoveODBC( MSIPACKAGE *package ) static UINT ACTION_RemoveODBC( MSIPACKAGE *package )
{ {
static const WCHAR table[] = { 'O','D','B','C','D','r','i','v','e','r',0 }; static const WCHAR table[] = { 'O','D','B','C','D','r','i','v','e','r',0 };
@ -6072,6 +6275,12 @@ static UINT ACTION_RemoveShortcuts( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "RemoveShortcuts", table ); return msi_unimplemented_action_stub( package, "RemoveShortcuts", table );
} }
static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
{
static const WCHAR table[] = { 'D','i','r','e','c','t','o','r','y',0 };
return msi_unimplemented_action_stub( package, "SetODBCFolders", table );
}
static UINT ACTION_UnpublishComponents( MSIPACKAGE *package ) static UINT ACTION_UnpublishComponents( MSIPACKAGE *package )
{ {
static const WCHAR table[] = { 'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t',0 }; static const WCHAR table[] = { 'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t',0 };
@ -6173,10 +6382,10 @@ StandardActions[] =
{ szRemoveShortcuts, ACTION_RemoveShortcuts }, { szRemoveShortcuts, ACTION_RemoveShortcuts },
{ szResolveSource, ACTION_ResolveSource }, { szResolveSource, ACTION_ResolveSource },
{ szRMCCPSearch, ACTION_RMCCPSearch }, { szRMCCPSearch, ACTION_RMCCPSearch },
{ szScheduleReboot, NULL }, { szScheduleReboot, ACTION_ScheduleReboot },
{ szSelfRegModules, ACTION_SelfRegModules }, { szSelfRegModules, ACTION_SelfRegModules },
{ szSelfUnregModules, ACTION_SelfUnregModules }, { szSelfUnregModules, ACTION_SelfUnregModules },
{ szSetODBCFolders, NULL }, { szSetODBCFolders, ACTION_SetODBCFolders },
{ szStartServices, ACTION_StartServices }, { szStartServices, ACTION_StartServices },
{ szStopServices, ACTION_StopServices }, { szStopServices, ACTION_StopServices },
{ szUnpublishComponents, ACTION_UnpublishComponents }, { szUnpublishComponents, ACTION_UnpublishComponents },

View file

@ -463,7 +463,7 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNAT
ACTION_ConvertRegValue(regType, value, sz, appValue); ACTION_ConvertRegValue(regType, value, sz, appValue);
break; break;
default: default:
FIXME("AppSearch unimplemented for type %d (key path %s, value %s)\n", FIXME("unimplemented for type %d (key path %s, value %s)\n",
type, debugstr_w(keyPath), debugstr_w(valueName)); type, debugstr_w(keyPath), debugstr_w(valueName));
} }
end: end:

View file

@ -1138,6 +1138,21 @@ static HRESULT WINAPI ViewImpl_Invoke(
return S_OK; return S_OK;
} }
static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
DISPPARAMS* pDispParams,
VARIANT* pVarResult,
EXCEPINFO* pExcepInfo,
UINT* puArgErr)
{
if (!(wFlags & DISPATCH_METHOD))
return DISP_E_MEMBERNOTFOUND;
FIXME("\n");
VariantInit(pVarResult);
return S_OK;
}
static HRESULT WINAPI DatabaseImpl_Invoke( static HRESULT WINAPI DatabaseImpl_Invoke(
AutomationObject* This, AutomationObject* This,
DISPID dispIdMember, DISPID dispIdMember,
@ -1208,6 +1223,11 @@ static HRESULT WINAPI DatabaseImpl_Invoke(
else return DISP_E_MEMBERNOTFOUND; else return DISP_E_MEMBERNOTFOUND;
break; break;
case DISPID_INSTALLER_LASTERRORRECORD:
return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
pVarResult, pExcepInfo,
puArgErr);
default: default:
return DISP_E_MEMBERNOTFOUND; return DISP_E_MEMBERNOTFOUND;
} }

View file

@ -119,6 +119,7 @@
#include "msiserver.h" #include "msiserver.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/list.h"
#define YYLEX_PARAM info #define YYLEX_PARAM info
#define YYPARSE_PARAM info #define YYPARSE_PARAM info
@ -133,6 +134,7 @@ typedef struct tag_yyinput
LPCWSTR str; LPCWSTR str;
INT n; INT n;
MSICONDITION result; MSICONDITION result;
struct list mem;
} COND_input; } COND_input;
struct cond_str { struct cond_str {
@ -140,10 +142,14 @@ struct cond_str {
INT len; INT len;
}; };
static LPWSTR COND_GetString( const struct cond_str *str ); static LPWSTR COND_GetString( COND_input *info, const struct cond_str *str );
static LPWSTR COND_GetLiteral( const struct cond_str *str ); static LPWSTR COND_GetLiteral( COND_input *info, const struct cond_str *str );
static int cond_lex( void *COND_lval, COND_input *info); static int cond_lex( void *COND_lval, COND_input *info);
static void *cond_alloc( COND_input *cond, unsigned int sz );
static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz );
static void cond_free( void *ptr );
static INT compare_int( INT a, INT operator, INT b ); static INT compare_int( INT a, INT operator, INT b );
static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert ); static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert );
@ -152,8 +158,8 @@ static INT compare_and_free_strings( LPWSTR a, INT op, LPWSTR b, BOOL convert )
INT r; INT r;
r = compare_string( a, op, b, convert ); r = compare_string( a, op, b, convert );
msi_free( a ); cond_free( a );
msi_free( b ); cond_free( b );
return r; return r;
} }
@ -184,7 +190,7 @@ static BOOL num_from_prop( LPCWSTR p, INT *val )
/* Line 189 of yacc.c */ /* Line 189 of yacc.c */
#line 188 "cond.tab.c" #line 194 "cond.tab.c"
/* Enabling traces. */ /* Enabling traces. */
#ifndef YYDEBUG #ifndef YYDEBUG
@ -259,7 +265,7 @@ typedef union YYSTYPE
{ {
/* Line 214 of yacc.c */ /* Line 214 of yacc.c */
#line 110 "cond.y" #line 116 "cond.y"
struct cond_str str; struct cond_str str;
LPWSTR string; LPWSTR string;
@ -268,7 +274,7 @@ typedef union YYSTYPE
/* Line 214 of yacc.c */ /* Line 214 of yacc.c */
#line 272 "cond.tab.c" #line 278 "cond.tab.c"
} YYSTYPE; } YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@ -280,7 +286,7 @@ typedef union YYSTYPE
/* Line 264 of yacc.c */ /* Line 264 of yacc.c */
#line 284 "cond.tab.c" #line 290 "cond.tab.c"
#ifdef short #ifdef short
# undef short # undef short
@ -584,12 +590,12 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 134, 134, 140, 147, 151, 155, 159, 163, 170, 0, 140, 140, 146, 153, 157, 161, 165, 169, 176,
174, 181, 185, 189, 194, 198, 207, 216, 220, 224, 180, 187, 191, 195, 200, 204, 213, 222, 226, 230,
228, 232, 237, 242, 250, 251, 252, 253, 254, 255, 234, 238, 243, 248, 256, 257, 258, 259, 260, 261,
256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
266, 267, 271, 275, 282, 291, 295, 304, 313, 326, 272, 273, 277, 281, 288, 298, 302, 311, 320, 333,
338, 345, 359, 368 345, 358, 375, 385
}; };
#endif #endif
@ -1540,7 +1546,7 @@ yyreduce:
case 2: case 2:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 135 "cond.y" #line 141 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
cond->result = (yyvsp[(1) - (1)].value); cond->result = (yyvsp[(1) - (1)].value);
@ -1550,7 +1556,7 @@ yyreduce:
case 3: case 3:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 140 "cond.y" #line 146 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
cond->result = MSICONDITION_NONE; cond->result = MSICONDITION_NONE;
@ -1560,7 +1566,7 @@ yyreduce:
case 4: case 4:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 148 "cond.y" #line 154 "cond.y"
{ {
(yyval.value) = (yyvsp[(1) - (1)].value); (yyval.value) = (yyvsp[(1) - (1)].value);
;} ;}
@ -1569,7 +1575,7 @@ yyreduce:
case 5: case 5:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 152 "cond.y" #line 158 "cond.y"
{ {
(yyval.value) = (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value); (yyval.value) = (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value);
;} ;}
@ -1578,7 +1584,7 @@ yyreduce:
case 6: case 6:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 156 "cond.y" #line 162 "cond.y"
{ {
(yyval.value) = !(yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value); (yyval.value) = !(yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value);
;} ;}
@ -1587,7 +1593,7 @@ yyreduce:
case 7: case 7:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 160 "cond.y" #line 166 "cond.y"
{ {
(yyval.value) = ( (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value) ) && !( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) ); (yyval.value) = ( (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value) ) && !( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) );
;} ;}
@ -1596,7 +1602,7 @@ yyreduce:
case 8: case 8:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 164 "cond.y" #line 170 "cond.y"
{ {
(yyval.value) = ( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) ) || ( !(yyvsp[(1) - (3)].value) && !(yyvsp[(3) - (3)].value) ); (yyval.value) = ( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) ) || ( !(yyvsp[(1) - (3)].value) && !(yyvsp[(3) - (3)].value) );
;} ;}
@ -1605,7 +1611,7 @@ yyreduce:
case 9: case 9:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 171 "cond.y" #line 177 "cond.y"
{ {
(yyval.value) = (yyvsp[(1) - (1)].value); (yyval.value) = (yyvsp[(1) - (1)].value);
;} ;}
@ -1614,7 +1620,7 @@ yyreduce:
case 10: case 10:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 175 "cond.y" #line 181 "cond.y"
{ {
(yyval.value) = (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value); (yyval.value) = (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value);
;} ;}
@ -1623,7 +1629,7 @@ yyreduce:
case 11: case 11:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 182 "cond.y" #line 188 "cond.y"
{ {
(yyval.value) = (yyvsp[(2) - (2)].value) ? 0 : 1; (yyval.value) = (yyvsp[(2) - (2)].value) ? 0 : 1;
;} ;}
@ -1632,7 +1638,7 @@ yyreduce:
case 12: case 12:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 186 "cond.y" #line 192 "cond.y"
{ {
(yyval.value) = (yyvsp[(1) - (1)].value) ? 1 : 0; (yyval.value) = (yyvsp[(1) - (1)].value) ? 1 : 0;
;} ;}
@ -1641,17 +1647,17 @@ yyreduce:
case 13: case 13:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 190 "cond.y" #line 196 "cond.y"
{ {
(yyval.value) = ((yyvsp[(1) - (1)].string) && (yyvsp[(1) - (1)].string)[0]) ? 1 : 0; (yyval.value) = ((yyvsp[(1) - (1)].string) && (yyvsp[(1) - (1)].string)[0]) ? 1 : 0;
msi_free((yyvsp[(1) - (1)].string)); cond_free( (yyvsp[(1) - (1)].string) );
;} ;}
break; break;
case 14: case 14:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 195 "cond.y" #line 201 "cond.y"
{ {
(yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) ); (yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) );
;} ;}
@ -1660,35 +1666,35 @@ yyreduce:
case 15: case 15:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 199 "cond.y" #line 205 "cond.y"
{ {
int num; int num;
if (num_from_prop( (yyvsp[(1) - (3)].string), &num )) if (num_from_prop( (yyvsp[(1) - (3)].string), &num ))
(yyval.value) = compare_int( num, (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) ); (yyval.value) = compare_int( num, (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) );
else else
(yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE ); (yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE );
msi_free((yyvsp[(1) - (3)].string)); cond_free( (yyvsp[(1) - (3)].string) );
;} ;}
break; break;
case 16: case 16:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 208 "cond.y" #line 214 "cond.y"
{ {
int num; int num;
if (num_from_prop( (yyvsp[(3) - (3)].string), &num )) if (num_from_prop( (yyvsp[(3) - (3)].string), &num ))
(yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), num ); (yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), num );
else else
(yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE ); (yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE );
msi_free((yyvsp[(3) - (3)].string)); cond_free( (yyvsp[(3) - (3)].string) );
;} ;}
break; break;
case 17: case 17:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 217 "cond.y" #line 223 "cond.y"
{ {
(yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE ); (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE );
;} ;}
@ -1697,7 +1703,7 @@ yyreduce:
case 18: case 18:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 221 "cond.y" #line 227 "cond.y"
{ {
(yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE ); (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE );
;} ;}
@ -1706,7 +1712,7 @@ yyreduce:
case 19: case 19:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 225 "cond.y" #line 231 "cond.y"
{ {
(yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE ); (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE );
;} ;}
@ -1715,7 +1721,7 @@ yyreduce:
case 20: case 20:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 229 "cond.y" #line 235 "cond.y"
{ {
(yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), FALSE ); (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), FALSE );
;} ;}
@ -1724,27 +1730,27 @@ yyreduce:
case 21: case 21:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 233 "cond.y" #line 239 "cond.y"
{ {
(yyval.value) = 0; (yyval.value) = 0;
msi_free((yyvsp[(1) - (3)].string)); cond_free( (yyvsp[(1) - (3)].string) );
;} ;}
break; break;
case 22: case 22:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 238 "cond.y" #line 244 "cond.y"
{ {
(yyval.value) = 0; (yyval.value) = 0;
msi_free((yyvsp[(3) - (3)].string)); cond_free( (yyvsp[(3) - (3)].string) );
;} ;}
break; break;
case 23: case 23:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 243 "cond.y" #line 249 "cond.y"
{ {
(yyval.value) = (yyvsp[(2) - (3)].value); (yyval.value) = (yyvsp[(2) - (3)].value);
;} ;}
@ -1753,133 +1759,133 @@ yyreduce:
case 24: case 24:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 250 "cond.y" #line 256 "cond.y"
{ (yyval.value) = COND_EQ; ;} { (yyval.value) = COND_EQ; ;}
break; break;
case 25: case 25:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 251 "cond.y" #line 257 "cond.y"
{ (yyval.value) = COND_NE; ;} { (yyval.value) = COND_NE; ;}
break; break;
case 26: case 26:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 252 "cond.y" #line 258 "cond.y"
{ (yyval.value) = COND_LT; ;} { (yyval.value) = COND_LT; ;}
break; break;
case 27: case 27:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 253 "cond.y" #line 259 "cond.y"
{ (yyval.value) = COND_GT; ;} { (yyval.value) = COND_GT; ;}
break; break;
case 28: case 28:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 254 "cond.y" #line 260 "cond.y"
{ (yyval.value) = COND_LE; ;} { (yyval.value) = COND_LE; ;}
break; break;
case 29: case 29:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 255 "cond.y" #line 261 "cond.y"
{ (yyval.value) = COND_GE; ;} { (yyval.value) = COND_GE; ;}
break; break;
case 30: case 30:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 256 "cond.y" #line 262 "cond.y"
{ (yyval.value) = COND_SS; ;} { (yyval.value) = COND_SS; ;}
break; break;
case 31: case 31:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 257 "cond.y" #line 263 "cond.y"
{ (yyval.value) = COND_IEQ; ;} { (yyval.value) = COND_IEQ; ;}
break; break;
case 32: case 32:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 258 "cond.y" #line 264 "cond.y"
{ (yyval.value) = COND_INE; ;} { (yyval.value) = COND_INE; ;}
break; break;
case 33: case 33:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 259 "cond.y" #line 265 "cond.y"
{ (yyval.value) = COND_ILT; ;} { (yyval.value) = COND_ILT; ;}
break; break;
case 34: case 34:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 260 "cond.y" #line 266 "cond.y"
{ (yyval.value) = COND_IGT; ;} { (yyval.value) = COND_IGT; ;}
break; break;
case 35: case 35:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 261 "cond.y" #line 267 "cond.y"
{ (yyval.value) = COND_ILE; ;} { (yyval.value) = COND_ILE; ;}
break; break;
case 36: case 36:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 262 "cond.y" #line 268 "cond.y"
{ (yyval.value) = COND_IGE; ;} { (yyval.value) = COND_IGE; ;}
break; break;
case 37: case 37:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 263 "cond.y" #line 269 "cond.y"
{ (yyval.value) = COND_ISS; ;} { (yyval.value) = COND_ISS; ;}
break; break;
case 38: case 38:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 264 "cond.y" #line 270 "cond.y"
{ (yyval.value) = COND_LHS; ;} { (yyval.value) = COND_LHS; ;}
break; break;
case 39: case 39:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 265 "cond.y" #line 271 "cond.y"
{ (yyval.value) = COND_RHS; ;} { (yyval.value) = COND_RHS; ;}
break; break;
case 40: case 40:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 266 "cond.y" #line 272 "cond.y"
{ (yyval.value) = COND_ILHS; ;} { (yyval.value) = COND_ILHS; ;}
break; break;
case 41: case 41:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 267 "cond.y" #line 273 "cond.y"
{ (yyval.value) = COND_IRHS; ;} { (yyval.value) = COND_IRHS; ;}
break; break;
case 42: case 42:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 272 "cond.y" #line 278 "cond.y"
{ {
(yyval.string) = (yyvsp[(1) - (1)].string); (yyval.string) = (yyvsp[(1) - (1)].string);
;} ;}
@ -1888,7 +1894,7 @@ yyreduce:
case 43: case 43:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 276 "cond.y" #line 282 "cond.y"
{ {
(yyval.string) = (yyvsp[(1) - (1)].string); (yyval.string) = (yyvsp[(1) - (1)].string);
;} ;}
@ -1897,9 +1903,10 @@ yyreduce:
case 44: case 44:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 283 "cond.y" #line 289 "cond.y"
{ {
(yyval.string) = COND_GetLiteral(&(yyvsp[(1) - (1)].str)); COND_input* cond = (COND_input*) info;
(yyval.string) = COND_GetLiteral( cond, &(yyvsp[(1) - (1)].str) );
if( !(yyval.string) ) if( !(yyval.string) )
YYABORT; YYABORT;
;} ;}
@ -1908,7 +1915,7 @@ yyreduce:
case 45: case 45:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 292 "cond.y" #line 299 "cond.y"
{ {
(yyval.value) = (yyvsp[(1) - (1)].value); (yyval.value) = (yyvsp[(1) - (1)].value);
;} ;}
@ -1917,35 +1924,35 @@ yyreduce:
case 46: case 46:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 296 "cond.y" #line 303 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action ); MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action );
(yyval.value) = action; (yyval.value) = action;
msi_free( (yyvsp[(2) - (2)].string) ); cond_free( (yyvsp[(2) - (2)].string) );
;} ;}
break; break;
case 47: case 47:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 305 "cond.y" #line 312 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action ); MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action );
(yyval.value) = install; (yyval.value) = install;
msi_free( (yyvsp[(2) - (2)].string) ); cond_free( (yyvsp[(2) - (2)].string) );
;} ;}
break; break;
case 48: case 48:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 314 "cond.y" #line 321 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
@ -1956,58 +1963,68 @@ yyreduce:
else else
(yyval.value) = action; (yyval.value) = action;
msi_free( (yyvsp[(2) - (2)].string) ); cond_free( (yyvsp[(2) - (2)].string) );
;} ;}
break; break;
case 49: case 49:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 327 "cond.y" #line 334 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetFeatureStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action ); MSI_GetFeatureStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action );
(yyval.value) = install; (yyval.value) = install;
msi_free( (yyvsp[(2) - (2)].string) ); cond_free( (yyvsp[(2) - (2)].string) );
;} ;}
break; break;
case 50: case 50:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 339 "cond.y" #line 346 "cond.y"
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
UINT len;
(yyval.string) = msi_dup_property( cond->package, (yyvsp[(1) - (1)].string) ); (yyval.string) = msi_dup_property( cond->package, (yyvsp[(1) - (1)].string) );
msi_free( (yyvsp[(1) - (1)].string) ); if ((yyval.string))
{
len = (lstrlenW((yyval.string)) + 1) * sizeof (WCHAR);
(yyval.string) = cond_track_mem( cond, (yyval.string), len );
}
cond_free( (yyvsp[(1) - (1)].string) );
;} ;}
break; break;
case 51: case 51:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 346 "cond.y" #line 359 "cond.y"
{ {
COND_input* cond = (COND_input*) info;
UINT len = GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), NULL, 0 ); UINT len = GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), NULL, 0 );
(yyval.string) = NULL; (yyval.string) = NULL;
if (len++) if (len++)
{ {
(yyval.string) = msi_alloc( len*sizeof (WCHAR) ); (yyval.string) = cond_alloc( cond, len*sizeof (WCHAR) );
if( !(yyval.string) )
YYABORT;
GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), (yyval.string), len ); GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), (yyval.string), len );
} }
msi_free( (yyvsp[(2) - (2)].string) ); cond_free( (yyvsp[(2) - (2)].string) );
;} ;}
break; break;
case 52: case 52:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 360 "cond.y" #line 376 "cond.y"
{ {
(yyval.string) = COND_GetString(&(yyvsp[(1) - (1)].str)); COND_input* cond = (COND_input*) info;
(yyval.string) = COND_GetString( cond, &(yyvsp[(1) - (1)].str) );
if( !(yyval.string) ) if( !(yyval.string) )
YYABORT; YYABORT;
;} ;}
@ -2016,20 +2033,21 @@ yyreduce:
case 53: case 53:
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 369 "cond.y" #line 386 "cond.y"
{ {
LPWSTR szNum = COND_GetString(&(yyvsp[(1) - (1)].str)); COND_input* cond = (COND_input*) info;
LPWSTR szNum = COND_GetString( cond, &(yyvsp[(1) - (1)].str) );
if( !szNum ) if( !szNum )
YYABORT; YYABORT;
(yyval.value) = atoiW( szNum ); (yyval.value) = atoiW( szNum );
msi_free( szNum ); cond_free( szNum );
;} ;}
break; break;
/* Line 1455 of yacc.c */ /* Line 1455 of yacc.c */
#line 2033 "cond.tab.c" #line 2051 "cond.tab.c"
default: break; default: break;
} }
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@ -2241,7 +2259,7 @@ yyreturn:
/* Line 1675 of yacc.c */ /* Line 1675 of yacc.c */
#line 378 "cond.y" #line 396 "cond.y"
@ -2558,11 +2576,11 @@ static int cond_lex( void *COND_lval, COND_input *cond )
return rc; return rc;
} }
static LPWSTR COND_GetString( const struct cond_str *str ) static LPWSTR COND_GetString( COND_input *cond, const struct cond_str *str )
{ {
LPWSTR ret; LPWSTR ret;
ret = msi_alloc( (str->len+1) * sizeof (WCHAR) ); ret = cond_alloc( cond, (str->len+1) * sizeof (WCHAR) );
if( ret ) if( ret )
{ {
memcpy( ret, str->data, str->len * sizeof(WCHAR)); memcpy( ret, str->data, str->len * sizeof(WCHAR));
@ -2572,11 +2590,11 @@ static LPWSTR COND_GetString( const struct cond_str *str )
return ret; return ret;
} }
static LPWSTR COND_GetLiteral( const struct cond_str *str ) static LPWSTR COND_GetLiteral( COND_input *cond, const struct cond_str *str )
{ {
LPWSTR ret; LPWSTR ret;
ret = msi_alloc( (str->len-1) * sizeof (WCHAR) ); ret = cond_alloc( cond, (str->len-1) * sizeof (WCHAR) );
if( ret ) if( ret )
{ {
memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) ); memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) );
@ -2586,6 +2604,48 @@ static LPWSTR COND_GetLiteral( const struct cond_str *str )
return ret; return ret;
} }
static void *cond_alloc( COND_input *cond, unsigned int sz )
{
struct list *mem;
mem = msi_alloc( sizeof (struct list) + sz );
if( !mem )
return NULL;
list_add_head( &(cond->mem), mem );
return mem + 1;
}
static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz )
{
void *new_ptr;
if( !ptr )
return ptr;
new_ptr = cond_alloc( cond, sz );
if( !new_ptr )
{
msi_free( ptr );
return NULL;
}
memcpy( new_ptr, ptr, sz );
msi_free( ptr );
return new_ptr;
}
static void cond_free( void *ptr )
{
struct list *mem = (struct list *)ptr - 1;
if( ptr )
{
list_remove( mem );
msi_free( mem );
}
}
static int cond_error(const char *str) static int cond_error(const char *str)
{ {
TRACE("%s\n", str ); TRACE("%s\n", str );
@ -2596,6 +2656,7 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
{ {
COND_input cond; COND_input cond;
MSICONDITION r; MSICONDITION r;
struct list *mem, *safety;
TRACE("%s\n", debugstr_w( szCondition ) ); TRACE("%s\n", debugstr_w( szCondition ) );
@ -2607,11 +2668,22 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
cond.n = 0; cond.n = 0;
cond.result = MSICONDITION_ERROR; cond.result = MSICONDITION_ERROR;
list_init( &cond.mem );
if ( !cond_parse( &cond ) ) if ( !cond_parse( &cond ) )
r = cond.result; r = cond.result;
else else
r = MSICONDITION_ERROR; r = MSICONDITION_ERROR;
LIST_FOR_EACH_SAFE( mem, safety, &cond.mem )
{
/* The tracked memory lives directly after the list struct */
void *ptr = mem + 1;
if ( r != MSICONDITION_ERROR )
WARN( "condition parser failed to free up some memory: %p\n", ptr );
cond_free( ptr );
}
TRACE("%i <- %s\n", r, debugstr_w(szCondition)); TRACE("%i <- %s\n", r, debugstr_w(szCondition));
return r; return r;
} }

View file

@ -87,7 +87,7 @@ typedef union YYSTYPE
{ {
/* Line 1676 of yacc.c */ /* Line 1676 of yacc.c */
#line 110 "cond.y" #line 116 "cond.y"
struct cond_str str; struct cond_str str;
LPWSTR string; LPWSTR string;

View file

@ -40,6 +40,7 @@
#include "msiserver.h" #include "msiserver.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/list.h"
#define YYLEX_PARAM info #define YYLEX_PARAM info
#define YYPARSE_PARAM info #define YYPARSE_PARAM info
@ -54,6 +55,7 @@ typedef struct tag_yyinput
LPCWSTR str; LPCWSTR str;
INT n; INT n;
MSICONDITION result; MSICONDITION result;
struct list mem;
} COND_input; } COND_input;
struct cond_str { struct cond_str {
@ -61,10 +63,14 @@ struct cond_str {
INT len; INT len;
}; };
static LPWSTR COND_GetString( const struct cond_str *str ); static LPWSTR COND_GetString( COND_input *info, const struct cond_str *str );
static LPWSTR COND_GetLiteral( const struct cond_str *str ); static LPWSTR COND_GetLiteral( COND_input *info, const struct cond_str *str );
static int cond_lex( void *COND_lval, COND_input *info); static int cond_lex( void *COND_lval, COND_input *info);
static void *cond_alloc( COND_input *cond, unsigned int sz );
static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz );
static void cond_free( void *ptr );
static INT compare_int( INT a, INT operator, INT b ); static INT compare_int( INT a, INT operator, INT b );
static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert ); static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert );
@ -73,8 +79,8 @@ static INT compare_and_free_strings( LPWSTR a, INT op, LPWSTR b, BOOL convert )
INT r; INT r;
r = compare_string( a, op, b, convert ); r = compare_string( a, op, b, convert );
msi_free( a ); cond_free( a );
msi_free( b ); cond_free( b );
return r; return r;
} }
@ -189,7 +195,7 @@ boolean_factor:
| value_s | value_s
{ {
$$ = ($1 && $1[0]) ? 1 : 0; $$ = ($1 && $1[0]) ? 1 : 0;
msi_free($1); cond_free( $1 );
} }
| value_i operator value_i | value_i operator value_i
{ {
@ -202,7 +208,7 @@ boolean_factor:
$$ = compare_int( num, $2, $3 ); $$ = compare_int( num, $2, $3 );
else else
$$ = ($2 == COND_NE || $2 == COND_INE ); $$ = ($2 == COND_NE || $2 == COND_INE );
msi_free($1); cond_free( $1 );
} }
| value_i operator symbol_s | value_i operator symbol_s
{ {
@ -211,7 +217,7 @@ boolean_factor:
$$ = compare_int( $1, $2, num ); $$ = compare_int( $1, $2, num );
else else
$$ = ($2 == COND_NE || $2 == COND_INE ); $$ = ($2 == COND_NE || $2 == COND_INE );
msi_free($3); cond_free( $3 );
} }
| symbol_s operator symbol_s | symbol_s operator symbol_s
{ {
@ -232,12 +238,12 @@ boolean_factor:
| literal operator value_i | literal operator value_i
{ {
$$ = 0; $$ = 0;
msi_free($1); cond_free( $1 );
} }
| value_i operator literal | value_i operator literal
{ {
$$ = 0; $$ = 0;
msi_free($3); cond_free( $3 );
} }
| COND_LPAR expression COND_RPAR | COND_LPAR expression COND_RPAR
{ {
@ -281,7 +287,8 @@ value_s:
literal: literal:
COND_LITER COND_LITER
{ {
$$ = COND_GetLiteral(&$1); COND_input* cond = (COND_input*) info;
$$ = COND_GetLiteral( cond, &$1 );
if( !$$ ) if( !$$ )
YYABORT; YYABORT;
} }
@ -299,7 +306,7 @@ value_i:
MSI_GetComponentStateW(cond->package, $2, &install, &action ); MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = action; $$ = action;
msi_free( $2 ); cond_free( $2 );
} }
| COND_QUESTION identifier | COND_QUESTION identifier
{ {
@ -308,7 +315,7 @@ value_i:
MSI_GetComponentStateW(cond->package, $2, &install, &action ); MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = install; $$ = install;
msi_free( $2 ); cond_free( $2 );
} }
| COND_AMPER identifier | COND_AMPER identifier
{ {
@ -321,7 +328,7 @@ value_i:
else else
$$ = action; $$ = action;
msi_free( $2 ); cond_free( $2 );
} }
| COND_EXCLAM identifier | COND_EXCLAM identifier
{ {
@ -330,7 +337,7 @@ value_i:
MSI_GetFeatureStateW(cond->package, $2, &install, &action ); MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = install; $$ = install;
msi_free( $2 ); cond_free( $2 );
} }
; ;
@ -338,27 +345,37 @@ symbol_s:
identifier identifier
{ {
COND_input* cond = (COND_input*) info; COND_input* cond = (COND_input*) info;
UINT len;
$$ = msi_dup_property( cond->package, $1 ); $$ = msi_dup_property( cond->package, $1 );
msi_free( $1 ); if ($$)
{
len = (lstrlenW($$) + 1) * sizeof (WCHAR);
$$ = cond_track_mem( cond, $$, len );
}
cond_free( $1 );
} }
| COND_PERCENT identifier | COND_PERCENT identifier
{ {
COND_input* cond = (COND_input*) info;
UINT len = GetEnvironmentVariableW( $2, NULL, 0 ); UINT len = GetEnvironmentVariableW( $2, NULL, 0 );
$$ = NULL; $$ = NULL;
if (len++) if (len++)
{ {
$$ = msi_alloc( len*sizeof (WCHAR) ); $$ = cond_alloc( cond, len*sizeof (WCHAR) );
if( !$$ )
YYABORT;
GetEnvironmentVariableW( $2, $$, len ); GetEnvironmentVariableW( $2, $$, len );
} }
msi_free( $2 ); cond_free( $2 );
} }
; ;
identifier: identifier:
COND_IDENT COND_IDENT
{ {
$$ = COND_GetString(&$1); COND_input* cond = (COND_input*) info;
$$ = COND_GetString( cond, &$1 );
if( !$$ ) if( !$$ )
YYABORT; YYABORT;
} }
@ -367,11 +384,12 @@ identifier:
integer: integer:
COND_NUMBER COND_NUMBER
{ {
LPWSTR szNum = COND_GetString(&$1); COND_input* cond = (COND_input*) info;
LPWSTR szNum = COND_GetString( cond, &$1 );
if( !szNum ) if( !szNum )
YYABORT; YYABORT;
$$ = atoiW( szNum ); $$ = atoiW( szNum );
msi_free( szNum ); cond_free( szNum );
} }
; ;
@ -691,11 +709,11 @@ static int cond_lex( void *COND_lval, COND_input *cond )
return rc; return rc;
} }
static LPWSTR COND_GetString( const struct cond_str *str ) static LPWSTR COND_GetString( COND_input *cond, const struct cond_str *str )
{ {
LPWSTR ret; LPWSTR ret;
ret = msi_alloc( (str->len+1) * sizeof (WCHAR) ); ret = cond_alloc( cond, (str->len+1) * sizeof (WCHAR) );
if( ret ) if( ret )
{ {
memcpy( ret, str->data, str->len * sizeof(WCHAR)); memcpy( ret, str->data, str->len * sizeof(WCHAR));
@ -705,11 +723,11 @@ static LPWSTR COND_GetString( const struct cond_str *str )
return ret; return ret;
} }
static LPWSTR COND_GetLiteral( const struct cond_str *str ) static LPWSTR COND_GetLiteral( COND_input *cond, const struct cond_str *str )
{ {
LPWSTR ret; LPWSTR ret;
ret = msi_alloc( (str->len-1) * sizeof (WCHAR) ); ret = cond_alloc( cond, (str->len-1) * sizeof (WCHAR) );
if( ret ) if( ret )
{ {
memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) ); memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) );
@ -719,6 +737,48 @@ static LPWSTR COND_GetLiteral( const struct cond_str *str )
return ret; return ret;
} }
static void *cond_alloc( COND_input *cond, unsigned int sz )
{
struct list *mem;
mem = msi_alloc( sizeof (struct list) + sz );
if( !mem )
return NULL;
list_add_head( &(cond->mem), mem );
return mem + 1;
}
static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz )
{
void *new_ptr;
if( !ptr )
return ptr;
new_ptr = cond_alloc( cond, sz );
if( !new_ptr )
{
msi_free( ptr );
return NULL;
}
memcpy( new_ptr, ptr, sz );
msi_free( ptr );
return new_ptr;
}
static void cond_free( void *ptr )
{
struct list *mem = (struct list *)ptr - 1;
if( ptr )
{
list_remove( mem );
msi_free( mem );
}
}
static int cond_error(const char *str) static int cond_error(const char *str)
{ {
TRACE("%s\n", str ); TRACE("%s\n", str );
@ -729,6 +789,7 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
{ {
COND_input cond; COND_input cond;
MSICONDITION r; MSICONDITION r;
struct list *mem, *safety;
TRACE("%s\n", debugstr_w( szCondition ) ); TRACE("%s\n", debugstr_w( szCondition ) );
@ -740,11 +801,22 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
cond.n = 0; cond.n = 0;
cond.result = MSICONDITION_ERROR; cond.result = MSICONDITION_ERROR;
list_init( &cond.mem );
if ( !cond_parse( &cond ) ) if ( !cond_parse( &cond ) )
r = cond.result; r = cond.result;
else else
r = MSICONDITION_ERROR; r = MSICONDITION_ERROR;
LIST_FOR_EACH_SAFE( mem, safety, &cond.mem )
{
/* The tracked memory lives directly after the list struct */
void *ptr = mem + 1;
if ( r != MSICONDITION_ERROR )
WARN( "condition parser failed to free up some memory: %p\n", ptr );
cond_free( ptr );
}
TRACE("%i <- %s\n", r, debugstr_w(szCondition)); TRACE("%i <- %s\n", r, debugstr_w(szCondition));
return r; return r;
} }

View file

@ -647,6 +647,28 @@ static UINT get_action_info( const GUID *guid, INT *type, MSIHANDLE *handle,
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
#ifdef __i386__
extern UINT CUSTOMPROC_wrapper( MsiCustomActionEntryPoint proc, MSIHANDLE handle );
__ASM_GLOBAL_FUNC( CUSTOMPROC_wrapper,
"pushl %ebp\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
"movl %esp,%ebp\n\t"
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
"pushl 12(%ebp)\n\t"
"movl 8(%ebp),%eax\n\t"
"call *%eax\n\t"
"leave\n\t"
__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
__ASM_CFI(".cfi_same_value %ebp\n\t")
"ret" )
#else
static inline UINT CUSTOMPROC_wrapper( MsiCustomActionEntryPoint proc, MSIHANDLE handle )
{
return proc(handle);
}
#endif
static DWORD ACTION_CallDllFunction( const GUID *guid ) static DWORD ACTION_CallDllFunction( const GUID *guid )
{ {
MsiCustomActionEntryPoint fn; MsiCustomActionEntryPoint fn;
@ -685,7 +707,7 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
__TRY __TRY
{ {
r = fn( hPackage ); r = CUSTOMPROC_wrapper( fn, hPackage );
} }
__EXCEPT_PAGE_FAULT __EXCEPT_PAGE_FAULT
{ {

View file

@ -51,6 +51,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
* Any binary data in a table is a reference to a stream. * Any binary data in a table is a reference to a stream.
*/ */
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
typedef struct tagMSITRANSFORM { typedef struct tagMSITRANSFORM {
struct list entry; struct list entry;
IStorage *stg; IStorage *stg;
@ -306,7 +308,7 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
save_path = szDBPath; save_path = szDBPath;
szMode = szPersist; szMode = szPersist;
if( HIWORD( szPersist ) ) if( !IS_INTMSIDBOPEN(szPersist) )
{ {
if (!CopyFileW( szDBPath, szPersist, FALSE )) if (!CopyFileW( szDBPath, szPersist, FALSE ))
return ERROR_OPEN_FAILED; return ERROR_OPEN_FAILED;
@ -459,7 +461,7 @@ UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
goto end; goto end;
} }
if( HIWORD(szPersist) ) if( !IS_INTMSIDBOPEN(szPersist) )
{ {
szwPersist = strdupAtoW( szPersist ); szwPersist = strdupAtoW( szPersist );
if( !szwPersist ) if( !szwPersist )
@ -471,7 +473,7 @@ UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB ); r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
end: end:
if( HIWORD(szPersist) ) if( !IS_INTMSIDBOPEN(szPersist) )
msi_free( szwPersist ); msi_free( szwPersist );
msi_free( szwDBPath ); msi_free( szwDBPath );

View file

@ -166,6 +166,8 @@ static MSIFEATURE *msi_seltree_get_selected_feature( msi_control *control );
#define WM_MSI_DIALOG_CREATE (WM_USER+0x100) #define WM_MSI_DIALOG_CREATE (WM_USER+0x100)
#define WM_MSI_DIALOG_DESTROY (WM_USER+0x101) #define WM_MSI_DIALOG_DESTROY (WM_USER+0x101)
#define USER_INSTALLSTATE_ALL 0x1000
static DWORD uiThreadId; static DWORD uiThreadId;
static HWND hMsiHiddenWindow; static HWND hMsiHiddenWindow;
@ -1876,7 +1878,7 @@ msi_seltree_popup_menu( HWND hwnd, INT x, INT y )
/* FIXME: load strings from resources */ /* FIXME: load strings from resources */
AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_LOCAL, "Install feature locally"); AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_LOCAL, "Install feature locally");
AppendMenuA( hMenu, MF_GRAYED, 0x1000, "Install entire feature"); AppendMenuA( hMenu, MF_ENABLED, USER_INSTALLSTATE_ALL, "Install entire feature");
AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ADVERTISED, "Install on demand"); AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ADVERTISED, "Install on demand");
AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ABSENT, "Don't install"); AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ABSENT, "Don't install");
r = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, r = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
@ -1899,6 +1901,37 @@ msi_seltree_feature_from_item( HWND hwnd, HTREEITEM hItem )
return (MSIFEATURE*) tvi.lParam; return (MSIFEATURE*) tvi.lParam;
} }
static void
msi_seltree_update_feature_installstate( HWND hwnd, HTREEITEM hItem,
MSIPACKAGE *package, MSIFEATURE *feature, INSTALLSTATE state )
{
msi_feature_set_state( package, feature, state );
msi_seltree_sync_item_state( hwnd, feature, hItem );
ACTION_UpdateComponentStates( package, feature->Feature );
}
static void
msi_seltree_update_siblings_and_children_installstate( HWND hwnd, HTREEITEM curr,
MSIPACKAGE *package, INSTALLSTATE state)
{
/* update all siblings */
do
{
MSIFEATURE *feature;
HTREEITEM child;
feature = msi_seltree_feature_from_item( hwnd, curr );
msi_seltree_update_feature_installstate( hwnd, curr, package, feature, state );
/* update this sibling's children */
child = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)curr );
if (child)
msi_seltree_update_siblings_and_children_installstate( hwnd, child,
package, state );
}
while ((curr = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)curr )));
}
static LRESULT static LRESULT
msi_seltree_menu( HWND hwnd, HTREEITEM hItem ) msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
{ {
@ -1931,18 +1964,22 @@ msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
switch (r) switch (r)
{ {
case INSTALLSTATE_LOCAL: case USER_INSTALLSTATE_ALL:
r = INSTALLSTATE_LOCAL;
/* fall-through */
case INSTALLSTATE_ADVERTISED: case INSTALLSTATE_ADVERTISED:
case INSTALLSTATE_ABSENT: case INSTALLSTATE_ABSENT:
msi_feature_set_state(package, feature, r); {
break; HTREEITEM child;
default: child = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem );
FIXME("select feature and all children\n"); if (child)
msi_seltree_update_siblings_and_children_installstate( hwnd, child, package, r );
}
/* fall-through */
case INSTALLSTATE_LOCAL:
msi_seltree_update_feature_installstate( hwnd, hItem, package, feature, r );
break;
} }
/* update */
msi_seltree_sync_item_state( hwnd, feature, hItem );
ACTION_UpdateComponentStates( package, feature->Feature );
return 0; return 0;
} }

View file

@ -383,6 +383,28 @@ static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument,
return MSI_SetPropertyW( package, szReinstallMode, argument ); return MSI_SetPropertyW( package, szReinstallMode, argument );
} }
static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,
msi_dialog *dialog)
{
static const WCHAR szProductID[] = {'P','r','o','d','u','c','t','I','D',0};
static const WCHAR szPIDTemplate[] = {'P','I','D','T','e','m','p','l','a','t','e',0};
static const WCHAR szPIDKEY[] = {'P','I','D','K','E','Y',0};
LPWSTR key, template;
UINT ret = ERROR_SUCCESS;
template = msi_dup_property( package, szPIDTemplate );
key = msi_dup_property( package, szPIDKEY );
if (key && template)
{
FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) );
ret = MSI_SetPropertyW( package, szProductID, key );
}
msi_free( template );
msi_free( key );
return ret;
}
static const struct _events Events[] = { static const struct _events Events[] = {
{ "EndDialog",ControlEvent_EndDialog }, { "EndDialog",ControlEvent_EndDialog },
{ "NewDialog",ControlEvent_NewDialog }, { "NewDialog",ControlEvent_NewDialog },
@ -398,6 +420,7 @@ static const struct _events Events[] = {
{ "DirectoryListUp",ControlEvent_DirectoryListUp }, { "DirectoryListUp",ControlEvent_DirectoryListUp },
{ "SelectionBrowse",ControlEvent_SpawnDialog }, { "SelectionBrowse",ControlEvent_SpawnDialog },
{ "ReinstallMode",ControlEvent_ReinstallMode }, { "ReinstallMode",ControlEvent_ReinstallMode },
{ "ValidateProductID",ControlEvent_ValidateProductID },
{ NULL,NULL }, { NULL,NULL },
}; };

View file

@ -365,6 +365,7 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
debugstr_w(component)); debugstr_w(component));
/* the action taken was the same as the current install state */ /* the action taken was the same as the current install state */
if (comp)
comp->Action = comp->Installed; comp->Action = comp->Installed;
return ERROR_SUCCESS; return ERROR_SUCCESS;

View file

@ -440,238 +440,6 @@ void msi_free_action_script(MSIPACKAGE *package, UINT script)
package->script->ActionCount[script] = 0; package->script->ActionCount[script] = 0;
} }
static void remove_tracked_tempfiles(MSIPACKAGE* package)
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
{
MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
list_remove( &temp->entry );
TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
if (!DeleteFileW( temp->Path ))
ERR("failed to delete %s\n", debugstr_w( temp->Path ));
msi_free( temp->Path );
msi_free( temp );
}
}
static void free_feature( MSIFEATURE *feature )
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
{
FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
list_remove( &fl->entry );
msi_free( fl );
}
LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
{
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
list_remove( &cl->entry );
msi_free( cl );
}
msi_free( feature->Feature );
msi_free( feature->Feature_Parent );
msi_free( feature->Directory );
msi_free( feature->Description );
msi_free( feature->Title );
msi_free( feature );
}
static void free_extension( MSIEXTENSION *ext )
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
{
MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
list_remove( &verb->entry );
msi_free( verb->Verb );
msi_free( verb->Command );
msi_free( verb->Argument );
msi_free( verb );
}
msi_free( ext->Extension );
msi_free( ext->ProgIDText );
msi_free( ext );
}
/* Called when the package is being closed */
void ACTION_free_package_structures( MSIPACKAGE* package)
{
INT i;
struct list *item, *cursor;
TRACE("Freeing package action data\n");
remove_tracked_tempfiles(package);
LIST_FOR_EACH_SAFE( item, cursor, &package->features )
{
MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
list_remove( &feature->entry );
free_feature( feature );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
{
MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
list_remove( &folder->entry );
msi_free( folder->Parent );
msi_free( folder->Directory );
msi_free( folder->TargetDefault );
msi_free( folder->SourceLongPath );
msi_free( folder->SourceShortPath );
msi_free( folder->ResolvedTarget );
msi_free( folder->ResolvedSource );
msi_free( folder->Property );
msi_free( folder );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->components )
{
MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
list_remove( &comp->entry );
msi_free( comp->Component );
msi_free( comp->ComponentId );
msi_free( comp->Directory );
msi_free( comp->Condition );
msi_free( comp->KeyPath );
msi_free( comp->FullKeypath );
msi_free( comp );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->files )
{
MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
list_remove( &file->entry );
msi_free( file->File );
msi_free( file->FileName );
msi_free( file->ShortName );
msi_free( file->LongName );
msi_free( file->Version );
msi_free( file->Language );
msi_free( file->TargetPath );
msi_free( file );
}
/* clean up extension, progid, class and verb structures */
LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
{
MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
list_remove( &cls->entry );
msi_free( cls->clsid );
msi_free( cls->Context );
msi_free( cls->Description );
msi_free( cls->FileTypeMask );
msi_free( cls->IconPath );
msi_free( cls->DefInprocHandler );
msi_free( cls->DefInprocHandler32 );
msi_free( cls->Argument );
msi_free( cls->ProgIDText );
msi_free( cls );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
{
MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
list_remove( &ext->entry );
free_extension( ext );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
{
MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
list_remove( &progid->entry );
msi_free( progid->ProgID );
msi_free( progid->Description );
msi_free( progid->IconPath );
msi_free( progid );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
{
MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
list_remove( &mt->entry );
msi_free( mt->clsid );
msi_free( mt->ContentType );
msi_free( mt );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
{
MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
list_remove( &appid->entry );
msi_free( appid->AppID );
msi_free( appid->RemoteServerName );
msi_free( appid->LocalServer );
msi_free( appid->ServiceParameters );
msi_free( appid->DllSurrogate );
msi_free( appid );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
{
MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
list_remove( &info->entry );
msi_free( info->value );
msi_free( info );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
{
MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
list_remove( &info->entry );
msi_free( info->volume_label );
msi_free( info->disk_prompt );
msi_free( info );
}
if (package->script)
{
for (i = 0; i < TOTAL_SCRIPTS; i++)
msi_free_action_script(package, i);
for (i = 0; i < package->script->UniqueActionsCount; i++)
msi_free(package->script->UniqueActions[i]);
msi_free(package->script->UniqueActions);
msi_free(package->script);
}
if (package->patch)
{
msi_free(package->patch->patchcode);
msi_free(package->patch->transforms);
msi_free(package->patch);
}
msi_free(package->BaseURL);
msi_free(package->PackagePath);
msi_free(package->ProductCode);
msi_free(package->ActionFormat);
msi_free(package->LastAction);
/* cleanup control event subscriptions */
ControlEvent_CleanupSubscriptions(package);
}
/* /*
* build_directory_name() * build_directory_name()
* *

View file

@ -117,8 +117,11 @@ static UINT JOIN_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStr
static UINT JOIN_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) static UINT JOIN_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
{ {
FIXME("(%p, %d, %p): stub!\n", view, row, rec); MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
return ERROR_FUNCTION_FAILED;
TRACE("%p %d %p\n", jv, row, rec);
return msi_view_get_row( jv->db, view, row, rec );
} }
static UINT JOIN_execute( struct tagMSIVIEW *view, MSIRECORD *record ) static UINT JOIN_execute( struct tagMSIVIEW *view, MSIRECORD *record )
@ -219,13 +222,119 @@ static UINT JOIN_get_column_info( struct tagMSIVIEW *view,
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, static UINT join_find_row( MSIJOINVIEW *jv, MSIRECORD *rec, UINT *row )
MSIRECORD *rec, UINT row )
{ {
TRACE("%p %d %p\n", view, eModifyMode, rec); LPCWSTR str;
UINT i, id, data;
str = MSI_RecordGetString( rec, 1 );
msi_string2idW( jv->db->strings, str, &id );
for (i = 0; i < jv->rows; i++)
{
JOIN_fetch_int( &jv->view, i, 1, &data );
if (data == id)
{
*row = i;
return ERROR_SUCCESS;
}
}
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
static UINT JOIN_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
{
MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
JOINTABLE *table;
UINT i, reduced_mask = 0, r = ERROR_SUCCESS, offset = 0, col_count;
MSIRECORD *reduced;
TRACE("%p %d %p %u %08x\n", jv, row, rec, rec->count, mask );
if (mask >= 1 << jv->columns)
return ERROR_INVALID_PARAMETER;
LIST_FOR_EACH_ENTRY(table, &jv->tables, JOINTABLE, entry)
{
r = table->view->ops->get_dimensions( table->view, NULL, &col_count );
if (r != ERROR_SUCCESS)
return r;
reduced = MSI_CreateRecord( col_count );
if (!reduced)
return ERROR_FUNCTION_FAILED;
for (i = 0; i < col_count; i++)
{
r = MSI_RecordCopyField( rec, i + offset + 1, reduced, i + 1 );
if (r != ERROR_SUCCESS)
break;
}
offset += col_count;
reduced_mask = mask >> (jv->columns - offset) & ((1 << col_count) - 1);
if (r == ERROR_SUCCESS)
r = table->view->ops->set_row( table->view, row, reduced, reduced_mask );
msiobj_release( &reduced->hdr );
}
return r;
}
static UINT join_modify_update( struct tagMSIVIEW *view, MSIRECORD *rec )
{
MSIJOINVIEW *jv = (MSIJOINVIEW *)view;
UINT r, row;
r = join_find_row( jv, rec, &row );
if (r != ERROR_SUCCESS)
return r;
return JOIN_set_row( view, row, rec, (1 << jv->columns) - 1 );
}
static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY mode, MSIRECORD *rec, UINT row )
{
UINT r;
TRACE("%p %d %p %u\n", view, mode, rec, row);
switch (mode)
{
case MSIMODIFY_UPDATE:
return join_modify_update( view, rec );
case MSIMODIFY_ASSIGN:
case MSIMODIFY_DELETE:
case MSIMODIFY_INSERT:
case MSIMODIFY_INSERT_TEMPORARY:
case MSIMODIFY_MERGE:
case MSIMODIFY_REPLACE:
case MSIMODIFY_SEEK:
case MSIMODIFY_VALIDATE:
case MSIMODIFY_VALIDATE_DELETE:
case MSIMODIFY_VALIDATE_FIELD:
case MSIMODIFY_VALIDATE_NEW:
r = ERROR_FUNCTION_FAILED;
break;
case MSIMODIFY_REFRESH:
r = ERROR_CALL_NOT_IMPLEMENTED;
break;
default:
WARN("%p %d %p %u - unknown mode\n", view, mode, rec, row );
r = ERROR_INVALID_PARAMETER;
break;
}
return r;
}
static UINT JOIN_delete( struct tagMSIVIEW *view ) static UINT JOIN_delete( struct tagMSIVIEW *view )
{ {
MSIJOINVIEW *jv = (MSIJOINVIEW*)view; MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
@ -259,7 +368,7 @@ static UINT JOIN_find_matching_rows( struct tagMSIVIEW *view, UINT col,
if (col == 0 || col > jv->columns) if (col == 0 || col > jv->columns)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
for (i = (UINT)*handle; i < jv->rows; i++) for (i = PtrToUlong(*handle); i < jv->rows; i++)
{ {
if (view->ops->fetch_int( view, i, col, &row_value ) != ERROR_SUCCESS) if (view->ops->fetch_int( view, i, col, &row_value ) != ERROR_SUCCESS)
continue; continue;

View file

@ -48,6 +48,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#include "msi_Si.rc" #include "msi_Si.rc"
#include "msi_Sv.rc" #include "msi_Sv.rc"
#include "msi_Tr.rc" #include "msi_Tr.rc"
#include "msi_Uk.rc"
#include "msi_Zh.rc" #include "msi_Zh.rc"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

View file

@ -0,0 +1,41 @@
/*
* Ukrainian resources for MSI
*
* Copyright 2005 Mike McCormack
* Copyright 2007 Artem Reznikov
* Copyright 2010 Igor Paliychuk
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "windef.h"
/* UTF-8 */
#pragma code_page(65001)
LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
STRINGTABLE DISCARDABLE
{
4 "Не вдалося відкрити вказаний пакет інсталяції. Перевірте шлях до файлу та спробуйте знов."
5 "шлях %s не знайдено"
9 "вставте диск %s"
10 "невірні параметри"
11 "вкажіть папку, що містить %s"
12 "джерело встановлення даної можливості не вказане"
13 "мережевий диск для даної можливості не вказаний"
14 "можливість з:"
15 "виберіть папку, що містить %s"
}

View file

@ -689,7 +689,6 @@ extern UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si
/* action internals */ /* action internals */
extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR ); extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR );
extern void ACTION_free_package_structures( MSIPACKAGE* );
extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR); extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR);
extern UINT ACTION_ForceReboot(MSIPACKAGE *package); extern UINT ACTION_ForceReboot(MSIPACKAGE *package);
extern UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR szTable, INT iSequenceMode ); extern UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR szTable, INT iSequenceMode );

View file

@ -831,7 +831,7 @@ UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
IWineMsiRemoteDatabase_Release( remote_database ); IWineMsiRemoteDatabase_Release( remote_database );
WARN("MsiDatabaseCommit not allowed during a custom action!\n"); WARN("not allowed during a custom action!\n");
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View file

@ -49,6 +49,237 @@
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
static void remove_tracked_tempfiles( MSIPACKAGE *package )
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
{
MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
list_remove( &temp->entry );
TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
if (!DeleteFileW( temp->Path ))
ERR("failed to delete %s\n", debugstr_w( temp->Path ));
msi_free( temp->Path );
msi_free( temp );
}
}
static void free_feature( MSIFEATURE *feature )
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
{
FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
list_remove( &fl->entry );
msi_free( fl );
}
LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
{
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
list_remove( &cl->entry );
msi_free( cl );
}
msi_free( feature->Feature );
msi_free( feature->Feature_Parent );
msi_free( feature->Directory );
msi_free( feature->Description );
msi_free( feature->Title );
msi_free( feature );
}
static void free_extension( MSIEXTENSION *ext )
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
{
MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
list_remove( &verb->entry );
msi_free( verb->Verb );
msi_free( verb->Command );
msi_free( verb->Argument );
msi_free( verb );
}
msi_free( ext->Extension );
msi_free( ext->ProgIDText );
msi_free( ext );
}
static void free_package_structures( MSIPACKAGE *package )
{
INT i;
struct list *item, *cursor;
TRACE("Freeing package action data\n");
remove_tracked_tempfiles(package);
LIST_FOR_EACH_SAFE( item, cursor, &package->features )
{
MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
list_remove( &feature->entry );
free_feature( feature );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
{
MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
list_remove( &folder->entry );
msi_free( folder->Parent );
msi_free( folder->Directory );
msi_free( folder->TargetDefault );
msi_free( folder->SourceLongPath );
msi_free( folder->SourceShortPath );
msi_free( folder->ResolvedTarget );
msi_free( folder->ResolvedSource );
msi_free( folder->Property );
msi_free( folder );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->components )
{
MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
list_remove( &comp->entry );
msi_free( comp->Component );
msi_free( comp->ComponentId );
msi_free( comp->Directory );
msi_free( comp->Condition );
msi_free( comp->KeyPath );
msi_free( comp->FullKeypath );
msi_free( comp );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->files )
{
MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
list_remove( &file->entry );
msi_free( file->File );
msi_free( file->FileName );
msi_free( file->ShortName );
msi_free( file->LongName );
msi_free( file->Version );
msi_free( file->Language );
msi_free( file->TargetPath );
msi_free( file );
}
/* clean up extension, progid, class and verb structures */
LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
{
MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
list_remove( &cls->entry );
msi_free( cls->clsid );
msi_free( cls->Context );
msi_free( cls->Description );
msi_free( cls->FileTypeMask );
msi_free( cls->IconPath );
msi_free( cls->DefInprocHandler );
msi_free( cls->DefInprocHandler32 );
msi_free( cls->Argument );
msi_free( cls->ProgIDText );
msi_free( cls );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
{
MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
list_remove( &ext->entry );
free_extension( ext );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
{
MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
list_remove( &progid->entry );
msi_free( progid->ProgID );
msi_free( progid->Description );
msi_free( progid->IconPath );
msi_free( progid );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
{
MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
list_remove( &mt->entry );
msi_free( mt->clsid );
msi_free( mt->ContentType );
msi_free( mt );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
{
MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
list_remove( &appid->entry );
msi_free( appid->AppID );
msi_free( appid->RemoteServerName );
msi_free( appid->LocalServer );
msi_free( appid->ServiceParameters );
msi_free( appid->DllSurrogate );
msi_free( appid );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
{
MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
list_remove( &info->entry );
msi_free( info->value );
msi_free( info );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
{
MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
list_remove( &info->entry );
msi_free( info->volume_label );
msi_free( info->disk_prompt );
msi_free( info );
}
if (package->script)
{
for (i = 0; i < TOTAL_SCRIPTS; i++)
msi_free_action_script( package, i );
for (i = 0; i < package->script->UniqueActionsCount; i++)
msi_free( package->script->UniqueActions[i] );
msi_free( package->script->UniqueActions );
msi_free( package->script );
}
if (package->patch)
{
msi_free( package->patch->patchcode );
msi_free( package->patch->transforms );
msi_free( package->patch );
}
msi_free( package->BaseURL );
msi_free( package->PackagePath );
msi_free( package->ProductCode );
msi_free( package->ActionFormat );
msi_free( package->LastAction );
/* cleanup control event subscriptions */
ControlEvent_CleanupSubscriptions( package );
}
static void MSI_FreePackage( MSIOBJECTHDR *arg) static void MSI_FreePackage( MSIOBJECTHDR *arg)
{ {
MSIPACKAGE *package= (MSIPACKAGE*) arg; MSIPACKAGE *package= (MSIPACKAGE*) arg;
@ -57,7 +288,7 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg)
msi_dialog_destroy( package->dialog ); msi_dialog_destroy( package->dialog );
msiobj_release( &package->db->hdr ); msiobj_release( &package->db->hdr );
ACTION_free_package_structures(package); free_package_structures(package);
} }
static UINT create_temp_property_table(MSIPACKAGE *package) static UINT create_temp_property_table(MSIPACKAGE *package)

View file

@ -452,7 +452,7 @@ static UINT STORAGES_find_matching_rows(struct tagMSIVIEW *view, UINT col,
UINT val, UINT *row, MSIITERHANDLE *handle) UINT val, UINT *row, MSIITERHANDLE *handle)
{ {
MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view; MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
UINT index = (UINT)*handle; UINT index = PtrToUlong(*handle);
TRACE("(%d, %d): %d\n", *row, col, val); TRACE("(%d, %d): %d\n", *row, col, val);
@ -470,7 +470,7 @@ static UINT STORAGES_find_matching_rows(struct tagMSIVIEW *view, UINT col,
index++; index++;
} }
*handle = (MSIITERHANDLE)++index; *handle = UlongToPtr(++index);
if (index >= sv->num_rows) if (index >= sv->num_rows)
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;

View file

@ -41,7 +41,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
typedef struct tabSTREAM typedef struct tabSTREAM
{ {
UINT str_index; UINT str_index;
LPWSTR name;
IStream *stream; IStream *stream;
} STREAM; } STREAM;
@ -72,7 +71,6 @@ static STREAM *create_stream(MSISTREAMSVIEW *sv, LPWSTR name, BOOL encoded, IStr
{ {
STREAM *stream; STREAM *stream;
WCHAR decoded[MAX_STREAM_NAME_LEN]; WCHAR decoded[MAX_STREAM_NAME_LEN];
LPWSTR ptr = name;
stream = msi_alloc(sizeof(STREAM)); stream = msi_alloc(sizeof(STREAM));
if (!stream) if (!stream)
@ -81,18 +79,11 @@ static STREAM *create_stream(MSISTREAMSVIEW *sv, LPWSTR name, BOOL encoded, IStr
if (encoded) if (encoded)
{ {
decode_streamname(name, decoded); decode_streamname(name, decoded);
ptr = decoded;
TRACE("stream -> %s %s\n", debugstr_w(name), debugstr_w(decoded)); TRACE("stream -> %s %s\n", debugstr_w(name), debugstr_w(decoded));
name = decoded;
} }
stream->name = strdupW(ptr); stream->str_index = msi_addstringW(sv->db->strings, 0, name, -1, 1, StringNonPersistent);
if (!stream->name)
{
msi_free(stream);
return NULL;
}
stream->str_index = msi_addstringW(sv->db->strings, 0, stream->name, -1, 1, StringNonPersistent);
stream->stream = stm; stream->stream = stm;
return stream; return stream;
} }
@ -133,9 +124,9 @@ static UINT STREAMS_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec
{ {
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
FIXME("%p %d %p\n", sv, row, rec); TRACE("%p %d %p\n", sv, row, rec);
return ERROR_CALL_NOT_IMPLEMENTED; return msi_view_get_row( sv->db, view, row, rec );
} }
static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
@ -144,13 +135,13 @@ static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U
STREAM *stream; STREAM *stream;
IStream *stm; IStream *stm;
STATSTG stat; STATSTG stat;
LPWSTR name = NULL; LPWSTR encname = NULL, name = NULL;
USHORT *data = NULL; USHORT *data = NULL;
HRESULT hr; HRESULT hr;
ULONG count; ULONG count;
UINT r = ERROR_FUNCTION_FAILED; UINT r = ERROR_FUNCTION_FAILED;
TRACE("(%p, %p)\n", view, rec); TRACE("(%p, %d, %p, %08x)\n", view, row, rec, mask);
if (row > sv->num_rows) if (row > sv->num_rows)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
@ -167,7 +158,10 @@ static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U
} }
if (stat.cbSize.QuadPart >> 32) if (stat.cbSize.QuadPart >> 32)
{
WARN("stream too large\n");
goto done; goto done;
}
data = msi_alloc(stat.cbSize.QuadPart); data = msi_alloc(stat.cbSize.QuadPart);
if (!data) if (!data)
@ -182,7 +176,13 @@ static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U
name = strdupW(MSI_RecordGetString(rec, 1)); name = strdupW(MSI_RecordGetString(rec, 1));
if (!name) if (!name)
{
WARN("failed to retrieve stream name\n");
goto done; goto done;
}
encname = encode_streamname(FALSE, name);
IStorage_DestroyElement(sv->db->storage, encname);
r = write_stream_data(sv->db->storage, name, data, count, FALSE); r = write_stream_data(sv->db->storage, name, data, count, FALSE);
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
@ -195,14 +195,20 @@ static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U
if (!stream) if (!stream)
goto done; goto done;
IStorage_OpenStream(sv->db->storage, name, 0, hr = IStorage_OpenStream(sv->db->storage, encname, 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
if (FAILED(hr))
{
WARN("failed to open stream: %08x\n", hr);
goto done;
}
sv->streams[row] = stream; sv->streams[row] = stream;
done: done:
msi_free(name); msi_free(name);
msi_free(data); msi_free(data);
msi_free(encname);
IStream_Release(stm); IStream_Release(stm);
@ -212,6 +218,9 @@ done:
static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary) static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
{ {
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
UINT i;
TRACE("(%p, %p, %d, %d)\n", view, rec, row, temporary);
if (!streams_set_table_size(sv, ++sv->num_rows)) if (!streams_set_table_size(sv, ++sv->num_rows))
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
@ -219,7 +228,11 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row
if (row == -1) if (row == -1)
row = sv->num_rows - 1; row = sv->num_rows - 1;
/* FIXME have to readjust rows */ /* shift the rows to make room for the new row */
for (i = sv->num_rows - 1; i > row; i--)
{
sv->streams[i] = sv->streams[i - 1];
}
return STREAMS_set_row(view, row, rec, 0); return STREAMS_set_row(view, row, rec, 0);
} }
@ -274,7 +287,7 @@ static UINT STREAMS_get_column_info(struct tagMSIVIEW *view, UINT n,
{ {
case 1: case 1:
name_ptr = Name; name_ptr = Name;
if (type) *type = MSITYPE_STRING | MAX_STREAM_NAME_LEN; if (type) *type = MSITYPE_STRING | MSITYPE_VALID | MAX_STREAM_NAME_LEN;
break; break;
case 2: case 2:
@ -404,8 +417,6 @@ static UINT STREAMS_delete(struct tagMSIVIEW *view)
{ {
if (sv->streams[i]->stream) if (sv->streams[i]->stream)
IStream_Release(sv->streams[i]->stream); IStream_Release(sv->streams[i]->stream);
msi_free(sv->streams[i]->name);
msi_free(sv->streams[i]); msi_free(sv->streams[i]);
} }
} }
@ -420,9 +431,9 @@ static UINT STREAMS_find_matching_rows(struct tagMSIVIEW *view, UINT col,
UINT val, UINT *row, MSIITERHANDLE *handle) UINT val, UINT *row, MSIITERHANDLE *handle)
{ {
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
UINT index = (UINT)*handle; UINT index = PtrToUlong(*handle);
TRACE("(%d, %d): %d\n", *row, col, val); TRACE("(%p, %d, %d, %p, %p)\n", view, col, val, row, handle);
if (col == 0 || col > NUM_STREAMS_COLS) if (col == 0 || col > NUM_STREAMS_COLS)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -438,8 +449,9 @@ static UINT STREAMS_find_matching_rows(struct tagMSIVIEW *view, UINT col,
index++; index++;
} }
*handle = (MSIITERHANDLE)++index; *handle = UlongToPtr(++index);
if (index >= sv->num_rows)
if (index > sv->num_rows)
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -510,10 +522,17 @@ static INT add_streams_to_table(MSISTREAMSVIEW *sv)
break; break;
} }
IStorage_OpenStream(sv->db->storage, stat.pwcsName, 0, hr = IStorage_OpenStream(sv->db->storage, stat.pwcsName, 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
CoTaskMemFree(stat.pwcsName); CoTaskMemFree(stat.pwcsName);
if (FAILED(hr))
{
WARN("failed to open stream: %08x\n", hr);
count = -1;
break;
}
if (!streams_set_table_size(sv, ++count)) if (!streams_set_table_size(sv, ++count))
{ {
count = -1; count = -1;

View file

@ -597,6 +597,10 @@ UINT WINAPI MsiSourceListEnumSourcesA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD,
UINT WINAPI MsiSourceListEnumSourcesW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPWSTR, LPDWORD); UINT WINAPI MsiSourceListEnumSourcesW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPWSTR, LPDWORD);
#define MsiSourceListEnumSources WINELIB_NAME_AW(MsiSourceListEnumSources) #define MsiSourceListEnumSources WINELIB_NAME_AW(MsiSourceListEnumSources)
UINT WINAPI MsiSourceListClearSourceA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR);
UINT WINAPI MsiSourceListClearSourceW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR);
#define MsiSourceListClearSource WINELIB_NAME_AW(MsiSourceListClearSource)
UINT WINAPI MsiSourceListClearAllA(LPCSTR, LPCSTR, DWORD); UINT WINAPI MsiSourceListClearAllA(LPCSTR, LPCSTR, DWORD);
UINT WINAPI MsiSourceListClearAllW(LPCWSTR, LPCWSTR, DWORD); UINT WINAPI MsiSourceListClearAllW(LPCWSTR, LPCWSTR, DWORD);
#define MsiSourceListClearAll WINELIB_NAME_AW(MsiSourceListClearAll) #define MsiSourceListClearAll WINELIB_NAME_AW(MsiSourceListClearAll)