Add more dialog controls, do something when they're clicked on.
This commit is contained in:
parent
ac643d3137
commit
fd91013b46
|
@ -27,152 +27,202 @@
|
|||
#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 };
|
||||
|
||||
struct tag_dialog_info
|
||||
struct msi_control_tag;
|
||||
typedef struct msi_control_tag msi_control;
|
||||
typedef UINT (*msi_click_handler)( msi_dialog *, msi_control * );
|
||||
|
||||
struct msi_control_tag
|
||||
{
|
||||
MSIPACKAGE *package;
|
||||
msi_dialog_event_handler event_handler;
|
||||
INT scale;
|
||||
struct msi_control_tag *next;
|
||||
HWND hwnd;
|
||||
msi_click_handler click_handler;
|
||||
WCHAR name[1];
|
||||
};
|
||||
|
||||
typedef UINT (*msi_dialog_control_func)( dialog_info *dialog, MSIRECORD *rec );
|
||||
typedef struct msi_font_tag
|
||||
{
|
||||
struct msi_font_tag *next;
|
||||
HFONT hfont;
|
||||
WCHAR name[1];
|
||||
} msi_font;
|
||||
|
||||
struct msi_dialog_tag
|
||||
{
|
||||
MSIPACKAGE *package;
|
||||
msi_dialog_event_handler event_handler;
|
||||
BOOL finished;
|
||||
INT scale;
|
||||
DWORD attributes;
|
||||
HWND hwnd;
|
||||
msi_font *font_list;
|
||||
msi_control *control_list;
|
||||
WCHAR name[1];
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
if (!hwnd)
|
||||
ERR("Failed to create hwnd\n");
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return (dialog->scale * val + 5) / 10;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_button_control( dialog_info *dialog, MSIRECORD *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 )
|
||||
{
|
||||
const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
HWND hwnd;
|
||||
LPWSTR ret = NULL;
|
||||
LPCWSTR p = *text, q;
|
||||
DWORD len;
|
||||
|
||||
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( szButton, text, WS_CHILD | WS_VISIBLE |WS_GROUP,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
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;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_line_control( dialog_info *dialog, MSIRECORD *rec )
|
||||
static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
|
||||
{
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
|
||||
HWND hwnd;
|
||||
msi_dialog *dialog = param;
|
||||
msi_font *font;
|
||||
LPCWSTR face, name;
|
||||
LOGFONTW lf;
|
||||
INT style;
|
||||
HDC hdc;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
/* create a font and add it to the list */
|
||||
name = MSI_RecordGetString( rec, 1 );
|
||||
font = HeapAlloc( GetProcessHeap(), 0,
|
||||
sizeof *font + strlenW( name )*sizeof (WCHAR) );
|
||||
strcpyW( font->name, name );
|
||||
font->next = dialog->font_list;
|
||||
dialog->font_list = font;
|
||||
|
||||
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 );
|
||||
memset( &lf, 0, sizeof lf );
|
||||
face = 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, face, LF_FACESIZE );
|
||||
|
||||
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 |
|
||||
SS_ETCHEDHORZ |SS_SUNKEN,
|
||||
x, y, width, height, dialog->hwnd, NULL, NULL, NULL );
|
||||
if (!hwnd)
|
||||
ERR("Failed to create hwnd\n");
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static UINT msi_load_picture( MSIDATABASE *db, LPCWSTR name, HBITMAP *hbm )
|
||||
{
|
||||
IPicture *pic = NULL;
|
||||
IPersistFile *pf = NULL;
|
||||
IStream *stm = NULL;
|
||||
HRESULT r;
|
||||
|
||||
r = CoCreateObject( &CLSID_Picture, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IPicture, (LPVOID*)&pic );
|
||||
if (FAILED(r))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = IPicture_QueryInterface( pic, &IID_IPersistFile, (LPVOID*) &pf );
|
||||
if (SUCCEEDED(r) )
|
||||
/* adjust the height */
|
||||
hdc = GetDC( dialog->hwnd );
|
||||
if (hdc)
|
||||
{
|
||||
r = IPersistFile_Load( pf, stm );
|
||||
IPersistFile_Release( pf );
|
||||
lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
||||
ReleaseDC( dialog->hwnd, hdc );
|
||||
}
|
||||
|
||||
if (SUCCEEDED(r) )
|
||||
IPicture_get_Handle( pic, hbm );
|
||||
IPicture_Release( pic );
|
||||
font->hfont = CreateFontIndirectW( &lf );
|
||||
|
||||
TRACE("Adding font style %s\n", debugstr_w(font->name) );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static msi_font *msi_dialog_find_font( msi_dialog *dialog, LPCWSTR name )
|
||||
{
|
||||
msi_font *font;
|
||||
|
||||
for( font = dialog->font_list; font; font = font->next )
|
||||
if( !strcmpW( font->name, name ) ) /* FIXME: case sensitive? */
|
||||
break;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_set_font( msi_dialog *dialog, HWND hwnd, LPCWSTR name )
|
||||
{
|
||||
msi_font *font;
|
||||
|
||||
font = msi_dialog_find_font( dialog, name );
|
||||
if( font )
|
||||
SendMessageW( hwnd, WM_SETFONT, (WPARAM) font->hfont, TRUE );
|
||||
else
|
||||
ERR("No font entry for %s\n", debugstr_w(name));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_build_font_list( msi_dialog *dialog )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'S','E','L','E','C','T',' ','*',' ',
|
||||
'F','R','O','M',' ','`','T','e','x','t','S','t','y','l','e','`',' ',0
|
||||
};
|
||||
UINT r;
|
||||
MSIQUERY *view = NULL;
|
||||
|
||||
TRACE("dialog %p\n", dialog );
|
||||
|
||||
r = MSI_OpenQuery( dialog->package->db, &view, query );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
r = MSI_IterateRecords( view, NULL, msi_dialog_add_font, dialog );
|
||||
msiobj_release( &view->hdr );
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
static UINT msi_dialog_bitmap_control( dialog_info *dialog, MSIRECORD *rec )
|
||||
static msi_control *msi_dialog_add_control( msi_dialog *dialog,
|
||||
MSIRECORD *rec, LPCWSTR szCls, DWORD style )
|
||||
{
|
||||
DWORD x, y, width, height;
|
||||
LPCWSTR text;
|
||||
const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
|
||||
HWND hwnd;
|
||||
LPCWSTR text, name;
|
||||
LPWSTR font, title = NULL;
|
||||
msi_control *control = NULL;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
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;
|
||||
control->click_handler = NULL;
|
||||
|
||||
x = MSI_RecordGetInteger( rec, 4 );
|
||||
y = MSI_RecordGetInteger( rec, 5 );
|
||||
|
@ -180,17 +230,92 @@ static UINT msi_dialog_bitmap_control( dialog_info *dialog, MSIRECORD *rec )
|
|||
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( szStatic, text, WS_CHILD | WS_VISIBLE |WS_GROUP | WS_DISABLED |
|
||||
SS_BITMAP | SS_LEFT | SS_CENTERIMAGE,
|
||||
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 (!hwnd)
|
||||
ERR("Failed to create hwnd\n");
|
||||
if( font )
|
||||
{
|
||||
msi_dialog_set_font( dialog, 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_add_control( dialog, rec, szStatic, 0 );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_button_click( msi_dialog *dialog, msi_control *control );
|
||||
|
||||
static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||
{
|
||||
const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
|
||||
msi_control *control;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
control = msi_dialog_add_control( dialog, rec, szButton, 0 );
|
||||
control->click_handler = msi_dialog_button_click;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_checkbox_click( msi_dialog *dialog, msi_control *control );
|
||||
|
||||
static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||
{
|
||||
const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
|
||||
msi_control *control;
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
control = msi_dialog_add_control( dialog, rec, szButton,
|
||||
BS_CHECKBOX | BS_MULTILINE );
|
||||
control->click_handler = msi_dialog_checkbox_click;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||
{
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
msi_dialog_add_control( dialog, rec, szStatic, SS_ETCHEDHORZ | SS_SUNKEN );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||
{
|
||||
const static WCHAR szEdit[] = { 'E','D','I','T',0 };
|
||||
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
msi_dialog_add_control( dialog, rec, szEdit,
|
||||
ES_MULTILINE | WS_VSCROLL | ES_READONLY | ES_AUTOVSCROLL );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec )
|
||||
{
|
||||
TRACE("%p %p\n", dialog, rec);
|
||||
|
||||
msi_dialog_add_control( dialog, rec, szStatic,
|
||||
SS_BITMAP | SS_LEFT | SS_CENTERIMAGE );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -198,6 +323,9 @@ static const WCHAR szText[] = { 'T','e','x','t',0 };
|
|||
static const WCHAR szButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 };
|
||||
static const WCHAR szLine[] = { 'L','i','n','e',0 };
|
||||
static const WCHAR szBitmap[] = { 'B','i','t','m','a','p',0 };
|
||||
static const WCHAR szCheckBox[] = { 'C','h','e','c','k','B','o','x',0 };
|
||||
static const WCHAR szScrollableText[] = {
|
||||
'S','c','r','o','l','l','a','b','l','e','T','e','x','t',0 };
|
||||
|
||||
struct control_handler msi_dialog_handler[] =
|
||||
{
|
||||
|
@ -205,41 +333,15 @@ struct control_handler msi_dialog_handler[] =
|
|||
{ szButton, msi_dialog_button_control },
|
||||
{ szLine, msi_dialog_line_control },
|
||||
{ szBitmap, msi_dialog_bitmap_control },
|
||||
{ szCheckBox, msi_dialog_checkbox_control },
|
||||
{ szScrollableText, msi_dialog_scrolltext_control },
|
||||
};
|
||||
|
||||
#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 +358,7 @@ static UINT msi_dialog_create_controls( MSIRECORD *rec, LPVOID param )
|
|||
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 +369,102 @@ static UINT msi_dialog_fill_controls( dialog_info *dialog, LPCWSTR name )
|
|||
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 ) ) /* FIXME: case sensitive? */
|
||||
break;
|
||||
return control;
|
||||
}
|
||||
|
||||
static msi_control *msi_dialog_find_control_by_hwnd( msi_dialog *dialog, HWND hwnd )
|
||||
{
|
||||
msi_control *control;
|
||||
|
||||
for( control = dialog->control_list; control; control = control->next )
|
||||
if( hwnd == control->hwnd )
|
||||
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));
|
||||
|
||||
/* FIXME: case sensitive? */
|
||||
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 +486,7 @@ static INT msi_dialog_get_sans_serif_height( HWND hwnd )
|
|||
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 +510,13 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
|
|||
'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 +529,7 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
|
|||
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,42 +538,152 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
|
|||
|
||||
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 ) + 25; /* FIXME */
|
||||
|
||||
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_build_font_list( dialog );
|
||||
msi_dialog_fill_controls( dialog );
|
||||
msi_dialog_evaluate_control_conditions( dialog );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT msi_dialog_handle_click( dialog_info *dialog,
|
||||
DWORD id, HWND handle )
|
||||
static UINT msi_dialog_send_event( msi_dialog *dialog, LPCWSTR event, LPCWSTR arg )
|
||||
{
|
||||
TRACE("BN_CLICKED %08lx %p\n", id, handle);
|
||||
LPWSTR event_fmt = NULL, arg_fmt = NULL;
|
||||
|
||||
TRACE("Sending control event %s %s\n", debugstr_w(event), debugstr_w(arg));
|
||||
|
||||
deformat_string( dialog->package, event, &event_fmt );
|
||||
deformat_string( dialog->package, arg, &arg_fmt );
|
||||
|
||||
dialog->event_handler( dialog->package, event_fmt, arg_fmt, dialog );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, event_fmt );
|
||||
HeapFree( GetProcessHeap(), 0, arg_fmt );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_set_property( msi_dialog *dialog, LPCWSTR event, LPCWSTR arg )
|
||||
{
|
||||
static const WCHAR szNullArg[] = { '{','}',0 };
|
||||
LPWSTR p, prop, arg_fmt = NULL;
|
||||
UINT len;
|
||||
|
||||
len = strlenW(event);
|
||||
prop = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
|
||||
strcpyW( prop, &event[1] );
|
||||
p = strchrW( prop, ']' );
|
||||
if( p && p[1] == 0 )
|
||||
{
|
||||
*p = 0;
|
||||
if( strcmpW( szNullArg, arg ) )
|
||||
deformat_string( dialog->package, arg, &arg_fmt );
|
||||
MSI_SetPropertyW( dialog->package, prop, arg_fmt );
|
||||
}
|
||||
else
|
||||
ERR("Badly formatted property string - what happens?\n");
|
||||
HeapFree( GetProcessHeap(), 0, prop );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_control_event( MSIRECORD *rec, LPVOID param )
|
||||
{
|
||||
msi_dialog *dialog = param;
|
||||
LPCWSTR condition, event, arg;
|
||||
UINT r;
|
||||
|
||||
condition = MSI_RecordGetString( rec, 5 );
|
||||
r = MSI_EvaluateConditionW( dialog->package, condition );
|
||||
if( r )
|
||||
{
|
||||
event = MSI_RecordGetString( rec, 3 );
|
||||
arg = MSI_RecordGetString( rec, 4 );
|
||||
if( event[0] == '[' )
|
||||
msi_dialog_set_property( dialog, event, arg );
|
||||
else
|
||||
msi_dialog_send_event( dialog, event, arg );
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_button_click( msi_dialog *dialog, msi_control *control )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'S','E','L','E','C','T',' ','*',' ',
|
||||
'F','R','O','M',' ','C','o','n','t','r','o','l','E','v','e','n','t',' ',
|
||||
'W','H','E','R','E',' ',
|
||||
'`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ',
|
||||
'A','N','D',' ',
|
||||
'`','C','o','n','t','r','o','l','_','`',' ','=',' ','\'','%','s','\'',' ',
|
||||
'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','i','n','g','`',0
|
||||
};
|
||||
MSIQUERY *view = NULL;
|
||||
UINT r;
|
||||
|
||||
r = MSI_OpenQuery( dialog->package->db, &view, query,
|
||||
dialog->name, control->name );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
ERR("query failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog );
|
||||
msiobj_release( &view->hdr );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_dialog_checkbox_click( msi_dialog *dialog, msi_control *control )
|
||||
{
|
||||
FIXME("clicked checkbox %s\n", debugstr_w(control->name));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static LRESULT msi_dialog_handle_click( msi_dialog *dialog, HWND hwnd )
|
||||
{
|
||||
msi_control *control;
|
||||
|
||||
TRACE("BN_CLICKED %p %p\n", dialog, hwnd);
|
||||
|
||||
control = msi_dialog_find_control_by_hwnd( dialog, hwnd );
|
||||
if( control )
|
||||
{
|
||||
if( control->click_handler )
|
||||
control->click_handler( dialog, control );
|
||||
}
|
||||
else
|
||||
ERR("button click from nowhere\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -394,7 +692,7 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
|
|||
|
||||
case WM_COMMAND:
|
||||
if( HIWORD(wParam) == BN_CLICKED )
|
||||
return msi_dialog_handle_click( dialog, LOWORD(wParam), (HWND)lParam );
|
||||
return msi_dialog_handle_click( dialog, (HWND)lParam );
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
|
@ -406,10 +704,10 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
|
|||
|
||||
/* 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));
|
||||
|
@ -422,28 +720,97 @@ dialog_info *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
|
|||
strcpyW( dialog->name, szDialogName );
|
||||
dialog->package = package;
|
||||
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 )
|
||||
void msi_dialog_end_dialog( msi_dialog *dialog )
|
||||
{
|
||||
dialog->finished = 1;
|
||||
}
|
||||
|
||||
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( !dialog->finished && GetMessageW( &msg, 0, 0, 0 ) )
|
||||
{
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessageW( &msg );
|
||||
}
|
||||
}
|
||||
else
|
||||
return ERROR_IO_PENDING;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
void msi_dialog_check_messages( msi_dialog *dialog )
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
if( dialog->finished )
|
||||
return;
|
||||
|
||||
while( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ) )
|
||||
{
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessageW( &msg );
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
ShowWindow( dialog->hwnd, SW_HIDE );
|
||||
|
||||
/* destroy the list of controls */
|
||||
while( dialog->control_list )
|
||||
{
|
||||
msi_control *t = dialog->control_list;
|
||||
dialog->control_list = t->next;
|
||||
/* leave dialog->hwnd - destroying parent destroys child windows */
|
||||
HeapFree( GetProcessHeap(), 0, t );
|
||||
}
|
||||
|
||||
/* destroy the list of fonts */
|
||||
while( dialog->font_list )
|
||||
{
|
||||
msi_font *t = dialog->font_list;
|
||||
dialog->font_list = t->next;
|
||||
DeleteObject( t->hfont );
|
||||
HeapFree( GetProcessHeap(), 0, t );
|
||||
}
|
||||
|
||||
if( dialog->hwnd )
|
||||
DestroyWindow( dialog->hwnd );
|
||||
msiobj_release( &dialog->package->hdr );
|
||||
|
||||
dialog->package = NULL;
|
||||
HeapFree( GetProcessHeap(), 0, dialog );
|
||||
}
|
||||
|
|
|
@ -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,15 @@ typedef struct tagMSIPACKAGE
|
|||
LPWSTR PackagePath;
|
||||
|
||||
UINT CurrentInstallState;
|
||||
msi_dialog *dialog;
|
||||
LPWSTR next_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
|
||||
|
@ -299,6 +301,7 @@ extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname,
|
|||
/* action internals */
|
||||
extern UINT ACTION_DoTopLevelINSTALL( MSIPACKAGE *, LPCWSTR, LPCWSTR );
|
||||
extern void ACTION_free_package_structures( MSIPACKAGE* );
|
||||
extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR);
|
||||
|
||||
/* record internals */
|
||||
extern UINT MSI_RecordSetIStream( MSIRECORD *, unsigned int, IStream *);
|
||||
|
@ -322,6 +325,8 @@ extern void enum_stream_names( IStorage *stg );
|
|||
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 * );
|
||||
|
@ -359,9 +364,13 @@ extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
|||
extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
|
||||
|
||||
/* 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* );
|
||||
typedef VOID (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* );
|
||||
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_end_dialog( msi_dialog* );
|
||||
extern void msi_dialog_check_messages( 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 );
|
||||
|
||||
|
|
|
@ -182,6 +182,40 @@ UINT MSI_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,8 @@ void MSI_FreePackage( MSIOBJECTHDR *arg)
|
|||
{
|
||||
MSIPACKAGE *package= (MSIPACKAGE*) arg;
|
||||
|
||||
if( package->dialog )
|
||||
msi_dialog_destroy( package->dialog );
|
||||
ACTION_free_package_structures(package);
|
||||
|
||||
msiobj_release( &package->db->hdr );
|
||||
|
@ -378,6 +380,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
|
|||
package->loaded_files = 0;
|
||||
package->ActionFormat = NULL;
|
||||
package->LastAction = NULL;
|
||||
package->dialog = NULL;
|
||||
package->next_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 */
|
||||
|
|
|
@ -82,7 +82,7 @@ UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE* phPreview )
|
|||
}
|
||||
|
||||
static VOID preview_event_handler( MSIPACKAGE *package, LPCWSTR event,
|
||||
LPCWSTR argument, HWND dialog )
|
||||
LPCWSTR argument, msi_dialog *dialog )
|
||||
{
|
||||
MESSAGE("Preview dialog event '%s' (arg='%s')\n",
|
||||
debugstr_w( event ), debugstr_w( argument ));
|
||||
|
@ -90,7 +90,7 @@ static VOID preview_event_handler( MSIPACKAGE *package, LPCWSTR event,
|
|||
|
||||
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 *preview, LPCWSTR szDialogName )
|
|||
{
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue