2002-08-02 10:01:35 +00:00
/*
2006-10-28 19:45:02 +00:00
* ResourceEditor . h
*
* This file is a part of NSIS .
*
2021-01-01 20:27:52 +00:00
* Copyright ( C ) 2002 - 2021 Amir Szekely < kichik @ users . sourceforge . net >
2006-10-28 19:45:02 +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
*
* Reviewed for Unicode support by Jim Park - - 08 / 21 / 2007
2006-10-28 19:45:02 +00:00
*/
2002-08-02 10:01:35 +00:00
# if !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_)
# define AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_
2005-08-27 19:56:00 +00:00
2002-08-02 10:01:35 +00:00
# if _MSC_VER > 1000
# pragma once
# endif // _MSC_VER > 1000
2013-12-08 14:34:38 +00:00
# include "Platform.h"
# include "winchar.h"
2004-03-29 20:21:00 +00:00
# include <vector>
2013-12-08 14:34:38 +00:00
# include <cassert>
2005-08-27 19:56:00 +00:00
2019-02-10 20:45:40 +00:00
# define MAIN_ICON_LAST_IMAGE 99 // Main icon is special, we must reserve space for installer/uninstaller images
2004-03-29 20:21:00 +00:00
# ifdef _WIN32
2010-03-27 19:20:16 +00:00
# include <winnt.h>
2004-03-29 20:21:00 +00:00
# else
// all definitions for non Win32 platforms were taken from MinGW's free Win32 library
2004-08-13 20:01:12 +00:00
# define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
2004-03-29 20:21:00 +00:00
# define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
# pragma pack(4)
typedef struct _IMAGE_RESOURCE_DIRECTORY {
2004-08-13 20:01:12 +00:00
DWORD Characteristics ;
DWORD TimeDateStamp ;
WORD MajorVersion ;
WORD MinorVersion ;
WORD NumberOfNamedEntries ;
WORD NumberOfIdEntries ;
2004-03-29 20:21:00 +00:00
} IMAGE_RESOURCE_DIRECTORY , * PIMAGE_RESOURCE_DIRECTORY ;
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
2004-08-13 20:01:12 +00:00
DWORD OffsetToData ;
DWORD Size ;
DWORD CodePage ;
DWORD Reserved ;
2004-03-29 20:21:00 +00:00
} IMAGE_RESOURCE_DATA_ENTRY , * PIMAGE_RESOURCE_DATA_ENTRY ;
typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
2004-08-13 20:01:12 +00:00
WORD Length ;
CHAR NameString [ 1 ] ;
2004-03-29 20:21:00 +00:00
} IMAGE_RESOURCE_DIRECTORY_STRING , * PIMAGE_RESOURCE_DIRECTORY_STRING ;
typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
2004-08-13 20:01:12 +00:00
WORD Length ;
WCHAR NameString [ 1 ] ;
2004-03-29 20:21:00 +00:00
} IMAGE_RESOURCE_DIR_STRING_U , * PIMAGE_RESOURCE_DIR_STRING_U ;
2006-04-28 15:54:42 +00:00
# pragma pack()
2004-03-29 20:21:00 +00:00
# endif
# pragma pack(4)
typedef struct _MY_IMAGE_RESOURCE_DIRECTORY_ENTRY {
2004-08-13 20:01:12 +00:00
union {
struct {
2006-03-25 17:24:28 +00:00
# ifndef __BIG_ENDIAN__
2004-08-13 20:01:12 +00:00
DWORD NameOffset : 31 ;
DWORD NameIsString : 1 ;
2006-03-25 17:24:28 +00:00
# else
DWORD NameIsString : 1 ;
DWORD NameOffset : 31 ;
# endif
2004-08-13 20:01:12 +00:00
} NameString ;
DWORD Name ;
WORD Id ;
2007-07-23 18:43:07 +00:00
} UName ;
2004-08-13 20:01:12 +00:00
union {
DWORD OffsetToData ;
struct {
2006-03-25 17:24:28 +00:00
# ifndef __BIG_ENDIAN__
2004-08-13 20:01:12 +00:00
DWORD OffsetToDirectory : 31 ;
DWORD DataIsDirectory : 1 ;
2006-03-25 17:24:28 +00:00
# else
DWORD DataIsDirectory : 1 ;
DWORD OffsetToDirectory : 31 ;
# endif
2004-08-13 20:01:12 +00:00
} DirectoryOffset ;
2007-07-23 18:43:07 +00:00
} UOffset ;
2004-03-29 20:21:00 +00:00
} MY_IMAGE_RESOURCE_DIRECTORY_ENTRY , * PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY ;
# pragma pack()
# include <stdexcept>
2002-08-02 10:01:35 +00:00
2006-03-25 18:50:51 +00:00
// classes
2002-08-02 10:01:35 +00:00
class CResourceDirectory ;
class CResourceDirectoryEntry ;
class CResourceDataEntry ;
// Resource directory with entries
typedef struct RESOURCE_DIRECTORY {
2003-06-24 19:17:51 +00:00
IMAGE_RESOURCE_DIRECTORY Header ;
2004-03-29 20:21:00 +00:00
MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries [ 1 ] ;
2002-08-02 10:01:35 +00:00
} * PRESOURCE_DIRECTORY ;
2015-10-01 17:32:56 +00:00
# define GetCommonStructField(ref, s1, s2, fld) \
( ( & ( ( ref ) . fld ) ) [ ( 1 / ( 0 + ! ! ( FIELD_OFFSET ( s1 , fld ) = = FIELD_OFFSET ( s2 , fld ) & & sizeof ( ( ( s1 * ) 0 ) - > fld ) = = sizeof ( ( ( s2 * ) 0 ) - > fld ) ) ) ) - 1 ] ) // Try to fail at compile-time if the field is not at the same offset in both structs or does not have the same size
# define GetCommonMemberFromPEOptHdr(OptHdr, Member) \
( & GetCommonStructField ( OptHdr , IMAGE_OPTIONAL_HEADER32 , IMAGE_OPTIONAL_HEADER64 , Member ) )
# define GetMemberFromPEOptHdrEx(OptHdr, Member, Sixtyfour) \
( ( Sixtyfour ) ? \
& ( ( PIMAGE_OPTIONAL_HEADER64 ) & ( OptHdr ) ) - > Member : \
& ( ( PIMAGE_OPTIONAL_HEADER32 ) & ( OptHdr ) ) - > Member \
)
# define GetMemberFromPEOptHdr(OptHdr, Member) \
( GetMemberFromPEOptHdrEx ( OptHdr , Member , ( ( OptHdr ) . Magic = = IMAGE_NT_OPTIONAL_HDR64_MAGIC ) ) )
2002-08-02 10:01:35 +00:00
class CResourceEditor {
public :
2017-10-04 23:40:45 +00:00
CResourceEditor ( void * pbPE , int iSize , bool bKeepData = true ) ;
2003-06-24 19:17:51 +00:00
virtual ~ CResourceEditor ( ) ;
2019-02-10 20:45:40 +00:00
enum { ANYLANGID = 0xffff , INVALIDLANGID = 0xffff - 1 , ALLLANGID = 0xffff - 2 } ;
typedef enum { TM_RAW = 0 , TM_ICONFILE = 0x01 , TM_ICONRSRC = 0x02 , TM_ICON = ( TM_ICONFILE | TM_ICONRSRC ) , TM_AUTO = 0x04 } TYPEMANIPULATION ;
2002-08-02 10:01:35 +00:00
2017-10-03 20:48:29 +00:00
// On POSIX+Unicode GetResource(RT_VERSION,..) is not TCHAR nor WINWCHAR, it is WCHAR/UINT16 (MAKEINTRESOURCEW).
2013-12-08 14:34:38 +00:00
// If it passes IS_INTRESOURCE we must allow it.
// Use TCHAR* for real strings. If you need to pass in a WINWCHAR*, make GetResourceW public...
2019-02-10 20:45:40 +00:00
template < class T > bool UpdateResource ( const T * Type , WORD Name , LANGID Lang , BYTE * Data , DWORD Size , TYPEMANIPULATION Manip = TM_RAW )
{
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return false ; }
return UpdateResourceT ( ( const TCHAR * ) Type , Name , Lang , Data , Size , Manip ) ;
}
template < class T > bool UpdateResource ( const T * Type , WORD Name , LANGID Lang , FILE * Data , TYPEMANIPULATION Manip = TM_AUTO )
2013-12-08 14:34:38 +00:00
{
2017-10-03 20:48:29 +00:00
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return false ; }
2019-02-10 20:45:40 +00:00
return UpdateResourceT ( ( const TCHAR * ) Type , Name , Lang , Data , Manip ) ;
}
template < class T > bool DeleteResource ( const T * Type , WORD Name , LANGID Lang , TYPEMANIPULATION Manip = TM_RAW )
{
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return false ; }
return DeleteResourceT ( ( const TCHAR * ) Type , Name , Lang , Manip ) ;
2013-12-08 14:34:38 +00:00
}
template < class T > BYTE * GetResource ( const T * Type , WORD Name , LANGID Lang )
{
2017-10-03 20:48:29 +00:00
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return NULL ; }
2013-12-08 14:34:38 +00:00
return GetResourceT ( ( const TCHAR * ) Type , Name , Lang ) ;
}
template < class T > int GetResourceSize ( const T * Type , WORD Name , LANGID Lang )
{
2017-10-03 20:48:29 +00:00
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return - 1 ; }
2013-12-08 14:34:38 +00:00
return GetResourceSizeT ( ( const TCHAR * ) Type , Name , Lang ) ;
}
template < class T > DWORD GetResourceOffset ( const T * Type , WORD Name , LANGID Lang )
{
2017-10-03 20:48:29 +00:00
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return - 1 ; }
2013-12-08 14:34:38 +00:00
return GetResourceOffsetT ( ( const TCHAR * ) Type , Name , Lang ) ;
}
2019-02-10 20:45:40 +00:00
template < class T > bool ResourceExists ( const T * Type , WORD Name , LANGID Lang , LANGID * pFoundLanguage = 0 )
{
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return false ; }
return ResourceExistsT ( ( const TCHAR * ) Type , Name , Lang , pFoundLanguage ) ;
}
2017-10-03 20:48:29 +00:00
template < class T > BYTE * GetFirstResource ( const T * Type , size_t & cbData )
{
if ( sizeof ( T ) ! = sizeof ( TCHAR ) & & ! IS_INTRESOURCE ( Type ) ) { assert ( IS_INTRESOURCE ( Type ) ) ; return NULL ; }
return GetFirstResourceT ( ( const TCHAR * ) Type , cbData ) ;
}
2013-12-08 14:34:38 +00:00
2019-02-10 20:45:40 +00:00
bool UpdateResourceT ( const TCHAR * szType , WORD szName , LANGID wLanguage , BYTE * lpData , DWORD dwSize , TYPEMANIPULATION Manip = TM_RAW ) ;
bool UpdateResourceT ( const TCHAR * szType , WORD szName , LANGID wLanguage , FILE * Data , TYPEMANIPULATION Manip = TM_AUTO ) ;
bool DeleteResourceT ( const TCHAR * szType , WORD szName , LANGID wLanguage , TYPEMANIPULATION Manip = TM_RAW ) ;
2013-12-08 14:34:38 +00:00
BYTE * GetResourceT ( const TCHAR * szType , WORD szName , LANGID wLanguage ) ;
int GetResourceSizeT ( const TCHAR * szType , WORD szName , LANGID wLanguage ) ;
DWORD GetResourceOffsetT ( const TCHAR * szType , WORD szName , LANGID wLanguage ) ;
2019-02-10 20:45:40 +00:00
bool ResourceExistsT ( const TCHAR * szType , WORD szName , LANGID wLanguage , LANGID * pFoundLanguage = 0 ) ;
2017-10-03 20:48:29 +00:00
BYTE * GetFirstResourceT ( const TCHAR * szType , size_t & cbData ) ;
2004-02-05 12:19:02 +00:00
void FreeResource ( BYTE * pbResource ) ;
2002-08-02 10:01:35 +00:00
2010-03-24 17:22:56 +00:00
// The section name must be in ASCII.
2012-09-06 22:43:31 +00:00
bool SetPESectionVirtualSize ( const char * pszSectionName , DWORD newsize ) ;
2004-02-05 12:19:02 +00:00
DWORD Save ( BYTE * pbBuf , DWORD & dwSize ) ;
2002-08-02 10:01:35 +00:00
2006-03-25 18:50:51 +00:00
// utitlity functions
static PIMAGE_NT_HEADERS GetNTHeaders ( BYTE * pbPE ) ;
static PRESOURCE_DIRECTORY GetResourceDirectory (
BYTE * pbPE ,
DWORD dwSize ,
PIMAGE_NT_HEADERS ntHeaders ,
DWORD * pdwResSecVA = NULL ,
DWORD * pdwSectionIndex = NULL
) ;
2017-10-03 20:48:29 +00:00
2019-02-10 20:45:40 +00:00
static const TCHAR * ParseResourceTypeString ( const TCHAR * String ) ;
static const TCHAR * ParseResourceNameString ( const TCHAR * String ) ;
static LANGID ParseResourceLangString ( const TCHAR * String ) ;
static LANGID ParseResourceTypeNameLangString ( const TCHAR * * Type , const TCHAR * * Name , const TCHAR * Lang ) ;
static bool EditorSupportsStringNames ( ) { return false ; } // UpdateResource/GetResource do not support string names (yet)
2010-04-12 16:00:17 +00:00
private :
2019-02-10 20:45:40 +00:00
bool UpdateResourceW ( const WINWCHAR * szType , WINWCHAR * szName , LANGID wLanguage , BYTE * lpData , DWORD dwSize , TYPEMANIPULATION Manip = TM_RAW ) ;
2017-10-03 20:48:29 +00:00
BYTE * GetResourceW ( const WINWCHAR * szType , WINWCHAR * szName , LANGID wLanguage ) ;
int GetResourceSizeW ( const WINWCHAR * szType , WINWCHAR * szName , LANGID wLanguage ) ;
2013-12-08 14:34:38 +00:00
DWORD GetResourceOffsetW ( const WINWCHAR * szType , WINWCHAR * szName , LANGID wLanguage ) ;
2017-10-03 20:48:29 +00:00
BYTE * GetFirstResourceW ( const WINWCHAR * szType , size_t & cbData ) ;
CResourceDataEntry * FindResource ( const WINWCHAR * Type , const WINWCHAR * Name , LANGID Language ) ;
2019-02-10 20:45:40 +00:00
CResourceDirectoryEntry * FindResourceLanguageDirEntryW ( const WINWCHAR * Type , const WINWCHAR * Name , LANGID Language ) ;
CResourceDirectoryEntry * FindResourceLanguageDirEntryT ( const TCHAR * Type , const TCHAR * Name , LANGID Language ) ;
bool DeleteIconImages ( const CResourceDirectoryEntry & LangDir ) ;
bool DeleteIconImagesW ( const WINWCHAR * OwnerType , WINWCHAR * Name , LANGID LangId ) ;
bool AddExtraIconFromFile ( const WINWCHAR * Type , WINWCHAR * Name , LANGID LangId , BYTE * Data , DWORD Size ) ;
2017-10-03 20:48:29 +00:00
BYTE * DupData ( CResourceDataEntry * pDE ) ; // Free with FreeResource
CResourceDirectory * ScanDirectory ( PRESOURCE_DIRECTORY rdRoot , PRESOURCE_DIRECTORY rdToScan ) ;
void WriteRsrcSec ( BYTE * pbRsrcSec ) ;
void SetOffsets ( CResourceDirectory * resDir , ULONG_PTR newResDirAt ) ;
DWORD AdjustVA ( DWORD dwVirtualAddress , DWORD dwAdjustment ) ;
DWORD AlignVA ( DWORD dwVirtualAddress ) ;
2006-03-25 18:50:51 +00:00
2002-08-02 10:01:35 +00:00
private :
2003-06-24 19:17:51 +00:00
BYTE * m_pbPE ;
int m_iSize ;
2009-01-31 15:46:54 +00:00
bool m_bKeepData ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
PIMAGE_NT_HEADERS m_ntHeaders ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
DWORD m_dwResourceSectionIndex ;
DWORD m_dwResourceSectionVA ;
CResourceDirectory * m_cResDir ;
2002-08-02 10:01:35 +00:00
} ;
class CResourceDirectory {
public :
2003-06-24 19:17:51 +00:00
CResourceDirectory ( PIMAGE_RESOURCE_DIRECTORY prd ) ;
virtual ~ CResourceDirectory ( ) ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
IMAGE_RESOURCE_DIRECTORY GetInfo ( ) ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
CResourceDirectoryEntry * GetEntry ( unsigned int i ) ;
2013-12-08 14:34:38 +00:00
bool AddEntry ( CResourceDirectoryEntry * entry ) ;
2003-06-24 19:17:51 +00:00
void RemoveEntry ( int i ) ;
2014-02-08 00:13:52 +00:00
unsigned int CountEntries ( ) ;
2013-12-08 14:34:38 +00:00
int Find ( const WINWCHAR * szName ) ;
2003-06-24 19:17:51 +00:00
int Find ( WORD wId ) ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
DWORD GetSize ( ) ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
void Destroy ( ) ;
2002-08-02 10:01:35 +00:00
2010-03-27 19:20:16 +00:00
ULONG_PTR m_ulWrittenAt ;
2002-08-02 10:01:35 +00:00
private :
2003-06-24 19:17:51 +00:00
IMAGE_RESOURCE_DIRECTORY m_rdDir ;
2005-08-27 19:56:00 +00:00
std : : vector < CResourceDirectoryEntry * > m_vEntries ;
2002-08-02 10:01:35 +00:00
} ;
class CResourceDirectoryEntry {
public :
2013-12-08 14:34:38 +00:00
CResourceDirectoryEntry ( const WINWCHAR * szName , CResourceDirectory * rdSubDir ) ;
CResourceDirectoryEntry ( const WINWCHAR * szName , CResourceDataEntry * rdeData ) ;
2003-06-24 19:17:51 +00:00
virtual ~ CResourceDirectoryEntry ( ) ;
2002-08-02 10:01:35 +00:00
2015-09-10 12:14:20 +00:00
bool HasName ( ) const ;
const WINWCHAR * GetName ( ) const ;
int GetNameLength ( ) const ;
WORD GetId ( ) const ;
bool IsDataDirectory ( ) const ;
CResourceDirectory * GetSubDirectory ( ) const ;
CResourceDataEntry * GetDataEntry ( ) const ;
2002-08-02 10:01:35 +00:00
2010-03-27 19:20:16 +00:00
ULONG_PTR m_ulWrittenAt ;
2002-08-02 10:01:35 +00:00
private :
2003-06-24 19:17:51 +00:00
bool m_bHasName ;
2013-12-08 14:34:38 +00:00
WINWCHAR * m_szName ;
2007-01-24 15:19:29 +00:00
WORD m_wId ;
2003-06-24 19:17:51 +00:00
bool m_bIsDataDirectory ;
union {
CResourceDirectory * m_rdSubDir ;
CResourceDataEntry * m_rdeData ;
} ;
2002-08-02 10:01:35 +00:00
} ;
class CResourceDataEntry {
public :
2007-10-03 17:01:19 +00:00
CResourceDataEntry ( BYTE * pbData , DWORD dwSize , DWORD dwCodePage = 0 , DWORD dwOffset = DWORD ( - 1 ) ) ;
2003-06-24 19:17:51 +00:00
~ CResourceDataEntry ( ) ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
BYTE * GetData ( ) ;
void SetData ( BYTE * pbData , DWORD dwSize ) ;
void SetData ( BYTE * pbData , DWORD dwSize , DWORD dwCodePage ) ;
2002-08-02 10:01:35 +00:00
2003-06-24 19:17:51 +00:00
DWORD GetSize ( ) ;
DWORD GetCodePage ( ) ;
2007-10-03 17:01:19 +00:00
DWORD GetOffset ( ) ;
2002-08-02 10:01:35 +00:00
2010-03-27 19:20:16 +00:00
ULONG_PTR m_ulWrittenAt ;
2002-08-02 10:01:35 +00:00
private :
2003-06-24 19:17:51 +00:00
BYTE * m_pbData ;
DWORD m_dwSize ;
DWORD m_dwCodePage ;
2007-10-03 17:01:19 +00:00
DWORD m_dwOffset ;
2002-08-02 10:01:35 +00:00
} ;
# endif // !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_)