1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
|
/*
* ResourceEditor.h
*
* This file is a part of NSIS.
*
* Copyright (C) 2002-2018 Amir Szekely <kichik@users.sourceforge.net>
*
* 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.
*
* Reviewed for Unicode support by Jim Park -- 08/21/2007
*/
#if !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_)
#define AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Platform.h"
#include "winchar.h"
#include <vector>
#include <cassert>
#ifdef _WIN32
#include <winnt.h>
#else
// all definitions for non Win32 platforms were taken from MinGW's free Win32 library
# define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
# define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
# pragma pack(4)
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY;
typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
WORD Length;
CHAR NameString[1];
} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING;
typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
WORD Length;
WCHAR NameString[1];
} IMAGE_RESOURCE_DIR_STRING_U,*PIMAGE_RESOURCE_DIR_STRING_U;
# pragma pack()
#endif
#pragma pack(4)
typedef struct _MY_IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
#ifndef __BIG_ENDIAN__
DWORD NameOffset:31;
DWORD NameIsString:1;
#else
DWORD NameIsString:1;
DWORD NameOffset:31;
#endif
} NameString;
DWORD Name;
WORD Id;
} UName;
union {
DWORD OffsetToData;
struct {
#ifndef __BIG_ENDIAN__
DWORD OffsetToDirectory:31;
DWORD DataIsDirectory:1;
#else
DWORD DataIsDirectory:1;
DWORD OffsetToDirectory:31;
#endif
} DirectoryOffset;
} UOffset;
} MY_IMAGE_RESOURCE_DIRECTORY_ENTRY,*PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY;
#pragma pack()
#include <stdexcept>
// classes
class CResourceDirectory;
class CResourceDirectoryEntry;
class CResourceDataEntry;
// Resource directory with entries
typedef struct RESOURCE_DIRECTORY {
IMAGE_RESOURCE_DIRECTORY Header;
MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1];
} *PRESOURCE_DIRECTORY;
#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)) )
class CResourceEditor {
public:
CResourceEditor(void* pbPE, int iSize, bool bKeepData = true);
virtual ~CResourceEditor();
enum { ANYLANGID = 0xffff };
// On POSIX+Unicode GetResource(RT_VERSION,..) is not TCHAR nor WINWCHAR, it is WCHAR/UINT16 (MAKEINTRESOURCEW).
// 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...
template<class T> bool UpdateResource(const T*Type, WORD Name, LANGID Lang, BYTE*Data, DWORD Size)
{
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return false; }
return UpdateResourceT((const TCHAR*) Type, Name, Lang, Data, Size);
}
template<class T> BYTE* GetResource(const T*Type, WORD Name, LANGID Lang)
{
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return NULL; }
return GetResourceT((const TCHAR*) Type, Name, Lang);
}
template<class T> int GetResourceSize(const T*Type, WORD Name, LANGID Lang)
{
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return -1; }
return GetResourceSizeT((const TCHAR*) Type, Name, Lang);
}
template<class T> DWORD GetResourceOffset(const T*Type, WORD Name, LANGID Lang)
{
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return -1; }
return GetResourceOffsetT((const TCHAR*) Type, Name, Lang);
}
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);
}
bool UpdateResourceT (const TCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
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);
BYTE* GetFirstResourceT (const TCHAR* szType, size_t&cbData);
void FreeResource(BYTE* pbResource);
// The section name must be in ASCII.
bool SetPESectionVirtualSize(const char* pszSectionName, DWORD newsize);
DWORD Save(BYTE* pbBuf, DWORD &dwSize);
// 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
);
private:
bool UpdateResourceW (const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
BYTE* GetResourceW (const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
int GetResourceSizeW (const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
DWORD GetResourceOffsetW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
BYTE* GetFirstResourceW (const WINWCHAR* szType, size_t&cbData);
CResourceDataEntry* FindResource(const WINWCHAR* Type, const WINWCHAR* Name, LANGID Language);
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);
private:
BYTE* m_pbPE;
int m_iSize;
bool m_bKeepData;
PIMAGE_NT_HEADERS m_ntHeaders;
DWORD m_dwResourceSectionIndex;
DWORD m_dwResourceSectionVA;
CResourceDirectory* m_cResDir;
};
class CResourceDirectory {
public:
CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY prd);
virtual ~CResourceDirectory();
IMAGE_RESOURCE_DIRECTORY GetInfo();
CResourceDirectoryEntry* GetEntry(unsigned int i);
bool AddEntry(CResourceDirectoryEntry* entry);
void RemoveEntry(int i);
unsigned int CountEntries();
int Find(const WINWCHAR* szName);
int Find(WORD wId);
DWORD GetSize();
void Destroy();
ULONG_PTR m_ulWrittenAt;
private:
IMAGE_RESOURCE_DIRECTORY m_rdDir;
std::vector<CResourceDirectoryEntry*> m_vEntries;
};
class CResourceDirectoryEntry {
public:
CResourceDirectoryEntry(const WINWCHAR* szName, CResourceDirectory* rdSubDir);
CResourceDirectoryEntry(const WINWCHAR* szName, CResourceDataEntry* rdeData);
virtual ~CResourceDirectoryEntry();
bool HasName() const;
const WINWCHAR* GetName() const;
int GetNameLength() const;
WORD GetId() const;
bool IsDataDirectory() const;
CResourceDirectory* GetSubDirectory() const;
CResourceDataEntry* GetDataEntry() const;
ULONG_PTR m_ulWrittenAt;
private:
bool m_bHasName;
WINWCHAR* m_szName;
WORD m_wId;
bool m_bIsDataDirectory;
union {
CResourceDirectory* m_rdSubDir;
CResourceDataEntry* m_rdeData;
};
};
class CResourceDataEntry {
public:
CResourceDataEntry(BYTE* pbData, DWORD dwSize, DWORD dwCodePage = 0, DWORD dwOffset = DWORD(-1));
~CResourceDataEntry();
BYTE* GetData();
void SetData(BYTE* pbData, DWORD dwSize);
void SetData(BYTE* pbData, DWORD dwSize, DWORD dwCodePage);
DWORD GetSize();
DWORD GetCodePage();
DWORD GetOffset();
ULONG_PTR m_ulWrittenAt;
private:
BYTE* m_pbData;
DWORD m_dwSize;
DWORD m_dwCodePage;
DWORD m_dwOffset;
};
#endif // !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_)
|