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 "msipriv.h" 22 23 WINE_DEFAULT_DEBUG_CHANNEL(msidb); 24 25 /* below is the query interface to a table */ 26 27 typedef struct tagMSIUPDATEVIEW 28 { 29 MSIVIEW view; 30 MSIDATABASE *db; 31 MSIVIEW *wv; 32 column_info *vals; 33 } MSIUPDATEVIEW; 34 35 static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) 36 { 37 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 38 39 TRACE("%p %d %d %p\n", uv, row, col, val ); 40 41 return ERROR_FUNCTION_FAILED; 42 } 43 44 static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) 45 { 46 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 47 UINT i, r, col_count = 0, row_count = 0; 48 MSIRECORD *values = NULL; 49 MSIRECORD *where = NULL; 50 MSIVIEW *wv; 51 UINT cols_count, where_count; 52 column_info *col = uv->vals; 53 54 TRACE("%p %p\n", uv, record ); 55 56 /* extract the where markers from the record */ 57 if (record) 58 { 59 r = MSI_RecordGetFieldCount(record); 60 61 for (i = 0; col; col = col->next) 62 i++; 63 64 cols_count = i; 65 where_count = r - i; 66 67 if (where_count > 0) 68 { 69 where = MSI_CreateRecord(where_count); 70 71 if (where) 72 for (i = 1; i <= where_count; i++) 73 MSI_RecordCopyField(record, cols_count + i, where, i); 74 } 75 } 76 77 wv = uv->wv; 78 if( !wv ) 79 { 80 r = ERROR_FUNCTION_FAILED; 81 goto done; 82 } 83 84 r = wv->ops->execute( wv, where ); 85 TRACE("tv execute returned %x\n", r); 86 if( r ) 87 goto done; 88 89 r = wv->ops->get_dimensions( wv, &row_count, &col_count ); 90 if( r ) 91 goto done; 92 93 values = msi_query_merge_record( col_count, uv->vals, record ); 94 if (!values) 95 { 96 r = ERROR_FUNCTION_FAILED; 97 goto done; 98 } 99 100 for ( i=0; i<row_count; i++ ) 101 { 102 r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 ); 103 if (r != ERROR_SUCCESS) 104 break; 105 } 106 107 done: 108 if ( where ) msiobj_release( &where->hdr ); 109 if ( values ) msiobj_release( &values->hdr ); 110 111 return r; 112 } 113 114 115 static UINT UPDATE_close( struct tagMSIVIEW *view ) 116 { 117 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 118 MSIVIEW *wv; 119 120 TRACE("%p\n", uv); 121 122 wv = uv->wv; 123 if( !wv ) 124 return ERROR_FUNCTION_FAILED; 125 126 return wv->ops->close( wv ); 127 } 128 129 static UINT UPDATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) 130 { 131 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 132 MSIVIEW *wv; 133 134 TRACE("%p %p %p\n", uv, rows, cols ); 135 136 wv = uv->wv; 137 if( !wv ) 138 return ERROR_FUNCTION_FAILED; 139 140 return wv->ops->get_dimensions( wv, rows, cols ); 141 } 142 143 static UINT UPDATE_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name, 144 UINT *type, BOOL *temporary, LPCWSTR *table_name ) 145 { 146 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 147 MSIVIEW *wv; 148 149 TRACE("%p %d %p %p %p %p\n", uv, n, name, type, temporary, table_name ); 150 151 wv = uv->wv; 152 if( !wv ) 153 return ERROR_FUNCTION_FAILED; 154 155 return wv->ops->get_column_info( wv, n, name, type, temporary, table_name ); 156 } 157 158 static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, 159 MSIRECORD *rec, UINT row ) 160 { 161 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 162 163 TRACE("%p %d %p\n", uv, eModifyMode, rec ); 164 165 return ERROR_FUNCTION_FAILED; 166 } 167 168 static UINT UPDATE_delete( struct tagMSIVIEW *view ) 169 { 170 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; 171 MSIVIEW *wv; 172 173 TRACE("%p\n", uv ); 174 175 wv = uv->wv; 176 if( wv ) 177 wv->ops->delete( wv ); 178 msiobj_release( &uv->db->hdr ); 179 msi_free( uv ); 180 181 return ERROR_SUCCESS; 182 } 183 184 static UINT UPDATE_find_matching_rows( struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle ) 185 { 186 TRACE("%p %d %d %p\n", view, col, val, *handle ); 187 188 return ERROR_FUNCTION_FAILED; 189 } 190 191 192 static const MSIVIEWOPS update_ops = 193 { 194 UPDATE_fetch_int, 195 NULL, 196 NULL, 197 NULL, 198 NULL, 199 NULL, 200 UPDATE_execute, 201 UPDATE_close, 202 UPDATE_get_dimensions, 203 UPDATE_get_column_info, 204 UPDATE_modify, 205 UPDATE_delete, 206 UPDATE_find_matching_rows, 207 NULL, 208 NULL, 209 NULL, 210 NULL, 211 NULL, 212 }; 213 214 UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table, 215 column_info *columns, struct expr *expr ) 216 { 217 MSIUPDATEVIEW *uv = NULL; 218 UINT r; 219 MSIVIEW *sv = NULL, *wv = NULL; 220 221 TRACE("%p\n", uv ); 222 223 if (expr) 224 r = WHERE_CreateView( db, &wv, table, expr ); 225 else 226 r = TABLE_CreateView( db, table, &wv ); 227 228 if( r != ERROR_SUCCESS ) 229 return r; 230 231 /* then select the columns we want */ 232 r = SELECT_CreateView( db, &sv, wv, columns ); 233 if( r != ERROR_SUCCESS ) 234 { 235 wv->ops->delete( wv ); 236 return r; 237 } 238 239 uv = msi_alloc_zero( sizeof *uv ); 240 if( !uv ) 241 { 242 wv->ops->delete( wv ); 243 return ERROR_FUNCTION_FAILED; 244 } 245 246 /* fill the structure */ 247 uv->view.ops = &update_ops; 248 msiobj_addref( &db->hdr ); 249 uv->db = db; 250 uv->vals = columns; 251 uv->wv = sv; 252 *view = (MSIVIEW*) uv; 253 254 return ERROR_SUCCESS; 255 } 256