Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/msi/tests/db.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
Rationale: apparantly some crappy Wix installers iterate over a MSI view *twice*, without calling MsiViewExecute before each iteration.
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index b42cc90a955..7999531b03e 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -9293,6 +9293,88 @@ static void test_view_get_error(void) DeleteFileA(msifile); }
+static void test_viewfetch_rollover(void) +{ + MSIHANDLE db = 0, view = 0, rec = 0; + UINT r, i, idset, tries; + const char *query; + + DeleteFileA(msifile); + + /* just MsiOpenDatabase should not create a file */ + r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &db ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + query = "CREATE TABLE `phone` ( " + "`id` INT, `name` CHAR(32), `number` CHAR(32) " + "PRIMARY KEY `id`)"; + r = run_query( db, 0, query ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + query = "INSERT INTO `phone` ( `id`, `name`, `number` )" + "VALUES('1', 'Alan', '5030581')"; + r = run_query( db, 0, query ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + query = "INSERT INTO `phone` ( `id`, `name`, `number` )" + "VALUES('2', 'Barry', '928440')"; + r = run_query( db, 0, query ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + query = "INSERT INTO `phone` ( `id`, `name`, `number` )" + "VALUES('3', 'Cindy', '2937550')"; + r = run_query( db, 0, query ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + query = "SELECT * FROM `phone`"; + r = MsiDatabaseOpenViewA( db, query, &view ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + r = MsiViewExecute( view, 0 ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + + for (tries = 0; tries < 3; tries++) + { + winetest_push_context( "Rollover attempt #%d", tries ); + idset = 0; + + for (i = 0; i < 3; i++) + { + winetest_push_context( "Record #%d", i ); + + r = MsiViewFetch( view, &rec ); + todo_wine_if(tries > 0) ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + if (r != ERROR_SUCCESS) + { + winetest_pop_context(); + break; + } + + r = MsiRecordGetInteger(rec, 1); + ok(r >= 1 && r <= 3, "Expected 1 <= id <= 3, got %d\n", r); + if (r < sizeof(idset) * 8) + { + ok(!(idset & (1 << r)), "Duplicate id %d\n", r); + idset |= 1 << r; + } + + MsiCloseHandle(rec); + + winetest_pop_context(); + } + + r = MsiViewFetch(view, &rec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + winetest_pop_context(); + } + + MsiViewClose(view); + MsiCloseHandle(view); + MsiCloseHandle(db); + DeleteFileA(msifile); +} + START_TEST(db) { test_msidatabase(); @@ -9352,4 +9434,5 @@ START_TEST(db) test_viewmodify_merge(); test_viewmodify_insert(); test_view_get_error(); + test_viewfetch_rollover(); }
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/msi/msiquery.c | 5 +++++ dlls/msi/tests/db.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
Rationale: apparantly some crappy Wix installers iterate over a MSI view *twice*, without calling MsiViewExecute before each iteration.
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index c217ee7c8f5..b3a499a0788 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -394,6 +394,11 @@ UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec) (*prec)->cookie = (UINT64)(ULONG_PTR)query; MSI_RecordSetInteger(*prec, 0, 1); } + else if (r == ERROR_NO_MORE_ITEMS) + { + /* end of view; reset cursor to first row */ + query->row = 0; + }
return r; } diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 7999531b03e..03ad4d75651 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -9343,7 +9343,7 @@ static void test_viewfetch_rollover(void) winetest_push_context( "Record #%d", i );
r = MsiViewFetch( view, &rec ); - todo_wine_if(tries > 0) ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); + ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); if (r != ERROR_SUCCESS) { winetest_pop_context();
On 11/28/21 10:51, Jinoh Kang wrote:
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
Change subject to
msi: Let MSI_ViewFetch roll over to first record on ERROR_NO_MORE_ITEMS.
dlls/msi/msiquery.c | 5 +++++ dlls/msi/tests/db.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
Rationale: apparantly some crappy Wix installers iterate over a MSI view *twice*, without calling MsiViewExecute before each iteration.
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index c217ee7c8f5..b3a499a0788 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -394,6 +394,11 @@ UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec) (*prec)->cookie = (UINT64)(ULONG_PTR)query; MSI_RecordSetInteger(*prec, 0, 1); }
else if (r == ERROR_NO_MORE_ITEMS)
{
/* end of view; reset cursor to first row */
query->row = 0;
}
return r;
} diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 7999531b03e..03ad4d75651 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -9343,7 +9343,7 @@ static void test_viewfetch_rollover(void) winetest_push_context( "Record #%d", i );
r = MsiViewFetch( view, &rec );
todo_wine_if(tries > 0) ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); if (r != ERROR_SUCCESS) { winetest_pop_context();