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

msiquery.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2002-2005 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 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "winerror.h"
00028 #include "wine/debug.h"
00029 #include "wine/unicode.h"
00030 #include "msi.h"
00031 #include "msiquery.h"
00032 #include "objbase.h"
00033 #include "objidl.h"
00034 #include "msipriv.h"
00035 #include "winnls.h"
00036 
00037 #include "query.h"
00038 #include "msiserver.h"
00039 
00040 #include "initguid.h"
00041 
00042 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00043 
00044 static void MSI_CloseView( MSIOBJECTHDR *arg )
00045 {
00046     MSIQUERY *query = (MSIQUERY*) arg;
00047     struct list *ptr, *t;
00048 
00049     if( query->view && query->view->ops->delete )
00050         query->view->ops->delete( query->view );
00051     msiobj_release( &query->db->hdr );
00052 
00053     LIST_FOR_EACH_SAFE( ptr, t, &query->mem )
00054     {
00055         msi_free( ptr );
00056     }
00057 }
00058 
00059 UINT VIEW_find_column( MSIVIEW *table, LPCWSTR name, LPCWSTR table_name, UINT *n )
00060 {
00061     LPCWSTR col_name, haystack_table_name;
00062     UINT i, count, r;
00063 
00064     r = table->ops->get_dimensions( table, NULL, &count );
00065     if( r != ERROR_SUCCESS )
00066         return r;
00067 
00068     for( i=1; i<=count; i++ )
00069     {
00070         INT x;
00071 
00072         r = table->ops->get_column_info( table, i, &col_name, NULL,
00073                                          NULL, &haystack_table_name );
00074         if( r != ERROR_SUCCESS )
00075             return r;
00076         x = strcmpW( name, col_name );
00077         if( table_name )
00078             x |= strcmpW( table_name, haystack_table_name );
00079         if( !x )
00080         {
00081             *n = i;
00082             return ERROR_SUCCESS;
00083         }
00084     }
00085     return ERROR_INVALID_PARAMETER;
00086 }
00087 
00088 UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
00089               LPCSTR szQuery, MSIHANDLE *phView)
00090 {
00091     UINT r;
00092     LPWSTR szwQuery;
00093 
00094     TRACE("%d %s %p\n", hdb, debugstr_a(szQuery), phView);
00095 
00096     if( szQuery )
00097     {
00098         szwQuery = strdupAtoW( szQuery );
00099         if( !szwQuery )
00100             return ERROR_FUNCTION_FAILED;
00101     }
00102     else
00103         szwQuery = NULL;
00104 
00105     r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
00106 
00107     msi_free( szwQuery );
00108     return r;
00109 }
00110 
00111 UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
00112               LPCWSTR szQuery, MSIQUERY **pView)
00113 {
00114     MSIQUERY *query;
00115     UINT r;
00116 
00117     TRACE("%s %p\n", debugstr_w(szQuery), pView);
00118 
00119     if( !szQuery)
00120         return ERROR_INVALID_PARAMETER;
00121 
00122     /* pre allocate a handle to hold a pointer to the view */
00123     query = alloc_msiobject( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY),
00124                               MSI_CloseView );
00125     if( !query )
00126         return ERROR_FUNCTION_FAILED;
00127 
00128     msiobj_addref( &db->hdr );
00129     query->db = db;
00130     list_init( &query->mem );
00131 
00132     r = MSI_ParseSQL( db, szQuery, &query->view, &query->mem );
00133     if( r == ERROR_SUCCESS )
00134     {
00135         msiobj_addref( &query->hdr );
00136         *pView = query;
00137     }
00138 
00139     msiobj_release( &query->hdr );
00140     return r;
00141 }
00142 
00143 UINT MSI_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
00144 {
00145     UINT r;
00146     int size = 100, res;
00147     LPWSTR query;
00148 
00149     /* construct the string */
00150     for (;;)
00151     {
00152         va_list va;
00153         query = msi_alloc( size*sizeof(WCHAR) );
00154         va_start(va, fmt);
00155         res = vsnprintfW(query, size, fmt, va);
00156         va_end(va);
00157         if (res == -1) size *= 2;
00158         else if (res >= size) size = res + 1;
00159         else break;
00160         msi_free( query );
00161     }
00162     /* perform the query */
00163     r = MSI_DatabaseOpenViewW(db, query, view);
00164     msi_free(query);
00165     return r;
00166 }
00167 
00168 UINT MSI_IterateRecords( MSIQUERY *view, LPDWORD count,
00169                          record_func func, LPVOID param )
00170 {
00171     MSIRECORD *rec = NULL;
00172     UINT r, n = 0, max = 0;
00173 
00174     r = MSI_ViewExecute( view, NULL );
00175     if( r != ERROR_SUCCESS )
00176         return r;
00177 
00178     if( count )
00179         max = *count;
00180 
00181     /* iterate a query */
00182     for( n = 0; (max == 0) || (n < max); n++ )
00183     {
00184         r = MSI_ViewFetch( view, &rec );
00185         if( r != ERROR_SUCCESS )
00186             break;
00187         if (func)
00188             r = func( rec, param );
00189         msiobj_release( &rec->hdr );
00190         if( r != ERROR_SUCCESS )
00191             break;
00192     }
00193 
00194     MSI_ViewClose( view );
00195 
00196     if( count )
00197         *count = n;
00198 
00199     if( r == ERROR_NO_MORE_ITEMS )
00200         r = ERROR_SUCCESS;
00201 
00202     return r;
00203 }
00204 
00205 /* return a single record from a query */
00206 MSIRECORD *MSI_QueryGetRecord( MSIDATABASE *db, LPCWSTR fmt, ... )
00207 {
00208     MSIRECORD *rec = NULL;
00209     MSIQUERY *view = NULL;
00210     UINT r;
00211     int size = 100, res;
00212     LPWSTR query;
00213 
00214     /* construct the string */
00215     for (;;)
00216     {
00217         va_list va;
00218         query = msi_alloc( size*sizeof(WCHAR) );
00219         va_start(va, fmt);
00220         res = vsnprintfW(query, size, fmt, va);
00221         va_end(va);
00222         if (res == -1) size *= 2;
00223         else if (res >= size) size = res + 1;
00224         else break;
00225         msi_free( query );
00226     }
00227     /* perform the query */
00228     r = MSI_DatabaseOpenViewW(db, query, &view);
00229     msi_free(query);
00230 
00231     if( r == ERROR_SUCCESS )
00232     {
00233         MSI_ViewExecute( view, NULL );
00234         MSI_ViewFetch( view, &rec );
00235         MSI_ViewClose( view );
00236         msiobj_release( &view->hdr );
00237     }
00238     return rec;
00239 }
00240 
00241 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
00242               LPCWSTR szQuery, MSIHANDLE *phView)
00243 {
00244     MSIDATABASE *db;
00245     MSIQUERY *query = NULL;
00246     UINT ret;
00247 
00248     TRACE("%s %p\n", debugstr_w(szQuery), phView);
00249 
00250     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
00251     if( !db )
00252     {
00253         HRESULT hr;
00254         IWineMsiRemoteDatabase *remote_database;
00255 
00256         remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hdb );
00257         if ( !remote_database )
00258             return ERROR_INVALID_HANDLE;
00259 
00260         hr = IWineMsiRemoteDatabase_OpenView( remote_database, szQuery, phView );
00261         IWineMsiRemoteDatabase_Release( remote_database );
00262 
00263         if (FAILED(hr))
00264         {
00265             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
00266                 return HRESULT_CODE(hr);
00267 
00268             return ERROR_FUNCTION_FAILED;
00269         }
00270 
00271         return ERROR_SUCCESS;
00272     }
00273 
00274     ret = MSI_DatabaseOpenViewW( db, szQuery, &query );
00275     if( ret == ERROR_SUCCESS )
00276     {
00277         *phView = alloc_msihandle( &query->hdr );
00278         if (! *phView)
00279            ret = ERROR_NOT_ENOUGH_MEMORY;
00280         msiobj_release( &query->hdr );
00281     }
00282     msiobj_release( &db->hdr );
00283 
00284     return ret;
00285 }
00286 
00287 UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
00288 {
00289     UINT row_count = 0, col_count = 0, i, ival, ret, type;
00290 
00291     TRACE("%p %p %d %p\n", db, view, row, rec);
00292 
00293     ret = view->ops->get_dimensions(view, &row_count, &col_count);
00294     if (ret)
00295         return ret;
00296 
00297     if (!col_count)
00298         return ERROR_INVALID_PARAMETER;
00299 
00300     if (row >= row_count)
00301         return ERROR_NO_MORE_ITEMS;
00302 
00303     *rec = MSI_CreateRecord(col_count);
00304     if (!*rec)
00305         return ERROR_FUNCTION_FAILED;
00306 
00307     for (i = 1; i <= col_count; i++)
00308     {
00309         ret = view->ops->get_column_info(view, i, NULL, &type, NULL, NULL);
00310         if (ret)
00311         {
00312             ERR("Error getting column type for %d\n", i);
00313             continue;
00314         }
00315 
00316         if (MSITYPE_IS_BINARY(type))
00317         {
00318             IStream *stm = NULL;
00319 
00320             ret = view->ops->fetch_stream(view, row, i, &stm);
00321             if ((ret == ERROR_SUCCESS) && stm)
00322             {
00323                 MSI_RecordSetIStream(*rec, i, stm);
00324                 IStream_Release(stm);
00325             }
00326             else
00327                 WARN("failed to get stream\n");
00328 
00329             continue;
00330         }
00331 
00332         ret = view->ops->fetch_int(view, row, i, &ival);
00333         if (ret)
00334         {
00335             ERR("Error fetching data for %d\n", i);
00336             continue;
00337         }
00338 
00339         if (! (type & MSITYPE_VALID))
00340             ERR("Invalid type!\n");
00341 
00342         /* check if it's nul (0) - if so, don't set anything */
00343         if (!ival)
00344             continue;
00345 
00346         if (type & MSITYPE_STRING)
00347         {
00348             LPCWSTR sval;
00349 
00350             sval = msi_string_lookup_id(db->strings, ival);
00351             MSI_RecordSetStringW(*rec, i, sval);
00352         }
00353         else
00354         {
00355             if ((type & MSI_DATASIZEMASK) == 2)
00356                 MSI_RecordSetInteger(*rec, i, ival - (1<<15));
00357             else
00358                 MSI_RecordSetInteger(*rec, i, ival - (1<<31));
00359         }
00360     }
00361 
00362     return ERROR_SUCCESS;
00363 }
00364 
00365 UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
00366 {
00367     MSIVIEW *view;
00368     UINT r;
00369 
00370     TRACE("%p %p\n", query, prec );
00371 
00372     view = query->view;
00373     if( !view )
00374         return ERROR_FUNCTION_FAILED;
00375 
00376     r = msi_view_get_row(query->db, view, query->row, prec);
00377     if (r == ERROR_SUCCESS)
00378     {
00379         query->row ++;
00380         MSI_RecordSetIntPtr(*prec, 0, (INT_PTR)query);
00381     }
00382 
00383     return r;
00384 }
00385 
00386 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
00387 {
00388     MSIQUERY *query;
00389     MSIRECORD *rec = NULL;
00390     UINT ret;
00391 
00392     TRACE("%d %p\n", hView, record);
00393 
00394     if( !record )
00395         return ERROR_INVALID_PARAMETER;
00396     *record = 0;
00397 
00398     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
00399     if( !query )
00400         return ERROR_INVALID_HANDLE;
00401     ret = MSI_ViewFetch( query, &rec );
00402     if( ret == ERROR_SUCCESS )
00403     {
00404         *record = alloc_msihandle( &rec->hdr );
00405         if (! *record)
00406            ret = ERROR_NOT_ENOUGH_MEMORY;
00407         msiobj_release( &rec->hdr );
00408     }
00409     msiobj_release( &query->hdr );
00410     return ret;
00411 }
00412 
00413 UINT MSI_ViewClose(MSIQUERY *query)
00414 {
00415     MSIVIEW *view;
00416 
00417     TRACE("%p\n", query );
00418 
00419     view = query->view;
00420     if( !view )
00421         return ERROR_FUNCTION_FAILED;
00422     if( !view->ops->close )
00423         return ERROR_FUNCTION_FAILED;
00424 
00425     return view->ops->close( view );
00426 }
00427 
00428 UINT WINAPI MsiViewClose(MSIHANDLE hView)
00429 {
00430     MSIQUERY *query;
00431     UINT ret;
00432 
00433     TRACE("%d\n", hView );
00434 
00435     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
00436     if( !query )
00437         return ERROR_INVALID_HANDLE;
00438 
00439     ret = MSI_ViewClose( query );
00440     msiobj_release( &query->hdr );
00441     return ret;
00442 }
00443 
00444 UINT MSI_ViewExecute(MSIQUERY *query, MSIRECORD *rec )
00445 {
00446     MSIVIEW *view;
00447 
00448     TRACE("%p %p\n", query, rec);
00449 
00450     view = query->view;
00451     if( !view )
00452         return ERROR_FUNCTION_FAILED;
00453     if( !view->ops->execute )
00454         return ERROR_FUNCTION_FAILED;
00455     query->row = 0;
00456 
00457     return view->ops->execute( view, rec );
00458 }
00459 
00460 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
00461 {
00462     MSIQUERY *query;
00463     MSIRECORD *rec = NULL;
00464     UINT ret;
00465     
00466     TRACE("%d %d\n", hView, hRec);
00467 
00468     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
00469     if( !query )
00470         return ERROR_INVALID_HANDLE;
00471 
00472     if( hRec )
00473     {
00474         rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD );
00475         if( !rec )
00476         {
00477             ret = ERROR_INVALID_HANDLE;
00478             goto out;
00479         }
00480     }
00481 
00482     msiobj_lock( &rec->hdr );
00483     ret = MSI_ViewExecute( query, rec );
00484     msiobj_unlock( &rec->hdr );
00485 
00486 out:
00487     msiobj_release( &query->hdr );
00488     if( rec )
00489         msiobj_release( &rec->hdr );
00490 
00491     return ret;
00492 }
00493 
00494 static UINT msi_set_record_type_string( MSIRECORD *rec, UINT field,
00495                                         UINT type, BOOL temporary )
00496 {
00497     static const WCHAR fmt[] = { '%','d',0 };
00498     WCHAR szType[0x10];
00499 
00500     if (MSITYPE_IS_BINARY(type))
00501         szType[0] = 'v';
00502     else if (type & MSITYPE_LOCALIZABLE)
00503         szType[0] = 'l';
00504     else if (type & MSITYPE_UNKNOWN)
00505         szType[0] = 'f';
00506     else if (type & MSITYPE_STRING)
00507     {
00508         if (temporary)
00509             szType[0] = 'g';
00510         else
00511           szType[0] = 's';
00512     }
00513     else
00514     {
00515         if (temporary)
00516             szType[0] = 'j';
00517         else
00518             szType[0] = 'i';
00519     }
00520 
00521     if (type & MSITYPE_NULLABLE)
00522         szType[0] &= ~0x20;
00523 
00524     sprintfW( &szType[1], fmt, (type&0xff) );
00525 
00526     TRACE("type %04x -> %s\n", type, debugstr_w(szType) );
00527 
00528     return MSI_RecordSetStringW( rec, field, szType );
00529 }
00530 
00531 UINT MSI_ViewGetColumnInfo( MSIQUERY *query, MSICOLINFO info, MSIRECORD **prec )
00532 {
00533     UINT r = ERROR_FUNCTION_FAILED, i, count = 0, type;
00534     MSIRECORD *rec;
00535     MSIVIEW *view = query->view;
00536     LPCWSTR name;
00537     BOOL temporary;
00538 
00539     if( !view )
00540         return ERROR_FUNCTION_FAILED;
00541 
00542     if( !view->ops->get_dimensions )
00543         return ERROR_FUNCTION_FAILED;
00544 
00545     r = view->ops->get_dimensions( view, NULL, &count );
00546     if( r != ERROR_SUCCESS )
00547         return r;
00548     if( !count )
00549         return ERROR_INVALID_PARAMETER;
00550 
00551     rec = MSI_CreateRecord( count );
00552     if( !rec )
00553         return ERROR_FUNCTION_FAILED;
00554 
00555     for( i=0; i<count; i++ )
00556     {
00557         name = NULL;
00558         r = view->ops->get_column_info( view, i+1, &name, &type, &temporary, NULL );
00559         if( r != ERROR_SUCCESS )
00560             continue;
00561         if (info == MSICOLINFO_NAMES)
00562             MSI_RecordSetStringW( rec, i+1, name );
00563         else
00564             msi_set_record_type_string( rec, i+1, type, temporary );
00565     }
00566     *prec = rec;
00567     return ERROR_SUCCESS;
00568 }
00569 
00570 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
00571 {
00572     MSIQUERY *query = NULL;
00573     MSIRECORD *rec = NULL;
00574     UINT r;
00575 
00576     TRACE("%d %d %p\n", hView, info, hRec);
00577 
00578     if( !hRec )
00579         return ERROR_INVALID_PARAMETER;
00580 
00581     if( info != MSICOLINFO_NAMES && info != MSICOLINFO_TYPES )
00582         return ERROR_INVALID_PARAMETER;
00583 
00584     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
00585     if( !query )
00586         return ERROR_INVALID_HANDLE;
00587 
00588     r = MSI_ViewGetColumnInfo( query, info, &rec );
00589     if ( r == ERROR_SUCCESS )
00590     {
00591         *hRec = alloc_msihandle( &rec->hdr );
00592         if ( !*hRec )
00593             r = ERROR_NOT_ENOUGH_MEMORY;
00594         msiobj_release( &rec->hdr );
00595     }
00596 
00597     msiobj_release( &query->hdr );
00598 
00599     return r;
00600 }
00601 
00602 UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec )
00603 {
00604     MSIVIEW *view = NULL;
00605     UINT r;
00606 
00607     if ( !query || !rec )
00608         return ERROR_INVALID_HANDLE;
00609 
00610     view = query->view;
00611     if ( !view  || !view->ops->modify)
00612         return ERROR_FUNCTION_FAILED;
00613 
00614     if ( mode == MSIMODIFY_UPDATE && MSI_RecordGetIntPtr( rec, 0 ) != (INT_PTR)query )
00615         return ERROR_FUNCTION_FAILED;
00616 
00617     r = view->ops->modify( view, mode, rec, query->row );
00618     if (mode == MSIMODIFY_DELETE && r == ERROR_SUCCESS)
00619         query->row--;
00620 
00621     return r;
00622 }
00623 
00624 UINT WINAPI MsiViewModify( MSIHANDLE hView, MSIMODIFY eModifyMode,
00625                 MSIHANDLE hRecord)
00626 {
00627     MSIQUERY *query = NULL;
00628     MSIRECORD *rec = NULL;
00629     UINT r = ERROR_FUNCTION_FAILED;
00630 
00631     TRACE("%d %x %d\n", hView, eModifyMode, hRecord);
00632 
00633     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
00634     if( !query )
00635         return ERROR_INVALID_HANDLE;
00636 
00637     rec = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
00638     r = MSI_ViewModify( query, eModifyMode, rec );
00639 
00640     msiobj_release( &query->hdr );
00641     if( rec )
00642         msiobj_release( &rec->hdr );
00643 
00644     return r;
00645 }
00646 
00647 MSIDBERROR WINAPI MsiViewGetErrorW( MSIHANDLE handle, LPWSTR buffer, LPDWORD buflen )
00648 {
00649     MSIQUERY *query;
00650     const WCHAR *column;
00651     MSIDBERROR r;
00652     DWORD len;
00653 
00654     TRACE("%u %p %p\n", handle, buffer, buflen);
00655 
00656     if (!buflen)
00657         return MSIDBERROR_INVALIDARG;
00658 
00659     query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
00660     if( !query )
00661         return MSIDBERROR_INVALIDARG;
00662 
00663     if ((r = query->view->error)) column = query->view->error_column;
00664     else column = szEmpty;
00665 
00666     len = strlenW( column );
00667     if (buffer)
00668     {
00669         if (*buflen > len)
00670             strcpyW( buffer, column );
00671         else
00672             r = MSIDBERROR_MOREDATA;
00673     }
00674     *buflen = len;
00675     msiobj_release( &query->hdr );
00676     return r;
00677 }
00678 
00679 MSIDBERROR WINAPI MsiViewGetErrorA( MSIHANDLE handle, LPSTR buffer, LPDWORD buflen )
00680 {
00681     MSIQUERY *query;
00682     const WCHAR *column;
00683     MSIDBERROR r;
00684     DWORD len;
00685 
00686     TRACE("%u %p %p\n", handle, buffer, buflen);
00687 
00688     if (!buflen)
00689         return MSIDBERROR_INVALIDARG;
00690 
00691     query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
00692     if (!query)
00693         return MSIDBERROR_INVALIDARG;
00694 
00695     if ((r = query->view->error)) column = query->view->error_column;
00696     else column = szEmpty;
00697 
00698     len = WideCharToMultiByte( CP_ACP, 0, column, -1, NULL, 0, NULL, NULL );
00699     if (buffer)
00700     {
00701         if (*buflen >= len)
00702             WideCharToMultiByte( CP_ACP, 0, column, -1, buffer, *buflen, NULL, NULL );
00703         else
00704             r = MSIDBERROR_MOREDATA;
00705     }
00706     *buflen = len - 1;
00707     msiobj_release( &query->hdr );
00708     return r;
00709 }
00710 
00711 MSIHANDLE WINAPI MsiGetLastErrorRecord( void )
00712 {
00713     FIXME("\n");
00714     return 0;
00715 }
00716 
00717 UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
00718                  LPCWSTR szTransformFile, int iErrorCond )
00719 {
00720     HRESULT r;
00721     UINT ret = ERROR_FUNCTION_FAILED;
00722     IStorage *stg = NULL;
00723     STATSTG stat;
00724 
00725     TRACE("%p %s %d\n", db, debugstr_w(szTransformFile), iErrorCond);
00726 
00727     r = StgOpenStorage( szTransformFile, NULL,
00728            STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
00729     if ( FAILED(r) )
00730     {
00731         WARN("failed to open transform 0x%08x\n", r);
00732         return ret;
00733     }
00734 
00735     r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
00736     if ( FAILED( r ) )
00737         goto end;
00738 
00739     if ( !IsEqualGUID( &stat.clsid, &CLSID_MsiTransform ) )
00740         goto end;
00741 
00742     if( TRACE_ON( msi ) )
00743         enum_stream_names( stg );
00744 
00745     ret = msi_table_apply_transform( db, stg );
00746 
00747 end:
00748     IStorage_Release( stg );
00749 
00750     return ret;
00751 }
00752 
00753 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
00754                  LPCWSTR szTransformFile, int iErrorCond)
00755 {
00756     MSIDATABASE *db;
00757     UINT r;
00758 
00759     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
00760     if( !db )
00761     {
00762         IWineMsiRemoteDatabase *remote_database;
00763 
00764         remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hdb );
00765         if ( !remote_database )
00766             return ERROR_INVALID_HANDLE;
00767 
00768         IWineMsiRemoteDatabase_Release( remote_database );
00769         WARN("MsiDatabaseApplyTransform not allowed during a custom action!\n");
00770 
00771         return ERROR_SUCCESS;
00772     }
00773 
00774     r = MSI_DatabaseApplyTransformW( db, szTransformFile, iErrorCond );
00775     msiobj_release( &db->hdr );
00776     return r;
00777 }
00778 
00779 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb, 
00780                  LPCSTR szTransformFile, int iErrorCond)
00781 {
00782     LPWSTR wstr;
00783     UINT ret;
00784 
00785     TRACE("%d %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
00786 
00787     wstr = strdupAtoW( szTransformFile );
00788     if( szTransformFile && !wstr )
00789         return ERROR_NOT_ENOUGH_MEMORY;
00790 
00791     ret = MsiDatabaseApplyTransformW( hdb, wstr, iErrorCond);
00792 
00793     msi_free( wstr );
00794 
00795     return ret;
00796 }
00797 
00798 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
00799                  LPCSTR szTransformFile, int iReserved1, int iReserved2 )
00800 {
00801     FIXME("%d %d %s %d %d\n", hdb, hdbref,
00802            debugstr_a(szTransformFile), iReserved1, iReserved2);
00803     return ERROR_CALL_NOT_IMPLEMENTED;
00804 }
00805 
00806 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
00807                  LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
00808 {
00809     FIXME("%d %d %s %d %d\n", hdb, hdbref,
00810            debugstr_w(szTransformFile), iReserved1, iReserved2);
00811     return ERROR_CALL_NOT_IMPLEMENTED;
00812 }
00813 
00814 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
00815 {
00816     MSIDATABASE *db;
00817     UINT r;
00818 
00819     TRACE("%d\n", hdb);
00820 
00821     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
00822     if( !db )
00823     {
00824         IWineMsiRemoteDatabase *remote_database;
00825 
00826         remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hdb );
00827         if ( !remote_database )
00828             return ERROR_INVALID_HANDLE;
00829 
00830         IWineMsiRemoteDatabase_Release( remote_database );
00831         WARN("not allowed during a custom action!\n");
00832 
00833         return ERROR_SUCCESS;
00834     }
00835 
00836     if (db->mode == MSIDBOPEN_READONLY)
00837     {
00838         msiobj_release( &db->hdr );
00839         return ERROR_SUCCESS;
00840     }
00841 
00842     /* FIXME: lock the database */
00843 
00844     r = MSI_CommitTables( db );
00845     if (r != ERROR_SUCCESS) ERR("Failed to commit tables!\n");
00846 
00847     /* FIXME: unlock the database */
00848 
00849     msiobj_release( &db->hdr );
00850 
00851     if (r == ERROR_SUCCESS)
00852     {
00853         msi_free( db->deletefile );
00854         db->deletefile = NULL;
00855     }
00856 
00857     return r;
00858 }
00859 
00860 struct msi_primary_key_record_info
00861 {
00862     DWORD n;
00863     MSIRECORD *rec;
00864 };
00865 
00866 static UINT msi_primary_key_iterator( MSIRECORD *rec, LPVOID param )
00867 {
00868     struct msi_primary_key_record_info *info = param;
00869     LPCWSTR name, table;
00870     DWORD type;
00871 
00872     type = MSI_RecordGetInteger( rec, 4 );
00873     if( type & MSITYPE_KEY )
00874     {
00875         info->n++;
00876         if( info->rec )
00877         {
00878             if ( info->n == 1 )
00879             {
00880                 table = MSI_RecordGetString( rec, 1 );
00881                 MSI_RecordSetStringW( info->rec, 0, table);
00882             }
00883 
00884             name = MSI_RecordGetString( rec, 3 );
00885             MSI_RecordSetStringW( info->rec, info->n, name );
00886         }
00887     }
00888 
00889     return ERROR_SUCCESS;
00890 }
00891 
00892 UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *db,
00893                 LPCWSTR table, MSIRECORD **prec )
00894 {
00895     static const WCHAR sql[] = {
00896         's','e','l','e','c','t',' ','*',' ',
00897         'f','r','o','m',' ','`','_','C','o','l','u','m','n','s','`',' ',
00898         'w','h','e','r','e',' ',
00899         '`','T','a','b','l','e','`',' ','=',' ','\'','%','s','\'',0 };
00900     struct msi_primary_key_record_info info;
00901     MSIQUERY *query = NULL;
00902     UINT r;
00903 
00904     if (!TABLE_Exists( db, table ))
00905         return ERROR_INVALID_TABLE;
00906 
00907     r = MSI_OpenQuery( db, &query, sql, table );
00908     if( r != ERROR_SUCCESS )
00909         return r;
00910 
00911     /* count the number of primary key records */
00912     info.n = 0;
00913     info.rec = 0;
00914     r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info );
00915     if( r == ERROR_SUCCESS )
00916     {
00917         TRACE("Found %d primary keys\n", info.n );
00918 
00919         /* allocate a record and fill in the names of the tables */
00920         info.rec = MSI_CreateRecord( info.n );
00921         info.n = 0;
00922         r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info );
00923         if( r == ERROR_SUCCESS )
00924             *prec = info.rec;
00925         else
00926             msiobj_release( &info.rec->hdr );
00927     }
00928     msiobj_release( &query->hdr );
00929 
00930     return r;
00931 }
00932 
00933 UINT WINAPI MsiDatabaseGetPrimaryKeysW( MSIHANDLE hdb,
00934                     LPCWSTR table, MSIHANDLE* phRec )
00935 {
00936     MSIRECORD *rec = NULL;
00937     MSIDATABASE *db;
00938     UINT r;
00939 
00940     TRACE("%d %s %p\n", hdb, debugstr_w(table), phRec);
00941 
00942     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
00943     if( !db )
00944     {
00945         HRESULT hr;
00946         IWineMsiRemoteDatabase *remote_database;
00947 
00948         remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hdb );
00949         if ( !remote_database )
00950             return ERROR_INVALID_HANDLE;
00951 
00952         hr = IWineMsiRemoteDatabase_GetPrimaryKeys( remote_database, table, phRec );
00953         IWineMsiRemoteDatabase_Release( remote_database );
00954 
00955         if (FAILED(hr))
00956         {
00957             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
00958                 return HRESULT_CODE(hr);
00959 
00960             return ERROR_FUNCTION_FAILED;
00961         }
00962 
00963         return ERROR_SUCCESS;
00964     }
00965 
00966     r = MSI_DatabaseGetPrimaryKeys( db, table, &rec );
00967     if( r == ERROR_SUCCESS )
00968     {
00969         *phRec = alloc_msihandle( &rec->hdr );
00970         if (! *phRec)
00971            r = ERROR_NOT_ENOUGH_MEMORY;
00972         msiobj_release( &rec->hdr );
00973     }
00974     msiobj_release( &db->hdr );
00975 
00976     return r;
00977 }
00978 
00979 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, 
00980                     LPCSTR table, MSIHANDLE* phRec)
00981 {
00982     LPWSTR szwTable = NULL;
00983     UINT r;
00984 
00985     TRACE("%d %s %p\n", hdb, debugstr_a(table), phRec);
00986 
00987     if( table )
00988     {
00989         szwTable = strdupAtoW( table );
00990         if( !szwTable )
00991             return ERROR_OUTOFMEMORY;
00992     }
00993     r = MsiDatabaseGetPrimaryKeysW( hdb, szwTable, phRec );
00994     msi_free( szwTable );
00995 
00996     return r;
00997 }
00998 
00999 MSICONDITION WINAPI MsiDatabaseIsTablePersistentA(
01000               MSIHANDLE hDatabase, LPCSTR szTableName)
01001 {
01002     LPWSTR szwTableName = NULL;
01003     MSICONDITION r;
01004 
01005     TRACE("%x %s\n", hDatabase, debugstr_a(szTableName));
01006 
01007     if( szTableName )
01008     {
01009         szwTableName = strdupAtoW( szTableName );
01010         if( !szwTableName )
01011             return MSICONDITION_ERROR;
01012     }
01013     r = MsiDatabaseIsTablePersistentW( hDatabase, szwTableName );
01014     msi_free( szwTableName );
01015 
01016     return r;
01017 }
01018 
01019 MSICONDITION WINAPI MsiDatabaseIsTablePersistentW(
01020               MSIHANDLE hDatabase, LPCWSTR szTableName)
01021 {
01022     MSIDATABASE *db;
01023     MSICONDITION r;
01024 
01025     TRACE("%x %s\n", hDatabase, debugstr_w(szTableName));
01026 
01027     db = msihandle2msiinfo( hDatabase, MSIHANDLETYPE_DATABASE );
01028     if( !db )
01029     {
01030         HRESULT hr;
01031         MSICONDITION condition;
01032         IWineMsiRemoteDatabase *remote_database;
01033 
01034         remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hDatabase );
01035         if ( !remote_database )
01036             return MSICONDITION_ERROR;
01037 
01038         hr = IWineMsiRemoteDatabase_IsTablePersistent( remote_database,
01039                                                        szTableName, &condition );
01040         IWineMsiRemoteDatabase_Release( remote_database );
01041 
01042         if (FAILED(hr))
01043             return MSICONDITION_ERROR;
01044 
01045         return condition;
01046     }
01047 
01048     r = MSI_DatabaseIsTablePersistent( db, szTableName );
01049 
01050     msiobj_release( &db->hdr );
01051 
01052     return r;
01053 }

Generated on Sat May 26 2012 04:23:49 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.