@@ -2220,6 +2220,112 @@ static UINT msi_record_stream_name( const MSITABLEVIEW *tv, MSIRECORD *rec, LPWS
22202220 return ERROR_SUCCESS ;
22212221}
22222222
2223+ static UINT TransformView_fetch_int ( MSIVIEW * view , UINT row , UINT col , UINT * val )
2224+ {
2225+ FIXME ("\n" );
2226+ return ERROR_CALL_NOT_IMPLEMENTED ;
2227+ }
2228+
2229+ static UINT TransformView_fetch_stream ( MSIVIEW * view , UINT row , UINT col , IStream * * stm )
2230+ {
2231+ FIXME ("\n" );
2232+ return ERROR_CALL_NOT_IMPLEMENTED ;
2233+ }
2234+
2235+ static UINT TransformView_set_row ( MSIVIEW * view , UINT row , MSIRECORD * rec , UINT mask )
2236+ {
2237+ FIXME ("\n" );
2238+ return ERROR_CALL_NOT_IMPLEMENTED ;
2239+ }
2240+
2241+ static UINT TransformView_insert_row ( MSIVIEW * view , MSIRECORD * rec , UINT row , BOOL temporary )
2242+ {
2243+ FIXME ("\n" );
2244+ return ERROR_CALL_NOT_IMPLEMENTED ;
2245+ }
2246+
2247+ static UINT TransformView_delete_row ( MSIVIEW * view , UINT row )
2248+ {
2249+ FIXME ("\n" );
2250+ return ERROR_CALL_NOT_IMPLEMENTED ;
2251+ }
2252+
2253+ static UINT TransformView_execute ( MSIVIEW * view , MSIRECORD * record )
2254+ {
2255+ return ERROR_SUCCESS ;
2256+ }
2257+
2258+ static UINT TransformView_close ( MSIVIEW * view )
2259+ {
2260+ return ERROR_SUCCESS ;
2261+ }
2262+
2263+ static UINT TransformView_get_dimensions ( MSIVIEW * view , UINT * rows , UINT * cols )
2264+ {
2265+ FIXME ("\n" );
2266+ return ERROR_CALL_NOT_IMPLEMENTED ;
2267+ }
2268+
2269+ static UINT TransformView_get_column_info ( MSIVIEW * view , UINT n , LPCWSTR * name , UINT * type ,
2270+ BOOL * temporary , LPCWSTR * table_name )
2271+ {
2272+ FIXME ("\n" );
2273+ return ERROR_CALL_NOT_IMPLEMENTED ;
2274+ }
2275+
2276+ static UINT TransformView_delete ( MSIVIEW * view )
2277+ {
2278+ return TABLE_delete ( view );
2279+ }
2280+
2281+ static const MSIVIEWOPS transform_view_ops =
2282+ {
2283+ TransformView_fetch_int ,
2284+ TransformView_fetch_stream ,
2285+ NULL ,
2286+ NULL ,
2287+ NULL ,
2288+ TransformView_set_row ,
2289+ TransformView_insert_row ,
2290+ TransformView_delete_row ,
2291+ TransformView_execute ,
2292+ TransformView_close ,
2293+ TransformView_get_dimensions ,
2294+ TransformView_get_column_info ,
2295+ NULL ,
2296+ TransformView_delete ,
2297+ NULL ,
2298+ NULL ,
2299+ NULL ,
2300+ NULL ,
2301+ NULL
2302+ };
2303+
2304+ UINT TransformView_Create ( MSIDATABASE * db , string_table * st , LPCWSTR name , MSIVIEW * * view )
2305+ {
2306+ MSITABLEVIEW * tv ;
2307+ UINT r ;
2308+
2309+ r = TABLE_CreateView ( db , name , view );
2310+ if (r == ERROR_INVALID_PARAMETER )
2311+ {
2312+ /* table does not exist */
2313+ FIXME ("\n" );
2314+ return ERROR_CALL_NOT_IMPLEMENTED ;
2315+ }
2316+ else if (r != ERROR_SUCCESS )
2317+ {
2318+ return r ;
2319+ }
2320+ else
2321+ {
2322+ tv = (MSITABLEVIEW * )* view ;
2323+ }
2324+
2325+ tv -> view .ops = & transform_view_ops ;
2326+ return ERROR_SUCCESS ;
2327+ }
2328+
22232329UINT MSI_CommitTables ( MSIDATABASE * db )
22242330{
22252331 UINT r , bytes_per_strref ;
@@ -2510,7 +2616,7 @@ typedef struct
25102616
25112617static UINT msi_table_load_transform ( MSIDATABASE * db , IStorage * stg ,
25122618 string_table * st , TRANSFORMDATA * transform ,
2513- UINT bytes_per_strref )
2619+ UINT bytes_per_strref , int err_cond )
25142620{
25152621 BYTE * rawdata = NULL ;
25162622 MSITABLEVIEW * tv = NULL ;
@@ -2536,7 +2642,10 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
25362642 }
25372643
25382644 /* create a table view */
2539- r = TABLE_CreateView ( db , name , (MSIVIEW * * ) & tv );
2645+ if ( err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM )
2646+ r = TransformView_Create ( db , st , name , (MSIVIEW * * ) & tv );
2647+ else
2648+ r = TABLE_CreateView ( db , name , (MSIVIEW * * ) & tv );
25402649 if ( r != ERROR_SUCCESS )
25412650 goto err ;
25422651
@@ -2646,34 +2755,35 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
26462755 if (!mask )
26472756 {
26482757 TRACE ("deleting row [%d]:\n" , row );
2649- r = TABLE_delete_row ( & tv -> view , row );
2758+ r = tv -> view . ops -> delete_row ( & tv -> view , row );
26502759 if (r != ERROR_SUCCESS )
26512760 WARN ("failed to delete row %u\n" , r );
26522761 }
26532762 else if (mask & 1 )
26542763 {
26552764 TRACE ("modifying full row [%d]:\n" , row );
2656- r = TABLE_set_row ( & tv -> view , row , rec , (1 << tv -> num_cols ) - 1 );
2765+ r = tv -> view . ops -> set_row ( & tv -> view , row , rec , (1 << tv -> num_cols ) - 1 );
26572766 if (r != ERROR_SUCCESS )
26582767 WARN ("failed to modify row %u\n" , r );
26592768 }
26602769 else
26612770 {
26622771 TRACE ("modifying masked row [%d]:\n" , row );
2663- r = TABLE_set_row ( & tv -> view , row , rec , mask );
2772+ r = tv -> view . ops -> set_row ( & tv -> view , row , rec , mask );
26642773 if (r != ERROR_SUCCESS )
26652774 WARN ("failed to modify row %u\n" , r );
26662775 }
26672776 }
26682777 else
26692778 {
26702779 TRACE ("inserting row\n" );
2671- r = TABLE_insert_row ( & tv -> view , rec , -1 , FALSE );
2780+ r = tv -> view . ops -> insert_row ( & tv -> view , rec , -1 , FALSE );
26722781 if (r != ERROR_SUCCESS )
26732782 WARN ("failed to insert row %u\n" , r );
26742783 }
26752784
2676- if (!wcscmp ( name , szColumns ))
2785+ if (!(err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM ) &&
2786+ !wcscmp ( name , szColumns ))
26772787 msi_update_table_columns ( db , table );
26782788
26792789 msiobj_release ( & rec -> hdr );
@@ -2696,7 +2806,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
26962806 *
26972807 * Enumerate the table transforms in a transform storage and apply each one.
26982808 */
2699- UINT msi_table_apply_transform ( MSIDATABASE * db , IStorage * stg )
2809+ UINT msi_table_apply_transform ( MSIDATABASE * db , IStorage * stg , int err_cond )
27002810{
27012811 struct list transforms ;
27022812 IEnumSTATSTG * stgenum = NULL ;
@@ -2708,6 +2818,7 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
27082818 UINT ret = ERROR_FUNCTION_FAILED ;
27092819 UINT bytes_per_strref ;
27102820 BOOL property_update = FALSE;
2821+ BOOL free_transform_view = FALSE;
27112822
27122823 TRACE ("%p %p\n" , db , stg );
27132824
@@ -2770,15 +2881,39 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
27702881 tv -> view .ops -> delete ( & tv -> view );
27712882 }
27722883
2884+ if (err_cond & MSITRANSFORM_ERROR_VIEWTRANSFORM )
2885+ {
2886+ static const WCHAR create_query [] = L"CREATE TABLE `_TransformView` ( "
2887+ L"`Table` CHAR(0) NOT NULL TEMPORARY, `Column` CHAR(0) NOT NULL TEMPORARY, "
2888+ L"`Row` CHAR(0) TEMPORARY, `Data` CHAR(0) TEMPORARY, `Current` CHAR(0) TEMPORARY "
2889+ L"PRIMARY KEY `Table`, `Column`, `Row` ) HOLD" ;
2890+ MSIQUERY * query ;
2891+ UINT r ;
2892+
2893+ r = MSI_DatabaseOpenViewW ( db , create_query , & query );
2894+ if (r != ERROR_SUCCESS )
2895+ goto end ;
2896+
2897+ r = MSI_ViewExecute ( query , NULL );
2898+ if (r == ERROR_SUCCESS )
2899+ MSI_ViewClose ( query );
2900+ msiobj_release ( & query -> hdr );
2901+ if (r == ERROR_BAD_QUERY_SYNTAX )
2902+ FIXME ( "support adding to _TransformView\n" );
2903+ if (r != ERROR_SUCCESS )
2904+ goto end ;
2905+ free_transform_view = TRUE;
2906+ }
2907+
27732908 /*
27742909 * Apply _Tables and _Columns transforms first so that
27752910 * the table metadata is correct, and empty tables exist.
27762911 */
2777- ret = msi_table_load_transform ( db , stg , strings , tables , bytes_per_strref );
2912+ ret = msi_table_load_transform ( db , stg , strings , tables , bytes_per_strref , err_cond );
27782913 if (ret != ERROR_SUCCESS && ret != ERROR_INVALID_TABLE )
27792914 goto end ;
27802915
2781- ret = msi_table_load_transform ( db , stg , strings , columns , bytes_per_strref );
2916+ ret = msi_table_load_transform ( db , stg , strings , columns , bytes_per_strref , err_cond );
27822917 if (ret != ERROR_SUCCESS && ret != ERROR_INVALID_TABLE )
27832918 goto end ;
27842919
@@ -2792,7 +2927,7 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
27922927 wcscmp ( transform -> name , szTables ) &&
27932928 ret == ERROR_SUCCESS )
27942929 {
2795- ret = msi_table_load_transform ( db , stg , strings , transform , bytes_per_strref );
2930+ ret = msi_table_load_transform ( db , stg , strings , transform , bytes_per_strref , err_cond );
27962931 }
27972932
27982933 list_remove ( & transform -> entry );
@@ -2811,6 +2946,17 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
28112946 IEnumSTATSTG_Release ( stgenum );
28122947 if ( strings )
28132948 msi_destroy_stringtable ( strings );
2949+ if (ret != ERROR_SUCCESS && free_transform_view )
2950+ {
2951+ MSIQUERY * query ;
2952+ if (MSI_DatabaseOpenViewW ( db , L"ALTER TABLE `_TransformView` FREE" ,
2953+ & query ) == ERROR_SUCCESS )
2954+ {
2955+ if (MSI_ViewExecute ( query , NULL ) == ERROR_SUCCESS )
2956+ MSI_ViewClose ( query );
2957+ msiobj_release ( & query -> hdr );
2958+ }
2959+ }
28142960
28152961 return ret ;
28162962}
0 commit comments