From 15bfb30fc3beaee28cf4008b982b90fa33b6f130 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 26 Oct 2006 17:09:47 +0900 Subject: [PATCH] msi: Update tables using records, not integer by integer. --- dlls/msi/delete.c | 16 ++++--- dlls/msi/msipriv.h | 4 +- dlls/msi/select.c | 41 ++++++++++++++---- dlls/msi/table.c | 106 ++++++++++++++++++++++++++------------------- dlls/msi/update.c | 39 +++-------------- dlls/msi/where.c | 14 +++--- 6 files changed, 122 insertions(+), 98 deletions(-) diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c index 3e8d69485e7..1484f6a61e1 100644 --- a/dlls/msi/delete.c +++ b/dlls/msi/delete.c @@ -76,7 +76,8 @@ static UINT DELETE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IS static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; - UINT r, i, j, rows = 0, cols = 0; + UINT r, i, rows = 0, cols = 0; + MSIRECORD *empty; TRACE("%p %p\n", dv, record); @@ -91,12 +92,17 @@ static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) if( r != ERROR_SUCCESS ) return r; - TRACE("blanking %d rows\n", rows); + TRACE("blanking %d rows\n", rows); + + empty = MSI_CreateRecord( cols ); + if (!empty) + return ERROR_FUNCTION_FAILED; /* blank out all the rows that match */ - for( i=0; itable->ops->set_int( dv->table, i, j, 0 ); + for ( i=0; itable->ops->set_row( dv->table, i, empty, (1<hdr ); return ERROR_SUCCESS; } diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index cdb95c4c9fb..4745b9eaaf4 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -133,11 +133,11 @@ typedef struct tagMSIVIEWOPS UINT (*fetch_stream)( struct tagMSIVIEW *, UINT row, UINT col, IStream **stm ); /* - * get_int - sets one integer at {row,col} in the table + * set_row - sets values in a row as specified by mask * * Similar semantics to fetch_int */ - UINT (*set_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT val ); + UINT (*set_row)( struct tagMSIVIEW *, UINT row, MSIRECORD *rec, UINT mask ); /* * Inserts a new row into the database from the records contents diff --git a/dlls/msi/select.c b/dlls/msi/select.c index c9611305fb0..60bb3901299 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -82,21 +82,46 @@ static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IS return sv->table->ops->fetch_stream( sv->table, row, col, stm ); } -static UINT SELECT_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) +static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view; + UINT i, expanded_mask = 0, r = ERROR_SUCCESS, col_count = 0; + MSIRECORD *expanded; - TRACE("%p %d %d %04x\n", sv, row, col, val ); + TRACE("%p %d %p %08x\n", sv, row, rec, mask ); - if( !sv->table ) + if ( !sv->table ) return ERROR_FUNCTION_FAILED; - if( (col==0) || (col>sv->num_cols) ) - return ERROR_FUNCTION_FAILED; + /* test if any of the mask bits are invalid */ + if ( mask >= (1<num_cols) ) + return ERROR_INVALID_PARAMETER; - col = sv->cols[ col - 1 ]; + /* find the number of columns in the table below */ + r = sv->table->ops->get_dimensions( sv->table, NULL, &col_count ); + if( r ) + return r; - return sv->table->ops->set_int( sv->table, row, col, val ); + /* expand the record to the right size for the underlying table */ + expanded = MSI_CreateRecord( col_count ); + if ( !expanded ) + return ERROR_FUNCTION_FAILED; + + /* move the right fields across */ + for ( i=0; inum_cols; i++ ) + { + r = MSI_RecordCopyField( rec, i+1, expanded, sv->cols[ i ] ); + if (r != ERROR_SUCCESS) + break; + expanded_mask |= (1<<(sv->cols[i]-1)); + } + + /* set the row in the underlying table */ + if (r == ERROR_SUCCESS) + r = sv->table->ops->set_row( sv->table, row, expanded, expanded_mask ); + + msiobj_release( &expanded->hdr ); + return r; } static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record ) @@ -240,7 +265,7 @@ static const MSIVIEWOPS select_ops = { SELECT_fetch_int, SELECT_fetch_stream, - SELECT_set_int, + SELECT_set_row, SELECT_insert_row, SELECT_execute, SELECT_close, diff --git a/dlls/msi/table.c b/dlls/msi/table.c index 444c2a85308..9b2d3570d23 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -1101,7 +1101,7 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT * { case 4: offset = tv->columns[col-1].offset/2; - *val = tv->table->data[row][offset] + + *val = tv->table->data[row][offset] + (tv->table->data[row][offset + 1] << 16); break; case 2: @@ -1186,9 +1186,8 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt return r; } -static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) +static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val ) { - MSITABLEVIEW *tv = (MSITABLEVIEW*)view; UINT offset, n; if( !tv->table ) @@ -1223,6 +1222,61 @@ static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val return ERROR_SUCCESS; } +static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW*)view; + UINT i, val, r = ERROR_SUCCESS; + + if ( !tv->table ) + return ERROR_INVALID_PARAMETER; + + /* test if any of the mask bits are invalid */ + if ( mask >= (1<num_cols) ) + return ERROR_INVALID_PARAMETER; + + for ( i = 0; i < tv->num_cols; i++ ) + { + /* only update the fields specified in the mask */ + if ( !(mask&(1<columns[ i ].type) ) + { + val = 1; /* refers to the first key column */ + } + else if ( tv->columns[i].type & MSITYPE_STRING ) + { + LPCWSTR sval = MSI_RecordGetString( rec, i + 1 ); + val = msi_addstringW( tv->db->strings, 0, sval, -1, 1 ); + } + else if ( 2 == bytes_per_column( &tv->columns[ i ] ) ) + { + val = 0x8000 + MSI_RecordGetInteger( rec, i + 1 ); + if ( val & 0xffff0000 ) + { + ERR("field %u value %d out of range\n", i+1, val - 0x8000 ); + return ERROR_FUNCTION_FAILED; + } + } + else + { + INT ival = MSI_RecordGetInteger( rec, i + 1 ); + val = ival ^ 0x80000000; + } + } + + r = TABLE_set_int( tv, row, i+1, val ); + if ( r != ERROR_SUCCESS ) + break; + } + return r; +} + static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num ) { MSITABLEVIEW *tv = (MSITABLEVIEW*)view; @@ -1365,43 +1419,6 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec ) return ERROR_SUCCESS; } -static UINT msi_table_modify_row( MSITABLEVIEW *tv, MSIRECORD *rec, - UINT row, UINT mask ) -{ - UINT i, val, r = ERROR_SUCCESS; - - TRACE("%p %p %u %08x\n", tv, rec, row, mask ); - - for( i = 0; i < tv->num_cols; i++ ) - { - /* set keys or values specified in the mask */ - if( (~tv->columns[i].type & MSITYPE_KEY) && (~mask & (1<columns[i].type & MSITYPE_STRING) && - ! MSITYPE_IS_BINARY(tv->columns[i].type) ) - { - const WCHAR *str = MSI_RecordGetString( rec, i+1 ); - val = msi_addstringW( tv->db->strings, 0, str, -1, 1 ); - } - else - { - val = MSI_RecordGetInteger( rec, i+1 ); - if ( 2 == bytes_per_column( &tv->columns[i] ) ) - val ^= 0x8000; - else - val ^= 0x80000000; - } - r = TABLE_set_int( &tv->view, row, i+1, val ); - if( r ) - break; - } - - return r; -} - static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec ) { MSITABLEVIEW *tv = (MSITABLEVIEW*)view; @@ -1419,7 +1436,7 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec ) if( r != ERROR_SUCCESS ) return r; - return msi_table_modify_row( tv, rec, row, ~0 ); + return TABLE_set_row( view, row, rec, (1<num_cols) - 1 ); } static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, @@ -1588,7 +1605,7 @@ static const MSIVIEWOPS table_ops = { TABLE_fetch_int, TABLE_fetch_stream, - TABLE_set_int, + TABLE_set_row, TABLE_insert_row, TABLE_execute, TABLE_close, @@ -1874,8 +1891,9 @@ static UINT msi_table_find_row( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row ) static UINT msi_delete_row( MSITABLEVIEW *tv, UINT row ) { UINT i; + for( i=1; i<=tv->num_cols; i++ ) - tv->view.ops->set_int( &tv->view, row, i, 0 ); + TABLE_set_int( tv, row, i, 0 ); return ERROR_SUCCESS; } @@ -1997,7 +2015,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg, else if ( mask ) { TRACE("modifying row [%d]:\n", row); - msi_table_modify_row( tv, rec, row, mask ); + TABLE_set_row( &tv->view, row, rec, mask ); } else { diff --git a/dlls/msi/update.c b/dlls/msi/update.c index c97d9e8fb0e..9c843393922 100644 --- a/dlls/msi/update.c +++ b/dlls/msi/update.c @@ -58,7 +58,7 @@ static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; - UINT n, type, val, r, row, col_count = 0, row_count = 0; + UINT i, r, col_count = 0, row_count = 0; MSIRECORD *values = NULL; MSIVIEW *wv; @@ -75,47 +75,22 @@ static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) r = wv->ops->get_dimensions( wv, &row_count, &col_count ); if( r ) - goto err; + return r; values = msi_query_merge_record( col_count, uv->vals, record ); if (!values) return ERROR_FUNCTION_FAILED; - for( row = 0; row < row_count; row++ ) + for ( i=0; iops->get_column_info( wv, n, NULL, &type ); - if( r ) - break; - - if( MSI_RecordIsNull( values, n )) - val = 0; - else if( type & MSITYPE_STRING ) - { - const WCHAR *str = MSI_RecordGetString( values, n ); - val = msi_addstringW( uv->db->strings, 0, str, -1, 1 ); - } - else if ((type & 0xff) == 2) - { - val = MSI_RecordGetInteger( values, n ); - val ^= 0x8000; - } - else - { - val = MSI_RecordGetInteger( values, n ); - val ^= 0x80000000; - } - r = wv->ops->set_int( wv, row, n, val ); - if( r ) - break; - } + r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 ); + if (r != ERROR_SUCCESS) + break; } msiobj_release( &values->hdr ); -err: - return ERROR_SUCCESS; + return r; } diff --git a/dlls/msi/where.c b/dlls/msi/where.c index d01510bce9f..6fd2f8838ab 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -82,21 +82,21 @@ static UINT WHERE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt return wv->table->ops->fetch_stream( wv->table, row, col, stm ); } -static UINT WHERE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) +static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) { MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; - TRACE("%p %d %d %04x\n", wv, row, col, val ); + TRACE("%p %d %p %08x\n", wv, row, rec, mask ); if( !wv->table ) return ERROR_FUNCTION_FAILED; - + if( row > wv->row_count ) return ERROR_NO_MORE_ITEMS; - + row = wv->reorder[ row ]; - - return wv->table->ops->set_int( wv->table, row, col, val ); + + return wv->table->ops->set_row( wv->table, row, rec, mask ); } static INT INT_evaluate( INT lval, UINT op, INT rval ) @@ -420,7 +420,7 @@ static const MSIVIEWOPS where_ops = { WHERE_fetch_int, WHERE_fetch_stream, - WHERE_set_int, + WHERE_set_row, NULL, WHERE_execute, WHERE_close,