msi [2/2]: Perform button control events in greatest to least order [RESEND]

James Hawkins truiken at gmail.com
Thu Oct 5 21:52:09 CDT 2006


Hi,

Is there anything wrong with this patch?  It fixes bug 6379.  msdn is
not specific about which order the events in the ControlEvent table
are executed, greatest to least or vice versa.

Ordering
    An integer used to order several events tied to the same control.

Also, msdn says this about SpawnDialog and NewDialog events in the
ControlEvent table:

"If multiple NewDialog and SpawnDialog control events are selected for
the same control, only the event with the largest value in the
Ordering column gets published when the control is activated."

which is more evidence that the order is greatest to least.  The
America's Army installer publishes two events when the Browse button
is pushed.  The first event, with order = 1, calls SpawnDialog on the
DestinationFolder dialog.  The second event, with order = 2, sets the
_BrowseProperty eqal to INSTALLDIR.  Before the events are published,
_BrowseProperty is empty.  The DestinationFolder dialog uses
_BrowseProperty to determine what directory should initially be
displayed.  This property must be set to INSTALLDIR before the dialog
is spawned, or the dialog wouldn't know what to display.  This is what
happens in our case, and this patch fixes the behavior.


Changelog:
* Perform button control events in greatest to least order.

 dlls/msi/dialog.c   |   10 +++++++++-
 dlls/msi/msipriv.h  |    1 +
 dlls/msi/msiquery.c |   28 ++++++++++++++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c
index 11890ac..b1c7288 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -2914,7 +2914,15 @@ static UINT msi_dialog_button_handler( m
         return 0;
     }
 
-    r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog );
+    r = MSI_ViewExecute( view, NULL );
+    if ( r != ERROR_SUCCESS )
+    {
+        msiobj_release( &view->hdr );
+        return r;
+    }
+
+    r = MSI_ReverseRecords( view, 0, msi_dialog_control_event, dialog );
+    MSI_ViewClose( view );
     msiobj_release( &view->hdr );
 
     return r;
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index cc3b88b..23caf15 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -386,6 +386,7 @@ extern UINT MSI_OpenDatabaseW( LPCWSTR, 
 extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** );
 extern UINT MSI_OpenQuery( MSIDATABASE *, MSIQUERY **, LPCWSTR, ... );
 typedef UINT (*record_func)( MSIRECORD *, LPVOID );
+extern UINT MSI_ReverseRecords( 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 7816e13..477f246 100644
--- a/dlls/msi/msiquery.c
+++ b/dlls/msi/msiquery.c
@@ -164,6 +164,34 @@ UINT MSI_OpenQuery( MSIDATABASE *db, MSI
     return r;
 }
 
+/* execute record_func on records in reverse order */
+UINT MSI_ReverseRecords( MSIQUERY *view, DWORD *count,
+                         record_func func, LPVOID param )
+{
+    MSIRECORD *rec = NULL;
+    UINT r;
+
+    r = MSI_ViewFetch( view, &rec );
+    if ( r != ERROR_SUCCESS )
+        return (r == ERROR_NO_MORE_ITEMS) ? ERROR_SUCCESS : r;
+
+    if (count) (*count)--;
+    r = MSI_ReverseRecords( view, count, func, param );
+    if ( r != ERROR_SUCCESS )
+        goto done;
+
+    if ( func )
+        r = func( rec, param );
+
+done:
+    msiobj_release( &rec->hdr );
+
+    if ( count )
+        (*count)++;
+
+    return r;
+}
+
 UINT MSI_IterateRecords( MSIQUERY *view, DWORD *count,
                          record_func func, LPVOID param )
 {
-- 
1.4.2.1


More information about the wine-patches mailing list