Make the MSI icon control work.
This commit is contained in:
parent
04598248af
commit
7e3918d53e
|
@ -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 = \
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue