Make the MSI icon control work.

This commit is contained in:
Mike McCormack 2005-06-23 16:43:38 +00:00 committed by Alexandre Julliard
parent 04598248af
commit 7e3918d53e
4 changed files with 174 additions and 3 deletions

View File

@ -4,7 +4,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = msi.dll MODULE = msi.dll
IMPORTLIB = libmsi.$(IMPLIBEXT) IMPORTLIB = libmsi.$(IMPLIBEXT)
IMPORTS = shell32 cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32 IMPORTS = shell32 shlwapi cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32
EXTRALIBS = -luuid $(LIBUNICODE) EXTRALIBS = -luuid $(LIBUNICODE)
C_SRCS = \ C_SRCS = \

View File

@ -54,6 +54,7 @@ struct msi_control_tag
LPWSTR property; LPWSTR property;
LPWSTR value; LPWSTR value;
IPicture *pic; IPicture *pic;
HICON hIcon;
WCHAR name[1]; WCHAR name[1];
}; };
@ -113,6 +114,7 @@ static const WCHAR szMaskedEdit[] = { 'M','a','s','k','e','d','E','d','i','t',0
static const WCHAR szPathEdit[] = { 'P','a','t','h','E','d','i','t',0 }; static const WCHAR szPathEdit[] = { 'P','a','t','h','E','d','i','t',0 };
static const WCHAR szRadioButtonGroup[] = { static const WCHAR szRadioButtonGroup[] = {
'R','a','d','i','o','B','u','t','t','o','n','G','r','o','u','p',0 }; 'R','a','d','i','o','B','u','t','t','o','n','G','r','o','u','p',0 };
static const WCHAR szIcon[] = { 'I','c','o','n',0 };
static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM ); static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM );
static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * ); static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * );
@ -296,6 +298,7 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
control->property = NULL; control->property = NULL;
control->value = NULL; control->value = NULL;
control->pic = NULL; control->pic = NULL;
control->hIcon = NULL;
x = MSI_RecordGetInteger( rec, 4 ); x = MSI_RecordGetInteger( rec, 4 );
y = MSI_RecordGetInteger( rec, 5 ); y = MSI_RecordGetInteger( rec, 5 );
@ -535,7 +538,7 @@ static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT msi_load_bitmap( MSIDATABASE *db, LPCWSTR name, IPicture **pic ) static MSIRECORD *msi_get_binary_record( MSIDATABASE *db, LPCWSTR name )
{ {
const static WCHAR query[] = { const static WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ', 's','e','l','e','c','t',' ','*',' ',
@ -543,11 +546,17 @@ static UINT msi_load_bitmap( MSIDATABASE *db, LPCWSTR name, IPicture **pic )
'w','h','e','r','e',' ', 'w','h','e','r','e',' ',
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0 '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0
}; };
return MSI_QueryGetRecord( db, query, name );
}
static UINT msi_load_bitmap( MSIDATABASE *db, LPCWSTR name, IPicture **pic )
{
MSIRECORD *rec = NULL; MSIRECORD *rec = NULL;
IStream *stm = NULL; IStream *stm = NULL;
UINT r; UINT r;
rec = MSI_QueryGetRecord( db, query, name ); rec = msi_get_binary_record( db, name );
if( !rec ) if( !rec )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
@ -587,6 +596,108 @@ static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static LPWSTR msi_create_tmp_path(void)
{
WCHAR tmp[MAX_PATH];
LPWSTR path = NULL;
static const WCHAR prefix[] = { 'm','s','i',0 };
DWORD len, r;
r = GetTempPathW( MAX_PATH, tmp );
if( !r )
return path;
len = lstrlenW( tmp ) + 20;
path = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
if( path )
{
r = GetTempFileNameW( tmp, prefix, 0, path );
if (!r)
{
HeapFree( GetProcessHeap(), 0, path );
path = NULL;
}
}
return path;
}
static UINT
msi_load_icon( MSIDATABASE *db, LPCWSTR name, DWORD attributes, HICON *picon )
{
UINT r = ERROR_FUNCTION_FAILED;
LPWSTR tmp;
MSIRECORD *rec;
HICON hicon = 0;
TRACE("loading %s\n", debugstr_w( name ) );
tmp = msi_create_tmp_path();
if( !tmp )
return r;
rec = msi_get_binary_record( db, name );
if( rec )
{
r = MSI_RecordStreamToFile( rec, 2, tmp );
if( r == ERROR_SUCCESS )
{
DWORD cx = 0, cy = 0, flags = LR_LOADFROMFILE | LR_DEFAULTSIZE;
if( attributes & msidbControlAttributesFixedSize )
{
flags &= ~LR_DEFAULTSIZE;
if( attributes & msidbControlAttributesIconSize16 )
{
cx += 16;
cy += 16;
}
if( attributes & msidbControlAttributesIconSize32 )
{
cx += 32;
cy += 32;
}
/* msidbControlAttributesIconSize48 handled by above logic */
}
hicon = LoadImageW( 0, tmp, IMAGE_ICON, cx, cy, flags );
if( hicon )
*picon = hicon;
else
ERR("failed to load icon from %s\n", debugstr_w( tmp ));
DeleteFileW( tmp );
}
msiobj_release( &rec->hdr );
}
HeapFree( GetProcessHeap(), 0, tmp );
return r;
}
static UINT msi_dialog_icon_control( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
DWORD attributes;
HICON hIcon = 0;
LPCWSTR text;
UINT r;
TRACE("\n");
control = msi_dialog_add_control( dialog, rec, szStatic,
SS_ICON | SS_CENTERIMAGE | WS_GROUP );
text = MSI_RecordGetString( rec, 10 );
attributes = MSI_RecordGetInteger( rec, 8 );
r = msi_load_icon( dialog->package->db, text, attributes, &hIcon );
if( r == ERROR_SUCCESS )
{
r = SendMessageW( control->hwnd, STM_SETICON, (WPARAM) hIcon, 0 );
control->hIcon = hIcon;
}
else
ERR("Failed to load bitmap %s\n", debugstr_w(text));
return ERROR_SUCCESS;
}
static UINT msi_dialog_combo_control( msi_dialog *dialog, MSIRECORD *rec ) static UINT msi_dialog_combo_control( msi_dialog *dialog, MSIRECORD *rec )
{ {
static const WCHAR szCombo[] = { 'C','O','M','B','O','B','O','X',0 }; static const WCHAR szCombo[] = { 'C','O','M','B','O','B','O','X',0 };
@ -982,6 +1093,7 @@ struct control_handler msi_dialog_handler[] =
{ szMaskedEdit, msi_dialog_maskedit_control }, { szMaskedEdit, msi_dialog_maskedit_control },
{ szPathEdit, msi_dialog_pathedit_control }, { szPathEdit, msi_dialog_pathedit_control },
{ szRadioButtonGroup, msi_dialog_radiogroup_control }, { szRadioButtonGroup, msi_dialog_radiogroup_control },
{ szIcon, msi_dialog_icon_control },
}; };
#define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0]) #define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0])
@ -1634,6 +1746,8 @@ void msi_dialog_destroy( msi_dialog *dialog )
HeapFree( GetProcessHeap(), 0, t->value ); HeapFree( GetProcessHeap(), 0, t->value );
if( t->pic ) if( t->pic )
IPicture_Release( t->pic ); IPicture_Release( t->pic );
if( t->hIcon )
DestroyIcon( t->hIcon );
HeapFree( GetProcessHeap(), 0, t ); HeapFree( GetProcessHeap(), 0, t );
} }

View File

@ -328,6 +328,7 @@ extern unsigned int MSI_RecordGetFieldCount( MSIRECORD *rec );
extern UINT MSI_RecordSetStreamW( MSIRECORD *, unsigned int, LPCWSTR ); extern UINT MSI_RecordSetStreamW( MSIRECORD *, unsigned int, LPCWSTR );
extern UINT MSI_RecordSetStreamA( MSIRECORD *, unsigned int, LPCSTR ); extern UINT MSI_RecordSetStreamA( MSIRECORD *, unsigned int, LPCSTR );
extern UINT MSI_RecordDataSize( MSIRECORD *, unsigned int ); extern UINT MSI_RecordDataSize( MSIRECORD *, unsigned int );
extern UINT MSI_RecordStreamToFile( MSIRECORD *, unsigned int, LPCWSTR );
/* stream internals */ /* stream internals */
extern UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm ); extern UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm );

View File

@ -34,6 +34,9 @@
#include "winnls.h" #include "winnls.h"
#include "ole2.h" #include "ole2.h"
#include "winreg.h"
#include "shlwapi.h"
#include "query.h" #include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); WINE_DEFAULT_DEBUG_CHANNEL(msi);
@ -774,3 +777,56 @@ UINT MSI_RecordGetIStream( MSIRECORD *rec, unsigned int iField, IStream **pstm)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT msi_dump_stream_to_file( IStream *stm, LPCWSTR name )
{
ULARGE_INTEGER size;
LARGE_INTEGER pos;
IStream *out;
DWORD stgm;
HRESULT r;
stgm = STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE;
r = SHCreateStreamOnFileW( name, stgm, &out );
if( FAILED( r ) )
return ERROR_FUNCTION_FAILED;
pos.QuadPart = 0;
r = IStream_Seek( stm, pos, STREAM_SEEK_END, &size );
if( FAILED( r ) )
goto end;
pos.QuadPart = 0;
r = IStream_Seek( stm, pos, STREAM_SEEK_SET, NULL );
if( FAILED( r ) )
goto end;
r = IStream_CopyTo( stm, out, size, NULL, NULL );
end:
IStream_Release( out );
if( FAILED( r ) )
return ERROR_FUNCTION_FAILED;
return ERROR_SUCCESS;
}
UINT MSI_RecordStreamToFile( MSIRECORD *rec, unsigned int iField, LPCWSTR name )
{
IStream *stm = NULL;
UINT r;
TRACE("%p %u %s\n", rec, iField, debugstr_w(name));
msiobj_lock( &rec->hdr );
r = MSI_RecordGetIStream( rec, iField, &stm );
if( r == ERROR_SUCCESS )
{
r = msi_dump_stream_to_file( stm, name );
IStream_Release( stm );
}
msiobj_unlock( &rec->hdr );
return r;
}