msi [4/4]: Handle adding columns in transforms
James Hawkins
truiken at gmail.com
Mon Jul 9 21:34:41 CDT 2007
Hi,
Changelog:
* Handle adding columns in transforms.
dlls/msi/table.c | 153 +++++++++++++++++++++++++++++++++++++++------------
dlls/msi/tests/db.c | 69 +++++------------------
2 files changed, 131 insertions(+), 91 deletions(-)
--
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 3541c2d..06652fe 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -1944,8 +1944,34 @@ static UINT msi_table_find_row( MSITABLE
return r;
}
+static void msi_update_table_columns( MSIDATABASE *db, LPWSTR name )
+{
+ MSITABLE *table;
+ UINT size, offset;
+ int n;
+
+ table = find_cached_table( db, name );
+ msi_free( table->colinfo );
+ table_get_column_info( db, name, &table->colinfo, &table->col_count );
+
+ size = msi_table_get_row_size( table->colinfo, table->col_count );
+ offset = table->colinfo[table->col_count - 1].offset;
+
+ for ( n = 0; n < table->row_count; n++ )
+ {
+ table->data[n] = msi_realloc( table->data[n], size );
+ table->data[n][offset] = (BYTE)MSI_NULL_INTEGER;
+ }
+}
+
+typedef struct
+{
+ struct list entry;
+ LPWSTR name;
+} TRANSFORMDATA;
+
static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
- string_table *st, LPCWSTR name,
+ string_table *st, TRANSFORMDATA *transform,
UINT bytes_per_strref )
{
UINT rawsize = 0;
@@ -1955,6 +1981,7 @@ static UINT msi_table_load_transform( MS
MSIRECORD *rec = NULL;
UINT colcol = 0;
WCHAR coltable[32];
+ LPWSTR name = transform->name;
coltable[0] = 0;
TRACE("%p %p %p %s\n", db, stg, st, debugstr_w(name) );
@@ -2038,34 +2065,41 @@ static UINT msi_table_load_transform( MS
{
if ( mask & 1 )
{
+ WCHAR table[32];
+ DWORD sz = 32;
+ UINT number = MSI_NULL_INTEGER;
+
TRACE("inserting record\n");
- /*
- * Native msi seems writes nul into the
- * Number (2nd) column of the _Columns table.
- * Not sure that it's deliberate...
- */
if (!lstrcmpW(name, szColumns))
{
- WCHAR table[32];
- DWORD sz = 32;
-
MSI_RecordGetStringW( rec, 1, table, &sz );
+ number = MSI_RecordGetInteger( rec, 2 );
- /* reset the column number on a new table */
- if ( lstrcmpW(coltable, table) )
+ /*
+ * Native msi seems writes nul into the Number (2nd) column of
+ * the _Columns table, only when the columns are from a new table
+ */
+ if ( number == MSI_NULL_INTEGER )
{
- colcol = 0;
- lstrcpyW( coltable, table );
+ /* reset the column number on a new table */
+ if ( lstrcmpW(coltable, table) )
+ {
+ colcol = 0;
+ lstrcpyW( coltable, table );
+ }
+
+ /* fix nul column numbers */
+ MSI_RecordSetInteger( rec, 2, ++colcol );
}
-
- /* fix nul column numbers */
- MSI_RecordSetInteger( rec, 2, ++colcol );
}
r = TABLE_insert_row( &tv->view, rec, FALSE );
if (r != ERROR_SUCCESS)
ERR("insert row failed\n");
+
+ if ( number != MSI_NULL_INTEGER && !lstrcmpW(name, szColumns) )
+ msi_update_table_columns( db, table );
}
else
{
@@ -2108,11 +2142,12 @@ err:
*/
UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
{
+ struct list transforms;
IEnumSTATSTG *stgenum = NULL;
+ TRANSFORMDATA *transform;
+ TRANSFORMDATA *tables = NULL, *columns = NULL;
HRESULT r;
STATSTG stat;
- ULONG count;
- WCHAR name[0x40];
string_table *strings;
UINT ret = ERROR_FUNCTION_FAILED;
UINT bytes_per_strref;
@@ -2127,40 +2162,84 @@ UINT msi_table_apply_transform( MSIDATAB
if( FAILED( r ) )
goto end;
+ list_init(&transforms);
+
+ while ( TRUE )
+ {
+ MSITABLEVIEW *tv = NULL;
+ WCHAR name[0x40];
+ ULONG count = 0;
+
+ r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
+ if ( FAILED( r ) || !count )
+ break;
+
+ decode_streamname( stat.pwcsName, name );
+ if ( name[0] != 0x4840 )
+ continue;
+
+ if ( !lstrcmpW( name+1, szStringPool ) ||
+ !lstrcmpW( name+1, szStringData ) )
+ continue;
+
+ transform = msi_alloc_zero( sizeof(TRANSFORMDATA) );
+ if ( !transform )
+ break;
+
+ list_add_tail( &transforms, &transform->entry );
+
+ transform->name = strdupW( name + 1 );
+
+ if ( !lstrcmpW( transform->name, szTables ) )
+ tables = transform;
+ else if (!lstrcmpW( transform->name, szColumns ) )
+ columns = transform;
+
+ TRACE("transform contains stream %s\n", debugstr_w(name));
+
+ /* load the table */
+ r = TABLE_CreateView( db, transform->name, (MSIVIEW**) &tv );
+ if( r != ERROR_SUCCESS )
+ continue;
+
+ r = tv->view.ops->execute( &tv->view, NULL );
+ if( r != ERROR_SUCCESS )
+ {
+ tv->view.ops->delete( &tv->view );
+ continue;
+ }
+
+ tv->view.ops->delete( &tv->view );
+ }
+
/*
* Apply _Tables and _Columns transforms first so that
* the table metadata is correct, and empty tables exist.
*/
- ret = msi_table_load_transform( db, stg, strings, szTables, bytes_per_strref );
+ ret = msi_table_load_transform( db, stg, strings, tables, bytes_per_strref );
if (ret != ERROR_SUCCESS && ret != ERROR_INVALID_TABLE)
goto end;
- ret = msi_table_load_transform( db, stg, strings, szColumns, bytes_per_strref );
+ ret = msi_table_load_transform( db, stg, strings, columns, bytes_per_strref );
if (ret != ERROR_SUCCESS && ret != ERROR_INVALID_TABLE)
goto end;
ret = ERROR_SUCCESS;
- while( r == ERROR_SUCCESS )
+ while ( !list_empty( &transforms ) )
{
- count = 0;
- r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
- if( FAILED( r ) || !count )
- break;
-
- decode_streamname( stat.pwcsName, name );
- if ( name[0] != 0x4840 )
- continue;
-
- TRACE("transform contains stream %s\n", debugstr_w(name));
+ transform = LIST_ENTRY( list_head( &transforms ), TRANSFORMDATA, entry );
- if ( !lstrcmpW( name+1, szStringPool ) ||
- !lstrcmpW( name+1, szStringData ) ||
- !lstrcmpW( name+1, szColumns ) ||
- !lstrcmpW( name+1, szTables ) )
- continue;
+ if ( lstrcmpW( transform->name, szColumns ) &&
+ lstrcmpW( transform->name, szTables ) &&
+ ret == ERROR_SUCCESS )
+ {
+ ret = msi_table_load_transform( db, stg, strings, transform, bytes_per_strref );
+ }
- ret = msi_table_load_transform( db, stg, strings, name+1, bytes_per_strref );
+ list_remove( &transform->entry );
+ msi_free( transform->name );
+ msi_free( transform );
}
if ( ret == ERROR_SUCCESS )
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c
index 2ce58ae..a6fe5e3 100644
--- a/dlls/msi/tests/db.c
+++ b/dlls/msi/tests/db.c
@@ -2049,30 +2049,21 @@ static void test_try_transform(void)
hrec = 0;
query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
r = do_query(hdb, query, &hrec);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "select query failed\n");
- }
+ ok(r == ERROR_SUCCESS, "select query failed\n");
MsiCloseHandle(hrec);
/* check unchanged value */
hrec = 0;
query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
r = do_query(hdb, query, &hrec);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "select query failed\n");
- }
+ ok(r == ERROR_SUCCESS, "select query failed\n");
MsiCloseHandle(hrec);
/* check deleted value */
hrec = 0;
query = "select * from `MOO` where `NOO` = 3";
r = do_query(hdb, query, &hrec);
- todo_wine
- {
- ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
- }
+ ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
if (hrec) MsiCloseHandle(hrec);
/* check added stream */
@@ -2093,67 +2084,40 @@ static void test_try_transform(void)
hrec = 0;
query = "select * from `MOO`";
r = MsiDatabaseOpenView(hdb, query, &hview);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "open view failed\n");
- }
+ ok(r == ERROR_SUCCESS, "open view failed\n");
r = MsiViewExecute(hview, 0);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "view execute failed\n");
- }
+ ok(r == ERROR_SUCCESS, "view execute failed\n");
r = MsiViewFetch(hview, &hrec);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "view fetch failed\n");
- }
+ ok(r == ERROR_SUCCESS, "view fetch failed\n");
r = MsiRecordGetInteger(hrec, 1);
- todo_wine
- {
- ok(r == 1, "Expected 1, got %d\n", r);
- }
+ ok(r == 1, "Expected 1, got %d\n", r);
sz = sizeof buffer;
r = MsiRecordGetString(hrec, 2, buffer, &sz);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "record get string failed\n");
- ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
- }
+ ok(r == ERROR_SUCCESS, "record get string failed\n");
+ ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
r = MsiRecordGetInteger(hrec, 3);
ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
r = MsiRecordGetInteger(hrec, 4);
- todo_wine
- {
- ok(r == 5, "Expected 5, got %d\n", r);
- }
+ ok(r == 5, "Expected 5, got %d\n", r);
MsiCloseHandle(hrec);
r = MsiViewFetch(hview, &hrec);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "view fetch failed\n");
- }
+ ok(r == ERROR_SUCCESS, "view fetch failed\n");
r = MsiRecordGetInteger(hrec, 1);
- todo_wine
- {
- ok(r == 2, "Expected 2, got %d\n", r);
- }
+ ok(r == 2, "Expected 2, got %d\n", r);
sz = sizeof buffer;
r = MsiRecordGetString(hrec, 2, buffer, &sz);
- todo_wine
- {
- ok(r == ERROR_SUCCESS, "record get string failed\n");
- ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
- }
+ ok(r == ERROR_SUCCESS, "record get string failed\n");
+ ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
r = MsiRecordGetInteger(hrec, 3);
ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
@@ -2164,10 +2128,7 @@ static void test_try_transform(void)
MsiCloseHandle(hrec);
r = MsiViewFetch(hview, &hrec);
- todo_wine
- {
- ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
- }
+ ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
MsiCloseHandle(hrec);
MsiCloseHandle(hview);
--
1.4.1
More information about the wine-patches
mailing list