[MSI] Sync with Wine 3.0. CORE-14225

This commit is contained in:
Amine Khaldi 2018-01-20 12:29:30 +01:00
parent 35e6bb9199
commit f8b992f2d3
14 changed files with 828 additions and 1151 deletions

View file

@ -139,13 +139,8 @@ static const WCHAR szValidateProductID[] =
{'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0};
static const WCHAR szWriteEnvironmentStrings[] =
{'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t','S','t','r','i','n','g','s',0};
struct dummy_thread
{
HANDLE started;
HANDLE stopped;
HANDLE thread;
};
static const WCHAR szINSTALL[] =
{'I','N','S','T','A','L','L',0};
static INT ui_actionstart(MSIPACKAGE *package, LPCWSTR action, LPCWSTR description, LPCWSTR template)
{
@ -182,7 +177,11 @@ static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
template = msi_get_error_message(package->db, start ? MSIERR_INFO_ACTIONSTART : MSIERR_INFO_ACTIONENDED);
row = MSI_CreateRecord(2);
if (!row) return;
if (!row)
{
msi_free(template);
return;
}
MSI_RecordSetStringW(row, 0, template);
MSI_RecordSetStringW(row, 1, action);
MSI_RecordSetInteger(row, 2, start ? package->LastActionResult : rc);
@ -493,10 +492,7 @@ static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
return ERROR_SUCCESS;
}
if (needs_ui_sequence(package))
rc = ACTION_PerformUIAction(package, action, SCRIPT_NONE);
else
rc = ACTION_PerformAction(package, action, SCRIPT_NONE);
rc = ACTION_PerformAction(package, action, SCRIPT_NONE);
msi_dialog_check_messages( NULL );
@ -536,41 +532,26 @@ UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR table )
return r;
}
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package)
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
'`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
'`','S','e','q','u','e','n','c','e','`',' ', '>',' ','%','i',' ',
'`','S','e','q','u','e','n','c','e','`',' ', '>',' ','0',' ',
'O','R','D','E','R',' ', 'B','Y',' ','`','S','e','q','u','e','n','c','e','`',0};
static const WCHAR query_validate[] = {
'S','E','L','E','C','T',' ','`','S','e','q','u','e','n','c','e','`',
' ', 'F','R','O','M',' ','`','I','n','s','t','a','l','l',
'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e','`',' ',
'W','H','E','R','E',' ','`','A','c','t','i','o','n','`',' ','=',
' ','\'', 'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','\'',0};
MSIQUERY *view;
INT seq = 0;
UINT rc;
if (package->script->ExecuteSequenceRun)
if (package->ExecuteSequenceRun)
{
TRACE("Execute Sequence already Run\n");
return ERROR_SUCCESS;
}
package->script->ExecuteSequenceRun = TRUE;
package->ExecuteSequenceRun = TRUE;
/* get the sequence number */
if (UIran)
{
MSIRECORD *row = MSI_QueryGetRecord(package->db, query_validate);
if (!row) return ERROR_FUNCTION_FAILED;
seq = MSI_RecordGetInteger(row,1);
msiobj_release(&row->hdr);
}
rc = MSI_OpenQuery(package->db, &view, query, seq);
rc = MSI_OpenQuery(package->db, &view, query);
if (rc == ERROR_SUCCESS)
{
TRACE("Running the actions\n");
@ -1541,39 +1522,36 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
return ERROR_SUCCESS;
}
static UINT execute_script_action( MSIPACKAGE *package, UINT script, UINT index )
{
const WCHAR *action = package->script->Actions[script][index];
ui_actionstart( package, action, NULL, NULL );
TRACE("executing %s\n", debugstr_w(action));
return ACTION_PerformAction( package, action, script );
}
static UINT execute_script( MSIPACKAGE *package, UINT script )
{
UINT i, rc = ERROR_SUCCESS;
TRACE("executing script %u\n", script);
if (!package->script)
{
ERR("no script!\n");
return ERROR_FUNCTION_FAILED;
}
if (script == SCRIPT_ROLLBACK)
{
for (i = package->script->ActionCount[script]; i > 0; i--)
for (i = package->script_actions_count[script]; i > 0; i--)
{
rc = execute_script_action( package, script, i - 1 );
if (rc != ERROR_SUCCESS) break;
rc = ACTION_PerformAction(package, package->script_actions[script][i-1], script);
if (rc != ERROR_SUCCESS)
{
ERR("Execution of script %i halted; action %s returned %u\n",
script, debugstr_w(package->script_actions[script][i-1]), rc);
break;
}
}
}
else
{
for (i = 0; i < package->script->ActionCount[script]; i++)
for (i = 0; i < package->script_actions_count[script]; i++)
{
rc = execute_script_action( package, script, i );
if (rc != ERROR_SUCCESS) break;
rc = ACTION_PerformAction(package, package->script_actions[script][i], script);
if (rc != ERROR_SUCCESS)
{
ERR("Execution of script %i halted; action %s returned %u\n",
script, debugstr_w(package->script_actions[script][i]), rc);
break;
}
}
}
msi_free_action_script(package, script);
@ -1743,7 +1721,7 @@ static BOOL process_overrides( MSIPACKAGE *package, int level )
ret |= process_state_property( package, level, szReinstall, INSTALLSTATE_UNKNOWN );
ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED );
if (ret && !package->full_reinstall)
if (ret)
msi_set_property( package->db, szPreselected, szOne, -1 );
return ret;
@ -1798,7 +1776,34 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
level = msi_get_property_int(package->db, szInstallLevel, 1);
if (!msi_get_property_int( package->db, szPreselected, 0 ))
if (msi_get_property_int( package->db, szPreselected, 0 ))
{
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if (!is_feature_selected( feature, level )) continue;
if (feature->ActionRequest == INSTALLSTATE_UNKNOWN)
{
if (feature->Installed == INSTALLSTATE_ABSENT)
{
feature->Action = INSTALLSTATE_UNKNOWN;
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
}
else
{
feature->Action = feature->Installed;
feature->ActionRequest = feature->Installed;
}
}
}
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if (feature->Feature_Parent) continue;
disable_children( feature, level );
follow_parent( feature );
}
}
else if (!msi_get_property_int( package->db, szInstalled, 0 ))
{
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
@ -1831,33 +1836,6 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
follow_parent( feature );
}
}
else /* preselected */
{
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if (!is_feature_selected( feature, level )) continue;
if (feature->ActionRequest == INSTALLSTATE_UNKNOWN)
{
if (feature->Installed == INSTALLSTATE_ABSENT)
{
feature->Action = INSTALLSTATE_UNKNOWN;
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
}
else
{
feature->Action = feature->Installed;
feature->ActionRequest = feature->Installed;
}
}
}
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if (feature->Feature_Parent) continue;
disable_children( feature, level );
follow_parent( feature );
}
}
/* now we want to set component state based based on feature state */
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
@ -1906,6 +1884,14 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
else
component->hasLocalFeature = 1;
break;
case INSTALLSTATE_UNKNOWN:
if (feature->Installed == INSTALLSTATE_ADVERTISED)
component->hasAdvertisedFeature = 1;
if (feature->Installed == INSTALLSTATE_SOURCE)
component->hasSourceFeature = 1;
if (feature->Installed == INSTALLSTATE_LOCAL)
component->hasLocalFeature = 1;
break;
default:
break;
}
@ -4318,7 +4304,7 @@ static BOOL msi_check_publish(MSIPACKAGE *package)
LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry)
{
feature->Action = msi_get_feature_action( package, feature );
if (feature->Action == INSTALLSTATE_LOCAL)
if (feature->Action == INSTALLSTATE_LOCAL || feature->Action == INSTALLSTATE_SOURCE)
return TRUE;
}
@ -5361,25 +5347,16 @@ static UINT ACTION_UnpublishProduct(MSIPACKAGE *package)
static BOOL is_full_uninstall( MSIPACKAGE *package )
{
WCHAR **features, *remove = msi_dup_property( package->db, szRemove );
MSIFEATURE *feature;
BOOL ret = TRUE;
UINT i;
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
if (feature->Action == INSTALLSTATE_LOCAL) ret = FALSE;
if (feature->Action != INSTALLSTATE_ABSENT &&
(feature->Installed != INSTALLSTATE_ABSENT || feature->Action != INSTALLSTATE_UNKNOWN))
return FALSE;
}
features = msi_split_string( remove, ',' );
for (i = 0; features && features[i]; i++)
{
if (!strcmpW( features[i], szAll )) ret = TRUE;
}
msi_free(features);
msi_free(remove);
return ret;
return TRUE;
}
static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
@ -5559,16 +5536,154 @@ end:
return rc;
}
static UINT iterate_properties(MSIRECORD *record, void *param)
{
static const WCHAR prop_template[] =
{'P','r','o','p','e','r','t','y','(','S',')',':',' ','[','1',']',' ','=',' ','[','2',']',0};
MSIRECORD *uirow;
uirow = MSI_CloneRecord(record);
if (!uirow) return ERROR_OUTOFMEMORY;
MSI_RecordSetStringW(uirow, 0, prop_template);
MSI_ProcessMessage(param, INSTALLMESSAGE_INFO|MB_ICONHAND, uirow);
msiobj_release(&uirow->hdr);
return ERROR_SUCCESS;
}
static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
{
static const WCHAR prop_query[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','_','P','r','o','p','e','r','t','y','`',0};
WCHAR *productname;
WCHAR *action;
WCHAR *info_template;
MSIQUERY *view;
MSIRECORD *uirow, *uirow_info;
UINT rc;
package->script->InWhatSequence |= SEQUENCE_EXEC;
rc = ACTION_ProcessExecSequence(package,FALSE);
/* Send COMMONDATA and INFO messages. */
/* FIXME: when should these messages be sent? [see also MsiOpenPackage()] */
uirow = MSI_CreateRecord(3);
if (!uirow) return ERROR_OUTOFMEMORY;
MSI_RecordSetStringW(uirow, 0, NULL);
MSI_RecordSetInteger(uirow, 1, 0);
MSI_RecordSetInteger(uirow, 2, package->num_langids ? package->langids[0] : 0);
MSI_RecordSetInteger(uirow, 3, msi_get_string_table_codepage(package->db->strings));
MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, uirow);
/* FIXME: send INSTALLMESSAGE_PROGRESS */
MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, uirow);
if (!(needs_ui_sequence(package) && ui_sequence_exists(package)))
{
uirow_info = MSI_CreateRecord(0);
if (!uirow_info)
{
msiobj_release(&uirow->hdr);
return ERROR_OUTOFMEMORY;
}
info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
MSI_RecordSetStringW(uirow_info, 0, info_template);
msi_free(info_template);
MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, uirow_info);
msiobj_release(&uirow_info->hdr);
}
MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, uirow);
productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
MSI_RecordSetInteger(uirow, 1, 1);
MSI_RecordSetStringW(uirow, 2, productname);
MSI_RecordSetStringW(uirow, 3, NULL);
MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, uirow);
msiobj_release(&uirow->hdr);
package->LastActionResult = MSI_NULL_INTEGER;
action = msi_dup_property(package->db, szEXECUTEACTION);
if (!action) action = msi_strdupW(szINSTALL, strlenW(szINSTALL));
/* Perform the action. Top-level actions trigger a sequence. */
if (!strcmpW(action, szINSTALL))
{
/* Send ACTIONSTART/INFO and INSTALLSTART. */
ui_actionstart(package, szINSTALL, NULL, NULL);
ui_actioninfo(package, szINSTALL, TRUE, 0);
uirow = MSI_CreateRecord(2);
if (!uirow)
{
rc = ERROR_OUTOFMEMORY;
goto end;
}
MSI_RecordSetStringW(uirow, 0, NULL);
MSI_RecordSetStringW(uirow, 1, productname);
MSI_RecordSetStringW(uirow, 2, package->ProductCode);
MSI_ProcessMessage(package, INSTALLMESSAGE_INSTALLSTART, uirow);
msiobj_release(&uirow->hdr);
/* Perform the installation. Always use the ExecuteSequence. */
package->InWhatSequence |= SEQUENCE_EXEC;
rc = ACTION_ProcessExecSequence(package);
/* Send return value and INSTALLEND. */
ui_actioninfo(package, szINSTALL, FALSE, !rc);
uirow = MSI_CreateRecord(3);
if (!uirow)
{
rc = ERROR_OUTOFMEMORY;
goto end;
}
MSI_RecordSetStringW(uirow, 0, NULL);
MSI_RecordSetStringW(uirow, 1, productname);
MSI_RecordSetStringW(uirow, 2, package->ProductCode);
MSI_RecordSetInteger(uirow, 3, !rc);
MSI_ProcessMessage(package, INSTALLMESSAGE_INSTALLEND, uirow);
msiobj_release(&uirow->hdr);
}
else
rc = ACTION_PerformAction(package, action, SCRIPT_NONE);
/* Send all set properties. */
if (!MSI_OpenQuery(package->db, &view, prop_query))
{
MSI_IterateRecords(view, NULL, iterate_properties, package);
msiobj_release(&view->hdr);
}
/* And finally, toggle the cancel off and on. */
uirow = MSI_CreateRecord(2);
if (!uirow)
{
rc = ERROR_OUTOFMEMORY;
goto end;
}
MSI_RecordSetStringW(uirow, 0, NULL);
MSI_RecordSetInteger(uirow, 1, 2);
MSI_RecordSetInteger(uirow, 2, 0);
MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, uirow);
MSI_RecordSetInteger(uirow, 2, 1);
MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, uirow);
msiobj_release(&uirow->hdr);
end:
msi_free(productname);
msi_free(action);
return rc;
}
static UINT ACTION_INSTALL(MSIPACKAGE *package)
{
msi_set_property(package->db, szEXECUTEACTION, szINSTALL, -1);
if (needs_ui_sequence(package) && ui_sequence_exists(package))
{
package->InWhatSequence |= SEQUENCE_UI;
return ACTION_ProcessUISequence(package);
}
else
return ACTION_ExecuteAction(package);
}
WCHAR *msi_create_component_advertise_string( MSIPACKAGE *package, MSICOMPONENT *component, const WCHAR *feature )
{
static const WCHAR fmt[] = {'%','s','%','s','%','c','%','s',0};
@ -7720,6 +7835,7 @@ StandardActions[] =
{ szWriteEnvironmentStrings, IDS_DESC_WRITEENVIRONMENTSTRINGS, IDS_TEMP_WRITEENVIRONMENTSTRINGS, ACTION_WriteEnvironmentStrings, szRemoveEnvironmentStrings },
{ szWriteIniValues, IDS_DESC_WRITEINIVALUES, IDS_TEMP_WRITEINIVALUES, ACTION_WriteIniValues, szRemoveIniValues },
{ szWriteRegistryValues, IDS_DESC_WRITEREGISTRYVALUES, IDS_TEMP_WRITEREGISTRYVALUES, ACTION_WriteRegistryValues, szRemoveRegistryValues },
{ szINSTALL, 0, 0, ACTION_INSTALL, NULL },
{ 0 }
};
@ -7771,23 +7887,6 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script)
TRACE("Performing action (%s)\n", debugstr_w(action));
rc = ACTION_HandleStandardAction(package, action);
if (rc == ERROR_FUNCTION_NOT_CALLED)
rc = ACTION_HandleCustomAction(package, action, script);
if (rc == ERROR_FUNCTION_NOT_CALLED)
WARN("unhandled msi action %s\n", debugstr_w(action));
return rc;
}
UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT script)
{
UINT rc;
TRACE("Performing action (%s)\n", debugstr_w(action));
package->action_progress_increment = 0;
rc = ACTION_HandleStandardAction(package, action);
@ -7845,10 +7944,7 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq)
return ERROR_FUNCTION_FAILED;
}
if (needs_ui_sequence(package))
rc = ACTION_PerformUIAction(package, action, SCRIPT_NONE);
else
rc = ACTION_PerformAction(package, action, SCRIPT_NONE);
rc = ACTION_PerformAction(package, action, SCRIPT_NONE);
msiobj_release(&row->hdr);
}
@ -7856,42 +7952,6 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq)
return rc;
}
DWORD WINAPI dummy_thread_proc(void *arg)
{
struct dummy_thread *info = arg;
HRESULT hr;
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr)) ERR("CoInitializeEx failed %08x\n", hr);
SetEvent(info->started);
WaitForSingleObject(info->stopped, INFINITE);
CoUninitialize();
return 0;
}
static void start_dummy_thread(struct dummy_thread *info)
{
if (!(info->started = CreateEventA(NULL, TRUE, FALSE, NULL))) return;
if (!(info->stopped = CreateEventA(NULL, TRUE, FALSE, NULL))) return;
if (!(info->thread = CreateThread(NULL, 0, dummy_thread_proc, info, 0, NULL))) return;
WaitForSingleObject(info->started, INFINITE);
}
static void stop_dummy_thread(struct dummy_thread *info)
{
if (info->thread)
{
SetEvent(info->stopped);
WaitForSingleObject(info->thread, INFINITE);
CloseHandle(info->thread);
}
if (info->started) CloseHandle(info->started);
if (info->stopped) CloseHandle(info->stopped);
}
/****************************************************
* TOP level entry points
*****************************************************/
@ -7901,15 +7961,9 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
{
static const WCHAR szDisableRollback[] = {'D','I','S','A','B','L','E','R','O','L','L','B','A','C','K',0};
static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
WCHAR *reinstall, *remove, *patch, *productcode;
struct dummy_thread thread_info = {NULL, NULL, NULL};
BOOL ui_exists;
WCHAR *reinstall = NULL, *productcode, *action;
UINT rc;
msi_set_property( package->db, szAction, szInstall, -1 );
package->script->InWhatSequence = SEQUENCE_INSTALL;
DWORD len = 0;
if (szPackagePath)
{
@ -7954,23 +8008,16 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
msi_apply_transforms( package );
msi_apply_patches( package );
patch = msi_dup_property( package->db, szPatch );
remove = msi_dup_property( package->db, szRemove );
reinstall = msi_dup_property( package->db, szReinstall );
if (msi_get_property_int( package->db, szInstalled, 0 ) && !remove && !reinstall && !patch)
{
TRACE("setting REINSTALL property to ALL\n");
msi_set_property( package->db, szReinstall, szAll, -1 );
package->full_reinstall = 1;
}
if (msi_get_property( package->db, szAction, NULL, &len ))
msi_set_property( package->db, szAction, szINSTALL, -1 );
action = msi_dup_property( package->db, szAction );
CharUpperW(action);
msi_set_original_database_property( package->db, szPackagePath );
msi_parse_command_line( package, szCommandLine, FALSE );
msi_adjust_privilege_properties( package );
msi_set_context( package );
start_dummy_thread(&thread_info);
productcode = msi_dup_property( package->db, szProductCode );
if (strcmpiW( productcode, package->ProductCode ))
{
@ -7986,19 +8033,7 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
msi_set_property( package->db, szRollbackDisabled, szOne, -1 );
}
if (needs_ui_sequence( package))
{
package->script->InWhatSequence |= SEQUENCE_UI;
rc = ACTION_ProcessUISequence(package);
ui_exists = ui_sequence_exists(package);
if (rc == ERROR_SUCCESS || !ui_exists)
{
package->script->InWhatSequence |= SEQUENCE_EXEC;
rc = ACTION_ProcessExecSequence(package, ui_exists);
}
}
else
rc = ACTION_ProcessExecSequence(package, FALSE);
rc = ACTION_PerformAction(package, action, SCRIPT_NONE);
/* process the ending type action */
if (rc == ERROR_SUCCESS)
@ -8019,16 +8054,13 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
/* finish up running custom actions */
ACTION_FinishCustomActions(package);
stop_dummy_thread(&thread_info);
if (package->need_rollback && !reinstall)
if (package->need_rollback && !(reinstall = msi_dup_property( package->db, szReinstall )))
{
WARN("installation failed, running rollback script\n");
execute_script( package, SCRIPT_ROLLBACK );
}
msi_free( reinstall );
msi_free( remove );
msi_free( patch );
msi_free( action );
if (rc == ERROR_SUCCESS && package->need_reboot_at_end)
return ERROR_SUCCESS_REBOOT_REQUIRED;

View file

@ -493,7 +493,7 @@ static LPWSTR get_ini_field(LPWSTR buf, int field)
while ((end = strchrW(beg, ',')) && i < field)
{
beg = end + 1;
while (*beg && *beg == ' ')
while (*beg == ' ')
beg++;
i++;

File diff suppressed because it is too large Load diff

View file

@ -20,27 +20,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "oleauto.h"
#include "msipriv.h"
#include "msiserver.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -58,6 +38,18 @@ struct cond_str {
INT len;
};
struct value {
enum value_type {
VALUE_INTEGER,
VALUE_LITERAL,
VALUE_SYMBOL
} type;
union {
INT integer;
WCHAR *string;
} u;
};
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);
@ -70,16 +62,6 @@ 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 );
static INT compare_and_free_strings( LPWSTR a, INT op, LPWSTR b, BOOL convert )
{
INT r;
r = compare_string( a, op, b, convert );
cond_free( a );
cond_free( b );
return r;
}
static BOOL num_from_prop( LPCWSTR p, INT *val )
{
INT ret = 0, sign = 1;
@ -104,6 +86,12 @@ static BOOL num_from_prop( LPCWSTR p, INT *val )
return TRUE;
}
static void value_free( struct value val )
{
if (val.type != VALUE_INTEGER)
cond_free( val.u.string );
}
%}
%lex-param { COND_input *info }
@ -113,8 +101,10 @@ static BOOL num_from_prop( LPCWSTR p, INT *val )
%union
{
struct cond_str str;
LPWSTR string;
INT value;
struct value value;
LPWSTR identifier;
INT operator;
BOOL bool;
}
%token COND_SPACE COND_EOF
@ -128,9 +118,10 @@ static BOOL num_from_prop( LPCWSTR p, INT *val )
%nonassoc COND_ERROR COND_EOF
%type <value> expression boolean_term boolean_factor
%type <value> value_i integer operator
%type <string> identifier symbol_s value_s literal
%type <bool> expression boolean_term boolean_factor
%type <value> value
%type <identifier> identifier
%type <operator> operator
%%
@ -184,64 +175,50 @@ boolean_term:
boolean_factor:
COND_NOT boolean_factor
{
$$ = $2 ? 0 : 1;
$$ = !$2;
}
| value_i
| value
{
$$ = $1 ? 1 : 0;
if ($1.type == VALUE_INTEGER)
$$ = $1.u.integer ? 1 : 0;
else
$$ = $1.u.string && $1.u.string[0];
value_free( $1 );
}
| value_s
| value operator value
{
$$ = ($1 && $1[0]) ? 1 : 0;
cond_free( $1 );
}
| value_i operator value_i
{
$$ = compare_int( $1, $2, $3 );
}
| symbol_s operator value_i
{
int num;
if (num_from_prop( $1, &num ))
$$ = compare_int( num, $2, $3 );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
cond_free( $1 );
}
| value_i operator symbol_s
{
int num;
if (num_from_prop( $3, &num ))
$$ = compare_int( $1, $2, num );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
cond_free( $3 );
}
| symbol_s operator symbol_s
{
$$ = compare_and_free_strings( $1, $2, $3, TRUE );
}
| symbol_s operator literal
{
$$ = compare_and_free_strings( $1, $2, $3, TRUE );
}
| literal operator symbol_s
{
$$ = compare_and_free_strings( $1, $2, $3, TRUE );
}
| literal operator literal
{
$$ = compare_and_free_strings( $1, $2, $3, FALSE );
}
| literal operator value_i
{
$$ = 0;
cond_free( $1 );
}
| value_i operator literal
{
$$ = 0;
cond_free( $3 );
if ($1.type == VALUE_INTEGER && $3.type == VALUE_INTEGER)
{
$$ = compare_int($1.u.integer, $2, $3.u.integer);
}
else if ($1.type != VALUE_INTEGER && $3.type != VALUE_INTEGER)
{
$$ = compare_string($1.u.string, $2, $3.u.string,
$1.type == VALUE_SYMBOL || $3.type == VALUE_SYMBOL);
}
else if ($1.type == VALUE_LITERAL || $3.type == VALUE_LITERAL)
{
$$ = FALSE;
}
else if ($1.type == VALUE_SYMBOL) /* symbol operator integer */
{
int num;
if (num_from_prop( $1.u.string, &num ))
$$ = compare_int( num, $2, $3.u.integer );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
}
else /* integer operator symbol */
{
int num;
if (num_from_prop( $3.u.string, &num ))
$$ = compare_int( $1.u.integer, $2, num );
else
$$ = ($2 == COND_NE || $2 == COND_INE );
}
value_free( $1 );
value_free( $3 );
}
| COND_LPAR expression COND_RPAR
{
@ -271,39 +248,69 @@ operator:
| COND_IRHS { $$ = COND_IRHS; }
;
value_s:
symbol_s
{
$$ = $1;
}
| literal
{
$$ = $1;
}
;
literal:
COND_LITER
value:
identifier
{
COND_input* cond = (COND_input*) info;
$$ = COND_GetLiteral( cond, &$1 );
if( !$$ )
UINT len;
$$.type = VALUE_SYMBOL;
$$.u.string = msi_dup_property( cond->package->db, $1 );
if ($$.u.string)
{
len = (lstrlenW($$.u.string) + 1) * sizeof (WCHAR);
$$.u.string = cond_track_mem( cond, $$.u.string, len );
}
cond_free( $1 );
}
| COND_PERCENT identifier
{
COND_input* cond = (COND_input*) info;
UINT len = GetEnvironmentVariableW( $2, NULL, 0 );
$$.type = VALUE_SYMBOL;
$$.u.string = NULL;
if (len++)
{
$$.u.string = cond_alloc( cond, len*sizeof (WCHAR) );
if( !$$.u.string )
YYABORT;
GetEnvironmentVariableW( $2, $$.u.string, len );
}
cond_free( $2 );
}
| COND_LITER
{
COND_input* cond = (COND_input*) info;
$$.type = VALUE_LITERAL;
$$.u.string = COND_GetLiteral( cond, &$1 );
if( !$$.u.string )
YYABORT;
}
;
value_i:
integer
| COND_NUMBER
{
$$ = $1;
COND_input* cond = (COND_input*) info;
LPWSTR szNum = COND_GetString( cond, &$1 );
if( !szNum )
YYABORT;
$$.type = VALUE_INTEGER;
$$.u.integer = atoiW( szNum );
cond_free( szNum );
}
| COND_DOLLARS identifier
{
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = action;
if(MSI_GetComponentStateW(cond->package, $2, &install, &action ) != ERROR_SUCCESS)
{
$$.type = VALUE_LITERAL;
$$.u.string = NULL;
}
else
{
$$.type = VALUE_INTEGER;
$$.u.integer = action;
}
cond_free( $2 );
}
| COND_QUESTION identifier
@ -311,21 +318,33 @@ value_i:
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetComponentStateW(cond->package, $2, &install, &action );
$$ = install;
if(MSI_GetComponentStateW(cond->package, $2, &install, &action ) != ERROR_SUCCESS)
{
$$.type = VALUE_LITERAL;
$$.u.string = NULL;
}
else
{
$$.type = VALUE_INTEGER;
$$.u.integer = install;
}
cond_free( $2 );
}
| COND_AMPER identifier
{
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
INSTALLSTATE install, action;
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
if (action == INSTALLSTATE_UNKNOWN)
$$ = MSICONDITION_FALSE;
if (MSI_GetFeatureStateW(cond->package, $2, &install, &action ) != ERROR_SUCCESS)
{
$$.type = VALUE_LITERAL;
$$.u.string = NULL;
}
else
$$ = action;
{
$$.type = VALUE_INTEGER;
$$.u.integer = action;
}
cond_free( $2 );
}
| COND_EXCLAM identifier
@ -333,37 +352,15 @@ value_i:
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MSI_GetFeatureStateW(cond->package, $2, &install, &action );
$$ = install;
cond_free( $2 );
}
;
symbol_s:
identifier
{
COND_input* cond = (COND_input*) info;
UINT len;
$$ = msi_dup_property( cond->package->db, $1 );
if ($$)
if(MSI_GetFeatureStateW(cond->package, $2, &install, &action ) != ERROR_SUCCESS)
{
len = (lstrlenW($$) + 1) * sizeof (WCHAR);
$$ = cond_track_mem( cond, $$, len );
$$.type = VALUE_LITERAL;
$$.u.string = NULL;
}
cond_free( $1 );
}
| COND_PERCENT identifier
{
COND_input* cond = (COND_input*) info;
UINT len = GetEnvironmentVariableW( $2, NULL, 0 );
$$ = NULL;
if (len++)
else
{
$$ = cond_alloc( cond, len*sizeof (WCHAR) );
if( !$$ )
YYABORT;
GetEnvironmentVariableW( $2, $$, len );
$$.type = VALUE_INTEGER;
$$.u.integer = install;
}
cond_free( $2 );
}
@ -379,18 +376,6 @@ identifier:
}
;
integer:
COND_NUMBER
{
COND_input* cond = (COND_input*) info;
LPWSTR szNum = COND_GetString( cond, &$1 );
if( !szNum )
YYABORT;
$$ = atoiW( szNum );
cond_free( szNum );
}
;
%%

View file

@ -64,14 +64,14 @@ UINT msi_schedule_action( MSIPACKAGE *package, UINT script, const WCHAR *action
}
TRACE("Scheduling action %s in script %u\n", debugstr_w(action), script);
count = package->script->ActionCount[script];
package->script->ActionCount[script]++;
if (count != 0) newbuf = msi_realloc( package->script->Actions[script],
package->script->ActionCount[script] * sizeof(WCHAR *) );
count = package->script_actions_count[script];
package->script_actions_count[script]++;
if (count != 0) newbuf = msi_realloc( package->script_actions[script],
package->script_actions_count[script] * sizeof(WCHAR *) );
else newbuf = msi_alloc( sizeof(WCHAR *) );
newbuf[count] = strdupW( action );
package->script->Actions[script] = newbuf;
package->script_actions[script] = newbuf;
return ERROR_SUCCESS;
}
@ -80,18 +80,16 @@ UINT msi_register_unique_action( MSIPACKAGE *package, const WCHAR *action )
UINT count;
WCHAR **newbuf = NULL;
if (!package->script) return FALSE;
TRACE("Registering %s as unique action\n", debugstr_w(action));
count = package->script->UniqueActionsCount;
package->script->UniqueActionsCount++;
if (count != 0) newbuf = msi_realloc( package->script->UniqueActions,
package->script->UniqueActionsCount * sizeof(WCHAR *) );
count = package->unique_actions_count;
package->unique_actions_count++;
if (count != 0) newbuf = msi_realloc( package->unique_actions,
package->unique_actions_count * sizeof(WCHAR *) );
else newbuf = msi_alloc( sizeof(WCHAR *) );
newbuf[count] = strdupW( action );
package->script->UniqueActions = newbuf;
package->unique_actions = newbuf;
return ERROR_SUCCESS;
}
@ -99,25 +97,20 @@ BOOL msi_action_is_unique( const MSIPACKAGE *package, const WCHAR *action )
{
UINT i;
if (!package->script) return FALSE;
for (i = 0; i < package->script->UniqueActionsCount; i++)
for (i = 0; i < package->unique_actions_count; i++)
{
if (!strcmpW( package->script->UniqueActions[i], action )) return TRUE;
if (!strcmpW( package->unique_actions[i], action )) return TRUE;
}
return FALSE;
}
static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
{
if (!package->script)
return TRUE;
if ((options & msidbCustomActionTypeClientRepeat) ==
msidbCustomActionTypeClientRepeat)
{
if (!(package->script->InWhatSequence & SEQUENCE_UI &&
package->script->InWhatSequence & SEQUENCE_EXEC))
if (!(package->InWhatSequence & SEQUENCE_UI &&
package->InWhatSequence & SEQUENCE_EXEC))
{
TRACE("Skipping action due to dbCustomActionTypeClientRepeat option.\n");
return FALSE;
@ -125,8 +118,8 @@ static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR acti
}
else if (options & msidbCustomActionTypeFirstSequence)
{
if (package->script->InWhatSequence & SEQUENCE_UI &&
package->script->InWhatSequence & SEQUENCE_EXEC )
if (package->InWhatSequence & SEQUENCE_UI &&
package->InWhatSequence & SEQUENCE_EXEC )
{
TRACE("Skipping action due to msidbCustomActionTypeFirstSequence option.\n");
return FALSE;
@ -258,7 +251,7 @@ static MSIBINARY *create_temp_binary( MSIPACKAGE *package, LPCWSTR source, BOOL
/* keep a reference to prevent the dll from being unloaded */
if (dll && !(binary->module = LoadLibraryW( tmpfile )))
{
WARN( "failed to load dll %s (%u)\n", debugstr_w( tmpfile ), GetLastError() );
ERR( "failed to load dll %s (%u)\n", debugstr_w( tmpfile ), GetLastError() );
}
binary->source = strdupW( source );
binary->tmpfile = tmpfile;
@ -562,7 +555,7 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
hModule = LoadLibraryW( dll );
if (!hModule)
{
WARN( "failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
ERR( "failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
return ERROR_SUCCESS;
}
@ -695,7 +688,7 @@ static HANDLE execute_command( const WCHAR *app, WCHAR *arg, const WCHAR *dir )
}
if (!len_exe)
{
WARN("can't find executable %u\n", GetLastError());
ERR("can't find executable %u\n", GetLastError());
msi_free( exe );
return INVALID_HANDLE_VALUE;
}
@ -733,7 +726,7 @@ static HANDLE execute_command( const WCHAR *app, WCHAR *arg, const WCHAR *dir )
msi_free( exe );
if (!ret)
{
WARN("unable to execute command %u\n", GetLastError());
ERR("unable to execute command %u\n", GetLastError());
return INVALID_HANDLE_VALUE;
}
CloseHandle( info.hThread );

View file

@ -36,13 +36,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
struct row_export_info
{
HANDLE handle;
LPCWSTR folder;
LPCWSTR table;
};
static void free_transforms( MSIDATABASE *db )
{
while( !list_empty( &db->transforms ) )
@ -911,131 +904,50 @@ end:
return r;
}
static UINT msi_export_field( HANDLE handle, MSIRECORD *row, UINT field )
static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
{
UINT i, count, len, r = ERROR_SUCCESS;
const char *sep;
char *buffer;
BOOL bret;
DWORD sz;
UINT r;
sz = 0x100;
buffer = msi_alloc( sz );
if (!buffer)
len = 0x100;
buffer = msi_alloc( len );
if ( !buffer )
return ERROR_OUTOFMEMORY;
r = MSI_RecordGetStringA( row, field, buffer, &sz );
if (r == ERROR_MORE_DATA)
{
char *p;
sz++; /* leave room for NULL terminator */
p = msi_realloc( buffer, sz );
if (!p)
{
msi_free( buffer );
return ERROR_OUTOFMEMORY;
}
buffer = p;
r = MSI_RecordGetStringA( row, field, buffer, &sz );
if (r != ERROR_SUCCESS)
{
msi_free( buffer );
return r;
}
}
else if (r != ERROR_SUCCESS)
return r;
bret = WriteFile( handle, buffer, sz, &sz, NULL );
msi_free( buffer );
if (!bret)
return ERROR_FUNCTION_FAILED;
return r;
}
static UINT msi_export_stream( LPCWSTR folder, LPCWSTR table, MSIRECORD *row, UINT field,
UINT start )
{
static const WCHAR fmt_file[] = { '%','s','/','%','s','/','%','s',0 };
static const WCHAR fmt_folder[] = { '%','s','/','%','s',0 };
WCHAR stream_name[256], stream_filename[MAX_PATH];
DWORD sz, read_size, write_size;
char buffer[1024];
HANDLE file;
UINT r;
/* get the name of the file */
sz = sizeof(stream_name)/sizeof(WCHAR);
r = MSI_RecordGetStringW( row, start, stream_name, &sz );
if (r != ERROR_SUCCESS)
return r;
/* if the destination folder does not exist then create it (folder name = table name) */
snprintfW( stream_filename, sizeof(stream_filename)/sizeof(WCHAR), fmt_folder, folder, table );
if (GetFileAttributesW( stream_filename ) == INVALID_FILE_ATTRIBUTES)
{
if (!CreateDirectoryW( stream_filename, NULL ))
return ERROR_PATH_NOT_FOUND;
}
/* actually create the file */
snprintfW( stream_filename, sizeof(stream_filename)/sizeof(WCHAR), fmt_file, folder, table, stream_name );
file = CreateFileW( stream_filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (file == INVALID_HANDLE_VALUE)
return ERROR_FILE_NOT_FOUND;
/* copy the stream to the file */
read_size = sizeof(buffer);
while (read_size == sizeof(buffer))
{
r = MSI_RecordReadStream( row, field, buffer, &read_size );
if (r != ERROR_SUCCESS)
{
CloseHandle( file );
return r;
}
if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
{
CloseHandle( file );
return ERROR_WRITE_FAULT;
}
}
CloseHandle( file );
return r;
}
static UINT msi_export_record( struct row_export_info *row_export_info, MSIRECORD *row, UINT start )
{
HANDLE handle = row_export_info->handle;
UINT i, count, r = ERROR_SUCCESS;
const char *sep;
DWORD sz;
count = MSI_RecordGetFieldCount( row );
for (i = start; i <= count; i++)
for ( i=start; i<=count; i++ )
{
r = msi_export_field( handle, row, i );
if (r == ERROR_INVALID_PARAMETER)
sz = len;
r = MSI_RecordGetStringA( row, i, buffer, &sz );
if (r == ERROR_MORE_DATA)
{
r = msi_export_stream( row_export_info->folder, row_export_info->table, row, i, start );
if (r != ERROR_SUCCESS)
return r;
/* exporting a binary stream, repeat the "Name" field */
r = msi_export_field( handle, row, start );
if (r != ERROR_SUCCESS)
return r;
char *p = msi_realloc( buffer, sz + 1 );
if (!p)
break;
len = sz + 1;
buffer = p;
}
sz = len;
r = MSI_RecordGetStringA( row, i, buffer, &sz );
if (r != ERROR_SUCCESS)
break;
if (!WriteFile( handle, buffer, sz, &sz, NULL ))
{
r = ERROR_FUNCTION_FAILED;
break;
}
else if (r != ERROR_SUCCESS)
return r;
sep = (i < count) ? "\t" : "\r\n";
if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
return ERROR_FUNCTION_FAILED;
{
r = ERROR_FUNCTION_FAILED;
break;
}
}
msi_free( buffer );
return r;
}
@ -1059,25 +971,9 @@ static UINT msi_export_forcecodepage( HANDLE handle, UINT codepage )
return ERROR_SUCCESS;
}
static UINT msi_export_summaryinformation( MSIDATABASE *db, HANDLE handle )
{
static const char header[] = "PropertyId\tValue\r\n"
"i2\tl255\r\n"
"_SummaryInformation\tPropertyId\r\n";
DWORD sz;
sz = lstrlenA(header);
if (!WriteFile(handle, header, sz, &sz, NULL))
return ERROR_WRITE_FAULT;
return msi_export_suminfo( db, handle );
}
static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
LPCWSTR folder, LPCWSTR file )
{
static const WCHAR summaryinformation[] = {
'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0 };
static const WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
static const WCHAR forcecodepage[] = {
@ -1116,22 +1012,14 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
goto done;
}
if (!strcmpW( table, summaryinformation ))
{
r = msi_export_summaryinformation( db, handle );
goto done;
}
r = MSI_OpenQuery( db, &view, query, table );
if (r == ERROR_SUCCESS)
{
struct row_export_info row_export_info = { handle, folder, table };
/* write out row 1, the column names */
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
if (r == ERROR_SUCCESS)
{
msi_export_record( &row_export_info, rec, 1 );
msi_export_record( handle, rec, 1 );
msiobj_release( &rec->hdr );
}
@ -1139,7 +1027,7 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
if (r == ERROR_SUCCESS)
{
msi_export_record( &row_export_info, rec, 1 );
msi_export_record( handle, rec, 1 );
msiobj_release( &rec->hdr );
}
@ -1148,12 +1036,12 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
if (r == ERROR_SUCCESS)
{
MSI_RecordSetStringW( rec, 0, table );
msi_export_record( &row_export_info, rec, 0 );
msi_export_record( handle, rec, 0 );
msiobj_release( &rec->hdr );
}
/* write out row 4 onwards, the data */
r = MSI_IterateRecords( view, 0, msi_export_row, &row_export_info );
r = MSI_IterateRecords( view, 0, msi_export_row, handle );
msiobj_release( &view->hdr );
}
@ -1991,8 +1879,16 @@ MSIDBSTATE WINAPI MsiGetDatabaseState( MSIHANDLE handle )
db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
if( !db )
{
IWineMsiRemoteDatabase *remote_database;
remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle );
if ( !remote_database )
return MSIDBSTATE_ERROR;
IWineMsiRemoteDatabase_Release( remote_database );
WARN("MsiGetDatabaseState not allowed during a custom action!\n");
return MSIDBSTATE_ERROR;
return MSIDBSTATE_READ;
}
if (db->mode != MSIDBOPEN_READONLY )

View file

@ -3179,13 +3179,13 @@ static LONGLONG msi_vcl_get_cost( msi_dialog *dialog )
MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &each_cost)))
{
/* each_cost is in 512-byte units */
total_cost += ((LONGLONG)each_cost) * 512;
total_cost += each_cost * 512;
}
if (ERROR_SUCCESS == (MSI_GetFeatureCost(dialog->package, feature,
MSICOSTTREE_SELFONLY, INSTALLSTATE_ABSENT, &each_cost)))
{
/* each_cost is in 512-byte units */
total_cost -= ((LONGLONG)each_cost) * 512;
total_cost -= each_cost * 512;
}
}
return total_cost;
@ -4288,7 +4288,7 @@ static UINT event_end_dialog( msi_dialog *dialog, const WCHAR *argument )
static UINT pending_event_end_dialog( msi_dialog *dialog, const WCHAR *argument )
{
dialog->pending_event = event_end_dialog;
if (dialog->pending_argument) msi_free( dialog->pending_argument );
msi_free( dialog->pending_argument );
dialog->pending_argument = strdupW( argument );
return ERROR_SUCCESS;
}
@ -4306,7 +4306,7 @@ static UINT event_new_dialog( msi_dialog *dialog, const WCHAR *argument )
static UINT pending_event_new_dialog( msi_dialog *dialog, const WCHAR *argument )
{
dialog->pending_event = event_new_dialog;
if (dialog->pending_argument) msi_free( dialog->pending_argument );
msi_free( dialog->pending_argument );
dialog->pending_argument = strdupW( argument );
return ERROR_SUCCESS;
}
@ -4331,7 +4331,7 @@ static UINT event_spawn_dialog( msi_dialog *dialog, const WCHAR *argument )
static UINT pending_event_spawn_dialog( msi_dialog *dialog, const WCHAR *argument )
{
dialog->pending_event = event_spawn_dialog;
if (dialog->pending_argument) msi_free( dialog->pending_argument );
msi_free( dialog->pending_argument );
dialog->pending_argument = strdupW( argument );
return ERROR_SUCCESS;
}

View file

@ -90,7 +90,7 @@ UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
return ERROR_SUCCESS;
}
ret = ACTION_PerformUIAction( package, szAction, SCRIPT_NONE );
ret = ACTION_PerformAction( package, szAction, SCRIPT_NONE );
msiobj_release( &package->hdr );
return ret;

View file

@ -3723,7 +3723,7 @@ UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
if (!package)
return ERROR_CALL_NOT_IMPLEMENTED;
rc = ACTION_PerformUIAction(package, szFirstRun, SCRIPT_NONE);
rc = ACTION_PerformAction(package, szFirstRun, SCRIPT_NONE);
msiobj_release( &package->hdr );
MsiCloseHandle(handle);
@ -3749,7 +3749,7 @@ UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
if (!package)
return ERROR_CALL_NOT_IMPLEMENTED;
rc = ACTION_PerformUIAction(package, szFirstRun, SCRIPT_NONE);
rc = ACTION_PerformAction(package, szFirstRun, SCRIPT_NONE);
msiobj_release( &package->hdr );
MsiCloseHandle(handle);
@ -3830,7 +3830,7 @@ UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLST
MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
r = ACTION_PerformUIAction( package, szCostInitialize, SCRIPT_NONE );
r = ACTION_PerformAction( package, szCostInitialize, SCRIPT_NONE );
if (r != ERROR_SUCCESS)
goto end;

View file

@ -387,6 +387,15 @@ enum clr_version
CLR_VERSION_MAX
};
enum script
{
SCRIPT_NONE = -1,
SCRIPT_INSTALL = 0,
SCRIPT_COMMIT = 1,
SCRIPT_ROLLBACK = 2,
SCRIPT_MAX = 3
};
typedef struct tagMSIPACKAGE
{
MSIOBJECTHDR hdr;
@ -419,7 +428,12 @@ typedef struct tagMSIPACKAGE
struct list mimes;
struct list appids;
struct tagMSISCRIPT *script;
LPWSTR *script_actions[SCRIPT_MAX];
int script_actions_count[SCRIPT_MAX];
LPWSTR *unique_actions;
int unique_actions_count;
BOOL ExecuteSequenceRun;
UINT InWhatSequence;
struct list RunningActions;
@ -449,7 +463,6 @@ typedef struct tagMSIPACKAGE
unsigned char need_reboot_at_end : 1;
unsigned char need_reboot_now : 1;
unsigned char need_rollback : 1;
unsigned char full_reinstall : 1;
} MSIPACKAGE;
typedef struct tagMSIPREVIEW
@ -695,28 +708,8 @@ struct tagMSIMIME
MSICLASS *Class;
};
enum SCRIPTS
{
SCRIPT_NONE = -1,
SCRIPT_INSTALL = 0,
SCRIPT_COMMIT = 1,
SCRIPT_ROLLBACK = 2,
SCRIPT_MAX = 3
};
#define SEQUENCE_UI 0x1
#define SEQUENCE_EXEC 0x2
#define SEQUENCE_INSTALL 0x10
typedef struct tagMSISCRIPT
{
LPWSTR *Actions[SCRIPT_MAX];
UINT ActionCount[SCRIPT_MAX];
BOOL ExecuteSequenceRun;
UINT InWhatSequence;
LPWSTR *UniqueActions;
UINT UniqueActionsCount;
} MSISCRIPT;
#define MSIHANDLETYPE_ANY 0
#define MSIHANDLETYPE_DATABASE 1
@ -975,7 +968,6 @@ extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ) DECL
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ) DECLSPEC_HIDDEN;
extern UINT msi_export_suminfo( MSIDATABASE *db, HANDLE handle ) DECLSPEC_HIDDEN;
extern UINT msi_load_suminfo_properties( MSIPACKAGE *package ) DECLSPEC_HIDDEN;
/* undocumented functions */
@ -1000,7 +992,6 @@ extern HINSTANCE msi_hInstance DECLSPEC_HIDDEN;
/* action related functions */
extern UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script) DECLSPEC_HIDDEN;
extern UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT script) DECLSPEC_HIDDEN;
extern void ACTION_FinishCustomActions( const MSIPACKAGE* package) DECLSPEC_HIDDEN;
extern UINT ACTION_CustomAction(MSIPACKAGE *, const WCHAR *, UINT) DECLSPEC_HIDDEN;
@ -1221,6 +1212,7 @@ static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n',
static const WCHAR szInstallLocation[] = {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0};
static const WCHAR szProperty[] = {'P','r','o','p','e','r','t','y',0};
static const WCHAR szUninstallable[] = {'U','n','i','n','s','t','a','l','l','a','b','l','e',0};
static const WCHAR szEXECUTEACTION[] = {'E','X','E','C','U','T','E','A','C','T','I','O','N',0};
/* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);

View file

@ -103,17 +103,18 @@ static void free_assembly( MSIASSEMBLY *assembly )
void msi_free_action_script( MSIPACKAGE *package, UINT script )
{
UINT i;
for (i = 0; i < package->script->ActionCount[script]; i++)
msi_free( package->script->Actions[script][i] );
for (i = 0; i < package->script_actions_count[script]; i++)
msi_free( package->script_actions[script][i] );
msi_free( package->script->Actions[script] );
package->script->Actions[script] = NULL;
package->script->ActionCount[script] = 0;
msi_free( package->script_actions[script] );
package->script_actions[script] = NULL;
package->script_actions_count[script] = 0;
}
static void free_package_structures( MSIPACKAGE *package )
{
struct list *item, *cursor;
int i;
LIST_FOR_EACH_SAFE( item, cursor, &package->features )
{
@ -249,20 +250,12 @@ static void free_package_structures( MSIPACKAGE *package )
msi_free( info );
}
if (package->script)
{
INT i;
UINT j;
for (i = 0; i < SCRIPT_MAX; i++)
msi_free_action_script( package, i );
for (i = 0; i < SCRIPT_MAX; i++)
msi_free_action_script( package, i );
for (j = 0; j < package->script->UniqueActionsCount; j++)
msi_free( package->script->UniqueActions[j] );
msi_free( package->script->UniqueActions );
msi_free( package->script );
}
for (i = 0; i < package->unique_actions_count; i++)
msi_free( package->unique_actions[i] );
msi_free( package->unique_actions);
LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
{
@ -1061,7 +1054,6 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
msi_adjust_privilege_properties( package );
package->ProductCode = msi_dup_property( package->db, szProductCode );
package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
set_installer_properties( package );
@ -1737,6 +1729,8 @@ static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
case INSTALLMESSAGE_INFO:
case INSTALLMESSAGE_INITIALIZE:
case INSTALLMESSAGE_TERMINATE:
case INSTALLMESSAGE_INSTALLSTART:
case INSTALLMESSAGE_INSTALLEND:
return 0;
case INSTALLMESSAGE_SHOWDIALOG:
{
@ -1858,7 +1852,8 @@ LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
{
LPWSTR message = {0};
DWORD len, log_type = 0;
DWORD len;
DWORD log_type = 1 << (eMessageType >> 24);
UINT res;
INT rc = 0;
char *msg;
@ -1866,35 +1861,6 @@ INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
TRACE("%x\n", eMessageType);
if (TRACE_ON(msi)) dump_record(record);
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT)
log_type |= INSTALLLOGMODE_FATALEXIT;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
log_type |= INSTALLLOGMODE_ERROR;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
log_type |= INSTALLLOGMODE_WARNING;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
log_type |= INSTALLLOGMODE_USER;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
log_type |= INSTALLLOGMODE_INFO;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_RESOLVESOURCE)
log_type |= INSTALLLOGMODE_RESOLVESOURCE;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_OUTOFDISKSPACE)
log_type |= INSTALLLOGMODE_OUTOFDISKSPACE;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
log_type |= INSTALLLOGMODE_COMMONDATA;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
log_type |= INSTALLLOGMODE_ACTIONSTART;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
log_type |= INSTALLLOGMODE_ACTIONDATA;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
log_type |= INSTALLLOGMODE_PROGRESS;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE)
log_type |= INSTALLLOGMODE_INITIALIZE;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
log_type |= INSTALLLOGMODE_TERMINATE;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG)
log_type |= INSTALLLOGMODE_SHOWDIALOG;
if (!package || !record)
message = NULL;
else {
@ -2293,7 +2259,10 @@ static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
row = MSI_CreateRecord(1);
if (!row)
{
msi_free(buffer);
return NULL;
}
MSI_RecordSetStringW(row, 1, buffer);
msi_free(buffer);
return row;
@ -2308,7 +2277,10 @@ static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
row = MSI_CreateRecord(1);
if (!row)
{
msi_free(buffer);
return NULL;
}
MSI_RecordSetStringW(row, 1, buffer);
msi_free(buffer);
return row;

View file

@ -194,28 +194,7 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row)
{
MSIDATABASE *db = ((MSISTREAMSVIEW *)view)->db;
UINT i, num_rows = db->num_streams - 1;
const WCHAR *name;
WCHAR *encname;
HRESULT hr;
TRACE("(%p %d)!\n", view, row);
name = msi_string_lookup( db->strings, db->streams[row].str_index, NULL );
if (!(encname = encode_streamname( FALSE, name ))) return ERROR_OUTOFMEMORY;
hr = IStorage_DestroyElement( db->storage, encname );
msi_free( encname );
if (FAILED( hr ))
return ERROR_FUNCTION_FAILED;
hr = IStream_Release( db->streams[row].stream );
if (FAILED( hr ))
return ERROR_FUNCTION_FAILED;
for (i = row; i < num_rows; i++)
db->streams[i] = db->streams[i + 1];
db->num_streams = num_rows;
FIXME("(%p %d): stub!\n", view, row);
return ERROR_SUCCESS;
}
@ -314,15 +293,12 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
r = streams_modify_update(view, rec);
break;
case MSIMODIFY_DELETE:
r = STREAMS_delete_row(view, row - 1);
break;
case MSIMODIFY_VALIDATE_NEW:
case MSIMODIFY_INSERT_TEMPORARY:
case MSIMODIFY_REFRESH:
case MSIMODIFY_REPLACE:
case MSIMODIFY_MERGE:
case MSIMODIFY_DELETE:
case MSIMODIFY_VALIDATE:
case MSIMODIFY_VALIDATE_FIELD:
case MSIMODIFY_VALIDATE_DELETE:

View file

@ -1000,117 +1000,6 @@ end:
return r;
}
static UINT save_prop( MSISUMMARYINFO *si, HANDLE handle, UINT row )
{
static const char fmt_systemtime[] = "%d/%02d/%02d %02d:%02d:%02d";
char data[20]; /* largest string: YYYY/MM/DD hh:mm:ss */
static const char fmt_begin[] = "%u\t";
static const char data_end[] = "\r\n";
static const char fmt_int[] = "%u";
UINT r, data_type, len;
SYSTEMTIME system_time;
FILETIME file_time;
INT int_value;
awstring str;
DWORD sz;
str.unicode = FALSE;
str.str.a = NULL;
len = 0;
r = get_prop( si, row, &data_type, &int_value, &file_time, &str, &len );
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
return r;
if (data_type == VT_EMPTY)
return ERROR_SUCCESS; /* property not set */
snprintf( data, sizeof(data), fmt_begin, row );
sz = lstrlenA( data );
if (!WriteFile( handle, data, sz, &sz, NULL ))
return ERROR_WRITE_FAULT;
switch (data_type)
{
case VT_I2:
case VT_I4:
snprintf( data, sizeof(data), fmt_int, int_value );
sz = lstrlenA( data );
if (!WriteFile( handle, data, sz, &sz, NULL ))
return ERROR_WRITE_FAULT;
break;
case VT_LPSTR:
len++;
if (!(str.str.a = msi_alloc( len )))
return ERROR_OUTOFMEMORY;
r = get_prop( si, row, NULL, NULL, NULL, &str, &len );
if (r != ERROR_SUCCESS)
{
msi_free( str.str.a );
return r;
}
sz = lstrlenA( str.str.a );
if (!WriteFile( handle, str.str.a, sz, &sz, NULL ))
{
msi_free( str.str.a );
return ERROR_WRITE_FAULT;
}
msi_free( str.str.a );
break;
case VT_FILETIME:
if (!FileTimeToSystemTime( &file_time, &system_time ))
return ERROR_FUNCTION_FAILED;
snprintf( data, sizeof(data), fmt_systemtime, system_time.wYear, system_time.wMonth,
system_time.wDay, system_time.wHour, system_time.wMinute,
system_time.wSecond );
sz = lstrlenA( data );
if (!WriteFile( handle, data, sz, &sz, NULL ))
return ERROR_WRITE_FAULT;
break;
case VT_EMPTY:
/* cannot reach here, property not set */
break;
default:
FIXME( "Unknown property variant type\n" );
return ERROR_FUNCTION_FAILED;
}
sz = lstrlenA( data_end );
if (!WriteFile( handle, data_end, sz, &sz, NULL ))
return ERROR_WRITE_FAULT;
return ERROR_SUCCESS;
}
UINT msi_export_suminfo( MSIDATABASE *db, HANDLE handle )
{
UINT i, r, num_rows;
MSISUMMARYINFO *si;
r = msi_get_suminfo( db->storage, 0, &si );
if (r != ERROR_SUCCESS)
r = msi_get_db_suminfo( db, 0, &si );
if (r != ERROR_SUCCESS)
return r;
num_rows = get_property_count( si->property );
if (!num_rows)
{
msiobj_release( &si->hdr );
return ERROR_FUNCTION_FAILED;
}
for (i = 0; i < num_rows; i++)
{
r = save_prop( si, handle, i );
if (r != ERROR_SUCCESS)
{
msiobj_release( &si->hdr );
return r;
}
}
msiobj_release( &si->hdr );
return ERROR_SUCCESS;
}
UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
{
MSISUMMARYINFO *si;

View file

@ -112,7 +112,7 @@ reactos/dll/win32/msg711.acm # Synced to WineStaging-2.9
reactos/dll/win32/msgsm32.acm # Synced to WineStaging-2.9
reactos/dll/win32/mshtml # Synced to WineStaging-1.7.55
reactos/dll/win32/mshtml.tlb # Synced to WineStaging-1.7.55
reactos/dll/win32/msi # Synced to WineStaging-2.16
reactos/dll/win32/msi # Synced to Wine-3.0
reactos/dll/win32/msimg32 # Synced to WineStaging-2.16
reactos/dll/win32/msimtf # Synced to WineStaging-2.9
reactos/dll/win32/msisip # Synced to WineStaging-2.9