[PATCH 6/6] msi: Make MsiViewFetch() RPC-compatible.

Zebediah Figura z.figura12 at gmail.com
Wed Apr 18 18:40:06 CDT 2018


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/msi/msipriv.h      |  2 ++
 dlls/msi/msiquery.c     | 29 +++++++++++++++++++--
 dlls/msi/record.c       | 55 ++++++++++++++++++++++++++++++++++++++++
 dlls/msi/tests/custom.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/msi/winemsi.idl    |  1 +
 5 files changed, 151 insertions(+), 3 deletions(-)

diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 7ea898c..f386f90 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -831,6 +831,8 @@ extern UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int) DECLSPE
 extern const WCHAR *msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN;
 extern void dump_record(MSIRECORD *) DECLSPEC_HIDDEN;
 extern UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out) DECLSPEC_HIDDEN;
+extern struct wire_record *marshal_record(MSIHANDLE handle) DECLSPEC_HIDDEN;
+extern void free_remote_record(struct wire_record *rec) DECLSPEC_HIDDEN;
 
 /* stream internals */
 extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN;
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c
index bfc239a..6eddf7a 100644
--- a/dlls/msi/msiquery.c
+++ b/dlls/msi/msiquery.c
@@ -389,8 +389,22 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
     *record = 0;
 
     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
-    if( !query )
-        return ERROR_INVALID_HANDLE;
+    if (!query)
+    {
+        struct wire_record *wire_rec = NULL;
+        MSIHANDLE remote;
+
+        if (!(remote = msi_get_remote(hView)))
+            return ERROR_INVALID_HANDLE;
+
+        ret = remote_ViewFetch(remote, &wire_rec);
+        if (!ret)
+        {
+            ret = unmarshal_record(wire_rec, record);
+            free_remote_record(wire_rec);
+        }
+        return ret;
+    }
     ret = MSI_ViewFetch( query, &rec );
     if( ret == ERROR_SUCCESS )
     {
@@ -1054,3 +1068,14 @@ UINT __cdecl remote_ViewExecute(MSIHANDLE view, struct wire_record *remote_rec)
     MsiCloseHandle(rec);
     return r;
 }
+
+UINT __cdecl remote_ViewFetch(MSIHANDLE view, struct wire_record **rec)
+{
+    MSIHANDLE handle;
+    UINT r = MsiViewFetch(view, &handle);
+    *rec = NULL;
+    if (!r)
+        *rec = marshal_record(handle);
+    MsiCloseHandle(handle);
+    return r;
+}
diff --git a/dlls/msi/record.c b/dlls/msi/record.c
index 4c504ea..91892d7 100644
--- a/dlls/msi/record.c
+++ b/dlls/msi/record.c
@@ -1103,3 +1103,58 @@ UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out)
     msiobj_release(&rec->hdr);
     return ERROR_SUCCESS;
 }
+
+struct wire_record *marshal_record(MSIHANDLE handle)
+{
+    struct wire_record *ret;
+    unsigned int i, count;
+    MSIRECORD *rec;
+
+    if (!(rec = msihandle2msiinfo(handle, MSIHANDLETYPE_RECORD)))
+        return NULL;
+
+    count = MSI_RecordGetFieldCount(rec);
+    ret = midl_user_allocate(sizeof(*ret) + count * sizeof(ret->fields[0]));
+    ret->count = count;
+
+    for (i = 0; i <= count; i++)
+    {
+        switch (rec->fields[i].type)
+        {
+        case MSIFIELD_NULL:
+            break;
+        case MSIFIELD_INT:
+            ret->fields[i].u.iVal = rec->fields[i].u.iVal;
+            break;
+        case MSIFIELD_WSTR:
+            ret->fields[i].u.szwVal = strdupW(rec->fields[i].u.szwVal);
+            break;
+        case MSIFIELD_STREAM:
+            IStream_AddRef(rec->fields[i].u.stream);
+            ret->fields[i].u.stream = rec->fields[i].u.stream;
+            break;
+        default:
+            ERR("invalid field type %d\n", rec->fields[i].type);
+            break;
+        }
+        ret->fields[i].type = rec->fields[i].type;
+    }
+
+    msiobj_release(&rec->hdr);
+    return ret;
+}
+
+void free_remote_record(struct wire_record *rec)
+{
+    int i;
+
+    for (i = 0; i <= rec->count; i++)
+    {
+        if (rec->fields[i].type == MSIFIELD_WSTR)
+            midl_user_free(rec->fields[i].u.szwVal);
+        else if (rec->fields[i].type == MSIFIELD_STREAM)
+            IStream_Release(rec->fields[i].u.stream);
+    }
+
+    midl_user_free(rec);
+}
diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c
index 8a0a20a..479cb93 100644
--- a/dlls/msi/tests/custom.c
+++ b/dlls/msi/tests/custom.c
@@ -243,7 +243,9 @@ static void test_props(MSIHANDLE hinst)
 
 static void test_db(MSIHANDLE hinst)
 {
-    MSIHANDLE hdb, view, rec;
+    MSIHANDLE hdb, view, rec, rec2;
+    char buffer[10];
+    DWORD sz;
     UINT r;
 
     hdb = MsiGetActiveDatabase(hinst);
@@ -264,6 +266,56 @@ static void test_db(MSIHANDLE hinst)
     r = MsiViewExecute(view, 0);
     ok(hinst, !r, "got %u\n", r);
 
+    r = MsiViewFetch(view, &rec2);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiRecordGetFieldCount(rec2);
+    ok(hinst, r == 3, "got %u\n", r);
+
+    sz = sizeof(buffer);
+    r = MsiRecordGetStringA(rec2, 1, buffer, &sz);
+    ok(hinst, !r, "got %u\n", r);
+    ok(hinst, sz == strlen(buffer), "got size %u\n", sz);
+    ok(hinst, !strcmp(buffer, "one"), "got '%s'\n", buffer);
+
+    r = MsiRecordGetInteger(rec2, 2);
+    ok(hinst, r == 1, "got %d\n", r);
+
+    sz = sizeof(buffer);
+    r = MsiRecordReadStream(rec2, 3, buffer, &sz);
+    ok(hinst, !r, "got %u\n", r);
+    ok(hinst, !memcmp(buffer, "unus", 4), "wrong data\n");
+
+    r = MsiCloseHandle(rec2);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiViewFetch(view, &rec2);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiRecordGetFieldCount(rec2);
+    ok(hinst, r == 3, "got %u\n", r);
+
+    sz = sizeof(buffer);
+    r = MsiRecordGetStringA(rec2, 1, buffer, &sz);
+    ok(hinst, !r, "got %u\n", r);
+    ok(hinst, sz == strlen(buffer), "got size %u\n", sz);
+    ok(hinst, !strcmp(buffer, "two"), "got '%s'\n", buffer);
+
+    r = MsiRecordGetInteger(rec2, 2);
+    ok(hinst, r == 2, "got %d\n", r);
+
+    sz = sizeof(buffer);
+    r = MsiRecordReadStream(rec2, 3, buffer, &sz);
+    ok(hinst, !r, "got %u\n", r);
+    ok(hinst, !memcmp(buffer, "duo", 3), "wrong data\n");
+
+    r = MsiCloseHandle(rec2);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiViewFetch(view, &rec2);
+    ok(hinst, r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
+    ok(hinst, !rec2, "got %u\n", rec2);
+
     r = MsiCloseHandle(view);
     ok(hinst, !r, "got %u\n", r);
 
@@ -276,6 +328,19 @@ static void test_db(MSIHANDLE hinst)
     r = MsiViewExecute(view, rec);
     ok(hinst, !r, "got %u\n", r);
 
+    r = MsiViewFetch(view, &rec2);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiRecordGetInteger(rec2, 2);
+    ok(hinst, r == 1, "got %d\n", r);
+
+    r = MsiCloseHandle(rec2);
+    ok(hinst, !r, "got %u\n", r);
+
+    r = MsiViewFetch(view, &rec2);
+    ok(hinst, r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
+    ok(hinst, !rec2, "got %u\n", rec2);
+
     r = MsiCloseHandle(rec);
     ok(hinst, !r, "got %u\n", r);
 
diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl
index e698f76..b892f34 100644
--- a/dlls/msi/winemsi.idl
+++ b/dlls/msi/winemsi.idl
@@ -57,6 +57,7 @@ struct wire_record {
 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 );
 
     MSICONDITION remote_DatabaseIsTablePersistent( [in] MSIHANDLE db, [in] LPCWSTR table );
     HRESULT remote_DatabaseGetPrimaryKeys( [in] MSIHANDLE db, [in] LPCWSTR table, [out] MSIHANDLE *keys );
-- 
2.7.4




More information about the wine-devel mailing list