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 const MSIVIEWOPS delete_ops = 168 { 169 DELETE_fetch_int, 170 DELETE_fetch_stream, 171 NULL, 172 NULL, 173 NULL, 174 NULL, 175 NULL, 176 NULL, 177 DELETE_execute, 178 DELETE_close, 179 DELETE_get_dimensions, 180 DELETE_get_column_info, 181 DELETE_modify, 182 DELETE_delete, 183 NULL, 184 NULL, 185 NULL, 186 NULL, 187 NULL, 188 }; 189 190 UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) 191 { 192 MSIDELETEVIEW *dv = NULL; 193 194 TRACE("%p\n", dv ); 195 196 dv = msi_alloc_zero( sizeof *dv ); 197 if( !dv ) 198 return ERROR_FUNCTION_FAILED; 199 200 /* fill the structure */ 201 dv->view.ops = &delete_ops; 202 dv->db = db; 203 dv->table = table; 204 205 *view = &dv->view; 206 207 return ERROR_SUCCESS; 208 } 209