update.c 6.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Implementation of the Microsoft Installer (msi.dll)
 *
 * Copyright 2004 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.
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 */

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"

#include "query.h"

36
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
37 38 39 40 41 42 43 44 45


/* below is the query interface to a table */

typedef struct tagMSIUPDATEVIEW
{
    MSIVIEW          view;
    MSIDATABASE     *db;
    MSIVIEW         *wv;
46
    column_info     *vals;
47 48 49 50 51 52 53 54 55 56 57
} MSIUPDATEVIEW;

static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;

    TRACE("%p %d %d %p\n", uv, row, col, val );

    return ERROR_FUNCTION_FAILED;
}

58
static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
59 60
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
61
    UINT i, r, col_count = 0, row_count = 0;
62
    MSIRECORD *values = NULL;
63
    MSIRECORD *where = NULL;
64
    MSIVIEW *wv;
65 66
    UINT cols_count, where_count;
    column_info *col = uv->vals;
67

68
    TRACE("%p %p\n", uv, record );
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
    /* extract the where markers from the record */
    if (record)
    {
        r = MSI_RecordGetFieldCount(record);

        for (i = 0; col; col = col->next)
            i++;

        cols_count = i;
        where_count = r - i;

        if (where_count > 0)
        {
            where = MSI_CreateRecord(where_count);

            if (where)
                for (i = 1; i <= where_count; i++)
                    MSI_RecordCopyField(record, cols_count + i, where, i);
        }
    }

91 92
    wv = uv->wv;
    if( !wv )
93 94 95 96
    {
        r = ERROR_FUNCTION_FAILED;
        goto done;
    }
97

98
    r = wv->ops->execute( wv, where );
99 100
    TRACE("tv execute returned %x\n", r);
    if( r )
101
        goto done;
102 103 104

    r = wv->ops->get_dimensions( wv, &row_count, &col_count );
    if( r )
105
        goto done;
106

107 108
    values = msi_query_merge_record( col_count, uv->vals, record );
    if (!values)
109 110 111 112
    {
        r = ERROR_FUNCTION_FAILED;
        goto done;
    }
113

114
    for ( i=0; i<row_count; i++ )
115
    {
116 117 118
        r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 );
        if (r != ERROR_SUCCESS)
            break;
119 120
    }

121 122 123
done:
    if ( where ) msiobj_release( &where->hdr );
    if ( values ) msiobj_release( &values->hdr );
124

125
    return r;
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
}


static UINT UPDATE_close( struct tagMSIVIEW *view )
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
    MSIVIEW *wv;

    TRACE("%p\n", uv);

    wv = uv->wv;
    if( !wv )
        return ERROR_FUNCTION_FAILED;

    return wv->ops->close( wv );
}

static UINT UPDATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
    MSIVIEW *wv;

    TRACE("%p %p %p\n", uv, rows, cols );

    wv = uv->wv;
    if( !wv )
        return ERROR_FUNCTION_FAILED;

    return wv->ops->get_dimensions( wv, rows, cols );
}

157 158
static UINT UPDATE_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name,
                                    UINT *type, BOOL *temporary, LPCWSTR *table_name )
159 160 161 162
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
    MSIVIEW *wv;

163
    TRACE("%p %d %p %p %p %p\n", uv, n, name, type, temporary, table_name );
164 165 166 167 168

    wv = uv->wv;
    if( !wv )
        return ERROR_FUNCTION_FAILED;

169
    return wv->ops->get_column_info( wv, n, name, type, temporary, table_name );
170 171
}

172
static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
173
                           MSIRECORD *rec, UINT row )
174 175 176
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;

177
    TRACE("%p %d %p\n", uv, eModifyMode, rec );
178 179 180 181 182 183 184 185 186 187 188 189 190 191

    return ERROR_FUNCTION_FAILED;
}

static UINT UPDATE_delete( struct tagMSIVIEW *view )
{
    MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
    MSIVIEW *wv;

    TRACE("%p\n", uv );

    wv = uv->wv;
    if( wv )
        wv->ops->delete( wv );
192
    msiobj_release( &uv->db->hdr );
193
    msi_free( uv );
194 195 196 197

    return ERROR_SUCCESS;
}

198 199 200 201 202 203 204
static UINT UPDATE_find_matching_rows( struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle )
{
    TRACE("%p %d %d %p\n", view, col, val, *handle );

    return ERROR_FUNCTION_FAILED;
}

205

206
static const MSIVIEWOPS update_ops =
207 208 209 210
{
    UPDATE_fetch_int,
    NULL,
    NULL,
211
    NULL,
212
    NULL,
213
    NULL,
214 215 216 217 218
    UPDATE_execute,
    UPDATE_close,
    UPDATE_get_dimensions,
    UPDATE_get_column_info,
    UPDATE_modify,
219
    UPDATE_delete,
220 221 222
    UPDATE_find_matching_rows,
    NULL,
    NULL,
223
    NULL,
224
    NULL,
225
    NULL,
226 227
};

228
UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
229
                        column_info *columns, struct expr *expr )
230 231 232
{
    MSIUPDATEVIEW *uv = NULL;
    UINT r;
233
    MSIVIEW *sv = NULL, *wv = NULL;
234 235 236

    TRACE("%p\n", uv );

237
    if (expr)
238
        r = WHERE_CreateView( db, &wv, table, expr );
239
    else
240 241 242 243
        r = TABLE_CreateView( db, table, &wv );

    if( r != ERROR_SUCCESS )
        return r;
244

245
    /* then select the columns we want */
246
    r = SELECT_CreateView( db, &sv, wv, columns );
247 248
    if( r != ERROR_SUCCESS )
    {
249
        wv->ops->delete( wv );
250 251 252
        return r;
    }

253
    uv = msi_alloc_zero( sizeof *uv );
254
    if( !uv )
255 256
    {
        wv->ops->delete( wv );
257
        return ERROR_FUNCTION_FAILED;
258
    }
259 260 261

    /* fill the structure */
    uv->view.ops = &update_ops;
262
    msiobj_addref( &db->hdr );
263
    uv->db = db;
264
    uv->vals = columns;
265 266 267 268 269
    uv->wv = sv;
    *view = (MSIVIEW*) uv;

    return ERROR_SUCCESS;
}