From ec7650908afcccd354b8e4450a31fda63d9cde45 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Fri, 26 Jul 2013 17:19:34 +0200 Subject: [PATCH] msi: Merge events.c into dialog.c. --- dlls/msi/Makefile.in | 1 - dlls/msi/dialog.c | 579 ++++++++++++++++++++++++++++++++++--------- dlls/msi/events.c | 449 --------------------------------- dlls/msi/msipriv.h | 17 +- dlls/msi/package.c | 10 +- 5 files changed, 469 insertions(+), 587 deletions(-) delete mode 100644 dlls/msi/events.c diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in index 140b5f1bf64..e7296d0c5e9 100644 --- a/dlls/msi/Makefile.in +++ b/dlls/msi/Makefile.in @@ -17,7 +17,6 @@ C_SRCS = \ dialog.c \ distinct.c \ drop.c \ - events.c \ files.c \ font.c \ format.c \ diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c index 80e2d68f745..943b6312dc8 100644 --- a/dlls/msi/dialog.c +++ b/dlls/msi/dialog.c @@ -2,6 +2,7 @@ * Implementation of the Microsoft Installer (msi.dll) * * Copyright 2005 Mike McCormack for CodeWeavers + * Copyright 2005 Aric Stewart for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -52,6 +53,7 @@ struct msi_control_tag; typedef struct msi_control_tag msi_control; typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM ); typedef void (*msi_update)( msi_dialog *, msi_control * ); +typedef UINT (*control_event_handler)( msi_dialog *, const WCHAR *, const WCHAR * ); struct msi_control_tag { @@ -85,7 +87,7 @@ struct msi_dialog_tag { MSIPACKAGE *package; msi_dialog *parent; - msi_dialog_event_handler event_handler; + control_event_handler event_handler; BOOL finished; INT scale; DWORD attributes; @@ -100,6 +102,15 @@ struct msi_dialog_tag WCHAR name[1]; }; +struct subscriber +{ + struct list entry; + msi_dialog *dialog; + WCHAR *event; + WCHAR *control; + WCHAR *attribute; +}; + typedef UINT (*msi_dialog_control_func)( msi_dialog *dialog, MSIRECORD *rec ); struct control_handler { @@ -247,16 +258,6 @@ static LPWSTR msi_dialog_dup_property( msi_dialog *dialog, LPCWSTR property, BOO return prop; } -msi_dialog *msi_dialog_get_parent( msi_dialog *dialog ) -{ - return dialog->parent; -} - -LPWSTR msi_dialog_get_name( msi_dialog *dialog ) -{ - return dialog->name; -} - /* * msi_dialog_get_style * @@ -405,9 +406,9 @@ static void msi_destroy_control( msi_control *t ) msi_free( t ); } -static msi_control *msi_dialog_create_window( msi_dialog *dialog, - MSIRECORD *rec, DWORD exstyle, LPCWSTR szCls, LPCWSTR name, LPCWSTR text, - DWORD style, HWND parent ) +static msi_control *dialog_create_window( msi_dialog *dialog, MSIRECORD *rec, DWORD exstyle, + const WCHAR *szCls, const WCHAR *name, const WCHAR *text, + DWORD style, HWND parent ) { DWORD x, y, width, height; LPWSTR font = NULL, title_font = NULL; @@ -616,9 +617,8 @@ static MSIFEATURE *msi_seltree_get_selected_feature( msi_control *control ) return msi_seltree_feature_from_item( control->hwnd, info->selected ); } -/* called from the Control Event subscription code */ -void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, - LPCWSTR attribute, MSIRECORD *rec ) +static void dialog_handle_event( msi_dialog *dialog, const WCHAR *control, + const WCHAR *attribute, MSIRECORD *rec ) { msi_control* ctrl; LPCWSTR font_text, text = NULL; @@ -711,7 +711,31 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, } } -static void msi_dialog_map_events(msi_dialog* dialog, LPCWSTR control) +static void event_subscribe( msi_dialog *dialog, const WCHAR *event, const WCHAR *control, const WCHAR *attribute ) +{ + struct subscriber *sub; + + TRACE("event %s control %s attribute %s\n", debugstr_w(event), debugstr_w(control), debugstr_w(attribute)); + + LIST_FOR_EACH_ENTRY( sub, &dialog->package->subscriptions, struct subscriber, entry ) + { + if (!strcmpiW( sub->event, event ) && + !strcmpiW( sub->control, control ) && + !strcmpiW( sub->attribute, attribute )) + { + TRACE("already subscribed\n"); + return; + }; + } + if (!(sub = msi_alloc( sizeof(*sub) ))) return; + sub->dialog = dialog; + sub->event = strdupW( event ); + sub->control = strdupW( control ); + sub->attribute = strdupW( attribute ); + list_add_tail( &dialog->package->subscriptions, &sub->entry ); +} + +static void dialog_map_events( msi_dialog *dialog, const WCHAR *control ) { static const WCHAR Query[] = { 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', @@ -730,7 +754,7 @@ static void msi_dialog_map_events(msi_dialog* dialog, LPCWSTR control) event = MSI_RecordGetString( row, 3 ); attribute = MSI_RecordGetString( row, 4 ); - ControlEvent_SubscribeToEvent( dialog->package, dialog, event, control, attribute ); + event_subscribe( dialog, event, control, attribute ); msiobj_release( &row->hdr ); } @@ -756,10 +780,9 @@ static msi_control *msi_dialog_add_control( msi_dialog *dialog, if( attributes & msidbControlAttributesSunken ) exstyle |= WS_EX_CLIENTEDGE; - msi_dialog_map_events(dialog, name); + dialog_map_events( dialog, name ); - return msi_dialog_create_window( dialog, rec, exstyle, szCls, name, - text, style, dialog->hwnd ); + return dialog_create_window( dialog, rec, exstyle, szCls, name, text, style, dialog->hwnd ); } struct msi_text_info @@ -854,9 +877,7 @@ static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec ) (LONG_PTR)MSIText_WndProc ); SetPropW( control->hwnd, szButtonData, info ); - ControlEvent_SubscribeToEvent( dialog->package, dialog, - szSelectionPath, control_name, szSelectionPath ); - + event_subscribe( dialog, szSelectionPath, control_name, szSelectionPath ); return ERROR_SUCCESS; } @@ -914,7 +935,7 @@ static UINT msi_dialog_send_event( msi_dialog *dialog, LPCWSTR event, LPCWSTR ar deformat_string( dialog->package, event, &event_fmt ); deformat_string( dialog->package, arg, &arg_fmt ); - dialog->event_handler( dialog->package, event_fmt, arg_fmt, dialog ); + dialog->event_handler( dialog, event_fmt, arg_fmt ); msi_free( event_fmt ); msi_free( arg_fmt ); @@ -1135,7 +1156,7 @@ static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec ) if( attributes & msidbControlAttributesSunken ) exstyle |= WS_EX_CLIENTEDGE; - msi_dialog_map_events(dialog, name); + dialog_map_events( dialog, name ); control = msi_alloc( FIELD_OFFSET(msi_control, name[strlenW( name ) + 1] )); if (!control) @@ -2070,8 +2091,7 @@ static UINT msi_dialog_progress_bar( msi_dialog *dialog, MSIRECORD *rec ) if( !control ) return ERROR_FUNCTION_FAILED; - ControlEvent_SubscribeToEvent( dialog->package, dialog, - szSetProgress, control->name, szProgress ); + event_subscribe( dialog, szSetProgress, control->name, szProgress ); return ERROR_SUCCESS; } @@ -2232,8 +2252,8 @@ static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param ) if( ~attributes & msidbControlAttributesEnabled ) style |= WS_DISABLED; - control = msi_dialog_create_window( dialog, rec, 0, szButton, name, text, - style, group->parent->hwnd ); + control = dialog_create_window( dialog, rec, 0, szButton, name, text, style, + group->parent->hwnd ); if (!control) return ERROR_FUNCTION_FAILED; control->handler = msi_dialog_radiogroup_handler; @@ -2616,7 +2636,7 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog, rec = MSI_CreateRecord( 1 ); MSI_RecordSetStringW( rec, 1, MSI_RecordGetString( row, 4 ) ); - ControlEvent_FireSubscribedEvent( dialog->package, szSelectionDescription, rec ); + msi_event_fire( dialog->package, szSelectionDescription, rec ); dir = MSI_RecordGetString( row, 7 ); if (dir) @@ -2632,7 +2652,7 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog, else MSI_RecordSetStringW( rec, 1, NULL ); - ControlEvent_FireSubscribedEvent( dialog->package, szSelectionPath, rec ); + msi_event_fire( dialog->package, szSelectionPath, rec ); done: msiobj_release(&row->hdr); @@ -2676,8 +2696,7 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec ) (LONG_PTR)MSISelectionTree_WndProc ); SetPropW( control->hwnd, szButtonData, info ); - ControlEvent_SubscribeToEvent( dialog->package, dialog, - szSelectionPath, control_name, szProperty ); + event_subscribe( dialog, szSelectionPath, control_name, szProperty ); /* initialize it */ msi_seltree_create_imagelist( control->hwnd ); @@ -3693,7 +3712,7 @@ static LRESULT msi_dialog_onnotify( msi_dialog *dialog, LPARAM param ) return 0; } -static void msi_dialog_setfocus( msi_dialog *dialog ) +static void dialog_setfocus( msi_dialog *dialog ) { HWND hwnd = dialog->hWndFocus; @@ -3727,11 +3746,11 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg, if( LOWORD(wParam) == WA_INACTIVE ) dialog->hWndFocus = GetFocus(); else - msi_dialog_setfocus( dialog ); + dialog_setfocus( dialog ); return 0; case WM_SETFOCUS: - msi_dialog_setfocus( dialog ); + dialog_setfocus( dialog ); return 0; /* bounce back to our subclassed static control */ @@ -3747,6 +3766,57 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg, return DefWindowProcW(hwnd, msg, wParam, lParam); } +static void process_pending_messages( HWND hdlg ) +{ + MSG msg; + + while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) + { + if (hdlg && IsDialogMessageW( hdlg, &msg )) continue; + TranslateMessage( &msg ); + DispatchMessageW( &msg ); + } +} + +static UINT dialog_run_message_loop( msi_dialog *dialog ) +{ + DWORD style; + HWND hwnd; + + if( uiThreadId != GetCurrentThreadId() ) + return SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_CREATE, 0, (LPARAM) dialog ); + + /* create the dialog window, don't show it yet */ + style = WS_OVERLAPPED; + if( dialog->attributes & msidbDialogAttributesVisible ) + style |= WS_VISIBLE; + + hwnd = CreateWindowW( szMsiDialogClass, dialog->name, style, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, NULL, dialog ); + if( !hwnd ) + { + ERR("Failed to create dialog %s\n", debugstr_w( dialog->name )); + return ERROR_FUNCTION_FAILED; + } + + ShowWindow( hwnd, SW_SHOW ); + /* UpdateWindow( hwnd ); - and causes the transparent static controls not to paint */ + + if( dialog->attributes & msidbDialogAttributesModal ) + { + while( !dialog->finished ) + { + MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLINPUT ); + process_pending_messages( dialog->hwnd ); + } + } + else + return ERROR_IO_PENDING; + + return ERROR_SUCCESS; +} + static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { @@ -3757,7 +3827,7 @@ static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg, switch (msg) { case WM_MSI_DIALOG_CREATE: - return msi_dialog_run_message_loop( dialog ); + return dialog_run_message_loop( dialog ); case WM_MSI_DIALOG_DESTROY: msi_dialog_destroy( dialog ); return 0; @@ -3765,7 +3835,7 @@ static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg, return DefWindowProcW( hwnd, msg, wParam, lParam ); } -static BOOL msi_dialog_register_class( void ) +static BOOL dialog_register_class( void ) { WNDCLASSW cls; @@ -3797,25 +3867,21 @@ static BOOL msi_dialog_register_class( void ) return TRUE; } -/* functions that interface to other modules within MSI */ - -msi_dialog *msi_dialog_create( MSIPACKAGE* package, - LPCWSTR szDialogName, msi_dialog *parent, - msi_dialog_event_handler event_handler ) +static msi_dialog *dialog_create( MSIPACKAGE *package, const WCHAR *name, msi_dialog *parent, + control_event_handler event_handler ) { MSIRECORD *rec = NULL; msi_dialog *dialog; - TRACE("%p %s\n", package, debugstr_w(szDialogName)); + TRACE("%s\n", debugstr_w(name)); - if (!hMsiHiddenWindow) - msi_dialog_register_class(); + if (!hMsiHiddenWindow) dialog_register_class(); /* allocate the structure for the dialog to use */ - dialog = msi_alloc_zero( FIELD_OFFSET( msi_dialog, name[strlenW( szDialogName ) + 1] )); + dialog = msi_alloc_zero( FIELD_OFFSET( msi_dialog, name[strlenW( name ) + 1] )); if( !dialog ) return NULL; - strcpyW( dialog->name, szDialogName ); + strcpyW( dialog->name, name ); dialog->parent = parent; msiobj_addref( &package->hdr ); dialog->package = package; @@ -3840,19 +3906,6 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package, return dialog; } -static void msi_process_pending_messages( HWND hdlg ) -{ - MSG msg; - - while( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ) ) - { - if( hdlg && IsDialogMessageW( hdlg, &msg )) - continue; - TranslateMessage( &msg ); - DispatchMessageW( &msg ); - } -} - void msi_dialog_end_dialog( msi_dialog *dialog ) { TRACE("%p\n", dialog); @@ -3883,7 +3936,7 @@ void msi_dialog_check_messages( HANDLE handle ) /* there's two choices for the UI thread */ while (1) { - msi_process_pending_messages( NULL ); + process_pending_messages( NULL ); if( !handle ) break; @@ -3898,51 +3951,34 @@ void msi_dialog_check_messages( HANDLE handle ) } } -UINT msi_dialog_run_message_loop( msi_dialog *dialog ) -{ - DWORD style; - HWND hwnd; - - if( uiThreadId != GetCurrentThreadId() ) - return SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_CREATE, 0, (LPARAM) dialog ); - - /* create the dialog window, don't show it yet */ - style = WS_OVERLAPPED; - if( dialog->attributes & msidbDialogAttributesVisible ) - style |= WS_VISIBLE; - - hwnd = CreateWindowW( szMsiDialogClass, dialog->name, style, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, NULL, dialog ); - if( !hwnd ) - { - ERR("Failed to create dialog %s\n", debugstr_w( dialog->name )); - return ERROR_FUNCTION_FAILED; - } - - ShowWindow( hwnd, SW_SHOW ); - /* UpdateWindow( hwnd ); - and causes the transparent static controls not to paint */ - - if( dialog->attributes & msidbDialogAttributesModal ) - { - while( !dialog->finished ) - { - MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLINPUT ); - msi_process_pending_messages( dialog->hwnd ); - } - } - else - return ERROR_IO_PENDING; - - return ERROR_SUCCESS; -} - -static void msi_dialog_do_preview( msi_dialog *dialog ) +static void dialog_do_preview( msi_dialog *dialog ) { TRACE("\n"); dialog->attributes |= msidbDialogAttributesVisible; dialog->attributes &= ~msidbDialogAttributesModal; - msi_dialog_run_message_loop( dialog ); + dialog_run_message_loop( dialog ); +} + +static void free_subscriber( struct subscriber *sub ) +{ + msi_free( sub->event ); + msi_free( sub->control ); + msi_free( sub->attribute ); + msi_free( sub ); +} + +static void event_cleanup_subscriptions( MSIPACKAGE *package, const WCHAR *dialog ) +{ + struct list *item, *next; + + LIST_FOR_EACH_SAFE( item, next, &package->subscriptions ) + { + struct subscriber *sub = LIST_ENTRY( item, struct subscriber, entry ); + + if (strcmpW( sub->dialog->name, dialog )) continue; + list_remove( &sub->entry ); + free_subscriber( sub ); + } } void msi_dialog_destroy( msi_dialog *dialog ) @@ -3962,7 +3998,7 @@ void msi_dialog_destroy( msi_dialog *dialog ) DestroyWindow( dialog->hwnd ); /* unsubscribe events */ - ControlEvent_CleanupDialogSubscriptions(dialog->package, dialog->name); + event_cleanup_subscriptions( dialog->package, dialog->name ); /* destroy the list of controls */ while( !list_empty( &dialog->controls ) ) @@ -3999,8 +4035,19 @@ void msi_dialog_unregister_class( void ) uiThreadId = 0; } -static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event, - LPCWSTR argument, msi_dialog* dialog) +void msi_event_cleanup_all_subscriptions( MSIPACKAGE *package ) +{ + struct list *item, *next; + + LIST_FOR_EACH_SAFE( item, next, &package->subscriptions ) + { + struct subscriber *sub = LIST_ENTRY( item, struct subscriber, entry ); + list_remove( &sub->entry ); + free_subscriber( sub ); + } +} + +static UINT error_dialog_handler( msi_dialog *dialog, const WCHAR *event, const WCHAR *argument ) { 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}; @@ -4016,10 +4063,10 @@ static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event, if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) || !strcmpW( argument, error_no ) ) { - msi_set_property( package->db, result_prop, error_abort, -1 ); + msi_set_property( dialog->package->db, result_prop, error_abort, -1 ); } - ControlEvent_CleanupSubscriptions(package); + msi_event_cleanup_all_subscriptions( dialog->package ); msi_dialog_end_dialog( dialog ); return ERROR_SUCCESS; @@ -4081,13 +4128,12 @@ UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR er if ( r != ERROR_SUCCESS ) return r; - dialog = msi_dialog_create( package, error_dialog, package->dialog, - error_dialog_handler ); + dialog = 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 ); + r = dialog_run_message_loop( dialog ); if ( r != ERROR_SUCCESS ) goto done; @@ -4166,8 +4212,7 @@ UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE *phPreview ) return r; } -static UINT preview_event_handler( MSIPACKAGE *package, LPCWSTR event, - LPCWSTR argument, msi_dialog *dialog ) +static UINT preview_event_handler( msi_dialog *dialog, const WCHAR *event, const WCHAR *argument ) { MESSAGE("Preview dialog event '%s' (arg='%s')\n", debugstr_w(event), debugstr_w(argument)); return ERROR_SUCCESS; @@ -4184,9 +4229,9 @@ static UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName ) /* an empty name means we should just destroy the current preview dialog */ if (szDialogName) { - dialog = msi_dialog_create( preview->package, szDialogName, NULL, preview_event_handler ); + dialog = dialog_create( preview->package, szDialogName, NULL, preview_event_handler ); if (dialog) - msi_dialog_do_preview( dialog ); + dialog_do_preview( dialog ); else r = ERROR_FUNCTION_FAILED; } @@ -4239,3 +4284,303 @@ UINT WINAPI MsiPreviewBillboardA( MSIHANDLE hPreview, LPCSTR szControlName, LPCS FIXME("%d %s %s\n", hPreview, debugstr_a(szControlName), debugstr_a(szBillboard)); return ERROR_CALL_NOT_IMPLEMENTED; } + +typedef UINT (*event_handler)( msi_dialog *, const WCHAR * ); + +struct control_event +{ + const WCHAR *event; + event_handler handler; +}; + +static UINT dialog_event_handler( msi_dialog *, const WCHAR *, const WCHAR * ); + +/* create a dialog box and run it if it's modal */ +static UINT event_do_dialog( MSIPACKAGE *package, const WCHAR *name, msi_dialog *parent, BOOL destroy_modeless ) +{ + msi_dialog *dialog; + UINT r; + + /* create a new dialog */ + dialog = dialog_create( package, name, parent, dialog_event_handler ); + if (dialog) + { + /* kill the current modeless dialog */ + if (destroy_modeless && package->dialog) + { + msi_dialog_destroy( package->dialog ); + package->dialog = NULL; + } + + /* modeless dialogs return an error message */ + r = dialog_run_message_loop( dialog ); + if (r == ERROR_SUCCESS) + msi_dialog_destroy( dialog ); + else + package->dialog = dialog; + } + else r = ERROR_FUNCTION_FAILED; + return r; +} + +/* end a modal dialog box */ +static UINT event_end_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + static const WCHAR exitW[] = {'E','x','i','t',0}; + static const WCHAR retryW[] = {'R','e','t','r','y',0}; + static const WCHAR ignoreW[] = {'I','g','n','o','r','e',0}; + static const WCHAR returnW[] = {'R','e','t','u','r','n',0}; + + if (!strcmpW( argument, exitW )) + dialog->package->CurrentInstallState = ERROR_INSTALL_USEREXIT; + else if (!strcmpW( argument, retryW )) + dialog->package->CurrentInstallState = ERROR_INSTALL_SUSPEND; + else if (!strcmpW( argument, ignoreW )) + dialog->package->CurrentInstallState = ERROR_SUCCESS; + else if (!strcmpW( argument, returnW )) + { + msi_dialog *parent = dialog->parent; + msi_free( dialog->package->next_dialog ); + dialog->package->next_dialog = (parent) ? strdupW( parent->name ) : NULL; + dialog->package->CurrentInstallState = ERROR_SUCCESS; + } + else + { + ERR("Unknown argument string %s\n", debugstr_w(argument)); + dialog->package->CurrentInstallState = ERROR_FUNCTION_FAILED; + } + event_cleanup_subscriptions( dialog->package, dialog->name ); + msi_dialog_end_dialog( dialog ); + return ERROR_SUCCESS; +} + +/* transition from one modal dialog to another modal dialog */ +static UINT event_new_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + /* store the name of the next dialog, and signal this one to end */ + dialog->package->next_dialog = strdupW( argument ); + msi_event_cleanup_all_subscriptions( dialog->package ); + msi_dialog_end_dialog( dialog ); + return ERROR_SUCCESS; +} + +/* create a new child dialog of an existing modal dialog */ +static UINT event_spawn_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + /* don't destroy a modeless dialogs that might be our parent */ + event_do_dialog( dialog->package, argument, dialog, FALSE ); + if (dialog->package->CurrentInstallState != ERROR_SUCCESS) msi_dialog_end_dialog( dialog ); + return ERROR_SUCCESS; +} + +/* creates a dialog that remains up for a period of time based on a condition */ +static UINT event_spawn_wait_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + FIXME("doing nothing\n"); + return ERROR_SUCCESS; +} + +static UINT event_do_action( msi_dialog *dialog, const WCHAR *argument ) +{ + ACTION_PerformAction( dialog->package, argument, SCRIPT_NONE ); + return ERROR_SUCCESS; +} + +static UINT event_add_local( msi_dialog *dialog, const WCHAR *argument ) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) + { + if (feature->ActionRequest != INSTALLSTATE_LOCAL) + msi_set_property( dialog->package->db, szPreselected, szOne, -1 ); + MSI_SetFeatureStateW( dialog->package, feature->Feature, INSTALLSTATE_LOCAL ); + } + } + return ERROR_SUCCESS; +} + +static UINT event_remove( msi_dialog *dialog, const WCHAR *argument ) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) + { + if (feature->ActionRequest != INSTALLSTATE_ABSENT) + msi_set_property( dialog->package->db, szPreselected, szOne, -1 ); + MSI_SetFeatureStateW( dialog->package, feature->Feature, INSTALLSTATE_ABSENT ); + } + } + return ERROR_SUCCESS; +} + +static UINT event_add_source( msi_dialog *dialog, const WCHAR *argument ) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) + { + if (feature->ActionRequest != INSTALLSTATE_SOURCE) + msi_set_property( dialog->package->db, szPreselected, szOne, -1 ); + MSI_SetFeatureStateW( dialog->package, feature->Feature, INSTALLSTATE_SOURCE ); + } + } + return ERROR_SUCCESS; +} + +void msi_event_fire( MSIPACKAGE *package, const WCHAR *event, MSIRECORD *rec ) +{ + struct subscriber *sub; + + TRACE("firing event %s\n", debugstr_w(event)); + + LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) + { + if (strcmpiW( sub->event, event )) continue; + dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec ); + } +} + +static UINT event_set_target_path( msi_dialog *dialog, const WCHAR *argument ) +{ + WCHAR *path = msi_dup_property( dialog->package->db, argument ); + MSIRECORD *rec = MSI_CreateRecord( 1 ); + UINT r = ERROR_SUCCESS; + + MSI_RecordSetStringW( rec, 1, path ); + msi_event_fire( dialog->package, szSelectionPath, rec ); + if (path) + { + /* failure to set the path halts the executing of control events */ + r = MSI_SetTargetPathW( dialog->package, argument, path ); + msi_free( path ); + } + msi_free( &rec->hdr ); + return r; +} + +static UINT event_reset( msi_dialog *dialog, const WCHAR *argument ) +{ + msi_dialog_reset( dialog ); + return ERROR_SUCCESS; +} + +/* Return ERROR_SUCCESS if dialog is process and ERROR_FUNCTION_FAILED + * if the given parameter is not a dialog box + */ +UINT ACTION_DialogBox( MSIPACKAGE *package, const WCHAR *dialog ) +{ + UINT r; + + if (package->next_dialog) ERR("Already got next dialog... ignoring it\n"); + package->next_dialog = NULL; + + /* Dialogs are chained by filling in the next_dialog member + * of the package structure, then terminating the current dialog. + * The code below sees the next_dialog member set, and runs the + * next dialog. + * We fall out of the loop below if we come across a modeless + * dialog, as it returns ERROR_IO_PENDING when we try to run + * its message loop. + */ + r = event_do_dialog( package, dialog, NULL, TRUE ); + while (r == ERROR_SUCCESS && package->next_dialog) + { + WCHAR *name = package->next_dialog; + + package->next_dialog = NULL; + r = event_do_dialog( package, name, NULL, TRUE ); + msi_free( name ); + } + if (r == ERROR_IO_PENDING) r = ERROR_SUCCESS; + return r; +} + +static UINT event_set_install_level( msi_dialog *dialog, const WCHAR *argument ) +{ + int level = atolW( argument ); + + TRACE("setting install level to %d\n", level); + return MSI_SetInstallLevel( dialog->package, level ); +} + +static UINT event_directory_list_up( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_dialog_directorylist_up( dialog ); +} + +static UINT event_reinstall_mode( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_set_property( dialog->package->db, szReinstallMode, argument, -1 ); +} + +static UINT event_reinstall( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_set_property( dialog->package->db, szReinstall, argument, -1 ); +} + +static UINT event_validate_product_id( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_validate_product_id( dialog->package ); +} + +static const WCHAR end_dialogW[] = {'E','n','d','D','i','a','l','o','g',0}; +static const WCHAR new_dialogW[] = {'N','e','w','D','i','a','l','o','g',0}; +static const WCHAR spawn_dialogW[] = {'S','p','a','w','n','D','i','a','l','o','g',0}; +static const WCHAR spawn_wait_dialogW[] = {'S','p','a','w','n','W','a','i','t','D','i','a','l','o','g',0}; +static const WCHAR do_actionW[] = {'D','o','A','c','t','i','o','n',0}; +static const WCHAR add_localW[] = {'A','d','d','L','o','c','a','l',0}; +static const WCHAR removeW[] = {'R','e','m','o','v','e',0}; +static const WCHAR add_sourceW[] = {'A','d','d','S','o','u','r','c','e',0}; +static const WCHAR set_target_pathW[] = {'S','e','t','T','a','r','g','e','t','P','a','t','h',0}; +static const WCHAR resetW[] = {'R','e','s','e','t',0}; +static const WCHAR set_install_levelW[] = {'S','e','t','I','n','s','t','a','l','l','L','e','v','e','l',0}; +static const WCHAR directory_list_upW[] = {'D','i','r','e','c','t','o','r','y','L','i','s','t','U','p',0}; +static const WCHAR selection_browseW[] = {'S','e','l','e','c','t','i','o','n','B','r','o','w','s','e',0}; +static const WCHAR reinstall_modeW[] = {'R','e','i','n','s','t','a','l','l','M','o','d','e',0}; +static const WCHAR reinstallW[] = {'R','e','i','n','s','t','a','l','l',0}; +static const WCHAR validate_product_idW[] = {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0}; + +static const struct control_event control_events[] = +{ + { end_dialogW, event_end_dialog }, + { new_dialogW, event_new_dialog }, + { spawn_dialogW, event_spawn_dialog }, + { spawn_wait_dialogW, event_spawn_wait_dialog }, + { do_actionW, event_do_action }, + { add_localW, event_add_local }, + { removeW, event_remove }, + { add_sourceW, event_add_source }, + { set_target_pathW, event_set_target_path }, + { resetW, event_reset }, + { set_install_levelW, event_set_install_level }, + { directory_list_upW, event_directory_list_up }, + { selection_browseW, event_spawn_dialog }, + { reinstall_modeW, event_reinstall_mode }, + { reinstallW, event_reinstall }, + { validate_product_idW, event_validate_product_id }, + { NULL, NULL } +}; + +static UINT dialog_event_handler( msi_dialog *dialog, const WCHAR *event, const WCHAR *argument ) +{ + unsigned int i; + + TRACE("handling event %s\n", debugstr_w(event)); + + if (!event) return ERROR_SUCCESS; + + for (i = 0; control_events[i].event; i++) + { + if (!strcmpW( control_events[i].event, event )) + return control_events[i].handler( dialog, argument ); + } + FIXME("unhandled event %s arg(%s)\n", debugstr_w(event), debugstr_w(argument)); + return ERROR_SUCCESS; +} diff --git a/dlls/msi/events.c b/dlls/msi/events.c deleted file mode 100644 index 707a4a235fd..00000000000 --- a/dlls/msi/events.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2005 Aric Stewart for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" -#include "msi.h" -#include "msipriv.h" - -#include "wine/debug.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -typedef UINT (*EVENTHANDLER)(MSIPACKAGE*,LPCWSTR,msi_dialog *); - -struct control_events -{ - const WCHAR *event; - EVENTHANDLER handler; -}; - -struct subscriber { - struct list entry; - msi_dialog *dialog; - LPWSTR event; - LPWSTR control; - LPWSTR attribute; -}; - -static UINT ControlEvent_HandleControlEvent(MSIPACKAGE *, LPCWSTR, LPCWSTR, msi_dialog*); - -/* - * Create a dialog box and run it if it's modal - */ -static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, msi_dialog *parent, BOOL destroy_modeless ) -{ - msi_dialog *dialog; - UINT r; - - /* create a new dialog */ - dialog = msi_dialog_create( package, name, parent, - ControlEvent_HandleControlEvent ); - if( dialog ) - { - /* kill the current modeless dialog */ - if( destroy_modeless && package->dialog ) - { - msi_dialog_destroy( package->dialog ); - package->dialog = NULL; - } - - /* modeless dialogs return an error message */ - r = msi_dialog_run_message_loop( dialog ); - if( r == ERROR_SUCCESS ) - msi_dialog_destroy( dialog ); - else - package->dialog = dialog; - } - else - r = ERROR_FUNCTION_FAILED; - - return r; -} - - -/* - * End a modal dialog box - */ -static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - static const WCHAR szExit[] = {'E','x','i','t',0}; - static const WCHAR szRetry[] = {'R','e','t','r','y',0}; - static const WCHAR szIgnore[] = {'I','g','n','o','r','e',0}; - static const WCHAR szReturn[] = {'R','e','t','u','r','n',0}; - - if (!strcmpW( argument, szExit )) - package->CurrentInstallState = ERROR_INSTALL_USEREXIT; - else if (!strcmpW( argument, szRetry )) - package->CurrentInstallState = ERROR_INSTALL_SUSPEND; - else if (!strcmpW( argument, szIgnore )) - package->CurrentInstallState = ERROR_SUCCESS; - else if (!strcmpW( argument, szReturn )) - { - msi_dialog *parent = msi_dialog_get_parent(dialog); - msi_free(package->next_dialog); - package->next_dialog = (parent) ? strdupW(msi_dialog_get_name(parent)) : NULL; - package->CurrentInstallState = ERROR_SUCCESS; - } - else - { - ERR("Unknown argument string %s\n",debugstr_w(argument)); - package->CurrentInstallState = ERROR_FUNCTION_FAILED; - } - - ControlEvent_CleanupDialogSubscriptions(package, msi_dialog_get_name( dialog )); - msi_dialog_end_dialog( dialog ); - return ERROR_SUCCESS; -} - -/* - * transition from one modal dialog to another modal dialog - */ -static UINT ControlEvent_NewDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog *dialog) -{ - /* store the name of the next dialog, and signal this one to end */ - package->next_dialog = strdupW(argument); - ControlEvent_CleanupSubscriptions(package); - msi_dialog_end_dialog( dialog ); - return ERROR_SUCCESS; -} - -/* - * Create a new child dialog of an existing modal dialog - */ -static UINT ControlEvent_SpawnDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog *dialog) -{ - /* don't destroy a modeless dialogs that might be our parent */ - event_do_dialog( package, argument, dialog, FALSE ); - if( package->CurrentInstallState != ERROR_SUCCESS ) - msi_dialog_end_dialog( dialog ); - return ERROR_SUCCESS; -} - -/* - * Creates a dialog that remains up for a period of time - * based on a condition - */ -static UINT ControlEvent_SpawnWaitDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - FIXME("Doing Nothing\n"); - return ERROR_SUCCESS; -} - -static UINT ControlEvent_DoAction(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - ACTION_PerformAction(package, argument, SCRIPT_NONE); - return ERROR_SUCCESS; -} - -static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) - { - if (feature->ActionRequest != INSTALLSTATE_LOCAL) - msi_set_property( package->db, szPreselected, szOne, -1 ); - MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_LOCAL ); - } - } - return ERROR_SUCCESS; -} - -static UINT ControlEvent_Remove( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) - { - if (feature->ActionRequest != INSTALLSTATE_ABSENT) - msi_set_property( package->db, szPreselected, szOne, -1 ); - MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_ABSENT ); - } - } - return ERROR_SUCCESS; -} - -static UINT ControlEvent_AddSource( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) - { - if (feature->ActionRequest != INSTALLSTATE_SOURCE) - msi_set_property( package->db, szPreselected, szOne, -1 ); - MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_SOURCE ); - } - } - return ERROR_SUCCESS; -} - -static UINT ControlEvent_SetTargetPath(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - static const WCHAR szSelectionPath[] = {'S','e','l','e','c','t','i','o','n','P','a','t','h',0}; - LPWSTR path = msi_dup_property( package->db, argument ); - MSIRECORD *rec = MSI_CreateRecord( 1 ); - UINT r = ERROR_SUCCESS; - - MSI_RecordSetStringW( rec, 1, path ); - ControlEvent_FireSubscribedEvent( package, szSelectionPath, rec ); - if (path) - { - /* failure to set the path halts the executing of control events */ - r = MSI_SetTargetPathW(package, argument, path); - msi_free(path); - } - msi_free(&rec->hdr); - return r; -} - -static UINT ControlEvent_Reset(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - msi_dialog_reset(dialog); - return ERROR_SUCCESS; -} - -/* - * Subscribed events - */ -static void free_subscriber( struct subscriber *sub ) -{ - msi_free(sub->event); - msi_free(sub->control); - msi_free(sub->attribute); - msi_free(sub); -} - -VOID ControlEvent_SubscribeToEvent( MSIPACKAGE *package, msi_dialog *dialog, - LPCWSTR event, LPCWSTR control, LPCWSTR attribute ) -{ - struct subscriber *sub; - - TRACE("event %s control %s attribute %s\n", debugstr_w(event), debugstr_w(control), debugstr_w(attribute)); - - LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) - { - if (!strcmpiW( sub->event, event ) && - !strcmpiW( sub->control, control ) && - !strcmpiW( sub->attribute, attribute )) - { - TRACE("already subscribed\n"); - return; - }; - } - if (!(sub = msi_alloc( sizeof(*sub) ))) return; - sub->dialog = dialog; - sub->event = strdupW(event); - sub->control = strdupW(control); - sub->attribute = strdupW(attribute); - list_add_tail( &package->subscriptions, &sub->entry ); -} - -VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event, MSIRECORD *rec ) -{ - struct subscriber *sub; - - TRACE("Firing event %s\n", debugstr_w(event)); - - LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) - { - if (strcmpiW( sub->event, event )) continue; - msi_dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec ); - } -} - -VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog) -{ - struct list *i, *t; - struct subscriber *sub; - - LIST_FOR_EACH_SAFE( i, t, &package->subscriptions ) - { - sub = LIST_ENTRY( i, struct subscriber, entry ); - - if (strcmpW( msi_dialog_get_name( sub->dialog ), dialog )) - continue; - - list_remove( &sub->entry ); - free_subscriber( sub ); - } -} - -VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package) -{ - struct list *i, *t; - struct subscriber *sub; - - LIST_FOR_EACH_SAFE( i, t, &package->subscriptions ) - { - sub = LIST_ENTRY( i, struct subscriber, entry ); - - list_remove( &sub->entry ); - free_subscriber( sub ); - } -} - -/* - * ACTION_DialogBox() - * - * Return ERROR_SUCCESS if dialog is process and ERROR_FUNCTION_FAILED - * if the given parameter is not a dialog box - */ -UINT ACTION_DialogBox( MSIPACKAGE* package, LPCWSTR szDialogName ) -{ - UINT r = ERROR_SUCCESS; - - if( package->next_dialog ) - ERR("Already a next dialog... ignoring it\n"); - package->next_dialog = NULL; - - /* - * Dialogs are chained by filling in the next_dialog member - * of the package structure, then terminating the current dialog. - * The code below sees the next_dialog member set, and runs the - * next dialog. - * We fall out of the loop below if we come across a modeless - * dialog, as it returns ERROR_IO_PENDING when we try to run - * its message loop. - */ - r = event_do_dialog( package, szDialogName, NULL, TRUE ); - while( r == ERROR_SUCCESS && package->next_dialog ) - { - LPWSTR name = package->next_dialog; - - package->next_dialog = NULL; - r = event_do_dialog( package, name, NULL, TRUE ); - msi_free( name ); - } - - if( r == ERROR_IO_PENDING ) - r = ERROR_SUCCESS; - - return r; -} - -static UINT ControlEvent_SetInstallLevel(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - int iInstallLevel = atolW(argument); - - TRACE("Setting install level: %i\n", iInstallLevel); - - return MSI_SetInstallLevel( package, iInstallLevel ); -} - -static UINT ControlEvent_DirectoryListUp(MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog) -{ - return msi_dialog_directorylist_up( dialog ); -} - -static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog) -{ - return msi_set_property( package->db, szReinstallMode, argument, -1 ); -} - -static UINT ControlEvent_Reinstall( MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog ) -{ - return msi_set_property( package->db, szReinstall, argument, -1 ); -} - -static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog) -{ - return msi_validate_product_id( package ); -} - -static const WCHAR end_dialogW[] = {'E','n','d','D','i','a','l','o','g',0}; -static const WCHAR new_dialogW[] = {'N','e','w','D','i','a','l','o','g',0}; -static const WCHAR spawn_dialogW[] = {'S','p','a','w','n','D','i','a','l','o','g',0}; -static const WCHAR spawn_wait_dialogW[] = {'S','p','a','w','n','W','a','i','t','D','i','a','l','o','g',0}; -static const WCHAR do_actionW[] = {'D','o','A','c','t','i','o','n',0}; -static const WCHAR add_localW[] = {'A','d','d','L','o','c','a','l',0}; -static const WCHAR removeW[] = {'R','e','m','o','v','e',0}; -static const WCHAR add_sourceW[] = {'A','d','d','S','o','u','r','c','e',0}; -static const WCHAR set_target_pathW[] = {'S','e','t','T','a','r','g','e','t','P','a','t','h',0}; -static const WCHAR resetW[] = {'R','e','s','e','t',0}; -static const WCHAR set_install_levelW[] = {'S','e','t','I','n','s','t','a','l','l','L','e','v','e','l',0}; -static const WCHAR directory_list_upW[] = {'D','i','r','e','c','t','o','r','y','L','i','s','t','U','p',0}; -static const WCHAR selection_browseW[] = {'S','e','l','e','c','t','i','o','n','B','r','o','w','s','e',0}; -static const WCHAR reinstall_modeW[] = {'R','e','i','n','s','t','a','l','l','M','o','d','e',0}; -static const WCHAR reinstallW[] = {'R','e','i','n','s','t','a','l','l',0}; -static const WCHAR validate_product_idW[] = {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0}; - -static const struct control_events control_events[] = -{ - { end_dialogW, ControlEvent_EndDialog }, - { new_dialogW, ControlEvent_NewDialog }, - { spawn_dialogW, ControlEvent_SpawnDialog }, - { spawn_wait_dialogW, ControlEvent_SpawnWaitDialog }, - { do_actionW, ControlEvent_DoAction }, - { add_localW, ControlEvent_AddLocal }, - { removeW, ControlEvent_Remove }, - { add_sourceW, ControlEvent_AddSource }, - { set_target_pathW, ControlEvent_SetTargetPath }, - { resetW, ControlEvent_Reset }, - { set_install_levelW, ControlEvent_SetInstallLevel }, - { directory_list_upW, ControlEvent_DirectoryListUp }, - { selection_browseW, ControlEvent_SpawnDialog }, - { reinstall_modeW, ControlEvent_ReinstallMode }, - { reinstallW, ControlEvent_Reinstall }, - { validate_product_idW, ControlEvent_ValidateProductID }, - { NULL, NULL } -}; - -UINT ControlEvent_HandleControlEvent( MSIPACKAGE *package, LPCWSTR event, - LPCWSTR argument, msi_dialog *dialog ) -{ - unsigned int i; - - TRACE("handling control event %s\n", debugstr_w(event)); - - if (!event) return ERROR_SUCCESS; - - for (i = 0; control_events[i].event; i++) - { - if (!strcmpW( control_events[i].event, event )) - return control_events[i].handler( package, argument, dialog ); - } - FIXME("unhandled control event %s arg(%s)\n", debugstr_w(event), debugstr_w(argument)); - return ERROR_SUCCESS; -} diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 773e8c1bd58..c597fe63ef9 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -934,18 +934,9 @@ extern LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val ) DECLSPEC extern LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val ) DECLSPEC_HIDDEN; /* msi dialog interface */ -typedef UINT (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* ); -extern msi_dialog *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog*, msi_dialog_event_handler ) DECLSPEC_HIDDEN; -extern UINT msi_dialog_run_message_loop( msi_dialog* ) DECLSPEC_HIDDEN; -extern void msi_dialog_end_dialog( msi_dialog* ) DECLSPEC_HIDDEN; extern void msi_dialog_check_messages( HANDLE ) DECLSPEC_HIDDEN; extern void msi_dialog_destroy( msi_dialog* ) DECLSPEC_HIDDEN; extern void msi_dialog_unregister_class( void ) DECLSPEC_HIDDEN; -extern void msi_dialog_handle_event( msi_dialog*, LPCWSTR, LPCWSTR, MSIRECORD * ) DECLSPEC_HIDDEN; -extern UINT msi_dialog_reset( msi_dialog *dialog ) DECLSPEC_HIDDEN; -extern UINT msi_dialog_directorylist_up( msi_dialog *dialog ) DECLSPEC_HIDDEN; -extern msi_dialog *msi_dialog_get_parent( msi_dialog *dialog ) DECLSPEC_HIDDEN; -extern LPWSTR msi_dialog_get_name( msi_dialog *dialog ) DECLSPEC_HIDDEN; extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR ) DECLSPEC_HIDDEN; /* summary information */ @@ -1066,12 +1057,8 @@ extern BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data) D extern UINT msi_add_cabinet_stream(MSIPACKAGE *, UINT, IStorage *, const WCHAR *) DECLSPEC_HIDDEN; /* control event stuff */ -extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event, - MSIRECORD *data) DECLSPEC_HIDDEN; -extern VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog) DECLSPEC_HIDDEN; -extern VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package) DECLSPEC_HIDDEN; -extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialog, - LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN; +extern void msi_event_fire(MSIPACKAGE *, const WCHAR *, MSIRECORD *) DECLSPEC_HIDDEN; +extern void msi_event_cleanup_all_subscriptions( MSIPACKAGE * ) DECLSPEC_HIDDEN; /* OLE automation */ typedef enum tid_t { diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 74f19ac08a8..1c1dd9456df 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -341,7 +341,7 @@ static void free_package_structures( MSIPACKAGE *package ) remove_tracked_tempfiles(package); /* cleanup control event subscriptions */ - ControlEvent_CleanupSubscriptions( package ); + msi_event_cleanup_all_subscriptions( package ); } static void MSI_FreePackage( MSIOBJECTHDR *arg) @@ -1937,7 +1937,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC MSI_RecordSetStringW(uirow, 1, deformated); msi_free(deformated); - ControlEvent_FireSubscribedEvent(package, szActionData, uirow); + msi_event_fire( package, szActionData, uirow ); msiobj_release(&uirow->hdr); if (package->action_progress_increment) @@ -1945,7 +1945,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC uirow = MSI_CreateRecord(2); MSI_RecordSetInteger(uirow, 1, 2); MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); - ControlEvent_FireSubscribedEvent(package, szSetProgress, uirow); + msi_event_fire( package, szSetProgress, uirow ); msiobj_release(&uirow->hdr); } break; @@ -1956,13 +1956,13 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC MSI_RecordSetStringW(uirow, 1, deformated); msi_free(deformated); - ControlEvent_FireSubscribedEvent(package, szActionText, uirow); + msi_event_fire( package, szActionText, uirow ); msiobj_release(&uirow->hdr); break; case INSTALLMESSAGE_PROGRESS: - ControlEvent_FireSubscribedEvent(package, szSetProgress, record); + msi_event_fire( package, szSetProgress, record ); break; }