[PATCH v2 2/5] msi: Use an external UI record handler before a string handler.

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v2 2/5] msi: Use an external UI record handler before a string handler.

Zebediah Figura
As per MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa370385(v=vs.85).aspx

Signed-off-by: Zebediah Figura <[hidden email]>
---
 dlls/msi/package.c       | 20 +++++-----
 dlls/msi/tests/package.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 10 deletions(-)

diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 330f80f..8f86352 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1819,21 +1819,21 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
     msg = msi_alloc( len );
     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
 
-    if (gUIHandlerW && (gUIFilter & log_type))
-    {
-        rc = gUIHandlerW( gUIContext, eMessageType, message );
-    }
-    else if (gUIHandlerA && (gUIFilter & log_type))
-    {
-        rc = gUIHandlerA( gUIContext, eMessageType, msg );
-    }
-    else if (gUIHandlerRecord && (gUIFilter & log_type))
+    if (gUIHandlerRecord && (gUIFilter & log_type))
     {
         MSIHANDLE rec = MsiCreateRecord( 1 );
         MsiRecordSetStringW( rec, 0, message );
         rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
         MsiCloseHandle( rec );
     }
+    if (!rc && gUIHandlerW && (gUIFilter & log_type))
+    {
+        rc = gUIHandlerW( gUIContext, eMessageType, message );
+    }
+    else if (!rc && gUIHandlerA && (gUIFilter & log_type))
+    {
+        rc = gUIHandlerA( gUIContext, eMessageType, msg );
+    }
 
     if (!rc && package->log_file != INVALID_HANDLE_VALUE &&
         (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
@@ -1882,7 +1882,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
         break;
     }
 
-    return ERROR_SUCCESS;
+    return rc;
 }
 
 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index 10ef84a..e18f0f0 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -39,6 +39,7 @@ static char CURR_DIR[MAX_PATH];
 
 static UINT (WINAPI *pMsiApplyMultiplePatchesA)(LPCSTR, LPCSTR, LPCSTR);
 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
+static UINT (WINAPI *pMsiSetExternalUIRecord)(INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
 
 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
@@ -67,6 +68,7 @@ static void init_functionpointers(void)
 
     GET_PROC(hmsi, MsiApplyMultiplePatchesA);
     GET_PROC(hmsi, MsiGetComponentPathExA);
+    GET_PROC(hmsi, MsiSetExternalUIRecord);
     GET_PROC(hshell32, SHGetFolderPathA);
 
     GET_PROC(hadvapi32, CheckTokenMembership);
@@ -9074,6 +9076,102 @@ error:
     DeleteFileA( msifile );
 }
 
+static int externalui_ran;
+
+static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
+{
+    externalui_ran = 1;
+    ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
+    return 0;
+}
+
+static int externalui_record_ran;
+
+static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
+{
+    INT retval = context ? *((INT *)context) : 0;
+    UINT r;
+    externalui_record_ran = 1;
+    ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
+    r = MsiRecordGetFieldCount(hrecord);
+    ok(r == 1, "expected 1, got %u\n", r);
+    r = MsiRecordGetInteger(hrecord, 1);
+    todo_wine
+    ok(r == 12345, "expected 12345, got %u\n", r);
+    return retval;
+}
+
+static void test_externalui(void)
+{
+    /* test that external UI handlers work correctly */
+
+    INSTALLUI_HANDLERA prev;
+    INSTALLUI_HANDLER_RECORD prev_record;
+    MSIHANDLE hpkg, hrecord;
+    UINT r;
+
+    prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
+
+    r = package_from_db(create_package_db(), &hpkg);
+    if (r == ERROR_INSTALL_PACKAGE_REJECTED)
+    {
+        skip("Not enough rights to perform tests\n");
+        DeleteFileA(msifile);
+        return;
+    }
+    ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
+
+    hrecord = MsiCreateRecord(1);
+    ok(hrecord, "Expected a valid record\n");
+    r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
+    ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
+    r = MsiRecordSetInteger(hrecord, 1, 12345);
+    ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
+
+    externalui_ran = 0;
+    r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
+    ok(r == 0, "expected 0, got %u\n", r);
+    ok(externalui_ran == 1, "external UI callback did not run\n");
+
+    if (pMsiSetExternalUIRecord)
+    {
+        INT retval = 0;
+
+        prev = MsiSetExternalUIA(prev, 0, NULL);
+        ok(prev == externalui_callback, "wrong callback function %p\n", prev);
+        r = pMsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
+        ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
+
+        externalui_ran = externalui_record_ran = 0;
+        r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
+        ok(r == 0, "expected 0, got %u\n", r);
+        ok(externalui_ran == 0, "external UI callback should not have run\n");
+        ok(externalui_record_ran == 1, "external UI record callback did not run\n");
+
+        MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
+
+        externalui_ran = externalui_record_ran = 0;
+        r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
+        ok(r == 0, "expected 0, got %u\n", r);
+        ok(externalui_ran == 1, "external UI callback did not run\n");
+        ok(externalui_record_ran == 1, "external UI record callback did not run\n");
+
+        retval = 1;
+        externalui_ran = externalui_record_ran = 0;
+        r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
+        todo_wine
+        ok(r == 1, "expected 1, got %u\n", r);
+        todo_wine
+        ok(externalui_ran == 0, "external UI callback should not have run\n");
+        ok(externalui_record_ran == 1, "external UI record callback did not run\n");
+    }
+    else
+        win_skip("MsiSetExternalUIRecord is not available\n");
+
+    MsiCloseHandle(hpkg);
+    DeleteFileA(msifile);
+}
+
 START_TEST(package)
 {
     STATEMGRSTATUS status;
@@ -9131,6 +9229,7 @@ START_TEST(package)
     test_MsiApplyPatch();
     test_MsiEnumComponentCosts();
     test_MsiDatabaseCommit();
+    test_externalui();
 
     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
     {
--
2.7.4



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v2 3/5] msi: Store string and record callback data separately.

Zebediah Figura
Signed-off-by: Zebediah Figura <[hidden email]>
---
 dlls/msi/media.c         |  2 +-
 dlls/msi/msi.c           |  4 ++--
 dlls/msi/msi_main.c      |  2 ++
 dlls/msi/msipriv.h       |  2 ++
 dlls/msi/package.c       | 13 ++++++++-----
 dlls/msi/tests/package.c | 12 ++++++++++--
 6 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/dlls/msi/media.c b/dlls/msi/media.c
index 1357a64..bbfdd6f 100644
--- a/dlls/msi/media.c
+++ b/dlls/msi/media.c
@@ -109,7 +109,7 @@ static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
         {
             MSIHANDLE rec = MsiCreateRecord(1);
             MsiRecordSetStringW(rec, 0, error);
-            gUIHandlerRecord(gUIContext, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, rec);
+            gUIHandlerRecord(gUIContextRecord, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, rec);
             MsiCloseHandle(rec);
         }
     }
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index 8a11e83..ce8a7be 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -4222,8 +4222,8 @@ UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler,
         *prev = gUIHandlerRecord;
 
     gUIHandlerRecord = handler;
-    gUIFilter        = filter;
-    gUIContext       = context;
+    gUIFilterRecord  = filter;
+    gUIContextRecord = context;
 
     return ERROR_SUCCESS;
 }
diff --git a/dlls/msi/msi_main.c b/dlls/msi/msi_main.c
index 0955856..11cbf41 100644
--- a/dlls/msi/msi_main.c
+++ b/dlls/msi/msi_main.c
@@ -44,7 +44,9 @@ INSTALLUI_HANDLERA       gUIHandlerA      = NULL;
 INSTALLUI_HANDLERW       gUIHandlerW      = NULL;
 INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
 DWORD                    gUIFilter        = 0;
+DWORD                    gUIFilterRecord  = 0;
 LPVOID                   gUIContext       = NULL;
+LPVOID                   gUIContextRecord = NULL;
 WCHAR                   *gszLogFile       = NULL;
 HINSTANCE msi_hInstance;
 
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 2e9e91e..cc42316 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -972,7 +972,9 @@ extern INSTALLUI_HANDLERA gUIHandlerA DECLSPEC_HIDDEN;
 extern INSTALLUI_HANDLERW gUIHandlerW DECLSPEC_HIDDEN;
 extern INSTALLUI_HANDLER_RECORD gUIHandlerRecord DECLSPEC_HIDDEN;
 extern DWORD gUIFilter DECLSPEC_HIDDEN;
+extern DWORD gUIFilterRecord DECLSPEC_HIDDEN;
 extern LPVOID gUIContext DECLSPEC_HIDDEN;
+extern LPVOID gUIContextRecord DECLSPEC_HIDDEN;
 extern WCHAR *gszLogFile DECLSPEC_HIDDEN;
 extern HINSTANCE msi_hInstance DECLSPEC_HIDDEN;
 
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 8f86352..eae01e0 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1811,27 +1811,30 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
         p[0] = 0;
     }
 
-    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 (gUIHandlerRecord && (gUIFilter & log_type))
+    if (gUIHandlerRecord && (gUIFilterRecord & log_type))
     {
         MSIHANDLE rec = MsiCreateRecord( 1 );
         MsiRecordSetStringW( rec, 0, message );
-        rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
+        TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n",
+              gUIHandlerRecord, gUIContextRecord, eMessageType, rec);
+        rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
         MsiCloseHandle( rec );
     }
     if (!rc && gUIHandlerW && (gUIFilter & log_type))
     {
+        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 (!rc && gUIHandlerA && (gUIFilter & log_type))
     {
+        TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
+              gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg));
         rc = gUIHandlerA( gUIContext, eMessageType, msg );
     }
 
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index e18f0f0..a7cec7f 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -9159,11 +9159,19 @@ static void test_externalui(void)
         retval = 1;
         externalui_ran = externalui_record_ran = 0;
         r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
-        todo_wine
         ok(r == 1, "expected 1, got %u\n", r);
-        todo_wine
         ok(externalui_ran == 0, "external UI callback should not have run\n");
         ok(externalui_record_ran == 1, "external UI record callback did not run\n");
+
+        /* filter and context should be kept separately */
+        r = pMsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
+        ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
+
+        externalui_ran = externalui_record_ran = 0;
+        r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
+        ok(r == 0, "expected 0, got %u\n", r);
+        ok(externalui_ran == 1, "external UI callback did not run\n");
+        ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
     }
     else
         win_skip("MsiSetExternalUIRecord is not available\n");
--
2.7.4



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v2 4/5] msi: Don't reimplement record formatting.

Zebediah Figura
In reply to this post by Zebediah Figura
Signed-off-by: Zebediah Figura <[hidden email]>
---
 dlls/msi/package.c | 41 ++++++-----------------------------------
 1 file changed, 6 insertions(+), 35 deletions(-)

diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index eae01e0..f16b1dc 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1709,8 +1709,8 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
     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;
+    LPWSTR deformated, message = {0};
+    DWORD len, log_type = 0;
     INT rc = 0;
     char *msg;
 
@@ -1776,39 +1776,10 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
     }
     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;
+        MSI_FormatRecordW(package, record, message, &len);
+        len++;
+        message = msi_alloc(len * sizeof(WCHAR));
+        MSI_FormatRecordW(package, record, message, &len);
     }
 
     /* convert it to ASCII */
--
2.7.4



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v2 5/5] msi: Pass the given record to the callback.

Zebediah Figura
In reply to this post by Zebediah Figura
Signed-off-by: Zebediah Figura <[hidden email]>
---
 dlls/msi/package.c       | 3 +--
 dlls/msi/tests/package.c | 1 -
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index f16b1dc..b8387fe 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1789,8 +1789,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
 
     if (gUIHandlerRecord && (gUIFilterRecord & log_type))
     {
-        MSIHANDLE rec = MsiCreateRecord( 1 );
-        MsiRecordSetStringW( rec, 0, 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 );
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index a7cec7f..146d1fc 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -9096,7 +9096,6 @@ static INT CALLBACK externalui_record_callback(void *context, UINT message_type,
     r = MsiRecordGetFieldCount(hrecord);
     ok(r == 1, "expected 1, got %u\n", r);
     r = MsiRecordGetInteger(hrecord, 1);
-    todo_wine
     ok(r == 12345, "expected 12345, got %u\n", r);
     return retval;
 }
--
2.7.4



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v2 2/5] msi: Use an external UI record handler before a string handler.

Hans Leidekker-4
In reply to this post by Zebediah Figura
Signed-off-by: Hans Leidekker <[hidden email]>




Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v2 3/5] msi: Store string and record callback data separately.

Hans Leidekker-4
In reply to this post by Zebediah Figura
Signed-off-by: Hans Leidekker <[hidden email]>




Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v2 5/5] msi: Pass the given record to the callback.

Hans Leidekker-4
In reply to this post by Zebediah Figura
Signed-off-by: Hans Leidekker <[hidden email]>




Loading...