https://git.reactos.org/?p=reactos.git;a=commitdiff;h=795da5286b33e47849f15…
commit 795da5286b33e47849f15528dbb17ce36df3f2e2
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Sat Mar 12 15:11:54 2022 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Mar 20 19:27:37 2022 +0100
[WINESYNC] msi: Make MsiViewFetch() RPC-compatible.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
wine commit id 39c116fd0c0aca6517b9c1f31296bf8665cf7834 by Zebediah Figura
<z.figura12(a)gmail.com>
---
dll/win32/msi/msipriv.h | 2 +
dll/win32/msi/msiquery.c | 29 +++++++++++++-
dll/win32/msi/record.c | 55 +++++++++++++++++++++++++++
dll/win32/msi/winemsi.idl | 1 +
modules/rostests/winetests/msi/custom.c | 67 ++++++++++++++++++++++++++++++++-
5 files changed, 151 insertions(+), 3 deletions(-)
diff --git a/dll/win32/msi/msipriv.h b/dll/win32/msi/msipriv.h
index cc2b8bec790..936ed4d7241 100644
--- a/dll/win32/msi/msipriv.h
+++ b/dll/win32/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/dll/win32/msi/msiquery.c b/dll/win32/msi/msiquery.c
index bfc239a53d5..6eddf7a8219 100644
--- a/dll/win32/msi/msiquery.c
+++ b/dll/win32/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/dll/win32/msi/record.c b/dll/win32/msi/record.c
index 4c504eac472..91892d7377f 100644
--- a/dll/win32/msi/record.c
+++ b/dll/win32/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/dll/win32/msi/winemsi.idl b/dll/win32/msi/winemsi.idl
index e698f76e202..b892f34bfea 100644
--- a/dll/win32/msi/winemsi.idl
+++ b/dll/win32/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 );
diff --git a/modules/rostests/winetests/msi/custom.c
b/modules/rostests/winetests/msi/custom.c
index 8a0a20aff05..479cb930de4 100644
--- a/modules/rostests/winetests/msi/custom.c
+++ b/modules/rostests/winetests/msi/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);