msi: Implement handling for the ErrorDialog and use it to change media

James Hawkins truiken at gmail.com
Thu Oct 26 04:29:01 CDT 2006


Hi,

This fixes bug 3236.  http://bugs.winehq.org/show_bug.cgi?id=3236

Changelog:
* Implement handling for the ErrorDialog and use it to change media.

 dlls/msi/dialog.c  |  112 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/msi/files.c   |   26 ++++++++++++
 dlls/msi/msipriv.h |    1
 3 files changed, 139 insertions(+), 0 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c
index 422f0c5..e1e7ac7 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -3449,3 +3449,115 @@ void msi_dialog_unregister_class( void )
     UnregisterClassW( szMsiHiddenWindow, NULL );
     uiThreadId = 0;
 }
+
+static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event,
+                                 LPCWSTR argument, msi_dialog* dialog)
+{
+    static const WCHAR end_dialog[] = {'E','n','d','D','i','a','l','o','g',0};
+    static const WCHAR error_abort[] = {'E','r','r','o','r','A','b','o','r','t',0};
+    static const WCHAR error_cancel[] = {'E','r','r','o','r','C','a','n','c','e','l',0};
+    static const WCHAR error_no[] = {'E','r','r','o','r','N','o',0};
+    static const WCHAR result_prop[] = {
+        'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
+    };
+
+    if ( lstrcmpW( event, end_dialog ) )
+        return ERROR_SUCCESS;
+
+    if ( !lstrcmpW( argument, error_abort ) || !lstrcmpW( argument, error_cancel ) ||
+         !lstrcmpW( argument, error_no ) )
+    {
+         MSI_SetPropertyW( package, result_prop, error_abort );
+    }
+
+    ControlEvent_CleanupSubscriptions(package);
+    msi_dialog_end_dialog( dialog );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT msi_error_dialog_set_error( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR error )
+{
+    static const WCHAR update[] = 
+        {'U','P','D','A','T','E',' ','`','C','o','n','t','r','o','l','`',' ',
+         'S','E','T',' ','`','E','r','r','o','r','T','e','x','t','`',' ','=',' ','\'','%','s','\'',' ',
+         'W','H','E','R','E', ' ','`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ',
+         'A','N','D',' ','`','C','o','n','t','r','o','l','`',' ','=',' ',
+         '\'','E','r','r','o','r','T','e','x','t','\'',0};
+    MSIRECORD * row;
+
+    row = MSI_QueryGetRecord( package->db, update, error, error_dialog );
+    if (!row)
+        return ERROR_FUNCTION_FAILED;
+
+    msiobj_release(&row->hdr);
+    return ERROR_SUCCESS;
+}
+
+UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR error )
+{
+    msi_dialog *dialog;
+    WCHAR result[MAX_PATH];
+    UINT r = ERROR_SUCCESS;
+    DWORD size = MAX_PATH;
+    int res;
+
+    static const WCHAR pn_prop[] = {'P','r','o','d','u','c','t','N','a','m','e',0};
+    static const WCHAR title_fmt[] = {'%','s',' ','W','a','r','n','i','n','g',0};
+    static const WCHAR error_abort[] = {'E','r','r','o','r','A','b','o','r','t',0};
+    static const WCHAR result_prop[] = {
+        'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
+    };
+
+    if ( !error_dialog )
+    {
+        LPWSTR product_name = msi_dup_property( package, pn_prop );
+        LPWSTR title;
+        DWORD size;
+
+        size = lstrlenW( title_fmt ) + lstrlenW( product_name ) - 1;
+        title = msi_alloc( size * sizeof(WCHAR) );
+        if ( !title )
+        {
+            msi_free( product_name );
+            return ERROR_OUTOFMEMORY;
+        }
+
+        sprintfW( title, title_fmt, product_name );
+        res = MessageBoxW( NULL, error, title, MB_OKCANCEL | MB_ICONWARNING );
+
+        msi_free( product_name );
+        msi_free( title );
+
+        if ( res != IDOK )
+            return ERROR_FUNCTION_FAILED;
+
+        return ERROR_SUCCESS;
+    }
+
+    r = msi_error_dialog_set_error( package, error_dialog, error );
+    if ( r != ERROR_SUCCESS )
+        return r;
+
+    dialog = msi_dialog_create( package, error_dialog, package->dialog,
+                                error_dialog_handler );
+    if ( !dialog )
+        return ERROR_FUNCTION_FAILED;
+
+    dialog->finished = FALSE;
+    r = msi_dialog_run_message_loop( dialog );
+    if ( r != ERROR_SUCCESS )
+        goto done;
+
+    r = MSI_GetPropertyW( package, result_prop, result, &size );
+    if ( r != ERROR_SUCCESS)
+        r = ERROR_SUCCESS;
+
+    if ( !lstrcmpW( result, error_abort ) )
+        r = ERROR_FUNCTION_FAILED;
+
+done:
+    msi_dialog_destroy( dialog );
+
+    return r;
+}
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index 99cc6b5..bfea3ea 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -425,6 +425,25 @@ static UINT msi_extract_remote_cabinet( 
     return !extract_cabinet_file(package, mi->source, mi->last_path);
 }
 
+static UINT msi_change_media( MSIPACKAGE *package, struct media_info *mi, LPCWSTR prompt )
+{
+    LPWSTR error, error_dialog;
+    UINT r = ERROR_SUCCESS;
+
+    static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0};
+
+    error = generate_error_string( package, 1302, 1, prompt );
+    error_dialog = msi_dup_property( package, error_prop );
+
+    while ( r == ERROR_SUCCESS && GetFileAttributesW( mi->source ) == INVALID_FILE_ATTRIBUTES )
+        r = msi_spawn_error_dialog( package, error_dialog, error );
+
+    msi_free( error );
+    msi_free( error_dialog );
+
+    return r;
+}
+
 static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
                                   MSIFILE *file )
 {
@@ -523,6 +542,12 @@ static UINT ready_media_for_file( MSIPAC
                 strcpyW(mi->last_path,mi->source);
                 strcatW(mi->source,cab);
 
+                if (GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
+                    rc = msi_change_media(package, mi, prompt);
+
+                if ( rc != ERROR_SUCCESS )
+                    goto done;
+
                 MsiSourceListSetInfoW(package->ProductCode, NULL,
                             MSIINSTALLCONTEXT_USERMANAGED,
                             MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
@@ -565,6 +590,7 @@ static UINT ready_media_for_file( MSIPAC
             MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, mi->count, volume,
             prompt);
 
+done:
     msiobj_release(&row->hdr);
 
     return rc;
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 5acdd25..97b9d18 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -680,6 +680,7 @@ extern UINT msi_dialog_reset( msi_dialog
 extern UINT msi_dialog_directorylist_up( msi_dialog *dialog );
 extern msi_dialog *msi_dialog_get_parent( msi_dialog *dialog );
 extern LPWSTR msi_dialog_get_name( msi_dialog *dialog );
+extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR );
 
 /* preview */
 extern MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE * );
-- 
1.4.2.4


More information about the wine-patches mailing list