From 35a6782d7ba96d73874356d365fdaaa225fdef9a Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Mon, 5 Nov 2007 04:35:13 -0500 Subject: [PATCH] msi: Test and implement the MSIMODIFY_DELETE command. --- dlls/msi/msiquery.c | 7 +++- dlls/msi/table.c | 25 +++++++++--- dlls/msi/tests/db.c | 99 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 7 deletions(-) diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index af14ae570b9..76e43d091ec 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -567,6 +567,7 @@ UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hR UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec ) { MSIVIEW *view = NULL; + UINT r; if ( !query || !rec ) return ERROR_INVALID_HANDLE; @@ -575,7 +576,11 @@ UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec ) if ( !view || !view->ops->modify) return ERROR_FUNCTION_FAILED; - return view->ops->modify( view, mode, rec, query->row ); + r = view->ops->modify( view, mode, rec, query->row ); + if (mode == MSIMODIFY_DELETE && r == ERROR_SUCCESS) + query->row--; + + return r; } UINT WINAPI MsiViewModify( MSIHANDLE hView, MSIMODIFY eModifyMode, diff --git a/dlls/msi/table.c b/dlls/msi/table.c index a8170982451..117c8364c4d 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -1518,8 +1518,7 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temp static UINT TABLE_delete_row( struct tagMSIVIEW *view, UINT row ) { MSITABLEVIEW *tv = (MSITABLEVIEW*)view; - UINT r, num_rows, num_cols; - BYTE *src, *dest; + UINT r, num_rows, num_cols, i; TRACE("%p %d\n", tv, row); @@ -1538,9 +1537,9 @@ static UINT TABLE_delete_row( struct tagMSIVIEW *view, UINT row ) if ( row == num_rows - 1 ) return ERROR_SUCCESS; - dest = tv->table->data[row]; - src = tv->table->data[row + 1]; - memmove(dest, src, (num_rows - row - 1) * tv->row_size); + for (i = row + 1; i < num_rows; i++) + memcpy(tv->table->data[i - 1], tv->table->data[i], tv->row_size); + return ERROR_SUCCESS; } @@ -1570,6 +1569,18 @@ static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1); } +static UINT modify_delete_row( struct tagMSIVIEW *view, MSIRECORD *rec ) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW *)view; + UINT row, r; + + r = msi_table_find_row(tv, rec, &row); + if (r != ERROR_SUCCESS) + return r; + + return TABLE_delete_row(view, row); +} + static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row) { @@ -1580,6 +1591,9 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, switch (eModifyMode) { + case MSIMODIFY_DELETE: + r = modify_delete_row( view, rec ); + break; case MSIMODIFY_VALIDATE_NEW: r = table_validate_new( tv, rec ); break; @@ -1600,7 +1614,6 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, case MSIMODIFY_ASSIGN: case MSIMODIFY_REPLACE: case MSIMODIFY_MERGE: - case MSIMODIFY_DELETE: case MSIMODIFY_VALIDATE: case MSIMODIFY_VALIDATE_FIELD: case MSIMODIFY_VALIDATE_DELETE: diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 8e96d77afcd..a1055e3f735 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -4354,6 +4354,104 @@ static void test_stringtable(void) DeleteFileA(msifile); } +static void test_viewmodify_delete(void) +{ + MSIHANDLE hdb = 0, hview = 0, hrec = 0; + UINT r; + const char *query; + char buffer[0x100]; + DWORD sz; + + DeleteFile(msifile); + + /* just MsiOpenDatabase should not create a file */ + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + 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(hdb, 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(hdb, 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(hdb, 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(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "SELECT * FROM `phone` WHERE `id` <= 2"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + /* delete 1 */ + r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + /* delete 2 */ + r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "SELECT * FROM `phone`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 3, "Expected 3, got %d\n", r); + + sz = sizeof(buffer); + r = MsiRecordGetString(hrec, 2, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer); + + sz = sizeof(buffer); + r = MsiRecordGetString(hrec, 3, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiCloseHandle(hdb); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); +} + START_TEST(db) { test_msidatabase(); @@ -4380,4 +4478,5 @@ START_TEST(db) test_select_markers(); test_viewmodify_update(); test_stringtable(); + test_viewmodify_delete(); }