[PATCH 9/13] msi: Add support for adding temporary/non-persistent data to tables.

Robert Shearman rob at codeweavers.com
Mon Apr 23 02:24:41 CDT 2007


---
  dlls/msi/insert.c  |    2 -
  dlls/msi/msipriv.h |    2 -
  dlls/msi/select.c  |    4 +-
  dlls/msi/table.c   |  131 
++++++++++++++++++++++++++++++++++++++--------------
  4 files changed, 100 insertions(+), 39 deletions(-)
-------------- next part --------------
diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c
index aefc8fc..623359f 100644
--- a/dlls/msi/insert.c
+++ b/dlls/msi/insert.c
@@ -132,7 +132,7 @@ static UINT INSERT_execute( struct tagMS
     if( !values )
         goto err;
 
-    r = sv->ops->insert_row( sv, values );
+    r = sv->ops->insert_row( sv, values, iv->bIsTemp );
 
 err:
     if( values )
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 53cd432..f622833 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -145,7 +145,7 @@ typedef struct tagMSIVIEWOPS
     /*
      * Inserts a new row into the database from the records contents
      */
-    UINT (*insert_row)( struct tagMSIVIEW *, MSIRECORD * );
+    UINT (*insert_row)( struct tagMSIVIEW *, MSIRECORD *, BOOL temporary );
 
     /*
      * execute - loads the underlying data into memory so it can be read
diff --git a/dlls/msi/select.c b/dlls/msi/select.c
index 60bb390..cc822a1 100644
--- a/dlls/msi/select.c
+++ b/dlls/msi/select.c
@@ -124,7 +124,7 @@ static UINT SELECT_set_row( struct tagMS
     return r;
 }
 
-static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
+static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, BOOL temporary )
 {
     MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
     UINT i, table_cols, r;
@@ -149,7 +149,7 @@ static UINT SELECT_insert_row( struct ta
             goto fail;
     }
 
-    r = sv->table->ops->insert_row( sv->table, outrec );
+    r = sv->table->ops->insert_row( sv->table, outrec, temporary );
 
 fail:
     msiobj_release( &outrec->hdr );
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 362d934..75b4c34 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -64,6 +64,8 @@ struct tagMSITABLE
 {
     USHORT **data;
     UINT row_count;
+    USHORT **nonpersistent_data;
+    UINT nonpersistent_row_count;
     struct list entry;
     MSICOLUMNINFO *colinfo;
     UINT col_count;
@@ -457,6 +459,9 @@ static void free_table( MSITABLE *table 
     for( i=0; i<table->row_count; i++ )
         msi_free( table->data[i] );
     msi_free( table->data );
+    for( i=0; i<table->nonpersistent_row_count; i++ )
+        msi_free( table->nonpersistent_data[i] );
+    msi_free( table->nonpersistent_data );
     if( (table->colinfo != _Tables_cols) &&
         (table->colinfo != _Columns_cols) )
     {
@@ -606,14 +611,19 @@ UINT msi_create_table( MSIDATABASE *db, 
 
     /* only add tables that don't exist already */
     if( TABLE_Exists(db, name ) )
+    {
+        WARN("table %s exists\n", debugstr_w(name));
         return ERROR_BAD_QUERY_SYNTAX;
+    }
 
     table = msi_alloc( sizeof (MSITABLE) + lstrlenW(name)*sizeof (WCHAR) );
     if( !table )
         return ERROR_FUNCTION_FAILED;
-    
+
     table->row_count = 0;
     table->data = NULL;
+    table->nonpersistent_row_count = 0;
+    table->nonpersistent_data = NULL;
     table->colinfo = NULL;
     table->col_count = 0;
     lstrcpyW( table->name, name );
@@ -660,7 +670,7 @@ UINT msi_create_table( MSIDATABASE *db, 
     if( r )
         goto err;
 
-    r = tv->ops->insert_row( tv, rec );
+    r = tv->ops->insert_row( tv, rec, FALSE );
     TRACE("insert_row returned %x\n", r);
     if( r )
         goto err;
@@ -707,7 +717,7 @@ UINT msi_create_table( MSIDATABASE *db, 
         if( r )
             goto err;
 
-        r = tv->ops->insert_row( tv, rec );
+        r = tv->ops->insert_row( tv, rec, !persistent );
         if( r )
             goto err;
 
@@ -754,6 +764,8 @@ static UINT get_table( MSIDATABASE *db, 
 
     table->row_count = 0;
     table->data = NULL;
+    table->nonpersistent_row_count = 0;
+    table->nonpersistent_data = NULL;
     table->colinfo = NULL;
     table->col_count = 0;
     lstrcpyW( table->name, name );
@@ -932,6 +944,8 @@ static UINT get_tablecolumns( MSIDATABAS
 
     TRACE("Table id is %d, row count is %d\n", table_id, table->row_count);
 
+    /* Note: _Columns table doesn't have non-persistent data */
+
     /* if maxcount is non-zero, assume it's exactly right for this table */
     memset( colinfo, 0, maxcount*sizeof(*colinfo) );
     count = table->row_count;
@@ -1008,7 +1022,6 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCW
         return FALSE;
     }
 
-    /* count = table->size/2; */
     count = table->row_count;
     for( i=0; i<count; i++ )
         if( table->data[ i ][ 0 ] == table_id )
@@ -1017,6 +1030,14 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCW
     if (i!=count)
         return TRUE;
 
+    count = table->nonpersistent_row_count;
+    for( i=0; i<count; i++ )
+        if( table->nonpersistent_data[ i ][ 0 ] == table_id )
+            break;
+
+    if (i!=count)
+        return TRUE;
+
     TRACE("Searched %d tables, but %d was not found\n", count, table_id );
 
     return FALSE;
@@ -1038,7 +1059,8 @@ typedef struct tagMSITABLEVIEW
 static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
-    UINT offset, num_rows, n;
+    UINT offset, n;
+    USHORT **data;
 
     if( !tv->table )
         return ERROR_INVALID_PARAMETER;
@@ -1047,8 +1069,7 @@ static UINT TABLE_fetch_int( struct tagM
         return ERROR_INVALID_PARAMETER;
 
     /* how many rows are there ? */
-    num_rows = tv->table->row_count;
-    if( row >= num_rows )
+    if( row >= tv->table->row_count + tv->table->nonpersistent_row_count )
         return ERROR_NO_MORE_ITEMS;
 
     if( tv->columns[col-1].offset >= tv->row_size )
@@ -1058,18 +1079,24 @@ static UINT TABLE_fetch_int( struct tagM
         return ERROR_FUNCTION_FAILED;
     }
 
-    offset = row + (tv->columns[col-1].offset/2) * num_rows;
+    if (row >= tv->table->row_count)
+    {
+        row -= tv->table->row_count;
+        data = tv->table->nonpersistent_data;
+    }
+    else
+        data = tv->table->data;
     n = bytes_per_column( &tv->columns[col-1] );
     switch( n )
     {
     case 4:
         offset = tv->columns[col-1].offset/2;
-        *val = tv->table->data[row][offset] +
-               (tv->table->data[row][offset + 1] << 16);
+        *val = data[row][offset] +
+               (data[row][offset + 1] << 16);
         break;
     case 2:
         offset = tv->columns[col-1].offset/2;
-        *val = tv->table->data[row][offset];
+        *val = data[row][offset];
         break;
     default:
         ERR("oops! what is %d bytes per column?\n", n );
@@ -1152,6 +1179,7 @@ static UINT TABLE_fetch_stream( struct t
 static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
 {
     UINT offset, n;
+    USHORT **data;
 
     if( !tv->table )
         return ERROR_INVALID_PARAMETER;
@@ -1159,6 +1187,9 @@ static UINT TABLE_set_int( MSITABLEVIEW 
     if( (col==0) || (col>tv->num_cols) )
         return ERROR_INVALID_PARAMETER;
 
+    if( row >= tv->table->row_count + tv->table->nonpersistent_row_count )
+        return ERROR_INVALID_PARAMETER;
+
     if( tv->columns[col-1].offset >= tv->row_size )
     {
         ERR("Stuffed up %d >= %d\n", tv->columns[col-1].offset, tv->row_size );
@@ -1169,17 +1200,24 @@ static UINT TABLE_set_int( MSITABLEVIEW 
     msi_free( tv->columns[col-1].hash_table );
     tv->columns[col-1].hash_table = NULL;
 
+    if (row >= tv->table->row_count)
+    {
+        row -= tv->table->row_count;
+        data = tv->table->nonpersistent_data;
+    }
+    else
+        data = tv->table->data;
     n = bytes_per_column( &tv->columns[col-1] );
     switch( n )
     {
     case 4:
         offset = tv->columns[col-1].offset/2;
-        tv->table->data[row][offset]     = val & 0xffff;
-        tv->table->data[row][offset + 1] = (val>>16)&0xffff;
+        data[row][offset]     = val & 0xffff;
+        data[row][offset + 1] = (val>>16)&0xffff;
         break;
     case 2:
         offset = tv->columns[col-1].offset/2;
-        tv->table->data[row][offset] = val;
+        data[row][offset] = val;
         break;
     default:
         ERR("oops! what is %d bytes per column?\n", n );
@@ -1243,13 +1281,15 @@ static UINT TABLE_set_row( struct tagMSI
     return r;
 }
 
-static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num )
+static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num, BOOL temporary )
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
     USHORT **p, *row;
     UINT sz;
+    USHORT ***data_ptr;
+    UINT *row_count;
 
-    TRACE("%p\n", view);
+    TRACE("%p %s\n", view, temporary ? "TRUE" : "FALSE");
 
     if( !tv->table )
         return ERROR_INVALID_PARAMETER;
@@ -1258,9 +1298,22 @@ static UINT table_create_new_row( struct
     if( !row )
         return ERROR_NOT_ENOUGH_MEMORY;
 
-    sz = (tv->table->row_count + 1) * sizeof (UINT*);
-    if( tv->table->data )
-        p = msi_realloc( tv->table->data, sz );
+    if( temporary )
+    {
+        row_count = &tv->table->nonpersistent_row_count;
+        data_ptr = &tv->table->nonpersistent_data;
+        *num = tv->table->row_count + tv->table->nonpersistent_row_count;
+    }
+    else
+    {
+        row_count = &tv->table->row_count;
+        data_ptr = &tv->table->data;
+        *num = tv->table->row_count;
+    }
+
+    sz = (*row_count + 1) * sizeof (UINT*);
+    if( *data_ptr )
+        p = msi_realloc( *data_ptr, sz );
     else
         p = msi_alloc( sz );
     if( !p )
@@ -1269,10 +1322,9 @@ static UINT table_create_new_row( struct
         return ERROR_NOT_ENOUGH_MEMORY;
     }
 
-    tv->table->data = p;
-    tv->table->data[tv->table->row_count] = row;
-    *num = tv->table->row_count;
-    tv->table->row_count++;
+    *data_ptr = p;
+    (*data_ptr)[*row_count] = row;
+    (*row_count)++;
 
     return ERROR_SUCCESS;
 }
@@ -1307,7 +1359,7 @@ static UINT TABLE_get_dimensions( struct
     {
         if( !tv->table )
             return ERROR_INVALID_PARAMETER;
-        *rows = tv->table->row_count;
+        *rows = tv->table->row_count + tv->table->nonpersistent_row_count;
     }
 
     return ERROR_SUCCESS;
@@ -1375,19 +1427,19 @@ static UINT table_validate_new( MSITABLE
     return ERROR_SUCCESS;
 }
 
-static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
+static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary )
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
     UINT r, row = -1;
 
-    TRACE("%p %p\n", tv, rec );
+    TRACE("%p %p %s\n", tv, rec, temporary ? "TRUE" : "FALSE" );
 
     /* check that the key is unique - can we find a matching row? */
     r = table_validate_new( tv, rec );
     if( r != ERROR_SUCCESS )
         return ERROR_FUNCTION_FAILED;
 
-    r = table_create_new_row( view, &row );
+    r = table_create_new_row( view, &row, temporary );
     TRACE("insert_row returned %08x\n", r);
     if( r != ERROR_SUCCESS )
         return r;
@@ -1413,7 +1465,7 @@ static UINT TABLE_modify( struct tagMSIV
         r = table_validate_new( tv, rec );
         if (r != ERROR_SUCCESS)
             break;
-        r = TABLE_insert_row( view, rec );
+        r = TABLE_insert_row( view, rec, TRUE );
         break;
 
     case MSIMODIFY_REFRESH:
@@ -1469,7 +1521,7 @@ static UINT TABLE_find_matching_rows( st
     if( !tv->columns[col-1].hash_table )
     {
         UINT i;
-        UINT num_rows = tv->table->row_count;
+        UINT num_rows = tv->table->row_count + tv->table->nonpersistent_row_count;
         MSICOLUMNHASHENTRY **hash_table;
         MSICOLUMNHASHENTRY *new_entry;
 
@@ -1495,18 +1547,27 @@ static UINT TABLE_find_matching_rows( st
         for (i = 0; i < num_rows; i++, new_entry++)
         {
             UINT row_value, n;
-            UINT offset = i + (tv->columns[col-1].offset/2) * num_rows;
+            UINT offset;
+            USHORT **data;
+            UINT row = i;
+            if( row >= tv->table->row_count )
+            {
+                row -= tv->table->row_count;
+                data = tv->table->nonpersistent_data;
+            }
+            else
+                data = tv->table->data;
             n = bytes_per_column( &tv->columns[col-1] );
             switch( n )
             {
             case 4:
                 offset = tv->columns[col-1].offset/2;
-                row_value = tv->table->data[i][offset] + 
-                    (tv->table->data[i][offset + 1] << 16);
+                row_value = data[row][offset] + 
+                    (data[row][offset + 1] << 16);
                 break;
             case 2:
                 offset = tv->columns[col-1].offset/2;
-                row_value = tv->table->data[i][offset];
+                row_value = data[row][offset];
                 break;
             default:
                 ERR("oops! what is %d bytes per column?\n", n );
@@ -1798,7 +1859,7 @@ static UINT msi_table_find_row( MSITABLE
     data = msi_record_to_row( tv, rec );
     if( !data )
         return r;
-    for( i=0; i<tv->table->row_count; i++ )
+    for( i = 0; i < tv->table->row_count + tv->table->nonpersistent_row_count; i++ )
     {
         r = msi_row_matches( tv, i, data );
         if( r == ERROR_SUCCESS )
@@ -1924,7 +1985,7 @@ static UINT msi_table_load_transform( MS
                     MSI_RecordSetInteger( rec, 2, ++colcol );
                 }
 
-                r = TABLE_insert_row( &tv->view, rec );
+                r = TABLE_insert_row( &tv->view, rec, FALSE );
                 if (r != ERROR_SUCCESS)
                     ERR("insert row failed\n");
             }


More information about the wine-patches mailing list