diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c index 11890ac5237..6c6aa0e4079 100644 --- a/dlls/msi/dialog.c +++ b/dlls/msi/dialog.c @@ -2914,7 +2914,7 @@ static UINT msi_dialog_button_handler( msi_dialog *dialog, return 0; } - r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog ); + r = MSI_ReverseIterateRecords( view, 0, msi_dialog_control_event, dialog ); msiobj_release( &view->hdr ); return r; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index cc3b88bc4a0..8b9eabb899b 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -386,6 +386,7 @@ extern UINT MSI_OpenDatabaseW( LPCWSTR, LPCWSTR, MSIDATABASE ** ); extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** ); extern UINT MSI_OpenQuery( MSIDATABASE *, MSIQUERY **, LPCWSTR, ... ); typedef UINT (*record_func)( MSIRECORD *, LPVOID ); +extern UINT MSI_ReverseIterateRecords( MSIQUERY *, DWORD *, record_func, LPVOID ); extern UINT MSI_IterateRecords( MSIQUERY *, DWORD *, record_func, LPVOID ); extern MSIRECORD *MSI_QueryGetRecord( MSIDATABASE *db, LPCWSTR query, ... ); extern UINT MSI_DatabaseImport( MSIDATABASE *, LPCWSTR, LPCWSTR ); diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index 7816e137ea0..ff8aa4226fa 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -27,6 +27,7 @@ #include "winerror.h" #include "wine/debug.h" #include "wine/unicode.h" +#include "wine/list.h" #include "msi.h" #include "msiquery.h" #include "objbase.h" @@ -164,6 +165,82 @@ UINT MSI_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... ) return r; } +struct rec_list +{ + struct list entry; + MSIRECORD *rec; +}; + +UINT MSI_ReverseIterateRecords( MSIQUERY *view, DWORD *count, + record_func func, LPVOID param ) +{ + MSIRECORD *rec = NULL; + struct rec_list *add_rec; + struct list records; + UINT r, n = 0, max = 0; + + r = MSI_ViewExecute( view, NULL ); + if( r != ERROR_SUCCESS ) + return r; + + list_init( &records ); + + if( count ) + max = *count; + + /* reverse the query */ + for( n = 0; (max == 0) || (n < max); n++ ) + { + r = MSI_ViewFetch( view, &rec ); + if( r != ERROR_SUCCESS ) + { + if ( r == ERROR_NO_MORE_ITEMS ) + break; + else + goto done; + } + + add_rec = msi_alloc( sizeof( *add_rec ) ); + if (!add_rec) + goto done; + + add_rec->rec = rec; + list_add_head( &records, &add_rec->entry ); + } + + /* iterate over the reversed records */ + n = 0; + LIST_FOR_EACH_ENTRY( add_rec, &records, struct rec_list, entry ) + { + if (func) + r = func( add_rec->rec, param ); + + msiobj_release( &add_rec->rec->hdr ); + if ( r != ERROR_SUCCESS ) + goto done; + + n++; + } + +done: + MSI_ViewClose( view ); + + while ( !list_empty( &records ) ) + { + add_rec = LIST_ENTRY( list_head( &records ), struct rec_list, entry ); + list_remove( &add_rec->entry ); + msi_free( add_rec ); + } + + if( count ) + *count = n; + + if( r == ERROR_NO_MORE_ITEMS ) + r = ERROR_SUCCESS; + + return r; +} + UINT MSI_IterateRecords( MSIQUERY *view, DWORD *count, record_func func, LPVOID param ) {