ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

select.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.