Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsiquery.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
1.7.6.1
|