James Hawkins : msi:
Implement handling for the ErrorDialog and use it to change media.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Oct 27 05:49:24 CDT 2006
Module: wine
Branch: master
Commit: c6bfbde849b5ddf2217f30bbac31bc7e43043278
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c6bfbde849b5ddf2217f30bbac31bc7e43043278
Author: James Hawkins <truiken at gmail.com>
Date: Thu Oct 26 17:13:52 2006 -0700
msi: Implement handling for the ErrorDialog and use it to change media.
---
dlls/msi/dialog.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/msi/files.c | 30 +++++++++++++
dlls/msi/msipriv.h | 1 +
dlls/msi/tests/install.c | 2 +
4 files changed, 136 insertions(+), 0 deletions(-)
diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c
index 403e65f..407cb29 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -3448,3 +3448,106 @@ 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 )
+{
+ MSIRECORD * row;
+
+ static const WCHAR update[] =
+ {'U','P','D','A','T','E',' ','`','C','o','n','t','r','o','l','`',' ',
+ 'S','E','T',' ','`','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};
+
+ 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 );
+ WCHAR title[MAX_PATH];
+
+ sprintfW( title, title_fmt, product_name );
+ res = MessageBoxW( NULL, error, title, MB_OKCANCEL | MB_ICONWARNING );
+
+ msi_free( product_name );
+
+ if ( res == IDOK )
+ return ERROR_SUCCESS;
+ else
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ 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 6c5b288..7eec8a2 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -425,6 +425,29 @@ 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 szUILevel[] = {'U','I','L','e','v','e','l',0};
+ static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0};
+
+ if ( msi_get_property_int(package, szUILevel, 0) == INSTALLUILEVEL_NONE )
+ return ERROR_SUCCESS;
+
+ 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 )
{
@@ -528,6 +551,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,
@@ -570,6 +599,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 4745b9e..45bdeac 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 * );
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c
index aed5a78..760e81e 100644
--- a/dlls/msi/tests/install.c
+++ b/dlls/msi/tests/install.c
@@ -803,6 +803,8 @@ static void test_continuouscabs(void)
create_cc_test_files();
create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
+ MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+
r = MsiInstallProductA(msifile, NULL);
todo_wine
{
More information about the wine-cvs
mailing list