1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2002-2005 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 /* 40 * Code to delete rows from a table. 41 * 42 * We delete rows by blanking them out rather than trying to remove the row. 43 * This appears to be what the native MSI does (or tries to do). For the query: 44 * 45 * delete from Property 46 * 47 * some non-zero entries are left in the table by native MSI. I'm not sure if 48 * that's a bug in the way I'm running the query, or a just a bug. 49 */ 50 51 typedef struct tagMSIDELETEVIEW 52 { 53 MSIVIEW view; 54 MSIDATABASE *db; 55 MSIVIEW *table; 56 } MSIDELETEVIEW; 57 58 static UINT DELETE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) 59 { 60 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 61 62 TRACE("%p %d %d %p\n", dv, row, col, val ); 63 64 return ERROR_FUNCTION_FAILED; 65 } 66 67 static UINT DELETE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm) 68 { 69 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 70 71 TRACE("%p %d %d %p\n", dv, row, col, stm ); 72 73 return ERROR_FUNCTION_FAILED; 74 } 75 76 static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) 77 { 78 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 79 UINT r, i, rows = 0, cols = 0; 80 81 TRACE("%p %p\n", dv, record); 82 83 if( !dv->table ) 84 return ERROR_FUNCTION_FAILED; 85 86 r = dv->table->ops->execute( dv->table, record ); 87 if( r != ERROR_SUCCESS ) 88 return r; 89 90 r = dv->table->ops->get_dimensions( dv->table, &rows, &cols ); 91 if( r != ERROR_SUCCESS ) 92 return r; 93 94 TRACE("deleting %d rows\n", rows); 95 96 /* blank out all the rows that match */ 97 for ( i=0; i<rows; i++ ) 98 dv->table->ops->delete_row( dv->table, i ); 99 100 return ERROR_SUCCESS; 101 } 102 103 static UINT DELETE_close( struct tagMSIVIEW *view ) 104 { 105 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 106 107 TRACE("%p\n", dv ); 108 109 if( !dv->table ) 110 return ERROR_FUNCTION_FAILED; 111 112 return dv->table->ops->close( dv->table ); 113 } 114 115 static UINT DELETE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) 116 { 117 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 118 119 TRACE("%p %p %p\n", dv, rows, cols ); 120 121 if( !dv->table ) 122 return ERROR_FUNCTION_FAILED; 123 124 *rows = 0; 125 126 return dv->table->ops->get_dimensions( dv->table, NULL, cols ); 127 } 128 129 static UINT DELETE_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name, 130 UINT *type, BOOL *temporary, LPCWSTR *table_name ) 131 { 132 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 133 134 TRACE("%p %d %p %p %p %p\n", dv, n, name, type, temporary, table_name ); 135 136 if( !dv->table ) 137 return ERROR_FUNCTION_FAILED; 138 139 return dv->table->ops->get_column_info( dv->table, n, name, 140 type, temporary, table_name); 141 } 142 143 static UINT DELETE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, 144 MSIRECORD *rec, UINT row ) 145 { 146 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 147 148 TRACE("%p %d %p\n", dv, eModifyMode, rec ); 149 150 return ERROR_FUNCTION_FAILED; 151 } 152 153 static UINT DELETE_delete( struct tagMSIVIEW *view ) 154 { 155 MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; 156 157 TRACE("%p\n", dv ); 158 159 if( dv->table ) 160 dv->table->ops->delete( dv->table ); 161 162 msi_free( dv ); 163 164 return ERROR_SUCCESS; 165 } 166 167 static UINT DELETE_find_matching_rows( struct tagMSIVIEW *view, UINT col, 168 UINT val, UINT *row, MSIITERHANDLE *handle ) 169 { 170 TRACE("%p, %d, %u, %p\n", view, col, val, *handle); 171 172 return ERROR_FUNCTION_FAILED; 173 } 174 175 176 static const MSIVIEWOPS delete_ops = 177 { 178 DELETE_fetch_int, 179 DELETE_fetch_stream, 180 NULL, 181 NULL, 182 NULL, 183 NULL, 184 DELETE_execute, 185 DELETE_close, 186 DELETE_get_dimensions, 187 DELETE_get_column_info, 188 DELETE_modify, 189 DELETE_delete, 190 DELETE_find_matching_rows, 191 NULL, 192 NULL, 193 NULL, 194 NULL, 195 NULL, 196 NULL, 197 }; 198 199 UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) 200 { 201 MSIDELETEVIEW *dv = NULL; 202 203 TRACE("%p\n", dv ); 204 205 dv = msi_alloc_zero( sizeof *dv ); 206 if( !dv ) 207 return ERROR_FUNCTION_FAILED; 208 209 /* fill the structure */ 210 dv->view.ops = &delete_ops; 211 dv->db = db; 212 dv->table = table; 213 214 *view = &dv->view; 215 216 return ERROR_SUCCESS; 217 } 218