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:
parent
1768555f2b
commit
41bb557cbc
11 changed files with 166 additions and 79 deletions
|
@ -120,9 +120,17 @@ This option makes the compiler use an external EXE packer (such as \W{http://www
|
|||
|
||||
\c command [compare comparevalue]
|
||||
|
||||
This option will execute 'command' using a call to system() after the output EXE has been generated. You can typically use it to sign (Authenticode) your installer. If 'command' contains a '%1' it will be replaced by the executables filename.
|
||||
This option will execute 'command' using a call to system() after the installer EXE has been generated. You can typically use it to sign (Authenticode) your installer. If 'command' contains a '%1' it will be replaced by the executables filename.
|
||||
|
||||
\c !finalize 'sign.bat "%1" "Product Installer" http://example.com'
|
||||
\c !finalize 'sign.bat "%1" "MyProduct Installer" http://example.com'
|
||||
|
||||
\S1{uninstfinalize} !uninstfinalize
|
||||
|
||||
\c command [compare comparevalue]
|
||||
|
||||
This option will execute 'command' using a call to system() after the uninstaller EXE has been generated. You can typically use it to sign (Authenticode) your uninstaller. If 'command' contains a '%1' it will be replaced by the executables filename.
|
||||
|
||||
\c !uninstfinalize 'sign.bat "%1" "MyProduct Installer" http://example.com'
|
||||
|
||||
\S1{system} !system
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ Released on ???? ??th, 20??
|
|||
|
||||
\S1{v3.08-cl} Changelog
|
||||
|
||||
\S2{} Major Changes
|
||||
|
||||
\b Added \R{uninstfinalize}{!uninstfinalize} (\W{http://sf.net/p/nsis/patches/280}{patch #280}, \W{http://sf.net/p/nsis/bugs/1241}{bug #1241})
|
||||
|
||||
\S2{} Minor Changes
|
||||
|
||||
\b Disallow start maximized mode
|
||||
|
|
141
Source/build.cpp
141
Source/build.cpp
|
@ -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;
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ class CEXEBuild {
|
|||
int pp_define(LineParser&line);
|
||||
int pp_undef(LineParser&line);
|
||||
int pp_packhdr(LineParser&line);
|
||||
int pp_finalize(LineParser&line);
|
||||
int pp_finalize(int which_token, LineParser&line);
|
||||
int pp_execute(int which_token, LineParser&line);
|
||||
int pp_addincludedir(LineParser&line);
|
||||
int pp_include(LineParser&line);
|
||||
|
@ -606,7 +606,7 @@ class CEXEBuild {
|
|||
TCHAR cmd[1];
|
||||
void delete_all();
|
||||
static postbuild_cmd* make(const TCHAR *cmdstr, int cmpop, int cmpval);
|
||||
} *postbuild_cmds;
|
||||
} *postbuild_cmds, *postubuild_cmds;
|
||||
int run_postbuild_cmds(const postbuild_cmd *cmds, const TCHAR *templatearg_pc1, const TCHAR* commandname);
|
||||
int check_external_exitcode(int exitcode, int op, int val);
|
||||
|
||||
|
|
|
@ -1563,36 +1563,41 @@ static int NSISCALL ExecuteEntry(entry *entry_)
|
|||
hFile=myOpenFile(buf1,GENERIC_WRITE,CREATE_ALWAYS);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
unsigned char *filebuf;
|
||||
int filehdrsize = g_filehdrsize;
|
||||
filebuf=(unsigned char *)GlobalAlloc(GPTR,filehdrsize);
|
||||
if (filebuf)
|
||||
int dboffset = parm1;
|
||||
if (parm2)
|
||||
{
|
||||
SetSelfFilePointer(0);
|
||||
ReadSelfFile((char*)filebuf,filehdrsize);
|
||||
unsigned char *filebuf;
|
||||
int filehdrsize = g_filehdrsize;
|
||||
filebuf=(unsigned char *)GlobalAlloc(GPTR,filehdrsize);
|
||||
if (filebuf)
|
||||
{
|
||||
// parm1 = uninstdata_offset
|
||||
// parm2 = m_unicon_size
|
||||
unsigned char* seeker;
|
||||
unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm2);
|
||||
if (unicon_data) {
|
||||
GetCompressedDataFromDataBlockToMemory(parm1,unicon_data,parm2);
|
||||
while (*seeker) {
|
||||
struct icondata {
|
||||
DWORD dwSize;
|
||||
DWORD dwOffset;
|
||||
} id = *(struct icondata *) seeker;
|
||||
seeker += sizeof(struct icondata);
|
||||
mini_memcpy(filebuf+id.dwOffset, seeker, id.dwSize);
|
||||
seeker += id.dwSize;
|
||||
SetSelfFilePointer(0);
|
||||
ReadSelfFile((char*)filebuf,filehdrsize);
|
||||
{
|
||||
// parm1 = uninstdata_offset
|
||||
// parm2 = m_unicon_size
|
||||
unsigned char* seeker;
|
||||
unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm2);
|
||||
if (unicon_data) {
|
||||
GetCompressedDataFromDataBlockToMemory(parm1,unicon_data,parm2);
|
||||
while (*seeker) {
|
||||
struct icondata {
|
||||
DWORD dwSize;
|
||||
DWORD dwOffset;
|
||||
} id = *(struct icondata *) seeker;
|
||||
seeker += sizeof(struct icondata);
|
||||
mini_memcpy(filebuf+id.dwOffset, seeker, id.dwSize);
|
||||
seeker += id.dwSize;
|
||||
}
|
||||
GlobalFree(unicon_data);
|
||||
}
|
||||
GlobalFree(unicon_data);
|
||||
}
|
||||
myWriteFile(hFile,(char*)filebuf,filehdrsize);
|
||||
GlobalFree(filebuf);
|
||||
dboffset = -1;
|
||||
}
|
||||
myWriteFile(hFile,(char*)filebuf,filehdrsize);
|
||||
GlobalFree(filebuf);
|
||||
ret=GetCompressedDataFromDataBlock(-1,hFile);
|
||||
}
|
||||
ret=GetCompressedDataFromDataBlock(dboffset, hFile);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
log_printf3(_T("created uninstaller: %d, \"%s\""),ret,buf1);
|
||||
|
|
|
@ -530,7 +530,7 @@ parse_again:
|
|||
extern FILE *g_output;
|
||||
bool pptok = is_pp_token(tkid), docmd = pptok;
|
||||
bool both = TOK_P_VERBOSE == tkid || TOK_P_WARNING == tkid || TOK_P_ECHO == tkid;
|
||||
if (TOK_P_FINALIZE == tkid || TOK_P_PACKEXEHEADER == tkid) docmd = false;
|
||||
if (TOK_P_FINALIZE == tkid || TOK_P_UNINSTFINALIZE == tkid || TOK_P_PACKEXEHEADER == tkid) docmd = false;
|
||||
if (docmd && is_unsafe_pp_token(tkid) && preprocessonly > 0) docmd = false;
|
||||
if (!docmd || both) _ftprintf(g_output,(_T("%") NPRIs _T("\n")),ppoline.get());
|
||||
if (!docmd && !both) return PS_OK;
|
||||
|
@ -2553,7 +2553,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
case TOK_P_PACKEXEHEADER:
|
||||
return pp_packhdr(line);
|
||||
case TOK_P_FINALIZE:
|
||||
return pp_finalize(line);
|
||||
case TOK_P_UNINSTFINALIZE:
|
||||
return pp_finalize(which_token, line);
|
||||
case TOK_P_SYSTEMEXEC:
|
||||
case TOK_P_EXECUTE:
|
||||
case TOK_P_MAKENSIS:
|
||||
|
|
|
@ -1058,8 +1058,15 @@ template<class T> void slist_append(T&list, T&item)
|
|||
(prev ? prev->next : list) = item;
|
||||
}
|
||||
|
||||
int CEXEBuild::pp_finalize(LineParser&line)
|
||||
int CEXEBuild::pp_finalize(int which_token, LineParser&line)
|
||||
{
|
||||
#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
|
||||
if (which_token == TOK_P_UNINSTFINALIZE)
|
||||
{
|
||||
ERROR_MSG(_T("Error: %") NPRIs _T(" specified, %") NPRIns _T(" not defined.\n"), line.gettoken_str(0), "NSIS_CONFIG_UNINSTALL_SUPPORT");
|
||||
return PS_ERROR;
|
||||
}
|
||||
#endif
|
||||
TCHAR* cmdstr = line.gettoken_str(1);
|
||||
int validparams = false;
|
||||
postbuild_cmd *newcmd = postbuild_cmd::make(cmdstr, line.gettoken_enum(2, _T("<\0>\0<>\0=\0ignore\0")), line.gettoken_int(3, &validparams));
|
||||
|
@ -1067,8 +1074,8 @@ int CEXEBuild::pp_finalize(LineParser&line)
|
|||
newcmd->cmpop = 4, validparams = true; // Just a command, ignore the exit code
|
||||
if (newcmd->cmpop == -1 || !validparams)
|
||||
PRINTHELP();
|
||||
slist_append(postbuild_cmds, newcmd);
|
||||
SCRIPT_MSG(_T("!finalize: \"%") NPRIs _T("\"\n"), cmdstr);
|
||||
slist_append(which_token == TOK_P_UNINSTFINALIZE ? postubuild_cmds : postbuild_cmds, newcmd);
|
||||
SCRIPT_MSG(_T("!%") NPRIns _T("finalize: \"%") NPRIs _T("\"\n"), which_token == TOK_P_UNINSTFINALIZE ? "uninst" : "", cmdstr);
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -273,6 +273,7 @@ static tokenType tokenlist[TOK__LAST] =
|
|||
{TOK_MANIFEST_GDISCALING,_T("ManifestGdiScaling"),1,0,_T("notset|true"),TP_GLOBAL},
|
||||
{TOK_P_PACKEXEHEADER,_T("!packhdr"),2,0,_T("temp_file_name command_line_to_compress_that_temp_file"),TP_ALL},
|
||||
{TOK_P_FINALIZE,_T("!finalize"),1,2,_T("command_with_%1 [<OP retval>]"),TP_ALL},
|
||||
{TOK_P_UNINSTFINALIZE,_T("!uninstfinalize"),1,2,_T("command_with_%1 [<OP retval>]"),TP_ALL},
|
||||
{TOK_P_SYSTEMEXEC,_T("!system"),1,2,_T("command [<OP retval> | <retvalsymbol>]\n OP=(< > <> =)"),TP_ALL},
|
||||
{TOK_P_EXECUTE,_T("!execute"),1,2,_T("command [<OP retval> | <retvalsymbol>]\n OP=(< > <> =)"),TP_ALL},
|
||||
{TOK_P_MAKENSIS,_T("!makensis"),1,2,_T("parameters [<OP retval> | <retvalsymbol>]"),TP_ALL},
|
||||
|
|
|
@ -117,6 +117,7 @@ enum
|
|||
TOK_P_UNDEF,
|
||||
TOK_P_PACKEXEHEADER,
|
||||
TOK_P_FINALIZE,
|
||||
TOK_P_UNINSTFINALIZE,
|
||||
TOK_P_SYSTEMEXEC,
|
||||
TOK_P_EXECUTE,
|
||||
TOK_P_MAKENSIS,
|
||||
|
|
|
@ -714,6 +714,15 @@ char* create_file_view_readonly(const TCHAR *filepath, FILEVIEW&mmfv)
|
|||
#endif
|
||||
}
|
||||
|
||||
size_t write_octets_to_file(const TCHAR *filename, const void *data, size_t cb)
|
||||
{
|
||||
FILE *hfile = FOPEN(filename, ("wb"));
|
||||
if (!hfile) return 0;
|
||||
size_t ret = fwrite(data, 1, cb, hfile);
|
||||
fclose(hfile);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TCHAR* create_tempfile_path()
|
||||
{
|
||||
TCHAR *tfpath = NULL;
|
||||
|
|
|
@ -287,6 +287,8 @@ typedef struct { char*base; size_t internal; } FILEVIEW;
|
|||
void close_file_view(FILEVIEW&mmfv);
|
||||
char* create_file_view_readonly(const TCHAR *filepath, FILEVIEW&mmfv);
|
||||
|
||||
size_t write_octets_to_file(const TCHAR *filename, const void *data, size_t cb);
|
||||
|
||||
// round a value up to be a multiple of 512
|
||||
// assumption: T is an int type
|
||||
template <class T> inline T align_to_512(const T x) { return (x+511) & ~511; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue