Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/alter.c | 1 + dlls/msi/create.c | 1 + dlls/msi/delete.c | 1 + dlls/msi/distinct.c | 1 + dlls/msi/drop.c | 1 + dlls/msi/insert.c | 1 + dlls/msi/msipriv.h | 7 +++++++ dlls/msi/select.c | 7 +++++-- dlls/msi/storages.c | 41 +++++++++++++++++++++++++++++++++++++++++ dlls/msi/streams.c | 14 ++++++++++++++ dlls/msi/table.c | 17 +++++++++++++++++ dlls/msi/update.c | 1 + dlls/msi/where.c | 21 +++++++++++++++++++++ 13 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c index d1a481ebfc..5c5893c824 100644 --- a/dlls/msi/alter.c +++ b/dlls/msi/alter.c @@ -221,6 +221,7 @@ static const MSIVIEWOPS alter_ops = NULL, NULL, NULL, + NULL, ALTER_execute, ALTER_close, ALTER_get_dimensions, diff --git a/dlls/msi/create.c b/dlls/msi/create.c index 3c00b70c53..2777954aa7 100644 --- a/dlls/msi/create.c +++ b/dlls/msi/create.c @@ -131,6 +131,7 @@ static const MSIVIEWOPS create_ops = NULL, NULL, NULL, + NULL, CREATE_execute, CREATE_close, CREATE_get_dimensions, diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c index e2e0e34678..81bd9d7db2 100644 --- a/dlls/msi/delete.c +++ b/dlls/msi/delete.c @@ -173,6 +173,7 @@ static const MSIVIEWOPS delete_ops = NULL, NULL, NULL, + NULL, DELETE_execute, DELETE_close, DELETE_get_dimensions, diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c index 5bd5bf8676..e102adb3de 100644 --- a/dlls/msi/distinct.c +++ b/dlls/msi/distinct.c @@ -256,6 +256,7 @@ static const MSIVIEWOPS distinct_ops = NULL, NULL, NULL, + NULL, DISTINCT_execute, DISTINCT_close, DISTINCT_get_dimensions, diff --git a/dlls/msi/drop.c b/dlls/msi/drop.c index 60a9202106..89fac9dfc7 100644 --- a/dlls/msi/drop.c +++ b/dlls/msi/drop.c @@ -101,6 +101,7 @@ static const MSIVIEWOPS drop_ops = NULL, NULL, NULL, + NULL, DROP_execute, DROP_close, DROP_get_dimensions, diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c index ed913c034c..f1185eebae 100644 --- a/dlls/msi/insert.c +++ b/dlls/msi/insert.c @@ -327,6 +327,7 @@ static const MSIVIEWOPS insert_ops = NULL, NULL, NULL, + NULL, INSERT_execute, INSERT_close, INSERT_get_dimensions, diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 3ff5ac2350..e4d2a625f7 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -256,6 +256,13 @@ typedef struct tagMSIVIEWOPS */ UINT (*set_string)( struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len );
+ /* + * set_stream - set the stream value at {row, col} + * This function has undefined behaviour if the column does not contain + * streams. + */ + UINT (*set_stream)( struct tagMSIVIEW *view, UINT row, UINT col, IStream *stream ); + /* * set_row - sets values in a row as specified by mask * diff --git a/dlls/msi/select.c b/dlls/msi/select.c index c6e7b20903..9d3d887f56 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -234,6 +234,7 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view; UINT r, i, col, type, val; + IStream *stream; LPCWSTR str;
for (i = 0; i < sv->num_cols; i++) @@ -249,8 +250,9 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
if (MSITYPE_IS_BINARY(type)) { - ERR("Cannot modify binary data!\n"); - return ERROR_FUNCTION_FAILED; + if (MSI_RecordGetIStream(rec, i + 1, &stream)) + return ERROR_FUNCTION_FAILED; + r = sv->table->ops->set_stream(sv->table, row, col, stream); } else if (type & MSITYPE_STRING) { @@ -311,6 +313,7 @@ static const MSIVIEWOPS select_ops = SELECT_fetch_stream, NULL, NULL, + NULL, SELECT_set_row, SELECT_insert_row, NULL, diff --git a/dlls/msi/storages.c b/dlls/msi/storages.c index 76a0e2e03f..521b6e89e8 100644 --- a/dlls/msi/storages.c +++ b/dlls/msi/storages.c @@ -153,6 +153,46 @@ done: return hr; }
+static UINT STORAGES_set_stream( MSIVIEW *view, UINT row, UINT col, IStream *stream ) +{ + MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view; + IStorage *stg, *substg, *prev; + const WCHAR *name; + HRESULT hr; + UINT r; + + TRACE("view %p, row %u, col %u, stream %p.\n", view, row, col, stream); + + if ((r = stream_to_storage(stream, &stg))) + return r; + + name = msi_string_lookup(sv->db->strings, sv->storages[row].str_index, NULL); + + hr = IStorage_CreateStorage(sv->db->storage, name, + STGM_WRITE | STGM_SHARE_EXCLUSIVE, + 0, 0, &substg); + if (FAILED(hr)) + { + IStorage_Release(stg); + return ERROR_FUNCTION_FAILED; + } + + hr = IStorage_CopyTo(stg, 0, NULL, NULL, substg); + if (FAILED(hr)) + { + IStorage_Release(substg); + IStorage_Release(stg); + return ERROR_FUNCTION_FAILED; + } + IStorage_Release(substg); + + prev = sv->storages[row].storage; + sv->storages[row].storage = stg; + if (prev) IStorage_Release(prev); + + return ERROR_SUCCESS; +} + static UINT STORAGES_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) { MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view; @@ -404,6 +444,7 @@ static const MSIVIEWOPS storages_ops = STORAGES_fetch_stream, NULL, STORAGES_set_string, + STORAGES_set_stream, STORAGES_set_row, STORAGES_insert_row, STORAGES_delete_row, diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index 2d458adb68..bc02fb2bac 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -110,6 +110,19 @@ static UINT STREAMS_set_string( struct tagMSIVIEW *view, UINT row, UINT col, con return ERROR_FUNCTION_FAILED; }
+static UINT STREAMS_set_stream( MSIVIEW *view, UINT row, UINT col, IStream *stream ) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + IStream *prev; + + TRACE("view %p, row %u, col %u, stream %p.\n", view, row, col, stream); + + prev = sv->db->streams[row].stream; + IStream_AddRef(sv->db->streams[row].stream = stream); + if (prev) IStream_Release(prev); + return ERROR_SUCCESS; +} + static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) { MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; @@ -340,6 +353,7 @@ static const MSIVIEWOPS streams_ops = STREAMS_fetch_stream, NULL, STREAMS_set_string, + STREAMS_set_stream, STREAMS_set_row, STREAMS_insert_row, STREAMS_delete_row, diff --git a/dlls/msi/table.c b/dlls/msi/table.c index f26ab9f5b4..a2b83e27de 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -1357,6 +1357,22 @@ done: return r; }
+static UINT TABLE_set_stream( MSIVIEW *view, UINT row, UINT col, IStream *stream ) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW *)view; + WCHAR *name; + UINT r; + + TRACE("row %u, col %u, stream %p.\n", row, col, stream); + + if ((r = get_stream_name( tv, row - 1, &name ))) + return r; + + r = add_stream( tv->db, name, stream ); + msi_free( name ); + return r; +} + static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT iField, UINT *pvalue ) { MSICOLUMNINFO columninfo; @@ -2126,6 +2142,7 @@ static const MSIVIEWOPS table_ops = TABLE_fetch_stream, TABLE_set_int, TABLE_set_string, + TABLE_set_stream, TABLE_set_row, TABLE_insert_row, TABLE_delete_row, diff --git a/dlls/msi/update.c b/dlls/msi/update.c index af629d2236..e61342d11e 100644 --- a/dlls/msi/update.c +++ b/dlls/msi/update.c @@ -204,6 +204,7 @@ static const MSIVIEWOPS update_ops = NULL, NULL, NULL, + NULL, UPDATE_execute, UPDATE_close, UPDATE_get_dimensions, diff --git a/dlls/msi/where.c b/dlls/msi/where.c index eaadac4310..66de85bec9 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -299,6 +299,26 @@ static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const return table->view->ops->set_string(table->view, rows[table->table_index], col, val, len); }
+static UINT WHERE_set_stream(MSIVIEW *view, UINT row, UINT col, IStream *stream) +{ + MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; + JOINTABLE *table; + UINT *rows; + UINT r; + + TRACE("view %p, row %u, col %u, stream %p.\n", wv, row, col, stream); + + r = find_row(wv, row, &rows); + if (r != ERROR_SUCCESS) + return r; + + table = find_table(wv, col, &col); + if (!table) + return ERROR_FUNCTION_FAILED; + + return table->view->ops->set_stream(table->view, rows[table->table_index], col, stream); +} + static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) { MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; @@ -1098,6 +1118,7 @@ static const MSIVIEWOPS where_ops = WHERE_fetch_stream, WHERE_set_int, WHERE_set_string, + WHERE_set_stream, WHERE_set_row, NULL, WHERE_delete_row,
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/query.h | 2 ++ dlls/msi/select.c | 2 +- dlls/msi/update.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/msi/query.h b/dlls/msi/query.h index 063fbb9749..d79c14fd42 100644 --- a/dlls/msi/query.h +++ b/dlls/msi/query.h @@ -151,4 +151,6 @@ MSIRECORD *msi_query_merge_record( UINT fields, const column_info *vl, MSIRECORD UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info, MSICONDITION persistent ) DECLSPEC_HIDDEN;
+UINT msi_select_update( MSIVIEW *view, MSIRECORD *rec, UINT row ) DECLSPEC_HIDDEN; + #endif /* __WINE_MSI_QUERY_H */ diff --git a/dlls/msi/select.c b/dlls/msi/select.c index 9d3d887f56..ef16e5d09f 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -230,7 +230,7 @@ static UINT SELECT_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *na type, temporary, table_name ); }
-static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) +UINT msi_select_update(MSIVIEW *view, MSIRECORD *rec, UINT row) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view; UINT r, i, col, type, val; diff --git a/dlls/msi/update.c b/dlls/msi/update.c index e61342d11e..4aa03443f0 100644 --- a/dlls/msi/update.c +++ b/dlls/msi/update.c @@ -113,7 +113,7 @@ static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
for ( i=0; i<row_count; i++ ) { - r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 ); + r = msi_select_update( wv, values, i ); if (r != ERROR_SUCCESS) break; }
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/msiquery.c | 47 +++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-)
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index 30c4f655d3..bea08c2822 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -287,7 +287,7 @@ UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, return ret; }
-UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) +UINT msi_view_refresh_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD *rec) { UINT row_count = 0, col_count = 0, i, ival, ret, type;
@@ -300,13 +300,6 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) if (!col_count) return ERROR_INVALID_PARAMETER;
- if (row >= row_count) - return ERROR_NO_MORE_ITEMS; - - *rec = MSI_CreateRecord(col_count); - if (!*rec) - return ERROR_FUNCTION_FAILED; - for (i = 1; i <= col_count; i++) { ret = view->ops->get_column_info(view, i, NULL, &type, NULL, NULL); @@ -323,7 +316,7 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) ret = view->ops->fetch_stream(view, row, i, &stm); if ((ret == ERROR_SUCCESS) && stm) { - MSI_RecordSetIStream(*rec, i, stm); + MSI_RecordSetIStream(rec, i, stm); IStream_Release(stm); } else @@ -342,28 +335,48 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) if (! (type & MSITYPE_VALID)) ERR("Invalid type!\n");
- /* check if it's nul (0) - if so, don't set anything */ - if (!ival) - continue; - if (type & MSITYPE_STRING) { int len; - const WCHAR *sval = msi_string_lookup( db->strings, ival, &len ); - msi_record_set_string( *rec, i, sval, len ); + const WCHAR *sval = msi_string_lookup(db->strings, ival, &len); + msi_record_set_string(rec, i, sval, len); } else { if ((type & MSI_DATASIZEMASK) == 2) - MSI_RecordSetInteger(*rec, i, ival - (1<<15)); + MSI_RecordSetInteger(rec, i, ival ? ival - (1<<15) : MSI_NULL_INTEGER); else - MSI_RecordSetInteger(*rec, i, ival - (1u<<31)); + MSI_RecordSetInteger(rec, i, ival - (1u<<31)); } }
return ERROR_SUCCESS; }
+UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) +{ + UINT row_count = 0, col_count = 0, r; + MSIRECORD *object; + + TRACE("view %p, row %u, rec %p.\n", view, row, rec); + + if ((r = view->ops->get_dimensions(view, &row_count, &col_count))) + return r; + + if (row >= row_count) + return ERROR_NO_MORE_ITEMS; + + if (!(object = MSI_CreateRecord( col_count ))) + return ERROR_OUTOFMEMORY; + + if ((r = msi_view_refresh_row(db, view, row, object))) + msiobj_release( &object->hdr ); + else + *rec = object; + + return r; +} + UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec) { MSIVIEW *view;
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/query.h | 2 ++ dlls/msi/select.c | 15 ++++++++++----- dlls/msi/tests/db.c | 4 +++- 3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/dlls/msi/query.h b/dlls/msi/query.h index d79c14fd42..c0144d3054 100644 --- a/dlls/msi/query.h +++ b/dlls/msi/query.h @@ -153,4 +153,6 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
UINT msi_select_update( MSIVIEW *view, MSIRECORD *rec, UINT row ) DECLSPEC_HIDDEN;
+UINT msi_view_refresh_row( MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD *rec ) DECLSPEC_HIDDEN; + #endif /* __WINE_MSI_QUERY_H */ diff --git a/dlls/msi/select.c b/dlls/msi/select.c index ef16e5d09f..b38f339bd7 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -276,20 +276,25 @@ UINT msi_select_update(MSIVIEW *view, MSIRECORD *rec, UINT row) return ERROR_SUCCESS; }
-static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, +static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY mode, MSIRECORD *rec, UINT row ) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
- TRACE("%p %d %p %d\n", sv, eModifyMode, rec, row ); + TRACE("view %p, mode %d, rec %p, row %u.\n", view, mode, rec, row);
if( !sv->table ) return ERROR_FUNCTION_FAILED;
- if (eModifyMode == MSIMODIFY_UPDATE) + switch (mode) + { + case MSIMODIFY_REFRESH: + return msi_view_refresh_row(sv->db, view, row, rec); + case MSIMODIFY_UPDATE: return msi_select_update(view, rec, row); - - return sv->table->ops->modify( sv->table, eModifyMode, rec, row ); + default: + return sv->table->ops->modify( sv->table, mode, rec, row ); + } }
static UINT SELECT_delete( struct tagMSIVIEW *view ) diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index da4e3b78c1..3b0d2ef91e 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -3618,6 +3618,7 @@ static void test_join(void)
r = MsiViewFetch(hview, &hrec); ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); + check_record(hrec, 2, "alveolar", "procerus");
r = MsiRecordSetStringA( hrec, 1, "epicranius" ); ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); @@ -3627,7 +3628,8 @@ static void test_join(void)
/* try another valid operation for joins */ r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); - todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r ); + ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r ); + check_record(hrec, 2, "epicranius", "procerus");
/* try an invalid operation for joins */ r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/table.c | 14 +------------- dlls/msi/tests/db.c | 1 + 2 files changed, 2 insertions(+), 13 deletions(-)
diff --git a/dlls/msi/table.c b/dlls/msi/table.c index a2b83e27de..57114baa74 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -1835,18 +1835,6 @@ static UINT msi_table_assign(struct tagMSIVIEW *view, MSIRECORD *rec) return TABLE_insert_row( view, rec, -1, FALSE ); }
-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, NULL); - if (r != ERROR_SUCCESS) - return r; - - return TABLE_delete_row(view, row); -} - static UINT msi_refresh_record( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row ) { MSIRECORD *curr; @@ -1878,7 +1866,7 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, switch (eModifyMode) { case MSIMODIFY_DELETE: - r = modify_delete_row( view, rec ); + r = TABLE_delete_row( view, row ); break; case MSIMODIFY_VALIDATE_NEW: r = table_validate_new( tv, rec, &column ); diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 3b0d2ef91e..a823da6003 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -5498,6 +5498,7 @@ static void test_viewmodify_delete(void) ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
/* delete 2 */ + MsiRecordSetInteger(hrec, 1, 4); r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
Signed-off-by: Hans Leidekker hans@codeweavers.com