Zebediah Figura : msi: Handle the remote case in MsiViewGetError().

Alexandre Julliard julliard at winehq.org
Wed Mar 27 17:27:36 CDT 2019


Module: wine
Branch: master
Commit: 942964fdfbd0cb2af1ea6a1c681fc73d399bcce3
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=942964fdfbd0cb2af1ea6a1c681fc73d399bcce3

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Tue Mar 26 18:56:17 2019 -0500

msi: Handle the remote case in MsiViewGetError().

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46830
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msi/msiquery.c      |  80 +++++++++++++++++++++++++++++++++---
 dlls/msi/tests/custom.c  | 104 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/msi/tests/install.c |  15 +++++++
 dlls/msi/winemsi.idl     |   2 +
 4 files changed, 195 insertions(+), 6 deletions(-)

diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c
index 3c22a21..2569d21 100644
--- a/dlls/msi/msiquery.c
+++ b/dlls/msi/msiquery.c
@@ -778,9 +778,35 @@ MSIDBERROR WINAPI MsiViewGetErrorW( MSIHANDLE handle, LPWSTR buffer, LPDWORD buf
     if (!buflen)
         return MSIDBERROR_INVALIDARG;
 
-    query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
-    if( !query )
-        return MSIDBERROR_INVALIDARG;
+    if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
+    {
+        WCHAR *remote_column = NULL;
+        MSIHANDLE remote;
+
+        if (!(remote = msi_get_remote(handle)))
+            return MSIDBERROR_INVALIDARG;
+
+        if (!*buflen)
+            return MSIDBERROR_FUNCTIONERROR;
+
+        __TRY
+        {
+            r = remote_ViewGetError(remote, &remote_column);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            r = GetExceptionCode();
+        }
+        __ENDTRY;
+
+        if (msi_strncpyW(remote_column ? remote_column : szEmpty, -1, buffer, buflen) == ERROR_MORE_DATA)
+            r = MSIDBERROR_MOREDATA;
+
+        if (remote_column)
+            midl_user_free(remote_column);
+
+        return r;
+    }
 
     if ((r = query->view->error)) column = query->view->error_column;
     else column = szEmpty;
@@ -803,9 +829,35 @@ MSIDBERROR WINAPI MsiViewGetErrorA( MSIHANDLE handle, LPSTR buffer, LPDWORD bufl
     if (!buflen)
         return MSIDBERROR_INVALIDARG;
 
-    query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
-    if (!query)
-        return MSIDBERROR_INVALIDARG;
+    if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
+    {
+        WCHAR *remote_column = NULL;
+        MSIHANDLE remote;
+
+        if (!(remote = msi_get_remote(handle)))
+            return MSIDBERROR_INVALIDARG;
+
+        if (!*buflen)
+            return MSIDBERROR_FUNCTIONERROR;
+
+        __TRY
+        {
+            r = remote_ViewGetError(remote, &remote_column);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            r = GetExceptionCode();
+        }
+        __ENDTRY;
+
+        if (msi_strncpyWtoA(remote_column ? remote_column : szEmpty, -1, buffer, buflen, FALSE) == ERROR_MORE_DATA)
+            r = MSIDBERROR_MOREDATA;
+
+        if (remote_column)
+            midl_user_free(remote_column);
+
+        return r;
+    }
 
     if ((r = query->view->error)) column = query->view->error_column;
     else column = szEmpty;
@@ -1199,6 +1251,22 @@ UINT __cdecl s_remote_ViewGetColumnInfo(MSIHANDLE view, MSICOLINFO info, struct
     return r;
 }
 
+MSIDBERROR __cdecl s_remote_ViewGetError(MSIHANDLE view, LPWSTR *column)
+{
+    WCHAR empty[1];
+    DWORD size = 1;
+    UINT r;
+
+    r = MsiViewGetErrorW(view, empty, &size);
+    if (r == MSIDBERROR_MOREDATA)
+    {
+        if (!(*column = midl_user_allocate(++size * sizeof(WCHAR))))
+            return MSIDBERROR_FUNCTIONERROR;
+        r = MsiViewGetErrorW(view, *column, &size);
+    }
+    return r;
+}
+
 UINT __cdecl s_remote_ViewModify(MSIHANDLE view, MSIMODIFY mode,
     struct wire_record *remote_rec, struct wire_record **remote_refreshed)
 {
diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c
index 43b8369..3a189ef 100644
--- a/dlls/msi/tests/custom.c
+++ b/dlls/msi/tests/custom.c
@@ -1159,6 +1159,109 @@ static void test_invalid_functions(MSIHANDLE hinst)
     MsiCloseHandle(db);
 }
 
+static void test_view_get_error(MSIHANDLE hinst)
+{
+    MSIHANDLE db, view, rec;
+    char buffer[5];
+    MSIDBERROR err;
+    DWORD sz;
+    UINT r;
+
+    db = MsiGetActiveDatabase(hinst);
+    ok(hinst, db, "MsiGetActiveDatabase failed\n");
+
+    r = MsiDatabaseOpenViewA(db, "SELECT * FROM `test2`", &view);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiViewExecute(view, 0);
+    ok(hinst, !r, "got %u\n", r);
+
+    sz = 0;
+    err = MsiViewGetErrorA(0, NULL, &sz);
+    todo_wine ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+    ok(hinst, sz == 0, "got size %u\n", sz);
+
+    err = MsiViewGetErrorA(view, NULL, NULL);
+    ok(hinst, err == MSIDBERROR_INVALIDARG, "got %d\n", err);
+
+    sz = 0;
+    err = MsiViewGetErrorA(view, NULL, &sz);
+    ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+    ok(hinst, sz == 0, "got size %u\n", sz);
+
+    sz = 0;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+    ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
+    ok(hinst, sz == 0, "got size %u\n", sz);
+
+    sz = 1;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
+    ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+    ok(hinst, sz == 0, "got size %u\n", sz);
+
+    rec = MsiCreateRecord(2);
+    MsiRecordSetInteger(rec, 1, 1);
+    MsiRecordSetInteger(rec, 2, 2);
+    r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
+    ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
+
+    sz = 2;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    ok(hinst, err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err);
+    ok(hinst, !strcmp(buffer, "A"), "got \"%s\"\n", buffer);
+    ok(hinst, sz == 1, "got size %u\n", sz);
+
+    sz = 2;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    todo_wine ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
+    todo_wine ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+    todo_wine ok(hinst, sz == 0, "got size %u\n", sz);
+
+    r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
+    ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
+
+    sz = 1;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    ok(hinst, err == MSIDBERROR_MOREDATA, "got %d\n", err);
+    ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+    ok(hinst, sz == 1, "got size %u\n", sz);
+
+    sz = 1;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    todo_wine ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
+    ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+    todo_wine ok(hinst, sz == 0, "got size %u\n", sz);
+
+    r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
+    ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
+
+    sz = 0;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+    ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
+    ok(hinst, sz == 0, "got size %u\n", sz);
+
+    sz = 0;
+    strcpy(buffer, "x");
+    err = MsiViewGetErrorA(view, buffer, &sz);
+    ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+    ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
+    ok(hinst, sz == 0, "got size %u\n", sz);
+
+    MsiCloseHandle(rec);
+    MsiCloseHandle(view);
+    MsiCloseHandle(db);
+}
+
 /* Main test. Anything that doesn't depend on a specific install configuration
  * or have undesired side effects should go here. */
 UINT WINAPI main_test(MSIHANDLE hinst)
@@ -1186,6 +1289,7 @@ UINT WINAPI main_test(MSIHANDLE hinst)
     test_format_record(hinst);
     test_costs(hinst);
     test_invalid_functions(hinst);
+    test_view_get_error(hinst);
 
     return ERROR_SUCCESS;
 }
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c
index 27dc83f..e348f32 100644
--- a/dlls/msi/tests/install.c
+++ b/dlls/msi/tests/install.c
@@ -700,6 +700,19 @@ static const CHAR ca1_test_seq_dat[] = "Action\tCondition\tSequence\n"
                                        "nested1\t\t1\n"
                                        "nested51\t\t2\n";
 
+static const CHAR ca1_test2_dat[] =
+    "A\tB\n"
+    "i2\ti2\n"
+    "test2\tA\n"
+    "1\t2\n";
+
+static const CHAR ca1__validation_dat[] =
+    "Table\tColumn\tNullable\tMinValue\tMaxValue\tKeyTable\tKeyColumn\tCategory\tSet\tDescription\n"
+    "s32\ts32\ts4\tI4\tI4\tS255\tI2\tS32\tS255\tS255\n"
+    "_Validation\tTable\tColumn\n"
+    "test2\tA\tN\t\t\t\t\t\t\t\n"
+    "test2\tB\tN\t\t\t\t\t\t\t\n";
+
 static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
                                          "s72\tS38\ts72\ti2\tS255\tS72\n"
                                          "Component\tComponent\n"
@@ -1714,6 +1727,8 @@ static const msi_table ca1_tables[] =
     ADD_TABLE(ca1_install_exec_seq),
     ADD_TABLE(ca1_custom_action),
     ADD_TABLE(ca1_test_seq),
+    ADD_TABLE(ca1_test2),
+    ADD_TABLE(ca1__validation),
 };
 
 static const msi_table ca51_tables[] =
diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl
index 1658603..7888b0c 100644
--- a/dlls/msi/winemsi.idl
+++ b/dlls/msi/winemsi.idl
@@ -32,6 +32,7 @@ typedef int INSTALLSTATE;
 typedef int MSICOLINFO;
 typedef int MSIMODIFY;
 typedef int MSICOSTTREE;
+typedef int MSIDBERROR;
 
 #define MSIFIELD_NULL   0
 #define MSIFIELD_INT    1
@@ -68,6 +69,7 @@ interface IWineMsiRemote
     UINT remote_ViewExecute( [in] MSIHANDLE view, [in, unique] struct wire_record *record );
     UINT remote_ViewFetch( [in] MSIHANDLE view, [out] struct wire_record **record );
     UINT remote_ViewGetColumnInfo( [in] MSIHANDLE view, [in] MSICOLINFO info, [out] struct wire_record **record );
+    MSIDBERROR remote_ViewGetError( [in] MSIHANDLE view, [out, string] LPWSTR *column );
     UINT remote_ViewModify( [in] MSIHANDLE view, [in] MSIMODIFY mode,
         [in] struct wire_record *record, [out] struct wire_record **refreshed );
 




More information about the wine-cvs mailing list