Implement MsiModifyView (MSIMODIFY_INSERT_TEMPORARY).
This commit is contained in:
parent
1bac61f8e5
commit
e8d1a167df
@ -60,10 +60,11 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||||||
{
|
{
|
||||||
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
|
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
|
||||||
column_info *col;
|
column_info *col;
|
||||||
UINT r, nField, row, table_val, column_val;
|
UINT r, nField;
|
||||||
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
|
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
|
||||||
static const WCHAR szColumns[] = { '_','C','o','l','u','m','n','s',0 };
|
static const WCHAR szColumns[] = { '_','C','o','l','u','m','n','s',0 };
|
||||||
MSIVIEW *tv = NULL;
|
MSIVIEW *tv = NULL;
|
||||||
|
MSIRECORD *rec;
|
||||||
|
|
||||||
TRACE("%p Table %s (%s)\n", cv, debugstr_w(cv->name),
|
TRACE("%p Table %s (%s)\n", cv, debugstr_w(cv->name),
|
||||||
cv->bIsTemp?"temporary":"permanent");
|
cv->bIsTemp?"temporary":"permanent");
|
||||||
@ -72,12 +73,6 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||||||
if( TABLE_Exists(cv->db, cv->name ) )
|
if( TABLE_Exists(cv->db, cv->name ) )
|
||||||
return ERROR_BAD_QUERY_SYNTAX;
|
return ERROR_BAD_QUERY_SYNTAX;
|
||||||
|
|
||||||
/* add the name to the _Tables table */
|
|
||||||
table_val = msi_addstringW( cv->db->strings, 0, cv->name, -1, 1 );
|
|
||||||
TRACE("New string %s -> %d\n", debugstr_w( cv->name ), table_val );
|
|
||||||
if( table_val < 0 )
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
|
|
||||||
r = TABLE_CreateView( cv->db, szTables, &tv );
|
r = TABLE_CreateView( cv->db, szTables, &tv );
|
||||||
TRACE("CreateView returned %x\n", r);
|
TRACE("CreateView returned %x\n", r);
|
||||||
if( r )
|
if( r )
|
||||||
@ -86,20 +81,26 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||||||
r = tv->ops->execute( tv, 0 );
|
r = tv->ops->execute( tv, 0 );
|
||||||
TRACE("tv execute returned %x\n", r);
|
TRACE("tv execute returned %x\n", r);
|
||||||
if( r )
|
if( r )
|
||||||
return r;
|
goto err;
|
||||||
|
|
||||||
row = -1;
|
rec = MSI_CreateRecord( 1 );
|
||||||
r = tv->ops->insert_row( tv, &row );
|
if( !rec )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
r = MSI_RecordSetStringW( rec, 1, cv->name );
|
||||||
|
if( r )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
r = tv->ops->insert_row( tv, rec );
|
||||||
TRACE("insert_row returned %x\n", r);
|
TRACE("insert_row returned %x\n", r);
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
r = tv->ops->set_int( tv, row, 1, table_val );
|
|
||||||
if( r )
|
|
||||||
goto err;
|
|
||||||
tv->ops->delete( tv );
|
tv->ops->delete( tv );
|
||||||
tv = NULL;
|
tv = NULL;
|
||||||
|
|
||||||
|
msiobj_release( &rec->hdr );
|
||||||
|
|
||||||
/* add each column to the _Columns table */
|
/* add each column to the _Columns table */
|
||||||
r = TABLE_CreateView( cv->db, szColumns, &tv );
|
r = TABLE_CreateView( cv->db, szColumns, &tv );
|
||||||
if( r )
|
if( r )
|
||||||
@ -108,7 +109,15 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||||||
r = tv->ops->execute( tv, 0 );
|
r = tv->ops->execute( tv, 0 );
|
||||||
TRACE("tv execute returned %x\n", r);
|
TRACE("tv execute returned %x\n", r);
|
||||||
if( r )
|
if( r )
|
||||||
return r;
|
goto err;
|
||||||
|
|
||||||
|
rec = MSI_CreateRecord( 4 );
|
||||||
|
if( !rec )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
r = MSI_RecordSetStringW( rec, 1, cv->name );
|
||||||
|
if( r )
|
||||||
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* need to set the table, column number, col name and type
|
* need to set the table, column number, col name and type
|
||||||
@ -117,36 +126,21 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||||||
nField = 1;
|
nField = 1;
|
||||||
for( col = cv->col_info; col; col = col->next )
|
for( col = cv->col_info; col; col = col->next )
|
||||||
{
|
{
|
||||||
row = -1;
|
r = MSI_RecordSetInteger( rec, 2, nField );
|
||||||
r = tv->ops->insert_row( tv, &row );
|
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
column_val = msi_addstringW( cv->db->strings, 0, col->column, -1, 1 );
|
r = MSI_RecordSetStringW( rec, 3, col->column );
|
||||||
TRACE("New string %s -> %d\n", debugstr_w( col->column ), column_val );
|
|
||||||
if( column_val < 0 )
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* add the string again here so we increase the reference count */
|
|
||||||
table_val = msi_addstringW( cv->db->strings, 0, cv->name, -1, 1 );
|
|
||||||
if( table_val < 0 )
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = tv->ops->set_int( tv, row, 1, table_val );
|
|
||||||
if( r )
|
if( r )
|
||||||
break;
|
goto err;
|
||||||
|
|
||||||
r = tv->ops->set_int( tv, row, 2, 0x8000|nField );
|
r = MSI_RecordSetInteger( rec, 4, col->type );
|
||||||
if( r )
|
if( r )
|
||||||
break;
|
goto err;
|
||||||
|
|
||||||
r = tv->ops->set_int( tv, row, 3, column_val );
|
r = tv->ops->insert_row( tv, rec );
|
||||||
if( r )
|
if( r )
|
||||||
break;
|
goto err;
|
||||||
|
|
||||||
r = tv->ops->set_int( tv, row, 4, 0x8000|col->type );
|
|
||||||
if( r )
|
|
||||||
break;
|
|
||||||
|
|
||||||
nField++;
|
nField++;
|
||||||
}
|
}
|
||||||
|
@ -82,11 +82,11 @@ static UINT DELETE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT va
|
|||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT DELETE_insert_row( struct tagMSIVIEW *view, UINT *num )
|
static UINT DELETE_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
{
|
{
|
||||||
MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
|
MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
|
||||||
|
|
||||||
TRACE("%p %p\n", dv, num );
|
TRACE("%p %p\n", dv, record );
|
||||||
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ err:
|
|||||||
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
{
|
{
|
||||||
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
|
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
|
||||||
UINT n, type, val, r, row, col_count = 0;
|
UINT r, col_count = 0;
|
||||||
MSIVIEW *sv;
|
MSIVIEW *sv;
|
||||||
MSIRECORD *values = NULL;
|
MSIRECORD *values = NULL;
|
||||||
|
|
||||||
@ -136,38 +136,13 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||||||
if( !values )
|
if( !values )
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
row = -1;
|
r = sv->ops->insert_row( sv, values );
|
||||||
r = sv->ops->insert_row( sv, &row );
|
|
||||||
TRACE("insert_row returned %x\n", r);
|
|
||||||
if( r )
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
for( n = 1; n <= col_count; n++ )
|
|
||||||
{
|
|
||||||
r = sv->ops->get_column_info( sv, n, NULL, &type );
|
|
||||||
if( r )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if( type & MSITYPE_STRING )
|
|
||||||
{
|
|
||||||
const WCHAR *str = MSI_RecordGetString( values, n );
|
|
||||||
val = msi_addstringW( iv->db->strings, 0, str, -1, 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val = MSI_RecordGetInteger( values, n );
|
|
||||||
val |= 0x8000;
|
|
||||||
}
|
|
||||||
r = sv->ops->set_int( sv, row, n, val );
|
|
||||||
if( r )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if( values )
|
if( values )
|
||||||
msiobj_release( &values->hdr );
|
msiobj_release( &values->hdr );
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,10 +129,9 @@ typedef struct tagMSIVIEWOPS
|
|||||||
UINT (*set_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT val );
|
UINT (*set_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT val );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inserts a new, blank row into the database
|
* Inserts a new row into the database from the records contents
|
||||||
* *row receives the number of the new row
|
|
||||||
*/
|
*/
|
||||||
UINT (*insert_row)( struct tagMSIVIEW *, UINT *row );
|
UINT (*insert_row)( struct tagMSIVIEW *, MSIRECORD * );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* execute - loads the underlying data into memory so it can be read
|
* execute - loads the underlying data into memory so it can be read
|
||||||
|
@ -99,16 +99,16 @@ static UINT SELECT_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT va
|
|||||||
return sv->table->ops->set_int( sv->table, row, col, val );
|
return sv->table->ops->set_int( sv->table, row, col, val );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT SELECT_insert_row( struct tagMSIVIEW *view, UINT *num )
|
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
{
|
{
|
||||||
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
|
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
|
||||||
|
|
||||||
TRACE("%p %p\n", sv, num );
|
TRACE("%p %p\n", sv, record );
|
||||||
|
|
||||||
if( !sv->table )
|
if( !sv->table )
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
return sv->table->ops->insert_row( sv->table, num );
|
return sv->table->ops->insert_row( sv->table, record );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
|
150
dlls/msi/table.c
150
dlls/msi/table.c
@ -1192,7 +1192,7 @@ static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val
|
|||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT TABLE_insert_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;
|
||||||
USHORT **p, *row;
|
USHORT **p, *row;
|
||||||
@ -1301,11 +1301,155 @@ static UINT TABLE_get_column_info( struct tagMSIVIEW *view,
|
|||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT table_find_in_column( MSITABLEVIEW *tv, UINT col, UINT val, UINT *row )
|
||||||
|
{
|
||||||
|
UINT i, r, x;
|
||||||
|
|
||||||
|
for( i=0; i<tv->table->row_count; i++ )
|
||||||
|
{
|
||||||
|
r = TABLE_fetch_int( (struct tagMSIVIEW*) tv, i, col, &x );
|
||||||
|
if ( r != ERROR_SUCCESS )
|
||||||
|
{
|
||||||
|
ERR("TABLE_fetch_int shouldn't fail here\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( x == val )
|
||||||
|
{
|
||||||
|
*row = i;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||||
|
{
|
||||||
|
LPCWSTR str;
|
||||||
|
UINT i, val, r, row;
|
||||||
|
|
||||||
|
/* FIXME: set the MsiViewGetError value */
|
||||||
|
|
||||||
|
for( i = 0; i<tv->num_cols; i++ )
|
||||||
|
{
|
||||||
|
/* check for duplicate keys */
|
||||||
|
if( !( tv->columns[i].type & MSITYPE_KEY ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TRACE("column %d (%s.%s)is a key\n", i,
|
||||||
|
debugstr_w(tv->columns[i].tablename),
|
||||||
|
debugstr_w(tv->columns[i].colname) );
|
||||||
|
|
||||||
|
val = 0;
|
||||||
|
if( tv->columns[i].type & MSITYPE_STRING )
|
||||||
|
{
|
||||||
|
/* keys can't be null */
|
||||||
|
str = MSI_RecordGetString( rec, i+1 );
|
||||||
|
if( !str )
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
|
/* if the string doesn't exist in the string table yet, it's OK */
|
||||||
|
r = msi_string2idW( tv->db->strings, str, &val );
|
||||||
|
if( ERROR_SUCCESS != r )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = MSI_RecordGetInteger( rec, i+1 );
|
||||||
|
val ^= 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we find the same value in the table, it's a duplicate */
|
||||||
|
row = 0;
|
||||||
|
r = table_find_in_column( tv, i+1, val, &row );
|
||||||
|
if( ERROR_SUCCESS == r )
|
||||||
|
{
|
||||||
|
TRACE("found in row %d\n", row );
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
|
||||||
|
{
|
||||||
|
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||||
|
UINT n, type, val, r, row, col_count = 0;
|
||||||
|
|
||||||
|
r = TABLE_get_dimensions( view, NULL, &col_count );
|
||||||
|
if( r )
|
||||||
|
return r;
|
||||||
|
|
||||||
|
row = -1;
|
||||||
|
r = table_create_new_row( view, &row );
|
||||||
|
TRACE("insert_row returned %08x\n", r);
|
||||||
|
if( r )
|
||||||
|
return r;
|
||||||
|
|
||||||
|
for( n = 1; n <= col_count; n++ )
|
||||||
|
{
|
||||||
|
r = TABLE_get_column_info( view, n, NULL, &type );
|
||||||
|
if( r )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( type & MSITYPE_STRING )
|
||||||
|
{
|
||||||
|
const WCHAR *str = MSI_RecordGetString( rec, n );
|
||||||
|
val = msi_addstringW( tv->db->strings, 0, str, -1, 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = MSI_RecordGetInteger( rec, n );
|
||||||
|
val ^= 0x8000;
|
||||||
|
}
|
||||||
|
r = TABLE_set_int( view, row, n, val );
|
||||||
|
if( r )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
||||||
MSIRECORD *rec)
|
MSIRECORD *rec)
|
||||||
{
|
{
|
||||||
FIXME("%p %d %p\n", view, eModifyMode, rec );
|
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
UINT r;
|
||||||
|
|
||||||
|
TRACE("%p %d %p\n", view, eModifyMode, rec );
|
||||||
|
|
||||||
|
switch (eModifyMode)
|
||||||
|
{
|
||||||
|
case MSIMODIFY_VALIDATE_NEW:
|
||||||
|
r = table_validate_new( tv, rec );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSIMODIFY_INSERT_TEMPORARY:
|
||||||
|
r = table_validate_new( tv, rec );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
break;
|
||||||
|
r = TABLE_insert_row( view, rec );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSIMODIFY_REFRESH:
|
||||||
|
case MSIMODIFY_INSERT:
|
||||||
|
case MSIMODIFY_UPDATE:
|
||||||
|
case MSIMODIFY_ASSIGN:
|
||||||
|
case MSIMODIFY_REPLACE:
|
||||||
|
case MSIMODIFY_MERGE:
|
||||||
|
case MSIMODIFY_DELETE:
|
||||||
|
case MSIMODIFY_VALIDATE:
|
||||||
|
case MSIMODIFY_VALIDATE_FIELD:
|
||||||
|
case MSIMODIFY_VALIDATE_DELETE:
|
||||||
|
FIXME("%p %d %p - mode not implemented\n", view, eModifyMode, rec );
|
||||||
|
r = ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
r = ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT TABLE_delete( struct tagMSIVIEW *view )
|
static UINT TABLE_delete( struct tagMSIVIEW *view )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user