Skip to content

Commit 317c1f6

Browse files
winesynclearn-more
authored andcommitted
[WINESYNC] msi: Support UPDATE when MSITRANSFORM_ERROR_VIEWTRANSFORM flag is used.
Signed-off-by: Piotr Caban <[email protected]> Signed-off-by: Hans Leidekker <[email protected]> Signed-off-by: Alexandre Julliard <[email protected]> wine commit id 6e7303a7006538d3df1a09e13f5a5f469098b35f by Piotr Caban <[email protected]>
1 parent 1bbb87b commit 317c1f6

File tree

1 file changed

+173
-10
lines changed

1 file changed

+173
-10
lines changed

dll/win32/msi/table.c

Lines changed: 173 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,6 +2188,38 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
21882188
return ERROR_SUCCESS;
21892189
}
21902190

2191+
static WCHAR* create_key_string(MSITABLEVIEW *tv, MSIRECORD *rec)
2192+
{
2193+
DWORD i, p, len, key_len = 0;
2194+
WCHAR *key;
2195+
2196+
for (i = 0; i < tv->num_cols; i++)
2197+
{
2198+
if (!(tv->columns[i].type & MSITYPE_KEY))
2199+
continue;
2200+
if (MSI_RecordGetStringW( rec, i+1, NULL, &len ) == ERROR_SUCCESS)
2201+
key_len += len;
2202+
key_len++;
2203+
}
2204+
2205+
key = msi_alloc( key_len * sizeof(WCHAR) );
2206+
if(!key)
2207+
return NULL;
2208+
2209+
p = 0;
2210+
for (i = 0; i < tv->num_cols; i++)
2211+
{
2212+
if (!(tv->columns[i].type & MSITYPE_KEY))
2213+
continue;
2214+
if (p)
2215+
key[p++] = '\t';
2216+
len = key_len - p;
2217+
if (MSI_RecordGetStringW( rec, i+1, key + p, &len ) == ERROR_SUCCESS)
2218+
p += len;
2219+
}
2220+
return key;
2221+
}
2222+
21912223
static UINT msi_record_stream_name( const MSITABLEVIEW *tv, MSIRECORD *rec, LPWSTR name, UINT *len )
21922224
{
21932225
UINT p = 0, l, i, r;
@@ -2222,20 +2254,153 @@ static UINT msi_record_stream_name( const MSITABLEVIEW *tv, MSIRECORD *rec, LPWS
22222254

22232255
static UINT TransformView_fetch_int( MSIVIEW *view, UINT row, UINT col, UINT *val )
22242256
{
2225-
FIXME("\n");
2226-
return ERROR_CALL_NOT_IMPLEMENTED;
2257+
return TABLE_fetch_int( view, row, col, val );
22272258
}
22282259

22292260
static UINT TransformView_fetch_stream( MSIVIEW *view, UINT row, UINT col, IStream **stm )
22302261
{
2231-
FIXME("\n");
2232-
return ERROR_CALL_NOT_IMPLEMENTED;
2262+
return TABLE_fetch_stream( view, row, col, stm );
22332263
}
22342264

22352265
static UINT TransformView_set_row( MSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
22362266
{
2237-
FIXME("\n");
2238-
return ERROR_CALL_NOT_IMPLEMENTED;
2267+
static const WCHAR query_pfx[] =
2268+
L"INSERT INTO `_TransformView` (`Table`, `Column`, `Row`, `Data`, `Current`) VALUES ('";
2269+
2270+
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
2271+
WCHAR buf[256], *query = buf;
2272+
MSIRECORD *old_rec;
2273+
MSIQUERY *q;
2274+
WCHAR *key;
2275+
UINT i, p, r, len, qlen;
2276+
2277+
if (!wcscmp( tv->name, szColumns ))
2278+
{
2279+
ERR( "trying to modify existing column\n" );
2280+
return ERROR_INSTALL_TRANSFORM_FAILURE;
2281+
}
2282+
2283+
if (!wcscmp( tv->name, szTables ))
2284+
{
2285+
ERR( "trying to modify existing table\n" );
2286+
return ERROR_INSTALL_TRANSFORM_FAILURE;
2287+
}
2288+
2289+
key = create_key_string( tv, rec );
2290+
if (!key)
2291+
return ERROR_OUTOFMEMORY;
2292+
2293+
r = msi_view_get_row( tv->db, view, row, &old_rec );
2294+
if (r != ERROR_SUCCESS)
2295+
old_rec = NULL;
2296+
2297+
for (i = 0; i < tv->num_cols; i++)
2298+
{
2299+
if (!(mask & (1 << i)))
2300+
continue;
2301+
if (tv->columns[i].type & MSITYPE_KEY)
2302+
continue;
2303+
2304+
qlen = p = wcslen( query_pfx );
2305+
qlen += wcslen( tv->name ) + 3; /* strlen("','") */
2306+
qlen += wcslen( tv->columns[i].colname ) + 3;
2307+
qlen += wcslen( key ) + 3;
2308+
if (MSITYPE_IS_BINARY( tv->columns[i].type ))
2309+
r = msi_record_stream_name( tv, rec, NULL, &len );
2310+
else
2311+
r = MSI_RecordGetStringW( rec, i + 1, NULL, &len );
2312+
if (r != ERROR_SUCCESS)
2313+
{
2314+
if (old_rec)
2315+
msiobj_release( &old_rec->hdr );
2316+
msi_free( key );
2317+
return r;
2318+
}
2319+
qlen += len + 3;
2320+
if (old_rec && (r = MSI_RecordGetStringW( old_rec, i+1, NULL, &len )))
2321+
{
2322+
msiobj_release( &old_rec->hdr );
2323+
msi_free( key );
2324+
return r;
2325+
}
2326+
qlen += len + 3; /* strlen("')") + 1 */
2327+
2328+
if (qlen > ARRAY_SIZE(buf))
2329+
{
2330+
query = msi_alloc( qlen * sizeof(WCHAR) );
2331+
if (!query)
2332+
{
2333+
if (old_rec)
2334+
msiobj_release( &old_rec->hdr );
2335+
msi_free( key );
2336+
return ERROR_OUTOFMEMORY;
2337+
}
2338+
}
2339+
2340+
memcpy( query, query_pfx, p * sizeof(WCHAR) );
2341+
len = wcslen( tv->name );
2342+
memcpy( query + p, tv->name, len * sizeof(WCHAR) );
2343+
p += len;
2344+
query[p++] = '\'';
2345+
query[p++] = ',';
2346+
query[p++] = '\'';
2347+
len = wcslen( tv->columns[i].colname );
2348+
memcpy( query + p, tv->columns[i].colname, len * sizeof(WCHAR) );
2349+
p += len;
2350+
query[p++] = '\'';
2351+
query[p++] = ',';
2352+
query[p++] = '\'';
2353+
len = wcslen( key );
2354+
memcpy( query + p, key, len * sizeof(WCHAR) );
2355+
p += len;
2356+
query[p++] = '\'';
2357+
query[p++] = ',';
2358+
query[p++] = '\'';
2359+
len = qlen - p;
2360+
if (MSITYPE_IS_BINARY( tv->columns[i].type ))
2361+
msi_record_stream_name( tv, rec, query + p, &len );
2362+
else
2363+
MSI_RecordGetStringW( rec, i + 1, query + p, &len );
2364+
p += len;
2365+
query[p++] = '\'';
2366+
query[p++] = ',';
2367+
query[p++] = '\'';
2368+
if (old_rec)
2369+
{
2370+
len = qlen - p;
2371+
MSI_RecordGetStringW( old_rec, i + 1, query + p, &len );
2372+
p += len;
2373+
}
2374+
query[p++] = '\'';
2375+
query[p++] = ')';
2376+
query[p++] = 0;
2377+
2378+
r = MSI_DatabaseOpenViewW( tv->db, query, &q );
2379+
if (query != buf)
2380+
msi_free( query );
2381+
if (r != ERROR_SUCCESS)
2382+
{
2383+
if (old_rec)
2384+
msiobj_release( &old_rec->hdr );
2385+
msi_free( key );
2386+
return r;
2387+
}
2388+
2389+
r = MSI_ViewExecute( q, NULL );
2390+
msiobj_release( &q->hdr );
2391+
if (r != ERROR_SUCCESS)
2392+
{
2393+
if (old_rec)
2394+
msiobj_release( &old_rec->hdr );
2395+
msi_free( key );
2396+
return r;
2397+
}
2398+
}
2399+
2400+
if (old_rec)
2401+
msiobj_release( &old_rec->hdr );
2402+
msi_free( key );
2403+
return ERROR_SUCCESS;
22392404
}
22402405

22412406
static UINT TransformView_insert_row( MSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary )
@@ -2262,15 +2427,13 @@ static UINT TransformView_close( MSIVIEW *view )
22622427

22632428
static UINT TransformView_get_dimensions( MSIVIEW *view, UINT *rows, UINT *cols )
22642429
{
2265-
FIXME("\n");
2266-
return ERROR_CALL_NOT_IMPLEMENTED;
2430+
return TABLE_get_dimensions( view, rows, cols );
22672431
}
22682432

22692433
static UINT TransformView_get_column_info( MSIVIEW *view, UINT n, LPCWSTR *name, UINT *type,
22702434
BOOL *temporary, LPCWSTR *table_name )
22712435
{
2272-
FIXME("\n");
2273-
return ERROR_CALL_NOT_IMPLEMENTED;
2436+
return TABLE_get_column_info( view, n, name, type, temporary, table_name );
22742437
}
22752438

22762439
static UINT TransformView_delete( MSIVIEW *view )

0 commit comments

Comments
 (0)