
The official plugins are now stored in architecture specific subdirectories under NSIS\Plugins. !AddPluginDir also gained a new (optional) architecture flag because MakeNSIS now stores separate plugin information for each target architecture. Storing plugins in the root of the Plugins directory is no longer supported. MinGW does not implement the unicode CRT startup functions so the entry point functions and linker parameters had to be changed. The unicode tools use the ansi entry point and a small helper function that calls into the real code: _tmain has full argc+argv emulation while wWinMain does not pass the command line parameters. The stubs do not use any CRT functions and have no CRT or unicode helper code, they call our entry point directly. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6269 212acab6-be3b-0410-9dea-997c60f758d6
6863 lines
226 KiB
C++
6863 lines
226 KiB
C++
/*
|
|
* script.cpp
|
|
*
|
|
* This file is a part of NSIS.
|
|
*
|
|
* Copyright (C) 1999-2009 Nullsoft and Contributors
|
|
*
|
|
* 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.
|
|
*
|
|
* Unicode support by Jim Park -- 08/09/2007
|
|
*/
|
|
|
|
#include "Platform.h"
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include "tokens.h"
|
|
#include "build.h"
|
|
#include "util.h"
|
|
#include "winchar.h"
|
|
#include "ResourceEditor.h"
|
|
#include "DialogTemplate.h"
|
|
#include "lang.h"
|
|
#include "dirreader.h"
|
|
#include <nsis-version.h>
|
|
#include "icon.h"
|
|
#include "exehead/api.h"
|
|
#include "exehead/resource.h"
|
|
#include <cassert> // for assert(3)
|
|
#include <time.h>
|
|
#include "tstring.h"
|
|
#include "utf.h"
|
|
#include <algorithm>
|
|
#include "boost/scoped_ptr.hpp"
|
|
|
|
using namespace std;
|
|
|
|
#ifdef _WIN32
|
|
# include <direct.h> // for chdir
|
|
#else
|
|
# include <sys/stat.h> // for stat and umask
|
|
# include <sys/types.h> // for mode_t
|
|
# include <fcntl.h> // for O_RDONLY
|
|
# include <unistd.h>
|
|
# include <stdlib.h> // for mkstemp
|
|
#endif
|
|
|
|
#define MAX_INCLUDEDEPTH 10
|
|
#define MAX_LINELENGTH 16384
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
TCHAR *CEXEBuild::set_file_predefine(const TCHAR *filename)
|
|
{
|
|
TCHAR *oldfileinfo = NULL;
|
|
TCHAR *oldfilename = definedlist.find(_T("__FILE__"));
|
|
TCHAR *oldfiledir = definedlist.find(_T("__FILEDIR__"));
|
|
if(oldfilename && oldfiledir)
|
|
{
|
|
oldfileinfo = new TCHAR[_tcslen(oldfilename)+_tcslen(oldfiledir)+2];
|
|
_tcscpy(oldfileinfo, oldfilename);
|
|
_tcscat(oldfileinfo, _T("|"));
|
|
_tcscat(oldfileinfo, oldfiledir);
|
|
definedlist.del(_T("__FILE__"));
|
|
definedlist.del(_T("__FILEDIR__"));
|
|
}
|
|
const TCHAR *p = _tcsrchr(filename,_T('\\'));
|
|
if(p) {
|
|
p++;
|
|
}
|
|
else {
|
|
p = filename;
|
|
}
|
|
definedlist.add(_T("__FILE__"),p);
|
|
TCHAR dir[MAX_PATH];
|
|
#ifdef _WIN32
|
|
LPTSTR lpFilePart;
|
|
GetFullPathName(filename, COUNTOF(dir), dir, &lpFilePart);
|
|
PathRemoveFileSpec(dir);
|
|
#else
|
|
if (p == filename)
|
|
_tcscpy(dir, _T("."));
|
|
else
|
|
_tcsncpy(dir, filename, p-filename-1);
|
|
#endif
|
|
definedlist.add(_T("__FILEDIR__"),dir);
|
|
|
|
return oldfileinfo;
|
|
}
|
|
|
|
void CEXEBuild::restore_file_predefine(TCHAR *oldfilename)
|
|
{
|
|
definedlist.del(_T("__FILEDIR__"));
|
|
definedlist.del(_T("__FILE__"));
|
|
if(oldfilename) {
|
|
TCHAR *oldfiledir = _tcschr(oldfilename, _T('|'));
|
|
definedlist.add(_T("__FILEDIR__"),oldfiledir+1);
|
|
*oldfiledir = '\0';
|
|
definedlist.add(_T("__FILE__"),oldfilename);
|
|
delete[] oldfilename;
|
|
}
|
|
}
|
|
|
|
TCHAR *CEXEBuild::set_timestamp_predefine(const TCHAR *filename)
|
|
{
|
|
TCHAR *oldtimestamp = definedlist.find(_T("__TIMESTAMP__"));
|
|
if(oldtimestamp) {
|
|
oldtimestamp = _tcsdup(oldtimestamp);
|
|
definedlist.del(_T("__TIMESTAMP__"));
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
TCHAR timestampbuf[256] = _T("");
|
|
TCHAR datebuf[128] = _T("");
|
|
TCHAR timebuf[128] = _T("");
|
|
WIN32_FIND_DATA fd;
|
|
FILETIME floctime;
|
|
SYSTEMTIME stime;
|
|
|
|
HANDLE hSearch = FindFirstFile(filename, &fd);
|
|
if (hSearch != INVALID_HANDLE_VALUE)
|
|
{
|
|
FindClose(hSearch);
|
|
|
|
FileTimeToLocalFileTime(&fd.ftLastWriteTime, &floctime);
|
|
FileTimeToSystemTime(&floctime, &stime);
|
|
|
|
GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &stime, NULL, datebuf, COUNTOF(datebuf));
|
|
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, timebuf, COUNTOF(timebuf));
|
|
wsprintf(timestampbuf,_T("%s %s"),datebuf,timebuf);
|
|
|
|
definedlist.add(_T("__TIMESTAMP__"),timestampbuf);
|
|
}
|
|
#else
|
|
struct stat st;
|
|
if (!stat(filename, &st))
|
|
definedlist.add(_T("__TIMESTAMP__"),_tctime(&st.st_mtime));
|
|
#endif
|
|
|
|
return oldtimestamp;
|
|
}
|
|
|
|
void CEXEBuild::restore_timestamp_predefine(TCHAR *oldtimestamp)
|
|
{
|
|
definedlist.del(_T("__TIMESTAMP__"));
|
|
if(oldtimestamp) {
|
|
definedlist.add(_T("__TIMESTAMP__"),oldtimestamp);
|
|
free(oldtimestamp);
|
|
}
|
|
}
|
|
|
|
TCHAR *CEXEBuild::set_line_predefine(int linecnt, BOOL is_macro)
|
|
{
|
|
TCHAR* linebuf = NULL;
|
|
MANAGE_WITH(linebuf, free);
|
|
|
|
TCHAR temp[128] = _T("");
|
|
_stprintf(temp,_T("%d"),linecnt);
|
|
|
|
TCHAR *oldline = definedlist.find(_T("__LINE__"));
|
|
if(oldline) {
|
|
oldline = _tcsdup(oldline);
|
|
definedlist.del(_T("__LINE__"));
|
|
}
|
|
if(is_macro && oldline) {
|
|
linebuf = (TCHAR *)malloc((_tcslen(oldline)+_tcslen(temp)+2)*sizeof(TCHAR));
|
|
_stprintf(linebuf,_T("%s.%s"),oldline,temp);
|
|
}
|
|
else {
|
|
linebuf = _tcsdup(temp);
|
|
}
|
|
definedlist.add(_T("__LINE__"),linebuf);
|
|
|
|
return oldline;
|
|
}
|
|
|
|
void CEXEBuild::restore_line_predefine(TCHAR *oldline)
|
|
{
|
|
definedlist.del(_T("__LINE__"));
|
|
if(oldline) {
|
|
definedlist.add(_T("__LINE__"),oldline);
|
|
free(oldline);
|
|
}
|
|
}
|
|
|
|
void CEXEBuild::set_date_time_predefines()
|
|
{
|
|
time_t etime;
|
|
struct tm * ltime;
|
|
TCHAR datebuf[128];
|
|
TCHAR timebuf[128];
|
|
|
|
time(&etime);
|
|
ltime = localtime(&etime);
|
|
#ifdef _WIN32
|
|
SYSTEMTIME stime;
|
|
stime.wYear = ltime->tm_year+1900;
|
|
stime.wMonth = ltime->tm_mon + 1;
|
|
stime.wDay = ltime->tm_mday;
|
|
stime.wHour= ltime->tm_hour;
|
|
stime.wMinute= ltime->tm_min;
|
|
stime.wSecond= ltime->tm_sec;
|
|
stime.wMilliseconds= 0;
|
|
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, datebuf, sizeof(datebuf));
|
|
definedlist.add(_T("__DATE__"),(TCHAR *)datebuf);
|
|
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, timebuf, sizeof(timebuf));
|
|
definedlist.add(_T("__TIME__"),(TCHAR *)timebuf);
|
|
#else
|
|
my_strftime(datebuf, sizeof(datebuf), _T("%x"), ltime);
|
|
definedlist.add(_T("__DATE__"),(TCHAR *)datebuf);
|
|
my_strftime(timebuf, sizeof(timebuf), _T("%X"), ltime);
|
|
definedlist.add(_T("__TIME__"),(TCHAR *)timebuf);
|
|
#endif
|
|
}
|
|
|
|
void CEXEBuild::del_date_time_predefines()
|
|
{
|
|
definedlist.del(_T("__DATE__"));
|
|
definedlist.del(_T("__TIME__"));
|
|
}
|
|
#endif
|
|
|
|
int CEXEBuild::process_script(FILE *filepointer, const TCHAR *filename, BOOL unicode)
|
|
{
|
|
linecnt = 0;
|
|
fp = filepointer;
|
|
curfilename = filename;
|
|
curfile_unicode = unicode;
|
|
|
|
if (has_called_write_output)
|
|
{
|
|
ERROR_MSG(_T("Error (process_script): write_output already called, can't continue\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
set_date_time_predefines();
|
|
TCHAR *oldfilename = set_file_predefine(curfilename);
|
|
TCHAR *oldtimestamp = set_timestamp_predefine(curfilename);
|
|
#endif
|
|
|
|
int ret=parseScript();
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
restore_file_predefine(oldfilename);
|
|
restore_timestamp_predefine(oldtimestamp);
|
|
del_date_time_predefines();
|
|
#endif
|
|
|
|
fp = 0;
|
|
curfilename = 0;
|
|
curfile_unicode = FALSE;
|
|
|
|
if (m_linebuild.getlen())
|
|
{
|
|
ERROR_MSG(_T("Error: invalid script: last line ended with \\\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (ret == PS_EOF && num_ifblock())
|
|
{
|
|
ERROR_MSG(_T("!if[macro][n]def: open at EOF - need !endif\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#define PRINTHELP() { print_help(line.gettoken_str(0)); return PS_ERROR; }
|
|
|
|
void CEXEBuild::start_ifblock()
|
|
{
|
|
ifblock ib = {0, };
|
|
if (cur_ifblock)
|
|
ib.inherited_ignore = cur_ifblock->ignore || cur_ifblock->inherited_ignore;
|
|
int num = build_preprocessor_data.getlen() / sizeof(ifblock);
|
|
build_preprocessor_data.add(&ib, sizeof(ifblock));
|
|
cur_ifblock = (ifblock *) build_preprocessor_data.get() + num;
|
|
}
|
|
|
|
void CEXEBuild::end_ifblock()
|
|
{
|
|
if (build_preprocessor_data.getlen())
|
|
{
|
|
cur_ifblock--;
|
|
build_preprocessor_data.resize(build_preprocessor_data.getlen() - sizeof(ifblock));
|
|
if (!build_preprocessor_data.getlen())
|
|
cur_ifblock = 0;
|
|
}
|
|
}
|
|
|
|
int CEXEBuild::num_ifblock()
|
|
{
|
|
return build_preprocessor_data.getlen() / sizeof(ifblock);
|
|
}
|
|
|
|
// Func size: just under 200 lines (orip)
|
|
int CEXEBuild::doParse(const TCHAR *str)
|
|
{
|
|
LineParser line(inside_comment);
|
|
int res;
|
|
|
|
while (*str == _T(' ') || *str == _T('\t')) str++;
|
|
|
|
// remove trailing slash and null, if there's a previous line
|
|
if (m_linebuild.getlen()>1)
|
|
m_linebuild.resize(m_linebuild.getlen()-(2*sizeof(TCHAR)));
|
|
|
|
// warn of comment with line-continuation
|
|
if (m_linebuild.getlen())
|
|
{
|
|
LineParser prevline(inside_comment);
|
|
prevline.parse((TCHAR*)m_linebuild.get());
|
|
LineParser thisline(inside_comment);
|
|
thisline.parse((TCHAR*)str);
|
|
|
|
if (prevline.inComment() && !thisline.inComment())
|
|
{
|
|
warning_fl(_T("comment contains line-continuation character, following line will be ignored"));
|
|
}
|
|
}
|
|
|
|
// add new line to line buffer
|
|
m_linebuild.add(str,(_tcslen(str)+1)*sizeof(TCHAR));
|
|
|
|
// keep waiting for more lines, if this line ends with a backslash
|
|
if (str[0] && CharPrev(str,str+_tcslen(str))[0] == _T('\\'))
|
|
{
|
|
return PS_OK;
|
|
}
|
|
|
|
// parse before checking if the line should be ignored, so block comments won't be missed
|
|
|
|
// escaped quotes should be ignored for compile time commands that set defines
|
|
// because defines can be inserted in commands at a later stage
|
|
bool ignore_escaping = (!_tcsnicmp((TCHAR*)m_linebuild.get(),_T("!define"),7) || !_tcsncicmp((TCHAR*)m_linebuild.get(),_T("!insertmacro"),12));
|
|
res=line.parse((TCHAR*)m_linebuild.get(), ignore_escaping);
|
|
|
|
inside_comment = line.inCommentBlock();
|
|
|
|
// if ignoring, ignore all lines that don't begin with an exclamation mark
|
|
{
|
|
bool ignore_line = cur_ifblock && (cur_ifblock->ignore || cur_ifblock->inherited_ignore);
|
|
TCHAR first_char = *(TCHAR *) m_linebuild.get();
|
|
if (ignore_line && (first_char!=_T('!') || !is_valid_token(line.gettoken_str(0))))
|
|
{
|
|
m_linebuild.resize(0);
|
|
return PS_OK;
|
|
}
|
|
}
|
|
|
|
m_linebuild.resize(0);
|
|
|
|
if (res)
|
|
{
|
|
if (res==-2) ERROR_MSG(_T("Error: unterminated string parsing line at %s:%d\n"),curfilename,linecnt);
|
|
else ERROR_MSG(_T("Error: error parsing line (%s:%d)\n"),curfilename,linecnt);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
parse_again:
|
|
if (line.getnumtokens() < 1) return PS_OK;
|
|
|
|
int np,op,pos;
|
|
int tkid=get_commandtoken(line.gettoken_str(0),&np,&op,&pos);
|
|
if (tkid == -1)
|
|
{
|
|
TCHAR *p=line.gettoken_str(0);
|
|
if (p[0] && p[_tcslen(p)-1]==_T(':'))
|
|
{
|
|
if (p[0] == _T('!') || (p[0] >= _T('0') && p[0] <= _T('9')) || p[0] == _T('$') || p[0] == _T('-') || p[0] == _T('+'))
|
|
{
|
|
ERROR_MSG(_T("Invalid label: %s (labels cannot begin with !, $, -, +, or 0-9)\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
if (add_label(line.gettoken_str(0))) return PS_ERROR;
|
|
line.eattoken();
|
|
goto parse_again;
|
|
}
|
|
|
|
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
|
// Added by Ximon Eighteen 5th August 2002
|
|
// We didn't recognise this command, could it be the name of a
|
|
// function exported from a dll?
|
|
// Plugins cannot be called in global scope so there is no need to initialize the list first
|
|
if (m_pPlugins && m_pPlugins->IsPluginCommand(line.gettoken_str(0)))
|
|
{
|
|
np = 0; // parameters are optional
|
|
op = -1; // unlimited number of optional parameters
|
|
pos = -1; // placement will tested later
|
|
tkid = TOK__PLUGINCOMMAND;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
ERROR_MSG(_T("Invalid command: %s\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
|
|
if (IsTokenPlacedRight(pos, line.gettoken_str(0)) != PS_OK)
|
|
return PS_ERROR;
|
|
|
|
int v=line.getnumtokens()-(np+1);
|
|
if (v < 0 || (op >= 0 && v > op)) // opt_parms is -1 for unlimited
|
|
{
|
|
ERROR_MSG(_T("%s expects %d"),line.gettoken_str(0),np);
|
|
if (op < 0) ERROR_MSG(_T("+"));
|
|
if (op > 0) ERROR_MSG(_T("-%d"),op+np);
|
|
ERROR_MSG(_T(" parameters, got %d.\n"),line.getnumtokens()-1);
|
|
PRINTHELP()
|
|
}
|
|
|
|
int if_from_else = 0;
|
|
|
|
if (tkid == TOK_P_ELSE)
|
|
{
|
|
if (cur_ifblock && cur_ifblock->inherited_ignore)
|
|
return PS_OK;
|
|
|
|
if (!num_ifblock())
|
|
{
|
|
ERROR_MSG(_T("!else: no if block open (!if[macro][n][def])\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (cur_ifblock->elseused)
|
|
{
|
|
ERROR_MSG(_T("!else: else already used in current if block\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (cur_ifblock->hasexeced)
|
|
{
|
|
cur_ifblock->ignore++;
|
|
return PS_OK;
|
|
}
|
|
|
|
if (line.getnumtokens() == 1)
|
|
{
|
|
cur_ifblock->ignore = !cur_ifblock->ignore;
|
|
// if not executed up until now, it will now
|
|
cur_ifblock->hasexeced++;
|
|
cur_ifblock->elseused++;
|
|
return PS_OK;
|
|
}
|
|
|
|
line.eattoken();
|
|
|
|
int v=line.gettoken_enum(0,_T("if\0ifdef\0ifndef\0ifmacrodef\0ifmacrondef\0"));
|
|
if (v < 0) PRINTHELP()
|
|
if (line.getnumtokens() == 1) PRINTHELP()
|
|
int cmds[] = {TOK_P_IF, TOK_P_IFDEF, TOK_P_IFNDEF, TOK_P_IFMACRODEF, TOK_P_IFMACRONDEF};
|
|
tkid = cmds[v];
|
|
if_from_else++;
|
|
}
|
|
|
|
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF ||
|
|
tkid == TOK_P_IFMACRODEF || tkid == TOK_P_IFMACRONDEF ||
|
|
tkid == TOK_P_IF)
|
|
{
|
|
if (!if_from_else)
|
|
start_ifblock();
|
|
|
|
if (cur_ifblock && cur_ifblock->inherited_ignore)
|
|
{
|
|
return PS_OK;
|
|
}
|
|
|
|
int istrue=0;
|
|
|
|
int mod=0;
|
|
|
|
int p=0;
|
|
|
|
if (tkid == TOK_P_IF) {
|
|
if(!_tcscmp(line.gettoken_str(1),_T("!"))) {
|
|
p = 1;
|
|
line.eattoken();
|
|
}
|
|
|
|
if(line.getnumtokens() == 2)
|
|
istrue = line.gettoken_int(1);
|
|
|
|
else if (line.getnumtokens() == 3) {
|
|
if (!_tcsicmp(line.gettoken_str(1),_T("/fileexists"))) {
|
|
TCHAR *fc = my_convert(line.gettoken_str(2));
|
|
tstring dir = get_dir_name(fc), spec = get_file_name(fc);
|
|
my_convert_free(fc);
|
|
if (dir == spec) dir = _T(".");
|
|
|
|
boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
|
|
dr->hack_simpleexcluded().erase(_T("."));
|
|
dr->read(dir);
|
|
|
|
for (dir_reader::iterator fit = dr->files().begin();
|
|
fit != dr->files().end() && !istrue; fit++)
|
|
{
|
|
if (dir_reader::matches(*fit, spec)) istrue = true;
|
|
}
|
|
if (!istrue) for (dir_reader::iterator dit = dr->dirs().begin();
|
|
dit != dr->dirs().end() && !istrue; dit++)
|
|
{
|
|
if (dir_reader::matches(*dit, spec)) istrue = true;
|
|
}
|
|
}
|
|
else PRINTHELP()
|
|
}
|
|
|
|
else if (line.getnumtokens() == 4) {
|
|
mod = line.gettoken_enum(2,
|
|
_T("==\0!=\0S==\0S!=\0")
|
|
_T("=\0<>\0<=\0<\0>\0>=\0")
|
|
_T("&\0&&\0|\0||\0")
|
|
);
|
|
|
|
int cnv1 = 1, cnv2 = 1;
|
|
switch(mod) {
|
|
case 0:
|
|
istrue = _tcsicmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break;
|
|
case 1:
|
|
istrue = _tcsicmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break;
|
|
case 2:
|
|
istrue = _tcscmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break;
|
|
case 3:
|
|
istrue = _tcscmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break;
|
|
case 4:
|
|
istrue = line.gettoken_number(1,&cnv1) == line.gettoken_number(3,&cnv2); break;
|
|
case 5:
|
|
istrue = line.gettoken_number(1,&cnv1) != line.gettoken_number(3,&cnv2); break;
|
|
case 6:
|
|
istrue = line.gettoken_number(1,&cnv1) <= line.gettoken_number(3,&cnv2); break;
|
|
case 7:
|
|
istrue = line.gettoken_number(1,&cnv1) < line.gettoken_number(3,&cnv2); break;
|
|
case 8:
|
|
istrue = line.gettoken_number(1,&cnv1) > line.gettoken_number(3,&cnv2); break;
|
|
case 9:
|
|
istrue = line.gettoken_number(1,&cnv1) >= line.gettoken_number(3,&cnv2); break;
|
|
case 10:
|
|
istrue = (line.gettoken_int(1,&cnv1) & line.gettoken_int(3,&cnv2)) != 0; break;
|
|
case 11:
|
|
istrue = line.gettoken_int(1,&cnv1) && line.gettoken_int(3,&cnv2); break;
|
|
case 12:
|
|
case 13:
|
|
istrue = line.gettoken_int(1,&cnv1) || line.gettoken_int(3,&cnv2); break;
|
|
default:
|
|
PRINTHELP()
|
|
}
|
|
if (!cnv1 || !cnv2) {
|
|
warning_fl(_T("Invalid number: \"%s\""), line.gettoken_str(!cnv1 ? 1 : 3));
|
|
}
|
|
}
|
|
else PRINTHELP()
|
|
|
|
if(p) istrue = !istrue;
|
|
}
|
|
|
|
else {
|
|
|
|
// pure left to right precedence. Not too powerful, but useful.
|
|
for (p = 1; p < line.getnumtokens(); p ++)
|
|
{
|
|
if (p & 1)
|
|
{
|
|
int new_s;
|
|
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF)
|
|
new_s=!!definedlist.find(line.gettoken_str(p));
|
|
else
|
|
new_s=MacroExists(line.gettoken_str(p));
|
|
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFMACRONDEF)
|
|
new_s=!new_s;
|
|
|
|
if (mod == 0) istrue = istrue || new_s;
|
|
else istrue = istrue && new_s;
|
|
}
|
|
else
|
|
{
|
|
mod=line.gettoken_enum(p,_T("|\0&\0||\0&&\0"));
|
|
if (mod == -1) PRINTHELP()
|
|
mod &= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (istrue)
|
|
{
|
|
cur_ifblock->hasexeced++;
|
|
cur_ifblock->ignore = 0;
|
|
}
|
|
else
|
|
cur_ifblock->ignore++;
|
|
|
|
return PS_OK;
|
|
}
|
|
if (tkid == TOK_P_ENDIF) {
|
|
if (!num_ifblock())
|
|
{
|
|
ERROR_MSG(_T("!endif: no if block open (!if[macro][n][def])\n"));
|
|
return PS_ERROR;
|
|
}
|
|
end_ifblock();
|
|
return PS_OK;
|
|
}
|
|
if (!cur_ifblock || (!cur_ifblock->ignore && !cur_ifblock->inherited_ignore))
|
|
{
|
|
return doCommand(tkid,line);
|
|
}
|
|
|
|
return PS_OK;
|
|
}
|
|
|
|
// Func size: about 140 lines (orip)
|
|
#ifdef NSIS_FIX_DEFINES_IN_STRINGS
|
|
void CEXEBuild::ps_addtoline(const TCHAR *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines /*= false*/)
|
|
#else
|
|
void CEXEBuild::ps_addtoline(const TCHAR *str, GrowBuf &linedata, StringList &hist)
|
|
#endif
|
|
{
|
|
// convert $\r, $\n to their literals
|
|
// preprocessor replace ${VAR} and $%VAR% with whatever value
|
|
// note that if VAR does not exist, ${VAR} or $%VAR% will go through unmodified
|
|
const TCHAR *in=str;
|
|
while (*in)
|
|
{
|
|
int add=1;
|
|
TCHAR *t;
|
|
TCHAR c=*in;
|
|
t=CharNext(in);
|
|
|
|
if (t-in > 1) // handle multibyte chars (no escape)
|
|
{
|
|
linedata.add((void*)in,(t-in)*sizeof(TCHAR));
|
|
in=t;
|
|
continue;
|
|
}
|
|
in=t;
|
|
|
|
if (c == _T('$'))
|
|
{
|
|
if (in[0] == _T('\\'))
|
|
{
|
|
if (in[1] == _T('r'))
|
|
{
|
|
in+=2;
|
|
c=_T('\r');
|
|
}
|
|
else if (in[1] == _T('n'))
|
|
{
|
|
in+=2;
|
|
c=_T('\n');
|
|
}
|
|
else if (in[1] == _T('t'))
|
|
{
|
|
in+=2;
|
|
c=_T('\t');
|
|
}
|
|
}
|
|
else if (in[0] == _T('{'))
|
|
{
|
|
TCHAR *s=_tcsdup(in+1);
|
|
MANAGE_WITH(s, free);
|
|
TCHAR *t=s;
|
|
unsigned int bn = 0;
|
|
while (*t)
|
|
{
|
|
if (*t == _T('{')) bn++;
|
|
if (*t == _T('}') && bn-- == 0) break;
|
|
t=CharNext(t);
|
|
}
|
|
if (*t && t!=s
|
|
#ifdef NSIS_FIX_DEFINES_IN_STRINGS
|
|
&& !bIgnoreDefines
|
|
#endif
|
|
)
|
|
{
|
|
*t=0;
|
|
// check for defines inside the define name - ${bla${blo}}
|
|
GrowBuf defname;
|
|
ps_addtoline(s,defname,hist);
|
|
defname.add(_T(""),sizeof(_T("")));
|
|
t=definedlist.find((TCHAR*)defname.get());
|
|
if (t && hist.find((TCHAR*)defname.get(),0)<0)
|
|
{
|
|
in+=_tcslen(s)+2;
|
|
add=0;
|
|
hist.add((TCHAR*)defname.get(),0);
|
|
#ifdef NSIS_FIX_DEFINES_IN_STRINGS
|
|
ps_addtoline(t,linedata,hist,true);
|
|
#else
|
|
ps_addtoline(t,linedata,hist);
|
|
#endif
|
|
hist.delbypos(hist.find((TCHAR*)defname.get(),0));
|
|
}
|
|
}
|
|
}
|
|
else if (in[0] == _T('%'))
|
|
{
|
|
TCHAR *s=_tcsdup(in+1);
|
|
MANAGE_WITH(s, free);
|
|
TCHAR *t=s;
|
|
while (*t)
|
|
{
|
|
if (*t == _T('%')) break;
|
|
t=CharNext(t);
|
|
}
|
|
if (*t && t!=s)
|
|
{
|
|
*t=0;
|
|
// check for defines inside the define name - ${bla${blo}}
|
|
GrowBuf defname;
|
|
ps_addtoline(s,defname,hist);
|
|
defname.add(_T(""),sizeof(_T("")));
|
|
t=_tgetenv((TCHAR*)defname.get());
|
|
if (t && hist.find((TCHAR*)defname.get(),0)<0)
|
|
{
|
|
in+=_tcslen(s)+2;
|
|
add=0;
|
|
hist.add((TCHAR*)defname.get(),0);
|
|
#ifdef NSIS_FIX_DEFINES_IN_STRINGS
|
|
ps_addtoline(t,linedata,hist,true);
|
|
#else
|
|
ps_addtoline(t,linedata,hist);
|
|
#endif
|
|
hist.delbypos(hist.find((TCHAR*)defname.get(),0));
|
|
}
|
|
}
|
|
}
|
|
#ifdef NSIS_FIX_DEFINES_IN_STRINGS
|
|
else if (in[0] == _T('$'))
|
|
{
|
|
if (in[1] == _T('{')) // Found $$ before - Don't replace this define
|
|
{
|
|
TCHAR *s=_tcsdup(in+2);
|
|
MANAGE_WITH(s, free);
|
|
TCHAR *t=s;
|
|
unsigned int bn = 0;
|
|
while (*t)
|
|
{
|
|
if (*t == _T('{')) bn++;
|
|
if (*t == _T('}') && bn-- == 0) break;
|
|
t=CharNext(t);
|
|
}
|
|
if (*t && t!=s)
|
|
{
|
|
*t=0;
|
|
// add text unchanged
|
|
GrowBuf defname;
|
|
ps_addtoline(s,defname,hist);
|
|
in++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
linedata.add((void*)&c,1*sizeof(TCHAR));
|
|
in++;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
if (add) linedata.add((void*)&c,1*sizeof(TCHAR));
|
|
}
|
|
}
|
|
|
|
int CEXEBuild::parseScript()
|
|
{
|
|
TCHAR str[MAX_LINELENGTH];
|
|
|
|
for (;;)
|
|
{
|
|
TCHAR *p=str;
|
|
*p=0;
|
|
_fgetts(str,MAX_LINELENGTH,fp);
|
|
linecnt++;
|
|
if (feof(fp)&&!str[0]) break;
|
|
|
|
// remove trailing whitespace
|
|
while (*p) p++;
|
|
if (p > str) p--;
|
|
while (p >= str && (*p == _T('\r') || *p == _T('\n') || *p == _T(' ') || *p == _T('\t'))) p--;
|
|
*++p=0;
|
|
|
|
StringList hist;
|
|
GrowBuf linedata;
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
TCHAR *oldline = set_line_predefine(linecnt, FALSE);
|
|
#endif
|
|
|
|
ps_addtoline(str,linedata,hist);
|
|
linedata.add(_T(""),sizeof(_T("")));
|
|
int ret=doParse((TCHAR*)linedata.get());
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
restore_line_predefine(oldline);
|
|
#endif
|
|
|
|
if (ret != PS_OK) return ret;
|
|
}
|
|
|
|
return PS_EOF;
|
|
}
|
|
|
|
int CEXEBuild::includeScript(TCHAR *f)
|
|
{
|
|
SCRIPT_MSG(_T("!include: \"%s\"\n"),f);
|
|
BOOL unicode;
|
|
FILE *incfp=FOPENTEXT2(f,"rt",&unicode);
|
|
if (!incfp)
|
|
{
|
|
ERROR_MSG(_T("!include: could not open file: \"%s\"\n"),f);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
// auto-fclose(3) incfp
|
|
MANAGE_WITH(incfp, fclose);
|
|
|
|
if (build_include_depth >= MAX_INCLUDEDEPTH)
|
|
{
|
|
ERROR_MSG(_T("parseScript: too many levels of includes (%d max).\n"),MAX_INCLUDEDEPTH);
|
|
return PS_ERROR;
|
|
}
|
|
build_include_depth++;
|
|
#ifndef _UNICODE
|
|
const bool org_build_include_isutf8 = build_include_isutf8;
|
|
build_include_isutf8 = IsUTF8BOM(incfp);
|
|
#endif
|
|
|
|
int last_linecnt=linecnt;
|
|
linecnt=0;
|
|
const TCHAR *last_filename=curfilename;
|
|
BOOL last_unicode=curfile_unicode;
|
|
curfilename=f;
|
|
curfile_unicode=unicode;
|
|
FILE *last_fp=fp;
|
|
fp=incfp;
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
TCHAR *oldfilename = set_file_predefine(curfilename);
|
|
TCHAR *oldtimestamp = set_timestamp_predefine(curfilename);
|
|
#endif
|
|
|
|
int r=parseScript();
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
restore_file_predefine(oldfilename);
|
|
restore_timestamp_predefine(oldtimestamp);
|
|
#endif
|
|
|
|
#ifndef _UNICODE
|
|
build_include_isutf8 = org_build_include_isutf8;
|
|
#endif
|
|
|
|
int errlinecnt=linecnt;
|
|
|
|
linecnt=last_linecnt;
|
|
curfilename=last_filename;
|
|
curfile_unicode=last_unicode;
|
|
fp=last_fp;
|
|
|
|
build_include_depth--;
|
|
if (r != PS_EOF && r != PS_OK)
|
|
{
|
|
ERROR_MSG(_T("!include: error in script: \"%s\" on line %d\n"),f,errlinecnt);
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("!include: closed: \"%s\"\n"),f);
|
|
return PS_OK;
|
|
}
|
|
|
|
// !ifmacro[n]def based on Anders Kjersem's code
|
|
int CEXEBuild::MacroExists(const TCHAR *macroname)
|
|
{
|
|
TCHAR *m = (TCHAR *) m_macros.get();
|
|
|
|
while (m && *m)
|
|
{
|
|
// check if macroname matches
|
|
if (!_tcsicmp(m, macroname))
|
|
return 1;
|
|
|
|
// skip macro name
|
|
m += _tcslen(m) + 1;
|
|
|
|
// skip params
|
|
while (*m) m += _tcslen(m) + 1;
|
|
m++;
|
|
|
|
// skip data
|
|
while (*m) m += _tcslen(m) + 1;
|
|
if (m - (TCHAR *) m_macros.get() >= m_macros.getlen() - 1) break;
|
|
m++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CEXEBuild::LoadLicenseFile(TCHAR *file, TCHAR** pdata, LineParser &line, BOOL* unicode) // caller must free *pdata, even on error result
|
|
{
|
|
FILE *fp=FOPENTEXT2(file,"rt",unicode);
|
|
if (!fp)
|
|
{
|
|
ERROR_MSG(_T("%s: open failed \"%s\"\n"),line.gettoken_str(0),file);
|
|
PRINTHELP()
|
|
}
|
|
MANAGE_WITH(fp, fclose);
|
|
unsigned int beginning=ftell(fp); // (we might be positionned after a BOM)
|
|
fseek(fp,0,SEEK_END);
|
|
unsigned int datalen=ftell(fp)-beginning; // size of file in bytes! not a number of characters
|
|
if (!datalen)
|
|
{
|
|
ERROR_MSG(_T("%s: empty license file \"%s\"\n"),line.gettoken_str(0),file);
|
|
return PS_ERROR;
|
|
}
|
|
fseek(fp,beginning,SEEK_SET);
|
|
TCHAR *data=(TCHAR*)malloc((datalen+2)*sizeof(TCHAR)); // alloc enough for worst-case scenario (ANSI/UTF8 characters read in WCHARs)
|
|
if (!data)
|
|
{
|
|
ERROR_MSG(_T("Internal compiler error #12345: %s malloc(%d) failed.\n"),line.gettoken_str(0),(datalen+2)*sizeof(TCHAR));
|
|
return PS_ERROR;
|
|
}
|
|
*pdata = data; // memory will be released by caller
|
|
TCHAR *ldata=data+1;
|
|
while (_fgetts(ldata, data+datalen+2-ldata, fp)) // _fgetts translates ANSI/UTF8 characters to TCHAR //BUGBUG: There is no reason to store ASCII files as TCHAR
|
|
ldata += _tcslen(ldata);
|
|
if (ferror(fp))
|
|
{
|
|
ERROR_MSG(_T("%s: can't read file.\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
bool disallowrichedunicode = false;
|
|
#ifdef _UNICODE
|
|
if (!build_unicode)
|
|
disallowrichedunicode = true; //RichEdit 1.0 does not support unicode
|
|
else
|
|
*unicode = true; // _fgetts converted to TCHAR
|
|
#endif
|
|
if (!memcmp(data+1,_T("{\\rtf"),5*sizeof(TCHAR)))
|
|
*data = SF_RTF;
|
|
else if (*unicode && !disallowrichedunicode)
|
|
*data = SF_TEXT|SF_UNICODE;
|
|
else
|
|
*data = SF_TEXT;
|
|
return PS_OK;
|
|
}
|
|
|
|
int CEXEBuild::process_oneline(TCHAR *line, const TCHAR *filename, int linenum)
|
|
{
|
|
const TCHAR *last_filename=curfilename;
|
|
curfilename=filename;
|
|
int last_linecnt=linecnt;
|
|
linecnt=linenum;
|
|
|
|
StringList hist;
|
|
GrowBuf linedata;
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
TCHAR *oldfilename = NULL;
|
|
TCHAR *oldtimestamp = NULL;
|
|
TCHAR *oldline = NULL;
|
|
BOOL is_commandline = !_tcscmp(filename,_T("command line"));
|
|
BOOL is_macro = !_tcsncmp(filename,_T("macro:"),_tcslen(_T("macro:")));
|
|
|
|
if(!is_commandline) { // Don't set the predefines for command line /X option
|
|
if(!is_macro) {
|
|
oldfilename = set_file_predefine(curfilename);
|
|
oldtimestamp = set_timestamp_predefine(curfilename);
|
|
}
|
|
oldline = set_line_predefine(linecnt, is_macro);
|
|
}
|
|
#endif
|
|
|
|
ps_addtoline(line,linedata,hist);
|
|
linedata.add(_T(""),sizeof(_T("")));
|
|
int ret=doParse((TCHAR*)linedata.get());
|
|
|
|
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
|
// Added by Sunil Kamath 11 June 2003
|
|
if(!is_commandline) { // Don't set the predefines for command line /X option
|
|
if(!is_macro) {
|
|
restore_file_predefine(oldfilename);
|
|
restore_timestamp_predefine(oldtimestamp);
|
|
}
|
|
restore_line_predefine(oldline);
|
|
}
|
|
#endif
|
|
|
|
linecnt=last_linecnt;
|
|
curfilename=last_filename;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int CEXEBuild::process_jump(LineParser &line, int wt, int *offs)
|
|
{
|
|
const TCHAR *s=line.gettoken_str(wt);
|
|
int v;
|
|
|
|
if (!_tcsicmp(s,_T("0")) || !_tcsicmp(s,_T(""))) *offs=0;
|
|
else if ((v=GetUserVarIndex(line, wt))>=0)
|
|
{
|
|
*offs=-v-1; // to jump to a user variable target, -variable_index-1 is stored.
|
|
}
|
|
else
|
|
{
|
|
if ((s[0] == _T('-') || s[0] == _T('+')) && !_ttoi(s+1))
|
|
{
|
|
ERROR_MSG(_T("Error: Goto targets beginning with '+' or '-' must be followed by nonzero integer (relative jump)\n"));
|
|
return 1;
|
|
}
|
|
if ((s[0] >= _T('0') && s[0] <= _T('9')) || s[0] == _T('$') || s[0] == _T('!'))
|
|
{
|
|
ERROR_MSG(_T("Error: Goto targets cannot begin with 0-9, $, !\n"));
|
|
return 1;
|
|
}
|
|
*offs=ns_label.add(s,0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define SECTION_FIELD_GET(field) (FIELD_OFFSET(section, field)/sizeof(int))
|
|
#define SECTION_FIELD_SET(field) (-1 - (int)(FIELD_OFFSET(section, field)/sizeof(int)))
|
|
|
|
// Func size: about 5000 lines (orip)
|
|
int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|
{
|
|
static const TCHAR *rootkeys[2] = {
|
|
_T("HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0SHCTX\0"),
|
|
_T("HKEY_CLASSES_ROOT\0HKEY_LOCAL_MACHINE\0HKEY_CURRENT_USER\0HKEY_USERS\0HKEY_CURRENT_CONFIG\0HKEY_DYN_DATA\0HKEY_PERFORMANCE_DATA\0SHELL_CONTEXT\0")
|
|
};
|
|
static HKEY rootkey_tab[] = {
|
|
HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA,0
|
|
};
|
|
|
|
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
|
if (PS_OK != initialize_default_plugins()) return PS_ERROR;
|
|
#endif
|
|
|
|
multiple_entries_instruction=0;
|
|
|
|
entry ent={0,};
|
|
switch (which_token)
|
|
{
|
|
// macro stuff
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
case TOK_P_MACRO:
|
|
{
|
|
if (!line.gettoken_str(1)[0]) PRINTHELP()
|
|
TCHAR *t=(TCHAR *)m_macros.get();
|
|
while (t && *t)
|
|
{
|
|
if (!_tcsicmp(t,line.gettoken_str(1))) break;
|
|
t+=_tcslen(t)+1;
|
|
|
|
// advance over parameters
|
|
while (*t) t+=_tcslen(t)+1;
|
|
t++;
|
|
|
|
// advance over data
|
|
while (*t) t+=_tcslen(t)+1;
|
|
if (t-(TCHAR *)m_macros.get() >= m_macros.getlen()-1)
|
|
break;
|
|
t++;
|
|
}
|
|
if (t && *t)
|
|
{
|
|
ERROR_MSG(_T("!macro: macro named \"%s\" already found!\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
m_macros.add(line.gettoken_str(1),(_tcslen(line.gettoken_str(1))+1)*sizeof(TCHAR));
|
|
|
|
int pc;
|
|
for (pc=2; pc < line.getnumtokens(); pc ++)
|
|
{
|
|
if (!line.gettoken_str(pc)[0])
|
|
{
|
|
ERROR_MSG(_T("!macro: macro parameter %d is empty, not valid!\n"),pc-1);
|
|
return PS_ERROR;
|
|
}
|
|
int a;
|
|
for (a=2; a < pc; a ++)
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(pc),line.gettoken_str(a)))
|
|
{
|
|
ERROR_MSG(_T("!macro: macro parameter named %s is used multiple times!\n"),
|
|
line.gettoken_str(pc));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
m_macros.add(line.gettoken_str(pc),(_tcslen(line.gettoken_str(pc))+1)*sizeof(TCHAR));
|
|
}
|
|
m_macros.add(_T(""),sizeof(_T("")));
|
|
|
|
for (;;)
|
|
{
|
|
TCHAR str[MAX_LINELENGTH];
|
|
TCHAR *p=str;
|
|
str[0]=0;
|
|
_fgetts(str,MAX_LINELENGTH,fp);
|
|
//SCRIPT_MSG(_T("%s%s"), str, str[_tcslen(str)-1]==_T('\n')?_T(""):_T("\n"));
|
|
if (feof(fp) && !str[0])
|
|
{
|
|
ERROR_MSG(_T("!macro \"%s\": unterminated (no !macroend found in file)!\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
// remove trailing whitespace
|
|
while (*p) p++;
|
|
if (p > str) p--;
|
|
while (p >= str && (*p == _T('\r') || *p == _T('\n') || *p == _T(' ') || *p == _T('\t'))) p--;
|
|
*++p=0;
|
|
LineParser l2(false);
|
|
if (!l2.parse(str))
|
|
{
|
|
if (!_tcsicmp(l2.gettoken_str(0),_T("!macroend")))
|
|
{
|
|
linecnt++;
|
|
break;
|
|
}
|
|
if (!_tcsicmp(l2.gettoken_str(0),_T("!macro")))
|
|
{
|
|
ERROR_MSG(_T("Error: can't define a macro inside a macro!\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
if (str[0]) m_macros.add(str,(_tcslen(str)+1)*sizeof(TCHAR));
|
|
else m_macros.add(_T(" "),sizeof(_T(" ")));
|
|
linecnt++;
|
|
}
|
|
m_macros.add(_T(""),sizeof(_T("")));
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_MACROEND:
|
|
ERROR_MSG(_T("!macroend: no macro currently open.\n"));
|
|
return PS_ERROR;
|
|
case TOK_P_MACROUNDEF:
|
|
{
|
|
const TCHAR* mname=line.gettoken_str(1);
|
|
if (!mname[0]) PRINTHELP()
|
|
TCHAR *t=(TCHAR *)m_macros.get(), *mbeg, *mend=0, *mbufb=t;
|
|
while (t && *t)
|
|
{
|
|
const bool foundit = !_tcsicmp((mbeg=t),mname);
|
|
t+=_tcslen(t)+1;
|
|
|
|
// advance over parameters
|
|
while (*t) t+=_tcslen(t)+1;
|
|
t++;
|
|
|
|
// advance over data
|
|
while (*t) t+=_tcslen(t)+1;
|
|
if (foundit)
|
|
{
|
|
mend=t;
|
|
break;
|
|
}
|
|
if (t-mbufb >= m_macros.getlen()-1)
|
|
break;
|
|
t++;
|
|
}
|
|
if (!mend)
|
|
{
|
|
ERROR_MSG(_T("!macroundef: \"%s\" does not exist!\n"),mname);
|
|
return PS_ERROR;
|
|
}
|
|
const unsigned int mcb=mend-mbeg, mbufcb=m_macros.getlen();
|
|
memmove(mbeg,mend+1,mbufcb-(mcb+(mbeg-mbufb)));
|
|
m_macros.resize(mbufcb-(mcb+1));
|
|
|
|
SCRIPT_MSG(_T("!macroundef: %s\n"),mname);
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_INSERTMACRO:
|
|
{
|
|
if (!line.gettoken_str(1)[0]) PRINTHELP()
|
|
TCHAR *t=(TCHAR *)m_macros.get();
|
|
TCHAR *m=t;
|
|
while (t && *t)
|
|
{
|
|
if (!_tcsicmp(t,line.gettoken_str(1))) break;
|
|
t+=_tcslen(t)+1;
|
|
|
|
// advance over parms
|
|
while (*t) t+=_tcslen(t)+1;
|
|
t++;
|
|
|
|
// advance over data
|
|
while (*t) t+=_tcslen(t)+1;
|
|
if (t-(TCHAR *)m_macros.get() >= m_macros.getlen()-1)
|
|
break;
|
|
t++;
|
|
}
|
|
SCRIPT_MSG(_T("!insertmacro: %s\n"),line.gettoken_str(1));
|
|
if (!t || !*t)
|
|
{
|
|
ERROR_MSG(_T("!insertmacro: macro named \"%s\" not found!\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
t+=_tcslen(t)+1;
|
|
|
|
|
|
GrowBuf l_define_names;
|
|
DefineList l_define_saves;
|
|
int npr=0;
|
|
// advance over parms
|
|
while (*t)
|
|
{
|
|
TCHAR *v=definedlist.find(t);
|
|
if (v)
|
|
{
|
|
l_define_saves.add(t,v);
|
|
definedlist.del(t);
|
|
}
|
|
l_define_names.add(t,(_tcslen(t)+1)*sizeof(TCHAR));
|
|
definedlist.add(t,line.gettoken_str(npr+2));
|
|
|
|
npr++;
|
|
t+=_tcslen(t)+1;
|
|
}
|
|
l_define_names.add(_T(""),sizeof(_T("")));
|
|
t++;
|
|
if (npr != line.getnumtokens()-2)
|
|
{
|
|
ERROR_MSG(_T("!insertmacro: macro \"%s\" requires %d parameter(s), passed %d!\n"),
|
|
line.gettoken_str(1),npr,line.getnumtokens()-2);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
int lp=0;
|
|
TCHAR str[1024];
|
|
if (m_macro_entry.find(line.gettoken_str(1),0)>=0)
|
|
{
|
|
ERROR_MSG(_T("!insertmacro: macro \"%s\" already being inserted!\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
int npos=m_macro_entry.add(line.gettoken_str(1),0);
|
|
|
|
wsprintf(str,_T("macro:%s"),line.gettoken_str(1));
|
|
const TCHAR* oldmacroname=m_currentmacroname;
|
|
m_currentmacroname=line.gettoken_str(1);
|
|
definedlist.del(_T("__MACRO__"));
|
|
definedlist.add(_T("__MACRO__"),m_currentmacroname);
|
|
while (*t)
|
|
{
|
|
lp++;
|
|
if (_tcscmp(t,_T(" ")))
|
|
{
|
|
int ret=process_oneline(t,str,lp);
|
|
if (ret != PS_OK)
|
|
{
|
|
ERROR_MSG(_T("Error in macro %s on macroline %d\n"),line.gettoken_str(1),lp);
|
|
return ret;
|
|
}
|
|
}
|
|
{
|
|
// fix t if process_oneline changed m_macros
|
|
TCHAR *nm=(TCHAR *)m_macros.get();
|
|
if (nm != m)
|
|
{
|
|
t += nm - m;
|
|
m = nm;
|
|
}
|
|
}
|
|
t+=_tcslen(t)+1;
|
|
}
|
|
m_macro_entry.delbypos(npos);
|
|
{
|
|
TCHAR *p=(TCHAR*)l_define_names.get();
|
|
while (*p)
|
|
{
|
|
definedlist.del(p);
|
|
TCHAR *v;
|
|
if ((v=l_define_saves.find(p))) definedlist.add(p,v);
|
|
p+=_tcslen(p)+1;
|
|
}
|
|
}
|
|
definedlist.del(_T("__MACRO__"));
|
|
m_currentmacroname = oldmacroname;
|
|
if (oldmacroname) definedlist.add(_T("__MACRO__"),oldmacroname);
|
|
SCRIPT_MSG(_T("!insertmacro: end of %s\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
|
|
// preprocessor files fun
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
case TOK_P_TEMPFILE:
|
|
{
|
|
TCHAR *symbol = line.gettoken_str(1);
|
|
TCHAR *fpath;
|
|
|
|
#ifdef _WIN32
|
|
TCHAR buf[MAX_PATH], buf2[MAX_PATH];
|
|
|
|
GetTempPath(MAX_PATH, buf);
|
|
if (!GetTempFileName(buf, _T("nst"), 0, buf2))
|
|
{
|
|
ERROR_MSG(_T("!tempfile: unable to create temporary file.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
fpath = buf2;
|
|
#else
|
|
TCHAR t[] = _T("/tmp/makensisXXXXXX");
|
|
|
|
mode_t old_umask = umask(0077);
|
|
|
|
int fd = mkstemp(t);
|
|
if (fd == -1) {
|
|
ERROR_MSG(_T("!tempfile: unable to create temporary file.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
close(fd);
|
|
|
|
umask(old_umask);
|
|
|
|
fpath = t;
|
|
#endif
|
|
|
|
if (definedlist.add(symbol, fpath))
|
|
{
|
|
ERROR_MSG(_T("!tempfile: \"%s\" already defined!\n"), symbol);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
SCRIPT_MSG(_T("!tempfile: \"%s\"=\"%s\"\n"), symbol, fpath);
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_P_DELFILE:
|
|
{
|
|
int fatal = 1;
|
|
int a = 1;
|
|
TCHAR *fc = line.gettoken_str(a);
|
|
if (line.getnumtokens()==3)
|
|
{
|
|
if(!_tcsicmp(fc,_T("/nonfatal")))
|
|
{
|
|
fatal = 0;
|
|
fc = line.gettoken_str(++a);
|
|
}
|
|
else PRINTHELP();
|
|
}
|
|
|
|
SCRIPT_MSG(_T("!delfile: \"%s\"\n"), line.gettoken_str(a));
|
|
|
|
tstring dir = get_dir_name(fc);
|
|
tstring spec = get_file_name(fc);
|
|
tstring basedir = dir + PLATFORM_PATH_SEPARATOR_STR;
|
|
if (dir == spec) {
|
|
// no path, just file name
|
|
dir = _T(".");
|
|
basedir = _T("");
|
|
}
|
|
|
|
boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
|
|
dr->read(dir);
|
|
|
|
for (dir_reader::iterator files_itr = dr->files().begin();
|
|
files_itr != dr->files().end();
|
|
files_itr++)
|
|
{
|
|
if (!dir_reader::matches(*files_itr, spec))
|
|
continue;
|
|
|
|
tstring file = basedir + *files_itr;
|
|
|
|
int result = _tunlink(file.c_str());
|
|
if (result == -1) {
|
|
ERROR_MSG(_T("!delfile: \"%s\" couldn't be deleted.\n"), file.c_str());
|
|
if (fatal)
|
|
{
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SCRIPT_MSG(_T("!delfile: deleted \"%s\"\n"), file.c_str());
|
|
}
|
|
}
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_P_APPENDFILE:
|
|
{
|
|
TCHAR *file = line.gettoken_str(1);
|
|
TCHAR *text = line.gettoken_str(2);
|
|
|
|
FILE *fp = FOPENTEXT(file, "a");
|
|
if (!fp)
|
|
{
|
|
ERROR_MSG(_T("!appendfile: \"%s\" couldn't be opened.\n"), file);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (_fputts(text, fp) < 0)
|
|
{
|
|
ERROR_MSG(_T("!appendfile: error writing to \"%s\".\n"), file);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
SCRIPT_MSG(_T("!appendfile: \"%s\" \"%s\"\n"), file, text);
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_P_GETDLLVERSION:
|
|
{
|
|
const TCHAR *cmdname = _T("!getdllversion");
|
|
DWORD low, high;
|
|
if (!GetDLLVersion(line.gettoken_str(1), high, low))
|
|
{
|
|
ERROR_MSG(_T("%s: error reading version info from \"%s\"\n"), cmdname, line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
TCHAR symbuf[MAX_LINELENGTH], numbuf[30], *basesymname = line.gettoken_str(2);
|
|
DWORD vals[] = { high>>16, high&0xffff, low>>16, low&0xffff };
|
|
SCRIPT_MSG(_T("%s: %s (%u.%u.%u.%u)->(%s<1..4>)\n"),
|
|
cmdname, line.gettoken_str(1), vals[0], vals[1], vals[2], vals[3], basesymname);
|
|
for (UINT i = 0; i < 4; ++i)
|
|
{
|
|
_stprintf(symbuf,_T("%s%u"), basesymname, i+1);
|
|
_stprintf(numbuf,_T("%lu"), vals[i]);
|
|
definedlist.add(symbuf, numbuf);
|
|
}
|
|
}
|
|
return PS_OK;
|
|
|
|
// page ordering stuff
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case TOK_UNINSTPAGE:
|
|
set_uninstall_mode(1);
|
|
case TOK_PAGE:
|
|
{
|
|
if (!uninstall_mode) {
|
|
enable_last_page_cancel = 0;
|
|
if (!_tcsicmp(line.gettoken_str(line.getnumtokens()-1),_T("/ENABLECANCEL")))
|
|
enable_last_page_cancel = 1;
|
|
}
|
|
else {
|
|
uenable_last_page_cancel = 0;
|
|
if (!_tcsicmp(line.gettoken_str(line.getnumtokens()-1),_T("/ENABLECANCEL")))
|
|
uenable_last_page_cancel = 1;
|
|
}
|
|
|
|
int k = line.gettoken_enum(1,_T("custom\0license\0components\0directory\0instfiles\0uninstConfirm\0"));
|
|
|
|
if (k < 0) PRINTHELP();
|
|
|
|
if (add_page(k) != PS_OK)
|
|
return PS_ERROR;
|
|
|
|
#ifndef NSIS_SUPPORT_CODECALLBACKS
|
|
if (!k) {
|
|
ERROR_MSG(_T("Error: custom page specified, NSIS_SUPPORT_CODECALLBACKS not defined.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
#endif//!NSIS_SUPPORT_CODECALLBACKS
|
|
|
|
if (k) {
|
|
// not custom
|
|
#ifdef NSIS_SUPPORT_CODECALLBACKS
|
|
switch (line.getnumtokens() - enable_last_page_cancel) {
|
|
case 6:
|
|
PRINTHELP();
|
|
case 5:
|
|
if (*line.gettoken_str(4))
|
|
cur_page->leavefunc = ns_func.add(line.gettoken_str(4),0);
|
|
case 4:
|
|
if (*line.gettoken_str(3))
|
|
cur_page->showfunc = ns_func.add(line.gettoken_str(3),0);
|
|
case 3:
|
|
if (*line.gettoken_str(2))
|
|
cur_page->prefunc = ns_func.add(line.gettoken_str(2),0);
|
|
}
|
|
#endif//NSIS_SUPPORT_CODECALLBACKS
|
|
}
|
|
#ifdef NSIS_SUPPORT_CODECALLBACKS
|
|
else {
|
|
// a custom page
|
|
switch (line.getnumtokens() - enable_last_page_cancel) {
|
|
case 6:
|
|
PRINTHELP();
|
|
case 5:
|
|
cur_page->caption = add_string(line.gettoken_str(4));
|
|
case 4:
|
|
if (*line.gettoken_str(3))
|
|
cur_page->leavefunc = ns_func.add(line.gettoken_str(3),0);
|
|
case 3:
|
|
if (*line.gettoken_str(2))
|
|
cur_page->prefunc = ns_func.add(line.gettoken_str(2),0);
|
|
break;
|
|
case 2:
|
|
ERROR_MSG(_T("Error: custom page must have a creator function!\n"));
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
#endif//NSIS_SUPPORT_CODECALLBACKS
|
|
|
|
SCRIPT_MSG(_T("%sPage: %s"), uninstall_mode?_T("Uninst"):_T(""), line.gettoken_str(1));
|
|
|
|
#ifdef NSIS_SUPPORT_CODECALLBACKS
|
|
if (cur_page->prefunc>=0)
|
|
SCRIPT_MSG(_T(" (%s:%s)"), k?_T("pre"):_T("creator"), line.gettoken_str(2));
|
|
if (cur_page->showfunc>=0 && k)
|
|
SCRIPT_MSG(_T(" (show:%s)"), line.gettoken_str(3));
|
|
if (cur_page->leavefunc>=0)
|
|
SCRIPT_MSG(_T(" (leave:%s)"), line.gettoken_str(4-!k));
|
|
else if (cur_page->caption && !k)
|
|
SCRIPT_MSG(_T(" (caption:%s)"), line.gettoken_str(3));
|
|
#endif
|
|
SCRIPT_MSG(_T("\n"));
|
|
|
|
page_end();
|
|
|
|
if (k == PAGE_INSTFILES) {
|
|
add_page(PAGE_COMPLETED);
|
|
page_end();
|
|
}
|
|
|
|
set_uninstall_mode(0);
|
|
}
|
|
return PS_OK;
|
|
|
|
// extended page setting
|
|
case TOK_PAGEEX:
|
|
{
|
|
int k = line.gettoken_enum(1,_T("custom\0license\0components\0directory\0instfiles\0uninstConfirm\0"));
|
|
if (k < 0) {
|
|
k = line.gettoken_enum(1,_T("un.custom\0un.license\0un.components\0un.directory\0un.instfiles\0un.uninstConfirm\0"));
|
|
if (k < 0) PRINTHELP();
|
|
set_uninstall_mode(1);
|
|
}
|
|
|
|
SCRIPT_MSG(_T("PageEx: %s\n"), line.gettoken_str(1));
|
|
|
|
if (add_page(k) != PS_OK)
|
|
return PS_ERROR;
|
|
|
|
cur_page->flags |= PF_PAGE_EX;
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_PAGEEXEND:
|
|
{
|
|
SCRIPT_MSG(_T("PageExEnd\n"));
|
|
|
|
#ifdef NSIS_SUPPORT_CODECALLBACKS
|
|
if (cur_page_type == PAGE_CUSTOM && !cur_page->prefunc) {
|
|
ERROR_MSG(_T("Error: custom pages must have a creator function.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
#endif
|
|
|
|
page_end();
|
|
|
|
if (cur_page_type == PAGE_INSTFILES) {
|
|
add_page(PAGE_COMPLETED);
|
|
page_end();
|
|
}
|
|
|
|
set_uninstall_mode(0);
|
|
}
|
|
return PS_OK;
|
|
case TOK_PAGECALLBACKS:
|
|
#ifdef NSIS_SUPPORT_CODECALLBACKS
|
|
{
|
|
SCRIPT_MSG(_T("PageCallbacks:"));
|
|
|
|
if (cur_page_type == PAGE_CUSTOM)
|
|
{
|
|
switch (line.getnumtokens())
|
|
{
|
|
case 4:
|
|
{
|
|
PRINTHELP();
|
|
}
|
|
case 3:
|
|
{
|
|
if (*line.gettoken_str(2))
|
|
{
|
|
if (_tcsnicmp(line.gettoken_str(2), _T("un."), 3))
|
|
{
|
|
if (uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
cur_page->leavefunc = ns_func.add(line.gettoken_str(2),0);
|
|
}
|
|
}
|
|
case 2:
|
|
{
|
|
if (*line.gettoken_str(1))
|
|
{
|
|
if (_tcsnicmp(line.gettoken_str(1), _T("un."), 3))
|
|
{
|
|
if (uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
cur_page->prefunc = ns_func.add(line.gettoken_str(1),0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (line.getnumtokens())
|
|
{
|
|
case 4:
|
|
{
|
|
if (*line.gettoken_str(3))
|
|
{
|
|
if (_tcsnicmp(line.gettoken_str(3), _T("un."), 3))
|
|
{
|
|
if (uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
cur_page->leavefunc = ns_func.add(line.gettoken_str(3),0);
|
|
}
|
|
}
|
|
case 3:
|
|
{
|
|
if (*line.gettoken_str(2))
|
|
{
|
|
if (_tcsnicmp(line.gettoken_str(2), _T("un."), 3))
|
|
{
|
|
if (uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
cur_page->showfunc = ns_func.add(line.gettoken_str(2),0);
|
|
}
|
|
}
|
|
case 2:
|
|
{
|
|
if (*line.gettoken_str(1))
|
|
{
|
|
if (_tcsnicmp(line.gettoken_str(1), _T("un."), 3))
|
|
{
|
|
if (uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("\nError: function names must start with \"un.\" in an uninstall page.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
cur_page->prefunc = ns_func.add(line.gettoken_str(1),0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int custom = cur_page_type == PAGE_CUSTOM ? 1 : 0;
|
|
|
|
if (cur_page->prefunc>=0)
|
|
SCRIPT_MSG(_T(" %s:%s"), !custom?_T("pre"):_T("creator"), line.gettoken_str(1));
|
|
if (cur_page->showfunc>=0 && !custom)
|
|
SCRIPT_MSG(_T(" show:%s"), line.gettoken_str(2));
|
|
if (cur_page->leavefunc>=0)
|
|
SCRIPT_MSG(_T(" leave:%s"), line.gettoken_str(3-custom));
|
|
|
|
SCRIPT_MSG(_T("\n"));
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_CODECALLBACKS not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_SUPPORT_CODECALLBACKS
|
|
#else
|
|
case TOK_PAGE:
|
|
case TOK_UNINSTPAGE:
|
|
case TOK_PAGEEX:
|
|
case TOK_PAGEEXEND:
|
|
case TOK_PAGECALLBACKS:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_CONFIG_VISIBLE_SUPPORT
|
|
// header flags
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
case TOK_LANGSTRING:
|
|
{
|
|
TCHAR *name = line.gettoken_str(1);
|
|
LANGID lang = line.gettoken_int(2);
|
|
TCHAR *str = line.gettoken_str(3);
|
|
int ret;
|
|
#ifndef _UNICODE
|
|
if (build_include_isutf8)
|
|
ret = SetUTF8LangString(name, lang, str);
|
|
else
|
|
#endif
|
|
ret = SetLangString(name, lang, str, curfile_unicode);
|
|
|
|
if (ret == PS_WARNING)
|
|
warning_fl(_T("LangString \"%s\" set multiple times for %d, wasting space"), name, lang);
|
|
else if (ret == PS_ERROR) {
|
|
ERROR_MSG(_T("Error: can't set LangString \"%s\"!\n"), name);
|
|
return PS_ERROR;
|
|
}
|
|
// BUGBUG: Does not display UTF-8 properly.
|
|
SCRIPT_MSG(_T("LangString: \"%s\" %d \"%s\"\n"), name, lang, str);
|
|
}
|
|
return PS_OK;
|
|
case TOK_LANGSTRINGUP:
|
|
SCRIPT_MSG(_T("Error: LangStringUP is obsolete, there are no more unprocessed strings. Use LangString.\n"));
|
|
return PS_ERROR;
|
|
case TOK_LICENSELANGSTRING:
|
|
{
|
|
#ifdef NSIS_CONFIG_SILENT_SUPPORT
|
|
if (build_header.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG))
|
|
{
|
|
warning_fl(_T("LicenseLangString: SilentInstall enabled, wasting space"));
|
|
}
|
|
#endif
|
|
TCHAR *name = line.gettoken_str(1);
|
|
LANGID lang = line.gettoken_int(2);
|
|
TCHAR *file = line.gettoken_str(3);
|
|
|
|
TCHAR *data = NULL;
|
|
MANAGE_WITH(data, free);
|
|
BOOL unicode;
|
|
|
|
int ret = LoadLicenseFile(file, &data, line, &unicode);
|
|
if (ret != PS_OK)
|
|
return ret;
|
|
|
|
ret = SetLangString(name, lang, data, unicode);
|
|
if (ret == PS_WARNING)
|
|
warning_fl(_T("LicenseLangString \"%s\" set multiple times for %d, wasting space"), name, lang);
|
|
else if (ret == PS_ERROR)
|
|
{
|
|
ERROR_MSG(_T("Error: can't set LicenseLangString \"%s\"!\n"), name);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
SCRIPT_MSG(_T("LicenseLangString: \"%s\" %d \"%s\"\n"), name, lang, file);
|
|
}
|
|
return PS_OK;
|
|
case TOK_NAME:
|
|
{
|
|
if (SetInnerString(NLF_NAME,line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
SetInnerString(NLF_NAME_DA,line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("Name: \"%s\""),line.gettoken_str(1));
|
|
if (*line.gettoken_str(2))
|
|
SCRIPT_MSG(_T(" \"%s\""),line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("\n"));
|
|
}
|
|
return PS_OK;
|
|
case TOK_CAPTION:
|
|
{
|
|
if (!cur_page)
|
|
{
|
|
if (SetInnerString(NLF_CAPTION,line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
}
|
|
else
|
|
{
|
|
cur_page->caption = add_string(line.gettoken_str(1));
|
|
}
|
|
SCRIPT_MSG(_T("Caption: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_ICON:
|
|
SCRIPT_MSG(_T("Icon: \"%s\"\n"),line.gettoken_str(1));
|
|
try {
|
|
free_loaded_icon(installer_icon);
|
|
installer_icon = load_icon_file(line.gettoken_str(1));
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error while loading icon from \"%s\": %s\n"), line.gettoken_str(1), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
return PS_OK;
|
|
#ifdef NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_CHECKBITMAP:
|
|
SCRIPT_MSG(_T("CheckBitmap: \"%s\"\n"),line.gettoken_str(1));
|
|
try {
|
|
init_res_editor();
|
|
int err = update_bitmap(res_editor, IDB_BITMAP1, line.gettoken_str(1), 96, 16, 8);
|
|
if (err) {
|
|
switch (err) {
|
|
case -1:
|
|
ERROR_MSG(_T("Error: can't find bitmap\n"));
|
|
break;
|
|
case -2:
|
|
ERROR_MSG(_T("Error: invalid bitmap file - corrupted or not a bitmap\n"));
|
|
break;
|
|
case -3:
|
|
ERROR_MSG(_T("Error: bitmap isn't 96x16 in size\n"));
|
|
break;
|
|
case -4:
|
|
ERROR_MSG(_T("Error: bitmap has more than 8bpp\n"));
|
|
break;
|
|
}
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error while replacing bitmap: %s\n"), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
return PS_OK;
|
|
#else//NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_CHECKBITMAP:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_DIRTEXT:
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
{
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_DIR_TEXT, line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
if (line.getnumtokens() > 2)
|
|
SetInnerString(NLF_DIR_SUBTEXT, line.gettoken_str(2));
|
|
if (line.getnumtokens() > 3)
|
|
SetInnerString(NLF_BTN_BROWSE, line.gettoken_str(3));
|
|
if (line.getnumtokens() > 4)
|
|
SetInnerString(NLF_DIR_BROWSETEXT, line.gettoken_str(4));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_DIRECTORY) {
|
|
ERROR_MSG(_T("Error: DirText can only be used inside PageEx directory.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[0] = add_string(line.gettoken_str(1));
|
|
if (line.getnumtokens() > 2)
|
|
cur_page->parms[1] = add_string(line.gettoken_str(2));
|
|
if (line.getnumtokens() > 3)
|
|
cur_page->parms[2] = add_string(line.gettoken_str(3));
|
|
if (line.getnumtokens() > 4)
|
|
cur_page->parms[3] = add_string(line.gettoken_str(4));
|
|
}
|
|
SCRIPT_MSG(_T("DirText: \"%s\" \"%s\" \"%s\" \"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
}
|
|
return PS_OK;
|
|
#else//NSIS_CONFIG_VISIBLE_SUPPORT
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case TOK_DIRVAR:
|
|
{
|
|
if (cur_page_type != PAGE_DIRECTORY && cur_page_type != PAGE_UNINSTCONFIRM) {
|
|
ERROR_MSG(_T("Error: can't use DirVar outside of PageEx directory|uninstConfirm.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[4] = GetUserVarIndex(line, 1) + 1;
|
|
if (cur_page->parms[4] <= 0) PRINTHELP();
|
|
SCRIPT_MSG(_T("DirVar: %s\n"), line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_DIRVERIFY:
|
|
{
|
|
if (cur_page_type != PAGE_DIRECTORY) {
|
|
ERROR_MSG(_T("Error: can't use DirVerify outside of PageEx directory.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->flags &= ~PF_DIR_NO_BTN_DISABLE;
|
|
int k = line.gettoken_enum(1,_T("auto\0leave\0"));
|
|
if (k == -1)
|
|
PRINTHELP();
|
|
if (k)
|
|
cur_page->flags |= PF_DIR_NO_BTN_DISABLE;
|
|
SCRIPT_MSG(_T("DirVerify: %s\n"), line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_GETINSTDIRERROR:
|
|
ent.which = EW_GETFLAG;
|
|
ent.offsets[0] = GetUserVarIndex(line, 1);
|
|
ent.offsets[1] = FLAG_OFFSET(instdir_error);
|
|
return add_entry(&ent);
|
|
#ifdef NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_COMPTEXT:
|
|
{
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_COMP_TEXT, line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
if (line.getnumtokens() > 2)
|
|
SetInnerString(NLF_COMP_SUBTEXT1, line.gettoken_str(2));
|
|
if (line.getnumtokens() > 3)
|
|
SetInnerString(NLF_COMP_SUBTEXT2, line.gettoken_str(3));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_COMPONENTS) {
|
|
ERROR_MSG(_T("Error: ComponentText can only be used inside PageEx components.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[0] = add_string(line.gettoken_str(1));
|
|
cur_page->parms[1] = add_string(line.gettoken_str(2));
|
|
cur_page->parms[2] = add_string(line.gettoken_str(3));
|
|
cur_page->parms[3] = cur_page->parms[1];
|
|
cur_page->parms[4] = cur_page->parms[2];
|
|
}
|
|
SCRIPT_MSG(_T("ComponentText: \"%s\" \"%s\" \"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
}
|
|
return PS_OK;
|
|
case TOK_INSTTYPE:
|
|
{
|
|
int x;
|
|
|
|
if (!_tcsicmp(line.gettoken_str(1),_T("/NOCUSTOM")))
|
|
{
|
|
build_header.flags|=CH_FLAGS_NO_CUSTOM;
|
|
SCRIPT_MSG(_T("InstType: disabling custom install type\n"));
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(1),_T("/COMPONENTSONLYONCUSTOM")))
|
|
{
|
|
build_header.flags|=CH_FLAGS_COMP_ONLY_ON_CUSTOM;
|
|
SCRIPT_MSG(_T("InstType: making components viewable only on custom install type\n"));
|
|
}
|
|
else if (!_tcsnicmp(line.gettoken_str(1),_T("/CUSTOMSTRING="),14))
|
|
{
|
|
SCRIPT_MSG(_T("InstType: setting custom text to: \"%s\"\n"),line.gettoken_str(1)+14);
|
|
if (SetInnerString(NLF_COMP_CUSTOM,line.gettoken_str(1)+14) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),_T("InstType /CUSTOMSTRING"));
|
|
}
|
|
else if (line.gettoken_str(1)[0]==_T('/'))
|
|
{
|
|
PRINTHELP()
|
|
}
|
|
else
|
|
{
|
|
TCHAR *itname = line.gettoken_str(1);
|
|
|
|
if (!_tcsnicmp(itname, _T("un."), 3)) {
|
|
set_uninstall_mode(1);
|
|
itname += 3;
|
|
}
|
|
|
|
for (x = 0; x < NSIS_MAX_INST_TYPES && cur_header->install_types[x]; x ++);
|
|
if (x == NSIS_MAX_INST_TYPES)
|
|
{
|
|
ERROR_MSG(_T("InstType: no more than %d install types allowed. %d specified\n"), NSIS_MAX_INST_TYPES, NSIS_MAX_INST_TYPES + 1);
|
|
return PS_ERROR;
|
|
}
|
|
else
|
|
{
|
|
cur_header->install_types[x] = add_string(itname);
|
|
SCRIPT_MSG(_T("InstType: %s%d=\"%s\"\n"), uninstall_mode ? _T("(uninstall) ") : _T(""), x+1, itname);
|
|
}
|
|
|
|
set_uninstall_mode(0);
|
|
}
|
|
}
|
|
return PS_OK;
|
|
#else//NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_COMPTEXT:
|
|
case TOK_INSTTYPE:
|
|
ERROR_MSG(_T("Error: %s specified but NSIS_CONFIG_COMPONENTPAGE not defined\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_CONFIG_COMPONENTPAGE
|
|
#ifdef NSIS_CONFIG_LICENSEPAGE
|
|
case TOK_LICENSETEXT:
|
|
{
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_LICENSE_TEXT, line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
SetInnerString(NLF_LICENSE_TEXT_FSRB, line.gettoken_str(1));
|
|
SetInnerString(NLF_LICENSE_TEXT_FSCB, line.gettoken_str(1));
|
|
if (line.getnumtokens() > 2)
|
|
SetInnerString(NLF_BTN_LICENSE, line.gettoken_str(2));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_LICENSE) {
|
|
ERROR_MSG(_T("Error: LicenseText can only be used inside PageEx license.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[0] = add_string(line.gettoken_str(1));
|
|
cur_page->next = add_string(line.gettoken_str(2));
|
|
}
|
|
SCRIPT_MSG(_T("LicenseText: \"%s\" \"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
}
|
|
return PS_OK;
|
|
case TOK_LICENSEDATA:
|
|
{
|
|
int idx = 0;
|
|
TCHAR *file = line.gettoken_str(1);
|
|
TCHAR *data = NULL;
|
|
TCHAR *filedata = NULL;
|
|
MANAGE_WITH(filedata, free);
|
|
|
|
if (file[0] == _T('$') && file[1] == _T('('))
|
|
{
|
|
TCHAR *cp = _tcsdup(file+2);
|
|
MANAGE_WITH(cp, free);
|
|
TCHAR *p = _tcschr(cp, _T(')'));
|
|
if (p && p[1] == 0) { // if string is only a language str identifier
|
|
*p = 0;
|
|
idx = DefineLangString(cp, 0);
|
|
}
|
|
data = file;
|
|
}
|
|
|
|
if (!idx)
|
|
{
|
|
BOOL unicode;
|
|
int ret = LoadLicenseFile(file, &filedata, line, &unicode);
|
|
if (ret != PS_OK)
|
|
return ret;
|
|
data = filedata;
|
|
}
|
|
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_LICENSE_DATA,data) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_LICENSE) {
|
|
ERROR_MSG(_T("Error: LicenseData can only be used inside PageEx license.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
cur_page->parms[1] = add_string(data, 0);
|
|
}
|
|
|
|
SCRIPT_MSG(_T("LicenseData: \"%s\"\n"),file);
|
|
}
|
|
return PS_OK;
|
|
case TOK_LICENSEFORCESELECTION:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("off\0checkbox\0radiobuttons\0"));
|
|
if (k == -1) PRINTHELP()
|
|
if (k < line.getnumtokens() - 2) PRINTHELP()
|
|
|
|
if (!cur_page) {
|
|
switch (line.getnumtokens()) {
|
|
case 4:
|
|
SetInnerString(NLF_BTN_LICENSE_DISAGREE, line.gettoken_str(3));
|
|
case 3:
|
|
SetInnerString(NLF_BTN_LICENSE_AGREE, line.gettoken_str(2));
|
|
break;
|
|
}
|
|
|
|
switch (k) {
|
|
case 0:
|
|
license_res_id = IDD_LICENSE;
|
|
break;
|
|
case 1:
|
|
license_res_id = IDD_LICENSE_FSCB;
|
|
break;
|
|
case 2:
|
|
license_res_id = IDD_LICENSE_FSRB;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_LICENSE) {
|
|
ERROR_MSG(_T("Error: LicenseForceSelection can only be used inside PageEx license.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
switch (line.getnumtokens()) {
|
|
case 4:
|
|
cur_page->parms[3] = add_string(line.gettoken_str(3));
|
|
case 3:
|
|
cur_page->parms[2] = add_string(line.gettoken_str(2));
|
|
break;
|
|
}
|
|
|
|
cur_page->flags &= ~(PF_LICENSE_FORCE_SELECTION | PF_LICENSE_NO_FORCE_SELECTION);
|
|
|
|
switch (k) {
|
|
case 0:
|
|
cur_page->dlg_id = IDD_LICENSE;
|
|
cur_page->flags |= PF_LICENSE_NO_FORCE_SELECTION;
|
|
break;
|
|
case 1:
|
|
cur_page->dlg_id = IDD_LICENSE_FSCB;
|
|
cur_page->flags |= PF_LICENSE_FORCE_SELECTION;
|
|
break;
|
|
case 2:
|
|
cur_page->dlg_id = IDD_LICENSE_FSRB;
|
|
cur_page->flags |= PF_LICENSE_FORCE_SELECTION;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SCRIPT_MSG(_T("LicenseForceSelection: %s \"%s\" \"%s\"\n"), line.gettoken_str(1), line.gettoken_str(2), line.gettoken_str(3));
|
|
}
|
|
return PS_OK;
|
|
case TOK_LICENSEBKCOLOR:
|
|
{
|
|
TCHAR *p = line.gettoken_str(1);
|
|
if (!_tcsicmp(p,_T("/windows")))
|
|
{
|
|
build_header.license_bg=-COLOR_WINDOW;
|
|
SCRIPT_MSG(_T("LicenseBkColor: /windows\n"));
|
|
}
|
|
else if (!_tcsicmp(p,_T("/grey")) || !_tcsicmp(p,_T("/gray")))
|
|
{
|
|
build_header.license_bg=-COLOR_BTNFACE;
|
|
SCRIPT_MSG(_T("LicenseBkColor: /grey\n"));
|
|
}
|
|
else
|
|
{
|
|
int v=_tcstoul(p,&p,16);
|
|
build_header.license_bg=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16);
|
|
build_uninst.license_bg=build_header.license_bg;
|
|
SCRIPT_MSG(_T("LicenseBkColor: %06X\n"),v);
|
|
}
|
|
}
|
|
return PS_OK;
|
|
#else//!NSIS_CONFIG_LICENSEPAGE
|
|
case TOK_LICENSETEXT:
|
|
case TOK_LICENSEDATA:
|
|
case TOK_LICENSEBKCOLOR:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_LICENSEPAGE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_CONFIG_LICENSEPAGE
|
|
#ifdef NSIS_CONFIG_SILENT_SUPPORT
|
|
case TOK_SILENTINST:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("normal\0silent\0silentlog\0"));
|
|
if (k<0) PRINTHELP()
|
|
#ifndef NSIS_CONFIG_LOG
|
|
if (k == 2)
|
|
{
|
|
ERROR_MSG(_T("SilentInstall: silentlog specified, no log support compiled in (use NSIS_CONFIG_LOG)\n"));
|
|
return PS_ERROR;
|
|
}
|
|
#endif//NSIS_CONFIG_LOG
|
|
SCRIPT_MSG(_T("SilentInstall: %s\n"),line.gettoken_str(1));
|
|
#ifdef NSIS_CONFIG_LICENSEPAGE
|
|
if (k && HasUserDefined(NLF_LICENSE_DATA))
|
|
{
|
|
warning_fl(_T("SilentInstall: LicenseData already specified. wasting space"));
|
|
}
|
|
if (k) {
|
|
build_header.flags|=CH_FLAGS_SILENT;
|
|
if (k == 2)
|
|
build_header.flags|=CH_FLAGS_SILENT_LOG;
|
|
}
|
|
else {
|
|
build_header.flags&=~CH_FLAGS_SILENT;
|
|
build_header.flags&=~CH_FLAGS_SILENT_LOG;
|
|
}
|
|
#endif//NSIS_CONFIG_LICENSEPAGE
|
|
}
|
|
return PS_OK;
|
|
case TOK_SILENTUNINST:
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
{
|
|
int k=line.gettoken_enum(1,_T("normal\0silent\0"));
|
|
if (k<0) PRINTHELP()
|
|
if (k)
|
|
build_uninst.flags|=CH_FLAGS_SILENT;
|
|
else
|
|
build_uninst.flags&=~CH_FLAGS_SILENT;
|
|
SCRIPT_MSG(_T("SilentUnInstall: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif
|
|
case TOK_IFSILENT:
|
|
ent.which=EW_IFFLAG;
|
|
if (process_jump(line,1,&ent.offsets[0]) ||
|
|
process_jump(line,2,&ent.offsets[1])) PRINTHELP()
|
|
ent.offsets[2]=FLAG_OFFSET(silent);
|
|
ent.offsets[3]=~0;//new value mask - keep flag
|
|
SCRIPT_MSG(_T("IfSilent ?%s:%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SETSILENT:
|
|
{
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(silent);
|
|
int k=line.gettoken_enum(1,_T("normal\0silent\0"));
|
|
if (k<0) PRINTHELP()
|
|
ent.offsets[1]=add_intstring(k);
|
|
SCRIPT_MSG(_T("SetSilent: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_CONFIG_SILENT_SUPPORT
|
|
case TOK_SILENTINST:
|
|
case TOK_SILENTUNINST:
|
|
case TOK_IFSILENT:
|
|
case TOK_SETSILENT:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_SILENT_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_CONFIG_SILENT_SUPPORT
|
|
case TOK_OUTFILE:
|
|
_tcsnccpy(build_output_filename,line.gettoken_str(1),1024-1);
|
|
SCRIPT_MSG(_T("OutFile: \"%s\"\n"),build_output_filename);
|
|
return PS_OK;
|
|
case TOK_INSTDIR:
|
|
{
|
|
TCHAR *p = line.gettoken_str(1);
|
|
if (build_header.install_directory_ptr)
|
|
{
|
|
warning_fl(_T("%s: specified multiple times. wasting space"),line.gettoken_str(0));
|
|
}
|
|
build_header.install_directory_ptr = add_string(p);
|
|
build_header.install_directory_auto_append = 0;
|
|
TCHAR *p2 = p + _tcslen(p);
|
|
if (*p && *CharPrev(p, p2) != _T('\\'))
|
|
{
|
|
// we risk hitting $\r or something like $(bla\ad) or ${bla\ad} here, but it's better
|
|
// than hitting backslashes in processed strings
|
|
while (p2 > p && *p2 != _T('\\'))
|
|
p2 = CharPrev(p, p2);
|
|
if (*p2 == _T('\\'))
|
|
{
|
|
build_header.install_directory_auto_append = add_string(p2 + 1);
|
|
}
|
|
}
|
|
SCRIPT_MSG(_T("InstallDir: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_INSTALLDIRREGKEY: // InstallDirRegKey
|
|
{
|
|
if (build_header.install_reg_key_ptr)
|
|
{
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
}
|
|
int k=line.gettoken_enum(1,rootkeys[0]);
|
|
if (k == -1) k=line.gettoken_enum(1,rootkeys[1]);
|
|
if (k == -1) PRINTHELP()
|
|
build_header.install_reg_rootkey=(INT_PTR)rootkey_tab[k];
|
|
if (!build_header.install_reg_rootkey) PRINTHELP() // SHCTX is invalid here
|
|
build_header.install_reg_key_ptr = add_string(line.gettoken_str(2),0);
|
|
if (line.gettoken_str(2)[0] == _T('\\'))
|
|
warning_fl(_T("%s: registry path name begins with \'\\\', may cause problems"),line.gettoken_str(0));
|
|
build_header.install_reg_value_ptr = add_string(line.gettoken_str(3),0);
|
|
SCRIPT_MSG(_T("InstallRegKey: \"%s\\%s\\%s\"\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
}
|
|
return PS_OK;
|
|
case TOK_CRCCHECK:
|
|
build_crcchk=line.gettoken_enum(1,_T("off\0on\0force\0"));
|
|
if (build_crcchk==-1) PRINTHELP()
|
|
SCRIPT_MSG(_T("CRCCheck: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
case TOK_INSTPROGRESSFLAGS:
|
|
{
|
|
int x;
|
|
int smooth=0;
|
|
build_header.flags&=~CH_FLAGS_PROGRESS_COLORED;
|
|
for (x = 1; x < line.getnumtokens(); x ++)
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(x),_T("smooth"))) smooth=1;
|
|
else if (!_tcsicmp(line.gettoken_str(x),_T("colored"))) build_header.flags|=CH_FLAGS_PROGRESS_COLORED;
|
|
else PRINTHELP()
|
|
}
|
|
try {
|
|
init_res_editor();
|
|
|
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INSTFILES, NSIS_DEFAULT_LANG);
|
|
if (!dlg) throw runtime_error("IDD_INSTFILES doesn't exist!");
|
|
CDialogTemplate dt(dlg,build_unicode,uDefCodePage);
|
|
free(dlg);
|
|
DialogItemTemplate* progress = dt.GetItem(IDC_PROGRESS);
|
|
if (!progress) {
|
|
throw runtime_error("IDC_PROGRESS doesn't exist!");
|
|
}
|
|
|
|
if (smooth)
|
|
progress->dwStyle |= PBS_SMOOTH;
|
|
else
|
|
progress->dwStyle &= ~PBS_SMOOTH;
|
|
|
|
DWORD dwSize;
|
|
dlg = dt.Save(dwSize);
|
|
res_editor->UpdateResource(RT_DIALOG, IDD_INSTFILES, NSIS_DEFAULT_LANG, dlg, dwSize);
|
|
delete [] dlg;
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error setting smooth progress bar: %s\n"), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("InstProgressFlags: smooth=%d, colored=%d\n"),smooth,
|
|
!!(build_header.flags&CH_FLAGS_PROGRESS_COLORED));
|
|
}
|
|
return PS_OK;
|
|
case TOK_AUTOCLOSE:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("false\0true\0"));
|
|
if (k == -1) PRINTHELP();
|
|
if (k)
|
|
build_header.flags|=CH_FLAGS_AUTO_CLOSE;
|
|
else
|
|
build_header.flags&=~CH_FLAGS_AUTO_CLOSE;
|
|
SCRIPT_MSG(_T("AutoCloseWindow: %s\n"),k?_T("true"):_T("false"));
|
|
}
|
|
return PS_OK;
|
|
case TOK_WINDOWICON:
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
disable_window_icon=line.gettoken_enum(1,_T("on\0off\0"));
|
|
if (disable_window_icon == -1) PRINTHELP();
|
|
SCRIPT_MSG(_T("WindowIcon: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
#else
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif // NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case TOK_SHOWDETAILSUNINST:
|
|
#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
ERROR_MSG(_T("Error: ShowUninstDetails specified but NSIS_CONFIG_UNINSTALL_SUPPORT not defined\n"));
|
|
return PS_ERROR;
|
|
#endif
|
|
case TOK_SHOWDETAILS:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("hide\0show\0nevershow\0"));
|
|
if (k == -1) PRINTHELP()
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
if (which_token == TOK_SHOWDETAILSUNINST)
|
|
{
|
|
build_uninst.flags&=~(CH_FLAGS_DETAILS_NEVERSHOW|CH_FLAGS_DETAILS_SHOWDETAILS);
|
|
if (k==1)
|
|
build_uninst.flags|=CH_FLAGS_DETAILS_SHOWDETAILS;
|
|
else if (k==2)
|
|
build_uninst.flags|=CH_FLAGS_DETAILS_NEVERSHOW;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
build_header.flags&=~(CH_FLAGS_DETAILS_NEVERSHOW|CH_FLAGS_DETAILS_SHOWDETAILS);
|
|
if (k==1)
|
|
build_header.flags|=CH_FLAGS_DETAILS_SHOWDETAILS;
|
|
else if (k==2)
|
|
build_header.flags|=CH_FLAGS_DETAILS_NEVERSHOW;
|
|
}
|
|
SCRIPT_MSG(_T("%s: %s\n"),line.gettoken_str(0),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_DIRSHOW:
|
|
/*{
|
|
int k=line.gettoken_enum(1,_T("show\0hide\0"));
|
|
if (k == -1) PRINTHELP();
|
|
if (k)
|
|
build_header.flags|=CH_FLAGS_DIR_NO_SHOW;
|
|
else
|
|
build_header.flags&=~CH_FLAGS_DIR_NO_SHOW;
|
|
SCRIPT_MSG(_T("DirShow: %s\n"),k?_T("hide"):_T("show"));
|
|
}*/
|
|
ERROR_MSG(_T("Error: DirShow doesn't currently work\n"));
|
|
return PS_ERROR;
|
|
case TOK_ROOTDIRINST:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("true\0false\0"));
|
|
if (k == -1) PRINTHELP();
|
|
if (k)
|
|
build_header.flags|=CH_FLAGS_NO_ROOT_DIR;
|
|
else
|
|
build_header.flags&=~CH_FLAGS_NO_ROOT_DIR;
|
|
SCRIPT_MSG(_T("AllowRootDirInstall: %s\n"),k?_T("false"):_T("true"));
|
|
}
|
|
return PS_OK;
|
|
case TOK_BGFONT:
|
|
#ifndef NSIS_SUPPORT_BGBG
|
|
ERROR_MSG(_T("Error: BGFont specified but NSIS_SUPPORT_BGBG not defined\n"));
|
|
return PS_ERROR;
|
|
#else//NSIS_SUPPORT_BGBG
|
|
if (line.getnumtokens()==1)
|
|
{
|
|
memcpy(&bg_font,&bg_default_font,sizeof(LOGFONT));
|
|
SCRIPT_MSG(_T("BGFont: default font\n"));
|
|
return PS_OK;
|
|
}
|
|
|
|
LOGFONT newfont;
|
|
newfont.lfHeight=40;
|
|
newfont.lfWidth=0;
|
|
newfont.lfEscapement=0;
|
|
newfont.lfOrientation=0;
|
|
newfont.lfWeight=FW_NORMAL;
|
|
newfont.lfItalic=FALSE;
|
|
newfont.lfUnderline=FALSE;
|
|
newfont.lfStrikeOut=FALSE;
|
|
newfont.lfCharSet=DEFAULT_CHARSET;
|
|
newfont.lfOutPrecision=OUT_DEFAULT_PRECIS;
|
|
newfont.lfClipPrecision=CLIP_DEFAULT_PRECIS;
|
|
newfont.lfQuality=DEFAULT_QUALITY;
|
|
newfont.lfPitchAndFamily=DEFAULT_PITCH;
|
|
|
|
_tcsnccpy(newfont.lfFaceName,line.gettoken_str(1),LF_FACESIZE);
|
|
|
|
SCRIPT_MSG(_T("BGFont: \"%s\""),line.gettoken_str(1));
|
|
{
|
|
bool height=false;
|
|
bool weight=false;
|
|
for (int i = 2; i < line.getnumtokens(); i++) {
|
|
TCHAR *tok=line.gettoken_str(i);
|
|
if (tok[0]==_T('/')) {
|
|
if (!_tcsicmp(tok,_T("/ITALIC"))) {
|
|
SCRIPT_MSG(_T(" /ITALIC"));
|
|
newfont.lfItalic=TRUE;
|
|
}
|
|
else if (!_tcsicmp(tok,_T("/UNDERLINE"))) {
|
|
SCRIPT_MSG(_T(" /UNDERLINE"));
|
|
newfont.lfUnderline=TRUE;
|
|
}
|
|
else if (!_tcsicmp(tok,_T("/STRIKE"))) {
|
|
SCRIPT_MSG(_T(" /STRIKE"));
|
|
newfont.lfStrikeOut=TRUE;
|
|
}
|
|
else {
|
|
SCRIPT_MSG(_T("\n"));
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
else {
|
|
if (!height) {
|
|
SCRIPT_MSG(_T(" height=%s"),tok);
|
|
newfont.lfHeight=line.gettoken_int(i);
|
|
height=true;
|
|
}
|
|
else if (!weight) {
|
|
SCRIPT_MSG(_T(" weight=%s"),tok);
|
|
newfont.lfWeight=line.gettoken_int(i);
|
|
weight=true;
|
|
}
|
|
else {
|
|
SCRIPT_MSG(_T("\n"));
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SCRIPT_MSG(_T("\n"));
|
|
memcpy(&bg_font, &newfont, sizeof(LOGFONT));
|
|
return PS_OK;
|
|
#endif//NSIS_SUPPORT_BGBG
|
|
case TOK_BGGRADIENT:
|
|
#ifndef NSIS_SUPPORT_BGBG
|
|
ERROR_MSG(_T("Error: BGGradient specified but NSIS_SUPPORT_BGBG not defined\n"));
|
|
return PS_ERROR;
|
|
#else//NSIS_SUPPORT_BGBG
|
|
if (line.getnumtokens()==1)
|
|
{
|
|
SCRIPT_MSG(_T("BGGradient: default colors\n"));
|
|
build_header.bg_color1=0;
|
|
build_header.bg_color2=RGB(0,0,255);
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(1),_T("off")))
|
|
{
|
|
build_header.bg_color1=build_header.bg_color2=build_header.bg_textcolor=-1;
|
|
SCRIPT_MSG(_T("BGGradient: off\n"));
|
|
if (line.getnumtokens()>2) PRINTHELP()
|
|
}
|
|
else
|
|
{
|
|
TCHAR *p = line.gettoken_str(1);
|
|
int v1,v2,v3=-1;
|
|
v1=_tcstoul(p,&p,16);
|
|
build_header.bg_color1=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16);
|
|
p=line.gettoken_str(2);
|
|
v2=_tcstoul(p,&p,16);
|
|
build_header.bg_color2=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16);
|
|
|
|
p=line.gettoken_str(3);
|
|
if (*p)
|
|
{
|
|
if (!_tcsicmp(p,_T("notext"))) build_header.bg_textcolor=-1;
|
|
else
|
|
{
|
|
v3=_tcstoul(p,&p,16);
|
|
build_header.bg_textcolor=((v3&0xff)<<16)|(v3&0xff00)|((v3&0xff0000)>>16);
|
|
}
|
|
}
|
|
|
|
SCRIPT_MSG(_T("BGGradient: 0x%06X->0x%06X (text=0x%06X)\n"),v1,v2,v3);
|
|
}
|
|
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
build_uninst.bg_color1=build_header.bg_color1;
|
|
build_uninst.bg_color2=build_header.bg_color2;
|
|
build_uninst.bg_textcolor=build_header.bg_textcolor;
|
|
#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
#endif//NSIS_SUPPORT_BGBG
|
|
return PS_OK;
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case TOK_INSTCOLORS:
|
|
{
|
|
TCHAR *p = line.gettoken_str(1);
|
|
if (p[0]==_T('/'))
|
|
{
|
|
if (_tcsicmp(p,_T("/windows")) || line.getnumtokens()!=2) PRINTHELP()
|
|
build_header.lb_fg=build_header.lb_bg=-1;
|
|
SCRIPT_MSG(_T("InstallColors: windows default colors\n"));
|
|
}
|
|
else
|
|
{
|
|
int v1,v2;
|
|
if (line.getnumtokens()!=3) PRINTHELP()
|
|
v1=_tcstoul(p,&p,16);
|
|
build_header.lb_fg=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16);
|
|
p=line.gettoken_str(2);
|
|
v2=_tcstoul(p,&p,16);
|
|
build_header.lb_bg=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16);
|
|
SCRIPT_MSG(_T("InstallColors: fg=%06X bg=%06X\n"),v1,v2);
|
|
}
|
|
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
build_uninst.lb_fg=build_header.lb_fg;
|
|
build_uninst.lb_bg=build_header.lb_bg;
|
|
#endif
|
|
}
|
|
return PS_OK;
|
|
case TOK_XPSTYLE:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("on\0off\0"));
|
|
if (k == -1) PRINTHELP()
|
|
SCRIPT_MSG(_T("XPStyle: %s\n"), line.gettoken_str(1));
|
|
if (!k)
|
|
manifest_comctl = manifest::comctl_xp;
|
|
else
|
|
manifest_comctl = manifest::comctl_old;
|
|
}
|
|
return PS_OK;
|
|
case TOK_CHANGEUI:
|
|
try {
|
|
DWORD dwSize;
|
|
int k=line.gettoken_enum(1, _T("all\0IDD_LICENSE\0IDD_DIR\0IDD_SELCOM\0IDD_INST\0IDD_INSTFILES\0IDD_UNINST\0IDD_VERIFY\0IDD_LICENSE_FSRB\0IDD_LICENSE_FSCB\0"));
|
|
if (k<0) PRINTHELP();
|
|
|
|
FILE *fui = FOPEN(line.gettoken_str(2), ("rb"));
|
|
if (!fui) {
|
|
ERROR_MSG(_T("Error: Can't open \"%s\"!\n"), line.gettoken_str(2));
|
|
return PS_ERROR;
|
|
}
|
|
MANAGE_WITH(fui, fclose);
|
|
|
|
fseek(fui, 0, SEEK_END);
|
|
unsigned int len = ftell(fui);
|
|
fseek(fui, 0, SEEK_SET);
|
|
LPBYTE ui = (LPBYTE) malloc(len);
|
|
if (!ui) {
|
|
ERROR_MSG(_T("Internal compiler error #12345: malloc(%d) failed\n"), len);
|
|
extern void quit(); quit();
|
|
}
|
|
MANAGE_WITH(ui, free);
|
|
if (fread(ui, 1, len, fui) != len) {
|
|
ERROR_MSG(_T("Error: Can't read \"%s\"!\n"), line.gettoken_str(2));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
CResourceEditor *uire = new CResourceEditor(ui, len);
|
|
|
|
init_res_editor();
|
|
|
|
// Search for required items
|
|
#define GET(x) dlg = uire->GetResource(RT_DIALOG, x, 0); if (!dlg) return PS_ERROR; CDialogTemplate UIDlg(dlg, build_unicode, uDefCodePage);
|
|
#define SEARCH(x) if (!UIDlg.GetItem(x)) {ERROR_MSG(_T("Error: Can't find %s (%u) in the custom UI!\n"), _T(#x), x);delete [] dlg;delete uire;return PS_ERROR;}
|
|
#define SAVE(x) dwSize = UIDlg.GetSize(); res_editor->UpdateResource(RT_DIALOG, x, NSIS_DEFAULT_LANG, dlg, dwSize); delete [] dlg;
|
|
|
|
LPBYTE dlg = NULL;
|
|
|
|
if (k == 0 || k == 1) {
|
|
GET(IDD_LICENSE);
|
|
SEARCH(IDC_EDIT1);
|
|
SAVE(IDD_LICENSE);
|
|
}
|
|
|
|
if (k == 0 || k == 2) {
|
|
GET(IDD_DIR);
|
|
SEARCH(IDC_DIR);
|
|
SEARCH(IDC_BROWSE);
|
|
#ifdef NSIS_CONFIG_LOG
|
|
SEARCH(IDC_CHECK1);
|
|
#endif
|
|
SAVE(IDD_DIR);
|
|
}
|
|
|
|
if (k == 0 || k == 3) {
|
|
GET(IDD_SELCOM);
|
|
SEARCH(IDC_TREE1);
|
|
SEARCH(IDC_COMBO1);
|
|
SAVE(IDD_SELCOM);
|
|
}
|
|
|
|
if (k == 0 || k == 4) {
|
|
GET(IDD_INST);
|
|
SEARCH(IDC_BACK);
|
|
SEARCH(IDC_CHILDRECT);
|
|
SEARCH(IDC_VERSTR);
|
|
SEARCH(IDOK);
|
|
SEARCH(IDCANCEL);
|
|
|
|
// Search for bitmap holder (default for SetBrandingImage)
|
|
branding_image_found = false;
|
|
DialogItemTemplate* dlgItem = 0;
|
|
for (int i = 0; (dlgItem = UIDlg.GetItemByIdx(i)); i++) {
|
|
bool check = false;
|
|
|
|
if (IS_INTRESOURCE(dlgItem->szClass)) {
|
|
if (dlgItem->szClass == MAKEINTRESOURCEW(0x0082)) {
|
|
check = true;
|
|
}
|
|
} else {
|
|
check = _wcsicmp(dlgItem->szClass, L"Static") == 0;
|
|
}
|
|
|
|
if (check) {
|
|
if ((dlgItem->dwStyle & SS_BITMAP) == SS_BITMAP) {
|
|
branding_image_found = true;
|
|
branding_image_id = dlgItem->wId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
SAVE(IDD_INST);
|
|
}
|
|
|
|
if (k == 0 || k == 5) {
|
|
GET(IDD_INSTFILES);
|
|
SEARCH(IDC_LIST1);
|
|
SEARCH(IDC_PROGRESS);
|
|
SEARCH(IDC_SHOWDETAILS);
|
|
SAVE(IDD_INSTFILES);
|
|
}
|
|
|
|
if (k == 0 || k == 6) {
|
|
GET(IDD_UNINST);
|
|
SEARCH(IDC_EDIT1);
|
|
SAVE(IDD_UNINST);
|
|
}
|
|
|
|
if (k == 0 || k == 7) {
|
|
GET(IDD_VERIFY);
|
|
SEARCH(IDC_STR);
|
|
SAVE(IDD_VERIFY);
|
|
}
|
|
|
|
if (k == 0 || k == 8) {
|
|
GET(IDD_LICENSE_FSRB);
|
|
SEARCH(IDC_EDIT1);
|
|
SEARCH(IDC_LICENSEAGREE);
|
|
SEARCH(IDC_LICENSEDISAGREE);
|
|
SAVE(IDD_LICENSE_FSRB);
|
|
}
|
|
|
|
if (k == 0 || k == 9) {
|
|
GET(IDD_LICENSE_FSCB);
|
|
SEARCH(IDC_EDIT1);
|
|
SEARCH(IDC_LICENSEAGREE);
|
|
SAVE(IDD_LICENSE_FSCB);
|
|
}
|
|
|
|
delete uire;
|
|
|
|
SCRIPT_MSG(_T("ChangeUI: %s %s%s\n"), line.gettoken_str(1), line.gettoken_str(2), branding_image_found?_T(" (branding image holder found)"):_T(""));
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error while changing UI: %s\n"), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
return PS_OK;
|
|
case TOK_ADDBRANDINGIMAGE:
|
|
#ifdef _WIN32
|
|
try {
|
|
int k=line.gettoken_enum(1,_T("top\0left\0bottom\0right\0"));
|
|
int wh=line.gettoken_int(2);
|
|
if (k == -1) PRINTHELP();
|
|
int padding = 2;
|
|
if (line.getnumtokens() == 4)
|
|
padding = line.gettoken_int(3);
|
|
|
|
init_res_editor();
|
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
|
|
|
CDialogTemplate dt(dlg, build_unicode, uDefCodePage);
|
|
|
|
res_editor->FreeResource(dlg);
|
|
|
|
DialogItemTemplate brandingCtl = {0,};
|
|
|
|
brandingCtl.dwStyle = SS_BITMAP | WS_CHILD | WS_VISIBLE;
|
|
brandingCtl.sX = padding;
|
|
brandingCtl.sY = padding;
|
|
brandingCtl.szClass = MAKEINTRESOURCEW(0x0082);
|
|
brandingCtl.szTitle = NULL;
|
|
brandingCtl.wId = IDC_BRANDIMAGE;
|
|
|
|
brandingCtl.sHeight = wh;
|
|
brandingCtl.sWidth = wh;
|
|
dt.PixelsToDlgUnits(brandingCtl.sWidth, brandingCtl.sHeight);
|
|
if (k%2) {
|
|
// left (1) / right (3)
|
|
|
|
if (k & 2) // right
|
|
brandingCtl.sX += dt.GetWidth();
|
|
else // left
|
|
dt.MoveAll(brandingCtl.sWidth + (padding * 2), 0);
|
|
|
|
dt.Resize(brandingCtl.sWidth + (padding * 2), 0);
|
|
|
|
brandingCtl.sHeight = dt.GetHeight() - (padding * 2);
|
|
}
|
|
else {
|
|
// top (0) / bottom (2)
|
|
|
|
if (k & 2) // bottom
|
|
brandingCtl.sY += dt.GetHeight();
|
|
else // top
|
|
dt.MoveAll(0, brandingCtl.sHeight + (padding * 2));
|
|
|
|
dt.Resize(0, brandingCtl.sHeight + (padding * 2));
|
|
|
|
brandingCtl.sWidth = dt.GetWidth() - (padding * 2);
|
|
}
|
|
|
|
dt.AddItem(brandingCtl);
|
|
|
|
DWORD dwDlgSize;
|
|
dlg = dt.Save(dwDlgSize);
|
|
|
|
res_editor->UpdateResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG, dlg, dwDlgSize);
|
|
|
|
delete [] dlg;
|
|
|
|
dt.DlgUnitsToPixels(brandingCtl.sWidth, brandingCtl.sHeight);
|
|
SCRIPT_MSG(_T("AddBrandingImage: %s %ux%u\n"), line.gettoken_str(1), brandingCtl.sWidth, brandingCtl.sHeight);
|
|
|
|
branding_image_found = true;
|
|
branding_image_id = IDC_BRANDIMAGE;
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error while adding image branding support: %s\n"), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
ERROR_MSG(_T("Error: AddBrandingImage is disabled for non Win32 platforms.\n"));
|
|
return PS_ERROR;
|
|
#endif
|
|
case TOK_SETFONT:
|
|
{
|
|
unsigned char failed = 0;
|
|
if (!_tcsnicmp(line.gettoken_str(1), _T("/LANG="), 6))
|
|
{
|
|
LANGID lang_id = _ttoi(line.gettoken_str(1) + 6);
|
|
LanguageTable *table = GetLangTable(lang_id);
|
|
const TCHAR*facename = line.gettoken_str(2);
|
|
#ifndef _UNICODE
|
|
if (build_include_isutf8)
|
|
{
|
|
EXEHEADTCHAR_T *bufEHTStr = UTF8ToExeHeadTStrDup(facename, table->nlf.m_uCodePage);
|
|
table->nlf.m_szFont = bufEHTStr;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
table->nlf.m_szFont = _tcsdup(facename);
|
|
}
|
|
table->nlf.m_iFontSize = line.gettoken_int(3);
|
|
|
|
if (table->nlf.m_szFont)
|
|
SCRIPT_MSG(_T("SetFont: lang=%d \"%s\" %s\n"), lang_id, facename, line.gettoken_str(3));
|
|
else
|
|
++failed;
|
|
}
|
|
else
|
|
{
|
|
const TCHAR*facename = line.gettoken_str(1);
|
|
#ifndef _UNICODE
|
|
if (build_include_isutf8)
|
|
{
|
|
EXEHEADTCHAR_T *bufEHTStr = UTF8ToExeHeadTStrDup(facename, CP_ACP);
|
|
if (!bufEHTStr) ++failed;
|
|
_tcsnccpy(build_font, bufEHTStr, COUNTOF(build_font));
|
|
free(bufEHTStr);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
_tcsnccpy(build_font, facename, COUNTOF(build_font));
|
|
}
|
|
build_font_size = line.gettoken_int(2);
|
|
|
|
if (!failed) SCRIPT_MSG(_T("SetFont: \"%s\" %s\n"), facename, line.gettoken_str(2));
|
|
}
|
|
if (failed)
|
|
{
|
|
ERROR_MSG(_T("Error: Unable to convert font name\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
case TOK_INSTCOLORS:
|
|
case TOK_XPSTYLE:
|
|
case TOK_CHANGEUI:
|
|
case TOK_ADDBRANDINGIMAGE:
|
|
case TOK_SETFONT:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif// NSIS_CONFIG_VISIBLE_SUPPORT
|
|
|
|
case TOK_REQEXECLEVEL:
|
|
switch (line.gettoken_enum(1,_T("none\0user\0highest\0admin\0")))
|
|
{
|
|
case 0: manifest_exec_level = manifest::exec_level_none; break;
|
|
case 1: manifest_exec_level = manifest::exec_level_user; break;
|
|
case 2: manifest_exec_level = manifest::exec_level_highest; break;
|
|
case 3: manifest_exec_level = manifest::exec_level_admin; break;
|
|
default: PRINTHELP();
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_MANIFEST_DPIAWARE:
|
|
switch(line.gettoken_enum(1,_T("none\0notset\0true\0false\0")))
|
|
{
|
|
case 0: // A lot of attributes use "none" so we support that along with the documented value
|
|
case 1: manifest_dpiaware = manifest::dpiaware_notset; break;
|
|
case 2: manifest_dpiaware = manifest::dpiaware_true; break;
|
|
case 3: manifest_dpiaware = manifest::dpiaware_false; break;
|
|
default: PRINTHELP();
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_MANIFEST_SUPPORTEDOS:
|
|
{
|
|
manifest_sosl.deleteall();
|
|
if (2 == line.getnumtokens())
|
|
{
|
|
switch(line.gettoken_enum(1,_T("none\0all\0")))
|
|
{
|
|
case 0:
|
|
return PS_OK;
|
|
case 1:
|
|
manifest_sosl.addall();
|
|
return PS_OK;
|
|
}
|
|
}
|
|
for(int argi = 1; argi < line.getnumtokens(); ++argi)
|
|
{
|
|
if (!manifest_sosl.append(line.gettoken_str(argi)))
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
return PS_OK;
|
|
|
|
#ifdef _UNICODE
|
|
case TOK_TARGETUNICODE:
|
|
{
|
|
if (build_compressor_set)
|
|
{
|
|
ERROR_MSG(_T("Error: Can't change target charset after data already got compressed or header already changed!\n"));
|
|
return PS_ERROR;
|
|
}
|
|
int k = line.gettoken_enum(1,_T("false\0true\0"));
|
|
if (-1==k) PRINTHELP();
|
|
SCRIPT_MSG(_T("Unicode: %s\n"),k?_T("true"):_T("false"));
|
|
if (set_target_charset(!!k) != PS_OK)
|
|
{
|
|
ERROR_MSG(_T("Error: Unable to set target charset (adequate stub not found?)\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
return PS_OK;
|
|
#endif
|
|
|
|
// Ability to change compression methods from within the script
|
|
case TOK_SETCOMPRESSOR:
|
|
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
|
{
|
|
if (build_compressor_set) {
|
|
ERROR_MSG(_T("Error: can't change compressor after data already got compressed or header already changed!\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (build_compressor_final)
|
|
{
|
|
warning_fl(_T("SetCompressor ignored due to previous call with the /FINAL switch"));
|
|
return PS_OK;
|
|
}
|
|
|
|
int a = 1;
|
|
|
|
build_compress_whole = false;
|
|
|
|
while (line.gettoken_str(a)[0] == _T('/'))
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("/FINAL")))
|
|
{
|
|
build_compressor_final = true;
|
|
a++;
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(a),_T("/SOLID")))
|
|
{
|
|
build_compress_whole = true;
|
|
a++;
|
|
}
|
|
else PRINTHELP();
|
|
}
|
|
|
|
if (a != line.getnumtokens() - 1)
|
|
{
|
|
ERROR_MSG(_T("%s expects %d parameters, got %d.\n"), line.gettoken_str(0), a + 1, line.getnumtokens());
|
|
PRINTHELP();
|
|
}
|
|
|
|
int k=line.gettoken_enum(a, _T("zlib\0bzip2\0lzma\0"));
|
|
switch (k) {
|
|
case 0:
|
|
compressor = &zlib_compressor;
|
|
break;
|
|
|
|
case 1:
|
|
compressor = &bzip2_compressor;
|
|
break;
|
|
|
|
case 2:
|
|
compressor = &lzma_compressor;
|
|
break;
|
|
|
|
default:
|
|
PRINTHELP();
|
|
}
|
|
|
|
tstring compressor_name = line.gettoken_str(a);
|
|
compressor_name = lowercase(compressor_name);
|
|
|
|
if (set_compressor(compressor_name, build_compress_whole) != PS_OK)
|
|
{
|
|
SCRIPT_MSG(_T("SetCompressor: error loading stub for \"%s\" compressor.\n"), compressor_name.c_str());
|
|
return PS_ERROR;
|
|
}
|
|
|
|
SCRIPT_MSG(_T("SetCompressor: %s%s%s\n"), build_compressor_final ? _T("/FINAL ") : _T(""), build_compress_whole ? _T("/SOLID ") : _T(""), line.gettoken_str(a));
|
|
}
|
|
return PS_OK;
|
|
#else//NSIS_CONFIG_COMPRESSION_SUPPORT
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_COMPRESSION_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
|
|
case TOK_LOADNLF:
|
|
{
|
|
SCRIPT_MSG(_T("LoadLanguageFile: %s\n"), line.gettoken_str(1));
|
|
|
|
LanguageTable *table = LoadLangFile(line.gettoken_str(1));
|
|
|
|
if (!table)
|
|
return PS_ERROR;
|
|
|
|
if (!defcodepage_set)
|
|
{
|
|
uDefCodePage = table->nlf.m_uCodePage;
|
|
defcodepage_set = true;
|
|
}
|
|
|
|
last_used_lang = table->lang_id;
|
|
// define LANG_LangName as "####" (lang id)
|
|
// for example ${LANG_ENGLISH} = 1033
|
|
TCHAR lang_id[16];
|
|
TCHAR lang_cp[16];
|
|
TCHAR lang_name[1024];
|
|
wsprintf(lang_name, _T("LANG_%s"), table->nlf.m_szName);
|
|
wsprintf(lang_id, _T("%u"), table->lang_id);
|
|
wsprintf(lang_cp, _T("%u"), table->nlf.m_uCodePage);
|
|
definedlist.add(lang_name, lang_id);
|
|
wsprintf(lang_name, _T("LANG_%s_CP"), table->nlf.m_szName);
|
|
definedlist.add(lang_name, lang_cp);
|
|
}
|
|
return PS_OK;
|
|
|
|
// preprocessor-ish (ifdef/ifndef/else/endif are handled one step out from here)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
case TOK_P_DEFINE:
|
|
{
|
|
TCHAR *define=line.gettoken_str(1);
|
|
TCHAR *value;
|
|
GrowBuf file_buf;
|
|
TCHAR datebuf[256];
|
|
TCHAR mathbuf[256];
|
|
int dupemode=0;
|
|
|
|
|
|
if (!_tcsicmp(define,_T("/ifndef")))
|
|
dupemode=1;
|
|
else if (!_tcsicmp(define,_T("/redef")))
|
|
dupemode=2;
|
|
|
|
if (dupemode!=0)
|
|
{
|
|
line.eattoken();
|
|
define=line.gettoken_str(1);
|
|
if (dupemode==1 && definedlist.find(define))return PS_OK;
|
|
}
|
|
|
|
|
|
if (!_tcsicmp(define,_T("/date")) || !_tcsicmp(define,_T("/utcdate"))) {
|
|
if (line.getnumtokens()!=4) PRINTHELP()
|
|
|
|
TCHAR *date_type = define;
|
|
|
|
define=line.gettoken_str(2);
|
|
value=line.gettoken_str(3);
|
|
|
|
time_t rawtime;
|
|
time(&rawtime);
|
|
|
|
if (!_tcsicmp(date_type,_T("/utcdate")))
|
|
rawtime = mktime(gmtime(&rawtime));
|
|
|
|
datebuf[0]=0;
|
|
size_t s=_tcsftime(datebuf,COUNTOF(datebuf),value,localtime(&rawtime));
|
|
|
|
if (s == 0)
|
|
datebuf[0]=0;
|
|
else
|
|
datebuf[max(s,COUNTOF(datebuf)-1)]=0;
|
|
|
|
value=datebuf;
|
|
} else if (!_tcsicmp(define,_T("/file")) || !_tcsicmp(define,_T("/file_noerr"))) {
|
|
|
|
if (line.getnumtokens()!=4) PRINTHELP()
|
|
|
|
define=line.gettoken_str(2);
|
|
const TCHAR *filename=line.gettoken_str(3);
|
|
FILE *fp=FOPENTEXT(filename,"r");
|
|
|
|
if (!fp && _tcsicmp(define,_T("/file_noerr"))) {
|
|
ERROR_MSG(_T("!define /file: file not found (\"%s\")\n"),filename);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (fp) {
|
|
TCHAR str[MAX_LINELENGTH];
|
|
for (;;) {
|
|
TCHAR *p=str;
|
|
*p=0;
|
|
_fgetts(str,MAX_LINELENGTH,fp);
|
|
linecnt++;
|
|
if (feof(fp)&&!str[0]) break;
|
|
|
|
while (*p) p++;
|
|
if (p > str) p--;
|
|
while (p >= str && (*p == _T('\r') || *p == _T('\n'))) p--;
|
|
*++p=0;
|
|
if (file_buf.getlen()) file_buf.add(_T("\n"),1);
|
|
file_buf.add(str,_tcslen(str));
|
|
}
|
|
fclose(fp);
|
|
}
|
|
file_buf.add(_T("\0"),1);
|
|
value = (TCHAR *)file_buf.get();
|
|
|
|
} else if (!_tcsicmp(define,_T("/math"))) {
|
|
|
|
int value1;
|
|
int value2;
|
|
TCHAR *mathop;
|
|
|
|
if (line.getnumtokens()!=6) PRINTHELP()
|
|
|
|
define = line.gettoken_str(2);
|
|
value1 = line.gettoken_int(3);
|
|
mathop = line.gettoken_str(4);
|
|
value2 = line.gettoken_int(5);
|
|
value = mathbuf;
|
|
|
|
if (!_tcscmp(mathop,_T("+"))) {
|
|
_stprintf(value,_T("%d"),value1+value2);
|
|
} else if (!_tcscmp(mathop,_T("-"))) {
|
|
_stprintf(value,_T("%d"),value1-value2);
|
|
} else if (!_tcscmp(mathop,_T("*"))) {
|
|
_stprintf(value,_T("%d"),value1*value2);
|
|
} else if (!_tcscmp(mathop,_T("&"))) {
|
|
_stprintf(value,_T("%d"),value1&value2);
|
|
} else if (!_tcscmp(mathop,_T("|"))) {
|
|
_stprintf(value,_T("%d"),value1|value2);
|
|
} else if (!_tcscmp(mathop,_T("^"))) {
|
|
_stprintf(value,_T("%d"),value1^value2);
|
|
} else if (!_tcscmp(mathop,_T("<<")) || !_tcscmp(mathop,_T("<<<")) ) {
|
|
_stprintf(value,_T("%d"),value1<<value2);
|
|
} else if (!_tcscmp(mathop,_T(">>"))) {
|
|
_stprintf(value,_T("%d"),(signed)value1>>(signed)value2);
|
|
} else if (!_tcscmp(mathop,_T(">>>"))) {
|
|
_stprintf(value,_T("%d"),(unsigned)value1>>(unsigned)value2);
|
|
} else if (!_tcscmp(mathop,_T("/"))) {
|
|
if (value2==0) {
|
|
ERROR_MSG(_T("!define /math: division by zero! (\"%i / %i\")\n"),value1,value2);
|
|
return PS_ERROR;
|
|
}
|
|
_stprintf(value,_T("%d"),value1/value2);
|
|
} else if (!_tcscmp(mathop,_T("%"))) {
|
|
if (value2==0) {
|
|
ERROR_MSG(_T("!define /math: division by zero! (\"%i %% %i\")\n"),value1,value2);
|
|
return PS_ERROR;
|
|
}
|
|
_stprintf(value,_T("%d"),value1%value2);
|
|
} else PRINTHELP()
|
|
|
|
} else {
|
|
if (line.getnumtokens()==4) PRINTHELP()
|
|
|
|
value=line.gettoken_str(2);
|
|
}
|
|
|
|
if (dupemode==2)definedlist.del(define);
|
|
if (definedlist.add(define,value))
|
|
{
|
|
ERROR_MSG(_T("!define: \"%s\" already defined!\n"),define);
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("!define: \"%s\"=\"%s\"\n"),define,value);
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_UNDEF:
|
|
if (definedlist.del(line.gettoken_str(1)))
|
|
{
|
|
ERROR_MSG(_T("!undef: \"%s\" not defined!\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("!undef: \"%s\"\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
case TOK_P_PACKEXEHEADER:
|
|
_tcsnccpy(build_packname,line.gettoken_str(1),COUNTOF(build_packname)-1);
|
|
_tcsnccpy(build_packcmd,line.gettoken_str(2),COUNTOF(build_packcmd)-1);
|
|
SCRIPT_MSG(_T("!packhdr: filename=\"%s\", command=\"%s\"\n"),
|
|
build_packname, build_packcmd);
|
|
return PS_OK;
|
|
case TOK_P_FINALIZE:
|
|
{
|
|
TCHAR* cmdstr=line.gettoken_str(1);
|
|
struct postbuild_cmd *newcmd, *prevcmd;
|
|
newcmd = (struct postbuild_cmd*) new BYTE[FIELD_OFFSET(struct postbuild_cmd,cmd[_tcsclen(cmdstr)+1])];
|
|
newcmd->next=NULL;
|
|
_tcscpy(newcmd->cmd,cmdstr);
|
|
for (prevcmd=postbuild_cmds; prevcmd && prevcmd->next;) prevcmd = prevcmd->next;
|
|
if (prevcmd) prevcmd->next = newcmd; else postbuild_cmds = newcmd;
|
|
SCRIPT_MSG(_T("!finalize: \"%s\"\n"),cmdstr);
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_SYSTEMEXEC:
|
|
{
|
|
TCHAR *exec=line.gettoken_str(1);
|
|
int comp=line.gettoken_enum(2,_T("<\0>\0<>\0=\0ignore\0"));
|
|
if (line.getnumtokens() == 2) comp = 4;
|
|
if (comp == -1 && line.getnumtokens() == 3) comp=4;
|
|
if (comp == -1) PRINTHELP()
|
|
int success=0;
|
|
int cmpv=line.gettoken_int(3,&success);
|
|
if (!success && comp != 4) PRINTHELP()
|
|
SCRIPT_MSG(_T("!system: \"%s\"\n"),exec);
|
|
#ifdef _WIN32
|
|
int ret=sane_system(exec);
|
|
#else
|
|
PATH_CONVERT(exec);
|
|
int ret=system(exec);
|
|
#endif
|
|
if (comp == 0 && ret < cmpv);
|
|
else if (comp == 1 && ret > cmpv);
|
|
else if (comp == 2 && ret != cmpv);
|
|
else if (comp == 3 && ret == cmpv);
|
|
else if (comp == 4);
|
|
else
|
|
{
|
|
ERROR_MSG(_T("!system: returned %d, aborting\n"),ret);
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("!system: returned %d\n"),ret);
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_EXECUTE:
|
|
{
|
|
TCHAR *exec=line.gettoken_str(1);
|
|
SCRIPT_MSG(_T("!execute: \"%s\"\n"),exec);
|
|
#ifdef _WIN32
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si={sizeof(STARTUPINFO),};
|
|
if (CreateProcess(NULL,exec,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
|
|
{
|
|
WaitForSingleObject(pi.hProcess,INFINITE);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
#else
|
|
TCHAR *execfixed = my_convert(exec);
|
|
system(execfixed);
|
|
my_convert_free(execfixed);
|
|
#endif
|
|
}
|
|
case TOK_P_ADDINCLUDEDIR:
|
|
{
|
|
TCHAR *f = line.gettoken_str(1);
|
|
PATH_CONVERT(f);
|
|
include_dirs.add(f,0);
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_INCLUDE:
|
|
{
|
|
bool required = true;
|
|
|
|
TCHAR *f = line.gettoken_str(1);
|
|
|
|
if(!_tcsicmp(f,_T("/nonfatal"))) {
|
|
if (line.getnumtokens()!=3)
|
|
PRINTHELP();
|
|
|
|
f = line.gettoken_str(2);
|
|
required = false;
|
|
} else if (line.getnumtokens()!=2) {
|
|
PRINTHELP();
|
|
}
|
|
|
|
TCHAR *fc = my_convert(f);
|
|
int included = 0;
|
|
|
|
tstring dir = get_dir_name(fc);
|
|
tstring spec = get_file_name(fc);
|
|
tstring basedir = dir + PLATFORM_PATH_SEPARATOR_STR;
|
|
if (dir == spec) {
|
|
// no path, just file name
|
|
dir = _T(".");
|
|
basedir = _T("");
|
|
}
|
|
|
|
my_convert_free(fc);
|
|
|
|
// search working directory
|
|
boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
|
|
dr->read(dir);
|
|
|
|
for (dir_reader::iterator files_itr = dr->files().begin();
|
|
files_itr != dr->files().end();
|
|
files_itr++)
|
|
{
|
|
if (!dir_reader::matches(*files_itr, spec))
|
|
continue;
|
|
|
|
tstring incfile = basedir + *files_itr;
|
|
|
|
if (includeScript((TCHAR *) incfile.c_str()) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
|
|
included++;
|
|
}
|
|
|
|
if (included)
|
|
return PS_OK;
|
|
|
|
// search include dirs
|
|
TCHAR *incdir = include_dirs.get();
|
|
int incdirs = include_dirs.getnum();
|
|
|
|
for (int i = 0; i < incdirs; i++, incdir += _tcslen(incdir) + 1) {
|
|
tstring curincdir = tstring(incdir) + PLATFORM_PATH_SEPARATOR_STR + dir;
|
|
|
|
boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
|
|
dr->read(curincdir);
|
|
|
|
for (dir_reader::iterator incdir_itr = dr->files().begin();
|
|
incdir_itr != dr->files().end();
|
|
incdir_itr++)
|
|
{
|
|
if (!dir_reader::matches(*incdir_itr, spec))
|
|
continue;
|
|
|
|
tstring incfile = tstring(incdir) + PLATFORM_PATH_SEPARATOR_STR + basedir + *incdir_itr;
|
|
|
|
if (includeScript((TCHAR *) incfile.c_str()) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
|
|
included++;
|
|
}
|
|
|
|
if (included)
|
|
return PS_OK;
|
|
|
|
}
|
|
|
|
// nothing found
|
|
if (!included)
|
|
{
|
|
if(required) {
|
|
ERROR_MSG(_T("!include: could not find: \"%s\"\n"),f);
|
|
return PS_ERROR;
|
|
} else {
|
|
warning_fl(_T("!include: could not find: \"%s\""),f);
|
|
}
|
|
}
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_CD:
|
|
if (!line.gettoken_str(1)[0] || _tchdir(line.gettoken_str(1)))
|
|
{
|
|
ERROR_MSG(_T("!cd: error changing to: \"%s\"\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_ERROR:
|
|
ERROR_MSG(_T("!error: %s\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
case TOK_P_WARNING:
|
|
warning_fl(_T("!warning: %s"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
case TOK_P_ECHO:
|
|
SCRIPT_MSG(_T("%s (%s:%d)\n"), line.gettoken_str(1),curfilename,linecnt);
|
|
return PS_OK;
|
|
case TOK_P_SEARCHPARSESTRING:
|
|
{
|
|
bool ignCase=false;
|
|
bool noErrors=false;
|
|
bool isFile=false;
|
|
int parmOffs=1;
|
|
while (parmOffs < line.getnumtokens())
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(parmOffs),_T("/ignorecase"))) { ignCase=true; parmOffs++; }
|
|
else if (!_tcsicmp(line.gettoken_str(parmOffs),_T("/noerrors"))) { noErrors=true; parmOffs++; }
|
|
else if (!_tcsicmp(line.gettoken_str(parmOffs),_T("/file"))) { isFile=true; parmOffs++; }
|
|
else break;
|
|
}
|
|
if (parmOffs+3 > line.getnumtokens())
|
|
{
|
|
ERROR_MSG(_T("!searchparse: not enough parameters\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
const TCHAR *source_string = line.gettoken_str(parmOffs++);
|
|
DefineList *list=NULL;
|
|
|
|
if (isFile)
|
|
{
|
|
FILE *fp=FOPENTEXT(source_string,"r");
|
|
if (!fp)
|
|
{
|
|
ERROR_MSG(_T("!searchparse /file: error opening \"%s\"\n"),source_string);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
int req_parm = (line.getnumtokens() - parmOffs)/2;
|
|
|
|
GrowBuf tmpstr;
|
|
TCHAR str[MAX_LINELENGTH];
|
|
for (;;)
|
|
{
|
|
tmpstr.resize(0);
|
|
for (;;)
|
|
{
|
|
str[0]=0;
|
|
_fgetts(str,COUNTOF(str),fp);
|
|
if (!str[0]) break; // eof
|
|
|
|
TCHAR *p=str;
|
|
while (*p) p++;
|
|
if (p > str) p--;
|
|
while (p >= str && (*p == _T('\r') || *p == _T('\n'))) p--;
|
|
*++p=0;
|
|
|
|
bool endSlash = (str[0] && str[_tcslen(str)-1] == _T('\\'));
|
|
if (tmpstr.getlen() || endSlash) tmpstr.add(str,sizeof(TCHAR)*_tcslen(str));
|
|
|
|
// if we have valid contents and not ending on slash, then done
|
|
if (!endSlash && (str[0] || tmpstr.getlen())) break;
|
|
}
|
|
|
|
if (!str[0] && !tmpstr.getlen()) break; // reached eof
|
|
|
|
TCHAR *thisline=str;
|
|
if (tmpstr.getlen())
|
|
{
|
|
tmpstr.add(_T("\0"),sizeof(TCHAR));
|
|
thisline=(TCHAR *)tmpstr.get();
|
|
}
|
|
|
|
DefineList *tlist = searchParseString(thisline,&line,parmOffs,ignCase,true);
|
|
if (tlist && tlist->getnum())
|
|
{
|
|
if (!list || tlist->getnum() > list->getnum())
|
|
{
|
|
delete list;
|
|
list=tlist;
|
|
if (tlist->getnum() >= req_parm) break; // success!
|
|
}
|
|
else delete list;
|
|
}
|
|
// parse line
|
|
}
|
|
fclose(fp);
|
|
if (!noErrors)
|
|
{
|
|
if (!list)
|
|
{
|
|
ERROR_MSG(_T("!searchparse: starting string \"%s\" not found in file!\n"),line.gettoken_str(parmOffs));
|
|
return PS_ERROR;
|
|
}
|
|
else if (list->getnum() < req_parm)
|
|
{
|
|
TCHAR *p=line.gettoken_str(parmOffs + list->getnum()*2);
|
|
ERROR_MSG(_T("!searchparse: failed search at string \"%s\" not found in file!\n"),p?p:_T("(null)"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
list=searchParseString(source_string,&line,parmOffs,ignCase,noErrors);
|
|
if (!list && !noErrors) return PS_ERROR;
|
|
}
|
|
|
|
if (list) // if we got our list, merge them defines in
|
|
{
|
|
int i;
|
|
for (i=0;i<list->getnum(); i ++)
|
|
{
|
|
TCHAR *def=list->getname(i);
|
|
TCHAR *val=list->getvalue(i);
|
|
if (def && val)
|
|
{
|
|
if (definedlist.find(def)) definedlist.del(def);
|
|
definedlist.add(def,val);
|
|
}
|
|
}
|
|
}
|
|
delete list;
|
|
}
|
|
return PS_OK;
|
|
case TOK_P_SEARCHREPLACESTRING:
|
|
{
|
|
int ignoreCase=!_tcsicmp(line.gettoken_str(1),_T("/ignorecase"));
|
|
if (line.getnumtokens()!=5+ignoreCase) PRINTHELP()
|
|
|
|
TCHAR *define=line.gettoken_str(1+ignoreCase);
|
|
TCHAR *src = line.gettoken_str(2+ignoreCase);
|
|
TCHAR *search = line.gettoken_str(3+ignoreCase);
|
|
TCHAR *replace = line.gettoken_str(4+ignoreCase);
|
|
int searchlen=_tcslen(search);
|
|
int replacelen=_tcslen(replace);
|
|
if (!searchlen)
|
|
{
|
|
ERROR_MSG(_T("!searchreplace: search string must not be empty for search/replace!\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
GrowBuf valout;
|
|
|
|
while (*src)
|
|
{
|
|
if (ignoreCase ? _tcsnicmp(src,search,searchlen) : _tcsncmp(src,search,searchlen))
|
|
valout.add(src++,sizeof(TCHAR));
|
|
else
|
|
{
|
|
valout.add(replace,sizeof(TCHAR)*replacelen);
|
|
src+=searchlen;
|
|
}
|
|
}
|
|
|
|
valout.add(_T(""),sizeof(TCHAR));
|
|
|
|
definedlist.del(define); // allow changing variables since we'll often use this in series
|
|
|
|
if (definedlist.add(define,(TCHAR*)valout.get()))
|
|
{
|
|
ERROR_MSG(_T("!searchreplace: error defining \"%s\"!\n"),define);
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("!searchreplace: \"%s\"=\"%s\"\n"),define,(TCHAR*)valout.get());
|
|
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_P_VERBOSE:
|
|
{
|
|
extern int g_display_errors;
|
|
for(int argi=1; argi<line.getnumtokens(); ++argi)
|
|
{
|
|
int v,k=line.gettoken_enum(argi,_T("push\0pop\0"));
|
|
if (k < 0)
|
|
{
|
|
// just set
|
|
int numconv;
|
|
v=line.gettoken_int(argi,&numconv);
|
|
if (!numconv || v < 0 || v > 4 )
|
|
{
|
|
// < 2.47 would reset level to 0 without warning!
|
|
ERROR_MSG(_T("!verbose: Invalid verbose level\n"));
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (k)
|
|
{
|
|
// pop
|
|
int l=verbose_stack.getlen();
|
|
if (l)
|
|
{
|
|
v=((int*)verbose_stack.get())[(l/sizeof(int))-1];
|
|
verbose_stack.resize(l-sizeof(int));
|
|
}
|
|
else
|
|
{
|
|
warning_fl(_T("!verbose: Pop failed, stack is empty"));
|
|
continue; // Pop failed, should still process the next parameter
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// push
|
|
v=0;
|
|
if (display_errors)
|
|
{
|
|
v++;
|
|
if (display_warnings)
|
|
{
|
|
v++;
|
|
if (display_info)
|
|
{
|
|
v++;
|
|
if (display_script)
|
|
{
|
|
v++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
verbose_stack.add(&v,sizeof(int));
|
|
continue;
|
|
}
|
|
}
|
|
display_script=v>3;
|
|
display_info=v>2;
|
|
display_warnings=v>1;
|
|
display_errors=v>0;
|
|
g_display_errors=display_errors;
|
|
}
|
|
}
|
|
return PS_OK;
|
|
|
|
case TOK_UNINSTALLEXENAME: PRINTHELP()
|
|
|
|
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
case TOK_UNINSTCAPTION:
|
|
{
|
|
if (SetInnerString(NLF_UCAPTION,line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
SCRIPT_MSG(_T("UninstCaption: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_UNINSTICON:
|
|
SCRIPT_MSG(_T("UninstallIcon: \"%s\"\n"),line.gettoken_str(1));
|
|
try {
|
|
free_loaded_icon(uninstaller_icon);
|
|
uninstaller_icon = load_icon_file(line.gettoken_str(1));
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error while loading icon from \"%s\": %s\n"), line.gettoken_str(1), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
return PS_OK;
|
|
case TOK_UNINSTTEXT:
|
|
{
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_UNINST_TEXT, line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
SetInnerString(NLF_UNINST_SUBTEXT, line.gettoken_str(2));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_UNINSTCONFIRM) {
|
|
ERROR_MSG(_T("Error: UninstallText can only be used inside PageEx uninstConfirm.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[0] = add_string(line.gettoken_str(1));
|
|
cur_page->parms[1] = add_string(line.gettoken_str(2));
|
|
}
|
|
SCRIPT_MSG(_T("UninstallText: \"%s\" \"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
}
|
|
return PS_OK;
|
|
case TOK_UNINSTSUBCAPTION:
|
|
{
|
|
int s;
|
|
int w=line.gettoken_int(1,&s);
|
|
if (!s || w < 0 || w > 2) PRINTHELP()
|
|
SetInnerString(NLF_USUBCAPTION_CONFIRM+w,line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("UninstSubCaption: page:%d, text=%s\n"),w,line.gettoken_str(2));
|
|
}
|
|
return PS_OK;
|
|
case TOK_WRITEUNINSTALLER:
|
|
{
|
|
if (uninstall_mode)
|
|
{
|
|
ERROR_MSG(_T("WriteUninstaller only valid from install, not from uninstall.\n"));
|
|
PRINTHELP()
|
|
}
|
|
uninstaller_writes_used++;
|
|
ent.which=EW_WRITEUNINSTALLER;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
tstring full = tstring(_T("$INSTDIR\\")) + tstring(line.gettoken_str(1));
|
|
ent.offsets[3]=add_string(full.c_str());
|
|
// ent.offsets[1] and ent.offsets[2] are set in CEXEBuild::uninstall_generate()
|
|
if (!ent.offsets[0]) PRINTHELP()
|
|
SCRIPT_MSG(_T("WriteUninstaller: \"%s\"\n"),line.gettoken_str(1));
|
|
|
|
DefineInnerLangString(NLF_ERR_CREATING);
|
|
DefineInnerLangString(NLF_CREATED_UNINST);
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
case TOK_WRITEUNINSTALLER:
|
|
case TOK_UNINSTCAPTION:
|
|
case TOK_UNINSTICON:
|
|
case TOK_UNINSTTEXT:
|
|
case TOK_UNINSTSUBCAPTION:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif
|
|
|
|
|
|
|
|
// section/function stuff
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
case TOK_SECTION:
|
|
{
|
|
int a=1,unselected = 0;
|
|
if (!_tcsicmp(line.gettoken_str(1),_T("/o")))
|
|
{
|
|
unselected = 1;
|
|
a++;
|
|
}
|
|
else if (line.getnumtokens() > 3)
|
|
PRINTHELP();
|
|
SCRIPT_MSG(_T("Section: \"%s\""),line.gettoken_str(a));
|
|
if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(_T(" ->(%s)"),line.gettoken_str(a+1));
|
|
SCRIPT_MSG(_T("\n"));
|
|
#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("uninstall")))
|
|
{
|
|
ERROR_MSG(_T("Error: Uninstall section declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n"));
|
|
return PS_ERROR;
|
|
}
|
|
#endif
|
|
|
|
int ret;
|
|
|
|
ret=add_section(line.gettoken_str(a),line.gettoken_str(a+1));
|
|
if (ret != PS_OK) return ret;
|
|
|
|
if (unselected)
|
|
build_cursection->flags &= ~SF_SELECTED;
|
|
|
|
return PS_OK;
|
|
}
|
|
case TOK_SECTIONEND:
|
|
SCRIPT_MSG(_T("SectionEnd\n"));
|
|
return section_end();
|
|
case TOK_SECTIONIN:
|
|
{
|
|
SCRIPT_MSG(_T("SectionIn: "));
|
|
int wt;
|
|
for (wt = 1; wt < line.getnumtokens(); wt ++)
|
|
{
|
|
TCHAR *p=line.gettoken_str(wt);
|
|
if (!_tcsicmp(p, _T("RO")))
|
|
{
|
|
if (section_add_flags(SF_RO) != PS_OK) return PS_ERROR;
|
|
SCRIPT_MSG(_T("[RO] "));
|
|
}
|
|
else
|
|
{
|
|
int x=_ttoi(p)-1;
|
|
if (x >= 0 && x < NSIS_MAX_INST_TYPES)
|
|
{
|
|
if (section_add_install_type(1<<x) != PS_OK) return PS_ERROR;
|
|
SCRIPT_MSG(_T("[%d] "),x);
|
|
}
|
|
else if (x < 0)
|
|
{
|
|
PRINTHELP()
|
|
}
|
|
else
|
|
{
|
|
ERROR_MSG(_T("Error: SectionIn section %d out of range 1-%d\n"),x+1,NSIS_MAX_INST_TYPES);
|
|
return PS_ERROR;
|
|
}
|
|
p++;
|
|
}
|
|
}
|
|
SCRIPT_MSG(_T("\n"));
|
|
}
|
|
return PS_OK;
|
|
case TOK_SECTIONGROUPEND:
|
|
case TOK_SUBSECTIONEND:
|
|
case TOK_SECTIONGROUP:
|
|
case TOK_SUBSECTION:
|
|
{
|
|
TCHAR buf[1024];
|
|
int a=1,ex = 0;
|
|
if (!_tcsicmp(line.gettoken_str(1),_T("/e")))
|
|
{
|
|
ex = 1;
|
|
a++;
|
|
}
|
|
wsprintf(buf,_T("\x1F%s"),line.gettoken_str(a));
|
|
if (which_token == TOK_SECTIONGROUP || which_token == TOK_SUBSECTION)
|
|
{
|
|
TCHAR *s = line.gettoken_str(a);
|
|
if (!s[0] || (!_tcsicmp(s, _T("un.")) && !s[3]))
|
|
PRINTHELP();
|
|
}
|
|
|
|
SCRIPT_MSG(_T("%s %s"),line.gettoken_str(0),line.gettoken_str(a));
|
|
if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(_T(" ->(%s)"),line.gettoken_str(a+1));
|
|
SCRIPT_MSG(_T("\n"));
|
|
return add_section(buf,line.gettoken_str(a+1),ex);
|
|
}
|
|
case TOK_FUNCTION:
|
|
if (!line.gettoken_str(1)[0]) PRINTHELP()
|
|
if (line.gettoken_str(1)[0]==_T(':') || line.gettoken_str(1)[0]==_T('/'))
|
|
{
|
|
ERROR_MSG(_T("Function: function name cannot begin with : or /.\n"));
|
|
PRINTHELP()
|
|
}
|
|
SCRIPT_MSG(_T("Function: \"%s\"\n"),line.gettoken_str(1));
|
|
#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
if (!_tcsnicmp(line.gettoken_str(1),_T("un."),3))
|
|
{
|
|
ERROR_MSG(_T("Error: Uninstall function declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n"));
|
|
return PS_ERROR;
|
|
}
|
|
#endif
|
|
return add_function(line.gettoken_str(1));
|
|
case TOK_FUNCTIONEND:
|
|
SCRIPT_MSG(_T("FunctionEnd\n"));
|
|
return function_end();
|
|
|
|
// flag setters
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// BEGIN - Added by ramon 23 May 2003
|
|
case TOK_ALLOWSKIPFILES:
|
|
build_allowskipfiles=line.gettoken_enum(1,_T("off\0on\0"));
|
|
if (build_allowskipfiles==-1) PRINTHELP()
|
|
SCRIPT_MSG(_T("AllowSkipFiles: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
// END - Added by ramon 23 May 2003
|
|
case TOK_SETDATESAVE:
|
|
build_datesave=line.gettoken_enum(1,_T("off\0on\0"));
|
|
if (build_datesave==-1) PRINTHELP()
|
|
SCRIPT_MSG(_T("SetDateSave: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
case TOK_SETOVERWRITE:
|
|
{
|
|
int k=line.gettoken_enum(1,_T("on\0off\0try\0ifnewer\0ifdiff\0lastused\0"));
|
|
if (k==-1) PRINTHELP()
|
|
if (k==5)
|
|
{
|
|
k=build_overwrite;
|
|
build_overwrite=build_last_overwrite;
|
|
build_last_overwrite=k;
|
|
}
|
|
else
|
|
{
|
|
build_last_overwrite=build_overwrite;
|
|
build_overwrite=k;
|
|
}
|
|
SCRIPT_MSG(_T("SetOverwrite: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
|
case TOK_SETPLUGINUNLOAD:
|
|
build_plugin_unload=line.gettoken_enum(1,_T("manual\0alwaysoff\0"));
|
|
if (build_plugin_unload==-1) PRINTHELP()
|
|
SCRIPT_MSG(_T("SetPluginUnload: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
#endif //NSIS_CONFIG_PLUGIN_SUPPORT
|
|
case TOK_SETCOMPRESS:
|
|
build_compress=line.gettoken_enum(1,_T("off\0auto\0force\0"));
|
|
if (build_compress==-1) PRINTHELP()
|
|
if (build_compress==0 && build_compress_whole)
|
|
{
|
|
warning_fl(_T("'SetCompress off' encountered, and in whole compression mode. Effectively ignored."));
|
|
}
|
|
SCRIPT_MSG(_T("SetCompress: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
case TOK_DBOPTIMIZE:
|
|
build_optimize_datablock=line.gettoken_enum(1,_T("off\0on\0"));
|
|
if (build_optimize_datablock==-1) PRINTHELP()
|
|
SCRIPT_MSG(_T("SetDatablockOptimize: %s\n"),line.gettoken_str(1));
|
|
return PS_OK;
|
|
case TOK_FILEBUFSIZE:
|
|
build_filebuflen=line.gettoken_int(1);
|
|
build_filebuflen<<=20;
|
|
if (build_filebuflen<=0)
|
|
{
|
|
ERROR_MSG(_T("Error: FileBufSize: invalid buffer size -- %d\n"),build_filebuflen);
|
|
return PS_ERROR;
|
|
}
|
|
SCRIPT_MSG(_T("FileBufSize: %smb (%d bytes)\n"),line.gettoken_str(1),build_filebuflen);
|
|
return PS_OK;
|
|
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
|
case TOK_SETCOMPRESSIONLEVEL:
|
|
{
|
|
if (compressor == &lzma_compressor)
|
|
warning_fl(_T("SetCompressionLevel: compressor is set to LZMA. Effectively ignored."));
|
|
if (build_compressor_set && build_compress_whole)
|
|
warning_fl(_T("SetCompressionLevel: data already compressed in compress whole mode. Effectively ignored."));
|
|
|
|
int s;
|
|
build_compress_level=line.gettoken_int(1,&s);
|
|
if (!s || build_compress_level < 0 || build_compress_level > 9) PRINTHELP();
|
|
SCRIPT_MSG(_T("SetCompressionLevel: %u\n"), build_compress_level);
|
|
}
|
|
return PS_OK;
|
|
case TOK_SETCOMPRESSORDICTSIZE:
|
|
{
|
|
if (compressor != &lzma_compressor)
|
|
warning_fl(_T("SetCompressorDictSize: compressor is not set to LZMA. Effectively ignored."));
|
|
if (build_compressor_set && build_compress_whole)
|
|
warning_fl(_T("SetCompressorDictSize: data already compressed in compress whole mode. Effectively ignored."));
|
|
|
|
int s;
|
|
build_compress_dict_size=line.gettoken_int(1,&s);
|
|
if (!s) PRINTHELP();
|
|
SCRIPT_MSG(_T("SetCompressorDictSize: %u mb\n"), build_compress_dict_size);
|
|
build_compress_dict_size <<= 20;
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
case TOK_SETCOMPRESSIONLEVEL:
|
|
case TOK_SETCOMPRESSORDICTSIZE:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_COMPRESSION_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
|
|
case TOK_ADDSIZE:
|
|
{
|
|
int s;
|
|
int size_kb=line.gettoken_int(1,&s);
|
|
if (!s) PRINTHELP()
|
|
SCRIPT_MSG(_T("AddSize: %d kb\n"),size_kb);
|
|
section_add_size_kb(size_kb);
|
|
}
|
|
return PS_OK;
|
|
case TOK_SUBCAPTION:
|
|
{
|
|
int s;
|
|
int w=line.gettoken_int(1,&s);
|
|
if (!s || w < 0 || w > 4) PRINTHELP()
|
|
SetInnerString(NLF_SUBCAPTION_LICENSE+w,line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("SubCaption: page:%d, text=%s\n"),w,line.gettoken_str(2));
|
|
}
|
|
return PS_OK;
|
|
case TOK_FILEERRORTEXT:
|
|
#ifdef NSIS_SUPPORT_FILE
|
|
{
|
|
SetInnerString(NLF_FILE_ERROR,line.gettoken_str(1));
|
|
SetInnerString(NLF_FILE_ERROR_NOIGNORE,line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("FileErrorText: \"%s\" \"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif
|
|
case TOK_BRANDINGTEXT:
|
|
{
|
|
int a = 1;
|
|
int trim = 0;
|
|
while (line.gettoken_str(a)[0] == _T('/')) {
|
|
if (!_tcsnicmp(line.gettoken_str(a),_T("/TRIM"),5)) {
|
|
if (!_tcsicmp(line.gettoken_str(a)+5,_T("LEFT"))) trim = 1;
|
|
else if (!_tcsicmp(line.gettoken_str(a)+5,_T("RIGHT"))) trim = 2;
|
|
else if (!_tcsicmp(line.gettoken_str(a)+5,_T("CENTER"))) trim = 3;
|
|
else PRINTHELP();
|
|
a++;
|
|
}
|
|
else break;
|
|
}
|
|
if (line.getnumtokens()!=a+1 && !trim) PRINTHELP();
|
|
if (line.getnumtokens()==a+1)
|
|
SetInnerString(NLF_BRANDING,line.gettoken_str(a));
|
|
#ifdef _WIN32
|
|
if (trim) try {
|
|
init_res_editor();
|
|
|
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
|
CDialogTemplate td(dlg,build_unicode,uDefCodePage);
|
|
free(dlg);
|
|
|
|
if (trim) {
|
|
TCHAR str[512];
|
|
if (line.getnumtokens()==a+1 && line.gettoken_str(a)[0])
|
|
_tcscpy(str, line.gettoken_str(a));
|
|
else
|
|
wsprintf(str, _T("Nullsoft Install System %s"), NSIS_VERSION);
|
|
|
|
short old_width = td.GetItem(IDC_VERSTR)->sWidth;
|
|
|
|
switch (trim) {
|
|
case 1: td.LTrimToString(IDC_VERSTR, str, 4); break;
|
|
case 2: td.RTrimToString(IDC_VERSTR, str, 4); break;
|
|
case 3: td.CTrimToString(IDC_VERSTR, str, 4); break;
|
|
}
|
|
|
|
if (td.GetItem(IDC_VERSTR)->sWidth > old_width)
|
|
{
|
|
warning_fl(_T("BrandingText: \"%s\" is too long, trimming has expanded the label"), str);
|
|
}
|
|
}
|
|
|
|
DWORD dwSize;
|
|
dlg = td.Save(dwSize);
|
|
res_editor->UpdateResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG, dlg, dwSize);
|
|
res_editor->FreeResource(dlg);
|
|
}
|
|
catch (exception& err) {
|
|
ERROR_MSG(_T("Error while triming branding text control: %s\n"), CtoTStrParam(err.what()));
|
|
return PS_ERROR;
|
|
}
|
|
#else
|
|
if (trim)
|
|
{
|
|
ERROR_MSG(_T("Error: BrandingText /TRIM* is disabled for non Win32 platforms.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
#endif
|
|
SCRIPT_MSG(_T("BrandingText: \"%s\"\n"),line.gettoken_str(a));
|
|
}
|
|
return PS_OK;
|
|
case TOK_MISCBUTTONTEXT:
|
|
{
|
|
SetInnerString(NLF_BTN_BACK,line.gettoken_str(1));
|
|
SetInnerString(NLF_BTN_NEXT,line.gettoken_str(2));
|
|
SetInnerString(NLF_BTN_CANCEL,line.gettoken_str(3));
|
|
SetInnerString(NLF_BTN_CLOSE,line.gettoken_str(4));
|
|
SCRIPT_MSG(_T("MiscButtonText: back=\"%s\" next=\"%s\" cancel=\"%s\" close=\"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
}
|
|
return PS_OK;
|
|
case TOK_SPACETEXTS:
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(1), _T("none"))) {
|
|
no_space_texts=true;
|
|
SCRIPT_MSG(_T("SpaceTexts: none\n"));
|
|
}
|
|
else {
|
|
no_space_texts=false;
|
|
SetInnerString(NLF_SPACE_REQ,line.gettoken_str(1));
|
|
SetInnerString(NLF_SPACE_AVAIL,line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("SpaceTexts: required=\"%s\" available=\"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
}
|
|
}
|
|
return PS_OK;
|
|
case TOK_INSTBUTTONTEXT:
|
|
{
|
|
SetInnerString(NLF_BTN_INSTALL,line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("InstallButtonText: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_DETAILSBUTTONTEXT:
|
|
{
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_BTN_DETAILS,line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_INSTFILES) {
|
|
ERROR_MSG(_T("Error: DetailsButtonText can only be used inside PageEx instfiles.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[1] = add_string(line.gettoken_str(1));
|
|
}
|
|
SCRIPT_MSG(_T("DetailsButtonText: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_COMPLETEDTEXT:
|
|
{
|
|
if (!cur_page) {
|
|
if (SetInnerString(NLF_COMPLETED,line.gettoken_str(1)) == PS_WARNING)
|
|
warning_fl(_T("%s: specified multiple times, wasting space"),line.gettoken_str(0));
|
|
}
|
|
else {
|
|
if (cur_page_type != PAGE_INSTFILES) {
|
|
ERROR_MSG(_T("Error: CompletedText can only be used inside PageEx instfiles.\n"));
|
|
return PS_ERROR;
|
|
}
|
|
cur_page->parms[2] = add_string(line.gettoken_str(1));
|
|
}
|
|
SCRIPT_MSG(_T("CompletedText: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
case TOK_UNINSTBUTTONTEXT:
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
{
|
|
SetInnerString(NLF_BTN_UNINSTALL,line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("UninstButtonText: \"%s\"\n"),line.gettoken_str(1));
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif
|
|
|
|
// instructions
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
case TOK_NOP:
|
|
SCRIPT_MSG(_T("Nop\n"));
|
|
ent.which=EW_NOP;
|
|
return add_entry(&ent);
|
|
case TOK_GOTO:
|
|
ent.which=EW_NOP;
|
|
if (process_jump(line,1,&ent.offsets[0])) PRINTHELP()
|
|
SCRIPT_MSG(_T("Goto: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_SETREGVIEW:
|
|
{
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(alter_reg_view);
|
|
// "64" results in setting the flag to 1 which alters the view
|
|
int k=line.gettoken_enum(1,_T("32\0") _T("64\0lastused\0"));
|
|
if (k<0) PRINTHELP()
|
|
if (k == 0) // 32
|
|
ent.offsets[1]=add_intstring(0);
|
|
else if (k == 1) // 64
|
|
ent.offsets[1]=add_intstring(KEY_WOW64_64KEY);
|
|
else if (k == 2) // last used
|
|
ent.offsets[2]=1;
|
|
SCRIPT_MSG(_T("SetRegView: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_SETSHELLVARCONTEXT:
|
|
{
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(all_user_var);
|
|
int k=line.gettoken_enum(1,_T("current\0all\0"));
|
|
if (k<0) PRINTHELP()
|
|
ent.offsets[1]=add_intstring(k);
|
|
SCRIPT_MSG(_T("SetShellVarContext: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_RET:
|
|
SCRIPT_MSG(_T("Return\n"));
|
|
ent.which=EW_RET;
|
|
return add_entry(&ent);
|
|
case TOK_CALL:
|
|
if (!line.gettoken_str(1)[0] || (line.gettoken_str(1)[0]==_T(':') && !line.gettoken_str(1)[1] )) PRINTHELP()
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
if (uninstall_mode && _tcsnicmp(line.gettoken_str(1),_T("un."),3)
|
|
&& (GetUserVarIndex(line,1) < 0) && line.gettoken_str(1)[0]!=_T(':'))
|
|
{
|
|
ERROR_MSG(_T("Call must be used with function names starting with \"un.\" in the uninstall section.\n"));
|
|
PRINTHELP()
|
|
}
|
|
if (!uninstall_mode && !_tcsnicmp(line.gettoken_str(1),_T("un."),3))
|
|
{
|
|
ERROR_MSG(_T("Call must not be used with functions starting with \"un.\" in the non-uninstall sections.\n"));
|
|
PRINTHELP()
|
|
}
|
|
#endif
|
|
ent.which=EW_CALL;
|
|
ent.offsets[1]=0;
|
|
{
|
|
int v;
|
|
if ((v=GetUserVarIndex(line, 1))>=0)
|
|
{
|
|
ent.offsets[0]=-v-2;
|
|
}
|
|
else
|
|
{
|
|
if (line.gettoken_str(1)[0] == _T(':'))
|
|
{
|
|
ent.offsets[1]=1;
|
|
ent.offsets[0]=ns_label.add(line.gettoken_str(1)+1,0);
|
|
}
|
|
else ent.offsets[0]=ns_func.add(line.gettoken_str(1),0);
|
|
}
|
|
}
|
|
SCRIPT_MSG(_T("Call \"%s\"\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_SETOUTPATH:
|
|
{
|
|
const TCHAR *op=line.gettoken_str(1);
|
|
if (!_tcscmp(op,_T("-")))
|
|
{
|
|
op=_T("$INSTDIR");
|
|
}
|
|
SCRIPT_MSG(_T("SetOutPath: \"%s\"\n"),op);
|
|
ent.which=EW_CREATEDIR;
|
|
ent.offsets[0]=add_string(op);
|
|
ent.offsets[1]=1;
|
|
|
|
DefineInnerLangString(NLF_OUTPUT_DIR);
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_CREATEDIR:
|
|
{
|
|
TCHAR out_path[1024];
|
|
TCHAR *p=line.gettoken_str(1);
|
|
if (*p == _T('-')) out_path[0]=0;
|
|
else
|
|
{
|
|
if (p[0] == _T('\\') && p[1] != _T('\\')) p++;
|
|
_tcsnccpy(out_path,p,1024-1);
|
|
if (*CharPrev(out_path,out_path+_tcslen(out_path))==_T('\\'))
|
|
*CharPrev(out_path,out_path+_tcslen(out_path))=0; // remove trailing slash
|
|
}
|
|
if (!*out_path) PRINTHELP()
|
|
SCRIPT_MSG(_T("CreateDirectory: \"%s\"\n"),out_path);
|
|
ent.which=EW_CREATEDIR;
|
|
ent.offsets[0]=add_string(out_path);
|
|
|
|
DefineInnerLangString(NLF_CREATE_DIR);
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_EXEC:
|
|
case TOK_EXECWAIT:
|
|
#ifdef NSIS_SUPPORT_EXECUTE
|
|
ent.which=EW_EXECUTE;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[2]=0;
|
|
if (which_token == TOK_EXECWAIT)
|
|
{
|
|
ent.offsets[2]=1;
|
|
ent.offsets[1]=GetUserVarIndex(line, 2);
|
|
if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
}
|
|
SCRIPT_MSG(_T("%s: \"%s\" (->%s)\n"),ent.offsets[2]?_T("ExecWait"):_T("Exec"),line.gettoken_str(1),line.gettoken_str(2));
|
|
|
|
DefineInnerLangString(NLF_EXEC);
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_EXECUTE
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_EXECUTE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_EXECUTE
|
|
case TOK_EXECSHELL: // this uses improvements of Andras Varga
|
|
#ifdef NSIS_SUPPORT_SHELLEXECUTE
|
|
{
|
|
ent.which=EW_SHELLEXEC;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
ent.offsets[3]=SW_SHOWNORMAL;
|
|
if (line.getnumtokens() > 4)
|
|
{
|
|
int tab[8]={SW_SHOWDEFAULT,SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,SW_HIDE,SW_SHOW,SW_SHOWNA,SW_SHOWMINNOACTIVE};
|
|
int a=line.gettoken_enum(4,_T("SW_SHOWDEFAULT\0SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0SW_HIDE\0SW_SHOW\0SW_SHOWNA\0SW_SHOWMINNOACTIVE\0"));
|
|
if (a < 0) PRINTHELP()
|
|
ent.offsets[3]=tab[a];
|
|
}
|
|
tstring detail=tstring(line.gettoken_str(1))+_T(" ")+tstring(line.gettoken_str(2));
|
|
ent.offsets[5]=add_string(detail.c_str());
|
|
SCRIPT_MSG(_T("ExecShell: %s: \"%s\" \"%s\" %s\n"),line.gettoken_str(1),line.gettoken_str(2),
|
|
line.gettoken_str(3),line.gettoken_str(4));
|
|
|
|
DefineInnerLangString(NLF_EXEC_SHELL);
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_SHELLEXECUTE
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_SHELLEXECUTE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_SHELLEXECUTE
|
|
case TOK_CALLINSTDLL:
|
|
case TOK_REGDLL:
|
|
case TOK_UNREGDLL:
|
|
#ifndef NSIS_SUPPORT_ACTIVEXREG
|
|
ERROR_MSG(_T("%s: support not compiled in (NSIS_SUPPORT_ACTIVEXREG)\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#else//NSIS_SUPPORT_ACTIVEXREG
|
|
ent.which=EW_REGISTERDLL;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
if (which_token == TOK_UNREGDLL)
|
|
{
|
|
ent.offsets[1]=add_string(_T("DllUnregisterServer"));
|
|
ent.offsets[2]=DefineInnerLangString(NLF_UNREGISTERING);
|
|
}
|
|
else if (which_token == TOK_CALLINSTDLL)
|
|
{
|
|
int a = 2;
|
|
if (!_tcsicmp(line.gettoken_str(a), _T("/NOUNLOAD"))) {
|
|
ent.offsets[3]=1;
|
|
a++;
|
|
}
|
|
if (a+1 != line.getnumtokens()) PRINTHELP();
|
|
ent.offsets[1]=add_string(line.gettoken_str(a));
|
|
if (!ent.offsets[1]) PRINTHELP()
|
|
ent.offsets[2]=0;
|
|
}
|
|
else // register
|
|
{
|
|
ent.offsets[1] = add_string(line.gettoken_str(2));
|
|
if (!ent.offsets[1]) ent.offsets[1]=add_string(_T("DllRegisterServer"));
|
|
ent.offsets[2]=DefineInnerLangString(NLF_REGISTERING);
|
|
}
|
|
|
|
SCRIPT_MSG(_T("%s: \"%s\" %s\n"),line.gettoken_str(0),line.gettoken_str(1), line.gettoken_str(ent.offsets[3]?3:2));
|
|
|
|
DefineInnerLangString(NLF_SYMBOL_NOT_FOUND);
|
|
DefineInnerLangString(NLF_COULD_NOT_LOAD);
|
|
DefineInnerLangString(NLF_NO_OLE);
|
|
// not used anywhere - DefineInnerLangString(NLF_ERR_REG_DLL);
|
|
return add_entry(&ent);
|
|
#endif//NSIS_SUPPORT_ACTIVEXREG
|
|
case TOK_RENAME:
|
|
#ifdef NSIS_SUPPORT_RENAME
|
|
{
|
|
int a=1;
|
|
ent.which=EW_RENAME;
|
|
if (!_tcsicmp(line.gettoken_str(1),_T("/REBOOTOK")))
|
|
{
|
|
ent.offsets[2]=1;
|
|
a++;
|
|
#ifndef NSIS_SUPPORT_MOVEONREBOOT
|
|
ERROR_MSG(_T("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"));
|
|
PRINTHELP()
|
|
#endif
|
|
}
|
|
else if (line.gettoken_str(1)[0]==_T('/'))
|
|
{
|
|
a=line.getnumtokens(); // cause usage to go here:
|
|
}
|
|
if (line.getnumtokens()!=a+2) PRINTHELP()
|
|
ent.offsets[0]=add_string(line.gettoken_str(a));
|
|
ent.offsets[1]=add_string(line.gettoken_str(a+1));
|
|
tstring print = tstring(line.gettoken_str(a)) + _T("->") + tstring(line.gettoken_str(a+1));
|
|
ent.offsets[3]=add_string(print.c_str());
|
|
SCRIPT_MSG(_T("Rename: %s%s->%s\n"),ent.offsets[2]?_T("/REBOOTOK "):_T(""),line.gettoken_str(a),line.gettoken_str(a+1));
|
|
|
|
DefineInnerLangString(NLF_RENAME);
|
|
#ifdef NSIS_SUPPORT_MOVEONREBOOT
|
|
DefineInnerLangString(NLF_RENAME_ON_REBOOT);
|
|
#endif
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_RENAME
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_RENAME not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_RENAME
|
|
case TOK_MESSAGEBOX:
|
|
#ifdef NSIS_SUPPORT_MESSAGEBOX
|
|
{
|
|
#define MBD(x) {x,_T(#x)},
|
|
struct
|
|
{
|
|
int id;
|
|
const TCHAR *str;
|
|
} list[]=
|
|
{
|
|
MBD(MB_ABORTRETRYIGNORE)
|
|
MBD(MB_OK)
|
|
MBD(MB_OKCANCEL)
|
|
MBD(MB_RETRYCANCEL)
|
|
MBD(MB_YESNO)
|
|
MBD(MB_YESNOCANCEL)
|
|
MBD(MB_ICONEXCLAMATION)
|
|
MBD(MB_ICONINFORMATION)
|
|
MBD(MB_ICONQUESTION)
|
|
MBD(MB_ICONSTOP)
|
|
MBD(MB_USERICON)
|
|
MBD(MB_TOPMOST)
|
|
MBD(MB_SETFOREGROUND)
|
|
MBD(MB_RIGHT)
|
|
MBD(MB_RTLREADING)
|
|
MBD(MB_DEFBUTTON1)
|
|
MBD(MB_DEFBUTTON2)
|
|
MBD(MB_DEFBUTTON3)
|
|
MBD(MB_DEFBUTTON4)
|
|
};
|
|
#undef MBD
|
|
int r=0;
|
|
int x;
|
|
TCHAR *p=line.gettoken_str(1);
|
|
|
|
while (*p)
|
|
{
|
|
TCHAR *np=p;
|
|
while (*np && *np != _T('|')) np++;
|
|
if (*np) *np++=0;
|
|
for (x = 0 ; (unsigned) x < COUNTOF(list) && _tcsicmp(list[x].str, p); x++);
|
|
if ((unsigned) x < COUNTOF(list))
|
|
{
|
|
r|=list[x].id;
|
|
}
|
|
else PRINTHELP()
|
|
p=np;
|
|
}
|
|
ent.which=EW_MESSAGEBOX;
|
|
ent.offsets[0]=r;
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
int rettab[] =
|
|
{
|
|
0,IDABORT,IDCANCEL,IDIGNORE,IDNO,IDOK,IDRETRY,IDYES
|
|
};
|
|
const TCHAR *retstr=_T("0\0IDABORT\0IDCANCEL\0IDIGNORE\0IDNO\0IDOK\0IDRETRY\0IDYES\0");
|
|
int a=3;
|
|
if (line.getnumtokens() > 3)
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(3),_T("/SD")))
|
|
{
|
|
int k=line.gettoken_enum(4,retstr);
|
|
if (k <= 0) PRINTHELP();
|
|
ent.offsets[0]|=rettab[k]<<21;
|
|
a=5;
|
|
}
|
|
else if (line.getnumtokens() > 7)
|
|
PRINTHELP();
|
|
|
|
if (line.getnumtokens() > a)
|
|
{
|
|
ent.offsets[2]=line.gettoken_enum(a,retstr);
|
|
if (ent.offsets[2] < 0)
|
|
PRINTHELP();
|
|
ent.offsets[2] = rettab[ent.offsets[2]];
|
|
if (process_jump(line,a+1,&ent.offsets[3]))
|
|
PRINTHELP();
|
|
if (line.getnumtokens() > a+2)
|
|
{
|
|
int v=line.gettoken_enum(a+2,retstr);
|
|
if (v < 0)
|
|
PRINTHELP();
|
|
ent.offsets[4] = rettab[v];
|
|
if (process_jump(line,a+3,&ent.offsets[5]))
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
}
|
|
SCRIPT_MSG(_T("MessageBox: %d: \"%s\""),r,line.gettoken_str(2));
|
|
if (line.getnumtokens()>a+1) SCRIPT_MSG(_T(" (on %s goto %s)"),line.gettoken_str(a),line.gettoken_str(a+1));
|
|
SCRIPT_MSG(_T("\n"));
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_MESSAGEBOX
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_MESSAGEBOX not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_MESSAGEBOX
|
|
case TOK_CREATESHORTCUT:
|
|
#ifdef NSIS_SUPPORT_CREATESHORTCUT
|
|
ent.which=EW_CREATESHORTCUT;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
ent.offsets[5]=add_string(line.gettoken_str(8));
|
|
int s;
|
|
ent.offsets[4]=line.gettoken_int(5,&s)&0xff;
|
|
if (!s)
|
|
{
|
|
if (line.getnumtokens() > 5 && *line.gettoken_str(5))
|
|
{
|
|
ERROR_MSG(_T("CreateShortCut: cannot interpret icon index\n"));
|
|
PRINTHELP()
|
|
}
|
|
ent.offsets[4]=0;
|
|
}
|
|
if (line.getnumtokens() > 6 && *line.gettoken_str(6))
|
|
{
|
|
int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINNOACTIVE/*SW_SHOWMINIMIZED doesn't work*/};
|
|
int a=line.gettoken_enum(6,_T("SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0"));
|
|
if (a < 0)
|
|
{
|
|
ERROR_MSG(_T("CreateShortCut: unknown show mode \"%s\"\n"),line.gettoken_str(6));
|
|
PRINTHELP()
|
|
}
|
|
ent.offsets[4]|=tab[a]<<8;
|
|
}
|
|
if (line.getnumtokens() > 7)
|
|
{
|
|
TCHAR *s=(line.gettoken_str(7));
|
|
|
|
TCHAR b[255];
|
|
for (unsigned int spos=0; (spos <= _tcslen(s)) && (spos <= 255); spos++)
|
|
b[spos]=_totupper(*(s+spos));
|
|
_tcscpy(s,b);
|
|
|
|
if (*s)
|
|
{
|
|
int c=0;
|
|
if (_tcsstr(s,_T("ALT|"))) ent.offsets[4]|=HOTKEYF_ALT << 24;
|
|
if (_tcsstr(s,_T("CONTROL|"))) ent.offsets[4]|=HOTKEYF_CONTROL << 24;
|
|
if (_tcsstr(s,_T("EXT|"))) ent.offsets[4]|=HOTKEYF_EXT << 24;
|
|
if (_tcsstr(s,_T("SHIFT|"))) ent.offsets[4]|=HOTKEYF_SHIFT << 24;
|
|
while (_tcsstr(s,_T("|")))
|
|
{
|
|
s=_tcsstr(s,_T("|"))+1;
|
|
}
|
|
if ((s[0] == _T('F')) && (s[1] >= _T('1') && s[1] <= _T('9')))
|
|
{
|
|
c=VK_F1-1+_ttoi(s+1);
|
|
if (_ttoi(s+1) < 1 || _ttoi(s+1) > 24)
|
|
{
|
|
warning_fl(_T("CreateShortCut: F-key \"%s\" out of range"),s);
|
|
}
|
|
}
|
|
else if (((s[0] >= _T('A') && s[0] <= _T('Z')) || (s[0] >= _T('0') && s[0] <= _T('9'))) && !s[1])
|
|
c=s[0];
|
|
else
|
|
{
|
|
c=s[0];
|
|
warning_fl(_T("CreateShortCut: unrecognized hotkey \"%s\""),s);
|
|
}
|
|
ent.offsets[4] |= (c) << 16;
|
|
}
|
|
}
|
|
SCRIPT_MSG(_T("CreateShortCut: \"%s\"->\"%s\" %s icon:%s,%d, showmode=0x%X, hotkey=0x%X, comment=%s\n"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),
|
|
line.gettoken_str(4),ent.offsets[4]&0xff,(ent.offsets[4]>>8)&0xff,ent.offsets[4]>>16,line.gettoken_str(8));
|
|
|
|
DefineInnerLangString(NLF_CREATE_SHORTCUT);
|
|
DefineInnerLangString(NLF_ERR_CREATING_SHORTCUT);
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_CREATESHORTCUT
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_CREATESHORTCUT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_SUPPORT_CREATESHORTCUT
|
|
#ifdef NSIS_SUPPORT_HWNDS
|
|
case TOK_FINDWINDOW:
|
|
ent.which=EW_FINDWINDOW;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
ent.offsets[4]=add_string(line.gettoken_str(5));
|
|
SCRIPT_MSG(_T("FindWindow: output=%s, class=\"%s\", text=\"%s\" hwndparent=\"%s\" hwndafter=\"%s\"\n"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5));
|
|
return add_entry(&ent);
|
|
case TOK_SENDMESSAGE:
|
|
ent.which=EW_SENDMESSAGE;
|
|
|
|
if (line.gettoken_str(1)[0] == _T('/') || line.gettoken_str(2)[0] == _T('/') ||
|
|
line.gettoken_str(3)[0] == _T('/') || line.gettoken_str(4)[0] == _T('/'))
|
|
{
|
|
PRINTHELP()
|
|
}
|
|
|
|
SCRIPT_MSG(_T("SendMessage:"));
|
|
{
|
|
int a=5;
|
|
ent.offsets[0]=GetUserVarIndex(line, 5);
|
|
if (ent.offsets[0]>=0)
|
|
{
|
|
SCRIPT_MSG(_T("(->%s)"),line.gettoken_str(5));
|
|
a++;
|
|
}
|
|
|
|
if (!_tcsncmp(line.gettoken_str(a),_T("/TIMEOUT="),9))
|
|
{
|
|
ent.offsets[5]|=_ttoi(line.gettoken_str(a)+9)<<2;
|
|
SCRIPT_MSG(_T(" (timeout=%d)"),ent.offsets[5]>>2);
|
|
a++;
|
|
}
|
|
|
|
if (line.getnumtokens()>a)
|
|
{
|
|
PRINTHELP()
|
|
}
|
|
}
|
|
|
|
if (!_tcsncmp(line.gettoken_str(3),_T("STR:"),4))
|
|
{
|
|
ent.offsets[5]|=1;
|
|
ent.offsets[3]=add_string(line.gettoken_str(3)+4);
|
|
}
|
|
else ent.offsets[3]=add_string(line.gettoken_str(3));
|
|
if (!_tcsncmp(line.gettoken_str(4),_T("STR:"),4))
|
|
{
|
|
ent.offsets[5]|=2;
|
|
ent.offsets[4]=add_string(line.gettoken_str(4)+4);
|
|
}
|
|
else ent.offsets[4]=add_string(line.gettoken_str(4));
|
|
|
|
ent.offsets[1]=add_string(line.gettoken_str(1));
|
|
ent.offsets[2]=add_string(line.gettoken_str(2));
|
|
|
|
SCRIPT_MSG(_T("(%s,%s,%s,%s)\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
return add_entry(&ent);
|
|
case TOK_ISWINDOW:
|
|
ent.which=EW_ISWINDOW;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
if (process_jump(line,2,&ent.offsets[1])||
|
|
process_jump(line,3,&ent.offsets[2])) PRINTHELP()
|
|
SCRIPT_MSG(_T("IsWindow(%s): %s:%s\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
case TOK_GETDLGITEM:
|
|
ent.which=EW_GETDLGITEM;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0]<0) PRINTHELP();
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
SCRIPT_MSG(_T("GetDlgItem: output=%s dialog=%s item=%s\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
case TOK_SETCTLCOLORS:
|
|
{
|
|
ctlcolors c={0, };
|
|
|
|
ent.which=EW_SETCTLCOLORS;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
|
|
int a = 2;
|
|
|
|
if (!_tcsicmp(line.gettoken_str(2),_T("/BRANDING")))
|
|
a++;
|
|
|
|
{
|
|
TCHAR *p;
|
|
|
|
if (a == 2 && line.getnumtokens() == 5) {
|
|
ERROR_MSG(_T("Error: SetCtlColors expected 3 parameters, got 4\n"));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (!_tcsicmp(line.gettoken_str(a+1),_T("transparent"))) {
|
|
c.flags|=CC_BKB;
|
|
c.lbStyle=BS_NULL;
|
|
c.bkmode=TRANSPARENT;
|
|
}
|
|
else {
|
|
p=line.gettoken_str(a+1);
|
|
if (*p) {
|
|
int v=_tcstoul(p,&p,16);
|
|
c.bkc=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16);
|
|
c.flags|=CC_BK|CC_BKB;
|
|
}
|
|
|
|
c.lbStyle=BS_SOLID;
|
|
c.bkmode=OPAQUE;
|
|
}
|
|
|
|
p=line.gettoken_str(a);
|
|
if (*p) {
|
|
int v=_tcstoul(p,&p,16);
|
|
c.text=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16);
|
|
c.flags|=CC_TEXT;
|
|
}
|
|
}
|
|
|
|
if (a == 3)
|
|
{
|
|
c.flags|=CC_BK|CC_BKB;
|
|
c.lbStyle=BS_NULL;
|
|
if (!*line.gettoken_str(a+1))
|
|
{
|
|
c.bkc=COLOR_BTNFACE;
|
|
c.flags|=CC_BK_SYS;
|
|
}
|
|
c.flags|=CC_TEXT;
|
|
if (!*line.gettoken_str(a))
|
|
{
|
|
c.text=COLOR_BTNFACE;
|
|
c.flags|=CC_TEXT_SYS;
|
|
}
|
|
c.bkmode=OPAQUE;
|
|
}
|
|
|
|
int i;
|
|
int l=cur_ctlcolors->getlen()/sizeof(ctlcolors);
|
|
for (i=0; i<l; i++) {
|
|
if (!memcmp((ctlcolors*)cur_ctlcolors->get()+i,&c,sizeof(ctlcolors))) {
|
|
ent.offsets[1]=i*sizeof(ctlcolors);
|
|
break;
|
|
}
|
|
}
|
|
if (i>=l) {
|
|
ent.offsets[1]=cur_ctlcolors->add(&c,sizeof(ctlcolors));
|
|
}
|
|
|
|
SCRIPT_MSG(_T("SetCtlColors: hwnd=%s %stext=%s background=%s\n"),line.gettoken_str(1),a==2?_T(""):_T("/BRANDING "),line.gettoken_str(a),line.gettoken_str(a+1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_CREATEFONT:
|
|
ent.which=EW_CREATEFONT;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("CreateFont: output=%s \"%s\""),line.gettoken_str(1),line.gettoken_str(2));
|
|
{
|
|
int height=0;
|
|
int weight=0;
|
|
int flags=0;
|
|
for (int i = 3; i < line.getnumtokens(); i++) {
|
|
TCHAR *tok=line.gettoken_str(i);
|
|
if (tok[0]=='/') {
|
|
if (!_tcsicmp(tok,_T("/ITALIC"))) {
|
|
SCRIPT_MSG(_T(" /ITALIC"));
|
|
flags|=1;
|
|
}
|
|
else if (!_tcsicmp(tok,_T("/UNDERLINE"))) {
|
|
SCRIPT_MSG(_T(" /UNDERLINE"));
|
|
flags|=2;
|
|
}
|
|
else if (!_tcsicmp(tok,_T("/STRIKE"))) {
|
|
SCRIPT_MSG(_T(" /STRIKE"));
|
|
flags|=4;
|
|
}
|
|
else {
|
|
SCRIPT_MSG(_T("\n"));
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
else {
|
|
if (!height) {
|
|
SCRIPT_MSG(_T(" height=%s"),tok);
|
|
height=add_string(tok);
|
|
}
|
|
else if (!weight) {
|
|
SCRIPT_MSG(_T(" weight=%s"),tok);
|
|
weight=add_string(tok);
|
|
}
|
|
else {
|
|
SCRIPT_MSG(_T("\n"));
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
}
|
|
ent.offsets[2]=height;
|
|
ent.offsets[3]=weight;
|
|
ent.offsets[4]=flags;
|
|
}
|
|
SCRIPT_MSG(_T("\n"));
|
|
return add_entry(&ent);
|
|
case TOK_ENABLEWINDOW:
|
|
ent.which=EW_SHOWWINDOW;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[3]=1;
|
|
SCRIPT_MSG(_T("EnableWindow: handle=%s enable=%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SHOWWINDOW:
|
|
ent.which=EW_SHOWWINDOW;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("ShowWindow: handle=%s show state=%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_HIDEWINDOW:
|
|
ent.which=EW_SHOWWINDOW;
|
|
ent.offsets[0]=add_string(_T("$HWNDPARENT"));
|
|
ent.offsets[1]=add_string(_T("0")/*SW_HIDE*/);
|
|
ent.offsets[2]=1;
|
|
SCRIPT_MSG(_T("HideWindow\n"));
|
|
return add_entry(&ent);
|
|
case TOK_BRINGTOFRONT:
|
|
{
|
|
int ret;
|
|
ent.which=EW_SHOWWINDOW;
|
|
ent.offsets[0]=add_string(_T("$HWNDPARENT"));
|
|
ent.offsets[1]=add_string(_T("5")/*SW_SHOW*/);
|
|
ret = add_entry(&ent);
|
|
if (ret != PS_OK) return ret;
|
|
ent.which=EW_BRINGTOFRONT;
|
|
ent.offsets[0]=0;
|
|
ent.offsets[1]=0;
|
|
SCRIPT_MSG(_T("BringToFront\n"));
|
|
}
|
|
return add_entry(&ent);
|
|
#else//NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
case TOK_GETDLGITEM:
|
|
case TOK_SETCTLCOLORS:
|
|
case TOK_SHOWWINDOW:
|
|
case TOK_BRINGTOFRONT:
|
|
case TOK_CREATEFONT:
|
|
case TOK_HIDEWINDOW:
|
|
case TOK_ENABLEWINDOW:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_ENHANCEDUI_SUPPORT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
#else//!NSIS_SUPPORT_HWNDS
|
|
case TOK_ISWINDOW:
|
|
case TOK_SENDMESSAGE:
|
|
case TOK_FINDWINDOW:
|
|
case TOK_GETDLGITEM:
|
|
case TOK_SETCTLCOLORS:
|
|
case TOK_SHOWWINDOW:
|
|
case TOK_ENABLEWINDOW:
|
|
case TOK_CREATEFONT:
|
|
case TOK_HIDEWINDOW:
|
|
case TOK_BRINGTOFRONT:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_HWNDS not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_HWNDS
|
|
case TOK_DELETE:
|
|
#ifdef NSIS_SUPPORT_DELETE
|
|
{
|
|
int a=1;
|
|
ent.which=EW_DELETEFILE;
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("/REBOOTOK")))
|
|
{
|
|
a++;
|
|
ent.offsets[1]=DEL_REBOOT;
|
|
#ifndef NSIS_SUPPORT_MOVEONREBOOT
|
|
ERROR_MSG(_T("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"));
|
|
PRINTHELP()
|
|
#endif
|
|
}
|
|
else if (line.gettoken_str(1)[0]==_T('/'))
|
|
{
|
|
a=line.getnumtokens();
|
|
}
|
|
if (line.getnumtokens() != a+1) PRINTHELP()
|
|
ent.offsets[0]=add_string(line.gettoken_str(a));
|
|
SCRIPT_MSG(_T("Delete: %s\"%s\"\n"),ent.offsets[1]?_T("/REBOOTOK "):_T(""),line.gettoken_str(a));
|
|
|
|
DefineInnerLangString(NLF_DEL_FILE);
|
|
#ifdef NSIS_SUPPORT_MOVEONREBOOT
|
|
DefineInnerLangString(NLF_DEL_ON_REBOOT);
|
|
#endif
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_DELETE
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_DELETE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_DELETE
|
|
case TOK_RMDIR:
|
|
#ifdef NSIS_SUPPORT_RMDIR
|
|
{
|
|
int a=1;
|
|
ent.which=EW_RMDIR;
|
|
ent.offsets[1]=DEL_DIR;
|
|
while (line.gettoken_str(a)[0]==_T('/'))
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("/r")))
|
|
{
|
|
if (a == 3) PRINTHELP();
|
|
a++;
|
|
ent.offsets[1]|=DEL_RECURSE;
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(a),_T("/REBOOTOK")))
|
|
{
|
|
if (a == 3) PRINTHELP();
|
|
a++;
|
|
ent.offsets[1]|=DEL_REBOOT;
|
|
}
|
|
else PRINTHELP();
|
|
}
|
|
if (a < line.getnumtokens() - 1) PRINTHELP();
|
|
ent.offsets[0]=add_string(line.gettoken_str(a));
|
|
SCRIPT_MSG(_T("RMDir: "));
|
|
if (a>1)
|
|
SCRIPT_MSG(_T("%s "),line.gettoken_str(1));
|
|
if (a>2)
|
|
SCRIPT_MSG(_T("%s "),line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("\"%s\"\n"),line.gettoken_str(a));
|
|
|
|
DefineInnerLangString(NLF_REMOVE_DIR);
|
|
DefineInnerLangString(NLF_DEL_FILE);
|
|
#ifdef NSIS_SUPPORT_MOVEONREBOOT
|
|
DefineInnerLangString(NLF_DEL_ON_REBOOT);
|
|
#endif
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_RMDIR
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_RMDIR not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_RMDIR
|
|
case TOK_RESERVEFILE:
|
|
case TOK_FILE:
|
|
#ifdef NSIS_SUPPORT_FILE
|
|
{
|
|
set<tstring> excluded;
|
|
int a=1,attrib=0,rec=0,fatal=1;
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("/nonfatal"))) {
|
|
fatal=0;
|
|
a++;
|
|
}
|
|
if (which_token == TOK_FILE && !_tcsicmp(line.gettoken_str(a),_T("/a")))
|
|
{
|
|
#ifdef _WIN32
|
|
attrib=1;
|
|
#else
|
|
warning_fl(_T("%sFile /a is disabled for non Win32 platforms."),(which_token == TOK_FILE)?_T(""):_T("Reserve"));
|
|
#endif
|
|
a++;
|
|
}
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("/r")))
|
|
{
|
|
rec=1;
|
|
a++;
|
|
}
|
|
else if (which_token == TOK_FILE && !_tcsnicmp(line.gettoken_str(a),_T("/oname="),7))
|
|
{
|
|
TCHAR *on=line.gettoken_str(a)+7;
|
|
a++;
|
|
if (!*on||line.getnumtokens()!=a+1||_tcsstr(on,_T("*")) || _tcsstr(on,_T("?"))) PRINTHELP()
|
|
|
|
if (on[0]==_T('"'))
|
|
{
|
|
ERROR_MSG(_T("%sFile: output name must not begin with a quote, use \"/oname=name with spaces\".\n"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),line.gettoken_str(a));
|
|
PRINTHELP();
|
|
}
|
|
|
|
int tf=0;
|
|
TCHAR *fn = line.gettoken_str(a);
|
|
PATH_CONVERT(fn);
|
|
int v=do_add_file(fn, attrib, 0, &tf, on);
|
|
if (v != PS_OK) return v;
|
|
if (tf > 1) PRINTHELP()
|
|
if (!tf)
|
|
{
|
|
if (fatal)
|
|
{
|
|
ERROR_MSG(_T("%sFile: \"%s\" -> no files found.\n"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),line.gettoken_str(a));
|
|
PRINTHELP()
|
|
}
|
|
else
|
|
{
|
|
warning_fl(_T("%sFile: \"%s\" -> no files found"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),line.gettoken_str(a));
|
|
|
|
// workaround for bug #1299100
|
|
// add a nop opcode so relative jumps will work as expected
|
|
add_entry_direct(EW_NOP);
|
|
}
|
|
}
|
|
|
|
return PS_OK;
|
|
}
|
|
if (!_tcsnicmp(line.gettoken_str(a),_T("/x"),2))
|
|
{
|
|
while (!_tcsnicmp(line.gettoken_str(a),_T("/x"),2))
|
|
{
|
|
a++;
|
|
|
|
if (line.getnumtokens() < a+1) PRINTHELP()
|
|
|
|
excluded.insert(line.gettoken_str(a));
|
|
a++;
|
|
}
|
|
}
|
|
#ifdef _WIN32
|
|
if (line.gettoken_str(a)[0] == _T('/')) PRINTHELP()
|
|
#endif
|
|
if (line.getnumtokens()<a+1) PRINTHELP()
|
|
while (a < line.getnumtokens())
|
|
{
|
|
#ifdef _WIN32
|
|
if (line.gettoken_str(a)[0]==_T('/')) PRINTHELP()
|
|
#endif
|
|
TCHAR buf[32];
|
|
TCHAR *t=line.gettoken_str(a++);
|
|
if (t[0] && CharNext(t)[0] == _T(':') && CharNext(t)[1] == _T('\\') && !CharNext(t)[2])
|
|
{
|
|
_tcscpy(buf,_T("X:\\*.*"));
|
|
buf[0]=t[0];
|
|
t=buf;
|
|
}
|
|
int tf=0;
|
|
TCHAR *fn = my_convert(t);
|
|
int v=do_add_file(fn, attrib, rec, &tf, NULL, which_token == TOK_FILE, NULL, excluded);
|
|
my_convert_free(fn);
|
|
if (v != PS_OK) return v;
|
|
if (!tf)
|
|
{
|
|
if (fatal)
|
|
{
|
|
ERROR_MSG(_T("%sFile: \"%s\" -> no files found.\n"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),t);
|
|
PRINTHELP();
|
|
}
|
|
else
|
|
{
|
|
warning_fl(_T("%sFile: \"%s\" -> no files found."),(which_token == TOK_FILE)?_T(""):_T("Reserve"),t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return PS_OK;
|
|
#else//!NSIS_SUPPORT_FILE
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_FILE
|
|
#ifdef NSIS_SUPPORT_COPYFILES
|
|
case TOK_COPYFILES:
|
|
{
|
|
ent.which=EW_COPYFILES;
|
|
ent.offsets[2]=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_NOERRORUI|FOF_SIMPLEPROGRESS;
|
|
|
|
int a=1;
|
|
int x;
|
|
for (x = 0; x < 2; x ++)
|
|
{
|
|
if (!_tcsicmp(line.gettoken_str(a),_T("/SILENT")))
|
|
{
|
|
a++;
|
|
ent.offsets[2]&=~FOF_SIMPLEPROGRESS;
|
|
ent.offsets[2]|=FOF_SILENT;
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(a),_T("/FILESONLY")))
|
|
{
|
|
a++;
|
|
ent.offsets[2]|=FOF_FILESONLY;
|
|
}
|
|
else if (line.gettoken_str(a)[0]==_T('/')) PRINTHELP()
|
|
else break;
|
|
}
|
|
if (line.getnumtokens() < a+2) PRINTHELP()
|
|
ent.offsets[0]=add_string(line.gettoken_str(a));
|
|
ent.offsets[1]=add_string(line.gettoken_str(a+1));
|
|
tstring copy_to = tstring(_T("$(^CopyTo)")) + line.gettoken_str(a+1);
|
|
ent.offsets[3]=add_string(copy_to.c_str());
|
|
int s;
|
|
int size_kb=line.gettoken_int(a+2,&s);
|
|
if (!s && line.gettoken_str(a+2)[0]) PRINTHELP()
|
|
section_add_size_kb(size_kb);
|
|
SCRIPT_MSG(_T("CopyFiles: %s\"%s\" -> \"%s\", size=%iKB\n"),ent.offsets[2]&FOF_SILENT?_T("(silent) "):_T(""), line.gettoken_str(a),line.gettoken_str(a+1),size_kb);
|
|
|
|
DefineInnerLangString(NLF_COPY_FAILED);
|
|
DefineInnerLangString(NLF_COPY_TO);
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_COPYFILES
|
|
case TOK_COPYFILES:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_COPYFILES not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_COPYFILES
|
|
|
|
case TOK_SETFILEATTRIBUTES:
|
|
{
|
|
#define MBD(x) {x,_T(#x)},
|
|
struct
|
|
{
|
|
int id;
|
|
const TCHAR *str;
|
|
} list[]=
|
|
{
|
|
MBD(FILE_ATTRIBUTE_NORMAL)
|
|
MBD(FILE_ATTRIBUTE_ARCHIVE)
|
|
MBD(FILE_ATTRIBUTE_HIDDEN)
|
|
MBD(FILE_ATTRIBUTE_OFFLINE)
|
|
MBD(FILE_ATTRIBUTE_READONLY)
|
|
MBD(FILE_ATTRIBUTE_SYSTEM)
|
|
MBD(FILE_ATTRIBUTE_TEMPORARY)
|
|
{FILE_ATTRIBUTE_NORMAL,_T("NORMAL")},
|
|
{FILE_ATTRIBUTE_ARCHIVE,_T("ARCHIVE")},
|
|
{FILE_ATTRIBUTE_HIDDEN,_T("HIDDEN")},
|
|
{FILE_ATTRIBUTE_OFFLINE,_T("OFFLINE")},
|
|
{FILE_ATTRIBUTE_READONLY,_T("READONLY")},
|
|
{FILE_ATTRIBUTE_SYSTEM,_T("SYSTEM")},
|
|
{FILE_ATTRIBUTE_TEMPORARY,_T("TEMPORARY")},
|
|
{FILE_ATTRIBUTE_NORMAL,_T("0")},
|
|
};
|
|
#undef MBD
|
|
int r=0;
|
|
int x;
|
|
TCHAR *p=line.gettoken_str(2);
|
|
|
|
while (*p)
|
|
{
|
|
TCHAR *np=p;
|
|
while (*np && *np != _T('|')) np++;
|
|
if (*np) *np++=0;
|
|
for (x = 0 ; (unsigned) x < COUNTOF(list) && _tcsicmp(list[x].str,p); x ++);
|
|
|
|
if ((unsigned) x < COUNTOF(list))
|
|
{
|
|
r|=list[x].id;
|
|
}
|
|
else PRINTHELP()
|
|
p=np;
|
|
}
|
|
ent.which=EW_SETFILEATTRIBUTES;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=r;
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_SLEEP:
|
|
{
|
|
ent.which=EW_SLEEP;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("Sleep: %s ms\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_IFFILEEXISTS:
|
|
ent.which=EW_IFFILEEXISTS;
|
|
ent.offsets[0] = add_string(line.gettoken_str(1));
|
|
if (process_jump(line,2,&ent.offsets[1]) ||
|
|
process_jump(line,3,&ent.offsets[2])) PRINTHELP()
|
|
SCRIPT_MSG(_T("IfFileExists: \"%s\" ? %s : %s\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
case TOK_QUIT:
|
|
ent.which=EW_QUIT;
|
|
SCRIPT_MSG(_T("Quit\n"));
|
|
return add_entry(&ent);
|
|
case TOK_ABORT:
|
|
ent.which=EW_ABORT;
|
|
ent.offsets[0] = add_string(line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("Abort: \"%s\"\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_SETDETAILSVIEW:
|
|
{
|
|
int v=line.gettoken_enum(1,_T("hide\0show\0"));
|
|
ent.which=EW_CHDETAILSVIEW;
|
|
if (v < 0) PRINTHELP()
|
|
ent.offsets[0] = v?SW_SHOWNA:SW_HIDE;
|
|
ent.offsets[1] = v?SW_HIDE:SW_SHOWNA;
|
|
SCRIPT_MSG(_T("SetDetailsView: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_SETDETAILSPRINT:
|
|
{
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(status_update);
|
|
int k=line.gettoken_enum(1,_T("both\0textonly\0listonly\0none\0lastused\0"));
|
|
if (k<0) PRINTHELP()
|
|
if (k == 4)
|
|
{
|
|
ent.offsets[2]=1;
|
|
}
|
|
else
|
|
{
|
|
// both 0
|
|
// textonly 2
|
|
// listonly 4
|
|
// none 6
|
|
ent.offsets[1]=add_intstring(k*2);
|
|
}
|
|
SCRIPT_MSG(_T("SetDetailsPrint: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_SETAUTOCLOSE:
|
|
{
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(autoclose);
|
|
int k=line.gettoken_enum(1,_T("false\0true\0"));
|
|
if (k < 0) PRINTHELP()
|
|
ent.offsets[1]=add_intstring(k);
|
|
SCRIPT_MSG(_T("SetAutoClose: %s\n"),line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_IFERRORS:
|
|
ent.which=EW_IFFLAG;
|
|
if (process_jump(line,1,&ent.offsets[0]) ||
|
|
process_jump(line,2,&ent.offsets[1])) PRINTHELP()
|
|
ent.offsets[2]=FLAG_OFFSET(exec_error);
|
|
ent.offsets[3]=0;//new value mask - clean error
|
|
SCRIPT_MSG(_T("IfErrors ?%s:%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_IFABORT:
|
|
ent.which=EW_IFFLAG;
|
|
if (process_jump(line,1,&ent.offsets[0]) ||
|
|
process_jump(line,2,&ent.offsets[1])) PRINTHELP()
|
|
ent.offsets[2]=FLAG_OFFSET(abort);
|
|
ent.offsets[3]=~0;//new value mask - keep flag
|
|
SCRIPT_MSG(_T("IfAbort ?%s:%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_CLEARERRORS:
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(exec_error);
|
|
ent.offsets[1]=add_intstring(0);
|
|
SCRIPT_MSG(_T("ClearErrors\n"));
|
|
return add_entry(&ent);
|
|
case TOK_SETERRORS:
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(exec_error);
|
|
ent.offsets[1]=add_intstring(1);
|
|
SCRIPT_MSG(_T("SetErrors\n"));
|
|
return add_entry(&ent);
|
|
case TOK_SETERRORLEVEL:
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(errlvl);
|
|
ent.offsets[1]=add_string(line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("SetErrorLevel: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_GETERRORLEVEL:
|
|
ent.which=EW_GETFLAG;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=FLAG_OFFSET(errlvl);
|
|
if (line.gettoken_str(1)[0] && ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetErrorLevel: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#ifdef NSIS_SUPPORT_STROPTS
|
|
case TOK_STRLEN:
|
|
ent.which=EW_STRLEN;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("StrLen %s \"%s\"\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_STRCPY:
|
|
case TOK_UNSAFESTRCPY:
|
|
{
|
|
ent.which = EW_ASSIGNVAR;
|
|
const TCHAR* msgprefix = _T("");
|
|
int idx = -1;
|
|
if (TOK_STRCPY == which_token)
|
|
{
|
|
idx = GetUserVarIndex(line, 1);
|
|
}
|
|
else
|
|
{
|
|
msgprefix = _T("Unsafe");
|
|
TCHAR *p = line.gettoken_str(1);
|
|
if (*p == _T('$') && *++p) idx = m_UserVarNames.get(p);
|
|
if (-1 != idx && m_UserVarNames.get_reference(idx) != -1) m_UserVarNames.inc_reference(idx);
|
|
}
|
|
if (idx < 0) PRINTHELP()
|
|
ent.offsets[0]=idx;
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
|
|
SCRIPT_MSG(_T("%sStrCpy %s \"%s\" (%s) (%s)\n"),
|
|
msgprefix,line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
return add_entry(&ent);
|
|
}
|
|
case TOK_GETFUNCTIONADDR:
|
|
ent.which=EW_GETFUNCTIONADDR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=ns_func.add(line.gettoken_str(2),0);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetFunctionAddress: %s %s"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_GETLABELADDR:
|
|
ent.which=EW_GETLABELADDR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0 || process_jump(line,2,&ent.offsets[1])) PRINTHELP()
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
SCRIPT_MSG(_T("GetLabelAddress: %s %s"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_GETCURRENTADDR:
|
|
ent.which=EW_ASSIGNVAR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=add_intstring(1+(cur_header->blocks[NB_ENTRIES].num));
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
SCRIPT_MSG(_T("GetCurrentAddress: %s"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_STRCMP:
|
|
case TOK_STRCMPS:
|
|
ent.which=EW_STRCMP;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[4]=which_token == TOK_STRCMPS;
|
|
if (process_jump(line,3,&ent.offsets[2]) ||
|
|
process_jump(line,4,&ent.offsets[3])) PRINTHELP()
|
|
SCRIPT_MSG(_T("%s \"%s\" \"%s\" equal=%s, nonequal=%s\n"),line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4));
|
|
return add_entry(&ent);
|
|
case TOK_GETDLLVERSIONLOCAL:
|
|
{
|
|
const TCHAR*cmdname=_T("GetDLLVersionLocal");
|
|
DWORD low, high;
|
|
if (!GetDLLVersion(line.gettoken_str(1),high,low))
|
|
{
|
|
ERROR_MSG(_T("%s: error reading version info from \"%s\"\n"),cmdname,line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
ent.which=EW_ASSIGNVAR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 2);
|
|
ent.offsets[1]=add_intstring(high);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
add_entry(&ent);
|
|
|
|
ent.offsets[0]=GetUserVarIndex(line, 3);
|
|
ent.offsets[1]=add_intstring(low);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("%s: %s (%u,%u)->(%s,%s)\n"),
|
|
cmdname,line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_GETFILETIMELOCAL:
|
|
{
|
|
TCHAR buf[129];
|
|
DWORD high=0,low=0;
|
|
#ifdef _WIN32
|
|
int flag=0;
|
|
HANDLE hFile=CreateFile(line.gettoken_str(1),0,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
FILETIME ft;
|
|
if (GetFileTime(hFile,NULL,NULL,&ft))
|
|
{
|
|
high=ft.dwHighDateTime;
|
|
low=ft.dwLowDateTime;
|
|
flag=1;
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
if (!flag)
|
|
{
|
|
ERROR_MSG(_T("GetFileTimeLocal: error reading date from \"%s\"\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
#else
|
|
struct stat st;
|
|
if (!stat(line.gettoken_str(1), &st))
|
|
{
|
|
unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
|
|
high = (DWORD) (ll >> 32);
|
|
low = (DWORD) ll;
|
|
}
|
|
else
|
|
{
|
|
ERROR_MSG(_T("GetFileTimeLocal: error reading date from \"%s\"\n"),line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
#endif
|
|
|
|
ent.which=EW_ASSIGNVAR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 2);
|
|
wsprintf(buf,_T("%u"),high);
|
|
ent.offsets[1]=add_string(buf);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
add_entry(&ent);
|
|
|
|
ent.offsets[0]=GetUserVarIndex(line, 3);
|
|
wsprintf(buf,_T("%u"),low);
|
|
ent.offsets[1]=add_string(buf);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetFileTimeLocal: %s (%u,%u)->(%s,%s)\n"),
|
|
line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3));
|
|
}
|
|
return add_entry(&ent);
|
|
|
|
#else//!NSIS_SUPPORT_STROPTS
|
|
case TOK_GETDLLVERSIONLOCAL:
|
|
case TOK_GETFILETIMELOCAL:
|
|
case TOK_GETFUNCTIONADDR:
|
|
case TOK_GETLABELADDR:
|
|
case TOK_GETCURRENTADDR:
|
|
case TOK_STRLEN:
|
|
case TOK_STRCPY:
|
|
case TOK_STRCMP:
|
|
case TOK_STRCMPS:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_STROPTS not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_STROPTS
|
|
#ifdef NSIS_SUPPORT_INIFILES
|
|
case TOK_DELETEINISEC:
|
|
case TOK_DELETEINISTR:
|
|
{
|
|
const TCHAR *vname=_T("");
|
|
const TCHAR *space=_T("");
|
|
ent.which=EW_WRITEINI;
|
|
ent.offsets[0]=add_string(line.gettoken_str(2)); // section name
|
|
if (line.getnumtokens() > 3)
|
|
{
|
|
vname=line.gettoken_str(3);
|
|
ent.offsets[1]=add_string(vname); // value name
|
|
space=_T(" ");
|
|
}
|
|
else ent.offsets[1]=0;
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=add_string(line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("DeleteINI%s: [%s] %s%sin %s\n"),*vname?_T("Str"):_T("Sec"),
|
|
line.gettoken_str(2),vname,space,line.gettoken_str(1));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_FLUSHINI:
|
|
ent.which=EW_WRITEINI;
|
|
ent.offsets[3]=add_string(line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("FlushINI: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_WRITEINISTR:
|
|
ent.which=EW_WRITEINI;
|
|
ent.offsets[0]=add_string(line.gettoken_str(2));
|
|
ent.offsets[1]=add_string(line.gettoken_str(3));
|
|
ent.offsets[2]=add_string(line.gettoken_str(4));
|
|
ent.offsets[3]=add_string(line.gettoken_str(1));
|
|
ent.offsets[4]=1; // write
|
|
SCRIPT_MSG(_T("WriteINIStr: [%s] %s=%s in %s\n"),
|
|
line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_READINISTR:
|
|
ent.which=EW_READINISTR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
ent.offsets[1]=add_string(line.gettoken_str(3));
|
|
ent.offsets[2]=add_string(line.gettoken_str(4));
|
|
ent.offsets[3]=add_string(line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("ReadINIStr %s [%s]:%s from %s\n"),line.gettoken_str(1),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_INIFILES
|
|
case TOK_DELETEINISEC:
|
|
case TOK_DELETEINISTR:
|
|
case TOK_FLUSHINI:
|
|
case TOK_WRITEINISTR:
|
|
case TOK_READINISTR:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_INIFILES not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_INIFILES
|
|
case TOK_DETAILPRINT:
|
|
ent.which=EW_UPDATETEXT;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=0;
|
|
SCRIPT_MSG(_T("DetailPrint: \"%s\"\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#ifdef NSIS_SUPPORT_FNUTIL
|
|
case TOK_GETTEMPFILENAME:
|
|
ent.which=EW_GETTEMPFILENAME;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (line.getnumtokens() == 3)
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
else
|
|
ent.offsets[1]=add_string(_T("$TEMP"));
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetTempFileName -> %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_GETFULLPATHNAME:
|
|
{
|
|
int a=0;
|
|
ent.which=EW_GETFULLPATHNAME;
|
|
if (line.getnumtokens()==4 && !_tcsicmp(line.gettoken_str(1),_T("/SHORT"))) a++;
|
|
else if (line.getnumtokens()==4 || *line.gettoken_str(1)==_T('/')) PRINTHELP()
|
|
ent.offsets[0]=add_string(line.gettoken_str(2+a));
|
|
ent.offsets[1]=GetUserVarIndex(line, 1+a);
|
|
ent.offsets[2]=!a;
|
|
if (ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetFullPathName: %s->%s (%d)\n"),
|
|
line.gettoken_str(2+a),line.gettoken_str(1+a),a?_T("sfn"):_T("lfn"));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_SEARCHPATH:
|
|
ent.which=EW_SEARCHPATH;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("SearchPath %s %s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
#else
|
|
case TOK_SEARCHPATH:
|
|
case TOK_GETTEMPFILENAME:
|
|
case TOK_GETFULLPATHNAME:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_FNUTIL not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif
|
|
case TOK_GETDLLVERSION:
|
|
#ifdef NSIS_SUPPORT_GETDLLVERSION
|
|
ent.which=EW_GETDLLVERSION;
|
|
ent.offsets[0]=GetUserVarIndex(line, 2);
|
|
ent.offsets[1]=GetUserVarIndex(line, 3);
|
|
ent.offsets[2]=add_string(line.gettoken_str(1));
|
|
if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetDLLVersion: %s->%s,%s\n"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_GETDLLVERSION
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_GETDLLVERSION not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_GETDLLVERSION
|
|
case TOK_GETFILETIME:
|
|
#ifdef NSIS_SUPPORT_GETFILETIME
|
|
ent.which=EW_GETFILETIME;
|
|
ent.offsets[0]=GetUserVarIndex(line, 2);
|
|
ent.offsets[1]=GetUserVarIndex(line, 3);
|
|
ent.offsets[2]=add_string(line.gettoken_str(1));
|
|
if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetFileTime: %s->%s,%s\n"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_GETFILETIME
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_GETFILETIME not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_GETFILETIME
|
|
#ifdef NSIS_SUPPORT_INTOPTS
|
|
case TOK_INTOP:
|
|
ent.which=EW_INTOP;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[3]=line.gettoken_enum(3,_T("+\0-\0*\0/\0|\0&\0^\0!\0||\0&&\0%\0<<\0>>\0~\0"));
|
|
if (ent.offsets[0] < 0 || ent.offsets[3] < 0 ||
|
|
((ent.offsets[3] == 7 || ent.offsets[3] == 13) && line.getnumtokens() > 4))
|
|
PRINTHELP()
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
if (ent.offsets[3] != 7 && ent.offsets[3] != 13) ent.offsets[2]=add_string(line.gettoken_str(4));
|
|
if (ent.offsets[3] == 13) {
|
|
ent.offsets[3]=6;
|
|
ent.offsets[2]=add_string(_T("0xFFFFFFFF"));
|
|
}
|
|
SCRIPT_MSG(_T("IntOp: %s=%s%s%s\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
return add_entry(&ent);
|
|
case TOK_INTFMT:
|
|
ent.which=EW_INTFMT;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
SCRIPT_MSG(_T("IntFmt: %s->%s (fmt:%s)\n"),line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_INTCMP:
|
|
case TOK_INTCMPU:
|
|
ent.which=EW_INTCMP;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[5]=which_token == TOK_INTCMPU;
|
|
if (process_jump(line,3,&ent.offsets[2]) ||
|
|
process_jump(line,4,&ent.offsets[3]) ||
|
|
process_jump(line,5,&ent.offsets[4])) PRINTHELP()
|
|
SCRIPT_MSG(_T("%s %s:%s equal=%s, < %s, > %s\n"),line.gettoken_str(0),
|
|
line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_INTOPTS
|
|
case TOK_INTOP:
|
|
case TOK_INTCMP:
|
|
case TOK_INTFMT:
|
|
case TOK_INTCMPU:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_INTOPTS not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_INTOPTS
|
|
#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
|
|
case TOK_READREGSTR:
|
|
case TOK_READREGDWORD:
|
|
{
|
|
ent.which=EW_READREGSTR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
int k=line.gettoken_enum(2,rootkeys[0]);
|
|
if (k == -1) k=line.gettoken_enum(2,rootkeys[1]);
|
|
if (ent.offsets[0] == -1 || k == -1) PRINTHELP()
|
|
ent.offsets[1]=(INT_PTR)rootkey_tab[k];
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
if (which_token == TOK_READREGDWORD) ent.offsets[4]=1;
|
|
else ent.offsets[4]=0;
|
|
if (line.gettoken_str(3)[0] == _T('\\'))
|
|
warning_fl(_T("%s: registry path name begins with \'\\\', may cause problems"),line.gettoken_str(0));
|
|
|
|
SCRIPT_MSG(_T("%s %s %s\\%s\\%s\n"),line.gettoken_str(0),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_DELETEREGVALUE:
|
|
case TOK_DELETEREGKEY:
|
|
{
|
|
int a=1;
|
|
if (which_token==TOK_DELETEREGKEY)
|
|
{
|
|
ent.offsets[4]=1;
|
|
TCHAR *s=line.gettoken_str(a);
|
|
if (s[0] == _T('/'))
|
|
{
|
|
if (_tcsicmp(s,_T("/ifempty"))) PRINTHELP()
|
|
a++;
|
|
ent.offsets[4]=3;
|
|
}
|
|
if (line.gettoken_str(a+2)[0]) PRINTHELP()
|
|
}
|
|
int k=line.gettoken_enum(a,rootkeys[0]);
|
|
if (k == -1) k=line.gettoken_enum(a,rootkeys[1]);
|
|
if (k == -1) PRINTHELP()
|
|
ent.which=EW_DELREG;
|
|
ent.offsets[1]=(INT_PTR)rootkey_tab[k];
|
|
ent.offsets[2]=add_string(line.gettoken_str(a+1));
|
|
ent.offsets[3]=(which_token==TOK_DELETEREGKEY)?0:add_string(line.gettoken_str(a+2));
|
|
if (line.gettoken_str(a+1)[0] == _T('\\'))
|
|
warning_fl(_T("%s: registry path name begins with \'\\\', may cause problems"),line.gettoken_str(0));
|
|
if (which_token==TOK_DELETEREGKEY)
|
|
SCRIPT_MSG(_T("DeleteRegKey: %s\\%s\n"),line.gettoken_str(a),line.gettoken_str(a+1));
|
|
else
|
|
SCRIPT_MSG(_T("DeleteRegValue: %s\\%s\\%s\n"),line.gettoken_str(a),line.gettoken_str(a+1),line.gettoken_str(a+2));
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_WRITEREGSTR:
|
|
case TOK_WRITEREGEXPANDSTR:
|
|
case TOK_WRITEREGBIN:
|
|
case TOK_WRITEREGDWORD:
|
|
{
|
|
int k=line.gettoken_enum(1,rootkeys[0]);
|
|
if (k == -1) k=line.gettoken_enum(1,rootkeys[1]);
|
|
if (k == -1) PRINTHELP()
|
|
ent.which=EW_WRITEREG;
|
|
ent.offsets[0]=(INT_PTR)rootkey_tab[k];
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
if (line.gettoken_str(2)[0] == _T('\\'))
|
|
warning_fl(_T("%s: registry path name begins with \'\\\', may cause problems"),line.gettoken_str(0));
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
if (which_token == TOK_WRITEREGSTR || which_token == TOK_WRITEREGEXPANDSTR)
|
|
{
|
|
SCRIPT_MSG(_T("%s: %s\\%s\\%s=%s\n"),
|
|
line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
ent.offsets[4]=ent.offsets[5]=REG_SZ;
|
|
if (which_token == TOK_WRITEREGEXPANDSTR)
|
|
{
|
|
ent.offsets[5]=REG_EXPAND_SZ;
|
|
}
|
|
}
|
|
if (which_token == TOK_WRITEREGBIN)
|
|
{
|
|
// Jim Park: Keep the data as char / 8 bits
|
|
char data[3*NSIS_MAX_STRLEN];
|
|
TCHAR *p=line.gettoken_str(4);
|
|
int data_len=0;
|
|
while (*p)
|
|
{
|
|
int c;
|
|
int a,b;
|
|
a=*p;
|
|
if (a >= _T('0') && a <= _T('9')) a-=_T('0');
|
|
else if (a >= _T('a') && a <= _T('f')) a-=_T('a')-10;
|
|
else if (a >= _T('A') && a <= _T('F')) a-=_T('A')-10;
|
|
else break;
|
|
b=*++p;
|
|
if (b >= _T('0') && b <= _T('9')) b-=_T('0');
|
|
else if (b >= _T('a') && b <= _T('f')) b-=_T('a')-10;
|
|
else if (b >= _T('A') && b <= _T('F')) b-=_T('A')-10;
|
|
else break;
|
|
p++;
|
|
c=(a<<4)|b;
|
|
if (data_len >= 3*NSIS_MAX_STRLEN)
|
|
{
|
|
ERROR_MSG(_T("WriteRegBin: %d bytes of data exceeded\n"),3*NSIS_MAX_STRLEN);
|
|
return PS_ERROR;
|
|
}
|
|
data[data_len++]=c;
|
|
}
|
|
if (*p) PRINTHELP()
|
|
SCRIPT_MSG(_T("WriteRegBin: %s\\%s\\%s=%s\n"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
ent.offsets[3]=add_db_data(data,data_len);
|
|
if (ent.offsets[3] < 0) return PS_ERROR;
|
|
ent.offsets[4]=ent.offsets[5]=REG_BINARY;
|
|
}
|
|
if (which_token == TOK_WRITEREGDWORD)
|
|
{
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
ent.offsets[4]=ent.offsets[5]=REG_DWORD;
|
|
|
|
SCRIPT_MSG(_T("WriteRegDWORD: %s\\%s\\%s=%s\n"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
}
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_ENUMREGKEY:
|
|
case TOK_ENUMREGVAL:
|
|
{
|
|
ent.which=EW_REGENUM;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
int k=line.gettoken_enum(2,rootkeys[0]);
|
|
if (k == -1) k=line.gettoken_enum(2,rootkeys[1]);
|
|
if (ent.offsets[0] == -1 || k == -1) PRINTHELP()
|
|
ent.offsets[1]=(INT_PTR)rootkey_tab[k];
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
ent.offsets[3]=add_string(line.gettoken_str(4));
|
|
ent.offsets[4]=which_token == TOK_ENUMREGKEY;
|
|
if (line.gettoken_str(3)[0] == _T('\\')) warning_fl(_T("%s: registry path name begins with \'\\\', may cause problems"),line.gettoken_str(0));
|
|
SCRIPT_MSG(_T("%s %s %s\\%s\\%s\n"),which_token == TOK_ENUMREGKEY ? _T("EnumRegKey") : _T("EnumRegValue"),
|
|
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_REGISTRYFUNCTIONS
|
|
case TOK_READREGSTR:
|
|
case TOK_READREGDWORD:
|
|
case TOK_DELETEREGVALUE:
|
|
case TOK_DELETEREGKEY:
|
|
case TOK_WRITEREGSTR:
|
|
case TOK_WRITEREGEXPANDSTR:
|
|
case TOK_WRITEREGBIN:
|
|
case TOK_WRITEREGDWORD:
|
|
case TOK_ENUMREGKEY:
|
|
case TOK_ENUMREGVAL:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_REGISTRYFUNCTIONS not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_REGISTRYFUNCTIONS
|
|
#ifdef NSIS_SUPPORT_STACK
|
|
case TOK_EXCH:
|
|
{
|
|
int swapitem=1;
|
|
int save=GetUserVarIndex(line, 1);
|
|
ent.which=EW_PUSHPOP;
|
|
if (line.gettoken_str(1)[0] && save<0)
|
|
{
|
|
int s=0;
|
|
swapitem=line.gettoken_int(1,&s);
|
|
if (!s || swapitem <= 0) PRINTHELP()
|
|
}
|
|
if (save>=0)
|
|
{
|
|
SCRIPT_MSG(_T("Exch(%s,0)\n"),line.gettoken_str(1));
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=0;
|
|
ent.offsets[2]=0;
|
|
add_entry(&ent);
|
|
}
|
|
else SCRIPT_MSG(_T("Exch(st(%d),0)\n"),swapitem);
|
|
|
|
ent.offsets[0]=0;
|
|
ent.offsets[1]=0;
|
|
ent.offsets[2]=swapitem;
|
|
|
|
if (save>=0)
|
|
{
|
|
add_entry(&ent);
|
|
ent.offsets[0]=save;
|
|
ent.offsets[1]=1;
|
|
ent.offsets[2]=0;
|
|
}
|
|
|
|
DefineInnerLangString(NLF_INST_CORRUPTED);
|
|
}
|
|
return add_entry(&ent);
|
|
case TOK_PUSH:
|
|
ent.which=EW_PUSHPOP;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=0;
|
|
SCRIPT_MSG(_T("Push: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_POP:
|
|
ent.which=EW_PUSHPOP;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=1;
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("Pop: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_STACK
|
|
case TOK_POP:
|
|
case TOK_PUSH:
|
|
case TOK_EXCH:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_STACK not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_STACK
|
|
#ifdef NSIS_SUPPORT_ENVIRONMENT
|
|
case TOK_READENVSTR:
|
|
ent.which=EW_READENVSTR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
{
|
|
TCHAR str[NSIS_MAX_STRLEN];
|
|
_tcscpy(str, _T("%"));
|
|
_tcscat(str, line.gettoken_str(2));
|
|
_tcscat(str, _T("%"));
|
|
ent.offsets[1]=add_string(str);
|
|
if (ent.offsets[0] < 0 || _tcslen(line.gettoken_str(2))<1) PRINTHELP()
|
|
}
|
|
ent.offsets[2]=1;
|
|
SCRIPT_MSG(_T("ReadEnvStr: %s->%s\n"),line.gettoken_str(2),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_EXPANDENVSTRS:
|
|
ent.which=EW_READENVSTR;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=0;
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("ExpandEnvStrings: %s->%s\n"),line.gettoken_str(2),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_ENVIRONMENT
|
|
case TOK_EXPANDENVSTRS:
|
|
case TOK_READENVSTR:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_ENVIRONMENT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_ENVIRONMENT
|
|
#ifdef NSIS_SUPPORT_FINDFIRST
|
|
case TOK_FINDFIRST:
|
|
ent.which=EW_FINDFIRST;
|
|
ent.offsets[0]=GetUserVarIndex(line, 2); // out
|
|
ent.offsets[1]=GetUserVarIndex(line, 1); // handleout
|
|
ent.offsets[2]=add_string(line.gettoken_str(3)); // filespec
|
|
if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FindFirst: spec=\"%s\" handle=%s output=%s\n"),line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_FINDNEXT:
|
|
ent.which=EW_FINDNEXT;
|
|
ent.offsets[0]=GetUserVarIndex(line, 2);
|
|
ent.offsets[1]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FindNext: handle=%s output=%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_FINDCLOSE:
|
|
ent.which=EW_FINDCLOSE;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FindClose: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_FINDFIRST
|
|
case TOK_FINDCLOSE:
|
|
case TOK_FINDNEXT:
|
|
case TOK_FINDFIRST:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_FINDFIRST not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
|
|
#endif//!NSIS_SUPPORT_FINDFIRST
|
|
|
|
|
|
#ifdef NSIS_SUPPORT_FILEFUNCTIONS
|
|
case TOK_FILEOPEN:
|
|
{
|
|
ent.which=EW_FOPEN;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[3]=add_string(line.gettoken_str(2));
|
|
ent.offsets[1]=0; //openmode
|
|
if (!_tcsicmp(line.gettoken_str(3),_T("r")))
|
|
{
|
|
ent.offsets[1]=GENERIC_READ;
|
|
ent.offsets[2]=OPEN_EXISTING;
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(3),_T("w")))
|
|
{
|
|
ent.offsets[1]=GENERIC_WRITE;
|
|
ent.offsets[2]=CREATE_ALWAYS;
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(3),_T("a")))
|
|
{
|
|
ent.offsets[1]=GENERIC_WRITE|GENERIC_READ;
|
|
ent.offsets[2]=OPEN_ALWAYS;
|
|
}
|
|
|
|
if (ent.offsets[0] < 0 || !ent.offsets[1]) PRINTHELP()
|
|
}
|
|
SCRIPT_MSG(_T("FileOpen: %s as %s -> %s\n"),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_FILECLOSE:
|
|
ent.which=EW_FCLOSE;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
if (ent.offsets[0] < 0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileClose: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_FILEREAD:
|
|
ent.which=EW_FGETS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=GetUserVarIndex(line, 2); // output string
|
|
if (line.gettoken_str(3)[0])
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
else
|
|
ent.offsets[2]=add_intstring(NSIS_MAX_STRLEN-1);
|
|
if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileRead: %s->%s (max:%s)\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
case TOK_FILEWRITE:
|
|
ent.which=EW_FPUTS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileWrite: %s->%s\n"),line.gettoken_str(2),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_FILEREADBYTE:
|
|
ent.which=EW_FGETS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=GetUserVarIndex(line, 2); // output string
|
|
ent.offsets[2]=add_string(_T("1"));
|
|
ent.offsets[3]=1;
|
|
if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileReadByte: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_FILEWRITEBYTE:
|
|
ent.which=EW_FPUTS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=1;
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileWriteByte: %s->%s\n"),line.gettoken_str(2),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#ifdef _UNICODE
|
|
case TOK_FILEREADUTF16LE:
|
|
if (!build_unicode)
|
|
{
|
|
ERROR_MSG(_T("Error: %s is only available when building a Unicode installer\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
ent.which=EW_FGETWS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=GetUserVarIndex(line, 2); // output string
|
|
if (line.gettoken_str(3)[0])
|
|
ent.offsets[2]=add_string(line.gettoken_str(3));
|
|
else
|
|
ent.offsets[2]=add_intstring(NSIS_MAX_STRLEN-1);
|
|
if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileReadUTF16LE: %s->%s (max:%s)\n"),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
|
|
return add_entry(&ent);
|
|
case TOK_FILEWRITEUTF16LE:
|
|
if (!build_unicode)
|
|
{
|
|
ERROR_MSG(_T("Error: %s is only available when building a Unicode installer\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
ent.which=EW_FPUTWS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileWriteUTF16LE: %s->%s\n"),line.gettoken_str(2),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_FILEREADWORD:
|
|
if (!build_unicode)
|
|
{
|
|
ERROR_MSG(_T("Error: %s is only available when building a Unicode installer\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
ent.which=EW_FGETWS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=GetUserVarIndex(line, 2); // output string
|
|
ent.offsets[2]=add_string(_T("1"));
|
|
ent.offsets[3]=1;
|
|
if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileReadWord: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_FILEWRITEWORD:
|
|
if (!build_unicode)
|
|
{
|
|
ERROR_MSG(_T("Error: %s is only available when building a Unicode installer\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
ent.which=EW_FPUTWS;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=1;
|
|
if (ent.offsets[0]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("FileWriteWord: %s->%s\n"),line.gettoken_str(2),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#endif
|
|
case TOK_FILESEEK:
|
|
{
|
|
const TCHAR *modestr;
|
|
int tab[3]={FILE_BEGIN,FILE_CURRENT,FILE_END};
|
|
int mode=line.gettoken_enum(3,_T("SET\0CUR\0END\0"));
|
|
ent.which=EW_FSEEK;
|
|
ent.offsets[0]=GetUserVarIndex(line, 1);
|
|
ent.offsets[1]=GetUserVarIndex(line, 4);
|
|
ent.offsets[2]=add_string(line.gettoken_str(2));
|
|
|
|
if (mode<0 && !line.gettoken_str(3)[0])
|
|
{
|
|
mode=0;
|
|
modestr=_T("SET");
|
|
}
|
|
else modestr=line.gettoken_str(3);
|
|
|
|
if (mode<0 || ent.offsets[0] < 0 || (ent.offsets[1]<0 && line.gettoken_str(4)[0])) PRINTHELP()
|
|
ent.offsets[3]=tab[mode];
|
|
SCRIPT_MSG(_T("FileSeek: fp=%s, ofs=%s, mode=%s, output=%s\n"),
|
|
line.gettoken_str(1),
|
|
line.gettoken_str(2),
|
|
modestr,
|
|
line.gettoken_str(4));
|
|
}
|
|
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_FILEFUNCTIONS
|
|
case TOK_FILEOPEN:
|
|
case TOK_FILECLOSE:
|
|
case TOK_FILESEEK:
|
|
case TOK_FILEREAD:
|
|
case TOK_FILEWRITE:
|
|
case TOK_FILEREADBYTE:
|
|
case TOK_FILEWRITEBYTE:
|
|
#ifdef _UNICODE
|
|
case TOK_FILEREADUTF16LE:
|
|
case TOK_FILEWRITEUTF16LE:
|
|
case TOK_FILEREADWORD:
|
|
case TOK_FILEWRITEWORD:
|
|
#endif
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_FILEFUNCTIONS not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
|
|
#endif//!NSIS_SUPPORT_FILEFUNCTIONS
|
|
#ifdef NSIS_SUPPORT_REBOOT
|
|
case TOK_REBOOT:
|
|
{
|
|
int ret = add_entry_direct(EW_REBOOT, 0xbadf00d);
|
|
if (ret != PS_OK) return ret;
|
|
|
|
ret = add_entry_direct(EW_QUIT);
|
|
if (ret != PS_OK) return ret;
|
|
|
|
SCRIPT_MSG(_T("Reboot! (WOW)\n"));
|
|
|
|
DefineInnerLangString(NLF_INST_CORRUPTED);
|
|
}
|
|
return PS_OK;
|
|
case TOK_IFREBOOTFLAG:
|
|
ent.which=EW_IFFLAG;
|
|
if (process_jump(line,1,&ent.offsets[0]) ||
|
|
process_jump(line,2,&ent.offsets[1])) PRINTHELP()
|
|
ent.offsets[2]=FLAG_OFFSET(exec_reboot);
|
|
ent.offsets[3]=~0;//new value mask - keep flag
|
|
SCRIPT_MSG(_T("IfRebootFlag ?%s:%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SETREBOOTFLAG:
|
|
{
|
|
ent.which=EW_SETFLAG;
|
|
ent.offsets[0]=FLAG_OFFSET(exec_reboot);
|
|
int k=line.gettoken_enum(1,_T("false\0true\0"));
|
|
if (k < 0) PRINTHELP()
|
|
ent.offsets[1]=add_intstring(k);
|
|
}
|
|
return add_entry(&ent);
|
|
#else//!NSIS_SUPPORT_REBOOT
|
|
case TOK_REBOOT:
|
|
case TOK_IFREBOOTFLAG:
|
|
case TOK_SETREBOOTFLAG:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_REBOOT not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_REBOOT
|
|
#ifdef NSIS_CONFIG_LOG
|
|
case TOK_LOGSET:
|
|
ent.which=EW_LOG;
|
|
ent.offsets[0]=1;
|
|
ent.offsets[1]=line.gettoken_enum(1,_T("off\0on\0"));
|
|
if (ent.offsets[1]<0) PRINTHELP()
|
|
|
|
SCRIPT_MSG(_T("LogSet: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_LOGTEXT:
|
|
ent.which=EW_LOG;
|
|
ent.offsets[0]=0;
|
|
ent.offsets[1]=add_string(line.gettoken_str(1));
|
|
SCRIPT_MSG(_T("LogText \"%s\"\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_CONFIG_LOG
|
|
|
|
case TOK_LOGSET:
|
|
case TOK_LOGTEXT:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_LOG not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_CONFIG_LOG
|
|
#ifdef NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_SECTIONSETTEXT:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[2]=SECTION_FIELD_SET(name_ptr);
|
|
ent.offsets[4]=add_string(line.gettoken_str(2));
|
|
SCRIPT_MSG(_T("SectionSetText: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONGETTEXT:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=GetUserVarIndex(line, 2);
|
|
ent.offsets[2]=SECTION_FIELD_GET(name_ptr);
|
|
if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("SectionGetText: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONSETFLAGS:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=SECTION_FIELD_SET(flags);
|
|
ent.offsets[3]=1;
|
|
SCRIPT_MSG(_T("SectionSetFlags: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONGETFLAGS:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=GetUserVarIndex(line, 2);
|
|
ent.offsets[2]=SECTION_FIELD_GET(flags);
|
|
if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("SectionGetFlags: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_INSTTYPESETTEXT:
|
|
ent.which=EW_INSTTYPESET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=1;
|
|
SCRIPT_MSG(_T("InstTypeSetText: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_INSTTYPEGETTEXT:
|
|
ent.which=EW_INSTTYPESET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=GetUserVarIndex(line, 2);
|
|
ent.offsets[2]=0;
|
|
if (line.gettoken_str(1)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("InstTypeGetText: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONSETINSTTYPES:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=SECTION_FIELD_SET(install_types);
|
|
SCRIPT_MSG(_T("SectionSetInstTypes: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONGETINSTTYPES:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=GetUserVarIndex(line, 2);
|
|
ent.offsets[2]=SECTION_FIELD_GET(install_types);
|
|
if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("SectionGetInstTypes: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONSETSIZE:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=add_string(line.gettoken_str(2));
|
|
ent.offsets[2]=SECTION_FIELD_SET(size_kb);
|
|
SCRIPT_MSG(_T("SectionSetSize: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SECTIONGETSIZE:
|
|
ent.which=EW_SECTIONSET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=GetUserVarIndex(line, 2);
|
|
ent.offsets[2]=SECTION_FIELD_GET(size_kb);
|
|
if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("SectionGetSize: %s->%s\n"),line.gettoken_str(1),line.gettoken_str(2));
|
|
return add_entry(&ent);
|
|
case TOK_SETCURINSTTYPE:
|
|
ent.which=EW_INSTTYPESET;
|
|
ent.offsets[0]=add_string(line.gettoken_str(1));
|
|
ent.offsets[1]=0;
|
|
ent.offsets[2]=1;
|
|
ent.offsets[3]=1;
|
|
SCRIPT_MSG(_T("SetCurInstType: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
case TOK_GETCURINSTTYPE:
|
|
ent.which=EW_INSTTYPESET;
|
|
ent.offsets[0]=0;
|
|
ent.offsets[1]=GetUserVarIndex(line,1);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=1;
|
|
if (line.gettoken_str(1)[0] && ent.offsets[1]<0) PRINTHELP()
|
|
SCRIPT_MSG(_T("GetCurInstType: %s\n"),line.gettoken_str(1));
|
|
return add_entry(&ent);
|
|
#else//!NSIS_CONFIG_COMPONENTPAGE
|
|
case TOK_SECTIONSETTEXT:
|
|
case TOK_SECTIONGETTEXT:
|
|
case TOK_SECTIONSETFLAGS:
|
|
case TOK_SECTIONGETFLAGS:
|
|
case TOK_SECTIONSETSIZE:
|
|
case TOK_SECTIONGETSIZE:
|
|
case TOK_SECTIONSETINSTTYPES:
|
|
case TOK_SECTIONGETINSTTYPES:
|
|
case TOK_SETCURINSTTYPE:
|
|
case TOK_GETCURINSTTYPE:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_CONFIG_COMPONENTPAGE
|
|
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
case TOK_SETBRANDINGIMAGE:
|
|
{
|
|
SCRIPT_MSG(_T("SetBrandingImage: "));
|
|
if (!branding_image_found) {
|
|
ERROR_MSG(_T("\nError: no branding image found in chosen UI!\n"));
|
|
return PS_ERROR;
|
|
}
|
|
ent.which=EW_SETBRANDINGIMAGE;
|
|
for (int i = 1; i < line.getnumtokens(); i++)
|
|
if (!_tcsnicmp(line.gettoken_str(i),_T("/IMGID="),7)) {
|
|
ent.offsets[1]=_ttoi(line.gettoken_str(i)+7);
|
|
SCRIPT_MSG(_T("/IMGID=%d "),ent.offsets[1]);
|
|
}
|
|
else if (!_tcsicmp(line.gettoken_str(i),_T("/RESIZETOFIT"))) {
|
|
ent.offsets[2]=1; // must be 1 or 0
|
|
SCRIPT_MSG(_T("/RESIZETOFIT "));
|
|
}
|
|
else if (!ent.offsets[0]) {
|
|
ent.offsets[0]=add_string(line.gettoken_str(i));
|
|
SCRIPT_MSG(_T("\"%s\" "), line.gettoken_str(i));
|
|
}
|
|
else {
|
|
SCRIPT_MSG(_T("\n"));
|
|
PRINTHELP();
|
|
}
|
|
|
|
if (!ent.offsets[1])
|
|
ent.offsets[1]=branding_image_id;
|
|
SCRIPT_MSG(_T("\n"));
|
|
}
|
|
return add_entry(&ent);
|
|
#else//NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
case TOK_SETBRANDINGIMAGE:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_ENHANCEDUI_SUPPORT not defined.\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif//!NSIS_SUPPORT_CREATEFONT
|
|
|
|
// Added by ramon 3 jun 2003
|
|
case TOK_DEFVAR:
|
|
{
|
|
int a=1;
|
|
|
|
if (!_tcsicmp(line.gettoken_str(1),_T("/GLOBAL")))
|
|
{
|
|
a++;
|
|
}
|
|
else if (line.getnumtokens() == 3)
|
|
{
|
|
PRINTHELP();
|
|
}
|
|
|
|
if (build_cursection)
|
|
{
|
|
if (a==1)
|
|
{
|
|
ERROR_MSG(_T("Var: currently, only global variables can be defined.\n"));
|
|
PRINTHELP();
|
|
}
|
|
}
|
|
|
|
SCRIPT_MSG(_T("Var: \"%s\"\n"),line.gettoken_str(a));
|
|
|
|
int res = DeclaredUserVar(line.gettoken_str(a));
|
|
if (res != PS_OK)
|
|
return res;
|
|
|
|
}
|
|
return PS_OK;
|
|
|
|
// Added by ramon 6 jun 2003
|
|
#ifdef NSIS_SUPPORT_VERSION_INFO
|
|
case TOK_VI_ADDKEY:
|
|
{
|
|
LANGID LangID=0;
|
|
int a = 1;
|
|
// Allow people to force Neutral, if /LANG=* is not present it uses the default
|
|
const bool forceneutrallang = !_tcsicmp(line.gettoken_str(a),_T("/LANG=0"));
|
|
|
|
if (!_tcsnicmp(line.gettoken_str(a),_T("/LANG="),6))
|
|
LangID=_ttoi(line.gettoken_str(a++)+6);
|
|
if (line.getnumtokens()!=a+2) PRINTHELP();
|
|
TCHAR *pKey = line.gettoken_str(a);
|
|
TCHAR *pValue = line.gettoken_str(a+1);
|
|
if ( !(*pKey) )
|
|
{
|
|
ERROR_MSG(_T("Error: empty name for version info key!\n"));
|
|
return PS_ERROR;
|
|
}
|
|
else
|
|
{
|
|
SCRIPT_MSG(_T("%s: \"%s\" \"%s\"\n"), line.gettoken_str(0), line.gettoken_str(a), line.gettoken_str(a+1));
|
|
const bool allowdeflangfallback = a <= 1 && !forceneutrallang;
|
|
if ( a > 1 && 0 == LangID && !forceneutrallang)
|
|
{
|
|
ERROR_MSG(_T("%s: \"%s\" is not a valid language code!\n"),line.gettoken_str(0), line.gettoken_str(1));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
unsigned int codepage;
|
|
// We rely on GetLangNameAndCPForVersionResource to update LangID if required
|
|
const TCHAR *lang_name = GetLangNameAndCPForVersionResource(LangID, &codepage, allowdeflangfallback);
|
|
|
|
if ( rVersionInfo.SetKeyValue(LangID, codepage, pKey, pValue) )
|
|
{
|
|
ERROR_MSG(_T("%s: \"%s\" \"%04d-%s\" already defined!\n"),line.gettoken_str(0), line.gettoken_str(2), LangID, lang_name);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
return PS_OK;
|
|
}
|
|
}
|
|
case TOK_VI_SETPRODUCTVERSION:
|
|
case TOK_VI_SETFILEVERSION:
|
|
// Probably not required, but this code retains the <= 2.46 behaviour and
|
|
// does not fail on bad product version number here, it "validates" in CEXEBuild::AddVersionInfo()
|
|
//
|
|
// It is ok for us to use rVersionInfo as storage since VIProductVersion is required by VIAddVersionKey
|
|
{
|
|
const bool settingFileVer = TOK_VI_SETFILEVERSION == which_token;
|
|
const unsigned int reuseFlag = settingFileVer ? 4 : 1;
|
|
if (reuseFlag & version_fixedflags)
|
|
{
|
|
ERROR_MSG(_T("Error: %s already defined!\n"), line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
version_fixedflags |= reuseFlag;
|
|
int imm, iml, ilm, ill;
|
|
const bool validInput = _stscanf(line.gettoken_str(1), _T("%d.%d.%d.%d"), &imm, &iml, &ilm, &ill) == 4;
|
|
if (settingFileVer)
|
|
{
|
|
if (!validInput)
|
|
{
|
|
ERROR_MSG(_T("Error: invalid %s format, should be X.X.X.X\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
|
|
}
|
|
else
|
|
{
|
|
if (validInput)
|
|
{
|
|
version_fixedflags |= 2;
|
|
rVersionInfo.SetProductVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
|
|
// FileVersion defaults to ProductVersion
|
|
if (!(4 & version_fixedflags)) rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
|
|
}
|
|
}
|
|
}
|
|
return PS_OK;
|
|
|
|
#else
|
|
case TOK_VI_ADDKEY:
|
|
case TOK_VI_SETPRODUCTVERSION:
|
|
case TOK_VI_SETFILEVERSION:
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_VERSION_INFO not defined.\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
#endif
|
|
|
|
// end of instructions
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Added by Ximon Eighteen 5th August 2002
|
|
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
|
case TOK_PLUGINDIR:
|
|
{
|
|
CEXEBuild::TARGETTYPE tt = m_target_type;
|
|
int numtok = line.getnumtokens() - 1;
|
|
TCHAR *path = line.gettoken_str(numtok);
|
|
if (2 == numtok)
|
|
{
|
|
const TCHAR* arcstr = line.gettoken_str(--numtok);
|
|
tt = get_target_type(arcstr+1);
|
|
if (_T('/') != arcstr[0] || CEXEBuild::TARGET_UNKNOWN == tt)
|
|
{
|
|
tstring es = get_commandtoken_name(which_token);
|
|
es += _T(": Target parameter must be one of: /");
|
|
for(int i = CEXEBuild::TARGETFIRST; i < CEXEBuild::TARGETCOUNT; ++i)
|
|
{
|
|
tt = (CEXEBuild::TARGETTYPE) i;
|
|
if (CEXEBuild::TARGETFIRST != tt) es += _T(", /");
|
|
es += get_target_suffix(tt);
|
|
}
|
|
ERROR_MSG(_T("Error: %s\n"),es.c_str());
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
if (1 == numtok)
|
|
{
|
|
SCRIPT_MSG(_T("PluginDir: \"%s\"\n"),path);
|
|
PATH_CONVERT(path);
|
|
m_plugins[tt].AddPluginsDir(path, !!display_script);
|
|
return PS_OK;
|
|
}
|
|
}
|
|
return PS_ERROR;
|
|
case TOK__PLUGINCOMMAND:
|
|
{
|
|
int ret;
|
|
tstring command, dllPath;
|
|
|
|
if (!m_pPlugins->GetCommandInfo(line.gettoken_str(0), command, dllPath))
|
|
{
|
|
ERROR_MSG(_T("Plugin command %s conflicts with a plugin in another directory!\n"),command.c_str());
|
|
return PS_ERROR;
|
|
}
|
|
|
|
tstring dllName = get_file_name(dllPath);
|
|
int data_handle = m_pPlugins->GetDllDataHandle(!!uninstall_mode, command);
|
|
|
|
if (uninstall_mode) uninst_plugin_used = true; else plugin_used = true;
|
|
|
|
// Initialize $PLUGINSDIR
|
|
ent.which=EW_CALL;
|
|
ent.offsets[0]=ns_func.add(uninstall_mode?_T("un.Initialize_____Plugins"):_T("Initialize_____Plugins"),0);
|
|
ret=add_entry(&ent);
|
|
if (ret != PS_OK) {
|
|
return ret;
|
|
}
|
|
|
|
// DLL name on the user machine
|
|
TCHAR tempDLL[NSIS_MAX_STRLEN];
|
|
wsprintf(tempDLL, _T("$PLUGINSDIR\\%s"), dllName.c_str());
|
|
|
|
// Add the DLL to the installer
|
|
if (data_handle == -1)
|
|
{
|
|
int files_added;
|
|
int old_build_allowskipfiles=build_allowskipfiles;
|
|
build_allowskipfiles=1; // on
|
|
int old_build_overwrite=build_overwrite;
|
|
build_overwrite=1; // off
|
|
int old_build_datesave=build_datesave;
|
|
build_datesave=0; // off
|
|
|
|
// Jim Park: While the code looks as if the same DLL is added multiple
|
|
// times for each command in the DLL, this is actually not the case
|
|
// because of CEXEBuild::datablock_optimize() that tries to discover
|
|
// duplicates and reuse them.
|
|
ret=do_add_file(dllPath.c_str(),0,0,&files_added,tempDLL,2,&data_handle); // 2 means no size add
|
|
if (ret != PS_OK) {
|
|
return ret;
|
|
}
|
|
m_pPlugins->SetDllDataHandle(!!uninstall_mode, command, data_handle);
|
|
build_overwrite=old_build_overwrite;
|
|
build_datesave=old_build_datesave;
|
|
// Added by ramon 23 May 2003
|
|
build_allowskipfiles=old_build_allowskipfiles;
|
|
}
|
|
else
|
|
{
|
|
ent.which=EW_EXTRACTFILE;
|
|
|
|
DefineInnerLangString(NLF_SKIPPED);
|
|
DefineInnerLangString(NLF_ERR_DECOMPRESSING);
|
|
DefineInnerLangString(NLF_ERR_WRITING);
|
|
DefineInnerLangString(NLF_EXTRACT);
|
|
DefineInnerLangString(NLF_CANT_WRITE);
|
|
|
|
ent.offsets[0]=1; // overwrite off
|
|
ent.offsets[0]|=(MB_RETRYCANCEL|MB_ICONSTOP|(IDCANCEL<<21))<<3;
|
|
ent.offsets[1]=add_string(tempDLL);
|
|
ent.offsets[2]=data_handle;
|
|
ent.offsets[3]=0xffffffff;
|
|
ent.offsets[4]=0xffffffff;
|
|
ent.offsets[5]=DefineInnerLangString(NLF_FILE_ERROR);
|
|
ret=add_entry(&ent);
|
|
if (ret != PS_OK) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
// SetDetailsPrint lastused
|
|
ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1);
|
|
if (ret != PS_OK) {
|
|
return ret;
|
|
}
|
|
|
|
// Call the DLL
|
|
tstring funcname = get_string_suffix(command, _T("::"));
|
|
SCRIPT_MSG(_T("Plugin Command: %s"),funcname.c_str());
|
|
|
|
int i = 1;
|
|
int nounload = 0;
|
|
if (!_tcsicmp(line.gettoken_str(i), _T("/NOUNLOAD"))) {
|
|
i++;
|
|
nounload++;
|
|
}
|
|
|
|
// First push dll args
|
|
|
|
int parmst=i; // we push em in reverse order
|
|
int nounloadmisused=0;
|
|
for (; i < line.getnumtokens(); i++) {
|
|
int w=parmst + (line.getnumtokens()-i - 1);
|
|
ent.which=EW_PUSHPOP;
|
|
ent.offsets[0]=add_string(line.gettoken_str(w));
|
|
if (!_tcsicmp(line.gettoken_str(w), _T("/NOUNLOAD"))) nounloadmisused=1;
|
|
ent.offsets[1]=0;
|
|
ent.offsets[2]=0;
|
|
ret=add_entry(&ent);
|
|
if (ret != PS_OK) {
|
|
return ret;
|
|
}
|
|
SCRIPT_MSG(_T(" %s"),line.gettoken_str(i));
|
|
}
|
|
SCRIPT_MSG(_T("\n"));
|
|
if (nounloadmisused)
|
|
warning_fl(_T("/NOUNLOAD must come first before any plugin parameter. Unless the plugin you are trying to use has a parameter /NOUNLOAD, you are doing something wrong"));
|
|
|
|
// next, call it
|
|
ent.which=EW_REGISTERDLL;
|
|
ent.offsets[0]=add_string(tempDLL);
|
|
ent.offsets[1]=add_string(funcname.c_str());
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=nounload|build_plugin_unload;
|
|
ent.offsets[4]=1;
|
|
ret=add_entry(&ent);
|
|
if (ret != PS_OK) {
|
|
return ret;
|
|
}
|
|
|
|
DefineInnerLangString(NLF_SYMBOL_NOT_FOUND);
|
|
DefineInnerLangString(NLF_COULD_NOT_LOAD);
|
|
DefineInnerLangString(NLF_NO_OLE);
|
|
// not used anywhere - DefineInnerLangString(NLF_ERR_REG_DLL);
|
|
|
|
return PS_OK;
|
|
}
|
|
case TOK_INITPLUGINSDIR:
|
|
{
|
|
int ret;
|
|
SCRIPT_MSG(_T("%s\n"),line.gettoken_str(0));
|
|
if (uninstall_mode) uninst_plugin_used = true;
|
|
else plugin_used = true;
|
|
// Call [un.]Initialize_____Plugins
|
|
ent.which=EW_CALL;
|
|
ent.offsets[0]=ns_func.add(uninstall_mode?_T("un.Initialize_____Plugins"):_T("Initialize_____Plugins"),0);
|
|
ret=add_entry(&ent);
|
|
if (ret != PS_OK) return ret;
|
|
// SetDetailsPrint lastused
|
|
ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1);
|
|
if (ret != PS_OK) return ret;
|
|
}
|
|
return PS_OK;
|
|
#else
|
|
case TOK_PLUGINDIR:
|
|
case TOK__PLUGINCOMMAND:
|
|
case TOK_INITPLUGINSDIR:
|
|
{
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_CONFIG_PLUGIN_SUPPORT not defined.\n"),line.gettoken_str(0));
|
|
}
|
|
return PS_ERROR;
|
|
#endif// NSIS_CONFIG_PLUGIN_SUPPORT
|
|
|
|
#ifdef NSIS_LOCKWINDOW_SUPPORT
|
|
case TOK_LOCKWINDOW:
|
|
SCRIPT_MSG(_T("LockWindow: lock state=%d\n"),line.gettoken_str(1));
|
|
ent.which=EW_LOCKWINDOW;
|
|
ent.offsets[0]=line.gettoken_enum(1,_T("on\0off\0"));
|
|
if (ent.offsets[0] == -1)
|
|
PRINTHELP();
|
|
return add_entry(&ent);
|
|
#else
|
|
case TOK_LOCKWINDOW:
|
|
{
|
|
ERROR_MSG(_T("Error: %s specified, NSIS_LOCKWINDOW_SUPPORT not defined.\n"),line.gettoken_str(0));
|
|
}
|
|
return PS_ERROR;
|
|
#endif // NSIS_LOCKWINDOW_SUPPORT
|
|
|
|
default: break;
|
|
|
|
}
|
|
ERROR_MSG(_T("Error: doCommand: Invalid token \"%s\".\n"),line.gettoken_str(0));
|
|
return PS_ERROR;
|
|
}
|
|
|
|
#ifdef NSIS_SUPPORT_FILE
|
|
int CEXEBuild::do_add_file(const TCHAR *lgss, int attrib, int recurse, int *total_files, const TCHAR *name_override, int generatecode, int *data_handle, const set<tstring>& excluded, const tstring& basedir, bool dir_created)
|
|
{
|
|
assert(!name_override || !recurse);
|
|
|
|
tstring dir = get_dir_name(lgss);
|
|
tstring spec;
|
|
|
|
if (dir == lgss) {
|
|
dir = _T(".");
|
|
spec = lgss;
|
|
} else {
|
|
spec = tstring(lgss).substr(dir.length() + 1, tstring::npos);
|
|
}
|
|
|
|
if (spec == _T("")) {
|
|
spec = _T("*");
|
|
}
|
|
|
|
if (basedir == _T("")) {
|
|
dir_created = true;
|
|
|
|
if (recurse) {
|
|
// save $OUTDIR into $_OUTDIR [StrCpy $_OUTDIR $OUTDIR]
|
|
if (add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get(_T("_OUTDIR")), add_string(_T("$OUTDIR"))) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
|
|
dr->exclude(excluded);
|
|
dr->read(dir);
|
|
|
|
// add files in the current directory
|
|
for (dir_reader::iterator files_itr = dr->files().begin();
|
|
files_itr != dr->files().end();
|
|
files_itr++)
|
|
{
|
|
if (!dir_reader::matches(*files_itr, spec))
|
|
continue;
|
|
|
|
if (!dir_created && generatecode) {
|
|
SCRIPT_MSG(_T("%sFile: Descending to: \"%s\"\n"), generatecode ? _T("") : _T("Reserve"), dir.c_str());
|
|
|
|
if (do_add_file_create_dir(dir, basedir, attrib) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
|
|
dir_created = true;
|
|
}
|
|
|
|
if (add_file(dir, *files_itr, attrib, name_override, generatecode, data_handle) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
|
|
(*total_files)++;
|
|
}
|
|
|
|
if (!recurse) {
|
|
return PS_OK;
|
|
}
|
|
|
|
// recurse into directories
|
|
for (dir_reader::iterator dirs_itr = dr->dirs().begin();
|
|
dirs_itr != dr->dirs().end();
|
|
dirs_itr++)
|
|
{
|
|
tstring new_dir;
|
|
bool created = false;
|
|
|
|
if (basedir == _T("")) {
|
|
new_dir = *dirs_itr;
|
|
} else {
|
|
new_dir = basedir + _T('\\') + *dirs_itr;
|
|
}
|
|
|
|
tstring new_spec = dir + PLATFORM_PATH_SEPARATOR_STR + *dirs_itr + PLATFORM_PATH_SEPARATOR_STR;
|
|
|
|
if (!dir_reader::matches(*dirs_itr, spec)) {
|
|
new_spec += spec;
|
|
} else if (generatecode) {
|
|
// always create directories that match
|
|
|
|
SCRIPT_MSG(_T("%sFile: Descending to: \"%s\"\n"), generatecode ? _T("") : _T("Reserve"), new_spec.c_str());
|
|
|
|
if (do_add_file_create_dir(dir + _T('\\') + *dirs_itr, new_dir, attrib) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
|
|
created = true;
|
|
}
|
|
|
|
const TCHAR *new_spec_c = new_spec.c_str();
|
|
|
|
int res = do_add_file(new_spec_c, attrib, 1, total_files, NULL, generatecode, NULL, excluded, new_dir, created);
|
|
if (res != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
|
|
if (basedir == _T("")) {
|
|
SCRIPT_MSG(_T("%sFile: Returning to: \"%s\"\n"), generatecode ? _T("") : _T("Reserve"), dir.c_str());
|
|
|
|
// restore $OUTDIR from $_OUTDIR [SetOutPath $_OUTDIR]
|
|
if (add_entry_direct(EW_CREATEDIR, add_string(_T("$_OUTDIR")), 1) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
|
|
return PS_OK;
|
|
}
|
|
|
|
int CEXEBuild::add_file(const tstring& dir, const tstring& file, int attrib, const TCHAR *name_override, int generatecode, int *data_handle) {
|
|
tstring newfn_s = dir + PLATFORM_PATH_SEPARATOR_C + file;
|
|
const TCHAR *newfn = newfn_s.c_str();
|
|
const TCHAR *filename = file.c_str();
|
|
|
|
MMapFile mmap;
|
|
DWORD len;
|
|
|
|
#ifdef _WIN32
|
|
HANDLE hFile = CreateFile(
|
|
newfn,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL
|
|
);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
ERROR_MSG(_T("%sFile: failed opening file \"%s\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
// Will auto-CloseHandle hFile
|
|
MANAGE_WITH(hFile, CloseHandle);
|
|
|
|
len = GetFileSize(hFile, NULL);
|
|
if (len && !mmap.setfile(hFile, len))
|
|
{
|
|
ERROR_MSG(_T("%sFile: failed creating mmap of \"%s\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
|
|
return PS_ERROR;
|
|
}
|
|
#else
|
|
struct stat s;
|
|
if (stat(newfn, &s)) {
|
|
ERROR_MSG(_T("%sFile: failed stating file \"%s\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
len = (DWORD) s.st_size;
|
|
|
|
int fd = OPEN(newfn, O_RDONLY);
|
|
if (fd == -1)
|
|
{
|
|
ERROR_MSG(_T("%sFile: failed opening file \"%s\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
|
|
return PS_ERROR;
|
|
}
|
|
|
|
// Will auto-close(2) fd
|
|
MANAGE_WITH(fd, close);
|
|
|
|
if (len && !mmap.setfile(fd, len))
|
|
{
|
|
ERROR_MSG(_T("%sFile: failed creating mmap of \"%s\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
|
|
return PS_ERROR;
|
|
}
|
|
#endif
|
|
|
|
if (generatecode&1)
|
|
section_add_size_kb((len+1023)/1024);
|
|
if (name_override) SCRIPT_MSG(_T("%sFile: \"%s\"->\"%s\""),generatecode?_T(""):_T("Reserve"),filename,name_override);
|
|
else SCRIPT_MSG(_T("%sFile: \"%s\""),generatecode?_T(""):_T("Reserve"),filename);
|
|
if (!build_compress_whole)
|
|
if (build_compress) SCRIPT_MSG(_T(" [compress]"));
|
|
fflush(stdout);
|
|
TCHAR buf[1024];
|
|
int last_build_datablock_used=getcurdbsize();
|
|
entry ent={0,};
|
|
if (generatecode)
|
|
{
|
|
ent.which=EW_EXTRACTFILE;
|
|
|
|
DefineInnerLangString(NLF_SKIPPED);
|
|
DefineInnerLangString(NLF_ERR_DECOMPRESSING);
|
|
DefineInnerLangString(NLF_ERR_WRITING);
|
|
DefineInnerLangString(NLF_EXTRACT);
|
|
DefineInnerLangString(NLF_CANT_WRITE);
|
|
|
|
ent.offsets[0]=build_overwrite;
|
|
if (name_override)
|
|
{
|
|
ent.offsets[1]=add_string(name_override);
|
|
}
|
|
else
|
|
{
|
|
const TCHAR *i=filename;
|
|
TCHAR *o=buf;
|
|
while (*i)
|
|
{
|
|
const TCHAR c=*i++;
|
|
*o++=c;
|
|
if (c == _T('$')) *o++=_T('$');
|
|
}
|
|
*o=0;
|
|
ent.offsets[1]=add_string(buf);
|
|
}
|
|
}
|
|
ent.offsets[2]=add_db_data(&mmap);
|
|
|
|
mmap.clear();
|
|
|
|
if (ent.offsets[2] < 0)
|
|
{
|
|
return PS_ERROR;
|
|
}
|
|
|
|
if (data_handle)
|
|
{
|
|
*data_handle=ent.offsets[2];
|
|
}
|
|
|
|
{
|
|
DWORD s=getcurdbsize()-last_build_datablock_used;
|
|
if (s) s-=4;
|
|
if (s != len) SCRIPT_MSG(_T(" %d/%d bytes\n"),s,len);
|
|
else SCRIPT_MSG(_T(" %d bytes\n"),len);
|
|
}
|
|
|
|
if (generatecode)
|
|
{
|
|
if (build_datesave || build_overwrite>=0x3 /*ifnewer or ifdiff*/)
|
|
{
|
|
#ifdef _WIN32
|
|
FILETIME ft;
|
|
if (GetFileTime(hFile,NULL,NULL,&ft))
|
|
{
|
|
// FAT write time has a resolution of 2 seconds
|
|
PULONGLONG fti = (PULONGLONG) &ft;
|
|
*fti -= *fti % 20000000;
|
|
|
|
ent.offsets[3]=ft.dwLowDateTime;
|
|
ent.offsets[4]=ft.dwHighDateTime;
|
|
}
|
|
#else
|
|
struct stat st;
|
|
if (!fstat(fd, &st))
|
|
{
|
|
unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
|
|
|
|
// FAT write time has a resolution of 2 seconds
|
|
ll -= ll % 20000000;
|
|
|
|
ent.offsets[3] = (int) ll;
|
|
ent.offsets[4] = (int) (ll >> 32);
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
ERROR_MSG(_T("%sFile: failed getting file date from \"%s\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ent.offsets[3]=0xffffffff;
|
|
ent.offsets[4]=0xffffffff;
|
|
}
|
|
|
|
// overwrite flag can be 0, 1, 2 or 3. in all cases, 2 bits
|
|
int mb = 0;
|
|
if (build_allowskipfiles)
|
|
{
|
|
mb = MB_ABORTRETRYIGNORE | MB_ICONSTOP;
|
|
// default for silent installers
|
|
mb |= IDIGNORE << 21;
|
|
}
|
|
else
|
|
{
|
|
mb = MB_RETRYCANCEL | MB_ICONSTOP;
|
|
// default for silent installers
|
|
mb |= IDCANCEL << 21;
|
|
}
|
|
ent.offsets[0] |= mb << 3;
|
|
|
|
ent.offsets[5] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE);
|
|
}
|
|
|
|
if (generatecode)
|
|
{
|
|
int a=add_entry(&ent);
|
|
if (a != PS_OK)
|
|
{
|
|
return a;
|
|
}
|
|
if (attrib)
|
|
{
|
|
#ifdef _WIN32
|
|
ent.which=EW_SETFILEATTRIBUTES;
|
|
// $OUTDIR is the working directory
|
|
ent.offsets[0]=add_string(name_override?name_override:buf);
|
|
ent.offsets[1]=GetFileAttributes(newfn);
|
|
ent.offsets[2]=0;
|
|
ent.offsets[3]=0;
|
|
ent.offsets[4]=0;
|
|
ent.offsets[5]=0;
|
|
|
|
if (INVALID_FILE_ATTRIBUTES != (unsigned)ent.offsets[1])
|
|
{
|
|
a=add_entry(&ent);
|
|
if (a != PS_OK)
|
|
{
|
|
return a;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return PS_OK;
|
|
}
|
|
|
|
int CEXEBuild::do_add_file_create_dir(const tstring& local_dir, const tstring& dir, int attrib) {
|
|
tstring outdir_s = _T("$_OUTDIR\\") + dir;
|
|
|
|
tstring::size_type pos = 1;
|
|
pos = outdir_s.find(_T('$'), pos);
|
|
while (pos != tstring::npos) {
|
|
outdir_s = outdir_s.insert(pos, _T("$"));
|
|
pos = outdir_s.find(_T('$'), pos + 2);
|
|
}
|
|
|
|
int outdir = add_string(outdir_s.c_str());
|
|
|
|
if (add_entry_direct(EW_CREATEDIR, outdir, 1) != PS_OK) {
|
|
return PS_ERROR;
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
if (attrib) {
|
|
int ndc = add_string(_T("."));
|
|
|
|
DWORD attr = GetFileAttributes(local_dir.c_str());
|
|
|
|
if (attr != INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
if (add_entry_direct(EW_SETFILEATTRIBUTES, ndc, attr) != PS_OK)
|
|
{
|
|
return PS_ERROR;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return PS_OK;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
DefineList *CEXEBuild::searchParseString(const TCHAR *source_string, LineParser *line, int parmOffs, bool ignCase, bool noErrors)
|
|
{
|
|
const TCHAR *tok = line->gettoken_str(parmOffs++);
|
|
if (tok && *tok)
|
|
{
|
|
int toklen = _tcslen(tok);
|
|
while (*source_string && (ignCase?_tcsnicmp(source_string,tok,toklen):_tcsncmp(source_string,tok,toklen))) source_string++;
|
|
|
|
if (!*source_string)
|
|
{
|
|
if (!noErrors) ERROR_MSG(_T("!searchparse: starting string \"%s\" not found, aborted search!\n"),tok);
|
|
return NULL;
|
|
}
|
|
if (*source_string) source_string+=toklen;
|
|
}
|
|
|
|
DefineList *ret = NULL;
|
|
|
|
while (parmOffs < line->getnumtokens())
|
|
{
|
|
const TCHAR *defout = line->gettoken_str(parmOffs++);
|
|
if (parmOffs < line->getnumtokens()) tok=line->gettoken_str(parmOffs++);
|
|
else tok=NULL;
|
|
|
|
|
|
int maxlen=-1;
|
|
const TCHAR *src_start = source_string;
|
|
if (tok && *tok)
|
|
{
|
|
int toklen = _tcslen(tok);
|
|
while (*source_string && (ignCase?_tcsnicmp(source_string,tok,toklen):_tcsncmp(source_string,tok,toklen))) source_string++;
|
|
|
|
maxlen = source_string - src_start;
|
|
|
|
if (*source_string) source_string += toklen;
|
|
else if (!noErrors)
|
|
{
|
|
ERROR_MSG(_T("!searchparse: string \"%s\" not found, aborted search!\n"),tok);
|
|
delete ret;
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
|
|
if (defout && defout[0])
|
|
{
|
|
if (!ret) ret = new DefineList;
|
|
|
|
if (maxlen < 0) ret->add(defout,src_start);
|
|
else
|
|
{
|
|
TCHAR *p=_tcsdup(src_start);
|
|
if (p)
|
|
{
|
|
p[maxlen]=0;
|
|
ret->add(defout,p);
|
|
free(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|