msi [2/3]: Run SetProperty events before all other events no matter
what the order is
James Hawkins
truiken at gmail.com
Mon Oct 16 17:44:52 CDT 2006
Hi,
This patch is the correct solution to fix the America's Army installer.
Changelog:
* Run SetProperty events before all other events no matter what the order is.
dlls/msi/dialog.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++-
dlls/msi/msipriv.h | 1 +
dlls/msi/record.c | 23 ++++++++++++++
3 files changed, 107 insertions(+), 1 deletions(-)
--
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c
index f40ed76..03ba6f2 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -2886,6 +2886,62 @@ static UINT msi_dialog_control_event( MS
return ERROR_SUCCESS;
}
+struct rec_list
+{
+ struct list entry;
+ MSIRECORD *rec;
+};
+
+static UINT add_recs_to_list( MSIRECORD *rec, LPVOID param )
+{
+ struct rec_list *add_rec;
+ struct list *records = (struct list *)param;
+ MSIRECORD *copy;
+
+ copy = MSI_CopyRecord( rec );
+ if (!copy)
+ return ERROR_OUTOFMEMORY;
+
+ add_rec = msi_alloc( sizeof( *add_rec ) );
+ if (!add_rec)
+ {
+ msiobj_release( ©->hdr );
+ return ERROR_OUTOFMEMORY;
+ }
+
+ add_rec->rec = copy;
+ list_add_tail( records, &add_rec->entry );
+ return ERROR_SUCCESS;
+}
+
+static void reprioritize_set_prop_events( struct list *events)
+{
+ struct rec_list *rec_entry, *next;
+ struct list set_props;
+ LPCWSTR event;
+ DWORD len;
+
+ list_init( &set_props );
+
+ LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, events, struct rec_list, entry )
+ {
+ event = MSI_RecordGetString( rec_entry->rec, 3 );
+ len = lstrlenW(event);
+
+ if ( event[0] == '[' && event[len - 1] == ']' )
+ {
+ list_remove( &rec_entry->entry );
+ list_add_head( &set_props, &rec_entry->entry );
+ }
+ }
+
+ LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, &set_props, struct rec_list, entry )
+ {
+ list_remove( &rec_entry->entry );
+ list_add_head( events, &rec_entry->entry );
+ }
+}
+
static UINT msi_dialog_button_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
@@ -2899,11 +2955,15 @@ static UINT msi_dialog_button_handler( m
'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','i','n','g','`',0
};
MSIQUERY *view = NULL;
+ struct rec_list *rec_entry, *next;
+ struct list events;
UINT r;
if( HIWORD(param) != BN_CLICKED )
return ERROR_SUCCESS;
+ list_init( &events );
+
r = MSI_OpenQuery( dialog->package->db, &view, query,
dialog->name, control->name );
if( r != ERROR_SUCCESS )
@@ -2912,8 +2972,30 @@ static UINT msi_dialog_button_handler( m
return 0;
}
- r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog );
+ r = MSI_IterateRecords( view, 0, add_recs_to_list, &events );
msiobj_release( &view->hdr );
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ /* move SetProperty events to the front of the list */
+ reprioritize_set_prop_events( &events );
+
+ LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, &events, struct rec_list, entry )
+ {
+ r = msi_dialog_control_event( rec_entry->rec, dialog );
+ list_remove( &rec_entry->entry );
+ msiobj_release( &rec_entry->rec->hdr );
+
+ if ( r != ERROR_SUCCESS )
+ goto done;
+ }
+
+done:
+ LIST_FOR_EACH_ENTRY_SAFE( rec_entry, next, &events, struct rec_list, entry )
+ {
+ list_remove( &rec_entry->entry );
+ msi_free( rec_entry );
+ }
return r;
}
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 94edb23..137f2d9 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -590,6 +590,7 @@ extern UINT MSI_RecordSetStreamA( MSIREC
extern UINT MSI_RecordDataSize( MSIRECORD *, unsigned int );
extern UINT MSI_RecordStreamToFile( MSIRECORD *, unsigned int, LPCWSTR );
extern UINT MSI_RecordCopyField( MSIRECORD *, unsigned int, MSIRECORD *, unsigned int );
+extern MSIRECORD *MSI_CopyRecord( MSIRECORD * );
/* stream internals */
extern UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm );
diff --git a/dlls/msi/record.c b/dlls/msi/record.c
index 6705a03..9ec9bd3 100644
--- a/dlls/msi/record.c
+++ b/dlls/msi/record.c
@@ -200,6 +200,29 @@ UINT MSI_RecordCopyField( MSIRECORD *in_
return r;
}
+MSIRECORD *MSI_CopyRecord( MSIRECORD *in )
+{
+ DWORD num_fields = MSI_RecordGetFieldCount( in );
+ MSIRECORD *out = MSI_CreateRecord( num_fields );
+ DWORD i;
+ UINT r;
+
+ if ( !out )
+ return NULL;
+
+ for ( i = 0; i < num_fields; i++)
+ {
+ r = MSI_RecordCopyField( in, i, out, i );
+ if ( r != ERROR_SUCCESS )
+ {
+ msiobj_release( &out->hdr );
+ return NULL;
+ }
+ }
+
+ return out;
+}
+
int MSI_RecordGetInteger( MSIRECORD *rec, unsigned int iField)
{
int ret = 0;
--
1.4.2.1
More information about the wine-patches
mailing list