Test for a class that Wine actually supports, and also make sure our apartment is uninitialized.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/custom.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 9cf90dc..8d32348 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -24,8 +24,7 @@ #include <windef.h> #include <winbase.h> #define COBJMACROS -#include <objbase.h> -#include <unknwn.h> +#include <msxml.h> #include <msi.h> #include <msiquery.h>
@@ -248,14 +247,19 @@ UINT WINAPI main_test(MSIHANDLE hinst) { UINT res; IUnknown *unk = NULL; - HRESULT hres; + HRESULT hr;
/* Test for an MTA apartment */ - hres = CoCreateInstance(&CLSID_Picture_Metafile, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); - todo_wine_ok(hinst, hres == S_OK, "CoCreateInstance failed with %08x\n", hres); + hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); + todo_wine_ok(hinst, hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
if (unk) IUnknown_Release(unk);
+ /* but ours is uninitialized */ + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(hinst, hr == S_OK, "got %#x\n", hr); + CoUninitialize(); + /* Test MsiGetDatabaseState() */ res = MsiGetDatabaseState(hinst); todo_wine_ok(hinst, res == MSIDBSTATE_ERROR, "expected MSIDBSTATE_ERROR, got %u\n", res);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/package.c | 9 ++++----- dlls/msi/tests/custom.c | 13 +++++++++++++ dlls/msi/winemsi.idl | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/dlls/msi/package.c b/dlls/msi/package.c index e7f51a6..d18736b 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -1686,7 +1686,8 @@ MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) } else if ((remote = msi_get_remote(hInstall))) { - remote_GetActiveDatabase(remote, &handle); + handle = remote_GetActiveDatabase(remote); + handle = alloc_msi_remote_handle(handle); }
return handle; @@ -2420,11 +2421,9 @@ UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); }
-HRESULT __cdecl remote_GetActiveDatabase(MSIHANDLE hinst, MSIHANDLE *handle) +MSIHANDLE __cdecl remote_GetActiveDatabase(MSIHANDLE hinst) { - *handle = MsiGetActiveDatabase(hinst); - - return S_OK; + return MsiGetActiveDatabase(hinst); }
UINT __cdecl remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 8d32348..00dcab3 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -241,6 +241,18 @@ static void test_props(MSIHANDLE hinst) ok(hinst, !memcmp(buffer, "a\0\0\0\xcc", 5), "wrong data\n"); }
+static void test_db(MSIHANDLE hinst) +{ + MSIHANDLE hdb; + UINT r; + + hdb = MsiGetActiveDatabase(hinst); + ok(hinst, hdb, "MsiGetActiveDatabase failed\n"); + + r = MsiCloseHandle(hdb); + ok(hinst, !r, "got %u\n", r); +} + /* 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) @@ -265,6 +277,7 @@ UINT WINAPI main_test(MSIHANDLE hinst) todo_wine_ok(hinst, res == MSIDBSTATE_ERROR, "expected MSIDBSTATE_ERROR, got %u\n", res);
test_props(hinst); + test_db(hinst);
return ERROR_SUCCESS; } diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index d97db4c..c158583 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -61,7 +61,7 @@ interface IWineMsiRemote HRESULT remote_DatabaseGetSummaryInformation( [in] MSIHANDLE db, [in] UINT updatecount, [out] MSIHANDLE *suminfo ); HRESULT remote_DatabaseOpenView( [in] MSIHANDLE db, [in] LPCWSTR query, [out] MSIHANDLE *view );
- HRESULT remote_GetActiveDatabase( [in] MSIHANDLE hinst, [out] MSIHANDLE *handle ); + MSIHANDLE remote_GetActiveDatabase( [in] MSIHANDLE hinst ); UINT remote_GetProperty( [in] MSIHANDLE hinst, [in, string] LPCWSTR property, [out, string] LPWSTR *value, [out] DWORD *size ); UINT remote_SetProperty( [in] MSIHANDLE hinst, [in, string, unique] LPCWSTR property, [in, string, unique] LPCWSTR value ); int remote_ProcessMessage( [in] MSIHANDLE hinst, [in] INSTALLMESSAGE message, [in] struct wire_record *record );
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37802
Your paranoid android.
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/database.c | 5 ++--- dlls/msi/msiquery.c | 9 +-------- dlls/msi/tests/custom.c | 3 +++ dlls/msi/tests/install.c | 16 ++++++++++++++++ dlls/msi/winemsi.idl | 2 +- 5 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/dlls/msi/database.c b/dlls/msi/database.c index d3eb910..c1309a5 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -1906,10 +1906,9 @@ MSIDBSTATE WINAPI MsiGetDatabaseState( MSIHANDLE handle ) return ret; }
-HRESULT __cdecl remote_DatabaseIsTablePersistent(MSIHANDLE db, LPCWSTR table, MSICONDITION *persistent) +MSICONDITION __cdecl remote_DatabaseIsTablePersistent(MSIHANDLE db, LPCWSTR table) { - *persistent = MsiDatabaseIsTablePersistentW(db, table); - return S_OK; + return MsiDatabaseIsTablePersistentW(db, table); }
HRESULT __cdecl remote_DatabaseGetPrimaryKeys(MSIHANDLE db, LPCWSTR table, MSIHANDLE *keys) diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index 1ba3076..fb99c96 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -1024,19 +1024,12 @@ MSICONDITION WINAPI MsiDatabaseIsTablePersistentW( db = msihandle2msiinfo( hDatabase, MSIHANDLETYPE_DATABASE ); if( !db ) { - HRESULT hr; - MSICONDITION condition; MSIHANDLE remote;
if (!(remote = msi_get_remote(hDatabase))) return MSICONDITION_ERROR;
- hr = remote_DatabaseIsTablePersistent(remote, szTableName, &condition); - - if (FAILED(hr)) - return MSICONDITION_ERROR; - - return condition; + return remote_DatabaseIsTablePersistent(remote, szTableName); }
r = MSI_DatabaseIsTablePersistent( db, szTableName ); diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 00dcab3..0756994 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -249,6 +249,9 @@ static void test_db(MSIHANDLE hinst) hdb = MsiGetActiveDatabase(hinst); ok(hinst, hdb, "MsiGetActiveDatabase failed\n");
+ r = MsiDatabaseIsTablePersistentA(hdb, "Test"); + ok(hinst, r == MSICONDITION_TRUE, "got %u\n", r); + r = MsiCloseHandle(hdb); ok(hinst, !r, "got %u\n", r); } diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 62fb81f..41a77cd 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -4108,11 +4108,25 @@ static INT CALLBACK ok_callback(void *context, UINT message_type, MSIHANDLE reco
static void test_customaction1(void) { + MSIHANDLE hdb, record; UINT r;
create_database(msifile, ca1_tables, sizeof(ca1_tables) / sizeof(msi_table)); add_custom_dll();
+ /* create a test table */ + MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb); + run_query(hdb, 0, "CREATE TABLE `Test` (`Name` CHAR(10), `Number` INTEGER, `Data` OBJECT PRIMARY KEY `Name`)"); + create_file("unus", 10); + create_file("duo", 10); + record = MsiCreateRecord(1); + MsiRecordSetStreamA(record, 1, "unus"); + run_query(hdb, record, "INSERT INTO `Test` (`Name`, `Number`, `Data`) VALUES ('one', 1, ?)"); + MsiRecordSetStreamA(record, 1, "duo"); + run_query(hdb, record, "INSERT INTO `Test` (`Name`, `Number`, `Data`) VALUES ('two', 2, ?)"); + MsiDatabaseCommit(hdb); + MsiCloseHandle(hdb); + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
r = MsiInstallProductA(msifile, "MAIN_TEST=1"); @@ -4136,6 +4150,8 @@ static void test_customaction1(void) ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
DeleteFileA(msifile); + DeleteFileA("unus"); + DeleteFileA("duo"); }
static void test_customaction51(void) diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index c158583..86f03e3 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -56,7 +56,7 @@ struct wire_record { ] interface IWineMsiRemote { - HRESULT remote_DatabaseIsTablePersistent( [in] MSIHANDLE db, [in] LPCWSTR table, [out] MSICONDITION *persistent ); + MSICONDITION remote_DatabaseIsTablePersistent( [in] MSIHANDLE db, [in] LPCWSTR table ); HRESULT remote_DatabaseGetPrimaryKeys( [in] MSIHANDLE db, [in] LPCWSTR table, [out] MSIHANDLE *keys ); HRESULT remote_DatabaseGetSummaryInformation( [in] MSIHANDLE db, [in] UINT updatecount, [out] MSIHANDLE *suminfo ); HRESULT remote_DatabaseOpenView( [in] MSIHANDLE db, [in] LPCWSTR query, [out] MSIHANDLE *view );
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37803
Your paranoid android.
=== w7pro64 (32 bit custom) === The previous 1 run(s) terminated abnormally
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/database.c | 5 ++--- dlls/msi/msiquery.c | 27 +++++++++++---------------- dlls/msi/tests/custom.c | 14 +++++++++++++- dlls/msi/winemsi.idl | 2 +- 4 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/dlls/msi/database.c b/dlls/msi/database.c index c1309a5..c1cf493 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -1923,8 +1923,7 @@ HRESULT __cdecl remote_DatabaseGetSummaryInformation(MSIHANDLE db, UINT updateco return HRESULT_FROM_WIN32(r); }
-HRESULT __cdecl remote_DatabaseOpenView(MSIHANDLE db, LPCWSTR query, MSIHANDLE *view) +UINT __cdecl remote_DatabaseOpenView(MSIHANDLE db, LPCWSTR query, MSIHANDLE *view) { - UINT r = MsiDatabaseOpenViewW(db, query, view); - return HRESULT_FROM_WIN32(r); + return MsiDatabaseOpenViewW(db, query, view); } diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index fb99c96..9518c59 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -116,9 +116,6 @@ UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
TRACE("%s %p\n", debugstr_w(szQuery), pView);
- if( !szQuery) - return ERROR_INVALID_PARAMETER; - /* pre allocate a handle to hold a pointer to the view */ query = alloc_msiobject( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY), MSI_CloseView ); @@ -247,26 +244,24 @@ UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
TRACE("%s %p\n", debugstr_w(szQuery), phView);
+ if (!phView) + return ERROR_INVALID_PARAMETER; + + if (!szQuery) + return ERROR_BAD_QUERY_SYNTAX; + db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE ); if( !db ) { - MSIHANDLE remote; - HRESULT hr; + MSIHANDLE remote, remote_view;
if (!(remote = msi_get_remote(hdb))) return ERROR_INVALID_HANDLE;
- hr = remote_DatabaseOpenView(remote, szQuery, phView); - - if (FAILED(hr)) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - return HRESULT_CODE(hr); - - return ERROR_FUNCTION_FAILED; - } - - return ERROR_SUCCESS; + ret = remote_DatabaseOpenView(remote, szQuery, &remote_view); + if (!ret) + *phView = alloc_msi_remote_handle(remote_view); + return ret; }
ret = MSI_DatabaseOpenViewW( db, szQuery, &query ); diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 0756994..e7a56ae 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -243,7 +243,7 @@ static void test_props(MSIHANDLE hinst)
static void test_db(MSIHANDLE hinst) { - MSIHANDLE hdb; + MSIHANDLE hdb, view; UINT r;
hdb = MsiGetActiveDatabase(hinst); @@ -252,6 +252,18 @@ static void test_db(MSIHANDLE hinst) r = MsiDatabaseIsTablePersistentA(hdb, "Test"); ok(hinst, r == MSICONDITION_TRUE, "got %u\n", r);
+ r = MsiDatabaseOpenViewA(hdb, NULL, &view); + ok(hinst, r == ERROR_BAD_QUERY_SYNTAX, "got %u\n", r); + + r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test`", NULL); + ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test`", &view); + ok(hinst, !r, "got %u\n", r); + + r = MsiCloseHandle(view); + ok(hinst, !r, "got %u\n", r); + r = MsiCloseHandle(hdb); ok(hinst, !r, "got %u\n", r); } diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index 86f03e3..54e6eb8 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -59,7 +59,7 @@ interface IWineMsiRemote MSICONDITION remote_DatabaseIsTablePersistent( [in] MSIHANDLE db, [in] LPCWSTR table ); HRESULT remote_DatabaseGetPrimaryKeys( [in] MSIHANDLE db, [in] LPCWSTR table, [out] MSIHANDLE *keys ); HRESULT remote_DatabaseGetSummaryInformation( [in] MSIHANDLE db, [in] UINT updatecount, [out] MSIHANDLE *suminfo ); - HRESULT remote_DatabaseOpenView( [in] MSIHANDLE db, [in] LPCWSTR query, [out] MSIHANDLE *view ); + UINT remote_DatabaseOpenView( [in] MSIHANDLE db, [in, string] LPCWSTR query, [out] MSIHANDLE *view );
MSIHANDLE remote_GetActiveDatabase( [in] MSIHANDLE hinst ); UINT remote_GetProperty( [in] MSIHANDLE hinst, [in, string] LPCWSTR property, [out, string] LPWSTR *value, [out] DWORD *size );
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37804
Your paranoid android.
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/msiquery.c | 39 ++++++++++++++++++++++++++++++--------- dlls/msi/record.c | 6 ++++++ dlls/msi/tests/custom.c | 20 +++++++++++++++++++- dlls/msi/winemsi.idl | 2 ++ 4 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index 9518c59..bfc239a 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -458,25 +458,32 @@ UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
TRACE("%d %d\n", hView, hRec);
- query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW ); - if( !query ) - return ERROR_INVALID_HANDLE; - if( hRec ) { rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD ); if( !rec ) - { - ret = ERROR_INVALID_HANDLE; - goto out; - } + return ERROR_INVALID_HANDLE; + } + + query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW ); + if( !query ) + { + MSIHANDLE remote; + + if (!(remote = msi_get_remote(hView))) + return ERROR_INVALID_HANDLE; + + ret = remote_ViewExecute(remote, rec ? (struct wire_record *)&rec->count : NULL); + + if (rec) + msiobj_release(&rec->hdr); + return ret; }
msiobj_lock( &rec->hdr ); ret = MSI_ViewExecute( query, rec ); msiobj_unlock( &rec->hdr );
-out: msiobj_release( &query->hdr ); if( rec ) msiobj_release( &rec->hdr ); @@ -1033,3 +1040,17 @@ MSICONDITION WINAPI MsiDatabaseIsTablePersistentW(
return r; } + +UINT __cdecl remote_ViewExecute(MSIHANDLE view, struct wire_record *remote_rec) +{ + MSIHANDLE rec = 0; + UINT r; + + if ((r = unmarshal_record(remote_rec, &rec))) + return r; + + r = MsiViewExecute(view, rec); + + MsiCloseHandle(rec); + return r; +} diff --git a/dlls/msi/record.c b/dlls/msi/record.c index 7b53d86..4c504ea 100644 --- a/dlls/msi/record.c +++ b/dlls/msi/record.c @@ -1061,6 +1061,12 @@ UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out) unsigned int i; UINT r;
+ if (!in) + { + *out = 0; + return ERROR_SUCCESS; + } + rec = MSI_CreateRecord(in->count); if (!rec) return ERROR_OUTOFMEMORY;
diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index e7a56ae..8a0a20a 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -243,7 +243,7 @@ static void test_props(MSIHANDLE hinst)
static void test_db(MSIHANDLE hinst) { - MSIHANDLE hdb, view; + MSIHANDLE hdb, view, rec; UINT r;
hdb = MsiGetActiveDatabase(hinst); @@ -261,6 +261,24 @@ static void test_db(MSIHANDLE hinst) r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test`", &view); ok(hinst, !r, "got %u\n", r);
+ r = MsiViewExecute(view, 0); + ok(hinst, !r, "got %u\n", r); + + r = MsiCloseHandle(view); + ok(hinst, !r, "got %u\n", r); + + r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test` WHERE `Name` = ?", &view); + ok(hinst, !r, "got %u\n", r); + + rec = MsiCreateRecord(1); + MsiRecordSetStringA(rec, 1, "one"); + + r = MsiViewExecute(view, rec); + ok(hinst, !r, "got %u\n", r); + + r = MsiCloseHandle(rec); + ok(hinst, !r, "got %u\n", r); + r = MsiCloseHandle(view); ok(hinst, !r, "got %u\n", r);
diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index 54e6eb8..e698f76 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -56,6 +56,8 @@ struct wire_record { ] interface IWineMsiRemote { + UINT remote_ViewExecute( [in] MSIHANDLE view, [in, unique] 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 ); HRESULT remote_DatabaseGetSummaryInformation( [in] MSIHANDLE db, [in] UINT updatecount, [out] MSIHANDLE *suminfo );
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37805
Your paranoid android.
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@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 );
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37806
Your paranoid android.
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37801
Your paranoid android.
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally