From 940277d9d8c961864ead5283317d03ad8c21a9dc Mon Sep 17 00:00:00 2001 From: anders_k Date: Fri, 18 Sep 2015 15:55:56 +0000 Subject: [PATCH] * block_header::offset is now pointer sized in exehead * Wininet.h -> wininet.h for POSIX git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6608 212acab6-be3b-0410-9dea-997c60f758d6 --- Contrib/Makensisw/update.cpp | 2 +- Source/build.cpp | 32 ++++++++++++++++++-------------- Source/build.h | 2 ++ Source/exehead/fileform.c | 20 +++++++++++++++++--- Source/exehead/fileform.h | 14 ++++++++++---- Source/fileform.cpp | 17 ++++++++++------- Source/fileform.h | 11 ++++++----- Source/makenssi.cpp | 2 +- Source/writer.cpp | 3 ++- Source/writer.h | 21 ++++++++++++++++----- 10 files changed, 83 insertions(+), 41 deletions(-) diff --git a/Contrib/Makensisw/update.cpp b/Contrib/Makensisw/update.cpp index 8d4728fb..726d1a3a 100644 --- a/Contrib/Makensisw/update.cpp +++ b/Contrib/Makensisw/update.cpp @@ -2,7 +2,7 @@ #include "makensisw.h" #include "update.h" -#include +#include #include "utils.h" // OpenUrlInDefaultBrowser #define mbtitle "NSIS Update" diff --git a/Source/build.cpp b/Source/build.cpp index b4402389..1d5ca3aa 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -2318,46 +2318,50 @@ void CEXEBuild::AddStandardStrings() #endif//NSIS_SUPPORT_MOVEONREBOOT } +writer_target_info CEXEBuild::mk_writer_target_info() { return writer_target_info(build_unicode, is_target_64bit()); } + void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf) { + const writer_target_info ti = mk_writer_target_info(); + const unsigned int cbHdr = get_header_size(); GrowBuf blocks_buf; - growbuf_writer_sink sink(&blocks_buf, build_unicode); + growbuf_writer_sink sink(&blocks_buf, ti); #ifdef NSIS_CONFIG_VISIBLE_SUPPORT - cur_header->blocks[NB_PAGES].offset = sizeof(header) + blocks_buf.getlen(); + cur_header->blocks[NB_PAGES].offset = cbHdr + blocks_buf.getlen(); page_writer::write_block(cur_pages, &sink); #endif - cur_header->blocks[NB_SECTIONS].offset = sizeof(header) + blocks_buf.getlen(); + cur_header->blocks[NB_SECTIONS].offset = cbHdr + blocks_buf.getlen(); section_writer::write_block(cur_sections, &sink); - cur_header->blocks[NB_ENTRIES].offset = sizeof(header) + blocks_buf.getlen(); + cur_header->blocks[NB_ENTRIES].offset = cbHdr + blocks_buf.getlen(); entry_writer::write_block(cur_entries, &sink); - cur_header->blocks[NB_STRINGS].offset = sizeof(header) + blocks_buf.getlen(); + cur_header->blocks[NB_STRINGS].offset = cbHdr + blocks_buf.getlen(); blocks_buf.add(cur_strlist->getstorageptr(), cur_strlist->gettotalsize()); - cur_header->blocks[NB_LANGTABLES].offset = sizeof(header) + blocks_buf.getlen(); + cur_header->blocks[NB_LANGTABLES].offset = cbHdr + blocks_buf.getlen(); lang_table_writer::write_block(cur_langtables, &sink, cur_header->langtable_size); - cur_header->blocks[NB_CTLCOLORS].offset = sizeof(header) + blocks_buf.getlen(); - ctlcolors_writer::write_block(cur_ctlcolors, &sink, build_unicode, is_target_64bit()); + cur_header->blocks[NB_CTLCOLORS].offset = cbHdr + blocks_buf.getlen(); + ctlcolors_writer::write_block(cur_ctlcolors, &sink); #ifdef NSIS_SUPPORT_BGBG if (cur_header->bg_color1 != -1) { bg_font.lfFaceName[LF_FACESIZE-1] = 0; - cur_header->blocks[NB_BGFONT].offset = sizeof(header) + blocks_buf.getlen(); + cur_header->blocks[NB_BGFONT].offset = cbHdr + blocks_buf.getlen(); LOGFONT_writer w(&sink); w.write(&bg_font); } #endif - growbuf_writer_sink sink2(hdrbuf, build_unicode); + growbuf_writer_sink sink2(hdrbuf, ti); header_writer header(&sink2); - header.write(cur_header); + header.write(cur_header, ti); sink2.write_growbuf(&blocks_buf); } @@ -2731,7 +2735,7 @@ int CEXEBuild::write_output(void) try { - file_writer_sink sink(fp); + file_writer_sink sink(fp, mk_writer_target_info()); firstheader_writer w(&sink); w.write(&fh); } @@ -2956,7 +2960,7 @@ int CEXEBuild::write_output(void) try { - file_writer_sink sink(fp); + file_writer_sink sink(fp, mk_writer_target_info()); firstheader_writer w(&sink); w.write(&fh); } @@ -3188,7 +3192,7 @@ int CEXEBuild::uninstall_generate() MMapBuf udata; { - growbuf_writer_sink sink(&udata, build_unicode); + growbuf_writer_sink sink(&udata, mk_writer_target_info()); firstheader_writer w(&sink); w.write(&fh); } diff --git a/Source/build.h b/Source/build.h index a4b98d4e..98a35fac 100644 --- a/Source/build.h +++ b/Source/build.h @@ -130,6 +130,7 @@ class CEXEBuild { const TCHAR* get_target_suffix(CEXEBuild::TARGETTYPE tt, const TCHAR*defval = _T("?")) const; const TCHAR* get_target_suffix() const {return get_target_suffix(m_target_type);} bool is_target_64bit() const { return TARGET_AMD64 == m_target_type; } + unsigned int get_header_size() const { return (unsigned int)sizeof(header) + (is_target_64bit() ? (4 * BLOCKS_NUM) : 0); } void set_default_output_filename(const tstring& filename); @@ -436,6 +437,7 @@ class CEXEBuild { bool no_space_texts; bool build_unicode;// generate installer with unicode exehead? bool build_lockedunicodetarget; + class writer_target_info mk_writer_target_info(); bool has_called_write_output; diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index 2d6e172d..0cd9475f 100644 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -175,6 +175,11 @@ const TCHAR * NSISCALL loadHeaders(int cl_flags) HANDLE db_hFile; +#ifdef C_ASSERT +{C_ASSERT(sizeof(firstheader) == sizeof(int) * 7);} +{C_ASSERT(sizeof(struct block_header) == sizeof(UINT_PTR) + sizeof(int));} +#endif + #ifdef NSIS_CONFIG_CRC_SUPPORT #ifdef NSIS_CONFIG_VISIBLE_SUPPORT verify_time = GetTickCount() + 1000; @@ -336,7 +341,7 @@ const TCHAR * NSISCALL loadHeaders(int cl_flags) if (h.length_of_header < header->blocks[left].offset) return _LANG_GENERIC_ERROR; // Should never happen #endif - header->blocks[left].offset += BUGBUG64TRUNCATE(UINT, (UINT_PTR) data); + header->blocks[left].offset += (UINT_PTR) data; } #ifdef NSIS_COMPRESS_WHOLE @@ -370,7 +375,12 @@ int NSISCALL _dodecomp(int offset, HANDLE hFileOut, unsigned char *outbuf, int o if (offset>=0) { - SetSelfFilePointer(g_blocks[NB_DATA].offset+offset); + UINT_PTR datofs=g_blocks[NB_DATA].offset+offset; +#if (NSIS_MAX_EXESIZE+0) > 0x7fffffff +#error "SetFilePointer is documented to only support signed 32-bit offsets in lDistanceToMove" +#endif + const int pos=(int)datofs; + SetSelfFilePointer(pos); } if (!ReadSelfFile((LPVOID)&input_len,sizeof(int))) return -3; @@ -542,7 +552,11 @@ int NSISCALL _dodecomp(int offset, HANDLE hFileOut, unsigned char *outbuf, int o int retval; if (offset>=0) { - dbd_pos=g_blocks[NB_DATA].offset+offset; + UINT_PTR datofs=g_blocks[NB_DATA].offset+offset; +#if (NSIS_MAX_EXESIZE+0) > 0x7fffffff +#error "SetFilePointer is documented to only support signed 32-bit offsets in lDistanceToMove" +#endif + dbd_pos=(int)datofs; SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN); } retval=__ensuredata(sizeof(int)); diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 9f47d52e..792e49cd 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -209,6 +209,8 @@ enum #endif }; +#pragma pack(push, 1) // fileform.cpp assumes no padding/alignment + #define FH_FLAGS_MASK 15 #define FH_FLAGS_UNINSTALL 1 #ifdef NSIS_CONFIG_SILENT_SUPPORT @@ -258,7 +260,11 @@ typedef struct // nsis blocks struct block_header { - /*UINT_PTR*/ int offset; // BUGBUG: This should probably be UINT_PTR but that currently crashes :( +#ifdef MAKENSIS + int offset; +#else + UINT_PTR offset; // exehead stores a memory location here so it needs to be pointer sized +#endif int num; }; @@ -286,7 +292,7 @@ typedef TCHAR NSIS_STRING[NSIS_MAX_STRLEN]; typedef struct { int flags; // CH_FLAGS_* - struct block_header blocks[BLOCKS_NUM]; + struct block_header blocks[BLOCKS_NUM]; // CEXEBuild::get_header_size needs to adjust the size of this based on the targets pointer size // InstallDirRegKey stuff int install_reg_rootkey; @@ -468,7 +474,6 @@ typedef struct #define CC_BK_SYS 8 #define CC_BKB 16 -#pragma pack(push, 4) typedef struct { COLORREF text; COLORREF bkc; @@ -498,7 +503,6 @@ typedef struct { #else # define ctlcolors ctlcolors32 #endif -#pragma pack(pop) // constants for myDelete (util.c) #define DEL_DIR 1 @@ -525,6 +529,8 @@ typedef struct { #define FIELDN(x, y) (((int *)&x)[y]) +#pragma pack(pop) + #ifdef EXEHEAD // the following are only used/implemented in exehead, not makensis. diff --git a/Source/fileform.cpp b/Source/fileform.cpp index 914b6b42..1055b963 100644 --- a/Source/fileform.cpp +++ b/Source/fileform.cpp @@ -35,20 +35,23 @@ void firstheader_writer::write(const firstheader *data) m_sink->write_int(data->length_of_all_following_data); } -void block_header_writer::write(const block_header *data) +void block_header_writer::write(const block_header *data, const writer_target_info&ti) { - m_sink->write_int(data->offset); + if (ti.is_64bit()) + m_sink->write_int64(data->offset); + else + m_sink->write_int(data->offset); m_sink->write_int(data->num); } -void header_writer::write(const header *data) +void header_writer::write(const header *data, const writer_target_info&ti) { m_sink->write_int(data->flags); block_header_writer bw(writer::m_sink); for (int i = 0; i < BLOCKS_NUM; i++) { - bw.write(&data->blocks[i]); + bw.write(&data->blocks[i], ti); } m_sink->write_int(data->install_reg_rootkey); @@ -146,13 +149,13 @@ void page_writer::write(const page *data) m_sink->write_int_array(data->parms, 5); } -void ctlcolors_writer::writeplatformitem(const void *data, bool wide, bool x64) +void ctlcolors_writer::write(const ctlcolors *data, const writer_target_info&ti) { assert(sizeof(int) == 4 && sizeof(ctlcolors64) > sizeof(ctlcolors32)); - ctlcolors *p = (ctlcolors*) data; + const ctlcolors *p = data; m_sink->write_int(p->text); m_sink->write_int(p->bkc); - if (x64) + if (ti.is_64bit()) { assert(!p->bkb); m_sink->write_int64(p->bkb); diff --git a/Source/fileform.h b/Source/fileform.h index aa489aaa..288dcc4b 100644 --- a/Source/fileform.h +++ b/Source/fileform.h @@ -43,19 +43,20 @@ #define DECLARE_PLATFORMITEMWRITER(x) class x##_writer : public writer \ { public: \ x##_writer(writer_sink *sink) : writer(sink) {} \ - void writeplatformitem(const void *data, bool wide, bool x64); \ - static void write_block(IGrowBuf *pGB, writer_sink *pS, bool wide, bool x64) \ + void write(const x *data, const writer_target_info&ti); \ + static void write_block(IGrowBuf *pGB, writer_sink *pS, const writer_target_info *pTI = 0) \ { \ x##_writer writer(pS); \ + if (!pTI) pTI = &pS->get_target_info(); /* Defaults to TI from sink */ \ for (size_t l = pGB->getlen() / sizeof(x), i = 0; i < l; i++) \ - writer.writeplatformitem(&(((x*)pGB->get())[i]), wide, x64); \ + writer.write(&(((x*)pGB->get())[i]), *pTI); \ } \ } DECLARE_WRITER(firstheader); -DECLARE_WRITER(block_header); -DECLARE_WRITER(header); +DECLARE_PLATFORMITEMWRITER(block_header); +DECLARE_PLATFORMITEMWRITER(header); // Platform specific because it writes block_headers DECLARE_WRITER(section); DECLARE_WRITER(entry); DECLARE_WRITER(page); diff --git a/Source/makenssi.cpp b/Source/makenssi.cpp index 33c23f7b..c8f98f87 100644 --- a/Source/makenssi.cpp +++ b/Source/makenssi.cpp @@ -199,7 +199,7 @@ static void print_stub_info(CEXEBuild& build) if (build.display_info) { _ftprintf(g_output,_T("Size of first header is %lu bytes.\n"),(unsigned long)sizeof(firstheader)); - _ftprintf(g_output,_T("Size of main header is %lu bytes.\n"),(unsigned long)sizeof(header)); + _ftprintf(g_output,_T("Size of main header is %lu bytes.\n"),(unsigned long)build.get_header_size()); _ftprintf(g_output,_T("Size of each section is %lu bytes.\n"),(unsigned long)sizeof(section)); _ftprintf(g_output,_T("Size of each page is %lu bytes.\n"),(unsigned long)sizeof(page)); _ftprintf(g_output,_T("Size of each instruction is %lu bytes.\n"),(unsigned long)sizeof(entry)); diff --git a/Source/writer.cpp b/Source/writer.cpp index d7e29fdf..dfa55804 100644 --- a/Source/writer.cpp +++ b/Source/writer.cpp @@ -59,7 +59,7 @@ void writer_sink::write_int_array(const int i[], const size_t len) void writer_sink::write_string(const TCHAR *s, size_t size) { #ifdef _UNICODE - if (m_build_unicode) + if (m_ti.is_unicode()) { bool strEnd = false; TCHAR ch = L'\0'; @@ -83,6 +83,7 @@ void writer_sink::write_string(const TCHAR *s, size_t size) delete [] wb; } #else + //TODO: Why does this allocate memory? It could just write the string and a manual zero character? char *wb = new char[size]; memset(wb, 0, size); strncpy(wb, s, size); diff --git a/Source/writer.h b/Source/writer.h index bbc7b486..4d961dfe 100644 --- a/Source/writer.h +++ b/Source/writer.h @@ -25,9 +25,19 @@ #include #include "tchar.h" +class writer_target_info { +public: + writer_target_info(bool Unicode = 0, bool Cpu64 = 0) { m_f = (Unicode ? F_U : 0) | (Cpu64 ? F_64 : 0); } + bool is_unicode() const { return !!(m_f & F_U); } + bool is_64bit() const { return !!(m_f & F_64); } +protected: + enum { F_U = 0x01, F_64 = 0x80 }; + BYTE m_f; +}; + class writer_sink { public: - writer_sink() : m_build_unicode(false) {} + writer_sink(const writer_target_info&ti) : m_ti(ti) {} virtual ~writer_sink() {} virtual void write_byte(const unsigned char b); @@ -39,8 +49,9 @@ public: virtual void write_growbuf(const IGrowBuf *b); virtual void write_data(const void *data, const size_t size) = 0; + virtual const writer_target_info& get_target_info() const { return m_ti; } protected: - bool m_build_unicode; + writer_target_info m_ti; }; class writer { @@ -56,7 +67,7 @@ protected: class growbuf_writer_sink : public writer_sink { public: typedef IGrowBuf sink_type; - growbuf_writer_sink(sink_type *buf, bool build_unicode) : m_buf(buf) { m_build_unicode=build_unicode; } + growbuf_writer_sink(sink_type *buf, const writer_target_info&ti) : writer_sink(ti), m_buf(buf) { } virtual void write_data(const void *data, const size_t size); @@ -67,7 +78,7 @@ private: class file_writer_sink : public writer_sink { public: - file_writer_sink(FILE *fp) : m_fp(fp) {} + file_writer_sink(FILE *fp, const writer_target_info&ti) : writer_sink(ti), m_fp(fp) {} virtual void write_data(const void *data, const size_t size); @@ -79,7 +90,7 @@ private: #ifdef NSIS_CONFIG_CRC_SUPPORT class crc_writer_sink : public writer_sink { public: - crc_writer_sink(crc32_t *crc) : m_crc(crc) {} + crc_writer_sink(crc32_t *crc) : writer_sink(writer_target_info()), m_crc(crc) {} virtual void write_data(const void *data, const size_t size);