[MSI 1/4] add streams table
Andrey Turkin
pancha at mail.nnov.ru
Mon Jun 19 11:31:30 CDT 2006
This patch adds virtual _Streams table to MSI because native MSI
maintains such table
ChangeLog:
virtual _Streams table added
-------------- next part --------------
--- wine-0.9.15-orig/dlls/msi/table.c 2006-06-19 19:45:21.000000000 +0400
+++ wine-0.9.15/dlls/msi/table.c 2006-06-19 19:45:36.000000000 +0400
@@ -833,12 +833,14 @@
/* information for default tables */
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
-static const WCHAR szTable[] = { 'T','a','b','l','e',0 };
+static const WCHAR szTable[] = { 'T','a','b','l','e',0 };
static const WCHAR szName[] = { 'N','a','m','e',0 };
static const WCHAR szColumns[] = { '_','C','o','l','u','m','n','s',0 };
static const WCHAR szColumn[] = { 'C','o','l','u','m','n',0 };
static const WCHAR szNumber[] = { 'N','u','m','b','e','r',0 };
static const WCHAR szType[] = { 'T','y','p','e',0 };
+static const WCHAR szStreams[] = { '_','S','t','r','e','a','m','s',0 };
+static const WCHAR szData[] = { 'D','a','t','a',0 };
static const MSICOLUMNINFO _Columns_cols[4] = {
{ szColumns, 1, szTable, MSITYPE_VALID | MSITYPE_STRING | 64, 0 },
@@ -849,6 +851,10 @@
static const MSICOLUMNINFO _Tables_cols[1] = {
{ szTables, 1, szName, MSITYPE_VALID | MSITYPE_STRING | 64, 0 },
};
+static const MSICOLUMNINFO _Streams_cols[2] = {
+ { szStreams, 1, szName, MSITYPE_VALID | MSITYPE_STRING | 62, 0 },
+ { szStreams, 2, szData, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_NULLABLE, 2 },
+};
static UINT get_defaulttablecolumns( LPCWSTR name, MSICOLUMNINFO *colinfo, UINT *sz)
{
@@ -867,6 +873,11 @@
p = _Columns_cols;
n = 4;
}
+ else if (!lstrcmpW( name, szStreams ))
+ {
+ p = _Streams_cols;
+ n = 2;
+ }
else
return ERROR_FUNCTION_FAILED;
@@ -886,6 +897,67 @@
return ERROR_SUCCESS;
}
+static MSITABLE *create_streams_table( MSIDATABASE *db )
+{
+ MSITABLE *t;
+ IEnumSTATSTG *stgenum = NULL;
+ HRESULT r;
+ ULONG alloced;
+
+ TRACE("\n");
+
+ t = msi_alloc( sizeof (MSITABLE) + lstrlenW(szStreams)*sizeof (WCHAR) );
+ if( !t )
+ return t;
+
+ lstrcpyW( t->name, szStreams );
+
+ t->row_count = alloced = 0;
+ t->data = NULL;
+
+ r = IStorage_EnumElements( db->storage, 0, NULL, 0, &stgenum );
+ if ( FAILED(r) )
+ goto err;
+
+ while ( 1 )
+ {
+ STATSTG stat;
+ DWORD count = 0;
+ WCHAR name[0x40];
+
+ r = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
+ if( FAILED( r ) || !count )
+ break;
+ decode_streamname( stat.pwcsName, name );
+ if ( t->row_count >= alloced)
+ {
+ alloced += 4;
+ if (t->data == NULL)
+ t->data = msi_alloc_zero( alloced * sizeof(WCHAR*) );
+ else
+ t->data = msi_realloc( t->data, alloced * sizeof(WCHAR*) );
+ if (!t->data)
+ {
+ IEnumSTATSTG_Release( stgenum );
+ goto err;
+ }
+ }
+ if ( (t->data[t->row_count] = msi_alloc(2 * sizeof(UINT))) == NULL )
+ goto err;
+ else
+ {
+ t->data[t->row_count][0] = msi_addstringW( db->strings, 0, name, -1, 0 );
+ t->data[t->row_count++][1] = 1;
+ }
+ }
+ IEnumSTATSTG_Release( stgenum );
+
+ return t;
+err:
+ free_table( t );
+ return NULL;
+}
+
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count )
{
UINT i;
@@ -993,6 +1065,8 @@
return TRUE;
if( !lstrcmpW( name, szColumns ) )
return TRUE;
+ if( !lstrcmpW( name, szStreams ) )
+ return TRUE;
r = msi_string2idW( db->strings, name, &table_id );
if( r != ERROR_SUCCESS )
@@ -1132,6 +1206,53 @@
return r;
}
+static UINT STREAMS_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm )
+{
+ MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
+ UINT ival = 0, refcol = 0, r;
+ LPWSTR sval;
+
+ ERR("\n");
+ if( !view->ops->fetch_int )
+ return ERROR_INVALID_PARAMETER;
+
+ /*
+ * The column marked with the type stream data seems to have a single number
+ * which references the column containing the name of the stream data
+ *
+ * Fetch the column to reference first.
+ */
+ r = view->ops->fetch_int( view, row, col, &ival );
+ if( r != ERROR_SUCCESS )
+ {
+ ERR("1: %d\n", r);
+ return r;
+ }
+
+ ERR("fetched %d\n", ival);
+ /* now get the column with the name of the stream */
+ r = view->ops->fetch_int( view, row, ival, &refcol );
+ if( r != ERROR_SUCCESS )
+ {
+ ERR("2: %d\n", r);
+ return r;
+ }
+
+ /* lookup the string value from the string table */
+ sval = MSI_makestring( tv->db, refcol );
+ if( !sval )
+ {
+ ERR("MSI_makestring failed\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ r = db_get_raw_stream( tv->db, sval, stm );
+ if( r )
+ ERR("fetching stream %s, error = %d\n",debugstr_w(sval), r);
+ msi_free( sval );
+
+ return r;
+}
static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val )
{
@@ -1218,6 +1339,25 @@
return ERROR_SUCCESS;
}
+static UINT STREAMS_execute( struct tagMSIVIEW *view, MSIRECORD *record )
+{
+ MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
+
+ TRACE("(%p, %p)\n", view, record);
+
+ tv->table = find_cached_table( tv->db, szStreams );
+ if( !tv->table )
+ {
+ tv->table = create_streams_table( tv->db );
+ if ( tv->table )
+ list_add_head( &tv->db->tables, &tv->table->entry );
+ else
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ return ERROR_SUCCESS;
+}
+
static UINT TABLE_close( struct tagMSIVIEW *view )
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@@ -1509,6 +1649,21 @@
TABLE_find_matching_rows
};
+MSIVIEWOPS streams_ops =
+{
+ TABLE_fetch_int,
+ STREAMS_fetch_stream,
+ TABLE_set_int,
+ TABLE_insert_row,
+ STREAMS_execute,
+ TABLE_close,
+ TABLE_get_dimensions,
+ TABLE_get_column_info,
+ TABLE_modify,
+ TABLE_delete,
+ TABLE_find_matching_rows
+};
+
UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
{
MSITABLEVIEW *tv ;
@@ -1521,11 +1676,17 @@
column_count = 0;
r = get_tablecolumns( db, name, NULL, &column_count );
if( r != ERROR_SUCCESS )
+ {
+ TRACE("get_tablecolumns failed: %d\n", r);
return r;
+ }
/* if there's no columns, there's no table */
if( column_count == 0 )
+ {
+ TRACE("column_count==0\n");
return ERROR_INVALID_PARAMETER;
+ }
TRACE("Table found\n");
@@ -1552,7 +1713,7 @@
TRACE("Table has %d columns\n", column_count);
/* fill the structure */
- tv->view.ops = &table_ops;
+ tv->view.ops = lstrcmpW(name, szStreams)?&table_ops:&streams_ops;
tv->db = db;
tv->columns = columns;
tv->num_cols = column_count;
--- wine-0.9.15-orig/dlls/msi/tests/db.c 2006-06-19 19:45:17.000000000 +0400
+++ wine-0.9.15/dlls/msi/tests/db.c 2006-06-19 19:46:41.000000000 +0400
@@ -743,10 +743,8 @@
rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
ok( rec, "failed to get column info record\n" );
- todo_wine {
ok( check_record( rec, 1, "s62"), "wrong record type\n");
ok( check_record( rec, 2, "V0"), "wrong record type\n");
- }
MsiCloseHandle( rec );
@@ -754,10 +752,8 @@
rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
ok( rec, "failed to get column info record\n" );
- todo_wine {
ok( check_record( rec, 1, "Name"), "wrong record type\n");
ok( check_record( rec, 2, "Data"), "wrong record type\n");
- }
MsiCloseHandle( rec );
MsiCloseHandle( hdb );
More information about the wine-patches
mailing list