mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +00:00
[MSI]
sync msi to wine 1.1.38 svn path=/trunk/; revision=45468
This commit is contained in:
parent
a5996ad2bf
commit
a1608caf31
21 changed files with 1160 additions and 530 deletions
|
@ -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 },
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
41
reactos/dll/win32/msi/msi_Uk.rc
Normal file
41
reactos/dll/win32/msi/msi_Uk.rc
Normal 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"
|
||||
}
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue