2015-02-14 22:27:29 +00:00
/*
* icon . cpp
*
* This file is a part of NSIS .
*
2021-01-01 20:27:52 +00:00
* Copyright ( C ) 1999 - 2021 Nullsoft and Contributors
2015-02-14 22:27:29 +00:00
*
* Licensed under the zlib / libpng license ( the " License " ) ;
* you may not use this file except in compliance with the License .
*
* Licence details can be found in the file COPYING .
*
* This software is provided ' as - is ' , without any express or implied
* warranty .
*/
2010-03-24 17:22:56 +00:00
2007-10-03 13:31:56 +00:00
# include "Platform.h"
2007-10-03 17:37:56 +00:00
# include "icon.h"
2007-10-03 13:31:56 +00:00
# include "util.h"
# include "lang.h"
# include <stdio.h>
# include <stdexcept>
2007-10-03 17:37:56 +00:00
# include <vector>
# include <algorithm>
2007-10-03 13:31:56 +00:00
using namespace std ;
extern int g_display_errors ;
extern FILE * g_output ;
# define SIZEOF_RSRC_ICON_GROUP_ENTRY 14
2019-02-10 20:45:40 +00:00
enum { ICO_TYPE_ICON = 1 , ICO_TYPE_CURSOR = 2 } ;
static bool is_valid_header ( const void * headerdata )
{
assert ( sizeof ( IconGroupHeader ) = = 6 ) ;
IconGroupHeader * pGH = ( IconGroupHeader * ) headerdata ;
if ( pGH - > wReserved ! = FIX_ENDIAN_INT16 ( 0x0000 ) ) return false ;
WORD type = FIX_ENDIAN_INT16 ( pGH - > wType ) ;
if ( type ! = ICO_TYPE_ICON & & type ! = ICO_TYPE_CURSOR ) return false ;
return FIX_ENDIAN_INT16 ( pGH - > wCount ) ! = 0 ;
}
2007-10-03 13:31:56 +00:00
2021-09-18 20:24:41 +00:00
template < class S > static WORD read_icon_header ( S * f , IconGroupHeader & igh )
2007-10-03 13:31:56 +00:00
{
2021-09-18 20:24:41 +00:00
if ( ! freadall ( & igh , sizeof ( IconGroupHeader ) , f ) )
2013-03-19 02:11:37 +00:00
{
fclose ( f ) ;
2007-10-03 17:37:56 +00:00
throw runtime_error ( " unable to read header from file " ) ;
2013-03-19 02:11:37 +00:00
}
2007-10-03 13:31:56 +00:00
2019-02-10 20:45:40 +00:00
if ( ! is_valid_header ( & igh ) )
2013-03-19 02:11:37 +00:00
{
2021-09-18 20:24:41 +00:00
igh . wType = igh . wCount = 0 ;
2013-03-19 02:11:37 +00:00
fclose ( f ) ;
2007-10-03 13:31:56 +00:00
throw runtime_error ( " invalid icon file " ) ;
2013-03-19 02:11:37 +00:00
}
2007-10-03 13:31:56 +00:00
2019-02-10 20:45:40 +00:00
FIX_ENDIAN_INT16_INPLACE ( igh . wReserved ) ;
FIX_ENDIAN_INT16_INPLACE ( igh . wType ) ;
FIX_ENDIAN_INT16_INPLACE ( igh . wCount ) ;
2021-09-18 20:24:41 +00:00
return igh . wCount ;
2007-10-03 13:31:56 +00:00
}
2021-09-18 20:24:41 +00:00
void free_loaded_icon ( IconGroup & icon )
2007-10-03 13:31:56 +00:00
{
2007-10-03 17:37:56 +00:00
for ( IconGroup : : size_type i = 0 ; i < icon . size ( ) ; i + + )
delete [ ] icon [ i ] . data ;
2021-09-18 20:24:41 +00:00
icon . clear ( ) ;
2007-10-03 17:37:56 +00:00
}
2007-10-03 13:31:56 +00:00
2021-09-19 18:24:24 +00:00
IconGroup load_icon_res ( CResourceEditor * re , LPWSTR RT , WORD RN , LANGID RL )
2007-10-03 18:25:00 +00:00
{
IconGroupHeader * header ;
IconGroup result ;
2021-09-18 20:24:41 +00:00
LPBYTE group = re - > GetResource ( RT , RN , RL ) ;
2007-10-03 18:25:00 +00:00
if ( ! group )
throw runtime_error ( " can't find icon group " ) ;
header = ( IconGroupHeader * ) group ;
2021-09-18 20:24:41 +00:00
// Note: To handle cursors, use CResourceEditor::ExtractIcoCur
if ( MAKEINTRESOURCE ( ( size_t ) RT ) ! = RT_GROUP_ICON )
throw runtime_error ( " unsupported type " ) ;
2007-10-03 18:27:37 +00:00
for ( WORD i = 0 ; i < FIX_ENDIAN_INT16 ( header - > wCount ) ; i + + )
2007-10-03 18:25:00 +00:00
{
Icon icon ;
icon . index = i ;
RsrcIconGroupEntry * entry = ( RsrcIconGroupEntry * ) ( group
+ sizeof ( IconGroupHeader ) + SIZEOF_RSRC_ICON_GROUP_ENTRY * i ) ;
memcpy ( & icon . meta , & entry - > header , sizeof ( IconGroupEntry ) ) ;
WORD rsrc_id = FIX_ENDIAN_INT16 ( entry - > wRsrcId ) ;
2021-09-18 20:24:41 +00:00
icon . data = re - > GetResource ( RT_ICON , rsrc_id , RL ) ;
2007-10-03 18:25:00 +00:00
if ( ! icon . data )
{
free_loaded_icon ( result ) ;
throw runtime_error ( " can't find icon " ) ;
}
result . push_back ( icon ) ;
}
2013-12-08 14:34:38 +00:00
re - > FreeResource ( group ) ;
2007-10-03 18:25:00 +00:00
return result ;
}
2021-09-18 20:24:41 +00:00
IconGroup load_icon_res ( CResourceEditor * re , WORD id )
2007-10-03 17:37:56 +00:00
{
2021-09-18 20:24:41 +00:00
return load_icon_res ( re , RT_GROUP_ICON , id , NSIS_DEFAULT_LANG ) ;
}
2007-10-03 13:31:56 +00:00
2021-09-18 20:24:41 +00:00
template < class S > static IconGroup load_iconimages_from_stream ( const IconGroupHeader & iconHeader , S & file )
{
IconGroup result ;
2007-10-03 13:31:56 +00:00
2007-10-03 18:25:00 +00:00
for ( WORD i = 0 ; i < iconHeader . wCount ; i + + )
2007-10-03 17:37:56 +00:00
{
Icon icon ;
icon . index = i ;
icon . data = NULL ;
2007-10-03 13:31:56 +00:00
2021-09-18 20:24:41 +00:00
if ( ! freadall ( & icon . meta , sizeof ( IconGroupEntry ) , file ) )
2007-10-03 18:27:37 +00:00
{
free_loaded_icon ( result ) ;
2007-10-03 17:37:56 +00:00
throw runtime_error ( " unable to read entry from file " ) ;
2007-10-03 18:27:37 +00:00
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
DWORD size = FIX_ENDIAN_INT32 ( icon . meta . dwRawSize ) ;
if ( size > 1048576 ) // magic numbers are great
2007-10-03 18:27:37 +00:00
{
free_loaded_icon ( result ) ;
2007-10-03 17:37:56 +00:00
throw runtime_error ( " invalid icon file size " ) ;
2007-10-03 18:27:37 +00:00
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
DWORD iconOffset ;
2021-09-18 20:24:41 +00:00
if ( ! freadall ( & iconOffset , sizeof ( DWORD ) , file ) )
2007-10-03 18:27:37 +00:00
{
free_loaded_icon ( result ) ;
2007-10-03 17:37:56 +00:00
throw runtime_error ( " unable to read offset from file " ) ;
2007-10-03 18:27:37 +00:00
}
2007-10-03 13:31:56 +00:00
2007-12-15 15:28:38 +00:00
FIX_ENDIAN_INT32_INPLACE ( iconOffset ) ;
2007-10-03 13:31:56 +00:00
fpos_t pos ;
2007-10-03 17:37:56 +00:00
fgetpos ( file , & pos ) ;
if ( fseek ( file , iconOffset , SEEK_SET ) )
2007-10-03 18:27:37 +00:00
{
free_loaded_icon ( result ) ;
2007-10-03 13:31:56 +00:00
throw runtime_error ( " corrupted icon file, too small " ) ;
2007-10-03 18:27:37 +00:00
}
2007-10-03 17:37:56 +00:00
icon . data = new BYTE [ size ] ;
2021-09-18 20:24:41 +00:00
if ( ! freadall ( icon . data , size , file ) ) die :
2007-10-03 17:37:56 +00:00
{
free_loaded_icon ( result ) ;
throw runtime_error ( " unable to read icon from file " ) ;
2007-10-03 13:31:56 +00:00
}
2021-09-18 20:24:41 +00:00
if ( fsetpos ( file , & pos ) )
goto die ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
result . push_back ( icon ) ;
2007-10-03 13:31:56 +00:00
}
2007-10-03 17:37:56 +00:00
return result ;
}
2007-10-03 13:31:56 +00:00
2021-09-18 20:24:41 +00:00
template < class S > static IconGroup load_icon_from_stream ( S * file )
{
IconGroupHeader iconHeader ;
read_icon_header ( file , iconHeader ) ;
return load_iconimages_from_stream ( iconHeader , file ) ;
}
IconGroup load_icon_file ( const TCHAR * filename )
{
FILE * f = FOPEN ( filename , ( " rb " ) ) ;
if ( ! f )
throw runtime_error ( " can't open file " ) ;
MANAGE_WITH ( f , fclose ) ;
return load_icon_from_stream ( f ) ;
}
IconGroup load_icon ( const TCHAR * filename )
{
if ( CResourceEditor : : IsResProtocol ( filename ) ) // Try opening embedded resource
{
CResourceEditor : : EXTERNAL x ;
if ( CResourceEditor : : MapExternal ( filename , CResourceEditor : : TM_ICON , x ) )
{
CStdFileStreamOnMemory stream ( x . Data , x . cbData ) ;
IconGroup icon = load_icon_from_stream ( & stream ) ;
CResourceEditor : : FreeExternal ( x ) ;
return icon ;
}
}
return load_icon_file ( filename ) ;
}
2007-10-03 17:37:56 +00:00
typedef struct
{
unsigned index1 ;
unsigned index2 ;
DWORD size ;
2008-05-02 18:21:13 +00:00
unsigned size_index ;
2007-10-03 17:37:56 +00:00
} IconPair ;
2007-10-03 13:31:56 +00:00
2010-03-24 17:22:56 +00:00
2008-05-02 16:47:28 +00:00
typedef vector < IconPair > IconPairs ;
static bool compare_icon ( Icon a , Icon b )
2007-10-03 17:37:56 +00:00
{
return FIX_ENDIAN_INT32 ( a . meta . dwRawSize ) > FIX_ENDIAN_INT32 ( b . meta . dwRawSize ) ;
2007-10-03 13:31:56 +00:00
}
2007-10-03 17:37:56 +00:00
static IconGroup sort_icon ( IconGroup icon )
2007-10-03 13:31:56 +00:00
{
2007-10-03 17:37:56 +00:00
IconGroup sorted = icon ;
sort ( sorted . begin ( ) , sorted . end ( ) , compare_icon ) ;
return sorted ;
}
2008-05-02 18:21:13 +00:00
static bool compare_pairs_index1 ( IconPair a , IconPair b )
{
return a . index1 < b . index1 ;
}
static bool compare_pairs_index2 ( IconPair a , IconPair b )
{
return a . index2 < b . index2 ;
}
static IconPairs sort_pairs ( IconPairs pairs , bool first )
{
IconPairs sorted = pairs ;
sort ( sorted . begin ( ) , sorted . end ( ) , first ? compare_pairs_index1 : compare_pairs_index2 ) ;
return sorted ;
}
2008-05-02 16:47:28 +00:00
static IconPairs get_icon_order ( IconGroup icon1 , IconGroup icon2 )
2007-10-03 17:37:56 +00:00
{
IconGroup sorted_icons1 = sort_icon ( icon1 ) ;
IconGroup sorted_icons2 = sort_icon ( icon2 ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
IconGroup : : size_type shared_count = min ( sorted_icons1 . size ( ) , sorted_icons2 . size ( ) ) ;
IconGroup : : size_type total_count = max ( sorted_icons1 . size ( ) , sorted_icons2 . size ( ) ) ;
2007-10-03 13:31:56 +00:00
2008-05-02 16:47:28 +00:00
IconPairs result ;
2007-10-03 17:37:56 +00:00
IconGroup : : size_type i ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
for ( i = 0 ; i < shared_count ; i + + )
{
IconPair pair ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
pair . index1 = sorted_icons1 [ i ] . index ;
pair . index2 = sorted_icons2 [ i ] . index ;
pair . size = max (
FIX_ENDIAN_INT32 ( sorted_icons1 [ i ] . meta . dwRawSize ) ,
FIX_ENDIAN_INT32 ( sorted_icons2 [ i ] . meta . dwRawSize )
) ;
2015-09-17 14:30:07 +00:00
pair . size_index = truncate_cast ( unsigned int , i ) ;
2007-10-03 17:37:56 +00:00
result . push_back ( pair ) ;
2007-10-03 13:31:56 +00:00
}
2007-10-03 17:37:56 +00:00
for ( ; i < total_count ; i + + )
{
IconPair pair ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
if ( i < sorted_icons1 . size ( ) )
{
pair . index1 = sorted_icons1 [ i ] . index ;
pair . index2 = 0xffff ;
pair . size = FIX_ENDIAN_INT32 ( sorted_icons1 [ i ] . meta . dwRawSize ) ;
2015-09-17 14:30:07 +00:00
pair . size_index = truncate_cast ( unsigned int , i ) ;
2007-10-03 17:37:56 +00:00
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
if ( i < sorted_icons2 . size ( ) )
{
pair . index2 = sorted_icons2 [ i ] . index ;
pair . index1 = 0xffff ;
pair . size = FIX_ENDIAN_INT32 ( sorted_icons2 [ i ] . meta . dwRawSize ) ;
2015-09-17 14:30:07 +00:00
pair . size_index = truncate_cast ( unsigned int , i ) ;
2007-10-03 17:37:56 +00:00
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
result . push_back ( pair ) ;
2007-10-03 13:31:56 +00:00
}
2007-10-03 17:37:56 +00:00
return result ;
}
2007-10-03 13:31:56 +00:00
2013-12-08 14:34:38 +00:00
# define destroy_icon_group(p) ( delete [] (p) )
2008-05-02 16:47:28 +00:00
static LPBYTE generate_icon_group ( IconGroup icon , IconPairs order , bool first )
2007-10-03 17:37:56 +00:00
{
2019-07-31 19:59:55 +00:00
size_t groupsize =
2007-10-03 17:37:56 +00:00
sizeof ( IconGroupHeader ) // header
2019-07-31 19:59:55 +00:00
+ order . size ( ) * SIZEOF_RSRC_ICON_GROUP_ENTRY ; // entries
LPBYTE group = new BYTE [ groupsize ] ;
memset ( group , 0 , groupsize ) ; // Reproducible builds (bug #1230)
2007-10-03 17:37:56 +00:00
IconGroupHeader * header = ( IconGroupHeader * ) group ;
header - > wReserved = 0 ;
2019-02-10 20:45:40 +00:00
header - > wType = FIX_ENDIAN_INT16 ( ICO_TYPE_ICON ) ;
2014-02-08 00:13:52 +00:00
header - > wCount = FIX_ENDIAN_INT16 ( ( WORD ) icon . size ( ) ) ;
2007-10-03 17:37:56 +00:00
2008-05-02 18:21:13 +00:00
order = sort_pairs ( order , first ) ;
2007-10-03 17:37:56 +00:00
for ( IconGroup : : size_type i = 0 ; i < icon . size ( ) ; i + + )
{
RsrcIconGroupEntry * entry = ( RsrcIconGroupEntry * )
& group [ sizeof ( IconGroupHeader ) + SIZEOF_RSRC_ICON_GROUP_ENTRY * i ] ;
unsigned index = first ? order [ i ] . index1 : order [ i ] . index2 ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
memcpy ( & entry - > header , & icon [ index ] . meta , sizeof ( IconGroupEntry ) ) ;
2008-05-02 18:21:13 +00:00
entry - > wRsrcId = FIX_ENDIAN_INT16 ( order [ i ] . size_index + 1 ) ;
2007-10-03 17:37:56 +00:00
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
return group ;
2007-10-03 13:31:56 +00:00
}
2007-10-03 17:37:56 +00:00
// set_icon, must get an initialized resource editor
2019-02-10 20:45:40 +00:00
void set_main_icon ( CResourceEditor * re , WORD wIconId , IconGroup icon1 , IconGroup icon2 )
2007-10-03 17:37:56 +00:00
{
2008-05-02 16:47:28 +00:00
IconPairs order = get_icon_order ( icon1 , icon2 ) ;
2007-10-03 17:37:56 +00:00
// genreate group
LPBYTE group1 = generate_icon_group ( icon1 , order , true ) ;
// set group
size_t group_size = sizeof ( IconGroupHeader ) // header
+ order . size ( ) * SIZEOF_RSRC_ICON_GROUP_ENTRY ; // entries
2007-10-03 13:31:56 +00:00
2019-02-10 20:45:40 +00:00
re - > UpdateResource ( RT_GROUP_ICON , wIconId , NSIS_DEFAULT_LANG , group1 , ( DWORD ) group_size , CResourceEditor : : TM_RAW ) ; // Update the group entries but not the images
2013-12-08 14:34:38 +00:00
destroy_icon_group ( group1 ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// delete old icons
unsigned i = 1 ;
2019-02-10 20:45:40 +00:00
while ( i < = MAIN_ICON_LAST_IMAGE & & re - > UpdateResource ( RT_ICON , i + + , NSIS_DEFAULT_LANG , 0 , 0 ) ) ;
2007-10-03 17:37:56 +00:00
// set new icons
IconGroup : : size_type order_index ;
for ( order_index = 0 ; order_index < order . size ( ) ; order_index + + )
{
2010-04-12 16:00:17 +00:00
WORD size_index = order [ order_index ] . size_index ;
2008-05-02 18:21:13 +00:00
DWORD size = order [ order_index ] . size ;
LPBYTE data = new BYTE [ size ] ;
memset ( data , 0 , size ) ;
2007-10-03 17:37:56 +00:00
if ( order_index < icon1 . size ( ) )
{
Icon * icon = & icon1 [ order [ order_index ] . index1 ] ;
memcpy ( data , icon - > data , FIX_ENDIAN_INT32 ( icon - > meta . dwRawSize ) ) ;
2007-10-03 13:31:56 +00:00
}
2010-04-12 16:00:17 +00:00
re - > UpdateResource ( RT_ICON , size_index + 1 , NSIS_DEFAULT_LANG , data , size ) ;
2007-10-03 17:37:56 +00:00
delete [ ] data ;
}
2007-10-03 13:31:56 +00:00
}
2007-10-03 17:37:56 +00:00
# ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
// returns the data of the uninstaller icon that should replace the installer icon data
unsigned char * generate_uninstall_icon_data ( IconGroup icon1 , IconGroup icon2 , size_t & data_size )
{
IconGroup : : size_type i ;
2008-05-02 16:47:28 +00:00
IconPairs order = get_icon_order ( icon1 , icon2 ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// genreate group
LPBYTE group = generate_icon_group ( icon2 , order , false ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// calculate size
size_t group_size = sizeof ( IconGroupHeader ) // header
+ order . size ( ) * SIZEOF_RSRC_ICON_GROUP_ENTRY ; // entries
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
data_size = group_size // group header
+ sizeof ( DWORD ) * 2 // offset and size of group header
+ ( sizeof ( DWORD ) * 2 ) * icon2 . size ( ) // offset and size per entry
+ sizeof ( DWORD ) ; // terminator
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
for ( i = 0 ; i < icon2 . size ( ) ; i + + )
{
// add icon sizes
data_size + = FIX_ENDIAN_INT32 ( icon2 [ i ] . meta . dwRawSize ) ;
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// allocate memory
LPBYTE uninst_data = new BYTE [ data_size ] ;
LPBYTE seeker = uninst_data ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// fill group header
2014-02-08 00:13:52 +00:00
* ( LPDWORD ) seeker = FIX_ENDIAN_INT32 ( ( UINT32 ) group_size ) ;
2007-10-03 17:37:56 +00:00
seeker + = sizeof ( DWORD ) ;
* ( LPDWORD ) seeker = 0 ;
seeker + = sizeof ( DWORD ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
memcpy ( seeker , group , group_size ) ;
seeker + = group_size ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// fill entries
for ( i = 0 ; i < icon2 . size ( ) ; i + + )
{
Icon * icon = & icon2 [ order [ i ] . index2 ] ;
2020-07-18 23:18:18 +00:00
DWORD size = icon - > meta . dwRawSize ;
2007-10-03 13:31:56 +00:00
2020-07-18 23:18:18 +00:00
memcpy ( seeker , & size , sizeof ( size ) ) ;
seeker + = sizeof ( size ) ;
memset ( seeker , 0 , sizeof ( DWORD ) ) ;
2007-10-03 17:37:56 +00:00
seeker + = sizeof ( DWORD ) ;
memcpy ( seeker , icon - > data , size ) ;
2020-07-18 23:18:18 +00:00
seeker + = FIX_ENDIAN_INT32 ( size ) ;
2007-10-03 17:37:56 +00:00
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// add terminator
2020-07-18 23:18:18 +00:00
memset ( seeker , 0 , sizeof ( DWORD ) ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// done
2013-12-08 14:34:38 +00:00
destroy_icon_group ( group ) ;
2007-10-03 17:37:56 +00:00
return uninst_data ;
}
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
// Fill the array of icons for uninstall with their offsets
// Returns zero on failure
2019-02-10 20:45:40 +00:00
int generate_unicons_offsets ( LPBYTE exeHeader , size_t exeHeaderSize , LPBYTE uninstIconData , WORD wIconId )
{
2007-10-03 17:37:56 +00:00
try
{
DWORD offset ;
DWORD size ;
2007-10-03 13:31:56 +00:00
2014-02-08 00:13:52 +00:00
CResourceEditor re ( exeHeader , ( DWORD ) exeHeaderSize , false ) ;
2007-10-03 13:31:56 +00:00
2007-10-03 17:37:56 +00:00
LPBYTE seeker = uninstIconData ;
2007-10-03 13:31:56 +00:00
2010-04-12 16:00:17 +00:00
offset = re . GetResourceOffset ( RT_GROUP_ICON , wIconId , NSIS_DEFAULT_LANG ) ;
2007-10-03 13:31:56 +00:00
2008-11-07 22:02:38 +00:00
size = FIX_ENDIAN_INT32 ( * ( LPDWORD ) seeker ) ;
2007-10-03 13:31:56 +00:00
seeker + = sizeof ( DWORD ) ;
2007-10-03 17:52:56 +00:00
* ( LPDWORD ) seeker = FIX_ENDIAN_INT32 ( offset ) ;
2007-10-03 13:31:56 +00:00
seeker + = sizeof ( DWORD ) ;
2007-10-03 17:37:56 +00:00
2008-11-07 22:02:38 +00:00
seeker + = size ;
2007-10-03 17:37:56 +00:00
WORD icon_index = 1 ;
while ( * ( LPDWORD ) seeker )
{
2010-04-12 16:00:17 +00:00
offset = re . GetResourceOffset ( RT_ICON , icon_index , NSIS_DEFAULT_LANG ) ;
2007-10-03 17:37:56 +00:00
2008-02-18 23:24:02 +00:00
if ( offset > exeHeaderSize )
{
2010-04-12 16:00:17 +00:00
throw runtime_error ( " invalid icon offset (possibly compressed icon) " ) ;
2008-02-18 23:24:02 +00:00
}
2010-04-12 16:00:17 +00:00
DWORD real_size = re . GetResourceSize ( RT_ICON , icon_index , NSIS_DEFAULT_LANG ) ;
2008-05-02 18:21:13 +00:00
2008-11-07 22:02:38 +00:00
size = FIX_ENDIAN_INT32 ( * ( LPDWORD ) seeker ) ;
2007-10-03 17:37:56 +00:00
seeker + = sizeof ( DWORD ) ;
2008-05-02 18:21:13 +00:00
2009-02-06 14:00:02 +00:00
if ( real_size < size ) // uninst icon could be smaller, in case we don't have perfect matches
2008-05-02 18:21:13 +00:00
{
throw runtime_error ( " invalid icon size (possibly compressed icon) " ) ;
}
2007-10-03 17:52:56 +00:00
* ( LPDWORD ) seeker = FIX_ENDIAN_INT32 ( offset ) ;
2007-10-03 17:37:56 +00:00
seeker + = sizeof ( DWORD ) ;
2008-11-07 22:02:38 +00:00
seeker + = size ;
2007-10-03 17:37:56 +00:00
icon_index + + ;
}
}
catch ( const exception & e )
{
if ( g_display_errors )
2013-12-08 14:34:38 +00:00
PrintColorFmtMsg_ERR ( _T ( " \n Error generating uninstaller icon: % " ) NPRIs _T ( " -- failing! \n " ) , CtoTStrParam ( e . what ( ) ) ) ;
2007-10-03 17:37:56 +00:00
return 0 ;
2007-10-03 13:31:56 +00:00
}
return 1 ;
}
2007-10-03 18:03:10 +00:00
# endif // NSIS_CONFIG_UNINSTALL_SUPPORT