msi: Update tables using records, not integer by integer.
This commit is contained in:
parent
9b95c27c9c
commit
15bfb30fc3
|
@ -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 )
|
static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
{
|
{
|
||||||
MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
|
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);
|
TRACE("%p %p\n", dv, record);
|
||||||
|
|
||||||
|
@ -91,12 +92,17 @@ static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
if( r != ERROR_SUCCESS )
|
if( r != ERROR_SUCCESS )
|
||||||
return r;
|
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 */
|
/* blank out all the rows that match */
|
||||||
for( i=0; i<rows; i++ )
|
for ( i=0; i<rows; i++ )
|
||||||
for( j=1; j<=cols; j++ )
|
dv->table->ops->set_row( dv->table, i, empty, (1<<cols)-1 );
|
||||||
dv->table->ops->set_int( dv->table, i, j, 0 );
|
|
||||||
|
msiobj_release( &empty->hdr );
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,11 +133,11 @@ typedef struct tagMSIVIEWOPS
|
||||||
UINT (*fetch_stream)( struct tagMSIVIEW *, UINT row, UINT col, IStream **stm );
|
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
|
* 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
|
* Inserts a new row into the database from the records contents
|
||||||
|
|
|
@ -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 );
|
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;
|
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;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
if( (col==0) || (col>sv->num_cols) )
|
/* test if any of the mask bits are invalid */
|
||||||
return ERROR_FUNCTION_FAILED;
|
if ( mask >= (1<<sv->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; i<sv->num_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 )
|
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
|
@ -240,7 +265,7 @@ static const MSIVIEWOPS select_ops =
|
||||||
{
|
{
|
||||||
SELECT_fetch_int,
|
SELECT_fetch_int,
|
||||||
SELECT_fetch_stream,
|
SELECT_fetch_stream,
|
||||||
SELECT_set_int,
|
SELECT_set_row,
|
||||||
SELECT_insert_row,
|
SELECT_insert_row,
|
||||||
SELECT_execute,
|
SELECT_execute,
|
||||||
SELECT_close,
|
SELECT_close,
|
||||||
|
|
106
dlls/msi/table.c
106
dlls/msi/table.c
|
@ -1101,7 +1101,7 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
|
||||||
{
|
{
|
||||||
case 4:
|
case 4:
|
||||||
offset = tv->columns[col-1].offset/2;
|
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);
|
(tv->table->data[row][offset + 1] << 16);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -1186,9 +1186,8 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
|
||||||
return r;
|
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;
|
UINT offset, n;
|
||||||
|
|
||||||
if( !tv->table )
|
if( !tv->table )
|
||||||
|
@ -1223,6 +1222,61 @@ static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val
|
||||||
return ERROR_SUCCESS;
|
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<<tv->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<<i)) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* FIXME: should we allow updating keys? */
|
||||||
|
|
||||||
|
val = 0;
|
||||||
|
if ( !MSI_RecordIsNull( rec, i + 1 ) )
|
||||||
|
{
|
||||||
|
if ( MSITYPE_IS_BINARY(tv->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 )
|
static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num )
|
||||||
{
|
{
|
||||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||||
|
@ -1365,43 +1419,6 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||||
return ERROR_SUCCESS;
|
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<<i)) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (MSI_RecordIsNull( rec, i+1))
|
|
||||||
val = 0;
|
|
||||||
else if( (tv->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 )
|
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
|
||||||
{
|
{
|
||||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||||
|
@ -1419,7 +1436,7 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
|
||||||
if( r != ERROR_SUCCESS )
|
if( r != ERROR_SUCCESS )
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return msi_table_modify_row( tv, rec, row, ~0 );
|
return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
||||||
|
@ -1588,7 +1605,7 @@ static const MSIVIEWOPS table_ops =
|
||||||
{
|
{
|
||||||
TABLE_fetch_int,
|
TABLE_fetch_int,
|
||||||
TABLE_fetch_stream,
|
TABLE_fetch_stream,
|
||||||
TABLE_set_int,
|
TABLE_set_row,
|
||||||
TABLE_insert_row,
|
TABLE_insert_row,
|
||||||
TABLE_execute,
|
TABLE_execute,
|
||||||
TABLE_close,
|
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 )
|
static UINT msi_delete_row( MSITABLEVIEW *tv, UINT row )
|
||||||
{
|
{
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
for( i=1; i<=tv->num_cols; 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;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1997,7 +2015,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
||||||
else if ( mask )
|
else if ( mask )
|
||||||
{
|
{
|
||||||
TRACE("modifying row [%d]:\n", row);
|
TRACE("modifying row [%d]:\n", row);
|
||||||
msi_table_modify_row( tv, rec, row, mask );
|
TABLE_set_row( &tv->view, row, rec, mask );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 )
|
static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
{
|
{
|
||||||
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
|
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;
|
MSIRECORD *values = NULL;
|
||||||
MSIVIEW *wv;
|
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 );
|
r = wv->ops->get_dimensions( wv, &row_count, &col_count );
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
return r;
|
||||||
|
|
||||||
values = msi_query_merge_record( col_count, uv->vals, record );
|
values = msi_query_merge_record( col_count, uv->vals, record );
|
||||||
if (!values)
|
if (!values)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
for( row = 0; row < row_count; row++ )
|
for ( i=0; i<row_count; i++ )
|
||||||
{
|
{
|
||||||
for( n = 1; n <= col_count; n++ )
|
r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 );
|
||||||
{
|
if (r != ERROR_SUCCESS)
|
||||||
r = wv->ops->get_column_info( wv, n, NULL, &type );
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msiobj_release( &values->hdr );
|
msiobj_release( &values->hdr );
|
||||||
|
|
||||||
err:
|
return r;
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
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;
|
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 )
|
if( !wv->table )
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
if( row > wv->row_count )
|
if( row > wv->row_count )
|
||||||
return ERROR_NO_MORE_ITEMS;
|
return ERROR_NO_MORE_ITEMS;
|
||||||
|
|
||||||
row = wv->reorder[ row ];
|
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 )
|
static INT INT_evaluate( INT lval, UINT op, INT rval )
|
||||||
|
@ -420,7 +420,7 @@ static const MSIVIEWOPS where_ops =
|
||||||
{
|
{
|
||||||
WHERE_fetch_int,
|
WHERE_fetch_int,
|
||||||
WHERE_fetch_stream,
|
WHERE_fetch_stream,
|
||||||
WHERE_set_int,
|
WHERE_set_row,
|
||||||
NULL,
|
NULL,
|
||||||
WHERE_execute,
|
WHERE_execute,
|
||||||
WHERE_close,
|
WHERE_close,
|
||||||
|
|
Loading…
Reference in New Issue