Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenselect.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of the Microsoft Installer (msi.dll) 00003 * 00004 * Copyright 2002-2004 Mike McCormack for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "winerror.h" 00026 #include "wine/debug.h" 00027 #include "msi.h" 00028 #include "msiquery.h" 00029 #include "objbase.h" 00030 #include "objidl.h" 00031 #include "msipriv.h" 00032 #include "winnls.h" 00033 00034 #include "query.h" 00035 00036 WINE_DEFAULT_DEBUG_CHANNEL(msidb); 00037 00038 00039 /* below is the query interface to a table */ 00040 00041 typedef struct tagMSISELECTVIEW 00042 { 00043 MSIVIEW view; 00044 MSIDATABASE *db; 00045 MSIVIEW *table; 00046 UINT num_cols; 00047 UINT max_cols; 00048 UINT cols[1]; 00049 } MSISELECTVIEW; 00050 00051 static UINT SELECT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) 00052 { 00053 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00054 00055 TRACE("%p %d %d %p\n", sv, row, col, val ); 00056 00057 if( !sv->table ) 00058 return ERROR_FUNCTION_FAILED; 00059 00060 if( !col || col > sv->num_cols ) 00061 return ERROR_FUNCTION_FAILED; 00062 00063 col = sv->cols[ col - 1 ]; 00064 if( !col ) 00065 { 00066 *val = 0; 00067 return ERROR_SUCCESS; 00068 } 00069 return sv->table->ops->fetch_int( sv->table, row, col, val ); 00070 } 00071 00072 static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm) 00073 { 00074 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00075 00076 TRACE("%p %d %d %p\n", sv, row, col, stm ); 00077 00078 if( !sv->table ) 00079 return ERROR_FUNCTION_FAILED; 00080 00081 if( !col || col > sv->num_cols ) 00082 return ERROR_FUNCTION_FAILED; 00083 00084 col = sv->cols[ col - 1 ]; 00085 if( !col ) 00086 { 00087 *stm = NULL; 00088 return ERROR_SUCCESS; 00089 } 00090 return sv->table->ops->fetch_stream( sv->table, row, col, stm ); 00091 } 00092 00093 static UINT SELECT_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) 00094 { 00095 MSISELECTVIEW *sv = (MSISELECTVIEW *)view; 00096 00097 TRACE("%p %d %p\n", sv, row, rec ); 00098 00099 if( !sv->table ) 00100 return ERROR_FUNCTION_FAILED; 00101 00102 return msi_view_get_row(sv->db, view, row, rec); 00103 } 00104 00105 static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) 00106 { 00107 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00108 UINT i, expanded_mask = 0, r = ERROR_SUCCESS, col_count = 0; 00109 MSIRECORD *expanded; 00110 00111 TRACE("%p %d %p %08x\n", sv, row, rec, mask ); 00112 00113 if ( !sv->table ) 00114 return ERROR_FUNCTION_FAILED; 00115 00116 /* test if any of the mask bits are invalid */ 00117 if ( mask >= (1<<sv->num_cols) ) 00118 return ERROR_INVALID_PARAMETER; 00119 00120 /* find the number of columns in the table below */ 00121 r = sv->table->ops->get_dimensions( sv->table, NULL, &col_count ); 00122 if( r ) 00123 return r; 00124 00125 /* expand the record to the right size for the underlying table */ 00126 expanded = MSI_CreateRecord( col_count ); 00127 if ( !expanded ) 00128 return ERROR_FUNCTION_FAILED; 00129 00130 /* move the right fields across */ 00131 for ( i=0; i<sv->num_cols; i++ ) 00132 { 00133 r = MSI_RecordCopyField( rec, i+1, expanded, sv->cols[ i ] ); 00134 if (r != ERROR_SUCCESS) 00135 break; 00136 expanded_mask |= (1<<(sv->cols[i]-1)); 00137 } 00138 00139 /* set the row in the underlying table */ 00140 if (r == ERROR_SUCCESS) 00141 r = sv->table->ops->set_row( sv->table, row, expanded, expanded_mask ); 00142 00143 msiobj_release( &expanded->hdr ); 00144 return r; 00145 } 00146 00147 static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary ) 00148 { 00149 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00150 UINT i, table_cols, r; 00151 MSIRECORD *outrec; 00152 00153 TRACE("%p %p\n", sv, record ); 00154 00155 if ( !sv->table ) 00156 return ERROR_FUNCTION_FAILED; 00157 00158 /* rearrange the record to suit the table */ 00159 r = sv->table->ops->get_dimensions( sv->table, NULL, &table_cols ); 00160 if (r != ERROR_SUCCESS) 00161 return r; 00162 00163 outrec = MSI_CreateRecord( table_cols + 1 ); 00164 00165 for (i=0; i<sv->num_cols; i++) 00166 { 00167 r = MSI_RecordCopyField( record, i+1, outrec, sv->cols[i] ); 00168 if (r != ERROR_SUCCESS) 00169 goto fail; 00170 } 00171 00172 r = sv->table->ops->insert_row( sv->table, outrec, row, temporary ); 00173 00174 fail: 00175 msiobj_release( &outrec->hdr ); 00176 00177 return r; 00178 } 00179 00180 static UINT SELECT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) 00181 { 00182 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00183 00184 TRACE("%p %p\n", sv, record); 00185 00186 if( !sv->table ) 00187 return ERROR_FUNCTION_FAILED; 00188 00189 return sv->table->ops->execute( sv->table, record ); 00190 } 00191 00192 static UINT SELECT_close( struct tagMSIVIEW *view ) 00193 { 00194 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00195 00196 TRACE("%p\n", sv ); 00197 00198 if( !sv->table ) 00199 return ERROR_FUNCTION_FAILED; 00200 00201 return sv->table->ops->close( sv->table ); 00202 } 00203 00204 static UINT SELECT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) 00205 { 00206 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00207 00208 TRACE("%p %p %p\n", sv, rows, cols ); 00209 00210 if( !sv->table ) 00211 return ERROR_FUNCTION_FAILED; 00212 00213 if( cols ) 00214 *cols = sv->num_cols; 00215 00216 return sv->table->ops->get_dimensions( sv->table, rows, NULL ); 00217 } 00218 00219 static UINT SELECT_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name, 00220 UINT *type, BOOL *temporary, LPCWSTR *table_name ) 00221 { 00222 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00223 00224 TRACE("%p %d %p %p %p %p\n", sv, n, name, type, temporary, table_name ); 00225 00226 if( !sv->table ) 00227 return ERROR_FUNCTION_FAILED; 00228 00229 if( !n || n > sv->num_cols ) 00230 return ERROR_FUNCTION_FAILED; 00231 00232 n = sv->cols[ n - 1 ]; 00233 if( !n ) 00234 { 00235 if (name) *name = szEmpty; 00236 if (type) *type = MSITYPE_UNKNOWN | MSITYPE_VALID; 00237 if (temporary) *temporary = FALSE; 00238 if (table_name) *table_name = szEmpty; 00239 return ERROR_SUCCESS; 00240 } 00241 return sv->table->ops->get_column_info( sv->table, n, name, 00242 type, temporary, table_name ); 00243 } 00244 00245 static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) 00246 { 00247 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00248 UINT r, i, num_columns, col, type, val; 00249 LPCWSTR str; 00250 MSIRECORD *mod; 00251 00252 r = SELECT_get_dimensions(view, NULL, &num_columns); 00253 if (r != ERROR_SUCCESS) 00254 return r; 00255 00256 r = sv->table->ops->get_row(sv->table, row - 1, &mod); 00257 if (r != ERROR_SUCCESS) 00258 return r; 00259 00260 for (i = 0; i < num_columns; i++) 00261 { 00262 col = sv->cols[i]; 00263 00264 r = SELECT_get_column_info(view, i + 1, NULL, &type, NULL, NULL); 00265 if (r != ERROR_SUCCESS) 00266 { 00267 ERR("Failed to get column information: %d\n", r); 00268 goto done; 00269 } 00270 00271 if (MSITYPE_IS_BINARY(type)) 00272 { 00273 ERR("Cannot modify binary data!\n"); 00274 r = ERROR_FUNCTION_FAILED; 00275 goto done; 00276 } 00277 else if (type & MSITYPE_STRING) 00278 { 00279 str = MSI_RecordGetString(rec, i + 1); 00280 r = MSI_RecordSetStringW(mod, col, str); 00281 } 00282 else 00283 { 00284 val = MSI_RecordGetInteger(rec, i + 1); 00285 r = MSI_RecordSetInteger(mod, col, val); 00286 } 00287 00288 if (r != ERROR_SUCCESS) 00289 { 00290 ERR("Failed to modify record: %d\n", r); 00291 goto done; 00292 } 00293 } 00294 00295 r = sv->table->ops->modify(sv->table, MSIMODIFY_UPDATE, mod, row); 00296 00297 done: 00298 msiobj_release(&mod->hdr); 00299 return r; 00300 } 00301 00302 static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, 00303 MSIRECORD *rec, UINT row ) 00304 { 00305 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00306 00307 TRACE("%p %d %p %d\n", sv, eModifyMode, rec, row ); 00308 00309 if( !sv->table ) 00310 return ERROR_FUNCTION_FAILED; 00311 00312 if (eModifyMode == MSIMODIFY_UPDATE) 00313 return msi_select_update(view, rec, row); 00314 00315 return sv->table->ops->modify( sv->table, eModifyMode, rec, row ); 00316 } 00317 00318 static UINT SELECT_delete( struct tagMSIVIEW *view ) 00319 { 00320 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00321 00322 TRACE("%p\n", sv ); 00323 00324 if( sv->table ) 00325 sv->table->ops->delete( sv->table ); 00326 sv->table = NULL; 00327 00328 msi_free( sv ); 00329 00330 return ERROR_SUCCESS; 00331 } 00332 00333 static UINT SELECT_find_matching_rows( struct tagMSIVIEW *view, UINT col, 00334 UINT val, UINT *row, MSIITERHANDLE *handle ) 00335 { 00336 MSISELECTVIEW *sv = (MSISELECTVIEW*)view; 00337 00338 TRACE("%p, %d, %u, %p\n", view, col, val, *handle); 00339 00340 if( !sv->table ) 00341 return ERROR_FUNCTION_FAILED; 00342 00343 if( (col==0) || (col>sv->num_cols) ) 00344 return ERROR_FUNCTION_FAILED; 00345 00346 col = sv->cols[ col - 1 ]; 00347 00348 return sv->table->ops->find_matching_rows( sv->table, col, val, row, handle ); 00349 } 00350 00351 00352 static const MSIVIEWOPS select_ops = 00353 { 00354 SELECT_fetch_int, 00355 SELECT_fetch_stream, 00356 SELECT_get_row, 00357 SELECT_set_row, 00358 SELECT_insert_row, 00359 NULL, 00360 SELECT_execute, 00361 SELECT_close, 00362 SELECT_get_dimensions, 00363 SELECT_get_column_info, 00364 SELECT_modify, 00365 SELECT_delete, 00366 SELECT_find_matching_rows, 00367 NULL, 00368 NULL, 00369 NULL, 00370 NULL, 00371 NULL, 00372 NULL, 00373 }; 00374 00375 static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name, 00376 LPCWSTR table_name ) 00377 { 00378 UINT r, n; 00379 MSIVIEW *table; 00380 00381 TRACE("%p adding %s.%s\n", sv, debugstr_w( table_name ), 00382 debugstr_w( name )); 00383 00384 if( sv->view.ops != &select_ops ) 00385 return ERROR_FUNCTION_FAILED; 00386 00387 table = sv->table; 00388 if( !table ) 00389 return ERROR_FUNCTION_FAILED; 00390 if( !table->ops->get_dimensions ) 00391 return ERROR_FUNCTION_FAILED; 00392 if( !table->ops->get_column_info ) 00393 return ERROR_FUNCTION_FAILED; 00394 00395 if( sv->num_cols >= sv->max_cols ) 00396 return ERROR_FUNCTION_FAILED; 00397 00398 if ( !name[0] ) n = 0; 00399 else 00400 { 00401 r = VIEW_find_column( table, name, table_name, &n ); 00402 if( r != ERROR_SUCCESS ) 00403 return r; 00404 } 00405 00406 sv->cols[sv->num_cols] = n; 00407 TRACE("Translating column %s from %d -> %d\n", 00408 debugstr_w( name ), sv->num_cols, n); 00409 00410 sv->num_cols++; 00411 00412 return ERROR_SUCCESS; 00413 } 00414 00415 static int select_count_columns( const column_info *col ) 00416 { 00417 int n; 00418 for (n = 0; col; col = col->next) 00419 n++; 00420 return n; 00421 } 00422 00423 UINT SELECT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table, 00424 const column_info *columns ) 00425 { 00426 MSISELECTVIEW *sv = NULL; 00427 UINT count = 0, r = ERROR_SUCCESS; 00428 00429 TRACE("%p\n", sv ); 00430 00431 count = select_count_columns( columns ); 00432 00433 sv = msi_alloc_zero( sizeof *sv + count*sizeof (UINT) ); 00434 if( !sv ) 00435 return ERROR_FUNCTION_FAILED; 00436 00437 /* fill the structure */ 00438 sv->view.ops = &select_ops; 00439 sv->db = db; 00440 sv->table = table; 00441 sv->num_cols = 0; 00442 sv->max_cols = count; 00443 00444 while( columns ) 00445 { 00446 r = SELECT_AddColumn( sv, columns->column, columns->table ); 00447 if( r ) 00448 break; 00449 columns = columns->next; 00450 } 00451 00452 if( r == ERROR_SUCCESS ) 00453 *view = &sv->view; 00454 else 00455 msi_free( sv ); 00456 00457 return r; 00458 } Generated on Sun May 27 2012 04:18:48 for ReactOS by
1.7.6.1
|