MSI: improvements to the dialog code

Mike McCormack mike at codeweavers.com
Mon Jan 31 23:09:20 CST 2005


ChangeLog:
* Respect the Visible property of the dialog.
* Rename dialog_info to msi_dialog.
* Store a list of the controls we create.
* Process the ControlConditions table to set the state of controls.
-------------- next part --------------
Index: dlls/msi/dialog.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/dialog.c,v
retrieving revision 1.1
diff -u -p -r1.1 dialog.c
--- dlls/msi/dialog.c	28 Jan 2005 12:39:57 -0000	1.1
+++ dlls/msi/dialog.c	1 Feb 2005 05:05:02 -0000
@@ -27,69 +27,160 @@
 #include "wingdi.h"
 #include "msi.h"
 #include "msipriv.h"
+#include "msidefs.h"
 
 #include "wine/debug.h"
 #include "wine/unicode.h"
 
+#include "action.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
 
 const WCHAR szMsiDialogClass[] = {
     'M','s','i','D','i','a','l','o','g','C','l','o','s','e','C','l','a','s','s',0
 };
+const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
+
+typedef struct msi_control_tag
+{
+    struct msi_control_tag *next;
+    HWND hwnd;
+    WCHAR name[1];
+} msi_control;
 
-struct tag_dialog_info
+struct msi_dialog_tag
 {
     MSIPACKAGE *package;
     msi_dialog_event_handler event_handler;
     INT scale;
+    DWORD attributes;
     HWND hwnd;
+    msi_control *control_list;
     WCHAR name[1];
 };
 
-typedef UINT (*msi_dialog_control_func)( dialog_info *dialog, MSIRECORD *rec );
+typedef UINT (*msi_dialog_control_func)( msi_dialog *dialog, MSIRECORD *rec );
 struct control_handler 
 {
     LPCWSTR control_type;
     msi_dialog_control_func func;
 };
 
-static UINT msi_dialog_text_control( dialog_info *dialog, MSIRECORD *rec )
+INT msi_dialog_scale_unit( msi_dialog *dialog, INT val )
 {
-    DWORD x, y, width, height;
-    LPCWSTR text;
-    const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
-    HWND hwnd;
+    return (dialog->scale * val + 5) / 10;
+}
 
-    TRACE("%p %p\n", dialog, rec);
+/*
+ * msi_dialog_get_style
+ *
+ * Extract the {\style} string from the front of the text to display and
+ *  update the pointer.
+ */
+static LPWSTR msi_dialog_get_style( LPCWSTR *text )
+{
+    LPWSTR ret = NULL;
+    LPCWSTR p = *text, q;
+    DWORD len;
+
+    if( *p++ != '{' )
+        return ret;
+    q = strchrW( p, '}' );
+    if( !q )
+        return ret;
+    *text = ++q;
+    if( *p++ != '\\' )
+        return ret;
+    len = q - p;
+    
+    ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+    if( !ret )
+        return ret;
+    strncpyW( ret, p, len );
+    ret[len-1] = 0;
+    return ret;
+}
 
-    x = MSI_RecordGetInteger( rec, 4 );
-    y = MSI_RecordGetInteger( rec, 5 );
-    width = MSI_RecordGetInteger( rec, 6 );
-    height = MSI_RecordGetInteger( rec, 7 );
-    text = MSI_RecordGetString( rec, 10 );
+static UINT msi_dialog_font_iter( MSIRECORD *rec, LPVOID param )
+{
+    HWND hwnd = param;
+    LOGFONTW lf;
+    LPCWSTR name;
+    HFONT hfont;
+    INT style;
+    HDC hdc;
 
-    x = (dialog->scale * x) / 10;
-    y = (dialog->scale * y) / 10;
-    width = (dialog->scale * width) / 10;
-    height = (dialog->scale * height) / 10;
+    TRACE("Setting style window %p\n", hwnd );
 
-    hwnd = CreateWindowW( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP,
-                          x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
-    if (!hwnd)
-        ERR("Failed to create hwnd\n");
+    memset( &lf, 0, sizeof lf );
+    name = MSI_RecordGetString( rec, 2 );
+    lf.lfHeight = MSI_RecordGetInteger( rec, 3 );
+    style = MSI_RecordGetInteger( rec, 5 );
+    if( style & 1 )
+        lf.lfWeight = FW_BOLD;
+    if( style & 2 )
+        lf.lfItalic = TRUE;
+    if( style & 4 )
+        lf.lfUnderline = TRUE;
+    if( style & 8 )
+        lf.lfStrikeOut = TRUE;
+    lstrcpynW( lf.lfFaceName, name, LF_FACESIZE );
+
+    /* adjust the height */
+    hdc = GetDC( hwnd );
+    if (hdc)
+    {
+        lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+        ReleaseDC( hwnd, hdc );
+    }
 
+    hfont = CreateFontIndirectW( &lf );
+    SendMessageW( hwnd, WM_SETFONT, (WPARAM) hfont, TRUE );
+    /* FIXME: DeleteObject( hfont ); */
     return ERROR_SUCCESS;
 }
 
-static UINT msi_dialog_button_control( dialog_info *dialog, MSIRECORD *rec )
+static UINT msi_dialog_set_font( MSIDATABASE *db, HWND hwnd, LPCWSTR font )
 {
-    const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
-    DWORD x, y, width, height;
-    LPCWSTR text;
-    HWND hwnd;
+    static const WCHAR query[] = {
+      'S','E','L','E','C','T',' ','*',' ',
+      'F','R','O','M',' ','`','T','e','x','t','S','t','y','l','e','`',' ',
+      'W','H','E','R','E',' ',
+      '`','T','e','x','t','S','t','y','l','e','`',' ','=',' ','\'','%','s','\'',0
+    };
+    DWORD count = 1;
+    UINT r;
+    MSIQUERY *view = NULL;
 
-    TRACE("%p %p\n", dialog, rec);
+    TRACE("Set font for %p to %s\n", hwnd, debugstr_w(font) );
+
+    r = MSI_OpenQuery( db, &view, query, font );
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    r = MSI_IterateRecords( view, &count, msi_dialog_font_iter, hwnd );
+    msiobj_release( &view->hdr );
+
+    return r;
+}
+
+static msi_control *msi_dialog_create_child( msi_dialog *dialog,
+                MSIRECORD *rec, LPCWSTR szCls, DWORD style )
+{
+    DWORD x, y, width, height;
+    LPCWSTR text, name;
+    LPWSTR font, title = NULL;
+    msi_control *control = NULL;
+
+    style |= WS_CHILD | WS_VISIBLE | WS_GROUP;
+
+    name = MSI_RecordGetString( rec, 2 );
+    control = HeapAlloc( GetProcessHeap(), 0,
+                         sizeof *control + strlenW(name)*sizeof(WCHAR) );
+    strcpyW( control->name, name );
+    control->next = dialog->control_list;
+    dialog->control_list = control;
 
     x = MSI_RecordGetInteger( rec, 4 );
     y = MSI_RecordGetInteger( rec, 5 );
@@ -97,43 +188,50 @@ static UINT msi_dialog_button_control( d
     height = MSI_RecordGetInteger( rec, 7 );
     text = MSI_RecordGetString( rec, 10 );
 
-    x = (dialog->scale * x) / 10;
-    y = (dialog->scale * y) / 10;
-    width = (dialog->scale * width) / 10;
-    height = (dialog->scale * height) / 10;
+    TRACE("Dialog %s control %s\n", debugstr_w(dialog->name), debugstr_w(text));
 
-    hwnd = CreateWindowW( szButton, text, WS_CHILD | WS_VISIBLE |WS_GROUP,
+    x = msi_dialog_scale_unit( dialog, x );
+    y = msi_dialog_scale_unit( dialog, y );
+    width = msi_dialog_scale_unit( dialog, width );
+    height = msi_dialog_scale_unit( dialog, height );
+
+    font = msi_dialog_get_style( &text );
+    deformat_string( dialog->package, text, &title );
+    control->hwnd = CreateWindowW( szCls, title, style,
                           x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
+    if( font )
+    {
+        msi_dialog_set_font( dialog->package->db, control->hwnd, font );
+        HeapFree( GetProcessHeap(), 0, font );
+    }
+    if( title )
+        HeapFree( GetProcessHeap(), 0, font );
+    return control;
+}
 
+static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec )
+{
+    TRACE("%p %p\n", dialog, rec);
+
+    msi_dialog_create_child( dialog, rec, szStatic, 0 );
     return ERROR_SUCCESS;
 }
 
-static UINT msi_dialog_line_control( dialog_info *dialog, MSIRECORD *rec )
+static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec )
 {
-    DWORD x, y, width, height;
-    LPCWSTR text;
-    const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
-    HWND hwnd;
+    const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
 
     TRACE("%p %p\n", dialog, rec);
 
-    x = MSI_RecordGetInteger( rec, 4 );
-    y = MSI_RecordGetInteger( rec, 5 );
-    width = MSI_RecordGetInteger( rec, 6 );
-    height = MSI_RecordGetInteger( rec, 7 );
-    text = MSI_RecordGetString( rec, 10 );
-
-    x = (dialog->scale * x) / 10;
-    y = (dialog->scale * y) / 10;
-    width = (dialog->scale * width) / 10;
-    height = (dialog->scale * height) / 10;
+    msi_dialog_create_child( dialog, rec, szButton, 0 );
+    return ERROR_SUCCESS;
+}
 
-    hwnd = CreateWindowW( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP |
-                          SS_ETCHEDHORZ |SS_SUNKEN,
-                          x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
-    if (!hwnd)
-        ERR("Failed to create hwnd\n");
+static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec )
+{
+    TRACE("%p %p\n", dialog, rec);
 
+    msi_dialog_create_child( dialog, rec, szStatic, SS_ETCHEDHORZ | SS_SUNKEN );
     return ERROR_SUCCESS;
 }
 
@@ -165,32 +263,12 @@ static UINT msi_load_picture( MSIDATABAS
 }
 #endif
 
-static UINT msi_dialog_bitmap_control( dialog_info *dialog, MSIRECORD *rec )
+static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec )
 {
-    DWORD x, y, width, height;
-    LPCWSTR text;
-    const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
-    HWND hwnd;
-
     TRACE("%p %p\n", dialog, rec);
 
-    x = MSI_RecordGetInteger( rec, 4 );
-    y = MSI_RecordGetInteger( rec, 5 );
-    width = MSI_RecordGetInteger( rec, 6 );
-    height = MSI_RecordGetInteger( rec, 7 );
-    text = MSI_RecordGetString( rec, 10 );
-
-    x = (dialog->scale * x) / 10;
-    y = (dialog->scale * y) / 10;
-    width = (dialog->scale * width) / 10;
-    height = (dialog->scale * height) / 10;
-
-    hwnd = CreateWindowW( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP | WS_DISABLED |
-                          SS_BITMAP | SS_LEFT | SS_CENTERIMAGE,
-                          x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
-    if (!hwnd)
-        ERR("Failed to create hwnd\n");
-
+    msi_dialog_create_child( dialog, rec, szStatic,
+                             SS_BITMAP | SS_LEFT | SS_CENTERIMAGE );
     return ERROR_SUCCESS;
 }
 
@@ -209,37 +287,9 @@ struct control_handler msi_dialog_handle
 
 #define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0])
 
-typedef UINT (*record_func)( MSIRECORD *rec, LPVOID param );
-
-static UINT msi_iterate_records( MSIQUERY *view, record_func func, LPVOID param )
-{
-    MSIRECORD *rec = NULL;
-    UINT r;
-
-    r = MSI_ViewExecute( view, NULL );
-    if( r != ERROR_SUCCESS )
-        return r;
-
-    /* iterate a query */
-    while( 1 )
-    {
-        r = MSI_ViewFetch( view, &rec );
-        if( r != ERROR_SUCCESS )
-            break;
-        r = func( rec, param );
-        msiobj_release( &rec->hdr );
-        if( r != ERROR_SUCCESS )
-            break;
-    }
-
-    MSI_ViewClose( view );
-
-    return ERROR_SUCCESS;
-}
-
 static UINT msi_dialog_create_controls( MSIRECORD *rec, LPVOID param )
 {
-    dialog_info *dialog = param;
+    msi_dialog *dialog = param;
     LPCWSTR control_type;
     UINT i;
 
@@ -256,7 +306,7 @@ static UINT msi_dialog_create_controls( 
     return ERROR_SUCCESS;
 }
 
-static UINT msi_dialog_fill_controls( dialog_info *dialog, LPCWSTR name )
+static UINT msi_dialog_fill_controls( msi_dialog *dialog )
 {
     static const WCHAR query[] = {
         'S','E','L','E','C','T',' ','*',' ',
@@ -267,17 +317,90 @@ static UINT msi_dialog_fill_controls( di
     MSIQUERY *view = NULL;
     MSIPACKAGE *package = dialog->package;
 
-    TRACE("%p %s\n", dialog, debugstr_w(name) );
+    TRACE("%p %s\n", dialog, debugstr_w(dialog->name) );
 
     /* query the Control table for all the elements of the control */
-    r = MSI_OpenQuery( package->db, &view, query, name );
+    r = MSI_OpenQuery( package->db, &view, query, dialog->name );
     if( r != ERROR_SUCCESS )
     {
-        ERR("query failed for dialog %s\n", debugstr_w(name));
+        ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
         return ERROR_INVALID_PARAMETER;
     }
 
-    r = msi_iterate_records( view, msi_dialog_create_controls, dialog );
+    r = MSI_IterateRecords( view, 0, msi_dialog_create_controls, dialog );
+    msiobj_release( &view->hdr );
+
+    return r;
+}
+
+static msi_control *msi_dialog_find_control( msi_dialog *dialog, LPCWSTR name )
+{
+    msi_control *control;
+
+    for( control = dialog->control_list; control; control = control->next )
+        if( !strcmpW( control->name, name ) )
+            break;
+    return control;
+}
+
+static UINT msi_dialog_set_control_condition( MSIRECORD *rec, LPVOID param )
+{
+    static const WCHAR szHide[] = { 'H','i','d','e',0 };
+    static const WCHAR szShow[] = { 'S','h','o','w',0 };
+    static const WCHAR szDisable[] = { 'D','i','s','a','b','l','e',0 };
+    static const WCHAR szEnable[] = { 'E','n','a','b','l','e',0 };
+    msi_dialog *dialog = param;
+    msi_control *control;
+    LPCWSTR name, action, condition;
+    UINT r;
+
+    name = MSI_RecordGetString( rec, 2 );
+    action = MSI_RecordGetString( rec, 3 );
+    condition = MSI_RecordGetString( rec, 4 );
+    r = MSI_EvaluateConditionW( dialog->package, condition );
+    control = msi_dialog_find_control( dialog, name );
+    if( r && control )
+    {
+        TRACE("%s control %s\n", debugstr_w(action), debugstr_w(name));
+        if(!strcmpW(action, szHide))
+            ShowWindow(control->hwnd, SW_HIDE);
+        else if(!strcmpW(action, szShow))
+            ShowWindow(control->hwnd, SW_SHOW);
+        else if(!strcmpW(action, szDisable))
+            EnableWindow(control->hwnd, FALSE);
+        else if(!strcmpW(action, szEnable))
+            EnableWindow(control->hwnd, FALSE);
+        else
+            FIXME("Unhandled action %s\n", debugstr_w(action));
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static UINT msi_dialog_evaluate_control_conditions( msi_dialog *dialog )
+{
+    static const WCHAR query[] = {
+      'S','E','L','E','C','T',' ','*',' ',
+      'F','R','O','M',' ',
+        'C','o','n','t','r','o','l','C','o','n','d','i','t','i','o','n',' ',
+      'W','H','E','R','E',' ',
+        '`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',0
+    };
+    UINT r;
+    MSIQUERY *view = NULL;
+    MSIPACKAGE *package = dialog->package;
+
+    TRACE("%p %s\n", dialog, debugstr_w(dialog->name) );
+
+    /* query the Control table for all the elements of the control */
+    r = MSI_OpenQuery( package->db, &view, query, dialog->name );
+    if( r != ERROR_SUCCESS )
+    {
+        ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    r = MSI_IterateRecords( view, 0, msi_dialog_set_control_condition, dialog );
     msiobj_release( &view->hdr );
 
     return r;
@@ -299,7 +422,7 @@ static INT msi_dialog_get_sans_serif_hei
     if (hdc)
     {
         memset( &lf, 0, sizeof lf );
-        lf.lfHeight = -MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+        lf.lfHeight = MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
         strcpyW( lf.lfFaceName, szSansSerif );
         hFont = CreateFontIndirectW(&lf);
         if (hFont)
@@ -323,12 +446,13 @@ static LRESULT msi_dialog_oncreate( HWND
         'F','R','O','M',' ','D','i','a','l','o','g',' ',
         'W','H','E','R','E',' ',
            '`','D','i','a','l','o','g','`',' ','=',' ','\'','%','s','\'',0};
-    dialog_info *dialog = (dialog_info*) cs->lpCreateParams;
+    msi_dialog *dialog = (msi_dialog*) cs->lpCreateParams;
     MSIPACKAGE *package = dialog->package;
     MSIQUERY *view = NULL;
     MSIRECORD *rec = NULL;
     DWORD width, height;
-    LPCWSTR title;
+    LPCWSTR text;
+    LPWSTR title = NULL;
     UINT r;
 
     TRACE("%p %p\n", dialog, package);
@@ -341,7 +465,7 @@ static LRESULT msi_dialog_oncreate( HWND
     if( r != ERROR_SUCCESS )
     {
         ERR("query failed for dialog %s\n", debugstr_w(dialog->name));
-        return 1;
+        return -1;
     }
     MSI_ViewExecute( view, NULL );
     MSI_ViewFetch( view, &rec );
@@ -350,31 +474,36 @@ static LRESULT msi_dialog_oncreate( HWND
 
     if( !rec )
     {
-        ERR("No record found for dialog %s\n", debugstr_w(dialog->name));
-        return 1;
+        TRACE("No record found for dialog %s\n", debugstr_w(dialog->name));
+        return -1;
     }
 
     dialog->scale = msi_dialog_get_sans_serif_height(dialog->hwnd);
 
     width = MSI_RecordGetInteger( rec, 4 );
     height = MSI_RecordGetInteger( rec, 5 );
-    title = MSI_RecordGetString( rec, 7 );
+    dialog->attributes = MSI_RecordGetInteger( rec, 6 );
+    text = MSI_RecordGetString( rec, 7 );
 
-    width = (dialog->scale * width) / 10;
-    height = (dialog->scale * height) / 10;
+    width = msi_dialog_scale_unit( dialog, width );
+    height = msi_dialog_scale_unit( dialog, height );
 
+    deformat_string( dialog->package, text, &title );
     SetWindowTextW( hwnd, title );
     SetWindowPos( hwnd, 0, 0, 0, width, height,
                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW );
 
+    if( title )
+        HeapFree( GetProcessHeap(), 0, title );
     msiobj_release( &rec->hdr );
 
-    msi_dialog_fill_controls( dialog, dialog->name );
+    msi_dialog_fill_controls( dialog );
+    msi_dialog_evaluate_control_conditions( dialog );
 
     return 0;
 }
 
-static LRESULT msi_dialog_handle_click( dialog_info *dialog,
+static LRESULT msi_dialog_handle_click( msi_dialog *dialog,
                                      DWORD id, HWND handle )
 {
     TRACE("BN_CLICKED %08lx %p\n", id, handle);
@@ -385,7 +514,7 @@ static LRESULT msi_dialog_handle_click( 
 static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
                 WPARAM wParam, LPARAM lParam )
 {
-    dialog_info *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
+    msi_dialog *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
 
     switch (msg)
     {
@@ -406,10 +535,10 @@ static LRESULT WINAPI MSIDialog_WndProc(
 
 /* functions that interface to other modules within MSI */
 
-dialog_info *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
+msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
                                 msi_dialog_event_handler event_handler )
 {
-    dialog_info *dialog;
+    msi_dialog *dialog;
     HWND hwnd;
 
     TRACE("%p %s\n", package, debugstr_w(szDialogName));
@@ -424,22 +553,50 @@ dialog_info *msi_dialog_create( MSIPACKA
     dialog->event_handler = event_handler;
     msiobj_addref( &package->hdr );
 
-    /* create and show the dialog window */
+    /* create the dialog window, don't show it yet */
     hwnd = CreateWindowW( szMsiDialogClass, szDialogName, WS_OVERLAPPEDWINDOW,
                      CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                      NULL, NULL, NULL, dialog );
     if( !hwnd )
     {
+        ERR("Failed to create dialog %s\n", debugstr_w( szDialogName ));
         msi_dialog_destroy( dialog );
         return NULL;
     }
-    ShowWindow( hwnd, SW_SHOW );
-    UpdateWindow( hwnd );
 
     return dialog;
 }
 
-void msi_dialog_destroy( dialog_info *dialog )
+UINT msi_dialog_run_message_loop( msi_dialog *dialog )
+{
+    MSG msg;
+
+    if( dialog->attributes & msidbDialogAttributesVisible )
+    {
+        ShowWindow( dialog->hwnd, SW_SHOW );
+        UpdateWindow( dialog->hwnd );
+    }
+
+    if( dialog->attributes & msidbDialogAttributesModal )
+    {
+        while(GetMessageW(&msg,0,0,0))
+        {
+            TranslateMessage(&msg);
+            DispatchMessageW(&msg);
+        }
+    }
+
+    return ERROR_SUCCESS;
+}
+
+void msi_dialog_do_preview( msi_dialog *dialog )
+{
+    dialog->attributes |= msidbDialogAttributesVisible;
+    dialog->attributes &= ~msidbDialogAttributesModal;
+    msi_dialog_run_message_loop( dialog );
+}
+
+void msi_dialog_destroy( msi_dialog *dialog )
 {
     if( dialog->hwnd )
         DestroyWindow( dialog->hwnd );
Index: dlls/msi/msipriv.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/msipriv.h,v
retrieving revision 1.44
diff -u -p -r1.44 msipriv.h
--- dlls/msi/msipriv.h	28 Jan 2005 12:39:57 -0000	1.44
+++ dlls/msi/msipriv.h	1 Feb 2005 05:05:02 -0000
@@ -182,6 +182,9 @@ struct tagMSIVIEW
     MSIVIEWOPS   *ops;
 };
 
+struct msi_dialog_tag;
+typedef struct msi_dialog_tag msi_dialog;
+
 typedef struct tagMSIPACKAGE
 {
     MSIOBJECTHDR hdr;
@@ -209,16 +212,14 @@ typedef struct tagMSIPACKAGE
     LPWSTR PackagePath;
 
     UINT CurrentInstallState;
+    msi_dialog *dialog;
 } MSIPACKAGE;
 
-struct tag_dialog_info;
-typedef struct tag_dialog_info dialog_info;
-
 typedef struct tagMSIPREVIEW
 {
     MSIOBJECTHDR hdr;
     MSIPACKAGE *package;
-    dialog_info *dialog;
+    msi_dialog *dialog;
 } MSIPREVIEW;
 
 #define MSIHANDLETYPE_ANY 0
@@ -322,6 +323,8 @@ extern void enum_stream_names( IStorage 
 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 *rec, LPVOID param );
+extern UINT MSI_IterateRecords( MSIQUERY *, DWORD *, record_func, LPVOID );
 
 /* view internals */
 extern UINT MSI_ViewExecute( MSIQUERY*, MSIRECORD * );
@@ -360,8 +363,10 @@ extern UINT MSIREG_OpenUserFeaturesKey(L
 
 /* msi dialog interface */
 typedef VOID (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, HWND );
-extern dialog_info *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog_event_handler );
-extern void msi_dialog_destroy( dialog_info* );
+extern msi_dialog *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog_event_handler );
+extern UINT msi_dialog_run_message_loop( msi_dialog* );
+extern void msi_dialog_do_preview( msi_dialog* );
+extern void msi_dialog_destroy( msi_dialog* );
 extern void msi_dialog_register_class( void );
 extern void msi_dialog_unregister_class( void );
 
Index: dlls/msi/msiquery.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/msiquery.c,v
retrieving revision 1.20
diff -u -p -r1.20 msiquery.c
--- dlls/msi/msiquery.c	21 Jan 2005 16:19:11 -0000	1.20
+++ dlls/msi/msiquery.c	1 Feb 2005 05:05:02 -0000
@@ -182,6 +182,40 @@ UINT MSI_OpenQuery( MSIDATABASE *db, MSI
     return rc;
 }
 
+UINT MSI_IterateRecords( MSIQUERY *view, DWORD *count,
+                         record_func func, LPVOID param )
+{
+    MSIRECORD *rec = NULL;
+    UINT r, n = 0, max = 0;
+
+    r = MSI_ViewExecute( view, NULL );
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    if( count )
+        max = *count;
+
+    /* iterate a query */
+    for( n = 0; (max == 0) || (n < max); n++ )
+    {
+        r = MSI_ViewFetch( view, &rec );
+        if( r != ERROR_SUCCESS )
+            break;
+        r = func( rec, param );
+        msiobj_release( &rec->hdr );
+        if( r != ERROR_SUCCESS )
+            break;
+        n++;
+    }
+
+    MSI_ViewClose( view );
+
+    if( count )
+        *count = n;
+
+    return r;
+}
+
 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
               LPCWSTR szQuery, MSIHANDLE *phView)
 {
Index: dlls/msi/package.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/package.c,v
retrieving revision 1.34
diff -u -p -r1.34 package.c
--- dlls/msi/package.c	28 Jan 2005 12:39:57 -0000	1.34
+++ dlls/msi/package.c	1 Feb 2005 05:05:03 -0000
@@ -378,6 +378,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABA
         package->loaded_files = 0;
         package->ActionFormat = NULL;
         package->LastAction = NULL;
+        package->dialog = NULL;
 
         /* OK, here is where we do a slew of things to the database to 
          * prep for all that is to come as a package */
Index: dlls/msi/preview.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/preview.c,v
retrieving revision 1.2
diff -u -p -r1.2 preview.c
--- dlls/msi/preview.c	28 Jan 2005 12:39:57 -0000	1.2
+++ dlls/msi/preview.c	1 Feb 2005 05:05:03 -0000
@@ -90,7 +90,7 @@ static VOID preview_event_handler( MSIPA
 
 UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName )
 {
-    dialog_info *dialog = NULL;
+    msi_dialog *dialog = NULL;
     UINT r = ERROR_SUCCESS;
 
     if( preview->dialog )
@@ -101,7 +101,9 @@ UINT MSI_PreviewDialogW( MSIPREVIEW *pre
     {
         dialog = msi_dialog_create( preview->package, szDialogName,
                                     preview_event_handler );
-        if( !dialog )
+        if( dialog )
+            msi_dialog_do_preview( dialog );
+        else
             r = ERROR_FUNCTION_FAILED;
     }
     preview->dialog = dialog;


More information about the wine-patches mailing list