From: Zebediah Figura Subject: [PATCH 3/6] msi: Correctly format the template field for MsiProcessMessage(). Message-Id: <1499398626-5020-3-git-send-email-z.figura12@gmail.com> Date: Thu, 6 Jul 2017 22:37:03 -0500 In-Reply-To: <1499398626-5020-1-git-send-email-z.figura12@gmail.com> References: <1499398626-5020-1-git-send-email-z.figura12@gmail.com> Signed-off-by: Zebediah Figura --- dlls/msi/dialog.c | 4 +- dlls/msi/msi.rc | 6 +- dlls/msi/msipriv.h | 2 + dlls/msi/package.c | 150 +++++++++++++++++++++++++++++++---------------- dlls/msi/resource.h | 10 +++- dlls/msi/tests/package.c | 51 ++++++++++++++-- 6 files changed, 164 insertions(+), 59 deletions(-) diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c index e0eda9b..ac2b29b 100644 --- a/dlls/msi/dialog.c +++ b/dlls/msi/dialog.c @@ -4530,10 +4530,10 @@ UINT ACTION_ShowDialog( MSIPACKAGE *package, const WCHAR *dialog ) WCHAR template[1024]; MSIRECORD *row = MSI_CreateRecord(2); if (!row) return -1; - MSI_RecordSetStringW(row, 0, szActionNotFound); /* FIXME: this shouldn't attach "Info [1]." */ + MSI_RecordSetStringW(row, 0, szActionNotFound); MSI_RecordSetInteger(row, 1, 2726); MSI_RecordSetStringW(row, 2, dialog); - MSI_ProcessMessage(package, INSTALLMESSAGE_INFO, row); + MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, row); LoadStringW(msi_hInstance, IDS_INSTALLERROR, template, 1024); MSI_RecordSetStringW(row, 0, template); diff --git a/dlls/msi/msi.rc b/dlls/msi/msi.rc index 2c86fae..73a600a 100644 --- a/dlls/msi/msi.rc +++ b/dlls/msi/msi.rc @@ -67,8 +67,12 @@ STRINGTABLE /* Install message format strings */ STRINGTABLE { + IDS_FATALEXIT "{{Fatal error: }}" + IDS_ERROR "{{Error [1]. }}" + IDS_WARNING "Warning [1]." + IDS_INFO "Info [1]." + IDS_OUTOFDISKSPACE "{{Disk full: }}" IDS_ACTIONSTART "Action %s: [1]. [2]" - IDS_INFO "Info [1]. " IDS_COMMONDATA "Message type: [1], Argument: [2]{, [3]}" } diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 9271065..bb9d224 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -390,6 +390,7 @@ typedef struct tagMSIPACKAGE struct list cabinet_streams; LPWSTR ActionFormat; LPWSTR LastAction; + LPWSTR LastActionTemplate; UINT action_progress_increment; HANDLE log_file; IAssemblyCache *cache_net[CLR_VERSION_MAX]; @@ -870,6 +871,7 @@ extern UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel ) DECLSP extern MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *, LPCWSTR ) DECLSPEC_HIDDEN; extern UINT MSI_OpenPackageW( LPCWSTR szPackage, MSIPACKAGE **pPackage ) DECLSPEC_HIDDEN; extern UINT MSI_SetTargetPathW( MSIPACKAGE *, LPCWSTR, LPCWSTR ) DECLSPEC_HIDDEN; +extern INT MSI_ProcessMessageVerbatim( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD * ) DECLSPEC_HIDDEN; extern INT MSI_ProcessMessage( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD * ) DECLSPEC_HIDDEN; extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR ) DECLSPEC_HIDDEN; extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * ) DECLSPEC_HIDDEN; diff --git a/dlls/msi/package.c b/dlls/msi/package.c index bd11656..7ba7c9a 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -331,6 +331,7 @@ static void free_package_structures( MSIPACKAGE *package ) msi_free( package->ProductCode ); msi_free( package->ActionFormat ); msi_free( package->LastAction ); + msi_free( package->LastActionTemplate ); msi_free( package->langids ); /* cleanup control event subscriptions */ @@ -1096,6 +1097,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) msiobj_addref( &db->hdr ); package->db = db; + package->LastAction = NULL; + package->LastActionTemplate = NULL; package->WordCount = 0; package->PackagePath = strdupW( db->path ); package->BaseURL = strdupW( base_url ); @@ -1622,11 +1625,11 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) data_row = MSI_CreateRecord(3); if (!data_row) return ERROR_OUTOFMEMORY; - /* FIXME: field 0 should be NULL */ + 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_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); + MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); info_row = MSI_CreateRecord(0); if (!info_row) @@ -1847,7 +1850,7 @@ static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, } } -INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) +INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) { LPWSTR message = {0}; DWORD len, log_type = 0; @@ -1886,52 +1889,6 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG) log_type |= INSTALLLOGMODE_SHOWDIALOG; - if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART) - { - WCHAR template_s[1024]; - static const WCHAR time_format[] = - {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; - WCHAR timet[100], template[1024]; - - LoadStringW(msi_hInstance, IDS_ACTIONSTART, template_s, 1024); - GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, time_format, timet, 100); - sprintfW(template, template_s, timet); - MSI_RecordSetStringW(record, 0, template); - } - else if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO && - MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) - { - WCHAR template_s[1024]; - WCHAR *template_rec, *template; - - LoadStringW(msi_hInstance, IDS_INFO, template_s, 1024); - - res = MSI_RecordGetStringW(record, 0, NULL, &len); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - len++; - template_rec = msi_alloc(len * sizeof(WCHAR)); - if (!template_rec) return ERROR_OUTOFMEMORY; - MSI_RecordGetStringW(record, 0, template_rec, &len); - len++; - - template = msi_alloc((len + strlenW(template_s)) * sizeof(WCHAR)); - if (!template) return ERROR_OUTOFMEMORY; - - strcpyW(template, template_s); - strcatW(template, template_rec); - MSI_RecordSetStringW(record, 0, template); - - msi_free(template_rec); - msi_free(template); - } - else if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA) - { - WCHAR template[1024]; - LoadStringW(msi_hInstance, IDS_COMMONDATA, template, 1024); - MSI_RecordSetStringW(record, 0, template); - } - if (!package || !record) message = NULL; else { @@ -1986,6 +1943,101 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC return rc; } +INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) +{ + switch (eMessageType & 0xff000000) + { + 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) + { + WCHAR template_prefix[1024]; + WCHAR *template_rec, *template; + UINT prefix_id = 0; + + if (MSI_RecordIsNull(record, 0)) + { + LoadStringW(msi_hInstance, IDS_INSTALLERROR, template_prefix, 1024); + MSI_RecordSetStringW(record, 0, template_prefix); + break; + } + + if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER) + break; + + switch(eMessageType & 0xff000000) + { + case INSTALLMESSAGE_FATALEXIT: prefix_id = IDS_FATALEXIT; break; + case INSTALLMESSAGE_ERROR: prefix_id = IDS_ERROR; break; + case INSTALLMESSAGE_WARNING: prefix_id = IDS_WARNING; break; + case INSTALLMESSAGE_INFO: prefix_id = IDS_INFO; break; + case INSTALLMESSAGE_OUTOFDISKSPACE: prefix_id = IDS_OUTOFDISKSPACE; break; + } + + LoadStringW(msi_hInstance, prefix_id, template_prefix, 1024); + + template_rec = msi_dup_record_field(record, 0); + if (!template_rec) return ERROR_OUTOFMEMORY; + + 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_rec); + msi_free(template); + } + break; + case INSTALLMESSAGE_ACTIONSTART: + { + WCHAR template_s[1024]; + static const WCHAR time_format[] = + {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; + WCHAR timet[100], template[1024]; + + LoadStringW(msi_hInstance, IDS_ACTIONSTART, template_s, 1024); + GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, time_format, timet, 100); + sprintfW(template, template_s, timet); + MSI_RecordSetStringW(record, 0, template); + + msi_free(package->LastAction); + msi_free(package->LastActionTemplate); + package->LastAction = msi_dup_record_field(record, 1); + 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[1024]; + LoadStringW(msi_hInstance, IDS_COMMONDATA, template, 1024); + MSI_RecordSetStringW(record, 0, template); + } + break; + } + + return MSI_ProcessMessageVerbatim(package, eMessageType, record); +} + INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, MSIHANDLE hRecord) { diff --git a/dlls/msi/resource.h b/dlls/msi/resource.h index 6392c91..77c0aa1 100644 --- a/dlls/msi/resource.h +++ b/dlls/msi/resource.h @@ -16,9 +16,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define IDS_ACTIONSTART 1000 -#define IDS_INFO 1001 -#define IDS_COMMONDATA 1002 +#define IDS_FATALEXIT 1000 +#define IDS_ERROR 1001 +#define IDS_WARNING 1002 +#define IDS_INFO 1004 +#define IDS_OUTOFDISKSPACE 1007 +#define IDS_ACTIONSTART 1008 +#define IDS_COMMONDATA 1011 #define IDS_INFO_ACTIONSTART 1050 #define IDS_INFO_ACTIONENDED 1051 diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c index 3179f3a..33afb4b 100644 --- a/dlls/msi/tests/package.c +++ b/dlls/msi/tests/package.c @@ -9352,6 +9352,21 @@ static const struct externalui_message openpackage_sequence[] = { {0} }; +static const struct externalui_message processmessage_info_sequence[] = { + {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}}, + {0} +}; + +static const struct externalui_message processmessage_actionstart_sequence[] = { + {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}}, + {0} +}; + +static const struct externalui_message processmessage_actiondata_sequence[] = { + {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}}, + {0} +}; + static const struct externalui_message doaction_costinitialize_sequence[] = { {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}}, {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}}, @@ -9452,7 +9467,7 @@ static void test_externalui_message(void) /* test that events trigger the correct sequence of messages */ INSTALLUI_HANDLER_RECORD prev; - MSIHANDLE hdb, hpkg; + MSIHANDLE hdb, hpkg, hrecord; INT retval = 1; UINT r; @@ -9489,7 +9504,34 @@ static void test_externalui_message(void) return; } ok(r == ERROR_SUCCESS, "failed to create package %u\n", r); - ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", TRUE); + ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE); + + /* Test MsiProcessMessage */ + hrecord = MsiCreateRecord(3); + ok(hrecord, "failed to create record\n"); + + MsiRecordSetStringA(hrecord, 0, "zero"); + MsiRecordSetStringA(hrecord, 1, "one"); + MsiRecordSetStringA(hrecord, 2, "two"); + MsiRecordSetStringA(hrecord, 3, "three"); + r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord); + ok(r == 1, "Expected 1, got %d\n", r); + ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE); + + MsiRecordSetStringA(hrecord, 1, "name"); + MsiRecordSetStringA(hrecord, 2, "description"); + MsiRecordSetStringA(hrecord, 3, "template"); + r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord); + ok(r == 1, "Expected 1, got %d\n", r); + ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE); + + MsiRecordSetStringA(hrecord, 0, "apple"); + MsiRecordSetStringA(hrecord, 1, "cherry"); + MsiRecordSetStringA(hrecord, 2, "banana"); + MsiRecordSetStringA(hrecord, 3, "guava"); + r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord); + ok(r == 1, "Expected 1, got %d\n", r); + ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE); /* Test a standard action */ r = MsiDoActionA(hpkg, "CostInitialize"); @@ -9528,7 +9570,7 @@ static void test_externalui_message(void) r = package_from_db(hdb, &hpkg); ok(r == ERROR_SUCCESS, "failed to create package %u\n", r); - ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", TRUE); + ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE); /* Test a custom action */ r = MsiDoActionA(hpkg, "custom"); @@ -9538,7 +9580,7 @@ static void test_externalui_message(void) retval = 0; r = MsiDoActionA(hpkg, "custom"); ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r); - ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", TRUE); + ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE); r = MsiDoActionA(hpkg, "dialog"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); @@ -9552,6 +9594,7 @@ static void test_externalui_message(void) MsiCloseHandle(hpkg); ok_sequence(closehandle_sequence, "MsiCloseHandle()", TRUE); + MsiCloseHandle(hrecord); CoUninitialize(); DeleteFileA(msifile); DeleteFileA("forcecodepage.idt"); -- 2.7.4