[PATCH 4/4] msi: Correctly format the template field for MsiProcessMessage().

Zebediah Figura z.figura12 at gmail.com
Mon Jul 3 00:34:55 CDT 2017


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 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 a1e94b1..a922de1 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -4531,10 +4531,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 f25c617..1358a44 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}},
@@ -9432,7 +9447,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;
 
@@ -9467,7 +9482,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");
@@ -9506,7 +9548,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");
@@ -9516,7 +9558,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);
@@ -9530,6 +9572,7 @@ static void test_externalui_message(void)
     MsiCloseHandle(hpkg);
     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
 
+    MsiCloseHandle(hrecord);
     CoUninitialize();
     DeleteFileA(msifile);
     DeleteFileA("forcecodepage.idt");
-- 
2.7.4




More information about the wine-patches mailing list