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 ));
- DeleteFileW( temp->Path );
- msi_free( temp->Path );
- msi_free( temp );
- }
-}
-
static void free_feature( MSIFEATURE *feature )
{
struct list *item, *cursor;
free_folder( folder );
}
+ 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 );
+ if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
+ msi_free( file->TargetPath );
+ msi_free( file );
+ }
+
LIST_FOR_EACH_SAFE( item, cursor, &package->components )
{
MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
msi_free( comp );
}
- LIST_FOR_EACH_SAFE( item, cursor, &package->files )
+ LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
{
- MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
+ MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, 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 );
+ list_remove( &patch->entry );
+ msi_free( patch->path );
+ msi_free( patch );
}
/* clean up extension, progid, class and verb structures */
msi_free( package->ProductCode );
msi_free( package->ActionFormat );
msi_free( package->LastAction );
+ msi_free( package->LastActionTemplate );
msi_free( package->langids );
- remove_tracked_tempfiles(package);
-
/* cleanup control event subscriptions */
msi_event_cleanup_all_subscriptions( package );
}
if (package->delete_on_close) DeleteFileW( package->localfile );
msi_free( package->localfile );
+ MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
}
static UINT create_temp_property_table(MSIPACKAGE *package)
return rc;
}
-UINT msi_clone_properties(MSIPACKAGE *package)
+UINT msi_clone_properties( MSIDATABASE *db )
{
static const WCHAR query_select[] = {
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
MSIQUERY *view_select;
UINT rc;
- rc = MSI_DatabaseOpenViewW( package->db, query_select, &view_select );
+ rc = MSI_DatabaseOpenViewW( db, query_select, &view_select );
if (rc != ERROR_SUCCESS)
return rc;
if (rc != ERROR_SUCCESS)
break;
- rc = MSI_DatabaseOpenViewW( package->db, query_insert, &view_insert );
+ rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert );
if (rc != ERROR_SUCCESS)
{
msiobj_release( &rec_select->hdr );
TRACE("insert failed, trying update\n");
- rc = MSI_DatabaseOpenViewW( package->db, query_update, &view_update );
+ rc = MSI_DatabaseOpenViewW( db, query_update, &view_update );
if (rc != ERROR_SUCCESS)
{
WARN("open view failed %u\n", rc);
HKEY hkey;
LPWSTR username, companyname;
SYSTEM_INFO sys_info;
- SYSTEMTIME systemtime;
LANGID langid;
static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
};
static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
- static const WCHAR szDate[] = {'D','a','t','e',0};
- static const WCHAR szTime[] = {'T','i','m','e',0};
static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0};
static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0};
static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0};
static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
- static const WCHAR szBrowseProperty[] = {'_','B','r','o','w','s','e','P','r','o','p','e','r','t','y',0};
- static const WCHAR szInstallDir[] = {'I','N','S','T','A','L','L','D','I','R',0};
/*
* Other things that probably should be set:
if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
ERR("Failed to set the UserSID property\n");
- /* Date and time properties */
- GetSystemTime( &systemtime );
- if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
- NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
- msi_set_property( package->db, szDate, bufstr, -1 );
- else
- ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError());
-
- if (GetTimeFormatW( LOCALE_USER_DEFAULT,
- TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
- &systemtime, NULL, bufstr,
- sizeof(bufstr)/sizeof(bufstr[0]) ))
- msi_set_property( package->db, szTime, bufstr, -1 );
- else
- ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
-
set_msi_assembly_prop( package );
langid = GetUserDefaultLangID();
msi_free( computername );
}
}
- msi_set_property( package->db, szBrowseProperty, szInstallDir, -1 );
-}
-
-static UINT msi_load_summary_properties( MSIPACKAGE *package )
-{
- UINT rc;
- MSIHANDLE suminfo;
- MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
- INT count;
- DWORD len;
- LPWSTR package_code;
- static const WCHAR szPackageCode[] = {
- 'P','a','c','k','a','g','e','C','o','d','e',0};
-
- if (!hdb) {
- ERR("Unable to allocate handle\n");
- return ERROR_OUTOFMEMORY;
- }
-
- rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
- MsiCloseHandle(hdb);
- if (rc != ERROR_SUCCESS)
- {
- ERR("Unable to open Summary Information\n");
- return rc;
- }
-
- rc = MsiSummaryInfoGetPropertyW( suminfo, PID_PAGECOUNT, NULL,
- &count, NULL, NULL, NULL );
- if (rc != ERROR_SUCCESS)
- {
- WARN("Unable to query page count: %d\n", rc);
- goto done;
- }
-
- /* load package code property */
- len = 0;
- rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
- NULL, NULL, NULL, &len );
- if (rc != ERROR_MORE_DATA)
- {
- WARN("Unable to query revision number: %d\n", rc);
- rc = ERROR_FUNCTION_FAILED;
- goto done;
- }
-
- len++;
- package_code = msi_alloc( len * sizeof(WCHAR) );
- rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
- NULL, NULL, package_code, &len );
- if (rc != ERROR_SUCCESS)
- {
- WARN("Unable to query rev number: %d\n", rc);
- goto done;
- }
-
- msi_set_property( package->db, szPackageCode, package_code, len );
- msi_free( package_code );
-
- /* load package attributes */
- count = 0;
- MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
- &count, NULL, NULL, NULL );
- package->WordCount = count;
-
-done:
- MsiCloseHandle(suminfo);
- return rc;
}
static MSIPACKAGE *msi_alloc_package( void )
msiobj_addref( &db->hdr );
package->db = db;
+ package->LastAction = NULL;
+ package->LastActionTemplate = NULL;
+ package->LastActionResult = MSI_NULL_INTEGER;
package->WordCount = 0;
package->PackagePath = strdupW( db->path );
package->BaseURL = strdupW( base_url );
create_temp_property_table( package );
- msi_clone_properties( package );
+ msi_clone_properties( package->db );
msi_adjust_privilege_properties( package );
package->ProductCode = msi_dup_property( package->db, szProductCode );
package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
- set_installed_prop( package );
set_installer_properties( package );
package->ui_level = gUILevel;
len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
msi_set_property( package->db, szUILevel, uilevel, len );
- r = msi_load_summary_properties( package );
+ r = msi_load_suminfo_properties( package );
if (r != ERROR_SUCCESS)
{
msiobj_release( &package->hdr );
return ERROR_SUCCESS;
}
-static enum platform parse_platform( WCHAR *str )
+static enum platform parse_platform( const WCHAR *str )
{
if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL;
else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64;
return PLATFORM_UNKNOWN;
}
-static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
+static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
{
WCHAR *template, *p, *q, *platform;
DWORD i, count;
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
}
-int msi_track_tempfile( MSIPACKAGE *package, const WCHAR *path )
-{
- MSITEMPFILE *temp;
-
- TRACE("%s\n", debugstr_w(path));
-
- LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
- {
- if (!strcmpW( path, temp->Path )) return 0;
- }
- if (!(temp = msi_alloc_zero( sizeof (MSITEMPFILE) ))) return -1;
- list_add_head( &package->tempfiles, &temp->entry );
- temp->Path = strdupW( path );
- return 0;
-}
-
static WCHAR *get_product_code( MSIDATABASE *db )
{
static const WCHAR query[] = {
{
WCHAR *ret;
MSISUMMARYINFO *si;
+ UINT r;
- if (!(si = MSI_GetSummaryInformationW( db->storage, 0 )))
+ r = msi_get_suminfo( db->storage, 0, &si );
+ if (r != ERROR_SUCCESS)
{
- WARN("failed to load summary info\n");
- return NULL;
+ r = msi_get_db_suminfo( db, 0, &si );
+ if (r != ERROR_SUCCESS)
+ {
+ WARN("failed to load summary info %u\n", r);
+ return NULL;
+ }
}
ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
msiobj_release( &si->hdr );
MSIDATABASE *db;
MSIPACKAGE *package;
MSIHANDLE handle;
+ MSIRECORD *data_row, *info_row;
LPWSTR ptr, base_url = NULL;
UINT r;
WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
DWORD index = 0;
MSISUMMARYINFO *si;
BOOL delete_on_close = FALSE;
+ LPWSTR productname;
+ WCHAR *info_template;
TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
+ MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0);
+
localfile[0] = 0;
if( szPackage[0] == '#' )
{
package->localfile = strdupW( localfile );
package->delete_on_close = delete_on_close;
- si = MSI_GetSummaryInformationW( db->storage, 0 );
- if (!si)
+ r = msi_get_suminfo( db->storage, 0, &si );
+ if (r != ERROR_SUCCESS)
{
- WARN("failed to load summary info\n");
- msiobj_release( &package->hdr );
- return ERROR_INSTALL_PACKAGE_INVALID;
+ r = msi_get_db_suminfo( db, 0, &si );
+ if (r != ERROR_SUCCESS)
+ {
+ WARN("failed to load summary info\n");
+ msiobj_release( &package->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
}
- r = msi_parse_summary( si, package );
+ r = parse_suminfo( si, package );
msiobj_release( &si->hdr );
if (r != ERROR_SUCCESS)
{
return r;
}
msi_set_property( package->db, szDatabase, db->path, -1 );
+ set_installed_prop( package );
msi_set_context( package );
while (1)
}
index++;
}
- if (index)
- {
- msi_clone_properties( package );
- msi_adjust_privilege_properties( package );
- }
+ if (index) msi_adjust_privilege_properties( package );
+
r = msi_set_original_database_property( package->db, szPackage );
if (r != ERROR_SUCCESS)
{
if (gszLogFile)
package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ /* FIXME: when should these messages be sent? */
+ data_row = MSI_CreateRecord(3);
+ if (!data_row)
+ return ERROR_OUTOFMEMORY;
+ MSI_RecordSetStringW(data_row, 0, NULL);
+ MSI_RecordSetInteger(data_row, 1, 0);
+ MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0);
+ MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings));
+ MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row);
+
+ info_row = MSI_CreateRecord(0);
+ if (!info_row)
+ {
+ msiobj_release(&data_row->hdr);
+ return ERROR_OUTOFMEMORY;
+ }
+ info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
+ MSI_RecordSetStringW(info_row, 0, info_template);
+ msi_free(info_template);
+ MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row);
+
+ MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
+
+ productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
+ MSI_RecordSetInteger(data_row, 1, 1);
+ MSI_RecordSetStringW(data_row, 2, productname);
+ MSI_RecordSetStringW(data_row, 3, NULL);
+ MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
+
+ msi_free(productname);
+ msiobj_release(&info_row->hdr);
+ msiobj_release(&data_row->hdr);
+
*pPackage = package;
return ERROR_SUCCESS;
}
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &package->hdr );
}
+ else
+ MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
return ret;
}
return handle;
}
-INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
+static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message)
{
static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0};
- static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0};
- MSIRECORD *uirow;
- LPWSTR deformated, message;
- DWORD i, len, total_len, log_type = 0;
+ static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
+ static const WCHAR szWindows_Installer[] =
+ {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0};
+
+ if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE)
+ return 0;
+
+ /* todo: check if message needs additional styles (topmost/foreground/modality?) */
+
+ switch (eMessageType & 0xff000000)
+ {
+ case INSTALLMESSAGE_FATALEXIT:
+ case INSTALLMESSAGE_ERROR:
+ case INSTALLMESSAGE_OUTOFDISKSPACE:
+ if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
+ if (!(eMessageType & MB_ICONMASK))
+ eMessageType |= MB_ICONEXCLAMATION;
+ return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
+ case INSTALLMESSAGE_WARNING:
+ if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
+ if (!(eMessageType & MB_ICONMASK))
+ eMessageType |= MB_ICONASTERISK;
+ return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
+ case INSTALLMESSAGE_USER:
+ if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
+ if (!(eMessageType & MB_ICONMASK))
+ eMessageType |= MB_USERICON;
+ return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
+ case INSTALLMESSAGE_INFO:
+ case INSTALLMESSAGE_INITIALIZE:
+ case INSTALLMESSAGE_TERMINATE:
+ return 0;
+ case INSTALLMESSAGE_SHOWDIALOG:
+ {
+ LPWSTR dialog = msi_dup_record_field(record, 0);
+ INT rc = ACTION_DialogBox(package, dialog);
+ msi_free(dialog);
+ return rc;
+ }
+ case INSTALLMESSAGE_ACTIONSTART:
+ {
+ LPWSTR deformatted;
+ MSIRECORD *uirow = MSI_CreateRecord(1);
+ if (!uirow) return -1;
+ deformat_string(package, MSI_RecordGetString(record, 2), &deformatted);
+ MSI_RecordSetStringW(uirow, 1, deformatted);
+ msi_event_fire(package, szActionText, uirow);
+
+ msi_free(deformatted);
+ msiobj_release(&uirow->hdr);
+ return 1;
+ }
+ case INSTALLMESSAGE_ACTIONDATA:
+ {
+ MSIRECORD *uirow = MSI_CreateRecord(1);
+ if (!uirow) return -1;
+ MSI_RecordSetStringW(uirow, 1, message);
+ msi_event_fire(package, szActionData, uirow);
+ msiobj_release(&uirow->hdr);
+
+ if (package->action_progress_increment)
+ {
+ uirow = MSI_CreateRecord(2);
+ if (!uirow) return -1;
+ MSI_RecordSetInteger(uirow, 1, 2);
+ MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
+ msi_event_fire(package, szSetProgress, uirow);
+ msiobj_release(&uirow->hdr);
+ }
+ return 1;
+ }
+ case INSTALLMESSAGE_PROGRESS:
+ msi_event_fire(package, szSetProgress, record);
+ return 1;
+ case INSTALLMESSAGE_COMMONDATA:
+ switch (MSI_RecordGetInteger(record, 1))
+ {
+ case 0:
+ case 1:
+ /* do nothing */
+ return 0;
+ default:
+ /* fall through */
+ ;
+ }
+ default:
+ FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level);
+ return 0;
+ }
+}
+
+static const WCHAR szActionNotFound[] = {'D','E','B','U','G',':',' ','E','r','r','o','r',' ','[','1',']',':',' ',' ','A','c','t','i','o','n',' ','n','o','t',' ','f','o','u','n','d',':',' ','[','2',']',0};
+
+static const struct
+{
+ int id;
+ const WCHAR *text;
+}
+internal_errors[] =
+{
+ {2726, szActionNotFound},
+ {0}
+};
+
+static LPCWSTR get_internal_error_message(int error)
+{
+ int i = 0;
+
+ while (internal_errors[i].id != 0)
+ {
+ if (internal_errors[i].id == error)
+ return internal_errors[i].text;
+ i++;
+ }
+
+ FIXME("missing error message %d\n", error);
+ return NULL;
+}
+
+/* Returned string must be freed */
+LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
+{
+ static const WCHAR query[] =
+ {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ',
+ 'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ',
+ '`','E','r','r','o','r','`',' ','=',' ','%','i',0};
+ MSIRECORD *record;
+ LPWSTR ret = NULL;
+
+ if ((record = MSI_QueryGetRecord(db, query, error)))
+ {
+ ret = msi_dup_record_field(record, 1);
+ msiobj_release(&record->hdr);
+ }
+ else if (error < 2000)
+ {
+ int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0);
+ if (len)
+ {
+ ret = msi_alloc((len + 1) * sizeof(WCHAR));
+ LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1);
+ }
+ else
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
+{
+ LPWSTR message = {0};
+ DWORD len, log_type = 0;
+ UINT res;
INT rc = 0;
char *msg;
TRACE("%x\n", eMessageType);
+ if (TRACE_ON(msi)) dump_record(record);
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT)
log_type |= INSTALLLOGMODE_FATALEXIT;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG)
log_type |= INSTALLLOGMODE_SHOWDIALOG;
- if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
- {
- static const WCHAR template_s[]=
- {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0};
- static const WCHAR format[] =
- {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
- WCHAR timet[0x100];
- LPCWSTR action_text, action;
- LPWSTR deformatted = NULL;
-
- GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
-
- action = MSI_RecordGetString(record, 1);
- action_text = MSI_RecordGetString(record, 2);
-
- if (!action || !action_text)
- return IDOK;
-
- deformat_string(package, action_text, &deformatted);
-
- len = strlenW(timet) + strlenW(action) + strlenW(template_s);
- if (deformatted)
- len += strlenW(deformatted);
- message = msi_alloc(len*sizeof(WCHAR));
- sprintfW(message, template_s, timet, action);
- if (deformatted)
- strcatW(message, deformatted);
- msi_free(deformatted);
- }
- else
- {
- static const WCHAR format[] = {'%','u',':',' ',0};
- UINT count = MSI_RecordGetFieldCount( record );
- WCHAR *p;
-
- total_len = 1;
- for (i = 1; i <= count; i++)
- {
- len = 0;
- MSI_RecordGetStringW( record, i, NULL, &len );
- total_len += len + 13;
- }
- p = message = msi_alloc( total_len * sizeof(WCHAR) );
- if (!p) return ERROR_OUTOFMEMORY;
-
- for (i = 1; i <= count; i++)
- {
- if (count > 1)
- {
- len = sprintfW( p, format, i );
- total_len -= len;
- p += len;
- }
- len = total_len;
- MSI_RecordGetStringW( record, i, p, &len );
- total_len -= len;
- p += len;
- if (count > 1 && total_len)
- {
- *p++ = ' ';
- total_len--;
- }
- }
- p[0] = 0;
+ if (!package || !record)
+ message = NULL;
+ else {
+ res = MSI_FormatRecordW(package, record, message, &len);
+ if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
+ return res;
+ len++;
+ message = msi_alloc(len * sizeof(WCHAR));
+ if (!message) return ERROR_OUTOFMEMORY;
+ MSI_FormatRecordW(package, record, message, &len);
}
- TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
- gUIFilter, log_type, debugstr_w(message));
-
/* convert it to ASCII */
len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
msg = msi_alloc( len );
WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
- if (gUIHandlerW && (gUIFilter & log_type))
+ if (gUIHandlerRecord && (gUIFilterRecord & log_type))
{
- rc = gUIHandlerW( gUIContext, eMessageType, message );
+ MSIHANDLE rec = alloc_msihandle(&record->hdr);
+ TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n",
+ gUIHandlerRecord, gUIContextRecord, eMessageType, rec);
+ rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
+ MsiCloseHandle( rec );
}
- else if (gUIHandlerA && (gUIFilter & log_type))
+ if (!rc && gUIHandlerW && (gUIFilter & log_type))
{
- rc = gUIHandlerA( gUIContext, eMessageType, msg );
+ TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
+ gUIHandlerW, gUIContext, eMessageType, debugstr_w(message));
+ rc = gUIHandlerW( gUIContext, eMessageType, message );
}
- else if (gUIHandlerRecord && (gUIFilter & log_type))
+ else if (!rc && gUIHandlerA && (gUIFilter & log_type))
{
- MSIHANDLE rec = MsiCreateRecord( 1 );
- MsiRecordSetStringW( rec, 0, message );
- rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
- MsiCloseHandle( rec );
+ TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
+ gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg));
+ rc = gUIHandlerA( gUIContext, eMessageType, msg );
}
- if (!rc && package->log_file != INVALID_HANDLE_VALUE &&
+ if (!rc)
+ rc = internal_ui_handler(package, eMessageType, record, message);
+
+ if (!rc && package && package->log_file != INVALID_HANDLE_VALUE &&
(eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
{
DWORD written;
msi_free( msg );
msi_free( message );
+ return rc;
+}
+
+INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
+{
switch (eMessageType & 0xff000000)
{
- case INSTALLMESSAGE_ACTIONDATA:
- deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
- uirow = MSI_CreateRecord(1);
- MSI_RecordSetStringW(uirow, 1, deformated);
- msi_free(deformated);
+ case INSTALLMESSAGE_FATALEXIT:
+ case INSTALLMESSAGE_ERROR:
+ case INSTALLMESSAGE_WARNING:
+ case INSTALLMESSAGE_USER:
+ case INSTALLMESSAGE_INFO:
+ case INSTALLMESSAGE_OUTOFDISKSPACE:
+ if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER)
+ {
+ /* error message */
- msi_event_fire( package, szActionData, uirow );
- msiobj_release(&uirow->hdr);
+ LPWSTR template;
+ LPWSTR template_rec = NULL, template_prefix = NULL;
+ int error = MSI_RecordGetInteger(record, 1);
- if (package->action_progress_increment)
- {
- uirow = MSI_CreateRecord(2);
- MSI_RecordSetInteger(uirow, 1, 2);
- MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
- msi_event_fire( package, szSetProgress, uirow );
- msiobj_release(&uirow->hdr);
- }
- break;
+ if (MSI_RecordIsNull(record, 0))
+ {
+ if (error >= 32)
+ {
+ template_rec = msi_get_error_message(package->db, error);
+
+ if (!template_rec && error >= 2000)
+ {
+ /* internal error, not localized */
+ if ((template_rec = (LPWSTR) get_internal_error_message(error)))
+ {
+ MSI_RecordSetStringW(record, 0, template_rec);
+ MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record);
+ }
+ template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR);
+ MSI_RecordSetStringW(record, 0, template_rec);
+ MSI_ProcessMessageVerbatim(package, eMessageType, record);
+ msi_free(template_rec);
+ return 0;
+ }
+ }
+ }
+ else
+ template_rec = msi_dup_record_field(record, 0);
- case INSTALLMESSAGE_ACTIONSTART:
- deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
- uirow = MSI_CreateRecord(1);
- MSI_RecordSetStringW(uirow, 1, deformated);
- msi_free(deformated);
+ template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
+ if (!template_prefix) template_prefix = strdupW(szEmpty);
- msi_event_fire( package, szActionText, uirow );
+ if (!template_rec)
+ {
+ /* always returns 0 */
+ MSI_RecordSetStringW(record, 0, template_prefix);
+ MSI_ProcessMessageVerbatim(package, eMessageType, record);
+ msi_free(template_prefix);
+ return 0;
+ }
- msiobj_release(&uirow->hdr);
+ template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR));
+ if (!template) return ERROR_OUTOFMEMORY;
+
+ strcpyW(template, template_prefix);
+ strcatW(template, template_rec);
+ MSI_RecordSetStringW(record, 0, template);
+
+ msi_free(template_prefix);
+ msi_free(template_rec);
+ msi_free(template);
+ }
break;
+ case INSTALLMESSAGE_ACTIONSTART:
+ {
+ WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART);
+ MSI_RecordSetStringW(record, 0, template);
+ msi_free(template);
- case INSTALLMESSAGE_PROGRESS:
- msi_event_fire( package, szSetProgress, record );
+ msi_free(package->LastAction);
+ msi_free(package->LastActionTemplate);
+ package->LastAction = msi_dup_record_field(record, 1);
+ if (!package->LastAction) package->LastAction = strdupW(szEmpty);
+ package->LastActionTemplate = msi_dup_record_field(record, 3);
+ break;
+ }
+ case INSTALLMESSAGE_ACTIONDATA:
+ if (package->LastAction && package->LastActionTemplate)
+ {
+ static const WCHAR template_s[] =
+ {'{','{','%','s',':',' ','}','}','%','s',0};
+ WCHAR *template;
+
+ template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR));
+ if (!template) return ERROR_OUTOFMEMORY;
+ sprintfW(template, template_s, package->LastAction, package->LastActionTemplate);
+ MSI_RecordSetStringW(record, 0, template);
+ msi_free(template);
+ }
break;
+ case INSTALLMESSAGE_COMMONDATA:
+ {
+ WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA);
+ MSI_RecordSetStringW(record, 0, template);
+ msi_free(template);
+ }
+ break;
}
- return ERROR_SUCCESS;
+ return MSI_ProcessMessageVerbatim(package, eMessageType, record);
}
INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
MSIPACKAGE *package = NULL;
MSIRECORD *record = NULL;
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE ||
+ (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
+ return -1;
+
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA &&
+ MsiRecordGetInteger(hRecord, 1) != 2)
+ return -1;
+
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
if( !package )
{
MSIQUERY *view;
UINT r;
+ static const WCHAR szDate[] = {'D','a','t','e',0};
+ static const WCHAR szTime[] = {'T','i','m','e',0};
+ WCHAR *buffer;
+ int length;
+
if (!name || !*name)
return NULL;
+ if (!strcmpW(name, szDate))
+ {
+ length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0);
+ if (!length)
+ return NULL;
+ buffer = msi_alloc(length * sizeof(WCHAR));
+ GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length);
+
+ row = MSI_CreateRecord(1);
+ if (!row)
+ return NULL;
+ MSI_RecordSetStringW(row, 1, buffer);
+ msi_free(buffer);
+ return row;
+ }
+ else if (!strcmpW(name, szTime))
+ {
+ length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0);
+ if (!length)
+ return NULL;
+ buffer = msi_alloc(length * sizeof(WCHAR));
+ GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length);
+
+ row = MSI_CreateRecord(1);
+ if (!row)
+ return NULL;
+ MSI_RecordSetStringW(row, 1, buffer);
+ msi_free(buffer);
+ return row;
+ }
+
rec = MSI_CreateRecord(1);
if (!rec)
return NULL;
MSIRECORD *row;
UINT rc = ERROR_FUNCTION_FAILED;
+ TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
+
row = msi_get_property_row( db, szName );
if (*pchValueBuf > 0)
This->package = 0;
This->refs = 1;
- *ppObj = This;
+ *ppObj = &This->IWineMsiRemotePackage_iface;
return S_OK;
}