Added !uninstfinalize (patch 280)

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7294 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2021-08-18 13:53:50 +00:00
parent 1768555f2b
commit 41bb557cbc
11 changed files with 166 additions and 79 deletions

View file

@ -100,8 +100,8 @@ CEXEBuild::~CEXEBuild()
for (int i = 0; i < nlt; i++)
DeleteLangTable(nla+i);
if (postbuild_cmds)
postbuild_cmds->delete_all();
if (postbuild_cmds) postbuild_cmds->delete_all();
if (postubuild_cmds) postubuild_cmds->delete_all();
}
CEXEBuild::CEXEBuild(signed char pponly, bool warnaserror) :
@ -191,7 +191,7 @@ CEXEBuild::CEXEBuild(signed char pponly, bool warnaserror) :
build_cursection=NULL;
// init public data.
build_packname[0]=build_packcmd[0]=build_output_filename[0]=0;
postbuild_cmds=NULL;
postbuild_cmds=postubuild_cmds=NULL;
// Added by ramon 23 May 2003
build_allowskipfiles=1;
@ -1731,21 +1731,21 @@ int CEXEBuild::add_page(int type)
#ifndef NSIS_CONFIG_LICENSEPAGE
if (type == PAGE_LICENSE)
{
ERROR_MSG(_T("Error: can't add license page, NSIS_CONFIG_LICENSEPAGE not defined.\n"));
ERROR_MSG(_T("Error: can't add %") NPRIns _T(" page, %") NPRIns _T(" not defined.\n"), "license", "NSIS_CONFIG_LICENSEPAGE");
return PS_ERROR;
}
#endif
#ifndef NSIS_CONFIG_COMPONENTPAGE
if (type == PAGE_COMPONENTS)
{
ERROR_MSG(_T("Error: can't add components page, NSIS_CONFIG_COMPONENTPAGE not defined.\n"));
ERROR_MSG(_T("Error: can't add %") NPRIns _T(" page, %") NPRIns _T(" not defined.\n"), "components", "NSIS_CONFIG_COMPONENTPAGE");
return PS_ERROR;
}
#endif
#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
if (type == PAGE_COMPONENTS)
{
ERROR_MSG(_T("Error: can't add uninstConfirm page, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n"));
ERROR_MSG(_T("Error: can't add %") NPRIns _T(" page, %") NPRIns _T(" not defined.\n"), "uninstConfirm", "NSIS_CONFIG_UNINSTALL_SUPPORT");
return PS_ERROR;
}
#endif
@ -2539,14 +2539,11 @@ int CEXEBuild::pack_exe_header()
// write out exe header, pack, read back in, and
// update the header info
FILE *tmpfile=FOPEN(build_packname,("wb"));
if (!tmpfile)
if (m_exehead_size != write_octets_to_file(build_packname, m_exehead, m_exehead_size))
{
ERROR_MSG(_T("Error: writing temporary file \"%") NPRIs _T("\" for pack\n"),build_packname);
return PS_ERROR;
}
fwrite(m_exehead,1,m_exehead_size,tmpfile);
fclose(tmpfile);
int ec = sane_system(build_packcmd);
if (ec == -1)
{
@ -3064,23 +3061,33 @@ int CEXEBuild::uninstall_generate()
{
SCRIPT_MSG(_T("Generating uninstaller... "));
const int start_offset = postubuild_cmds ? truncate_cast(int, m_exehead_size) : 0;
entry *ent = (entry *) build_entries.get();
if (!ent) return PS_ERROR; // Check this early
MMapBuf udata;
firstheader fh={0,};
GrowBuf uhd;
{
GrowBuf udata;
GrowBuf udata_exehead;
set_uninstall_mode(1);
PrepareHeaders(&udata);
PrepareHeaders(&udata_exehead);
fh.length_of_header=udata.getlen();
int err=add_data((char*)udata.get(),udata.getlen(),&uhd);
fh.length_of_header=udata_exehead.getlen();
int err=add_data((char*)udata_exehead.get(),udata_exehead.getlen(),&uhd);
set_uninstall_mode(0);
if (err < 0) return PS_ERROR;
}
crc32_t crc=0;
#ifdef NSIS_CONFIG_CRC_SUPPORT
bool calc_crc = true;
#else
bool calc_crc = false;
#endif
// Get offsets of icons to replace for uninstall
// Also makes sure that the icons are there and in the right size.
@ -3091,41 +3098,34 @@ int CEXEBuild::uninstall_generate()
return PS_ERROR;
}
entry *ent = (entry *) build_entries.get();
if (!ent)
{
delete [] unicon_data;
return PS_ERROR;
}
int ents = build_header.blocks[NB_ENTRIES].num;
int uns = uninstaller_writes_used;
int uninstdata_offset = build_datablock.getlen();
while (ents--)
for (int ents = build_header.blocks[NB_ENTRIES].num; ents--; ent++)
{
if (ent->which == EW_WRITEUNINSTALLER)
{
ent->offsets[1] = uninstdata_offset;
ent->offsets[2] = (int) m_unicon_size;
uns--;
if (!uns)
ent->offsets[2] = start_offset ? 0 : (int) m_unicon_size;
if (!--uns)
break;
}
ent++;
}
if (add_db_data((char *)unicon_data,m_unicon_size) < 0)
if (!start_offset && add_db_data((char *)unicon_data,m_unicon_size) < 0)
{
delete [] unicon_data;
return PS_ERROR;
}
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (start_offset || calc_crc)
{
// "create" the uninstaller
// create the uninstaller
LPBYTE uninst_header = (LPBYTE) malloc(m_exehead_size);
if (!uninst_header)
{
delete [] unicon_data;
return PS_ERROR;
}
memcpy(uninst_header, m_exehead, m_exehead_size);
@ -3140,17 +3140,25 @@ int CEXEBuild::uninstall_generate()
seeker += dwSize;
}
delete [] unicon_data;
if (calc_crc)
{
#ifdef NSIS_CONFIG_CRC_SUPPORT
#ifdef NSIS_CONFIG_CRC_ANAL
crc=CRC32(crc, uninst_header, (DWORD)m_exehead_size);
crc=CRC32(crc, uninst_header, (DWORD)m_exehead_size);
#else
crc=CRC32(crc, uninst_header + 512, (DWORD)m_exehead_size - 512);
crc=CRC32(crc, uninst_header + 512, (DWORD)m_exehead_size - 512);
#endif
#endif
}
// write the exehead
if (start_offset)
udata.add((char *)uninst_header, truncate_cast(int, m_exehead_size));
free(uninst_header);
}
#endif
delete [] unicon_data;
fh.nsinst[0]=FH_INT1;
fh.nsinst[1]=FH_INT2;
fh.nsinst[2]=FH_INT3;
@ -3165,8 +3173,6 @@ int CEXEBuild::uninstall_generate()
fh.length_of_all_following_data=
uhd.getlen()+ubuild_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0);
MMapBuf udata;
{
growbuf_writer_sink sink(&udata, mk_writer_target_info());
firstheader_writer w(&sink);
@ -3231,8 +3237,8 @@ int CEXEBuild::uninstall_generate()
compressor->End();
}
firstheader *_fh=(firstheader *)udata.get(0, sizeof(firstheader));
_fh->length_of_all_following_data=FIX_ENDIAN_INT32(udata.getlen()+(build_crcchk?sizeof(crc32_t):0));
firstheader *ufh=(firstheader *)udata.get(start_offset, sizeof(firstheader));
ufh->length_of_all_following_data=FIX_ENDIAN_INT32((udata.getlen()-start_offset)+(build_crcchk?sizeof(crc32_t):0));
udata.release();
}
else
@ -3264,11 +3270,11 @@ int CEXEBuild::uninstall_generate()
if (build_crcchk)
{
int pos = 0;
int left = udata.getlen();
int left = udata.getlen() - start_offset;
while (left > 0)
{
int l = min(build_filebuflen, left);
crc = CRC32(crc, (unsigned char *) udata.get(pos, l), l);
crc = CRC32(crc, (unsigned char *) udata.get(pos + start_offset, l), l);
udata.release();
pos += l;
left -= l;
@ -3280,14 +3286,57 @@ int CEXEBuild::uninstall_generate()
}
#endif
if (add_db_data(&udata) < 0)
return PS_ERROR;
if (start_offset)
{
TCHAR* fpath;
unsigned long in_len;
if (!(fpath = create_tempfile_path()))
{
ERROR_MSG(_T("Error: can't get temporary path\n"));
return PS_ERROR;
}
size_t ret_size = write_octets_to_file(fpath, (unsigned char*)udata.get(0, udata.getlen()), udata.getlen());
udata.release();
if ((size_t)udata.getlen() != ret_size)
{
ERROR_MSG(_T("Error: can't write %d bytes to output\n"), udata.getlen());
free(fpath);
return PS_ERROR;
}
if (PS_OK != run_postbuild_cmds(postubuild_cmds, fpath, _T("UninstFinalize")))
{
free(fpath);
return PS_ERROR;
}
BYTE* in_buf = alloc_and_read_file(fpath, in_len);
_tremove(fpath);
free(fpath);
if (!in_buf)
{
ERROR_MSG(_T("Error: can't read %d bytes from input\n"), in_len);
return PS_ERROR;
}
MMapBuf udata_in;
udata_in.add(in_buf, in_len);
free(in_buf);
if (add_db_data(&udata_in) < 0)
return PS_ERROR;
uninstall_size_full = udata_in.getlen();
udata_in.clear();
}
else
{
if (add_db_data(&udata) < 0)
return PS_ERROR;
//uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int);
uninstall_size_full = fh.length_of_all_following_data+(int)m_unicon_size;
}
udata.clear();
//uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int);
uninstall_size_full=fh.length_of_all_following_data+(int)m_unicon_size;
// compressed size
uninstall_size=build_datablock.getlen()-uninstdata_offset;