1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2004 Mike McCormack for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 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 #include <stdarg.h> 22 23 #include "windef.h" 24 #include "winbase.h" 25 #include "winerror.h" 26 #include "wine/debug.h" 27 #include "msi.h" 28 #include "msiquery.h" 29 #include "objbase.h" 30 #include "objidl.h" 31 #include "msipriv.h" 32 #include "winnls.h" 33 34 #include "query.h" 35 36 WINE_DEFAULT_DEBUG_CHANNEL(msidb); 37 38 39 /* below is the query interface to a table */ 40 41 typedef struct tagMSIUPDATEVIEW 42 { 43 MSIVIEW view; 44 MSIDATABASE *db; 45 MSIVIEW *wv; 46 column_info *vals; 47 } MSIUPDATEVIEW; 48 49 static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) 50 { 51 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 52 53 TRACE("%p %d %d %p\n", uv, row, col, val ); 54 55 return ERROR_FUNCTION_FAILED; 56 } 57 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 UINT cols_count, where_count; 66 column_info *col = uv->vals; 67 68 TRACE("%p %p\n", uv, record ); 69 70 /* extract the where markers from the record */ 71 if (record) 72 { 73 r = MSI_RecordGetFieldCount(record); 74 75 for (i = 0; col; col = col->next) 76 i++; 77 78 cols_count = i; 79 where_count = r - i; 80 81 if (where_count > 0) 82 { 83 where = MSI_CreateRecord(where_count); 84 85 if (where) 86 for (i = 1; i <= where_count; i++) 87 MSI_RecordCopyField(record, cols_count + i, where, i); 88 } 89 } 90 91 wv = uv->wv; 92 if( !wv ) 93 { 94 r = ERROR_FUNCTION_FAILED; 95 goto done; 96 } 97 98 r = wv->ops->execute( wv, where ); 99 TRACE("tv execute returned %x\n", r); 100 if( r ) 101 goto done; 102 103 r = wv->ops->get_dimensions( wv, &row_count, &col_count ); 104 if( r ) 105 goto done; 106 107 values = msi_query_merge_record( col_count, uv->vals, record ); 108 if (!values) 109 { 110 r = ERROR_FUNCTION_FAILED; 111 goto done; 112 } 113 114 for ( i=0; i<row_count; i++ ) 115 { 116 r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 ); 117 if (r != ERROR_SUCCESS) 118 break; 119 } 120 121 done: 122 if ( where ) msiobj_release( &where->hdr ); 123 if ( values ) msiobj_release( &values->hdr ); 124 125 return r; 126 } 127 128 129 static UINT UPDATE_close( struct tagMSIVIEW *view ) 130 { 131 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 132 MSIVIEW *wv; 133 134 TRACE("%p\n", uv); 135 136 wv = uv->wv; 137 if( !wv ) 138 return ERROR_FUNCTION_FAILED; 139 140 return wv->ops->close( wv ); 141 } 142 143 static UINT UPDATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) 144 { 145 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 146 MSIVIEW *wv; 147 148 TRACE("%p %p %p\n", uv, rows, cols ); 149 150 wv = uv->wv; 151 if( !wv ) 152 return ERROR_FUNCTION_FAILED; 153 154 return wv->ops->get_dimensions( wv, rows, cols ); 155 } 156 157 static UINT UPDATE_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name, 158 UINT *type, BOOL *temporary, LPCWSTR *table_name ) 159 { 160 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 161 MSIVIEW *wv; 162 163 TRACE("%p %d %p %p %p %p\n", uv, n, name, type, temporary, table_name ); 164 165 wv = uv->wv; 166 if( !wv ) 167 return ERROR_FUNCTION_FAILED; 168 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 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 176 177 TRACE("%p %d %p\n", uv, eModifyMode, rec ); 178 179 return ERROR_FUNCTION_FAILED; 180 } 181 182 static UINT UPDATE_delete( struct tagMSIVIEW *view ) 183 { 184 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 185 MSIVIEW *wv; 186 187 TRACE("%p\n", uv ); 188 189 wv = uv->wv; 190 if( wv ) 191 wv->ops->delete( wv ); 192 msiobj_release( &uv->db->hdr ); 193 msi_free( uv ); 194 195 return ERROR_SUCCESS; 196 } 197 198 static UINT UPDATE_find_matching_rows( struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle ) 199 { 200 TRACE("%p %d %d %p\n", view, col, val, *handle ); 201 202 return ERROR_FUNCTION_FAILED; 203 } 204 205 206 static const MSIVIEWOPS update_ops = 207 { 208 UPDATE_fetch_int, 209 NULL, 210 NULL, 211 NULL, 212 NULL, 213 NULL, 214 UPDATE_execute, 215 UPDATE_close, 216 UPDATE_get_dimensions, 217 UPDATE_get_column_info, 218 UPDATE_modify, 219 UPDATE_delete, 220 UPDATE_find_matching_rows, 221 NULL, 222 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 MSIUPDATEVIEW *uv = NULL; 232 UINT r; 233 MSIVIEW *sv = NULL, *wv = NULL; 234 235 TRACE("%p\n", uv ); 236 237 if (expr) 238 r = WHERE_CreateView( db, &wv, table, expr ); 239 else 240 r = TABLE_CreateView( db, table, &wv ); 241 242 if( r != ERROR_SUCCESS ) 243 return r; 244 245 /* then select the columns we want */ 246 r = SELECT_CreateView( db, &sv, wv, columns ); 247 if( r != ERROR_SUCCESS ) 248 { 249 wv->ops->delete( wv ); 250 return r; 251 } 252 253 uv = msi_alloc_zero( sizeof *uv ); 254 if( !uv ) 255 { 256 wv->ops->delete( wv ); 257 return ERROR_FUNCTION_FAILED; 258 } 259 260 /* fill the structure */ 261 uv->view.ops = &update_ops; 262 msiobj_addref( &db->hdr ); 263 uv->db = db; 264 uv->vals = columns; 265 uv->wv = sv; 266 *view = (MSIVIEW*) uv; 267 268 return ERROR_SUCCESS; 269 } 270