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;
}
/*
* 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 const WCHAR ExecSeqQuery[] =
@ -981,7 +977,60 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package)
rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package);
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;
}
@ -1562,8 +1611,10 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
while (ptr)
{
if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
|| (!ptr2 && strcmpW(ptr,feature->Feature)==0))
int len = ptr2 - ptr;
if ((ptr2 && strlenW(feature->Feature) == len && !strncmpW(ptr, feature->Feature, len))
|| (!ptr2 && !strcmpW(ptr, feature->Feature)))
{
msi_feature_set_state(package, feature, state);
break;
@ -1583,55 +1634,57 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
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[] =
{'A','D','D','L','O','C','A','L',0};
static const WCHAR szAddSource[] =
{'A','D','D','S','O','U','R','C','E',0};
static const WCHAR szAdvertise[] =
{'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;
MSIFEATURE *feature;
/* I do not know if this is where it should happen.. but */
TRACE("Checking Install Level\n");
level = msi_get_property_int(package, szlevel, 1);
/* ok here is the _real_ rub
* 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)
if (!msi_get_property_int( package, szPreselected, 0 ))
{
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);
}
}
else
MSI_SetPropertyW(package, szPreselected, szOne);
/*
* 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[] =
{'O','u','t','O','f','D','i','s','k','S','p','a','c','e',0};
MSICOMPONENT *comp;
UINT rc;
UINT rc = ERROR_SUCCESS;
MSIQUERY * view;
LPWSTR level;
@ -1982,26 +2033,28 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
TRACE("File calculations\n");
msi_check_file_install_states( package );
TRACE("Evaluating Condition Table\n");
rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);
if (rc == ERROR_SUCCESS)
if (!process_overrides( package, msi_get_property_int( package, szlevel, 1 ) ))
{
rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeConditions,
package);
msiobj_release(&view->hdr);
}
TRACE("Evaluating Condition Table\n");
TRACE("Enabling or Disabling Components\n");
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{
if (MSI_EvaluateConditionW(package, comp->Condition) == MSICONDITION_FALSE)
rc = MSI_DatabaseOpenViewW( package->db, ConditionQuery, &view );
if (rc == ERROR_SUCCESS)
{
TRACE("Disabling component %s\n", debugstr_w(comp->Component));
comp->Enabled = FALSE;
rc = MSI_IterateRecords( view, NULL, ITERATE_CostFinalizeConditions, package );
msiobj_release( &view->hdr );
}
TRACE("Enabling or Disabling Components\n");
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{
if (MSI_EvaluateConditionW( package, comp->Condition ) == MSICONDITION_FALSE)
{
TRACE("Disabling component %s\n", debugstr_w(comp->Component));
comp->Enabled = FALSE;
}
else
comp->Enabled = TRUE;
}
else
comp->Enabled = TRUE;
}
MSI_SetPropertyW(package,szCosting,szOne);
@ -3652,6 +3705,89 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
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)
{
MSIFEATURE *feature;
@ -4462,8 +4598,8 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
SC_HANDLE scm, service = NULL;
LPCWSTR name, *vector = NULL;
LPWSTR args;
LPCWSTR *vector = NULL;
LPWSTR name, args;
DWORD event, numargs;
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)
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);
args = strdupW(MSI_RecordGetString(rec, 4));
if (!(event & msidbServiceControlEventStart))
return ERROR_SUCCESS;
@ -4488,15 +4624,16 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
service = OpenServiceW(scm, name, SERVICE_START);
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;
}
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;
}
@ -4506,6 +4643,7 @@ done:
CloseServiceHandle(service);
CloseServiceHandle(scm);
msi_free(name);
msi_free(args);
msi_free(vector);
return r;
@ -4570,27 +4708,12 @@ error:
return FALSE;
}
static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
static UINT stop_service( LPCWSTR name )
{
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
SC_HANDLE scm = NULL, service = NULL;
SERVICE_STATUS status;
SERVICE_STATUS_PROCESS ssp;
SC_HANDLE scm = NULL, service = NULL;
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));
DWORD needed;
scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!scm)
@ -4605,16 +4728,14 @@ static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
SERVICE_ENUMERATE_DEPENDENTS);
if (!service)
{
WARN("Failed to open service (%s): %d\n",
debugstr_w(name), GetLastError());
WARN("Failed to open service (%s): %d\n", debugstr_w(name), GetLastError());
goto done;
}
if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS), &needed))
{
WARN("Failed to query service status (%s): %d\n",
debugstr_w(name), GetLastError());
WARN("Failed to query service status (%s): %d\n", debugstr_w(name), GetLastError());
goto done;
}
@ -4629,8 +4750,28 @@ static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
done:
CloseServiceHandle(service);
CloseServiceHandle(scm);
msi_free(name);
msi_free(args);
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 );
return ERROR_SUCCESS;
}
@ -4654,6 +4795,69 @@ static UINT ACTION_StopServices( MSIPACKAGE *package )
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 )
{
MSIFILE *file;
@ -4922,16 +5126,30 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
LPCWSTR ptr = *value;
if (!strncmpW(ptr, prefix, prefix_len))
{
*flags |= ENV_MOD_APPEND;
*value += lstrlenW(prefix);
if (ptr[prefix_len] == szSemiColon[0])
{
*flags |= ENV_MOD_APPEND;
*value += lstrlenW(prefix);
}
else
{
*value = NULL;
}
}
else if (lstrlenW(*value) >= prefix_len)
{
ptr += lstrlenW(ptr) - prefix_len;
if (!lstrcmpW(ptr, prefix))
{
*flags |= ENV_MOD_PREFIX;
/* the "[~]" will be removed by deformat_string */;
if ((ptr-1) > *value && *(ptr-1) == szSemiColon[0])
{
*flags |= ENV_MOD_PREFIX;
/* 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));
res = env_set_flags(&name, &value, &flags);
if (res != ERROR_SUCCESS)
if (res != ERROR_SUCCESS || !value)
goto done;
if (value && !deformat_string(package, value, &deformatted))
@ -5023,6 +5241,9 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
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);
newval = strdupW(value);
if (!newval)
@ -5033,7 +5254,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
}
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;
goto done;
@ -5063,7 +5285,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
int multiplier = 0;
if (flags & ENV_MOD_APPEND) multiplier++;
if (flags & ENV_MOD_PREFIX) multiplier++;
mod_size = (lstrlenW(value) + 1) * multiplier;
mod_size = lstrlenW(value) * multiplier;
size += mod_size * sizeof(WCHAR);
}
@ -5078,26 +5300,18 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_PREFIX)
{
lstrcpyW(newval, value);
lstrcatW(newval, szSemiColon);
ptr = newval + lstrlenW(value) + 1;
ptr = newval + lstrlenW(value);
}
lstrcpyW(ptr, data);
if (flags & ENV_MOD_APPEND)
{
lstrcatW(newval, szSemiColon);
lstrcatW(newval, value);
}
}
if (newval)
{
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
}
else
res = ERROR_SUCCESS;
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
done:
if (env) RegCloseKey(env);
@ -5911,6 +6125,13 @@ done:
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,
LPCSTR action, LPCWSTR table )
{
@ -5973,18 +6194,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
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 const WCHAR table[] = {
@ -6048,12 +6257,6 @@ static UINT ACTION_RemoveExistingProducts( MSIPACKAGE *package )
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 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 );
}
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 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 },
{ szResolveSource, ACTION_ResolveSource },
{ szRMCCPSearch, ACTION_RMCCPSearch },
{ szScheduleReboot, NULL },
{ szScheduleReboot, ACTION_ScheduleReboot },
{ szSelfRegModules, ACTION_SelfRegModules },
{ szSelfUnregModules, ACTION_SelfUnregModules },
{ szSetODBCFolders, NULL },
{ szSetODBCFolders, ACTION_SetODBCFolders },
{ szStartServices, ACTION_StartServices },
{ szStopServices, ACTION_StopServices },
{ szUnpublishComponents, ACTION_UnpublishComponents },

View file

@ -463,7 +463,7 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNAT
ACTION_ConvertRegValue(regType, value, sz, appValue);
break;
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));
}
end:

View file

@ -1138,6 +1138,21 @@ static HRESULT WINAPI ViewImpl_Invoke(
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(
AutomationObject* This,
DISPID dispIdMember,
@ -1208,6 +1223,11 @@ static HRESULT WINAPI DatabaseImpl_Invoke(
else return DISP_E_MEMBERNOTFOUND;
break;
case DISPID_INSTALLER_LASTERRORRECORD:
return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
pVarResult, pExcepInfo,
puArgErr);
default:
return DISP_E_MEMBERNOTFOUND;
}

View file

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

View file

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

View file

@ -40,6 +40,7 @@
#include "msiserver.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/list.h"
#define YYLEX_PARAM info
#define YYPARSE_PARAM info
@ -54,6 +55,7 @@ typedef struct tag_yyinput
LPCWSTR str;
INT n;
MSICONDITION result;
struct list mem;
} COND_input;
struct cond_str {
@ -61,10 +63,14 @@ struct cond_str {
INT len;
};
static LPWSTR COND_GetString( const struct cond_str *str );
static LPWSTR COND_GetLiteral( const struct cond_str *str );
static LPWSTR COND_GetString( COND_input *info, 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 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_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;
r = compare_string( a, op, b, convert );
msi_free( a );
msi_free( b );
cond_free( a );
cond_free( b );
return r;
}
@ -189,7 +195,7 @@ boolean_factor:
| value_s
{
$$ = ($1 && $1[0]) ? 1 : 0;
msi_free($1);
cond_free( $1 );
}
| value_i operator value_i
{
@ -202,7 +208,7 @@ boolean_factor:
$$ = compare_int( num, $2, $3 );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
msi_free($1);
cond_free( $1 );
}
| value_i operator symbol_s
{
@ -211,7 +217,7 @@ boolean_factor:
$$ = compare_int( $1, $2, num );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
msi_free($3);
cond_free( $3 );
}
| symbol_s operator symbol_s
{
@ -232,12 +238,12 @@ boolean_factor:
| literal operator value_i
{
$$ = 0;
msi_free($1);
cond_free( $1 );
}
| value_i operator literal
{
$$ = 0;
msi_free($3);
cond_free( $3 );
}
| COND_LPAR expression COND_RPAR
{
@ -281,7 +287,8 @@ value_s:
literal:
COND_LITER
{
$$ = COND_GetLiteral(&$1);
COND_input* cond = (COND_input*) info;
$$ = COND_GetLiteral( cond, &$1 );
if( !$$ )
YYABORT;
}
@ -299,7 +306,7 @@ value_i:
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = action;
msi_free( $2 );
cond_free( $2 );
}
| COND_QUESTION identifier
{
@ -308,7 +315,7 @@ value_i:
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = install;
msi_free( $2 );
cond_free( $2 );
}
| COND_AMPER identifier
{
@ -321,7 +328,7 @@ value_i:
else
$$ = action;
msi_free( $2 );
cond_free( $2 );
}
| COND_EXCLAM identifier
{
@ -330,7 +337,7 @@ value_i:
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = install;
msi_free( $2 );
cond_free( $2 );
}
;
@ -338,27 +345,37 @@ symbol_s:
identifier
{
COND_input* cond = (COND_input*) info;
UINT len;
$$ = 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_input* cond = (COND_input*) info;
UINT len = GetEnvironmentVariableW( $2, NULL, 0 );
$$ = NULL;
if (len++)
{
$$ = msi_alloc( len*sizeof (WCHAR) );
$$ = cond_alloc( cond, len*sizeof (WCHAR) );
if( !$$ )
YYABORT;
GetEnvironmentVariableW( $2, $$, len );
}
msi_free( $2 );
cond_free( $2 );
}
;
identifier:
COND_IDENT
{
$$ = COND_GetString(&$1);
COND_input* cond = (COND_input*) info;
$$ = COND_GetString( cond, &$1 );
if( !$$ )
YYABORT;
}
@ -367,11 +384,12 @@ identifier:
integer:
COND_NUMBER
{
LPWSTR szNum = COND_GetString(&$1);
COND_input* cond = (COND_input*) info;
LPWSTR szNum = COND_GetString( cond, &$1 );
if( !szNum )
YYABORT;
$$ = atoiW( szNum );
msi_free( szNum );
cond_free( szNum );
}
;
@ -691,11 +709,11 @@ static int cond_lex( void *COND_lval, COND_input *cond )
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;
ret = msi_alloc( (str->len+1) * sizeof (WCHAR) );
ret = cond_alloc( cond, (str->len+1) * sizeof (WCHAR) );
if( ret )
{
memcpy( ret, str->data, str->len * sizeof(WCHAR));
@ -705,11 +723,11 @@ static LPWSTR COND_GetString( const struct cond_str *str )
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;
ret = msi_alloc( (str->len-1) * sizeof (WCHAR) );
ret = cond_alloc( cond, (str->len-1) * sizeof (WCHAR) );
if( ret )
{
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;
}
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)
{
TRACE("%s\n", str );
@ -729,6 +789,7 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
{
COND_input cond;
MSICONDITION r;
struct list *mem, *safety;
TRACE("%s\n", debugstr_w( szCondition ) );
@ -739,12 +800,23 @@ MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *package, LPCWSTR szCondition )
cond.str = szCondition;
cond.n = 0;
cond.result = MSICONDITION_ERROR;
list_init( &cond.mem );
if ( !cond_parse( &cond ) )
r = cond.result;
else
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));
return r;
}

View file

@ -647,6 +647,28 @@ static UINT get_action_info( const GUID *guid, INT *type, MSIHANDLE *handle,
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 )
{
MsiCustomActionEntryPoint fn;
@ -685,7 +707,7 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
__TRY
{
r = fn( hPackage );
r = CUSTOMPROC_wrapper( fn, hPackage );
}
__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.
*/
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
typedef struct tagMSITRANSFORM {
struct list entry;
IStorage *stg;
@ -306,7 +308,7 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
save_path = szDBPath;
szMode = szPersist;
if( HIWORD( szPersist ) )
if( !IS_INTMSIDBOPEN(szPersist) )
{
if (!CopyFileW( szDBPath, szPersist, FALSE ))
return ERROR_OPEN_FAILED;
@ -459,7 +461,7 @@ UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
goto end;
}
if( HIWORD(szPersist) )
if( !IS_INTMSIDBOPEN(szPersist) )
{
szwPersist = strdupAtoW( szPersist );
if( !szwPersist )
@ -471,7 +473,7 @@ UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
end:
if( HIWORD(szPersist) )
if( !IS_INTMSIDBOPEN(szPersist) )
msi_free( szwPersist );
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_DESTROY (WM_USER+0x101)
#define USER_INSTALLSTATE_ALL 0x1000
static DWORD uiThreadId;
static HWND hMsiHiddenWindow;
@ -1876,7 +1878,7 @@ msi_seltree_popup_menu( HWND hwnd, INT x, INT y )
/* FIXME: load strings from resources */
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_ABSENT, "Don't install");
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;
}
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
msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
{
@ -1931,19 +1964,23 @@ msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
switch (r)
{
case INSTALLSTATE_LOCAL:
case USER_INSTALLSTATE_ALL:
r = INSTALLSTATE_LOCAL;
/* fall-through */
case INSTALLSTATE_ADVERTISED:
case INSTALLSTATE_ABSENT:
msi_feature_set_state(package, feature, r);
{
HTREEITEM child;
child = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem );
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;
default:
FIXME("select feature and all children\n");
}
/* update */
msi_seltree_sync_item_state( hwnd, feature, hItem );
ACTION_UpdateComponentStates( package, feature->Feature );
return 0;
}

View file

@ -383,6 +383,28 @@ static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR 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[] = {
{ "EndDialog",ControlEvent_EndDialog },
{ "NewDialog",ControlEvent_NewDialog },
@ -398,6 +420,7 @@ static const struct _events Events[] = {
{ "DirectoryListUp",ControlEvent_DirectoryListUp },
{ "SelectionBrowse",ControlEvent_SpawnDialog },
{ "ReinstallMode",ControlEvent_ReinstallMode },
{ "ValidateProductID",ControlEvent_ValidateProductID },
{ NULL,NULL },
};

View file

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

View file

@ -440,238 +440,6 @@ void msi_free_action_script(MSIPACKAGE *package, UINT script)
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()
*

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 )
{
FIXME("(%p, %d, %p): stub!\n", view, row, rec);
return ERROR_FUNCTION_FAILED;
MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
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 )
@ -219,13 +222,119 @@ static UINT JOIN_get_column_info( struct tagMSIVIEW *view,
return ERROR_FUNCTION_FAILED;
}
static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec, UINT row )
static UINT join_find_row( MSIJOINVIEW *jv, 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;
}
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 )
{
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)
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)
continue;

View file

@ -48,6 +48,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#include "msi_Si.rc"
#include "msi_Sv.rc"
#include "msi_Tr.rc"
#include "msi_Uk.rc"
#include "msi_Zh.rc"
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 */
extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR );
extern void ACTION_free_package_structures( MSIPACKAGE* );
extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR);
extern UINT ACTION_ForceReboot(MSIPACKAGE *package);
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;
IWineMsiRemoteDatabase_Release( remote_database );
WARN("MsiDatabaseCommit not allowed during a custom action!\n");
WARN("not allowed during a custom action!\n");
return ERROR_SUCCESS;
}

View file

@ -49,6 +49,237 @@
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)
{
MSIPACKAGE *package= (MSIPACKAGE*) arg;
@ -57,7 +288,7 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg)
msi_dialog_destroy( package->dialog );
msiobj_release( &package->db->hdr );
ACTION_free_package_structures(package);
free_package_structures(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)
{
MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
UINT index = (UINT)*handle;
UINT index = PtrToUlong(*handle);
TRACE("(%d, %d): %d\n", *row, col, val);
@ -470,7 +470,7 @@ static UINT STORAGES_find_matching_rows(struct tagMSIVIEW *view, UINT col,
index++;
}
*handle = (MSIITERHANDLE)++index;
*handle = UlongToPtr(++index);
if (index >= sv->num_rows)
return ERROR_NO_MORE_ITEMS;

View file

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