2006-02-17 00:04:10 +00:00
|
|
|
/*
|
|
|
|
* Implementation of the Microsoft Installer (msi.dll)
|
|
|
|
*
|
|
|
|
* Copyright 2002-2005 Mike McCormack for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-08-01 23:12:11 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2006-02-17 00:04:10 +00:00
|
|
|
*/
|
|
|
|
|
2018-03-04 23:30:58 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winerror.h"
|
|
|
|
#include "wine/debug.h"
|
2022-03-12 22:54:40 +00:00
|
|
|
#include "wine/exception.h"
|
2018-03-04 23:30:58 +00:00
|
|
|
#include "msi.h"
|
|
|
|
#include "msiquery.h"
|
|
|
|
#include "objbase.h"
|
|
|
|
#include "objidl.h"
|
|
|
|
#include "winnls.h"
|
|
|
|
|
2022-03-12 14:11:45 +00:00
|
|
|
#include "msipriv.h"
|
2018-03-04 23:30:58 +00:00
|
|
|
#include "query.h"
|
2022-03-12 14:12:08 +00:00
|
|
|
#include "winemsi_s.h"
|
2018-03-04 23:30:58 +00:00
|
|
|
|
|
|
|
#include "initguid.h"
|
2006-10-22 20:23:59 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|
|
|
|
|
|
|
static void MSI_CloseView( MSIOBJECTHDR *arg )
|
|
|
|
{
|
|
|
|
MSIQUERY *query = (MSIQUERY*) arg;
|
|
|
|
struct list *ptr, *t;
|
|
|
|
|
|
|
|
if( query->view && query->view->ops->delete )
|
|
|
|
query->view->ops->delete( query->view );
|
|
|
|
msiobj_release( &query->db->hdr );
|
|
|
|
|
|
|
|
LIST_FOR_EACH_SAFE( ptr, t, &query->mem )
|
|
|
|
{
|
|
|
|
msi_free( ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-16 01:13:42 +00:00
|
|
|
UINT VIEW_find_column( MSIVIEW *table, LPCWSTR name, LPCWSTR table_name, UINT *n )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
LPCWSTR col_name, haystack_table_name;
|
2006-02-17 00:04:10 +00:00
|
|
|
UINT i, count, r;
|
|
|
|
|
|
|
|
r = table->ops->get_dimensions( table, NULL, &count );
|
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
return r;
|
|
|
|
|
|
|
|
for( i=1; i<=count; i++ )
|
|
|
|
{
|
|
|
|
INT x;
|
|
|
|
|
2009-11-16 01:13:42 +00:00
|
|
|
r = table->ops->get_column_info( table, i, &col_name, NULL,
|
|
|
|
NULL, &haystack_table_name );
|
2006-02-17 00:04:10 +00:00
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
return r;
|
2022-03-13 00:35:24 +00:00
|
|
|
x = wcscmp( name, col_name );
|
2009-11-16 01:13:42 +00:00
|
|
|
if( table_name )
|
2022-03-13 00:35:24 +00:00
|
|
|
x |= wcscmp( table_name, haystack_table_name );
|
2006-02-17 00:04:10 +00:00
|
|
|
if( !x )
|
|
|
|
{
|
|
|
|
*n = i;
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiDatabaseOpenViewA( MSIHANDLE hdb, const char *szQuery, MSIHANDLE *phView )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
UINT r;
|
2022-03-14 20:20:29 +00:00
|
|
|
WCHAR *szwQuery;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %s, %p\n", hdb, debugstr_a(szQuery), phView );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if( szQuery )
|
|
|
|
{
|
|
|
|
szwQuery = strdupAtoW( szQuery );
|
|
|
|
if( !szwQuery )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
szwQuery = NULL;
|
|
|
|
|
|
|
|
r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
|
|
|
|
|
|
|
|
msi_free( szwQuery );
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT MSI_DatabaseOpenViewW( MSIDATABASE *db, const WCHAR *szQuery, MSIQUERY **pView )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIQUERY *query;
|
|
|
|
UINT r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%s, %p\n", debugstr_w(szQuery), pView );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
/* pre allocate a handle to hold a pointer to the view */
|
|
|
|
query = alloc_msiobject( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY),
|
|
|
|
MSI_CloseView );
|
|
|
|
if( !query )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
|
|
|
|
msiobj_addref( &db->hdr );
|
|
|
|
query->db = db;
|
|
|
|
list_init( &query->mem );
|
|
|
|
|
|
|
|
r = MSI_ParseSQL( db, szQuery, &query->view, &query->mem );
|
|
|
|
if( r == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
msiobj_addref( &query->hdr );
|
|
|
|
*pView = query;
|
|
|
|
}
|
|
|
|
|
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-13 00:35:24 +00:00
|
|
|
UINT WINAPIV MSI_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
UINT r;
|
|
|
|
int size = 100, res;
|
|
|
|
LPWSTR query;
|
|
|
|
|
|
|
|
/* construct the string */
|
|
|
|
for (;;)
|
|
|
|
{
|
2022-03-13 22:59:52 +00:00
|
|
|
va_list va;
|
2006-02-17 00:04:10 +00:00
|
|
|
query = msi_alloc( size*sizeof(WCHAR) );
|
2022-03-13 22:59:52 +00:00
|
|
|
va_start(va, fmt);
|
2022-03-13 00:35:24 +00:00
|
|
|
res = vswprintf(query, size, fmt, va);
|
2022-03-13 22:59:52 +00:00
|
|
|
va_end(va);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (res == -1) size *= 2;
|
|
|
|
else if (res >= size) size = res + 1;
|
|
|
|
else break;
|
|
|
|
msi_free( query );
|
|
|
|
}
|
|
|
|
/* perform the query */
|
|
|
|
r = MSI_DatabaseOpenViewW(db, query, view);
|
|
|
|
msi_free(query);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
UINT MSI_IterateRecords( MSIQUERY *view, LPDWORD count,
|
2006-02-17 00:04:10 +00:00
|
|
|
record_func func, LPVOID param )
|
|
|
|
{
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
UINT r, n = 0, max = 0;
|
|
|
|
|
|
|
|
r = MSI_ViewExecute( view, NULL );
|
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if( count )
|
|
|
|
max = *count;
|
|
|
|
|
|
|
|
/* iterate a query */
|
|
|
|
for( n = 0; (max == 0) || (n < max); n++ )
|
|
|
|
{
|
|
|
|
r = MSI_ViewFetch( view, &rec );
|
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
break;
|
|
|
|
if (func)
|
|
|
|
r = func( rec, param );
|
|
|
|
msiobj_release( &rec->hdr );
|
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
MSI_ViewClose( view );
|
|
|
|
|
|
|
|
if( count )
|
|
|
|
*count = n;
|
|
|
|
|
|
|
|
if( r == ERROR_NO_MORE_ITEMS )
|
|
|
|
r = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return a single record from a query */
|
2022-03-13 00:35:24 +00:00
|
|
|
MSIRECORD * WINAPIV MSI_QueryGetRecord( MSIDATABASE *db, LPCWSTR fmt, ... )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
MSIQUERY *view = NULL;
|
|
|
|
UINT r;
|
|
|
|
int size = 100, res;
|
|
|
|
LPWSTR query;
|
|
|
|
|
|
|
|
/* construct the string */
|
|
|
|
for (;;)
|
|
|
|
{
|
2022-03-13 22:59:52 +00:00
|
|
|
va_list va;
|
2006-02-17 00:04:10 +00:00
|
|
|
query = msi_alloc( size*sizeof(WCHAR) );
|
2022-03-13 22:59:52 +00:00
|
|
|
va_start(va, fmt);
|
2022-03-13 00:35:24 +00:00
|
|
|
res = vswprintf(query, size, fmt, va);
|
2022-03-13 22:59:52 +00:00
|
|
|
va_end(va);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (res == -1) size *= 2;
|
|
|
|
else if (res >= size) size = res + 1;
|
|
|
|
else break;
|
|
|
|
msi_free( query );
|
|
|
|
}
|
|
|
|
/* perform the query */
|
|
|
|
r = MSI_DatabaseOpenViewW(db, query, &view);
|
|
|
|
msi_free(query);
|
|
|
|
|
|
|
|
if( r == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
MSI_ViewExecute( view, NULL );
|
|
|
|
MSI_ViewFetch( view, &rec );
|
|
|
|
MSI_ViewClose( view );
|
|
|
|
msiobj_release( &view->hdr );
|
|
|
|
}
|
|
|
|
return rec;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
|
|
|
|
LPCWSTR szQuery, MSIHANDLE *phView)
|
|
|
|
{
|
|
|
|
MSIDATABASE *db;
|
|
|
|
MSIQUERY *query = NULL;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
TRACE("%s %p\n", debugstr_w(szQuery), phView);
|
|
|
|
|
2022-03-12 14:11:52 +00:00
|
|
|
if (!phView)
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
if (!szQuery)
|
|
|
|
return ERROR_BAD_QUERY_SYNTAX;
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
|
|
|
|
if( !db )
|
2008-01-16 10:11:22 +00:00
|
|
|
{
|
2022-03-12 14:11:52 +00:00
|
|
|
MSIHANDLE remote, remote_view;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2022-03-12 14:11:45 +00:00
|
|
|
if (!(remote = msi_get_remote(hdb)))
|
2008-01-16 10:11:22 +00:00
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
ret = remote_DatabaseOpenView(remote, szQuery, &remote_view);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
ret = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
2022-03-12 14:11:52 +00:00
|
|
|
if (!ret)
|
|
|
|
*phView = alloc_msi_remote_handle(remote_view);
|
|
|
|
return ret;
|
2008-01-16 10:11:22 +00:00
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
ret = MSI_DatabaseOpenViewW( db, szQuery, &query );
|
|
|
|
if( ret == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
*phView = alloc_msihandle( &query->hdr );
|
2006-08-30 19:24:26 +00:00
|
|
|
if (! *phView)
|
|
|
|
ret = ERROR_NOT_ENOUGH_MEMORY;
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
}
|
|
|
|
msiobj_release( &db->hdr );
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-12 23:16:38 +00:00
|
|
|
UINT msi_view_refresh_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD *rec)
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
UINT row_count = 0, col_count = 0, i, ival, ret, type;
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
TRACE("%p %p %d %p\n", db, view, row, rec);
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
ret = view->ops->get_dimensions(view, &row_count, &col_count);
|
|
|
|
if (ret)
|
2006-02-17 00:04:10 +00:00
|
|
|
return ret;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
|
|
|
if (!col_count)
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
for (i = 1; i <= col_count; i++)
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2009-11-16 01:13:42 +00:00
|
|
|
ret = view->ops->get_column_info(view, i, NULL, &type, NULL, NULL);
|
2008-01-16 10:11:22 +00:00
|
|
|
if (ret)
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
ERR("Error getting column type for %d\n", i);
|
2006-02-17 00:04:10 +00:00
|
|
|
continue;
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
|
|
|
if (MSITYPE_IS_BINARY(type))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
IStream *stm = NULL;
|
|
|
|
|
|
|
|
ret = view->ops->fetch_stream(view, row, i, &stm);
|
|
|
|
if ((ret == ERROR_SUCCESS) && stm)
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-12 23:16:38 +00:00
|
|
|
MSI_RecordSetIStream(rec, i, stm);
|
2008-01-16 10:11:22 +00:00
|
|
|
IStream_Release(stm);
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
else
|
2008-09-21 15:24:30 +00:00
|
|
|
WARN("failed to get stream\n");
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
ret = view->ops->fetch_int(view, row, i, &ival);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ERR("Error fetching data for %d\n", i);
|
|
|
|
continue;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
if (! (type & MSITYPE_VALID))
|
|
|
|
ERR("Invalid type!\n");
|
|
|
|
|
|
|
|
if (type & MSITYPE_STRING)
|
|
|
|
{
|
2012-12-09 19:43:59 +00:00
|
|
|
int len;
|
2022-03-12 23:16:38 +00:00
|
|
|
const WCHAR *sval = msi_string_lookup(db->strings, ival, &len);
|
|
|
|
msi_record_set_string(rec, i, sval, len);
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
if ((type & MSI_DATASIZEMASK) == 2)
|
2022-03-12 23:16:38 +00:00
|
|
|
MSI_RecordSetInteger(rec, i, ival ? ival - (1<<15) : MSI_NULL_INTEGER);
|
2006-02-17 00:04:10 +00:00
|
|
|
else
|
2022-03-12 23:16:38 +00:00
|
|
|
MSI_RecordSetInteger(rec, i, ival - (1u<<31));
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-03-12 23:16:38 +00:00
|
|
|
UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
|
|
|
|
{
|
|
|
|
UINT row_count = 0, col_count = 0, r;
|
|
|
|
MSIRECORD *object;
|
|
|
|
|
|
|
|
TRACE("view %p, row %u, rec %p.\n", view, row, rec);
|
|
|
|
|
|
|
|
if ((r = view->ops->get_dimensions(view, &row_count, &col_count)))
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (row >= row_count)
|
|
|
|
return ERROR_NO_MORE_ITEMS;
|
|
|
|
|
|
|
|
if (!(object = MSI_CreateRecord( col_count )))
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
|
|
|
if ((r = msi_view_refresh_row(db, view, row, object)))
|
|
|
|
msiobj_release( &object->hdr );
|
|
|
|
else
|
|
|
|
*rec = object;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
|
|
|
|
{
|
|
|
|
MSIVIEW *view;
|
|
|
|
UINT r;
|
|
|
|
|
|
|
|
TRACE("%p %p\n", query, prec );
|
|
|
|
|
|
|
|
view = query->view;
|
|
|
|
if( !view )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
|
|
|
|
r = msi_view_get_row(query->db, view, query->row, prec);
|
|
|
|
if (r == ERROR_SUCCESS)
|
2009-05-20 12:59:23 +00:00
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
query->row ++;
|
2022-03-12 23:08:18 +00:00
|
|
|
(*prec)->cookie = (UINT64)(ULONG_PTR)query;
|
2022-03-12 14:11:48 +00:00
|
|
|
MSI_RecordSetInteger(*prec, 0, 1);
|
2009-05-20 12:59:23 +00:00
|
|
|
}
|
2022-03-13 23:16:45 +00:00
|
|
|
else if (r == ERROR_NO_MORE_ITEMS)
|
|
|
|
{
|
|
|
|
/* end of view; reset cursor to first row */
|
|
|
|
query->row = 0;
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiViewFetch( MSIHANDLE hView, MSIHANDLE *record )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIQUERY *query;
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
UINT ret;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %p\n", hView, record );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2006-08-01 23:12:11 +00:00
|
|
|
if( !record )
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
*record = 0;
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
|
2022-03-12 14:11:54 +00:00
|
|
|
if (!query)
|
|
|
|
{
|
|
|
|
struct wire_record *wire_rec = NULL;
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(hView)))
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
ret = remote_ViewFetch(remote, &wire_rec);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
ret = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
2022-03-12 14:11:54 +00:00
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
ret = unmarshal_record(wire_rec, record);
|
|
|
|
free_remote_record(wire_rec);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
ret = MSI_ViewFetch( query, &rec );
|
|
|
|
if( ret == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
*record = alloc_msihandle( &rec->hdr );
|
2006-08-30 19:24:26 +00:00
|
|
|
if (! *record)
|
|
|
|
ret = ERROR_NOT_ENOUGH_MEMORY;
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &rec->hdr );
|
|
|
|
}
|
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT MSI_ViewClose(MSIQUERY *query)
|
|
|
|
{
|
|
|
|
MSIVIEW *view;
|
|
|
|
|
|
|
|
TRACE("%p\n", query );
|
|
|
|
|
|
|
|
view = query->view;
|
|
|
|
if( !view )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
if( !view->ops->close )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
|
|
|
|
return view->ops->close( view );
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiViewClose( MSIHANDLE hView )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIQUERY *query;
|
|
|
|
UINT ret;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu\n", hView );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
|
2022-03-12 14:11:54 +00:00
|
|
|
if (!query)
|
|
|
|
{
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(hView)))
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
ret = remote_ViewClose(remote);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
ret = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
|
|
|
return ret;
|
2022-03-12 14:11:54 +00:00
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
ret = MSI_ViewClose( query );
|
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT MSI_ViewExecute(MSIQUERY *query, MSIRECORD *rec )
|
|
|
|
{
|
|
|
|
MSIVIEW *view;
|
|
|
|
|
|
|
|
TRACE("%p %p\n", query, rec);
|
|
|
|
|
|
|
|
view = query->view;
|
|
|
|
if( !view )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
if( !view->ops->execute )
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
query->row = 0;
|
|
|
|
|
|
|
|
return view->ops->execute( view, rec );
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiViewExecute( MSIHANDLE hView, MSIHANDLE hRec )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIQUERY *query;
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
UINT ret;
|
2022-03-13 20:31:42 +00:00
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %lu\n", hView, hRec );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if( hRec )
|
|
|
|
{
|
|
|
|
rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD );
|
|
|
|
if( !rec )
|
2022-03-12 14:11:53 +00:00
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
|
|
|
|
if( !query )
|
|
|
|
{
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(hView)))
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
ret = remote_ViewExecute(remote, rec ? (struct wire_record *)&rec->count : NULL);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
ret = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
2022-03-12 14:11:53 +00:00
|
|
|
|
|
|
|
if (rec)
|
|
|
|
msiobj_release(&rec->hdr);
|
|
|
|
return ret;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
msiobj_lock( &rec->hdr );
|
|
|
|
ret = MSI_ViewExecute( query, rec );
|
|
|
|
msiobj_unlock( &rec->hdr );
|
|
|
|
|
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
if( rec )
|
|
|
|
msiobj_release( &rec->hdr );
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-05-20 12:59:23 +00:00
|
|
|
static UINT msi_set_record_type_string( MSIRECORD *rec, UINT field,
|
|
|
|
UINT type, BOOL temporary )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
WCHAR szType[0x10];
|
|
|
|
|
|
|
|
if (MSITYPE_IS_BINARY(type))
|
|
|
|
szType[0] = 'v';
|
|
|
|
else if (type & MSITYPE_LOCALIZABLE)
|
|
|
|
szType[0] = 'l';
|
2012-01-21 17:19:12 +00:00
|
|
|
else if (type & MSITYPE_UNKNOWN)
|
|
|
|
szType[0] = 'f';
|
2006-02-17 00:04:10 +00:00
|
|
|
else if (type & MSITYPE_STRING)
|
2009-05-20 12:59:23 +00:00
|
|
|
{
|
|
|
|
if (temporary)
|
|
|
|
szType[0] = 'g';
|
|
|
|
else
|
|
|
|
szType[0] = 's';
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
else
|
2009-05-20 12:59:23 +00:00
|
|
|
{
|
|
|
|
if (temporary)
|
|
|
|
szType[0] = 'j';
|
|
|
|
else
|
|
|
|
szType[0] = 'i';
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
if (type & MSITYPE_NULLABLE)
|
|
|
|
szType[0] &= ~0x20;
|
|
|
|
|
2022-03-13 20:31:42 +00:00
|
|
|
swprintf( &szType[1], ARRAY_SIZE(szType) - 1, L"%d", (type&0xff) );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
TRACE("type %04x -> %s\n", type, debugstr_w(szType) );
|
|
|
|
|
|
|
|
return MSI_RecordSetStringW( rec, field, szType );
|
|
|
|
}
|
|
|
|
|
2006-09-09 17:48:42 +00:00
|
|
|
UINT MSI_ViewGetColumnInfo( MSIQUERY *query, MSICOLINFO info, MSIRECORD **prec )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
UINT r = ERROR_FUNCTION_FAILED, i, count = 0, type;
|
2006-09-09 17:48:42 +00:00
|
|
|
MSIRECORD *rec;
|
|
|
|
MSIVIEW *view = query->view;
|
2012-01-21 17:19:12 +00:00
|
|
|
LPCWSTR name;
|
2009-05-20 12:59:23 +00:00
|
|
|
BOOL temporary;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if( !view )
|
2006-09-09 17:48:42 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if( !view->ops->get_dimensions )
|
2006-09-09 17:48:42 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
r = view->ops->get_dimensions( view, NULL, &count );
|
2006-09-09 17:48:42 +00:00
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
if( !count )
|
2006-09-09 17:48:42 +00:00
|
|
|
return ERROR_INVALID_PARAMETER;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
rec = MSI_CreateRecord( count );
|
|
|
|
if( !rec )
|
2006-09-09 17:48:42 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
for( i=0; i<count; i++ )
|
|
|
|
{
|
|
|
|
name = NULL;
|
2012-01-21 17:19:12 +00:00
|
|
|
r = view->ops->get_column_info( view, i+1, &name, &type, &temporary, NULL );
|
2006-02-17 00:04:10 +00:00
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
continue;
|
|
|
|
if (info == MSICOLINFO_NAMES)
|
|
|
|
MSI_RecordSetStringW( rec, i+1, name );
|
|
|
|
else
|
2009-05-20 12:59:23 +00:00
|
|
|
msi_set_record_type_string( rec, i+1, type, temporary );
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
2006-09-09 17:48:42 +00:00
|
|
|
*prec = rec;
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiViewGetColumnInfo( MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec )
|
2006-09-09 17:48:42 +00:00
|
|
|
{
|
|
|
|
MSIQUERY *query = NULL;
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
UINT r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %d, %p\n", hView, info, hRec );
|
2006-09-09 17:48:42 +00:00
|
|
|
|
|
|
|
if( !hRec )
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
if( info != MSICOLINFO_NAMES && info != MSICOLINFO_TYPES )
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
|
2022-03-12 14:11:55 +00:00
|
|
|
if (!query)
|
|
|
|
{
|
|
|
|
struct wire_record *wire_rec = NULL;
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(hView)))
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
r = remote_ViewGetColumnInfo(remote, info, &wire_rec);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
r = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
2022-03-12 14:11:55 +00:00
|
|
|
if (!r)
|
|
|
|
{
|
|
|
|
r = unmarshal_record(wire_rec, hRec);
|
|
|
|
free_remote_record(wire_rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
2006-09-09 17:48:42 +00:00
|
|
|
|
|
|
|
r = MSI_ViewGetColumnInfo( query, info, &rec );
|
|
|
|
if ( r == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
*hRec = alloc_msihandle( &rec->hdr );
|
|
|
|
if ( !*hRec )
|
|
|
|
r = ERROR_NOT_ENOUGH_MEMORY;
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &rec->hdr );
|
2006-09-09 17:48:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
msiobj_release( &query->hdr );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec )
|
|
|
|
{
|
|
|
|
MSIVIEW *view = NULL;
|
|
|
|
UINT r;
|
|
|
|
|
|
|
|
if ( !query || !rec )
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
|
|
|
view = query->view;
|
|
|
|
if ( !view || !view->ops->modify)
|
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
|
2022-03-12 23:08:18 +00:00
|
|
|
if ( mode == MSIMODIFY_UPDATE && rec->cookie != (UINT64)(ULONG_PTR)query )
|
2009-05-20 12:59:23 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
|
2022-03-12 23:16:30 +00:00
|
|
|
r = view->ops->modify( view, mode, rec, query->row - 1 );
|
2008-01-16 10:11:22 +00:00
|
|
|
if (mode == MSIMODIFY_DELETE && r == ERROR_SUCCESS)
|
|
|
|
query->row--;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiViewModify( MSIHANDLE hView, MSIMODIFY eModifyMode, MSIHANDLE hRecord )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIQUERY *query = NULL;
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
UINT r = ERROR_FUNCTION_FAILED;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %#x, %lu\n", hView, eModifyMode, hRecord );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-12 14:11:55 +00:00
|
|
|
rec = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
|
|
|
|
|
|
|
|
if (!rec)
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 14:11:55 +00:00
|
|
|
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
|
|
|
|
if (!query)
|
|
|
|
{
|
|
|
|
struct wire_record *wire_refreshed = NULL;
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(hView)))
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
r = remote_ViewModify(remote, eModifyMode,
|
|
|
|
(struct wire_record *)&rec->count, &wire_refreshed);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
r = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
2022-03-12 14:11:55 +00:00
|
|
|
if (!r && (eModifyMode == MSIMODIFY_REFRESH || eModifyMode == MSIMODIFY_SEEK))
|
|
|
|
{
|
|
|
|
r = copy_remote_record(wire_refreshed, hRecord);
|
|
|
|
free_remote_record(wire_refreshed);
|
|
|
|
}
|
|
|
|
|
|
|
|
msiobj_release(&rec->hdr);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
r = MSI_ViewModify( query, eModifyMode, rec );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
msiobj_release( &query->hdr );
|
2022-03-12 14:11:55 +00:00
|
|
|
msiobj_release(&rec->hdr);
|
2006-02-17 00:04:10 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
MSIDBERROR WINAPI MsiViewGetErrorW( MSIHANDLE handle, WCHAR *buffer, DWORD *buflen )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
MSIQUERY *query;
|
|
|
|
const WCHAR *column;
|
|
|
|
MSIDBERROR r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %p, %p\n", handle, buffer, buflen );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
if (!buflen)
|
2006-02-17 00:04:10 +00:00
|
|
|
return MSIDBERROR_INVALIDARG;
|
|
|
|
|
2022-03-13 00:21:43 +00:00
|
|
|
if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
|
|
|
|
{
|
|
|
|
WCHAR *remote_column = NULL;
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(handle)))
|
|
|
|
return MSIDBERROR_INVALIDARG;
|
|
|
|
|
|
|
|
if (!*buflen)
|
|
|
|
return MSIDBERROR_FUNCTIONERROR;
|
|
|
|
|
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
r = remote_ViewGetError(remote, &remote_column);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
r = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY;
|
|
|
|
|
2022-03-13 20:31:42 +00:00
|
|
|
if (msi_strncpyW(remote_column ? remote_column : L"", -1, buffer, buflen) == ERROR_MORE_DATA)
|
2022-03-13 00:21:43 +00:00
|
|
|
r = MSIDBERROR_MOREDATA;
|
|
|
|
|
|
|
|
if (remote_column)
|
|
|
|
midl_user_free(remote_column);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
if ((r = query->view->error)) column = query->view->error_column;
|
2022-03-13 20:31:42 +00:00
|
|
|
else column = L"";
|
2012-01-21 17:19:12 +00:00
|
|
|
|
2022-03-13 00:21:42 +00:00
|
|
|
if (msi_strncpyW(column, -1, buffer, buflen) == ERROR_MORE_DATA)
|
|
|
|
r = MSIDBERROR_MOREDATA;
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
MSIDBERROR WINAPI MsiViewGetErrorA( MSIHANDLE handle, char *buffer, DWORD *buflen )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
MSIQUERY *query;
|
|
|
|
const WCHAR *column;
|
|
|
|
MSIDBERROR r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %p, %p\n", handle, buffer, buflen );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
if (!buflen)
|
2006-02-17 00:04:10 +00:00
|
|
|
return MSIDBERROR_INVALIDARG;
|
|
|
|
|
2022-03-13 00:21:43 +00:00
|
|
|
if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
|
|
|
|
{
|
|
|
|
WCHAR *remote_column = NULL;
|
|
|
|
MSIHANDLE remote;
|
|
|
|
|
|
|
|
if (!(remote = msi_get_remote(handle)))
|
|
|
|
return MSIDBERROR_INVALIDARG;
|
|
|
|
|
|
|
|
if (!*buflen)
|
|
|
|
return MSIDBERROR_FUNCTIONERROR;
|
|
|
|
|
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
r = remote_ViewGetError(remote, &remote_column);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
r = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY;
|
|
|
|
|
2022-03-13 20:31:42 +00:00
|
|
|
if (msi_strncpyWtoA(remote_column ? remote_column : L"", -1, buffer, buflen, FALSE) == ERROR_MORE_DATA)
|
2022-03-13 00:21:43 +00:00
|
|
|
r = MSIDBERROR_MOREDATA;
|
|
|
|
|
|
|
|
if (remote_column)
|
|
|
|
midl_user_free(remote_column);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
if ((r = query->view->error)) column = query->view->error_column;
|
2022-03-13 20:31:42 +00:00
|
|
|
else column = L"";
|
2012-01-21 17:19:12 +00:00
|
|
|
|
2022-03-13 00:21:42 +00:00
|
|
|
if (msi_strncpyWtoA(column, -1, buffer, buflen, FALSE) == ERROR_MORE_DATA)
|
|
|
|
r = MSIDBERROR_MOREDATA;
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
MSIHANDLE WINAPI MsiGetLastErrorRecord( void )
|
|
|
|
{
|
|
|
|
FIXME("\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db, const WCHAR *transform, int error_cond )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-12 23:16:14 +00:00
|
|
|
HRESULT hr;
|
2006-10-22 20:23:59 +00:00
|
|
|
UINT ret = ERROR_FUNCTION_FAILED;
|
2022-03-12 23:16:14 +00:00
|
|
|
IStorage *stg;
|
2006-10-22 20:23:59 +00:00
|
|
|
STATSTG stat;
|
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
TRACE( "%p %s %08x\n", db, debugstr_w(transform), error_cond );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
if (*transform == ':')
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
{
|
2022-03-12 23:16:14 +00:00
|
|
|
hr = IStorage_OpenStorage( db->storage, transform + 1, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg );
|
|
|
|
if (FAILED( hr ))
|
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
WARN( "failed to open substorage transform %#lx\n", hr );
|
2022-03-12 23:16:14 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hr = StgOpenStorage( transform, NULL, STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg );
|
|
|
|
if (FAILED( hr ))
|
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
WARN( "failed to open file transform %#lx\n", hr );
|
2022-03-12 23:16:14 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
2006-10-22 20:23:59 +00:00
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
hr = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
|
|
|
|
if (FAILED( hr )) goto end;
|
|
|
|
if (!IsEqualGUID( &stat.clsid, &CLSID_MsiTransform )) goto end;
|
|
|
|
if (TRACE_ON( msi )) enum_stream_names( stg );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-13 18:08:38 +00:00
|
|
|
ret = msi_table_apply_transform( db, stg, error_cond );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2006-10-22 20:23:59 +00:00
|
|
|
end:
|
2006-02-17 00:04:10 +00:00
|
|
|
IStorage_Release( stg );
|
2006-10-22 20:23:59 +00:00
|
|
|
return ret;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb, const WCHAR *transform, int error_cond )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIDATABASE *db;
|
|
|
|
UINT r;
|
|
|
|
|
2022-03-13 18:08:38 +00:00
|
|
|
if (error_cond & ~MSITRANSFORM_ERROR_VIEWTRANSFORM) FIXME( "ignoring error conditions\n" );
|
2022-03-12 23:16:14 +00:00
|
|
|
|
2022-03-13 00:21:39 +00:00
|
|
|
if (!(db = msihandle2msiinfo(hdb, MSIHANDLETYPE_DATABASE)))
|
|
|
|
return ERROR_INVALID_HANDLE;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
r = MSI_DatabaseApplyTransformW( db, transform, error_cond );
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &db->hdr );
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb, const char *transform, int error_cond )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-12 23:16:14 +00:00
|
|
|
WCHAR *wstr;
|
2006-02-17 00:04:10 +00:00
|
|
|
UINT ret;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %s, %#x\n", hdb, debugstr_a(transform), error_cond );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
wstr = strdupAtoW( transform );
|
|
|
|
if (transform && !wstr)
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
2022-03-12 23:16:14 +00:00
|
|
|
ret = MsiDatabaseApplyTransformW( hdb, wstr, error_cond );
|
2006-02-17 00:04:10 +00:00
|
|
|
msi_free( wstr );
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref, const char *szTransformFile,
|
|
|
|
int iReserved1, int iReserved2 )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
FIXME( "%lu, %lu, %s, %d, %d\n", hdb, hdbref, debugstr_a(szTransformFile), iReserved1, iReserved2 );
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref, const WCHAR *szTransformFile,
|
|
|
|
int iReserved1, int iReserved2 )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
FIXME( "%lu, %lu, %s, %d, %d\n", hdb, hdbref, debugstr_w(szTransformFile), iReserved1, iReserved2 );
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
|
|
|
|
{
|
|
|
|
MSIDATABASE *db;
|
|
|
|
UINT r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu\n", hdb );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
|
|
|
|
if( !db )
|
2008-01-16 10:11:22 +00:00
|
|
|
{
|
2022-03-12 14:11:45 +00:00
|
|
|
MSIHANDLE remote;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2022-03-12 14:11:45 +00:00
|
|
|
if (!(remote = msi_get_remote(hdb)))
|
2008-01-16 10:11:22 +00:00
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2010-02-06 21:28:28 +00:00
|
|
|
WARN("not allowed during a custom action!\n");
|
2008-01-16 10:11:22 +00:00
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2022-03-13 18:05:01 +00:00
|
|
|
if (db->mode == MSI_OPEN_READONLY)
|
2012-01-21 17:19:12 +00:00
|
|
|
{
|
|
|
|
msiobj_release( &db->hdr );
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
/* FIXME: lock the database */
|
|
|
|
|
2015-03-09 20:28:19 +00:00
|
|
|
r = msi_commit_streams( db );
|
|
|
|
if (r != ERROR_SUCCESS) ERR("Failed to commit streams!\n");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r = MSI_CommitTables( db );
|
|
|
|
if (r != ERROR_SUCCESS) ERR("Failed to commit tables!\n");
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
/* FIXME: unlock the database */
|
|
|
|
|
|
|
|
msiobj_release( &db->hdr );
|
|
|
|
|
2006-09-18 16:45:21 +00:00
|
|
|
if (r == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
msi_free( db->deletefile );
|
|
|
|
db->deletefile = NULL;
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct msi_primary_key_record_info
|
|
|
|
{
|
|
|
|
DWORD n;
|
|
|
|
MSIRECORD *rec;
|
|
|
|
};
|
|
|
|
|
|
|
|
static UINT msi_primary_key_iterator( MSIRECORD *rec, LPVOID param )
|
|
|
|
{
|
|
|
|
struct msi_primary_key_record_info *info = param;
|
2009-05-20 12:59:23 +00:00
|
|
|
LPCWSTR name, table;
|
2006-02-17 00:04:10 +00:00
|
|
|
DWORD type;
|
|
|
|
|
|
|
|
type = MSI_RecordGetInteger( rec, 4 );
|
|
|
|
if( type & MSITYPE_KEY )
|
|
|
|
{
|
|
|
|
info->n++;
|
|
|
|
if( info->rec )
|
|
|
|
{
|
2009-05-20 12:59:23 +00:00
|
|
|
if ( info->n == 1 )
|
|
|
|
{
|
|
|
|
table = MSI_RecordGetString( rec, 1 );
|
|
|
|
MSI_RecordSetStringW( info->rec, 0, table);
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
name = MSI_RecordGetString( rec, 3 );
|
|
|
|
MSI_RecordSetStringW( info->rec, info->n, name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *db,
|
|
|
|
LPCWSTR table, MSIRECORD **prec )
|
|
|
|
{
|
|
|
|
struct msi_primary_key_record_info info;
|
|
|
|
MSIQUERY *query = NULL;
|
|
|
|
UINT r;
|
2008-05-17 19:46:01 +00:00
|
|
|
|
2010-10-22 13:18:11 +00:00
|
|
|
if (!TABLE_Exists( db, table ))
|
|
|
|
return ERROR_INVALID_TABLE;
|
|
|
|
|
2022-03-13 20:31:42 +00:00
|
|
|
r = MSI_OpenQuery( db, &query, L"SELECT * FROM `_Columns` WHERE `Table` = '%s'", table );
|
2006-02-17 00:04:10 +00:00
|
|
|
if( r != ERROR_SUCCESS )
|
|
|
|
return r;
|
|
|
|
|
|
|
|
/* count the number of primary key records */
|
|
|
|
info.n = 0;
|
|
|
|
info.rec = 0;
|
|
|
|
r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info );
|
|
|
|
if( r == ERROR_SUCCESS )
|
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "found %lu primary keys\n", info.n );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
/* allocate a record and fill in the names of the tables */
|
|
|
|
info.rec = MSI_CreateRecord( info.n );
|
|
|
|
info.n = 0;
|
|
|
|
r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info );
|
|
|
|
if( r == ERROR_SUCCESS )
|
|
|
|
*prec = info.rec;
|
|
|
|
else
|
|
|
|
msiobj_release( &info.rec->hdr );
|
|
|
|
}
|
|
|
|
msiobj_release( &query->hdr );
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiDatabaseGetPrimaryKeysW( MSIHANDLE hdb, const WCHAR *table, MSIHANDLE *phRec )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
MSIRECORD *rec = NULL;
|
|
|
|
MSIDATABASE *db;
|
|
|
|
UINT r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %s, %p\n", hdb, debugstr_w(table), phRec );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
|
|
|
|
if( !db )
|
2008-01-16 10:11:22 +00:00
|
|
|
{
|
2022-03-12 14:11:56 +00:00
|
|
|
struct wire_record *wire_rec = NULL;
|
2022-03-12 14:11:45 +00:00
|
|
|
MSIHANDLE remote;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2022-03-12 14:11:45 +00:00
|
|
|
if (!(remote = msi_get_remote(hdb)))
|
2008-01-16 10:11:22 +00:00
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
r = remote_DatabaseGetPrimaryKeys(remote, table, &wire_rec);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
r = GetExceptionCode();
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
2022-03-12 14:11:56 +00:00
|
|
|
if (!r)
|
2008-01-16 10:11:22 +00:00
|
|
|
{
|
2022-03-12 14:11:56 +00:00
|
|
|
r = unmarshal_record(wire_rec, phRec);
|
|
|
|
free_remote_record(wire_rec);
|
2008-01-16 10:11:22 +00:00
|
|
|
}
|
|
|
|
|
2022-03-12 14:11:56 +00:00
|
|
|
return r;
|
2008-01-16 10:11:22 +00:00
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
r = MSI_DatabaseGetPrimaryKeys( db, table, &rec );
|
|
|
|
if( r == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
*phRec = alloc_msihandle( &rec->hdr );
|
2006-08-30 19:24:26 +00:00
|
|
|
if (! *phRec)
|
|
|
|
r = ERROR_NOT_ENOUGH_MEMORY;
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &rec->hdr );
|
|
|
|
}
|
|
|
|
msiobj_release( &db->hdr );
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
UINT WINAPI MsiDatabaseGetPrimaryKeysA( MSIHANDLE hdb, const char *table, MSIHANDLE *phRec )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
WCHAR *szwTable = NULL;
|
2006-02-17 00:04:10 +00:00
|
|
|
UINT r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %s, %p\n", hdb, debugstr_a(table), phRec );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if( table )
|
|
|
|
{
|
|
|
|
szwTable = strdupAtoW( table );
|
|
|
|
if( !szwTable )
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
r = MsiDatabaseGetPrimaryKeysW( hdb, szwTable, phRec );
|
|
|
|
msi_free( szwTable );
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
MSICONDITION WINAPI MsiDatabaseIsTablePersistentA( MSIHANDLE hDatabase, const char *szTableName )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2022-03-14 20:20:29 +00:00
|
|
|
WCHAR *szwTableName = NULL;
|
2006-08-01 23:12:11 +00:00
|
|
|
MSICONDITION r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %s\n", hDatabase, debugstr_a(szTableName) );
|
2006-08-01 23:12:11 +00:00
|
|
|
|
|
|
|
if( szTableName )
|
|
|
|
{
|
|
|
|
szwTableName = strdupAtoW( szTableName );
|
|
|
|
if( !szwTableName )
|
|
|
|
return MSICONDITION_ERROR;
|
|
|
|
}
|
|
|
|
r = MsiDatabaseIsTablePersistentW( hDatabase, szwTableName );
|
|
|
|
msi_free( szwTableName );
|
|
|
|
|
|
|
|
return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
MSICONDITION WINAPI MsiDatabaseIsTablePersistentW( MSIHANDLE hDatabase, const WCHAR *szTableName )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2006-09-18 16:45:21 +00:00
|
|
|
MSIDATABASE *db;
|
|
|
|
MSICONDITION r;
|
|
|
|
|
2022-03-14 20:20:29 +00:00
|
|
|
TRACE( "%lu, %s\n", hDatabase, debugstr_w(szTableName) );
|
2006-09-18 16:45:21 +00:00
|
|
|
|
|
|
|
db = msihandle2msiinfo( hDatabase, MSIHANDLETYPE_DATABASE );
|
|
|
|
if( !db )
|
2008-01-16 10:11:22 +00:00
|
|
|
{
|
2022-03-12 14:11:45 +00:00
|
|
|
MSIHANDLE remote;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2022-03-12 14:11:45 +00:00
|
|
|
if (!(remote = msi_get_remote(hDatabase)))
|
2008-01-16 10:11:22 +00:00
|
|
|
return MSICONDITION_ERROR;
|
|
|
|
|
2022-03-12 22:54:40 +00:00
|
|
|
__TRY
|
|
|
|
{
|
|
|
|
r = remote_DatabaseIsTablePersistent(remote, szTableName);
|
|
|
|
}
|
|
|
|
__EXCEPT(rpc_filter)
|
|
|
|
{
|
|
|
|
r = MSICONDITION_ERROR;
|
|
|
|
}
|
|
|
|
__ENDTRY
|
|
|
|
|
|
|
|
return r;
|
2008-01-16 10:11:22 +00:00
|
|
|
}
|
2006-09-18 16:45:21 +00:00
|
|
|
|
|
|
|
r = MSI_DatabaseIsTablePersistent( db, szTableName );
|
|
|
|
|
|
|
|
msiobj_release( &db->hdr );
|
|
|
|
|
|
|
|
return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
2022-03-12 14:11:53 +00:00
|
|
|
|
2022-03-12 14:12:08 +00:00
|
|
|
UINT __cdecl s_remote_ViewClose(MSIHANDLE view)
|
2022-03-12 14:11:54 +00:00
|
|
|
{
|
|
|
|
return MsiViewClose(view);
|
|
|
|
}
|
|
|
|
|
2022-03-12 14:12:08 +00:00
|
|
|
UINT __cdecl s_remote_ViewExecute(MSIHANDLE view, struct wire_record *remote_rec)
|
2022-03-12 14:11:53 +00:00
|
|
|
{
|
|
|
|
MSIHANDLE rec = 0;
|
|
|
|
UINT r;
|
|
|
|
|
|
|
|
if ((r = unmarshal_record(remote_rec, &rec)))
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = MsiViewExecute(view, rec);
|
|
|
|
|
|
|
|
MsiCloseHandle(rec);
|
|
|
|
return r;
|
|
|
|
}
|
2022-03-12 14:11:54 +00:00
|
|
|
|
2022-03-12 14:12:08 +00:00
|
|
|
UINT __cdecl s_remote_ViewFetch(MSIHANDLE view, struct wire_record **rec)
|
2022-03-12 14:11:54 +00:00
|
|
|
{
|
|
|
|
MSIHANDLE handle;
|
|
|
|
UINT r = MsiViewFetch(view, &handle);
|
|
|
|
*rec = NULL;
|
|
|
|
if (!r)
|
|
|
|
*rec = marshal_record(handle);
|
|
|
|
MsiCloseHandle(handle);
|
|
|
|
return r;
|
|
|
|
}
|
2022-03-12 14:11:55 +00:00
|
|
|
|
2022-03-12 14:12:08 +00:00
|
|
|
UINT __cdecl s_remote_ViewGetColumnInfo(MSIHANDLE view, MSICOLINFO info, struct wire_record **rec)
|
2022-03-12 14:11:55 +00:00
|
|
|
{
|
|
|
|
MSIHANDLE handle;
|
|
|
|
UINT r = MsiViewGetColumnInfo(view, info, &handle);
|
|
|
|
*rec = NULL;
|
|
|
|
if (!r)
|
|
|
|
*rec = marshal_record(handle);
|
|
|
|
MsiCloseHandle(handle);
|
|
|
|
return r;
|
|
|
|
}
|
2022-03-12 14:11:55 +00:00
|
|
|
|
2022-03-13 00:21:43 +00:00
|
|
|
MSIDBERROR __cdecl s_remote_ViewGetError(MSIHANDLE view, LPWSTR *column)
|
|
|
|
{
|
|
|
|
WCHAR empty[1];
|
|
|
|
DWORD size = 1;
|
|
|
|
UINT r;
|
|
|
|
|
|
|
|
r = MsiViewGetErrorW(view, empty, &size);
|
|
|
|
if (r == MSIDBERROR_MOREDATA)
|
|
|
|
{
|
|
|
|
if (!(*column = midl_user_allocate(++size * sizeof(WCHAR))))
|
|
|
|
return MSIDBERROR_FUNCTIONERROR;
|
|
|
|
r = MsiViewGetErrorW(view, *column, &size);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2022-03-12 14:12:08 +00:00
|
|
|
UINT __cdecl s_remote_ViewModify(MSIHANDLE view, MSIMODIFY mode,
|
2022-03-12 14:11:55 +00:00
|
|
|
struct wire_record *remote_rec, struct wire_record **remote_refreshed)
|
|
|
|
{
|
|
|
|
MSIHANDLE handle = 0;
|
|
|
|
UINT r;
|
|
|
|
|
|
|
|
if ((r = unmarshal_record(remote_rec, &handle)))
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = MsiViewModify(view, mode, handle);
|
|
|
|
*remote_refreshed = NULL;
|
|
|
|
if (!r && (mode == MSIMODIFY_REFRESH || mode == MSIMODIFY_SEEK))
|
|
|
|
*remote_refreshed = marshal_record(handle);
|
|
|
|
|
|
|
|
MsiCloseHandle(handle);
|
|
|
|
return r;
|
|
|
|
}
|