5899 lines
136 KiB
C++
5899 lines
136 KiB
C++
|
// NsisIn.cpp
|
||
|
|
||
|
#include "StdAfx.h"
|
||
|
|
||
|
#include "../../../Common/IntToString.h"
|
||
|
#include "../../../Common/StringToInt.h"
|
||
|
|
||
|
#include "../../Common/LimitedStreams.h"
|
||
|
#include "../../Common/StreamUtils.h"
|
||
|
|
||
|
#include "NsisIn.h"
|
||
|
|
||
|
#define Get16(p) GetUi16(p)
|
||
|
#define Get32(p) GetUi32(p)
|
||
|
|
||
|
// #define NUM_SPEED_TESTS 1000
|
||
|
|
||
|
namespace NArchive {
|
||
|
namespace NNsis {
|
||
|
|
||
|
static const size_t kInputBufSize = 1 << 20;
|
||
|
|
||
|
const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
|
||
|
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
|
||
|
|
||
|
static const unsigned kNumCommandParams = 6;
|
||
|
static const unsigned kCmdSize = 4 + kNumCommandParams * 4;
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
#define CR_LF "\x0D\x0A"
|
||
|
#endif
|
||
|
|
||
|
static const char * const kErrorStr = "$_ERROR_STR_";
|
||
|
|
||
|
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||
|
|
||
|
|
||
|
/* There are several versions of NSIS:
|
||
|
1) Original NSIS:
|
||
|
NSIS-2 ANSI
|
||
|
NSIS-3 ANSI
|
||
|
NSIS-3 Unicode
|
||
|
2) NSIS from Jim Park that extends old NSIS-2 to Unicode support:
|
||
|
NSIS-Park-(1,2,3) ANSI
|
||
|
NSIS-Park-(1,2,3) Unicode
|
||
|
|
||
|
The command IDs layout is slightly different for different versions.
|
||
|
Also there are additional "log" versions of NSIS that support EW_LOG.
|
||
|
We use the layout of "NSIS-3 Unicode" without "log" as main layout.
|
||
|
And we transfer the command IDs to main layout, if another layout is detected. */
|
||
|
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
EW_INVALID_OPCODE,
|
||
|
EW_RET, // Return
|
||
|
EW_NOP, // Nop, Goto
|
||
|
EW_ABORT, // Abort
|
||
|
EW_QUIT, // Quit
|
||
|
EW_CALL, // Call, InitPluginsDir
|
||
|
EW_UPDATETEXT, // DetailPrint
|
||
|
EW_SLEEP, // Sleep
|
||
|
EW_BRINGTOFRONT, // BringToFront
|
||
|
EW_CHDETAILSVIEW, // SetDetailsView
|
||
|
EW_SETFILEATTRIBUTES, // SetFileAttributes
|
||
|
EW_CREATEDIR, // CreateDirectory, SetOutPath
|
||
|
EW_IFFILEEXISTS, // IfFileExists
|
||
|
EW_SETFLAG, // SetRebootFlag, ...
|
||
|
EW_IFFLAG, // IfAbort, IfSilent, IfErrors, IfRebootFlag
|
||
|
EW_GETFLAG, // GetInstDirError, GetErrorLevel
|
||
|
EW_RENAME, // Rename
|
||
|
EW_GETFULLPATHNAME, // GetFullPathName
|
||
|
EW_SEARCHPATH, // SearchPath
|
||
|
EW_GETTEMPFILENAME, // GetTempFileName
|
||
|
EW_EXTRACTFILE, // File
|
||
|
EW_DELETEFILE, // Delete
|
||
|
EW_MESSAGEBOX, // MessageBox
|
||
|
EW_RMDIR, // RMDir
|
||
|
EW_STRLEN, // StrLen
|
||
|
EW_ASSIGNVAR, // StrCpy
|
||
|
EW_STRCMP, // StrCmp
|
||
|
EW_READENVSTR, // ReadEnvStr, ExpandEnvStrings
|
||
|
EW_INTCMP, // IntCmp, IntCmpU
|
||
|
EW_INTOP, // IntOp
|
||
|
EW_INTFMT, // IntFmt
|
||
|
EW_PUSHPOP, // Push/Pop/Exchange
|
||
|
EW_FINDWINDOW, // FindWindow
|
||
|
EW_SENDMESSAGE, // SendMessage
|
||
|
EW_ISWINDOW, // IsWindow
|
||
|
EW_GETDLGITEM, // GetDlgItem
|
||
|
EW_SETCTLCOLORS, // SetCtlColors
|
||
|
EW_SETBRANDINGIMAGE, // SetBrandingImage
|
||
|
EW_CREATEFONT, // CreateFont
|
||
|
EW_SHOWWINDOW, // ShowWindow, EnableWindow, HideWindow
|
||
|
EW_SHELLEXEC, // ExecShell
|
||
|
EW_EXECUTE, // Exec, ExecWait
|
||
|
EW_GETFILETIME, // GetFileTime
|
||
|
EW_GETDLLVERSION, // GetDLLVersion
|
||
|
|
||
|
// EW_GETFONTVERSION, // Park : 2.46.2
|
||
|
// EW_GETFONTNAME, // Park : 2.46.3
|
||
|
|
||
|
EW_REGISTERDLL, // RegDLL, UnRegDLL, CallInstDLL
|
||
|
EW_CREATESHORTCUT, // CreateShortCut
|
||
|
EW_COPYFILES, // CopyFiles
|
||
|
EW_REBOOT, // Reboot
|
||
|
EW_WRITEINI, // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI
|
||
|
EW_READINISTR, // ReadINIStr
|
||
|
EW_DELREG, // DeleteRegValue, DeleteRegKey
|
||
|
EW_WRITEREG, // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD
|
||
|
EW_READREGSTR, // ReadRegStr, ReadRegDWORD
|
||
|
EW_REGENUM, // EnumRegKey, EnumRegValue
|
||
|
EW_FCLOSE, // FileClose
|
||
|
EW_FOPEN, // FileOpen
|
||
|
EW_FPUTS, // FileWrite, FileWriteByte
|
||
|
EW_FGETS, // FileRead, FileReadByte
|
||
|
|
||
|
// Park
|
||
|
// EW_FPUTWS, // FileWriteUTF16LE, FileWriteWord
|
||
|
// EW_FGETWS, // FileReadUTF16LE, FileReadWord
|
||
|
|
||
|
EW_FSEEK, // FileSeek
|
||
|
EW_FINDCLOSE, // FindClose
|
||
|
EW_FINDNEXT, // FindNext
|
||
|
EW_FINDFIRST, // FindFirst
|
||
|
EW_WRITEUNINSTALLER, // WriteUninstaller
|
||
|
|
||
|
// Park : since 2.46.3 the log is enabled in main Park version
|
||
|
// EW_LOG, // LogSet, LogText
|
||
|
|
||
|
EW_SECTIONSET, // Get*, Set*
|
||
|
EW_INSTTYPESET, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType
|
||
|
|
||
|
// instructions not actually implemented in exehead, but used in compiler.
|
||
|
EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR
|
||
|
EW_GETFUNCTIONADDR,
|
||
|
|
||
|
EW_LOCKWINDOW, // LockWindow
|
||
|
|
||
|
// 2 unicode commands available only in Unicode archive
|
||
|
EW_FPUTWS, // FileWriteUTF16LE, FileWriteWord
|
||
|
EW_FGETWS, // FileReadUTF16LE, FileReadWord
|
||
|
|
||
|
// The following IDs are not IDs in real order.
|
||
|
// We just need some IDs to translate eny extended layout to main layout.
|
||
|
|
||
|
EW_LOG, // LogSet, LogText
|
||
|
|
||
|
// Park
|
||
|
EW_FINDPROC, // FindProc
|
||
|
|
||
|
EW_GETFONTVERSION, // GetFontVersion
|
||
|
EW_GETFONTNAME, // GetFontName
|
||
|
|
||
|
kNumCmds
|
||
|
};
|
||
|
|
||
|
static const unsigned kNumAdditionalParkCmds = 3;
|
||
|
|
||
|
struct CCommandInfo
|
||
|
{
|
||
|
Byte NumParams;
|
||
|
};
|
||
|
|
||
|
static const CCommandInfo k_Commands[kNumCmds] =
|
||
|
{
|
||
|
{ 0 }, // "Invalid" },
|
||
|
{ 0 }, // Return
|
||
|
{ 1 }, // Nop, Goto
|
||
|
{ 1 }, // "Abort" },
|
||
|
{ 0 }, // "Quit" },
|
||
|
{ 2 }, // Call
|
||
|
{ 6 }, // "DetailPrint" }, // 1 param in new versions, 6 in old NSIS versions
|
||
|
{ 1 }, // "Sleep" },
|
||
|
{ 0 }, // "BringToFront" },
|
||
|
{ 2 }, // "SetDetailsView" },
|
||
|
{ 2 }, // "SetFileAttributes" },
|
||
|
{ 2 }, // CreateDirectory, SetOutPath
|
||
|
{ 3 }, // "IfFileExists" },
|
||
|
{ 3 }, // SetRebootFlag, ...
|
||
|
{ 4 }, // "If" }, // IfAbort, IfSilent, IfErrors, IfRebootFlag
|
||
|
{ 2 }, // "Get" }, // GetInstDirError, GetErrorLevel
|
||
|
{ 4 }, // "Rename" },
|
||
|
{ 3 }, // "GetFullPathName" },
|
||
|
{ 2 }, // "SearchPath" },
|
||
|
{ 2 }, // "GetTempFileName" },
|
||
|
{ 6 }, // "File"
|
||
|
{ 2 }, // "Delete" },
|
||
|
{ 6 }, // "MessageBox" },
|
||
|
{ 2 }, // "RMDir" },
|
||
|
{ 2 }, // "StrLen" },
|
||
|
{ 4 }, // StrCpy, GetCurrentAddress
|
||
|
{ 5 }, // "StrCmp" },
|
||
|
{ 3 }, // ReadEnvStr, ExpandEnvStrings
|
||
|
{ 6 }, // "IntCmp" },
|
||
|
{ 4 }, // "IntOp" },
|
||
|
{ 3 }, // "IntFmt" },
|
||
|
{ 6 }, // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage.
|
||
|
{ 5 }, // "FindWindow" },
|
||
|
{ 6 }, // "SendMessage" },
|
||
|
{ 3 }, // "IsWindow" },
|
||
|
{ 3 }, // "GetDlgItem" },
|
||
|
{ 2 }, // "SetCtlColors" },
|
||
|
{ 3 }, // "SetBrandingImage" },
|
||
|
{ 5 }, // "CreateFont" },
|
||
|
{ 4 }, // ShowWindow, EnableWindow, HideWindow
|
||
|
{ 6 }, // "ExecShell" },
|
||
|
{ 3 }, // "Exec" }, // Exec, ExecWait
|
||
|
{ 3 }, // "GetFileTime" },
|
||
|
{ 3 }, // "GetDLLVersion" },
|
||
|
{ 6 }, // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage.
|
||
|
{ 6 }, // "CreateShortCut" },
|
||
|
{ 4 }, // "CopyFiles" },
|
||
|
{ 1 }, // "Reboot" },
|
||
|
{ 5 }, // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI
|
||
|
{ 4 }, // "ReadINIStr" },
|
||
|
{ 5 }, // "DeleteReg" }, // DeleteRegKey, DeleteRegValue
|
||
|
{ 6 }, // "WriteReg" }, // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD
|
||
|
{ 5 }, // "ReadReg" }, // ReadRegStr, ReadRegDWORD
|
||
|
{ 5 }, // "EnumReg" }, // EnumRegKey, EnumRegValue
|
||
|
{ 1 }, // "FileClose" },
|
||
|
{ 4 }, // "FileOpen" },
|
||
|
{ 3 }, // "FileWrite" }, // FileWrite, FileWriteByte
|
||
|
{ 4 }, // "FileRead" }, // FileRead, FileReadByte
|
||
|
{ 4 }, // "FileSeek" },
|
||
|
{ 1 }, // "FindClose" },
|
||
|
{ 2 }, // "FindNext" },
|
||
|
{ 3 }, // "FindFirst" },
|
||
|
{ 4 }, // "WriteUninstaller" },
|
||
|
{ 5 }, // "Section" }, // ***
|
||
|
{ 4 }, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType
|
||
|
{ 6 }, // "GetLabelAddr" },
|
||
|
{ 2 }, // "GetFunctionAddress" },
|
||
|
{ 1 }, // "LockWindow" },
|
||
|
{ 3 }, // "FileWrite" }, // FileWriteUTF16LE, FileWriteWord
|
||
|
{ 4 }, // "FileRead" }, // FileReadUTF16LE, FileReadWord
|
||
|
|
||
|
{ 2 }, // "Log" }, // LogSet, LogText
|
||
|
// Park
|
||
|
{ 2 }, // "FindProc" },
|
||
|
{ 2 }, // "GetFontVersion" },
|
||
|
{ 2 }, // "GetFontName" }
|
||
|
};
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
static const char * const k_CommandNames[kNumCmds] =
|
||
|
{
|
||
|
"Invalid"
|
||
|
, NULL // Return
|
||
|
, NULL // Nop, Goto
|
||
|
, "Abort"
|
||
|
, "Quit"
|
||
|
, NULL // Call
|
||
|
, "DetailPrint" // 1 param in new versions, 6 in old NSIS versions
|
||
|
, "Sleep"
|
||
|
, "BringToFront"
|
||
|
, "SetDetailsView"
|
||
|
, "SetFileAttributes"
|
||
|
, NULL // CreateDirectory, SetOutPath
|
||
|
, "IfFileExists"
|
||
|
, NULL // SetRebootFlag, ...
|
||
|
, "If" // IfAbort, IfSilent, IfErrors, IfRebootFlag
|
||
|
, "Get" // GetInstDirError, GetErrorLevel
|
||
|
, "Rename"
|
||
|
, "GetFullPathName"
|
||
|
, "SearchPath"
|
||
|
, "GetTempFileName"
|
||
|
, NULL // File
|
||
|
, "Delete"
|
||
|
, "MessageBox"
|
||
|
, "RMDir"
|
||
|
, "StrLen"
|
||
|
, NULL // StrCpy, GetCurrentAddress
|
||
|
, "StrCmp"
|
||
|
, NULL // ReadEnvStr, ExpandEnvStrings
|
||
|
, "IntCmp"
|
||
|
, "IntOp"
|
||
|
, "IntFmt"
|
||
|
, NULL // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage.
|
||
|
, "FindWindow"
|
||
|
, "SendMessage"
|
||
|
, "IsWindow"
|
||
|
, "GetDlgItem"
|
||
|
, "SetCtlColors"
|
||
|
, "SetBrandingImage"
|
||
|
, "CreateFont"
|
||
|
, NULL // ShowWindow, EnableWindow, HideWindow
|
||
|
, "ExecShell"
|
||
|
, "Exec" // Exec, ExecWait
|
||
|
, "GetFileTime"
|
||
|
, "GetDLLVersion"
|
||
|
, NULL // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage.
|
||
|
, "CreateShortCut"
|
||
|
, "CopyFiles"
|
||
|
, "Reboot"
|
||
|
, NULL // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI
|
||
|
, "ReadINIStr"
|
||
|
, "DeleteReg" // DeleteRegKey, DeleteRegValue
|
||
|
, "WriteReg" // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD
|
||
|
, "ReadReg" // ReadRegStr, ReadRegDWORD
|
||
|
, "EnumReg" // EnumRegKey, EnumRegValue
|
||
|
, "FileClose"
|
||
|
, "FileOpen"
|
||
|
, "FileWrite" // FileWrite, FileWriteByte
|
||
|
, "FileRead" // FileRead, FileReadByte
|
||
|
, "FileSeek"
|
||
|
, "FindClose"
|
||
|
, "FindNext"
|
||
|
, "FindFirst"
|
||
|
, "WriteUninstaller"
|
||
|
, "Section" // ***
|
||
|
, NULL // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType
|
||
|
, "GetLabelAddr"
|
||
|
, "GetFunctionAddress"
|
||
|
, "LockWindow"
|
||
|
, "FileWrite" // FileWriteUTF16LE, FileWriteWord
|
||
|
, "FileRead" // FileReadUTF16LE, FileReadWord
|
||
|
|
||
|
, "Log" // LogSet, LogText
|
||
|
|
||
|
// Park
|
||
|
, "FindProc"
|
||
|
, "GetFontVersion"
|
||
|
, "GetFontName"
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/* NSIS can use one name for two CSIDL_*** and CSIDL_COMMON_*** items (CurrentUser / AllUsers)
|
||
|
Some NSIS shell names are not identical to WIN32 CSIDL_* names.
|
||
|
NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */
|
||
|
|
||
|
static const char * const kShellStrings[] =
|
||
|
{
|
||
|
"DESKTOP" // +
|
||
|
, "INTERNET" // +
|
||
|
, "SMPROGRAMS" // CSIDL_PROGRAMS
|
||
|
, "CONTROLS" // +
|
||
|
, "PRINTERS" // +
|
||
|
, "DOCUMENTS" // CSIDL_PERSONAL
|
||
|
, "FAVORITES" // CSIDL_FAVORITES
|
||
|
, "SMSTARTUP" // CSIDL_STARTUP
|
||
|
, "RECENT" // CSIDL_RECENT
|
||
|
, "SENDTO" // CSIDL_SENDTO
|
||
|
, "BITBUCKET" // +
|
||
|
, "STARTMENU"
|
||
|
, NULL // CSIDL_MYDOCUMENTS = CSIDL_PERSONAL
|
||
|
, "MUSIC" // CSIDL_MYMUSIC
|
||
|
, "VIDEOS" // CSIDL_MYVIDEO
|
||
|
, NULL
|
||
|
, "DESKTOP" // CSIDL_DESKTOPDIRECTORY
|
||
|
, "DRIVES" // +
|
||
|
, "NETWORK" // +
|
||
|
, "NETHOOD"
|
||
|
, "FONTS"
|
||
|
, "TEMPLATES"
|
||
|
, "STARTMENU" // CSIDL_COMMON_STARTMENU
|
||
|
, "SMPROGRAMS" // CSIDL_COMMON_PROGRAMS
|
||
|
, "SMSTARTUP" // CSIDL_COMMON_STARTUP
|
||
|
, "DESKTOP" // CSIDL_COMMON_DESKTOPDIRECTORY
|
||
|
, "APPDATA" // CSIDL_APPDATA !!! "QUICKLAUNCH"
|
||
|
, "PRINTHOOD"
|
||
|
, "LOCALAPPDATA"
|
||
|
, "ALTSTARTUP"
|
||
|
, "ALTSTARTUP" // CSIDL_COMMON_ALTSTARTUP
|
||
|
, "FAVORITES" // CSIDL_COMMON_FAVORITES
|
||
|
, "INTERNET_CACHE"
|
||
|
, "COOKIES"
|
||
|
, "HISTORY"
|
||
|
, "APPDATA" // CSIDL_COMMON_APPDATA
|
||
|
, "WINDIR"
|
||
|
, "SYSDIR"
|
||
|
, "PROGRAM_FILES" // +
|
||
|
, "PICTURES" // CSIDL_MYPICTURES
|
||
|
, "PROFILE"
|
||
|
, "SYSTEMX86" // +
|
||
|
, "PROGRAM_FILESX86" // +
|
||
|
, "PROGRAM_FILES_COMMON" // +
|
||
|
, "PROGRAM_FILES_COMMONX8" // + CSIDL_PROGRAM_FILES_COMMONX86
|
||
|
, "TEMPLATES" // CSIDL_COMMON_TEMPLATES
|
||
|
, "DOCUMENTS" // CSIDL_COMMON_DOCUMENTS
|
||
|
, "ADMINTOOLS" // CSIDL_COMMON_ADMINTOOLS
|
||
|
, "ADMINTOOLS" // CSIDL_ADMINTOOLS
|
||
|
, "CONNECTIONS" // +
|
||
|
, NULL
|
||
|
, NULL
|
||
|
, NULL
|
||
|
, "MUSIC" // CSIDL_COMMON_MUSIC
|
||
|
, "PICTURES" // CSIDL_COMMON_PICTURES
|
||
|
, "VIDEOS" // CSIDL_COMMON_VIDEO
|
||
|
, "RESOURCES"
|
||
|
, "RESOURCES_LOCALIZED"
|
||
|
, "COMMON_OEM_LINKS" // +
|
||
|
, "CDBURN_AREA"
|
||
|
, NULL // unused
|
||
|
, "COMPUTERSNEARME" // +
|
||
|
};
|
||
|
|
||
|
|
||
|
static void UIntToString(AString &s, UInt32 v)
|
||
|
{
|
||
|
char sz[16];
|
||
|
ConvertUInt32ToString(v, sz);
|
||
|
s += sz;
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
void CInArchive::Add_UInt(UInt32 v)
|
||
|
{
|
||
|
char sz[16];
|
||
|
ConvertUInt32ToString(v, sz);
|
||
|
Script += sz;
|
||
|
}
|
||
|
|
||
|
static void Add_SignedInt(CDynLimBuf &s, Int32 v)
|
||
|
{
|
||
|
char sz[32];
|
||
|
ConvertInt64ToString(v, sz);
|
||
|
s += sz;
|
||
|
}
|
||
|
|
||
|
static void Add_Hex(CDynLimBuf &s, UInt32 v)
|
||
|
{
|
||
|
char sz[16];
|
||
|
sz[0] = '0';
|
||
|
sz[1] = 'x';
|
||
|
ConvertUInt32ToHex(v, sz + 2);
|
||
|
s += sz;
|
||
|
}
|
||
|
|
||
|
static UInt32 GetUi16Str_Len(const Byte *p)
|
||
|
{
|
||
|
const Byte *pp = p;
|
||
|
for (; *pp != 0 || *(pp + 1) != 0; pp += 2);
|
||
|
return (UInt32)((pp - p) >> 1);
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddLicense(UInt32 param, Int32 langID)
|
||
|
{
|
||
|
Space();
|
||
|
if (param >= NumStringChars ||
|
||
|
param + 1 >= NumStringChars)
|
||
|
{
|
||
|
Script += kErrorStr;
|
||
|
return;
|
||
|
}
|
||
|
strUsed[param] = 1;
|
||
|
|
||
|
UInt32 start = _stringsPos + (IsUnicode ? param * 2 : param);
|
||
|
UInt32 offset = start + (IsUnicode ? 2 : 1);
|
||
|
{
|
||
|
FOR_VECTOR (i, LicenseFiles)
|
||
|
{
|
||
|
const CLicenseFile &lic = LicenseFiles[i];
|
||
|
if (offset == lic.Offset)
|
||
|
{
|
||
|
Script += lic.Name;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
AString fileName = "[LICENSE]";
|
||
|
if (langID >= 0)
|
||
|
{
|
||
|
fileName += "\\license-";
|
||
|
// LangId_To_String(fileName, langID);
|
||
|
UIntToString(fileName, langID);
|
||
|
}
|
||
|
else if (++_numRootLicenses > 1)
|
||
|
{
|
||
|
fileName += '-';
|
||
|
UIntToString(fileName, _numRootLicenses);
|
||
|
}
|
||
|
const Byte *sz = (_data + start);
|
||
|
unsigned marker = IsUnicode ? Get16(sz) : *sz;
|
||
|
bool isRTF = (marker == 2);
|
||
|
fileName += isRTF ? ".rtf" : ".txt"; // if (*sz == 1) it's text;
|
||
|
Script += fileName;
|
||
|
|
||
|
CLicenseFile &lic = LicenseFiles.AddNew();
|
||
|
lic.Name = fileName;
|
||
|
lic.Offset = offset;
|
||
|
if (!IsUnicode)
|
||
|
lic.Size = (UInt32)strlen((const char *)sz + 1);
|
||
|
else
|
||
|
{
|
||
|
sz += 2;
|
||
|
UInt32 len = GetUi16Str_Len(sz);
|
||
|
lic.Size = len * 2;
|
||
|
if (isRTF)
|
||
|
{
|
||
|
lic.Text.Alloc((size_t)len);
|
||
|
for (UInt32 i = 0; i < len; i++, sz += 2)
|
||
|
{
|
||
|
unsigned c = Get16(sz);
|
||
|
if (c >= 256)
|
||
|
c = '?';
|
||
|
lic.Text[i] = (Byte)(c);
|
||
|
}
|
||
|
lic.Size = len;
|
||
|
lic.Offset = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define kVar_CMDLINE 20
|
||
|
#define kVar_INSTDIR 21
|
||
|
#define kVar_OUTDIR 22
|
||
|
#define kVar_EXEDIR 23
|
||
|
#define kVar_LANGUAGE 24
|
||
|
#define kVar_TEMP 25
|
||
|
#define kVar_PLUGINSDIR 26
|
||
|
#define kVar_EXEPATH 27 // NSIS 2.26+
|
||
|
#define kVar_EXEFILE 28 // NSIS 2.26+
|
||
|
|
||
|
#define kVar_HWNDPARENT_225 27
|
||
|
#define kVar_HWNDPARENT 29
|
||
|
|
||
|
// #define kVar__CLICK 30
|
||
|
#define kVar_Spec_OUTDIR_225 29 // NSIS 2.04 - 2.25
|
||
|
#define kVar_Spec_OUTDIR 31 // NSIS 2.26+
|
||
|
|
||
|
|
||
|
static const char * const kVarStrings[] =
|
||
|
{
|
||
|
"CMDLINE"
|
||
|
, "INSTDIR"
|
||
|
, "OUTDIR"
|
||
|
, "EXEDIR"
|
||
|
, "LANGUAGE"
|
||
|
, "TEMP"
|
||
|
, "PLUGINSDIR"
|
||
|
, "EXEPATH" // NSIS 2.26+
|
||
|
, "EXEFILE" // NSIS 2.26+
|
||
|
, "HWNDPARENT"
|
||
|
, "_CLICK" // is set from page->clicknext
|
||
|
, "_OUTDIR" // NSIS 2.04+
|
||
|
};
|
||
|
|
||
|
static const unsigned kNumInternalVars = 20 + ARRAY_SIZE(kVarStrings);
|
||
|
|
||
|
#define GET_NUM_INTERNAL_VARS (IsNsis200 ? kNumInternalVars - 3 : IsNsis225 ? kNumInternalVars - 2 : kNumInternalVars);
|
||
|
|
||
|
void CInArchive::GetVar2(AString &res, UInt32 index)
|
||
|
{
|
||
|
if (index < 20)
|
||
|
{
|
||
|
if (index >= 10)
|
||
|
{
|
||
|
res += 'R';
|
||
|
index -= 10;
|
||
|
}
|
||
|
UIntToString(res, index);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned numInternalVars = GET_NUM_INTERNAL_VARS;
|
||
|
if (index < numInternalVars)
|
||
|
{
|
||
|
if (IsNsis225 && index >= kVar_EXEPATH)
|
||
|
index += 2;
|
||
|
res += kVarStrings[index - 20];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
res += '_';
|
||
|
UIntToString(res, index - numInternalVars);
|
||
|
res += '_';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInArchive::GetVar(AString &res, UInt32 index)
|
||
|
{
|
||
|
res += '$';
|
||
|
GetVar2(res, index);
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
void CInArchive::Add_Var(UInt32 index)
|
||
|
{
|
||
|
_tempString_for_GetVar.Empty();
|
||
|
GetVar(_tempString_for_GetVar, index);
|
||
|
Script += _tempString_for_GetVar;
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddParam_Var(UInt32 index)
|
||
|
{
|
||
|
Space();
|
||
|
Add_Var(index);
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddParam_UInt(UInt32 value)
|
||
|
{
|
||
|
Space();
|
||
|
Add_UInt(value);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define NS_CODE_SKIP 252
|
||
|
#define NS_CODE_VAR 253
|
||
|
#define NS_CODE_SHELL 254
|
||
|
#define NS_CODE_LANG 255
|
||
|
|
||
|
#define NS_3_CODE_LANG 1
|
||
|
#define NS_3_CODE_SHELL 2
|
||
|
#define NS_3_CODE_VAR 3
|
||
|
#define NS_3_CODE_SKIP 4
|
||
|
|
||
|
#define PARK_CODE_SKIP 0xE000
|
||
|
#define PARK_CODE_VAR 0xE001
|
||
|
#define PARK_CODE_SHELL 0xE002
|
||
|
#define PARK_CODE_LANG 0xE003
|
||
|
|
||
|
#define IS_NS_SPEC_CHAR(c) ((c) >= NS_CODE_SKIP)
|
||
|
#define IS_PARK_SPEC_CHAR(c) ((c) >= PARK_CODE_SKIP && (c) <= PARK_CODE_LANG)
|
||
|
|
||
|
#define DECODE_NUMBER_FROM_2_CHARS(c0, c1) (((c0) & 0x7F) | (((unsigned)((c1) & 0x7F)) << 7))
|
||
|
#define CONVERT_NUMBER_NS_3_UNICODE(n) n = ((n & 0x7F) | (((n >> 8) & 0x7F) << 7))
|
||
|
#define CONVERT_NUMBER_PARK(n) n &= 0x7FFF
|
||
|
|
||
|
|
||
|
static bool AreStringsEqual_16and8(const Byte *p16, const char *p8)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
unsigned c16 = Get16(p16); p16 += 2;
|
||
|
unsigned c = (Byte)(*p8++);
|
||
|
if (c16 != c)
|
||
|
return false;
|
||
|
if (c == 0)
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2)
|
||
|
{
|
||
|
// zeros are not allowed here.
|
||
|
// if (index1 == 0 || index2 == 0) throw 333;
|
||
|
|
||
|
if ((index1 & 0x80) != 0)
|
||
|
{
|
||
|
unsigned offset = (index1 & 0x3F);
|
||
|
|
||
|
/* NSIS reads registry string:
|
||
|
keyName = HKLM Software\\Microsoft\\Windows\\CurrentVersion
|
||
|
mask = KEY_WOW64_64KEY, If 64-bit flag in index1 is set
|
||
|
valueName = string(offset)
|
||
|
If registry reading is failed, NSIS uses second parameter (index2)
|
||
|
to read string. The recursion is possible in that case in NSIS.
|
||
|
We don't parse index2 string. We only set strUsed status for that
|
||
|
string (but without recursion). */
|
||
|
|
||
|
if (offset >= NumStringChars)
|
||
|
{
|
||
|
s += kErrorStr;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
strUsed[offset] = 1;
|
||
|
if (index2 < NumStringChars)
|
||
|
strUsed[index2] = 1;
|
||
|
#endif
|
||
|
|
||
|
const Byte *p = (const Byte *)(_data + _stringsPos);
|
||
|
int id = -1;
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
p += offset * 2;
|
||
|
if (AreStringsEqual_16and8(p, "ProgramFilesDir"))
|
||
|
id = 0;
|
||
|
else if (AreStringsEqual_16and8(p, "CommonFilesDir"))
|
||
|
id = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
p += offset;
|
||
|
if (strcmp((const char *)p, "ProgramFilesDir") == 0)
|
||
|
id = 0;
|
||
|
else if (strcmp((const char *)p, "CommonFilesDir") == 0)
|
||
|
id = 1;
|
||
|
}
|
||
|
|
||
|
s += ((id >= 0) ? (id == 0 ? "$PROGRAMFILES" : "$COMMONFILES") :
|
||
|
"$_ERROR_UNSUPPORTED_VALUE_REGISTRY_");
|
||
|
// s += ((index1 & 0x40) != 0) ? "64" : "32";
|
||
|
if ((index1 & 0x40) != 0)
|
||
|
s += "64";
|
||
|
|
||
|
if (id < 0)
|
||
|
{
|
||
|
s += '(';
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
for (unsigned i = 0; i < 256; i++)
|
||
|
{
|
||
|
wchar_t c = Get16(p + i * 2);
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (c < 0x80)
|
||
|
s += (char)c;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
s += (const char *)p;
|
||
|
s += ')';
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
s += '$';
|
||
|
if (index1 < ARRAY_SIZE(kShellStrings))
|
||
|
{
|
||
|
const char *sz = kShellStrings[index1];
|
||
|
if (sz)
|
||
|
{
|
||
|
s += sz;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
if (index2 < ARRAY_SIZE(kShellStrings))
|
||
|
{
|
||
|
const char *sz = kShellStrings[index2];
|
||
|
if (sz)
|
||
|
{
|
||
|
s += sz;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
s += "_ERROR_UNSUPPORTED_SHELL_";
|
||
|
s += '[';
|
||
|
UIntToString(s, index1);
|
||
|
s += ',';
|
||
|
UIntToString(s, index2);
|
||
|
s += ']';
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
void CInArchive::Add_LangStr_Simple(UInt32 id)
|
||
|
{
|
||
|
Script += "LSTR_";
|
||
|
Add_UInt(id);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
void CInArchive::Add_LangStr(AString &res, UInt32 id)
|
||
|
{
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
langStrIDs.Add(id);
|
||
|
#endif
|
||
|
res += "$(LSTR_";
|
||
|
UIntToString(res, id);
|
||
|
res += ')';
|
||
|
}
|
||
|
|
||
|
void CInArchive::GetNsisString_Raw(const Byte *s)
|
||
|
{
|
||
|
Raw_AString.Empty();
|
||
|
|
||
|
if (NsisType != k_NsisType_Nsis3)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
Byte c = *s++;
|
||
|
if (c == 0)
|
||
|
return;
|
||
|
if (IS_NS_SPEC_CHAR(c))
|
||
|
{
|
||
|
Byte c0 = *s++;
|
||
|
if (c0 == 0)
|
||
|
return;
|
||
|
if (c != NS_CODE_SKIP)
|
||
|
{
|
||
|
Byte c1 = *s++;
|
||
|
if (c1 == 0)
|
||
|
return;
|
||
|
|
||
|
if (c == NS_CODE_SHELL)
|
||
|
GetShellString(Raw_AString, c0, c1);
|
||
|
else
|
||
|
{
|
||
|
unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
if (c == NS_CODE_VAR)
|
||
|
GetVar(Raw_AString, n);
|
||
|
else // if (c == NS_CODE_LANG)
|
||
|
Add_LangStr(Raw_AString, n);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
c = c0;
|
||
|
}
|
||
|
Raw_AString += (char)c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NSIS-3 ANSI
|
||
|
for (;;)
|
||
|
{
|
||
|
Byte c = *s++;
|
||
|
if (c <= NS_3_CODE_SKIP)
|
||
|
{
|
||
|
if (c == 0)
|
||
|
return;
|
||
|
Byte c0 = *s++;
|
||
|
if (c0 == 0)
|
||
|
return;
|
||
|
if (c != NS_3_CODE_SKIP)
|
||
|
{
|
||
|
Byte c1 = *s++;
|
||
|
if (c1 == 0)
|
||
|
return;
|
||
|
|
||
|
if (c == NS_3_CODE_SHELL)
|
||
|
GetShellString(Raw_AString, c0, c1);
|
||
|
else
|
||
|
{
|
||
|
unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
if (c == NS_3_CODE_VAR)
|
||
|
GetVar(Raw_AString, n);
|
||
|
else // if (c == NS_3_CODE_LANG)
|
||
|
Add_LangStr(Raw_AString, n);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
c = c0;
|
||
|
}
|
||
|
Raw_AString += (char)c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
void CInArchive::GetNsisString(AString &res, const Byte *s)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
Byte c = *s++;
|
||
|
if (c == 0)
|
||
|
return;
|
||
|
if (NsisType != k_NsisType_Nsis3)
|
||
|
{
|
||
|
if (IS_NS_SPEC_CHAR(c))
|
||
|
{
|
||
|
Byte c0 = *s++;
|
||
|
if (c0 == 0)
|
||
|
return;
|
||
|
if (c != NS_CODE_SKIP)
|
||
|
{
|
||
|
Byte c1 = *s++;
|
||
|
if (c1 == 0)
|
||
|
return;
|
||
|
if (c == NS_CODE_SHELL)
|
||
|
GetShellString(res, c0, c1);
|
||
|
else
|
||
|
{
|
||
|
unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
if (c == NS_CODE_VAR)
|
||
|
GetVar(res, n);
|
||
|
else // if (c == NS_CODE_LANG)
|
||
|
Add_LangStr(res, n);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
c = c0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// NSIS-3 ANSI
|
||
|
if (c <= NS_3_CODE_SKIP)
|
||
|
{
|
||
|
Byte c0 = *s++;
|
||
|
if (c0 == 0)
|
||
|
return;
|
||
|
if (c0 == 0)
|
||
|
break;
|
||
|
if (c != NS_3_CODE_SKIP)
|
||
|
{
|
||
|
Byte c1 = *s++;
|
||
|
if (c1 == 0)
|
||
|
return;
|
||
|
if (c == NS_3_CODE_SHELL)
|
||
|
GetShellString(res, c0, c1);
|
||
|
else
|
||
|
{
|
||
|
unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
if (c == NS_3_CODE_VAR)
|
||
|
GetVar(res, n);
|
||
|
else // if (c == NS_3_CODE_LANG)
|
||
|
Add_LangStr(res, n);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
c = c0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
const char *e;
|
||
|
if (c == 9) e = "$\\t";
|
||
|
else if (c == 10) e = "$\\n";
|
||
|
else if (c == 13) e = "$\\r";
|
||
|
else if (c == '"') e = "$\\\"";
|
||
|
else if (c == '$') e = "$$";
|
||
|
else
|
||
|
{
|
||
|
res += (char)c;
|
||
|
continue;
|
||
|
}
|
||
|
res += e;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
|
||
|
{
|
||
|
Raw_UString.Empty();
|
||
|
|
||
|
if (IsPark())
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
unsigned c = Get16(p);
|
||
|
p += 2;
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (c < 0x80)
|
||
|
{
|
||
|
Raw_UString += (wchar_t)c;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (IS_PARK_SPEC_CHAR(c))
|
||
|
{
|
||
|
unsigned n = Get16(p);
|
||
|
p += 2;
|
||
|
if (n == 0)
|
||
|
break;
|
||
|
if (c != PARK_CODE_SKIP)
|
||
|
{
|
||
|
Raw_AString.Empty();
|
||
|
if (c == PARK_CODE_SHELL)
|
||
|
GetShellString(Raw_AString, n & 0xFF, n >> 8);
|
||
|
else
|
||
|
{
|
||
|
CONVERT_NUMBER_PARK(n);
|
||
|
if (c == PARK_CODE_VAR)
|
||
|
GetVar(Raw_AString, n);
|
||
|
else // if (c == PARK_CODE_LANG)
|
||
|
Add_LangStr(Raw_AString, n);
|
||
|
}
|
||
|
Raw_UString.AddAscii(Raw_AString);
|
||
|
continue;
|
||
|
}
|
||
|
c = n;
|
||
|
}
|
||
|
|
||
|
Raw_UString += (wchar_t)c;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// NSIS-3 Unicode
|
||
|
for (;;)
|
||
|
{
|
||
|
unsigned c = Get16(p);
|
||
|
p += 2;
|
||
|
if (c > NS_3_CODE_SKIP)
|
||
|
{
|
||
|
Raw_UString += (wchar_t)c;
|
||
|
continue;
|
||
|
}
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
|
||
|
unsigned n = Get16(p);
|
||
|
p += 2;
|
||
|
if (n == 0)
|
||
|
break;
|
||
|
if (c == NS_3_CODE_SKIP)
|
||
|
{
|
||
|
Raw_UString += (wchar_t)n;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
Raw_AString.Empty();
|
||
|
if (c == NS_3_CODE_SHELL)
|
||
|
GetShellString(Raw_AString, n & 0xFF, n >> 8);
|
||
|
else
|
||
|
{
|
||
|
CONVERT_NUMBER_NS_3_UNICODE(n);
|
||
|
if (c == NS_3_CODE_VAR)
|
||
|
GetVar(Raw_AString, n);
|
||
|
else // if (c == NS_3_CODE_LANG)
|
||
|
Add_LangStr(Raw_AString, n);
|
||
|
}
|
||
|
Raw_UString.AddAscii(Raw_AString);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||
|
|
||
|
void CInArchive::GetNsisString_Unicode(AString &res, const Byte *p)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
unsigned c = Get16(p);
|
||
|
p += 2;
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (IsPark())
|
||
|
{
|
||
|
if (IS_PARK_SPEC_CHAR(c))
|
||
|
{
|
||
|
unsigned n = Get16(p);
|
||
|
p += 2;
|
||
|
if (n == 0)
|
||
|
break;
|
||
|
if (c != PARK_CODE_SKIP)
|
||
|
{
|
||
|
if (c == PARK_CODE_SHELL)
|
||
|
GetShellString(res, n & 0xFF, n >> 8);
|
||
|
else
|
||
|
{
|
||
|
CONVERT_NUMBER_PARK(n);
|
||
|
if (c == PARK_CODE_VAR)
|
||
|
GetVar(res, n);
|
||
|
else // if (c == PARK_CODE_LANG)
|
||
|
Add_LangStr(res, n);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
c = n;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// NSIS-3 Unicode
|
||
|
if (c <= NS_3_CODE_SKIP)
|
||
|
{
|
||
|
unsigned n = Get16(p);
|
||
|
p += 2;
|
||
|
if (n == 0)
|
||
|
break;
|
||
|
if (c != NS_3_CODE_SKIP)
|
||
|
{
|
||
|
if (c == NS_3_CODE_SHELL)
|
||
|
GetShellString(res, n & 0xFF, n >> 8);
|
||
|
else
|
||
|
{
|
||
|
CONVERT_NUMBER_NS_3_UNICODE(n);
|
||
|
if (c == NS_3_CODE_VAR)
|
||
|
GetVar(res, n);
|
||
|
else // if (c == NS_3_CODE_LANG)
|
||
|
Add_LangStr(res, n);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
c = n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (c < 0x80)
|
||
|
{
|
||
|
const char *e;
|
||
|
if (c == 9) e = "$\\t";
|
||
|
else if (c == 10) e = "$\\n";
|
||
|
else if (c == 13) e = "$\\r";
|
||
|
else if (c == '"') e = "$\\\"";
|
||
|
else if (c == '$') e = "$$";
|
||
|
else
|
||
|
{
|
||
|
res += (char)c;
|
||
|
continue;
|
||
|
}
|
||
|
res += e;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
UInt32 value = c;
|
||
|
/*
|
||
|
if (value >= 0xD800 && value < 0xE000)
|
||
|
{
|
||
|
UInt32 c2;
|
||
|
if (value >= 0xDC00 || srcPos == srcLen)
|
||
|
break;
|
||
|
c2 = src[srcPos++];
|
||
|
if (c2 < 0xDC00 || c2 >= 0xE000)
|
||
|
break;
|
||
|
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
||
|
}
|
||
|
*/
|
||
|
unsigned numAdds;
|
||
|
for (numAdds = 1; numAdds < 5; numAdds++)
|
||
|
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
|
||
|
break;
|
||
|
res += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
|
||
|
do
|
||
|
{
|
||
|
numAdds--;
|
||
|
res += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
|
||
|
// destPos++;
|
||
|
}
|
||
|
while (numAdds != 0);
|
||
|
|
||
|
// AddToUtf8(res, c);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
void CInArchive::ReadString2_Raw(UInt32 pos)
|
||
|
{
|
||
|
Raw_AString.Empty();
|
||
|
Raw_UString.Empty();
|
||
|
if ((Int32)pos < 0)
|
||
|
Add_LangStr(Raw_AString, -((Int32)pos + 1));
|
||
|
else if (pos >= NumStringChars)
|
||
|
{
|
||
|
Raw_AString += kErrorStr;
|
||
|
// UIntToString(Raw_AString, pos);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (IsUnicode)
|
||
|
GetNsisString_Unicode_Raw(_data + _stringsPos + pos * 2);
|
||
|
else
|
||
|
GetNsisString_Raw(_data + _stringsPos + pos);
|
||
|
return;
|
||
|
}
|
||
|
Raw_UString.SetFromAscii(Raw_AString);
|
||
|
}
|
||
|
|
||
|
bool CInArchive::IsGoodString(UInt32 param) const
|
||
|
{
|
||
|
if (param >= NumStringChars)
|
||
|
return false;
|
||
|
if (param == 0)
|
||
|
return true;
|
||
|
const Byte *p = _data + _stringsPos;
|
||
|
unsigned c;
|
||
|
if (IsUnicode)
|
||
|
c = Get16(p + param * 2 - 2);
|
||
|
else
|
||
|
c = p[param - 1];
|
||
|
// some files have '\\' character before string?
|
||
|
return (c == 0 || c == '\\');
|
||
|
}
|
||
|
|
||
|
bool CInArchive::AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const
|
||
|
{
|
||
|
if (param1 == param2)
|
||
|
return true;
|
||
|
|
||
|
/* NSIS-3.0a1 probably contains bug, so it can use 2 different strings
|
||
|
with same content. So we check real string also.
|
||
|
Also it's possible to check identical postfix parts of strings. */
|
||
|
|
||
|
if (param1 >= NumStringChars ||
|
||
|
param2 >= NumStringChars)
|
||
|
return false;
|
||
|
|
||
|
const Byte *p = _data + _stringsPos;
|
||
|
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
const Byte *p1 = p + param1 * 2;
|
||
|
const Byte *p2 = p + param2 * 2;
|
||
|
for (;;)
|
||
|
{
|
||
|
UInt16 c = Get16(p1);
|
||
|
if (c != Get16(p2))
|
||
|
return false;
|
||
|
if (c == 0)
|
||
|
return true;
|
||
|
p1 += 2;
|
||
|
p2 += 2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const Byte *p1 = p + param1;
|
||
|
const Byte *p2 = p + param2;
|
||
|
for (;;)
|
||
|
{
|
||
|
Byte c = *p1++;
|
||
|
if (c != *p2++)
|
||
|
return false;
|
||
|
if (c == 0)
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
UInt32 CInArchive::GetNumUsedVars() const
|
||
|
{
|
||
|
UInt32 numUsedVars = 0;
|
||
|
const Byte *data = (const Byte *)_data + _stringsPos;
|
||
|
unsigned npi = 0;
|
||
|
for (UInt32 i = 0; i < NumStringChars;)
|
||
|
{
|
||
|
bool process = true;
|
||
|
if (npi < noParseStringIndexes.Size() && noParseStringIndexes[npi] == i)
|
||
|
{
|
||
|
process = false;
|
||
|
npi++;
|
||
|
}
|
||
|
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (IsPark())
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
unsigned c = Get16(data + i * 2);
|
||
|
i++;
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (IS_PARK_SPEC_CHAR(c))
|
||
|
{
|
||
|
UInt32 n = Get16(data + i * 2);
|
||
|
i++;
|
||
|
if (n == 0)
|
||
|
break;
|
||
|
if (process && c == PARK_CODE_VAR)
|
||
|
{
|
||
|
CONVERT_NUMBER_PARK(n);
|
||
|
n++;
|
||
|
if (numUsedVars < n)
|
||
|
numUsedVars = n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else // NSIS-3 Unicode
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
unsigned c = Get16(data + i * 2);
|
||
|
i++;
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (c > NS_3_CODE_SKIP)
|
||
|
continue;
|
||
|
UInt32 n = Get16(data + i * 2);
|
||
|
i++;
|
||
|
if (n == 0)
|
||
|
break;
|
||
|
if (process && c == NS_3_CODE_VAR)
|
||
|
{
|
||
|
CONVERT_NUMBER_NS_3_UNICODE(n);
|
||
|
n++;
|
||
|
if (numUsedVars < n)
|
||
|
numUsedVars = n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else // not Unicode (ANSI)
|
||
|
{
|
||
|
if (NsisType != k_NsisType_Nsis3)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
Byte c = data[i++];
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (IS_NS_SPEC_CHAR(c))
|
||
|
{
|
||
|
Byte c0 = data[i++];
|
||
|
if (c0 == 0)
|
||
|
break;
|
||
|
if (c == NS_CODE_SKIP)
|
||
|
continue;
|
||
|
Byte c1 = data[i++];
|
||
|
if (c1 == 0)
|
||
|
break;
|
||
|
if (process && c == NS_CODE_VAR)
|
||
|
{
|
||
|
UInt32 n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
n++;
|
||
|
if (numUsedVars < n)
|
||
|
numUsedVars = n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// NSIS-3 ANSI
|
||
|
for (;;)
|
||
|
{
|
||
|
Byte c = data[i++];
|
||
|
if (c == 0)
|
||
|
break;
|
||
|
if (c > NS_3_CODE_SKIP)
|
||
|
continue;
|
||
|
|
||
|
Byte c0 = data[i++];
|
||
|
if (c0 == 0)
|
||
|
break;
|
||
|
if (c == NS_3_CODE_SKIP)
|
||
|
continue;
|
||
|
Byte c1 = data[i++];
|
||
|
if (c1 == 0)
|
||
|
break;
|
||
|
if (process && c == NS_3_CODE_VAR)
|
||
|
{
|
||
|
UInt32 n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
n++;
|
||
|
if (numUsedVars < n)
|
||
|
numUsedVars = n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return numUsedVars;
|
||
|
}
|
||
|
|
||
|
void CInArchive::ReadString2(AString &s, UInt32 pos)
|
||
|
{
|
||
|
if ((Int32)pos < 0)
|
||
|
{
|
||
|
Add_LangStr(s, -((Int32)pos + 1));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (pos >= NumStringChars)
|
||
|
{
|
||
|
s += kErrorStr;
|
||
|
// UIntToString(s, pos);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
strUsed[pos] = 1;
|
||
|
#endif
|
||
|
|
||
|
if (IsUnicode)
|
||
|
GetNsisString_Unicode(s, _data + _stringsPos + pos * 2);
|
||
|
else
|
||
|
GetNsisString(s, _data + _stringsPos + pos);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
#define DEL_DIR 1
|
||
|
#define DEL_RECURSE 2
|
||
|
#define DEL_REBOOT 4
|
||
|
// #define DEL_SIMPLE 8
|
||
|
|
||
|
void CInArchive::AddRegRoot(UInt32 val)
|
||
|
{
|
||
|
Space();
|
||
|
const char *s;
|
||
|
switch (val)
|
||
|
{
|
||
|
case 0: s = "SHCTX"; break;
|
||
|
case 0x80000000: s = "HKCR"; break;
|
||
|
case 0x80000001: s = "HKCU"; break;
|
||
|
case 0x80000002: s = "HKLM"; break;
|
||
|
case 0x80000003: s = "HKU"; break;
|
||
|
case 0x80000004: s = "HKPD"; break;
|
||
|
case 0x80000005: s = "HKCC"; break;
|
||
|
case 0x80000006: s = "HKDD"; break;
|
||
|
case 0x80000050: s = "HKPT"; break;
|
||
|
case 0x80000060: s = "HKPN"; break;
|
||
|
default:
|
||
|
// Script += " RRRRR ";
|
||
|
// throw 1;
|
||
|
Add_Hex(Script, val); return;
|
||
|
}
|
||
|
Script += s;
|
||
|
}
|
||
|
|
||
|
static const char *g_WinAttrib[] =
|
||
|
{
|
||
|
"READONLY"
|
||
|
, "HIDDEN"
|
||
|
, "SYSTEM"
|
||
|
, NULL
|
||
|
, "DIRECTORY"
|
||
|
, "ARCHIVE"
|
||
|
, "DEVICE"
|
||
|
, "NORMAL"
|
||
|
, "TEMPORARY"
|
||
|
, "SPARSE_FILE"
|
||
|
, "REPARSE_POINT"
|
||
|
, "COMPRESSED"
|
||
|
, "OFFLINE"
|
||
|
, "NOT_CONTENT_INDEXED"
|
||
|
, "ENCRYPTED"
|
||
|
, NULL
|
||
|
, "VIRTUAL"
|
||
|
};
|
||
|
|
||
|
#define FLAGS_DELIMITER '|'
|
||
|
|
||
|
static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned num, UInt32 flags)
|
||
|
{
|
||
|
bool filled = false;
|
||
|
for (unsigned i = 0; i < num; i++)
|
||
|
{
|
||
|
UInt32 f = (UInt32)1 << i;
|
||
|
if ((flags & f) != 0)
|
||
|
{
|
||
|
const char *name = table[i];
|
||
|
if (name)
|
||
|
{
|
||
|
if (filled)
|
||
|
s += FLAGS_DELIMITER;
|
||
|
filled = true;
|
||
|
s += name;
|
||
|
flags &= ~f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (flags != 0)
|
||
|
{
|
||
|
if (filled)
|
||
|
s += FLAGS_DELIMITER;
|
||
|
Add_Hex(s, flags);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool DoesNeedQuotes(const char *s)
|
||
|
{
|
||
|
char c = s[0];
|
||
|
if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*'))
|
||
|
return true;
|
||
|
for (;;)
|
||
|
{
|
||
|
char c = *s++;
|
||
|
if (c == 0)
|
||
|
return false;
|
||
|
if (c == ' ')
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_QuStr(const AString &s)
|
||
|
{
|
||
|
bool needQuotes = DoesNeedQuotes(s);
|
||
|
if (needQuotes)
|
||
|
Script += '\"';
|
||
|
Script += s;
|
||
|
if (needQuotes)
|
||
|
Script += '\"';
|
||
|
}
|
||
|
|
||
|
void CInArchive::SpaceQuStr(const AString &s)
|
||
|
{
|
||
|
Space();
|
||
|
Add_QuStr(s);
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddParam(UInt32 pos)
|
||
|
{
|
||
|
_tempString.Empty();
|
||
|
ReadString2(_tempString, pos);
|
||
|
SpaceQuStr(_tempString);
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddParams(const UInt32 *params, unsigned num)
|
||
|
{
|
||
|
for (unsigned i = 0; i < num; i++)
|
||
|
AddParam(params[i]);
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddOptionalParam(UInt32 pos)
|
||
|
{
|
||
|
if (pos != 0)
|
||
|
AddParam(pos);
|
||
|
}
|
||
|
|
||
|
static unsigned GetNumParams(const UInt32 *params, unsigned num)
|
||
|
{
|
||
|
for (; num > 0 && params[num - 1] == 0; num--);
|
||
|
return num;
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddOptionalParams(const UInt32 *params, unsigned num)
|
||
|
{
|
||
|
AddParams(params, GetNumParams(params, num));
|
||
|
}
|
||
|
|
||
|
|
||
|
static const UInt32 CMD_REF_Goto = (1 << 0);
|
||
|
static const UInt32 CMD_REF_Call = (1 << 1);
|
||
|
static const UInt32 CMD_REF_Pre = (1 << 2);
|
||
|
static const UInt32 CMD_REF_Show = (1 << 3);
|
||
|
static const UInt32 CMD_REF_Leave = (1 << 4);
|
||
|
static const UInt32 CMD_REF_OnFunc = (1 << 5);
|
||
|
static const UInt32 CMD_REF_Section = (1 << 6);
|
||
|
static const UInt32 CMD_REF_InitPluginDir = (1 << 7);
|
||
|
// static const UInt32 CMD_REF_Creator = (1 << 5); // _Pre is used instead
|
||
|
static const unsigned CMD_REF_OnFunc_NumShifts = 28; // it uses for onFunc too
|
||
|
static const unsigned CMD_REF_Page_NumShifts = 16; // it uses for onFunc too
|
||
|
static const UInt32 CMD_REF_Page_Mask = 0x0FFF0000;
|
||
|
static const UInt32 CMD_REF_OnFunc_Mask = 0xF0000000;
|
||
|
|
||
|
inline bool IsPageFunc(UInt32 flag)
|
||
|
{
|
||
|
return (flag & (CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave)) != 0;
|
||
|
}
|
||
|
|
||
|
inline bool IsFunc(UInt32 flag)
|
||
|
{
|
||
|
// return (flag & (CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave | CMD_REF_OnFunc)) != 0;
|
||
|
return (flag & (CMD_REF_Call | CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave | CMD_REF_OnFunc)) != 0;
|
||
|
}
|
||
|
|
||
|
inline bool IsProbablyEndOfFunc(UInt32 flag)
|
||
|
{
|
||
|
return (flag != 0 && flag != CMD_REF_Goto);
|
||
|
}
|
||
|
|
||
|
static const char * const kOnFunc[] =
|
||
|
{
|
||
|
"Init"
|
||
|
, "InstSuccess"
|
||
|
, "InstFailed"
|
||
|
, "UserAbort"
|
||
|
, "GUIInit"
|
||
|
, "GUIEnd"
|
||
|
, "MouseOverSection"
|
||
|
, "VerifyInstDir"
|
||
|
, "SelChange"
|
||
|
, "RebootFailed"
|
||
|
};
|
||
|
|
||
|
void CInArchive::Add_FuncName(const UInt32 *labels, UInt32 index)
|
||
|
{
|
||
|
UInt32 mask = labels[index];
|
||
|
if (mask & CMD_REF_OnFunc)
|
||
|
{
|
||
|
Script += ".on";
|
||
|
Script += kOnFunc[labels[index] >> CMD_REF_OnFunc_NumShifts];
|
||
|
}
|
||
|
else if (mask & CMD_REF_InitPluginDir)
|
||
|
{
|
||
|
/*
|
||
|
if (!IsInstaller)
|
||
|
Script += "un."
|
||
|
*/
|
||
|
Script += "Initialize_____Plugins";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Script += "func_";
|
||
|
Add_UInt(index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddParam_Func(const UInt32 *labels, UInt32 index)
|
||
|
{
|
||
|
Space();
|
||
|
if ((Int32)index >= 0)
|
||
|
Add_FuncName(labels, index);
|
||
|
else
|
||
|
AddQuotes();
|
||
|
}
|
||
|
|
||
|
|
||
|
void CInArchive::Add_LabelName(UInt32 index)
|
||
|
{
|
||
|
Script += "label_";
|
||
|
Add_UInt(index);
|
||
|
}
|
||
|
|
||
|
// param != 0
|
||
|
void CInArchive::Add_GotoVar(UInt32 param)
|
||
|
{
|
||
|
Space();
|
||
|
if ((Int32)param < 0)
|
||
|
Add_Var(-((Int32)param + 1));
|
||
|
else
|
||
|
Add_LabelName(param - 1);
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_GotoVar1(UInt32 param)
|
||
|
{
|
||
|
if (param == 0)
|
||
|
Script += " 0";
|
||
|
else
|
||
|
Add_GotoVar(param);
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_GotoVars2(const UInt32 *params)
|
||
|
{
|
||
|
Add_GotoVar1(params[0]);
|
||
|
if (params[1] != 0)
|
||
|
Add_GotoVar(params[1]);
|
||
|
}
|
||
|
|
||
|
static bool NoLabels(const UInt32 *labels, UInt32 num)
|
||
|
{
|
||
|
for (UInt32 i = 0; i < num; i++)
|
||
|
if (labels[i] != 0)
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static const char * const k_REBOOTOK = " /REBOOTOK";
|
||
|
|
||
|
#define MY__MB_ABORTRETRYIGNORE 2
|
||
|
#define MY__MB_RETRYCANCEL 5
|
||
|
|
||
|
static const char * const k_MB_Buttons[] =
|
||
|
{
|
||
|
"OK"
|
||
|
, "OKCANCEL"
|
||
|
, "ABORTRETRYIGNORE"
|
||
|
, "YESNOCANCEL"
|
||
|
, "YESNO"
|
||
|
, "RETRYCANCEL"
|
||
|
, "CANCELTRYCONTINUE"
|
||
|
};
|
||
|
|
||
|
#define MY__MB_ICONSTOP (1 << 4)
|
||
|
|
||
|
static const char * const k_MB_Icons[] =
|
||
|
{
|
||
|
NULL
|
||
|
, "ICONSTOP"
|
||
|
, "ICONQUESTION"
|
||
|
, "ICONEXCLAMATION"
|
||
|
, "ICONINFORMATION"
|
||
|
};
|
||
|
|
||
|
static const char * const k_MB_Flags[] =
|
||
|
{
|
||
|
"HELP"
|
||
|
, "NOFOCUS"
|
||
|
, "SETFOREGROUND"
|
||
|
, "DEFAULT_DESKTOP_ONLY"
|
||
|
, "TOPMOST"
|
||
|
, "RIGHT"
|
||
|
, "RTLREADING"
|
||
|
// , "SERVICE_NOTIFICATION" // unsupported. That bit is used for NSIS purposes
|
||
|
};
|
||
|
|
||
|
#define MY__IDCANCEL 2
|
||
|
#define MY__IDIGNORE 5
|
||
|
|
||
|
static const char * const k_Button_IDs[] =
|
||
|
{
|
||
|
"0"
|
||
|
, "IDOK"
|
||
|
, "IDCANCEL"
|
||
|
, "IDABORT"
|
||
|
, "IDRETRY"
|
||
|
, "IDIGNORE"
|
||
|
, "IDYES"
|
||
|
, "IDNO"
|
||
|
, "IDCLOSE"
|
||
|
, "IDHELP"
|
||
|
, "IDTRYAGAIN"
|
||
|
, "IDCONTINUE"
|
||
|
};
|
||
|
|
||
|
void CInArchive::Add_ButtonID(UInt32 buttonID)
|
||
|
{
|
||
|
Space();
|
||
|
if (buttonID < ARRAY_SIZE(k_Button_IDs))
|
||
|
Script += k_Button_IDs[buttonID];
|
||
|
else
|
||
|
{
|
||
|
Script += "Button_";
|
||
|
Add_UInt(buttonID);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const
|
||
|
{
|
||
|
if (offset >= NumStringChars)
|
||
|
return false;
|
||
|
if (IsUnicode)
|
||
|
return AreStringsEqual_16and8(_data + _stringsPos + offset * 2, s);
|
||
|
else
|
||
|
return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0;
|
||
|
}
|
||
|
|
||
|
static bool StringToUInt32(const char *s, UInt32 &res)
|
||
|
{
|
||
|
const char *end;
|
||
|
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
|
||
|
res = ConvertHexStringToUInt32(s + 2, &end);
|
||
|
else
|
||
|
res = ConvertStringToUInt32(s, &end);
|
||
|
return (*end == 0);
|
||
|
}
|
||
|
|
||
|
static const unsigned k_CtlColors_Size = 24;
|
||
|
|
||
|
struct CNsis_CtlColors
|
||
|
{
|
||
|
UInt32 text; // COLORREF
|
||
|
UInt32 bkc; // COLORREF
|
||
|
UInt32 lbStyle;
|
||
|
UInt32 bkb; // HBRUSH
|
||
|
Int32 bkmode;
|
||
|
Int32 flags;
|
||
|
|
||
|
void Parse(const Byte *p);
|
||
|
};
|
||
|
|
||
|
void CNsis_CtlColors::Parse(const Byte *p)
|
||
|
{
|
||
|
text = Get32(p);
|
||
|
bkc = Get32(p + 4);
|
||
|
lbStyle = Get32(p + 8);
|
||
|
bkb = Get32(p + 12);
|
||
|
bkmode = (Int32)Get32(p + 16);
|
||
|
flags = (Int32)Get32(p + 20);
|
||
|
}
|
||
|
|
||
|
// Win32 constants
|
||
|
#define MY__TRANSPARENT 1
|
||
|
#define MY__OPAQUE 2
|
||
|
|
||
|
#define MY__GENERIC_READ (1 << 31)
|
||
|
#define MY__GENERIC_WRITE (1 << 30)
|
||
|
#define MY__GENERIC_EXECUTE (1 << 29)
|
||
|
#define MY__GENERIC_ALL (1 << 28)
|
||
|
|
||
|
#define MY__CREATE_NEW 1
|
||
|
#define MY__CREATE_ALWAYS 2
|
||
|
#define MY__OPEN_EXISTING 3
|
||
|
#define MY__OPEN_ALWAYS 4
|
||
|
#define MY__TRUNCATE_EXISTING 5
|
||
|
|
||
|
// text/bg colors
|
||
|
#define kColorsFlags_TEXT 1
|
||
|
#define kColorsFlags_TEXT_SYS 2
|
||
|
#define kColorsFlags_BK 4
|
||
|
#define kColorsFlags_BK_SYS 8
|
||
|
#define kColorsFlags_BKB 16
|
||
|
|
||
|
void CInArchive::Add_Color2(UInt32 v)
|
||
|
{
|
||
|
v = ((v & 0xFF) << 16) | (v & 0xFF00) | ((v >> 16) & 0xFF);
|
||
|
char sz[32];
|
||
|
for (int i = 5; i >= 0; i--)
|
||
|
{
|
||
|
unsigned t = v & 0xF;
|
||
|
v >>= 4;
|
||
|
sz[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));
|
||
|
}
|
||
|
sz[6] = 0;
|
||
|
Script += sz;
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_ColorParam(UInt32 v)
|
||
|
{
|
||
|
Space();
|
||
|
Add_Color2(v);
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_Color(UInt32 v)
|
||
|
{
|
||
|
Script += "0x";
|
||
|
Add_Color2(v);
|
||
|
}
|
||
|
|
||
|
#define MY__SW_HIDE 0
|
||
|
#define MY__SW_SHOWNORMAL 1
|
||
|
|
||
|
#define MY__SW_SHOWMINIMIZED 2
|
||
|
#define MY__SW_SHOWMINNOACTIVE 7
|
||
|
#define MY__SW_SHOWNA 8
|
||
|
|
||
|
static const char * const kShowWindow_Commands[] =
|
||
|
{
|
||
|
"HIDE"
|
||
|
, "SHOWNORMAL" // "NORMAL"
|
||
|
, "SHOWMINIMIZED"
|
||
|
, "SHOWMAXIMIZED" // "MAXIMIZE"
|
||
|
, "SHOWNOACTIVATE"
|
||
|
, "SHOW"
|
||
|
, "MINIMIZE"
|
||
|
, "SHOWMINNOACTIVE"
|
||
|
, "SHOWNA"
|
||
|
, "RESTORE"
|
||
|
, "SHOWDEFAULT"
|
||
|
, "FORCEMINIMIZE" // "MAX"
|
||
|
};
|
||
|
|
||
|
static void Add_ShowWindow_Cmd_2(AString &s, UInt32 cmd)
|
||
|
{
|
||
|
if (cmd < ARRAY_SIZE(kShowWindow_Commands))
|
||
|
{
|
||
|
s += "SW_";
|
||
|
s += kShowWindow_Commands[cmd];
|
||
|
}
|
||
|
else
|
||
|
UIntToString(s, cmd);
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_ShowWindow_Cmd(UInt32 cmd)
|
||
|
{
|
||
|
if (cmd < ARRAY_SIZE(kShowWindow_Commands))
|
||
|
{
|
||
|
Script += "SW_";
|
||
|
Script += kShowWindow_Commands[cmd];
|
||
|
}
|
||
|
else
|
||
|
Add_UInt(cmd);
|
||
|
}
|
||
|
|
||
|
void CInArchive::Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type)
|
||
|
{
|
||
|
if (type < tableSize)
|
||
|
Script += table[type];
|
||
|
else
|
||
|
{
|
||
|
Script += '_';
|
||
|
Add_UInt(type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define ADD_TYPE_FROM_LIST(table, type) Add_TypeFromList(table, ARRAY_SIZE(table), type)
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
k_ExecFlags_AutoClose,
|
||
|
k_ExecFlags_ShellVarContext,
|
||
|
k_ExecFlags_Errors,
|
||
|
k_ExecFlags_Abort,
|
||
|
k_ExecFlags_RebootFlag,
|
||
|
k_ExecFlags_reboot_called,
|
||
|
k_ExecFlags_cur_insttype,
|
||
|
k_ExecFlags_plugin_api_version,
|
||
|
k_ExecFlags_Silent,
|
||
|
k_ExecFlags_InstDirError,
|
||
|
k_ExecFlags_rtl,
|
||
|
k_ExecFlags_ErrorLevel,
|
||
|
k_ExecFlags_RegView,
|
||
|
k_ExecFlags_DetailsPrint = 13,
|
||
|
};
|
||
|
|
||
|
// Names for NSIS exec_flags_t structure vars
|
||
|
static const char * const kExecFlags_VarsNames[] =
|
||
|
{
|
||
|
"AutoClose" // autoclose;
|
||
|
, "ShellVarContext" // all_user_var;
|
||
|
, "Errors" // exec_error;
|
||
|
, "Abort" // abort;
|
||
|
, "RebootFlag" // exec_reboot; // NSIS_SUPPORT_REBOOT
|
||
|
, "reboot_called" // reboot_called; // NSIS_SUPPORT_REBOOT
|
||
|
, "cur_insttype" // XXX_cur_insttype; // depreacted
|
||
|
, "plugin_api_version" // plugin_api_version; // see NSISPIAPIVER_CURR
|
||
|
// used to be XXX_insttype_changed
|
||
|
, "Silent" // silent; // NSIS_CONFIG_SILENT_SUPPORT
|
||
|
, "InstDirError" // instdir_error;
|
||
|
, "rtl" // rtl;
|
||
|
, "ErrorLevel" // errlvl;
|
||
|
, "RegView" // alter_reg_view;
|
||
|
, "DetailsPrint" // status_update;
|
||
|
};
|
||
|
|
||
|
void CInArchive::Add_ExecFlags(UInt32 flagsType)
|
||
|
{
|
||
|
ADD_TYPE_FROM_LIST(kExecFlags_VarsNames, flagsType);
|
||
|
}
|
||
|
|
||
|
|
||
|
// ---------- Page ----------
|
||
|
|
||
|
// page flags
|
||
|
#define PF_CANCEL_ENABLE 4
|
||
|
#define PF_LICENSE_FORCE_SELECTION 32
|
||
|
#define PF_LICENSE_NO_FORCE_SELECTION 64
|
||
|
#define PF_PAGE_EX 512
|
||
|
#define PF_DIR_NO_BTN_DISABLE 1024
|
||
|
/*
|
||
|
#define PF_LICENSE_SELECTED 1
|
||
|
#define PF_NEXT_ENABLE 2
|
||
|
#define PF_BACK_SHOW 8
|
||
|
#define PF_LICENSE_STREAM 16
|
||
|
#define PF_NO_NEXT_FOCUS 128
|
||
|
#define PF_BACK_ENABLE 256
|
||
|
*/
|
||
|
|
||
|
// page window proc
|
||
|
enum
|
||
|
{
|
||
|
PWP_LICENSE,
|
||
|
PWP_SELCOM,
|
||
|
PWP_DIR,
|
||
|
PWP_INSTFILES,
|
||
|
PWP_UNINST,
|
||
|
PWP_COMPLETED,
|
||
|
PWP_CUSTOM
|
||
|
};
|
||
|
|
||
|
static const char * const kPageTypes[] =
|
||
|
{
|
||
|
"license"
|
||
|
, "components"
|
||
|
, "directory"
|
||
|
, "instfiles"
|
||
|
, "uninstConfirm"
|
||
|
, "COMPLETED"
|
||
|
, "custom"
|
||
|
};
|
||
|
|
||
|
#define SET_FUNC_REF(x, flag) if ((Int32)(x) >= 0 && (x) < bh.Num) \
|
||
|
{ labels[x] = (labels[x] & ~CMD_REF_Page_Mask) | ((flag) | (pageIndex << CMD_REF_Page_NumShifts)); }
|
||
|
|
||
|
// #define IDD_LICENSE 102
|
||
|
#define IDD_LICENSE_FSRB 108
|
||
|
#define IDD_LICENSE_FSCB 109
|
||
|
|
||
|
void CInArchive::AddPageOption1(UInt32 param, const char *name)
|
||
|
{
|
||
|
if (param == 0)
|
||
|
return;
|
||
|
TabString(name);
|
||
|
AddParam(param);
|
||
|
NewLine();
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddPageOption(const UInt32 *params, unsigned num, const char *name)
|
||
|
{
|
||
|
num = GetNumParams(params, num);
|
||
|
if (num == 0)
|
||
|
return;
|
||
|
TabString(name);
|
||
|
AddParams(params, num);
|
||
|
NewLine();
|
||
|
}
|
||
|
|
||
|
void CInArchive::Separator()
|
||
|
{
|
||
|
AddLF();
|
||
|
AddCommentAndString("--------------------");
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
void CInArchive::Space()
|
||
|
{
|
||
|
Script += ' ';
|
||
|
}
|
||
|
|
||
|
void CInArchive::Tab()
|
||
|
{
|
||
|
Script += " ";
|
||
|
}
|
||
|
|
||
|
void CInArchive::Tab(bool commented)
|
||
|
{
|
||
|
Script += commented ? " ; " : " ";
|
||
|
}
|
||
|
|
||
|
void CInArchive::BigSpaceComment()
|
||
|
{
|
||
|
Script += " ; ";
|
||
|
}
|
||
|
|
||
|
void CInArchive::SmallSpaceComment()
|
||
|
{
|
||
|
Script += " ; ";
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddCommentAndString(const char *s)
|
||
|
{
|
||
|
Script += "; ";
|
||
|
Script += s;
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddError(const char *s)
|
||
|
{
|
||
|
BigSpaceComment();
|
||
|
Script += "!!! ERROR: ";
|
||
|
Script += s;
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddErrorLF(const char *s)
|
||
|
{
|
||
|
AddError(s);
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
void CInArchive::CommentOpen()
|
||
|
{
|
||
|
AddStringLF("/*");
|
||
|
}
|
||
|
|
||
|
void CInArchive::CommentClose()
|
||
|
{
|
||
|
AddStringLF("*/");
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddLF()
|
||
|
{
|
||
|
Script += CR_LF;
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddQuotes()
|
||
|
{
|
||
|
Script += "\"\"";
|
||
|
}
|
||
|
|
||
|
void CInArchive::TabString(const char *s)
|
||
|
{
|
||
|
Tab();
|
||
|
Script += s;
|
||
|
}
|
||
|
|
||
|
void CInArchive::AddStringLF(const char *s)
|
||
|
{
|
||
|
Script += s;
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
// ---------- Section ----------
|
||
|
|
||
|
static const char * const kSection_VarsNames[] =
|
||
|
{
|
||
|
"Text"
|
||
|
, "InstTypes"
|
||
|
, "Flags"
|
||
|
, "Code"
|
||
|
, "CodeSize"
|
||
|
, "Size" // size in KB
|
||
|
};
|
||
|
|
||
|
void CInArchive::Add_SectOp(UInt32 opType)
|
||
|
{
|
||
|
ADD_TYPE_FROM_LIST(kSection_VarsNames, opType);
|
||
|
}
|
||
|
|
||
|
void CSection::Parse(const Byte *p)
|
||
|
{
|
||
|
Name = Get32(p);
|
||
|
InstallTypes = Get32(p + 4);
|
||
|
Flags = Get32(p + 8);
|
||
|
StartCmdIndex = Get32(p + 12);
|
||
|
NumCommands = Get32(p + 16);
|
||
|
SizeKB = Get32(p + 20);
|
||
|
};
|
||
|
|
||
|
// used for section->flags
|
||
|
#define SF_SELECTED (1 << 0)
|
||
|
#define SF_SECGRP (1 << 1)
|
||
|
#define SF_SECGRPEND (1 << 2)
|
||
|
#define SF_BOLD (1 << 3)
|
||
|
#define SF_RO (1 << 4)
|
||
|
#define SF_EXPAND (1 << 5)
|
||
|
#define SF_PSELECTED (1 << 6)
|
||
|
#define SF_TOGGLED (1 << 7)
|
||
|
#define SF_NAMECHG (1 << 8)
|
||
|
|
||
|
bool CInArchive::PrintSectionBegin(const CSection §, unsigned index)
|
||
|
{
|
||
|
AString name;
|
||
|
if (sect.Flags & SF_BOLD)
|
||
|
name += '!';
|
||
|
AString s2;
|
||
|
ReadString2(s2, sect.Name);
|
||
|
if (!IsInstaller)
|
||
|
{
|
||
|
if (!StringsAreEqualNoCase_Ascii(s2, "uninstall"))
|
||
|
name += "un.";
|
||
|
}
|
||
|
name += s2;
|
||
|
|
||
|
if (sect.Flags & SF_SECGRPEND)
|
||
|
{
|
||
|
AddStringLF("SectionGroupEnd");
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (sect.Flags & SF_SECGRP)
|
||
|
{
|
||
|
Script += "SectionGroup";
|
||
|
if (sect.Flags & SF_EXPAND)
|
||
|
Script += " /e";
|
||
|
SpaceQuStr(name);
|
||
|
Script += " ; Section";
|
||
|
AddParam_UInt(index);
|
||
|
NewLine();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
Script += "Section";
|
||
|
if ((sect.Flags & SF_SELECTED) == 0)
|
||
|
Script += " /o";
|
||
|
if (!name.IsEmpty())
|
||
|
SpaceQuStr(name);
|
||
|
|
||
|
/*
|
||
|
if (!name.IsEmpty())
|
||
|
Script += ' ';
|
||
|
else
|
||
|
*/
|
||
|
SmallSpaceComment();
|
||
|
Script += "Section_";
|
||
|
Add_UInt(index);
|
||
|
|
||
|
/*
|
||
|
Script += " ; flags = ";
|
||
|
Add_Hex(Script, sect.Flags);
|
||
|
*/
|
||
|
|
||
|
NewLine();
|
||
|
|
||
|
if (sect.SizeKB != 0)
|
||
|
{
|
||
|
// probably we must show AddSize, only if there is additional size.
|
||
|
Tab();
|
||
|
AddCommentAndString("AddSize");
|
||
|
AddParam_UInt(sect.SizeKB);
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
bool needSectionIn =
|
||
|
(sect.Name != 0 && sect.InstallTypes != 0) ||
|
||
|
(sect.Name == 0 && sect.InstallTypes != 0xFFFFFFFF);
|
||
|
if (needSectionIn || (sect.Flags & SF_RO) != 0)
|
||
|
{
|
||
|
TabString("SectionIn");
|
||
|
UInt32 instTypes = sect.InstallTypes;
|
||
|
for (int i = 0; i < 32; i++, instTypes >>= 1)
|
||
|
if ((instTypes & 1) != 0)
|
||
|
{
|
||
|
AddParam_UInt(i + 1);
|
||
|
}
|
||
|
if ((sect.Flags & SF_RO) != 0)
|
||
|
Script += " RO";
|
||
|
AddLF();
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void CInArchive::PrintSectionEnd()
|
||
|
{
|
||
|
AddStringLF("SectionEnd");
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
// static const unsigned kOnFuncShift = 4;
|
||
|
|
||
|
void CInArchive::ClearLangComment()
|
||
|
{
|
||
|
langStrIDs.Clear();
|
||
|
}
|
||
|
|
||
|
void CInArchive::PrintNumComment(const char *name, UInt32 value)
|
||
|
{
|
||
|
// size_t len = Script.Len();
|
||
|
AddCommentAndString(name);
|
||
|
Script += ": ";
|
||
|
Add_UInt(value);
|
||
|
AddLF();
|
||
|
/*
|
||
|
len = Script.Len() - len;
|
||
|
char sz[16];
|
||
|
ConvertUInt32ToString(value, sz);
|
||
|
len += MyStringLen(sz);
|
||
|
for (; len < 20; len++)
|
||
|
Space();
|
||
|
AddStringLF(sz);
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
void CInArchive::NewLine()
|
||
|
{
|
||
|
if (!langStrIDs.IsEmpty())
|
||
|
{
|
||
|
BigSpaceComment();
|
||
|
for (unsigned i = 0; i < langStrIDs.Size() && i < 20; i++)
|
||
|
{
|
||
|
/*
|
||
|
if (i != 0)
|
||
|
Script += ' ';
|
||
|
*/
|
||
|
UInt32 langStr = langStrIDs[i];
|
||
|
if (langStr >= _numLangStrings)
|
||
|
{
|
||
|
AddError("langStr");
|
||
|
break;
|
||
|
}
|
||
|
UInt32 param = Get32(_mainLang + langStr * 4);
|
||
|
if (param != 0)
|
||
|
AddParam(param);
|
||
|
}
|
||
|
ClearLangComment();
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
static const UInt32 kPageSize = 16 * 4;
|
||
|
|
||
|
static const char * const k_SetOverwrite_Modes[] =
|
||
|
{
|
||
|
"on"
|
||
|
, "off"
|
||
|
, "try"
|
||
|
, "ifnewer"
|
||
|
, "ifdiff"
|
||
|
// "lastused"
|
||
|
};
|
||
|
|
||
|
|
||
|
void CInArchive::MessageBox_MB_Part(UInt32 param)
|
||
|
{
|
||
|
{
|
||
|
UInt32 v = param & 0xF;
|
||
|
Script += " MB_";
|
||
|
if (v < ARRAY_SIZE(k_MB_Buttons))
|
||
|
Script += k_MB_Buttons[v];
|
||
|
else
|
||
|
{
|
||
|
Script += "Buttons_";
|
||
|
Add_UInt(v);
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
UInt32 icon = (param >> 4) & 0x7;
|
||
|
if (icon != 0)
|
||
|
{
|
||
|
Script += "|MB_";
|
||
|
if (icon < ARRAY_SIZE(k_MB_Icons) && k_MB_Icons[icon] != 0)
|
||
|
Script += k_MB_Icons[icon];
|
||
|
else
|
||
|
{
|
||
|
Script += "Icon_";
|
||
|
Add_UInt(icon);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ((param & 0x80) != 0)
|
||
|
Script += "|MB_USERICON";
|
||
|
{
|
||
|
UInt32 defButton = (param >> 8) & 0xF;
|
||
|
if (defButton != 0)
|
||
|
{
|
||
|
Script += "|MB_DEFBUTTON";
|
||
|
Add_UInt(defButton + 1);
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
UInt32 modal = (param >> 12) & 0x3;
|
||
|
if (modal == 1) Script += "|MB_SYSTEMMODAL";
|
||
|
else if (modal == 2) Script += "|MB_TASKMODAL";
|
||
|
else if (modal == 3) Script += "|0x3000";
|
||
|
UInt32 flags = (param >> 14);
|
||
|
for (unsigned i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
|
||
|
if ((flags & (1 << i)) != 0)
|
||
|
{
|
||
|
Script += "|MB_";
|
||
|
Script += k_MB_Flags[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define GET_CMD_PARAM(ppp, index) Get32((ppp) + 4 + (index) * 4)
|
||
|
|
||
|
static const Byte k_InitPluginDir_Commands[] =
|
||
|
{ 13, 26, 31, 13, 19, 21, 11, 14, 25, 31, 1, 22, 4, 1 };
|
||
|
|
||
|
bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands)
|
||
|
{
|
||
|
for (UInt32 kkk = 0; kkk < numCommands; kkk++, rawCmds += kCmdSize)
|
||
|
if (GetCmd(Get32(rawCmds)) != sequence[kkk])
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
static const UInt32 kSectionSize_base = 6 * 4;
|
||
|
static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024;
|
||
|
static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2;
|
||
|
static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;
|
||
|
// 8196 is default string length in NSIS-Unicode since 2.37.3
|
||
|
|
||
|
|
||
|
static void AddString(AString &dest, const char *src)
|
||
|
{
|
||
|
dest.Add_Space_if_NotEmpty();
|
||
|
dest += src;
|
||
|
}
|
||
|
|
||
|
AString CInArchive::GetFormatDescription() const
|
||
|
{
|
||
|
AString s = "NSIS-";
|
||
|
char c;
|
||
|
if (IsPark())
|
||
|
{
|
||
|
s += "Park-";
|
||
|
c = '1';
|
||
|
if (NsisType == k_NsisType_Park2) c = '2';
|
||
|
else if (NsisType == k_NsisType_Park3) c = '3';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c = '2';
|
||
|
if (NsisType == k_NsisType_Nsis3)
|
||
|
c = '3';
|
||
|
}
|
||
|
s += c;
|
||
|
if (IsNsis200)
|
||
|
s += ".00";
|
||
|
else if (IsNsis225)
|
||
|
s += ".25";
|
||
|
|
||
|
if (IsUnicode)
|
||
|
AddString(s, "Unicode");
|
||
|
if (LogCmdIsEnabled)
|
||
|
AddString(s, "log");
|
||
|
if (BadCmd >= 0)
|
||
|
{
|
||
|
AddString(s, "BadCmd=");
|
||
|
UIntToString(s, BadCmd);
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
unsigned CInArchive::GetNumSupportedCommands() const
|
||
|
{
|
||
|
unsigned numCmds = IsPark() ? kNumCmds : kNumCmds - kNumAdditionalParkCmds;
|
||
|
if (!LogCmdIsEnabled)
|
||
|
numCmds--;
|
||
|
if (!IsUnicode)
|
||
|
numCmds -= 2;
|
||
|
return numCmds;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
UInt32 CInArchive::GetCmd(UInt32 a)
|
||
|
{
|
||
|
if (!IsPark())
|
||
|
{
|
||
|
if (!LogCmdIsEnabled)
|
||
|
return a;
|
||
|
if (a < EW_SECTIONSET)
|
||
|
return a;
|
||
|
if (a == EW_SECTIONSET)
|
||
|
return EW_LOG;
|
||
|
return a - 1;
|
||
|
}
|
||
|
|
||
|
if (a < EW_REGISTERDLL)
|
||
|
return a;
|
||
|
if (NsisType >= k_NsisType_Park2)
|
||
|
{
|
||
|
if (a == EW_REGISTERDLL) return EW_GETFONTVERSION;
|
||
|
a--;
|
||
|
}
|
||
|
if (NsisType >= k_NsisType_Park3)
|
||
|
{
|
||
|
if (a == EW_REGISTERDLL) return EW_GETFONTNAME;
|
||
|
a--;
|
||
|
}
|
||
|
if (a >= EW_FSEEK)
|
||
|
{
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (a == EW_FSEEK) return EW_FPUTWS;
|
||
|
if (a == EW_FSEEK + 1) return EW_FPUTWS + 1;
|
||
|
a -= 2;
|
||
|
}
|
||
|
|
||
|
if (a >= EW_SECTIONSET && LogCmdIsEnabled)
|
||
|
{
|
||
|
if (a == EW_SECTIONSET)
|
||
|
return EW_LOG;
|
||
|
return a - 1;
|
||
|
}
|
||
|
if (a == EW_FPUTWS)
|
||
|
return EW_FINDPROC;
|
||
|
// if (a > EW_FPUTWS) return 0;
|
||
|
}
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
void CInArchive::FindBadCmd(const CBlockHeader &bh, const Byte *p)
|
||
|
{
|
||
|
BadCmd = -1;
|
||
|
|
||
|
for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)
|
||
|
{
|
||
|
UInt32 id = GetCmd(Get32(p));
|
||
|
if (id >= kNumCmds)
|
||
|
continue;
|
||
|
if (BadCmd >= 0 && id >= (unsigned)BadCmd)
|
||
|
continue;
|
||
|
unsigned i;
|
||
|
if (id == EW_GETLABELADDR ||
|
||
|
id == EW_GETFUNCTIONADDR)
|
||
|
{
|
||
|
BadCmd = id;
|
||
|
continue;
|
||
|
}
|
||
|
for (i = 6; i != 0; i--)
|
||
|
{
|
||
|
UInt32 param = Get32(p + i * 4);
|
||
|
if (param != 0)
|
||
|
break;
|
||
|
}
|
||
|
if (id == EW_FINDPROC && i == 0)
|
||
|
{
|
||
|
BadCmd = id;
|
||
|
continue;
|
||
|
}
|
||
|
if (k_Commands[id].NumParams < i)
|
||
|
BadCmd = id;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* We calculate the number of parameters in commands to detect
|
||
|
layout of commands. It's not very good way.
|
||
|
If you know simpler and more robust way to detect Version and layout,
|
||
|
please write to 7-Zip forum */
|
||
|
|
||
|
void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
|
||
|
{
|
||
|
bool strongPark = false;
|
||
|
bool strongNsis = false;
|
||
|
|
||
|
{
|
||
|
const Byte *strData = _data + _stringsPos;
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
UInt32 num = NumStringChars;
|
||
|
for (UInt32 i = 0; i < num; i++)
|
||
|
{
|
||
|
if (Get16(strData + i * 2) == 0)
|
||
|
{
|
||
|
unsigned c2 = Get16(strData + 2 + i * 2);
|
||
|
// if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL)
|
||
|
if (c2 == NS_3_CODE_VAR)
|
||
|
{
|
||
|
// it can be TXT/RTF string with marker char (1 or 2). so we must next char
|
||
|
// const wchar_t *p2 = (const wchar_t *)(strData + i * 2 + 2);
|
||
|
// p2 = p2;
|
||
|
if ((Get16(strData + 3 + i * 2) & 0x8000) != 0)
|
||
|
{
|
||
|
NsisType = k_NsisType_Nsis3;
|
||
|
strongNsis = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (!strongNsis)
|
||
|
{
|
||
|
NsisType = k_NsisType_Park1;
|
||
|
strongPark = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UInt32 num = NumStringChars;
|
||
|
for (UInt32 i = 0; i < num; i++)
|
||
|
{
|
||
|
if (strData[i] == 0)
|
||
|
{
|
||
|
Byte c2 = strData[i + 1];
|
||
|
// it can be TXT/RTF with marker char (1 or 2). so we must check next char
|
||
|
// for marker=1 (txt)
|
||
|
if (c2 == NS_3_CODE_VAR)
|
||
|
// if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL && c2 != 1)
|
||
|
{
|
||
|
if ((strData[i+ 2] & 0x80) != 0)
|
||
|
{
|
||
|
// const char *p2 = (const char *)(strData + i + 1);
|
||
|
// p2 = p2;
|
||
|
NsisType = k_NsisType_Nsis3;
|
||
|
strongNsis = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NsisType == k_NsisType_Nsis2 && !IsUnicode)
|
||
|
{
|
||
|
const Byte *p2 = p;
|
||
|
|
||
|
for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize)
|
||
|
{
|
||
|
UInt32 cmd = GetCmd(Get32(p2));
|
||
|
if (cmd != EW_GETDLGITEM &&
|
||
|
cmd != EW_ASSIGNVAR)
|
||
|
continue;
|
||
|
|
||
|
UInt32 params[kNumCommandParams];
|
||
|
for (unsigned i = 0; i < kNumCommandParams; i++)
|
||
|
params[i] = Get32(p2 + 4 + 4 * i);
|
||
|
|
||
|
if (cmd == EW_GETDLGITEM)
|
||
|
{
|
||
|
// we can use also EW_SETCTLCOLORS
|
||
|
if (IsVarStr(params[1], kVar_HWNDPARENT_225))
|
||
|
{
|
||
|
IsNsis225 = true;
|
||
|
if (params[0] == kVar_Spec_OUTDIR_225)
|
||
|
{
|
||
|
IsNsis200 = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else // if (cmd == EW_ASSIGNVAR)
|
||
|
{
|
||
|
if (params[0] == kVar_Spec_OUTDIR_225 &&
|
||
|
params[2] == 0 &&
|
||
|
params[3] == 0 &&
|
||
|
IsVarStr(params[1], kVar_OUTDIR))
|
||
|
IsNsis225 = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool parkVer_WasDetected = false;
|
||
|
|
||
|
if (!strongNsis && !IsNsis225 && !IsNsis200)
|
||
|
{
|
||
|
// it must be before FindBadCmd(bh, p);
|
||
|
unsigned mask = 0;
|
||
|
|
||
|
unsigned numInsertMax = IsUnicode ? 4 : 2;
|
||
|
|
||
|
const Byte *p2 = p;
|
||
|
|
||
|
for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize)
|
||
|
{
|
||
|
UInt32 cmd = Get32(p2); // we use original (not converted) command
|
||
|
|
||
|
if (cmd < EW_WRITEUNINSTALLER ||
|
||
|
cmd > EW_WRITEUNINSTALLER + numInsertMax)
|
||
|
continue;
|
||
|
|
||
|
UInt32 params[kNumCommandParams];
|
||
|
for (unsigned i = 0; i < kNumCommandParams; i++)
|
||
|
params[i] = Get32(p2 + 4 + 4 * i);
|
||
|
|
||
|
if (params[4] != 0 ||
|
||
|
params[5] != 0 ||
|
||
|
params[0] <= 1 ||
|
||
|
params[3] <= 1)
|
||
|
continue;
|
||
|
|
||
|
UInt32 altParam = params[3];
|
||
|
if (!IsGoodString(params[0]) ||
|
||
|
!IsGoodString(altParam))
|
||
|
continue;
|
||
|
|
||
|
UInt32 additional = 0;
|
||
|
if (GetVarIndexFinished(altParam, '\\', additional) != kVar_INSTDIR)
|
||
|
continue;
|
||
|
if (AreTwoParamStringsEqual(altParam + additional, params[0]))
|
||
|
{
|
||
|
unsigned numInserts = cmd - EW_WRITEUNINSTALLER;
|
||
|
mask |= (1 << numInserts);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mask == 1)
|
||
|
{
|
||
|
parkVer_WasDetected = true; // it can be original NSIS or Park-1
|
||
|
}
|
||
|
else if (mask != 0)
|
||
|
{
|
||
|
ENsisType newType = NsisType;
|
||
|
if (IsUnicode)
|
||
|
switch (mask)
|
||
|
{
|
||
|
case (1 << 3): newType = k_NsisType_Park2; break;
|
||
|
case (1 << 4): newType = k_NsisType_Park3; break;
|
||
|
}
|
||
|
else
|
||
|
switch (mask)
|
||
|
{
|
||
|
case (1 << 1): newType = k_NsisType_Park2; break;
|
||
|
case (1 << 2): newType = k_NsisType_Park3; break;
|
||
|
}
|
||
|
if (newType != NsisType)
|
||
|
{
|
||
|
parkVer_WasDetected = true;
|
||
|
NsisType = newType;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FindBadCmd(bh, p);
|
||
|
|
||
|
/*
|
||
|
if (strongNsis)
|
||
|
return;
|
||
|
*/
|
||
|
|
||
|
if (BadCmd < EW_REGISTERDLL)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
// in ANSI archive we don't check Park and log version
|
||
|
if (!IsUnicode)
|
||
|
return;
|
||
|
*/
|
||
|
|
||
|
// We can support Park-ANSI archives, if we remove if (strongPark) check
|
||
|
if (strongPark && !parkVer_WasDetected)
|
||
|
{
|
||
|
if (BadCmd < EW_SECTIONSET)
|
||
|
{
|
||
|
NsisType = k_NsisType_Park3;
|
||
|
LogCmdIsEnabled = true; // version 3 is provided with log enabled
|
||
|
FindBadCmd(bh, p);
|
||
|
if (BadCmd > 0 && BadCmd < EW_SECTIONSET)
|
||
|
{
|
||
|
NsisType = k_NsisType_Park2;
|
||
|
LogCmdIsEnabled = false;
|
||
|
FindBadCmd(bh, p);
|
||
|
if (BadCmd > 0 && BadCmd < EW_SECTIONSET)
|
||
|
{
|
||
|
NsisType = k_NsisType_Park1;
|
||
|
FindBadCmd(bh, p);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (BadCmd >= EW_SECTIONSET)
|
||
|
{
|
||
|
LogCmdIsEnabled = !LogCmdIsEnabled;
|
||
|
FindBadCmd(bh, p);
|
||
|
if (BadCmd >= EW_SECTIONSET && LogCmdIsEnabled)
|
||
|
{
|
||
|
LogCmdIsEnabled = false;
|
||
|
FindBadCmd(bh, p);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Int32 CInArchive::GetVarIndex(UInt32 strPos) const
|
||
|
{
|
||
|
if (strPos >= NumStringChars)
|
||
|
return -1;
|
||
|
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (NumStringChars - strPos < 3 * 2)
|
||
|
return -1;
|
||
|
const Byte *p = _data + _stringsPos + strPos * 2;
|
||
|
unsigned code = Get16(p);
|
||
|
if (IsPark())
|
||
|
{
|
||
|
if (code != PARK_CODE_VAR)
|
||
|
return -1;
|
||
|
UInt32 n = Get16(p + 2);
|
||
|
if (n == 0)
|
||
|
return -1;
|
||
|
CONVERT_NUMBER_PARK(n);
|
||
|
return (Int32)n;
|
||
|
}
|
||
|
|
||
|
// NSIS-3
|
||
|
{
|
||
|
if (code != NS_3_CODE_VAR)
|
||
|
return -1;
|
||
|
UInt32 n = Get16(p + 2);
|
||
|
if (n == 0)
|
||
|
return -1;
|
||
|
CONVERT_NUMBER_NS_3_UNICODE(n);
|
||
|
return (Int32)n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NumStringChars - strPos < 4)
|
||
|
return -1;
|
||
|
|
||
|
const Byte *p = _data + _stringsPos + strPos;
|
||
|
unsigned c = *p;
|
||
|
if (NsisType == k_NsisType_Nsis3)
|
||
|
{
|
||
|
if (c != NS_3_CODE_VAR)
|
||
|
return -1;
|
||
|
}
|
||
|
else if (c != NS_CODE_VAR)
|
||
|
return -1;
|
||
|
|
||
|
unsigned c0 = p[1];
|
||
|
if (c0 == 0)
|
||
|
return -1;
|
||
|
unsigned c1 = p[2];
|
||
|
if (c1 == 0)
|
||
|
return -1;
|
||
|
return DECODE_NUMBER_FROM_2_CHARS(c0, c1);
|
||
|
}
|
||
|
|
||
|
Int32 CInArchive::GetVarIndex(UInt32 strPos, UInt32 &resOffset) const
|
||
|
{
|
||
|
resOffset = 0;
|
||
|
Int32 varIndex = GetVarIndex(strPos);
|
||
|
if (varIndex < 0)
|
||
|
return varIndex;
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (NumStringChars - strPos < 2 * 2)
|
||
|
return -1;
|
||
|
resOffset = 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (NumStringChars - strPos < 3)
|
||
|
return -1;
|
||
|
resOffset = 3;
|
||
|
}
|
||
|
return varIndex;
|
||
|
}
|
||
|
|
||
|
Int32 CInArchive::GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const
|
||
|
{
|
||
|
resOffset = 0;
|
||
|
Int32 varIndex = GetVarIndex(strPos);
|
||
|
if (varIndex < 0)
|
||
|
return varIndex;
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (NumStringChars - strPos < 3 * 2)
|
||
|
return -1;
|
||
|
const Byte *p = _data + _stringsPos + strPos * 2;
|
||
|
if (Get16(p + 4) != endChar)
|
||
|
return -1;
|
||
|
resOffset = 3;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (NumStringChars - strPos < 4)
|
||
|
return -1;
|
||
|
const Byte *p = _data + _stringsPos + strPos;
|
||
|
if (p[3] != endChar)
|
||
|
return -1;
|
||
|
resOffset = 4;
|
||
|
}
|
||
|
return varIndex;
|
||
|
}
|
||
|
|
||
|
bool CInArchive::IsVarStr(UInt32 strPos, UInt32 varIndex) const
|
||
|
{
|
||
|
if (varIndex > (UInt32)0x7FFF)
|
||
|
return false;
|
||
|
UInt32 resOffset;
|
||
|
return GetVarIndexFinished(strPos, 0, resOffset) == (Int32)varIndex;
|
||
|
}
|
||
|
|
||
|
bool CInArchive::IsAbsolutePathVar(UInt32 strPos) const
|
||
|
{
|
||
|
Int32 varIndex = GetVarIndex(strPos);
|
||
|
if (varIndex < 0)
|
||
|
return false;
|
||
|
switch (varIndex)
|
||
|
{
|
||
|
case kVar_INSTDIR:
|
||
|
case kVar_EXEDIR:
|
||
|
case kVar_TEMP:
|
||
|
case kVar_PLUGINSDIR:
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
|
||
|
|
||
|
// We use same check as in NSIS decoder
|
||
|
bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; }
|
||
|
bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; }
|
||
|
|
||
|
static bool IsAbsolutePath(const wchar_t *s)
|
||
|
{
|
||
|
return
|
||
|
s[0] == WCHAR_PATH_SEPARATOR &&
|
||
|
s[1] == WCHAR_PATH_SEPARATOR ||
|
||
|
IsDrivePath(s);
|
||
|
}
|
||
|
|
||
|
static bool IsAbsolutePath(const char *s)
|
||
|
{
|
||
|
return
|
||
|
s[0] == CHAR_PATH_SEPARATOR &&
|
||
|
s[1] == CHAR_PATH_SEPARATOR ||
|
||
|
IsDrivePath(s);
|
||
|
}
|
||
|
|
||
|
void CInArchive::SetItemName(CItem &item, UInt32 strPos)
|
||
|
{
|
||
|
ReadString2_Raw(strPos);
|
||
|
bool isAbs = IsAbsolutePathVar(strPos);
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
item.NameU = Raw_UString;
|
||
|
if (!isAbs && !IsAbsolutePath(Raw_UString))
|
||
|
item.Prefix = UPrefixes.Size() - 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
item.NameA = Raw_AString;
|
||
|
if (!isAbs && !IsAbsolutePath(Raw_AString))
|
||
|
item.Prefix = APrefixes.Size() - 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||
|
{
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
CDynLimBuf &s = Script;
|
||
|
|
||
|
CObjArray<UInt32> labels;
|
||
|
labels.Alloc(bh.Num);
|
||
|
memset(labels, 0, bh.Num * sizeof(UInt32));
|
||
|
|
||
|
{
|
||
|
const Byte *p = _data;
|
||
|
UInt32 i;
|
||
|
for (i = 0; i < numOnFunc; i++)
|
||
|
{
|
||
|
UInt32 func = Get32(p + onFuncOffset + 4 * i);
|
||
|
if (func < bh.Num)
|
||
|
labels[func] = (labels[func] & ~CMD_REF_OnFunc_Mask) | (CMD_REF_OnFunc | (i << CMD_REF_OnFunc_NumShifts));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
{
|
||
|
for (int i = 0; i < OnFuncs.Size(); i++)
|
||
|
{
|
||
|
UInt32 address = OnFuncs[i] >> kOnFuncShift;
|
||
|
if (address < bh.Num)
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
if (bhPages.Num != 0)
|
||
|
{
|
||
|
Separator();
|
||
|
PrintNumComment("PAGES", bhPages.Num);
|
||
|
|
||
|
if (bhPages.Num > (1 << 12)
|
||
|
|| bhPages.Offset > _size
|
||
|
|| bhPages.Num * kPageSize > _size - bhPages.Offset)
|
||
|
{
|
||
|
AddErrorLF("Pages error");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
AddLF();
|
||
|
const Byte *p = _data + bhPages.Offset;
|
||
|
|
||
|
for (UInt32 pageIndex = 0; pageIndex < bhPages.Num; pageIndex++, p += kPageSize)
|
||
|
{
|
||
|
UInt32 dlgID = Get32(p);
|
||
|
UInt32 wndProcID = Get32(p + 4);
|
||
|
UInt32 preFunc = Get32(p + 8);
|
||
|
UInt32 showFunc = Get32(p + 12);
|
||
|
UInt32 leaveFunc = Get32(p + 16);
|
||
|
UInt32 flags = Get32(p + 20);
|
||
|
UInt32 caption = Get32(p + 24);
|
||
|
// UInt32 back = Get32(p + 28);
|
||
|
UInt32 next = Get32(p + 32);
|
||
|
// UInt32 clickNext = Get32(p + 36);
|
||
|
// UInt32 cancel = Get32(p + 40);
|
||
|
UInt32 params[5];
|
||
|
for (int i = 0; i < 5; i++)
|
||
|
params[i] = Get32(p + 44 + 4 * i);
|
||
|
|
||
|
SET_FUNC_REF(preFunc, CMD_REF_Pre);
|
||
|
SET_FUNC_REF(showFunc, CMD_REF_Show);
|
||
|
SET_FUNC_REF(leaveFunc, CMD_REF_Leave);
|
||
|
|
||
|
if (wndProcID == PWP_COMPLETED)
|
||
|
CommentOpen();
|
||
|
|
||
|
AddCommentAndString("Page ");
|
||
|
Add_UInt(pageIndex);
|
||
|
AddLF();
|
||
|
|
||
|
if (flags & PF_PAGE_EX)
|
||
|
{
|
||
|
s += "PageEx ";
|
||
|
if (!IsInstaller)
|
||
|
s += "un.";
|
||
|
}
|
||
|
else
|
||
|
s += IsInstaller ? "Page " : "UninstPage ";
|
||
|
|
||
|
if (wndProcID < ARRAY_SIZE(kPageTypes))
|
||
|
s += kPageTypes[wndProcID];
|
||
|
else
|
||
|
Add_UInt(wndProcID);
|
||
|
|
||
|
|
||
|
bool needCallbacks = (
|
||
|
(Int32)preFunc >= 0 ||
|
||
|
(Int32)showFunc >= 0 ||
|
||
|
(Int32)leaveFunc >= 0);
|
||
|
|
||
|
if (flags & PF_PAGE_EX)
|
||
|
{
|
||
|
AddLF();
|
||
|
if (needCallbacks)
|
||
|
TabString("PageCallbacks");
|
||
|
}
|
||
|
|
||
|
if (needCallbacks)
|
||
|
{
|
||
|
AddParam_Func(labels, preFunc); // it's creator_function for PWP_CUSTOM
|
||
|
if (wndProcID != PWP_CUSTOM)
|
||
|
{
|
||
|
AddParam_Func(labels, showFunc);
|
||
|
}
|
||
|
AddParam_Func(labels, leaveFunc);
|
||
|
}
|
||
|
|
||
|
if ((flags & PF_PAGE_EX) == 0)
|
||
|
{
|
||
|
// AddOptionalParam(caption);
|
||
|
if (flags & PF_CANCEL_ENABLE)
|
||
|
s += " /ENABLECANCEL";
|
||
|
AddLF();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AddLF();
|
||
|
AddPageOption1(caption, "Caption");
|
||
|
}
|
||
|
|
||
|
if (wndProcID == PWP_LICENSE)
|
||
|
{
|
||
|
if ((flags & PF_LICENSE_NO_FORCE_SELECTION) != 0 ||
|
||
|
(flags & PF_LICENSE_FORCE_SELECTION) != 0)
|
||
|
{
|
||
|
TabString("LicenseForceSelection ");
|
||
|
if (flags & PF_LICENSE_NO_FORCE_SELECTION)
|
||
|
s += "off";
|
||
|
else
|
||
|
{
|
||
|
if (dlgID == IDD_LICENSE_FSCB)
|
||
|
s += "checkbox";
|
||
|
else if (dlgID == IDD_LICENSE_FSRB)
|
||
|
s += "radiobuttons";
|
||
|
else
|
||
|
Add_UInt(dlgID);
|
||
|
AddOptionalParams(params + 2, 2);
|
||
|
}
|
||
|
NewLine();
|
||
|
}
|
||
|
|
||
|
if (params[0] != 0 || next != 0)
|
||
|
{
|
||
|
TabString("LicenseText");
|
||
|
AddParam(params[0]);
|
||
|
AddOptionalParam(next);
|
||
|
NewLine();
|
||
|
}
|
||
|
if (params[1] != 0)
|
||
|
{
|
||
|
TabString("LicenseData");
|
||
|
if ((Int32)params[1] < 0)
|
||
|
AddParam(params[1]);
|
||
|
else
|
||
|
AddLicense(params[1], -1);
|
||
|
ClearLangComment();
|
||
|
NewLine();
|
||
|
}
|
||
|
}
|
||
|
else if (wndProcID == PWP_SELCOM)
|
||
|
AddPageOption(params, 3, "ComponentsText");
|
||
|
else if (wndProcID == PWP_DIR)
|
||
|
{
|
||
|
AddPageOption(params, 4, "DirText");
|
||
|
if (params[4] != 0)
|
||
|
{
|
||
|
TabString("DirVar");
|
||
|
AddParam_Var(params[4] - 1);
|
||
|
AddLF();
|
||
|
}
|
||
|
if (flags & PF_DIR_NO_BTN_DISABLE)
|
||
|
{
|
||
|
TabString("DirVerify leave");
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if (wndProcID == PWP_INSTFILES)
|
||
|
{
|
||
|
AddPageOption1(params[2], "CompletedText");
|
||
|
AddPageOption1(params[1], "DetailsButtonText");
|
||
|
}
|
||
|
else if (wndProcID == PWP_UNINST)
|
||
|
{
|
||
|
if (params[4] != 0)
|
||
|
{
|
||
|
TabString("DirVar");
|
||
|
AddParam_Var(params[4] - 1);
|
||
|
AddLF();
|
||
|
}
|
||
|
AddPageOption(params, 2, "UninstallText");
|
||
|
}
|
||
|
|
||
|
if (flags & PF_PAGE_EX)
|
||
|
{
|
||
|
s += "PageExEnd";
|
||
|
NewLine();
|
||
|
}
|
||
|
if (wndProcID == PWP_COMPLETED)
|
||
|
CommentClose();
|
||
|
NewLine();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CObjArray<CSection> Sections;
|
||
|
|
||
|
{
|
||
|
Separator();
|
||
|
PrintNumComment("SECTIONS", bhSections.Num);
|
||
|
PrintNumComment("COMMANDS", bh.Num);
|
||
|
AddLF();
|
||
|
|
||
|
if (bhSections.Num > (1 << 15)
|
||
|
// || bhSections.Offset > _size
|
||
|
// || (bhSections.Num * SectionSize > _size - bhSections.Offset)
|
||
|
)
|
||
|
{
|
||
|
AddErrorLF("Sections error");
|
||
|
}
|
||
|
else if (bhSections.Num != 0)
|
||
|
{
|
||
|
Sections.Alloc((unsigned)bhSections.Num);
|
||
|
const Byte *p = _data + bhSections.Offset;
|
||
|
for (UInt32 i = 0; i < bhSections.Num; i++, p += SectionSize)
|
||
|
{
|
||
|
CSection §ion = Sections[i];
|
||
|
section.Parse(p);
|
||
|
if (section.StartCmdIndex < bh.Num)
|
||
|
labels[section.StartCmdIndex] |= CMD_REF_Section;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
const Byte *p;
|
||
|
UInt32 kkk;
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
p = _data + bh.Offset;
|
||
|
|
||
|
for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)
|
||
|
{
|
||
|
UInt32 commandId = GetCmd(Get32(p));
|
||
|
UInt32 mask;
|
||
|
switch (commandId)
|
||
|
{
|
||
|
case EW_NOP: mask = 1 << 0; break;
|
||
|
case EW_IFFILEEXISTS: mask = 3 << 1; break;
|
||
|
case EW_IFFLAG: mask = 3 << 0; break;
|
||
|
case EW_MESSAGEBOX: mask = 5 << 3; break;
|
||
|
case EW_STRCMP: mask = 3 << 2; break;
|
||
|
case EW_INTCMP: mask = 7 << 2; break;
|
||
|
case EW_ISWINDOW: mask = 3 << 1; break;
|
||
|
case EW_CALL:
|
||
|
{
|
||
|
if (Get32(p + 4 + 4) == 1) // it's Call :Label
|
||
|
{
|
||
|
mask = 1 << 0;
|
||
|
break;
|
||
|
}
|
||
|
UInt32 param0 = Get32(p + 4);
|
||
|
if ((Int32)param0 > 0)
|
||
|
labels[param0 - 1] |= CMD_REF_Call;
|
||
|
continue;
|
||
|
}
|
||
|
default: continue;
|
||
|
}
|
||
|
for (unsigned i = 0; mask != 0; i++, mask >>= 1)
|
||
|
if (mask & 1)
|
||
|
{
|
||
|
UInt32 param = Get32(p + 4 + 4 * i);
|
||
|
if ((Int32)param > 0 && (Int32)param <= (Int32)bh.Num)
|
||
|
labels[param - 1] |= CMD_REF_Goto;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int InitPluginsDir_Start = -1;
|
||
|
int InitPluginsDir_End = -1;
|
||
|
p = _data + bh.Offset;
|
||
|
for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)
|
||
|
{
|
||
|
UInt32 flg = labels[kkk];
|
||
|
/*
|
||
|
if (IsFunc(flg))
|
||
|
{
|
||
|
AddLF();
|
||
|
for (int i = 0; i < 14; i++)
|
||
|
{
|
||
|
UInt32 commandId = GetCmd(Get32(p + kCmdSize * i));
|
||
|
s += ", ";
|
||
|
UIntToString(s, commandId);
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
*/
|
||
|
if (IsFunc(flg)
|
||
|
&& bh.Num - kkk >= ARRAY_SIZE(k_InitPluginDir_Commands)
|
||
|
&& CompareCommands(p, k_InitPluginDir_Commands, ARRAY_SIZE(k_InitPluginDir_Commands)))
|
||
|
{
|
||
|
InitPluginsDir_Start = kkk;
|
||
|
InitPluginsDir_End = kkk + ARRAY_SIZE(k_InitPluginDir_Commands);
|
||
|
labels[kkk] |= CMD_REF_InitPluginDir;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// AString prefixA_Temp;
|
||
|
// UString prefixU_Temp;
|
||
|
|
||
|
|
||
|
// const UInt32 kFindS = 158;
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
UInt32 curSectionIndex = 0;
|
||
|
// UInt32 lastSectionEndCmd = 0xFFFFFFFF;
|
||
|
bool sectionIsOpen = false;
|
||
|
// int curOnFunc = 0;
|
||
|
bool onFuncIsOpen = false;
|
||
|
|
||
|
/*
|
||
|
for (unsigned yyy = 0; yyy + 3 < _data.Size(); yyy++)
|
||
|
{
|
||
|
UInt32 val = Get32(_data + yyy);
|
||
|
if (val == kFindS)
|
||
|
val = val;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
UInt32 overwrite_State = 0; // "SetOverwrite on"
|
||
|
Int32 allowSkipFiles_State = -1; // -1: on, -2: off, >=0 : RAW value
|
||
|
UInt32 endCommentIndex = 0;
|
||
|
|
||
|
unsigned numSupportedCommands = GetNumSupportedCommands();
|
||
|
|
||
|
#endif
|
||
|
|
||
|
p = _data + bh.Offset;
|
||
|
|
||
|
UString spec_outdir_U;
|
||
|
AString spec_outdir_A;
|
||
|
|
||
|
UPrefixes.Add(L"$INSTDIR");
|
||
|
APrefixes.Add("$INSTDIR");
|
||
|
|
||
|
p = _data + bh.Offset;
|
||
|
|
||
|
unsigned spec_outdir_VarIndex = IsNsis225 ?
|
||
|
kVar_Spec_OUTDIR_225 :
|
||
|
kVar_Spec_OUTDIR;
|
||
|
|
||
|
for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)
|
||
|
{
|
||
|
UInt32 commandId;
|
||
|
UInt32 params[kNumCommandParams];
|
||
|
commandId = GetCmd(Get32(p));
|
||
|
{
|
||
|
for (unsigned i = 0; i < kNumCommandParams; i++)
|
||
|
{
|
||
|
params[i] = Get32(p + 4 + 4 * i);
|
||
|
/*
|
||
|
if (params[i] == kFindS)
|
||
|
i = i;
|
||
|
*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
bool IsSectionGroup = false;
|
||
|
while (curSectionIndex < bhSections.Num)
|
||
|
{
|
||
|
const CSection § = Sections[curSectionIndex];
|
||
|
if (sectionIsOpen)
|
||
|
{
|
||
|
if (sect.StartCmdIndex + sect.NumCommands + 1 != kkk)
|
||
|
break;
|
||
|
PrintSectionEnd();
|
||
|
sectionIsOpen = false;
|
||
|
// lastSectionEndCmd = kkk;
|
||
|
curSectionIndex++;
|
||
|
continue;
|
||
|
}
|
||
|
if (sect.StartCmdIndex != kkk)
|
||
|
break;
|
||
|
if (PrintSectionBegin(sect, curSectionIndex))
|
||
|
{
|
||
|
IsSectionGroup = true;
|
||
|
curSectionIndex++;
|
||
|
// do we need to flush prefixes in new section?
|
||
|
// FlushOutPathPrefixes();
|
||
|
}
|
||
|
else
|
||
|
sectionIsOpen = true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if (curOnFunc < OnFuncs.Size())
|
||
|
{
|
||
|
if ((OnFuncs[curOnFunc] >> kOnFuncShift) == kkk)
|
||
|
{
|
||
|
s += "Function .on";
|
||
|
s += kOnFunc[OnFuncs[curOnFunc++] & ((1 << kOnFuncShift) - 1)];
|
||
|
AddLF();
|
||
|
onFuncIsOpen = true;
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
if (labels[kkk] != 0 && labels[kkk] != CMD_REF_Section)
|
||
|
{
|
||
|
UInt32 flg = labels[kkk];
|
||
|
if (IsFunc(flg))
|
||
|
{
|
||
|
if ((int)kkk == InitPluginsDir_Start)
|
||
|
CommentOpen();
|
||
|
|
||
|
onFuncIsOpen = true;
|
||
|
s += "Function ";
|
||
|
Add_FuncName(labels, kkk);
|
||
|
if (IsPageFunc(flg))
|
||
|
{
|
||
|
BigSpaceComment();
|
||
|
s += "Page ";
|
||
|
Add_UInt((flg & CMD_REF_Page_Mask) >> CMD_REF_Page_NumShifts);
|
||
|
// if (flg & CMD_REF_Creator) s += ", Creator";
|
||
|
if (flg & CMD_REF_Leave) s += ", Leave";
|
||
|
if (flg & CMD_REF_Pre) s += ", Pre";
|
||
|
if (flg & CMD_REF_Show) s += ", Show";
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
if (flg & CMD_REF_Goto)
|
||
|
{
|
||
|
Add_LabelName(kkk);
|
||
|
s += ':';
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (commandId != EW_RET)
|
||
|
{
|
||
|
Tab(kkk < endCommentIndex);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
UInt32 originalCmd = Get32(p);
|
||
|
if (originalCmd >= EW_REGISTERDLL)
|
||
|
{
|
||
|
UIntToString(s, originalCmd);
|
||
|
s += ' ';
|
||
|
if (originalCmd != commandId)
|
||
|
{
|
||
|
UIntToString(s, commandId);
|
||
|
s += ' ';
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
unsigned numSkipParams = 0;
|
||
|
|
||
|
if (commandId < ARRAY_SIZE(k_Commands) && commandId < numSupportedCommands)
|
||
|
{
|
||
|
numSkipParams = k_Commands[commandId].NumParams;
|
||
|
const char *sz = k_CommandNames[commandId];
|
||
|
if (sz)
|
||
|
s += sz;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += "Command";
|
||
|
Add_UInt(commandId);
|
||
|
/* We don't show wrong commands that use overlapped ids.
|
||
|
So we change commandId to big value */
|
||
|
if (commandId < (1 << 12))
|
||
|
commandId += (1 << 12);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
switch (commandId)
|
||
|
{
|
||
|
case EW_CREATEDIR:
|
||
|
{
|
||
|
bool isSetOutPath = (params[1] != 0);
|
||
|
|
||
|
if (isSetOutPath)
|
||
|
{
|
||
|
UInt32 par0 = params[0];
|
||
|
|
||
|
UInt32 resOffset;
|
||
|
Int32 idx = GetVarIndex(par0, resOffset);
|
||
|
if (idx == (Int32)spec_outdir_VarIndex ||
|
||
|
idx == kVar_OUTDIR)
|
||
|
par0 += resOffset;
|
||
|
|
||
|
ReadString2_Raw(par0);
|
||
|
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (idx == (Int32)spec_outdir_VarIndex)
|
||
|
Raw_UString.Insert(0, spec_outdir_U);
|
||
|
else if (idx == kVar_OUTDIR)
|
||
|
Raw_UString.Insert(0, UPrefixes.Back());
|
||
|
UPrefixes.Add(Raw_UString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (idx == (Int32)spec_outdir_VarIndex)
|
||
|
Raw_AString.Insert(0, spec_outdir_A);
|
||
|
else if (idx == kVar_OUTDIR)
|
||
|
Raw_AString.Insert(0, APrefixes.Back());
|
||
|
APrefixes.Add(Raw_AString);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
s += isSetOutPath ? "SetOutPath" : "CreateDirectory";
|
||
|
AddParam(params[0]);
|
||
|
#endif
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
case EW_ASSIGNVAR:
|
||
|
{
|
||
|
if (params[0] == spec_outdir_VarIndex)
|
||
|
{
|
||
|
spec_outdir_U.Empty();
|
||
|
spec_outdir_A.Empty();
|
||
|
if (IsVarStr(params[1], kVar_OUTDIR) &&
|
||
|
params[2] == 0 &&
|
||
|
params[3] == 0)
|
||
|
{
|
||
|
if (IsVarStr(params[1], kVar_OUTDIR))
|
||
|
{
|
||
|
spec_outdir_U = UPrefixes.Back(); // outdir_U;
|
||
|
spec_outdir_A = APrefixes.Back();// outdir_A;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
if (params[2] == 0 &&
|
||
|
params[3] == 0 &&
|
||
|
params[4] == 0 &&
|
||
|
params[5] == 0 &&
|
||
|
params[1] != 0 &&
|
||
|
params[1] < NumStringChars)
|
||
|
{
|
||
|
char sz[16];
|
||
|
ConvertUInt32ToString(kkk + 1, sz);
|
||
|
if (IsDirectString_Equal(params[1], sz))
|
||
|
{
|
||
|
// we suppose that it's GetCurrentAddress command
|
||
|
// but there is probability that it's StrCpy command
|
||
|
s += "GetCurrentAddress";
|
||
|
AddParam_Var(params[0]);
|
||
|
SmallSpaceComment();
|
||
|
}
|
||
|
}
|
||
|
s += "StrCpy";
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
|
||
|
AddOptionalParams(params + 2, 2);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_EXTRACTFILE:
|
||
|
{
|
||
|
CItem &item = Items.AddNew();
|
||
|
|
||
|
UInt32 par1 = params[1];
|
||
|
|
||
|
SetItemName(item, par1);
|
||
|
|
||
|
item.Pos = params[2];
|
||
|
item.MTime.dwLowDateTime = params[3];
|
||
|
item.MTime.dwHighDateTime = params[4];
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
{
|
||
|
UInt32 overwrite = params[0] & 0x7;
|
||
|
if (overwrite != overwrite_State)
|
||
|
{
|
||
|
s += "SetOverwrite ";
|
||
|
ADD_TYPE_FROM_LIST(k_SetOverwrite_Modes, overwrite);
|
||
|
overwrite_State = overwrite;
|
||
|
AddLF();
|
||
|
Tab(kkk < endCommentIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UInt32 nsisMB = params[0] >> 3;
|
||
|
if ((Int32)nsisMB != allowSkipFiles_State)
|
||
|
{
|
||
|
UInt32 mb = nsisMB & ((1 << 20) - 1); // old/new NSIS
|
||
|
UInt32 b1 = nsisMB >> 21; // NSIS 2.06+
|
||
|
UInt32 b2 = nsisMB >> 20; // NSIS old
|
||
|
Int32 asf = (Int32)nsisMB;
|
||
|
if (mb == (MY__MB_ABORTRETRYIGNORE | MY__MB_ICONSTOP) && (b1 == MY__IDIGNORE || b2 == MY__IDIGNORE))
|
||
|
asf = -1;
|
||
|
else if (mb == (MY__MB_RETRYCANCEL | MY__MB_ICONSTOP) && (b1 == MY__IDCANCEL || b2 == MY__IDCANCEL))
|
||
|
asf = -2;
|
||
|
else
|
||
|
{
|
||
|
AddCommentAndString("AllowSkipFiles [Overwrite]: ");
|
||
|
MessageBox_MB_Part(mb);
|
||
|
if (b1 != 0)
|
||
|
{
|
||
|
s += " /SD";
|
||
|
Add_ButtonID(b1);
|
||
|
}
|
||
|
}
|
||
|
if (asf != allowSkipFiles_State)
|
||
|
{
|
||
|
if (asf < 0)
|
||
|
{
|
||
|
s += "AllowSkipFiles ";
|
||
|
s += (asf == -1) ? "on" : "off";
|
||
|
}
|
||
|
AddLF();
|
||
|
Tab(kkk < endCommentIndex);
|
||
|
}
|
||
|
allowSkipFiles_State = (Int32)nsisMB;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s += "File";
|
||
|
AddParam(params[1]);
|
||
|
|
||
|
/* params[5] contains link to LangString (negative value)
|
||
|
with NLF_FILE_ERROR or NLF_FILE_ERROR_NOIGNORE message for MessageBox.
|
||
|
We don't need to print it. */
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (IsVarStr(par1, 10)) // is $R0
|
||
|
{
|
||
|
// we parse InstallLib macro in 7-Zip installers
|
||
|
unsigned kBackOffset = 28;
|
||
|
if (kkk > 1)
|
||
|
{
|
||
|
// detect old version of InstallLib macro
|
||
|
if (Get32(p - 1 * kCmdSize) == EW_NOP) // goto command
|
||
|
kBackOffset -= 2;
|
||
|
}
|
||
|
|
||
|
if (kkk > kBackOffset)
|
||
|
{
|
||
|
const Byte *p2 = p - kBackOffset * kCmdSize;
|
||
|
UInt32 cmd = Get32(p2);
|
||
|
if (cmd == EW_ASSIGNVAR)
|
||
|
{
|
||
|
UInt32 pars[6];
|
||
|
for (int i = 0; i < 6; i++)
|
||
|
pars[i] = Get32(p2 + i * 4 + 4);
|
||
|
if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4
|
||
|
{
|
||
|
item.Prefix = -1;
|
||
|
item.NameA.Empty();
|
||
|
item.NameU.Empty();
|
||
|
SetItemName(item, pars[1]);
|
||
|
// maybe here we can restore original item name, if new name is empty
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/* UInt32 allowIgnore = params[5]; */
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SETFILEATTRIBUTES:
|
||
|
{
|
||
|
if (kkk > 0 && Get32(p - kCmdSize) == EW_EXTRACTFILE)
|
||
|
{
|
||
|
if (params[0] == Get32(p - kCmdSize + 4 + 4 * 1)) // compare with PrevCmd.Params[1]
|
||
|
{
|
||
|
CItem &item = Items.Back();
|
||
|
item.Attrib_Defined = true;
|
||
|
item.Attrib = params[1];
|
||
|
}
|
||
|
}
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
AddParam(params[0]);
|
||
|
Space();
|
||
|
FlagsToString2(s, g_WinAttrib, ARRAY_SIZE(g_WinAttrib), params[1]);
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_WRITEUNINSTALLER:
|
||
|
{
|
||
|
/* NSIS 2.29+ writes alternative path to params[3]
|
||
|
"$INSTDIR\\" + Str(params[0])
|
||
|
NSIS installer uses alternative path, if main path
|
||
|
from params[0] is not absolute path */
|
||
|
|
||
|
bool pathOk = (params[0] > 0) && IsGoodString(params[0]);
|
||
|
|
||
|
if (!pathOk)
|
||
|
{
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
AddError("bad path");
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bool altPathOk = true;
|
||
|
|
||
|
UInt32 altParam = params[3];
|
||
|
if (altParam != 0)
|
||
|
{
|
||
|
altPathOk = false;
|
||
|
UInt32 additional = 0;
|
||
|
if (GetVarIndexFinished(altParam, '\\', additional) == kVar_INSTDIR)
|
||
|
altPathOk = AreTwoParamStringsEqual(altParam + additional, params[0]);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
AddParam(params[0]);
|
||
|
|
||
|
/*
|
||
|
for (int i = 1; i < 3; i++)
|
||
|
AddParam_UInt(params[i]);
|
||
|
*/
|
||
|
|
||
|
if (params[3] != 0)
|
||
|
{
|
||
|
SmallSpaceComment();
|
||
|
AddParam(params[3]);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (!altPathOk)
|
||
|
{
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
AddError("alt path error");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (BadCmd >= 0 && BadCmd <= EW_WRITEUNINSTALLER)
|
||
|
{
|
||
|
/* We don't cases with incorrect installer commands.
|
||
|
Such bad installer item can break unpacking for other items. */
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
AddError("SKIP possible BadCmd");
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
CItem &item = Items.AddNew();;
|
||
|
|
||
|
SetItemName(item, params[0]);
|
||
|
|
||
|
item.Pos = params[1];
|
||
|
item.PatchSize = params[2];
|
||
|
item.IsUninstaller = true;
|
||
|
|
||
|
/*
|
||
|
// we can add second time to test the code
|
||
|
CItem item2 = item;
|
||
|
item2.NameU += L'2';
|
||
|
item2.NameA += '2';
|
||
|
Items.Add(item2);
|
||
|
*/
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
case EW_RET:
|
||
|
{
|
||
|
// bool needComment = false;
|
||
|
if (onFuncIsOpen)
|
||
|
{
|
||
|
if (kkk == bh.Num - 1 || IsProbablyEndOfFunc(labels[kkk + 1]))
|
||
|
{
|
||
|
AddStringLF("FunctionEnd");
|
||
|
|
||
|
if ((int)kkk + 1 == InitPluginsDir_End)
|
||
|
CommentClose();
|
||
|
AddLF();
|
||
|
onFuncIsOpen = false;
|
||
|
// needComment = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// if (!needComment)
|
||
|
if (IsSectionGroup)
|
||
|
break;
|
||
|
if (sectionIsOpen)
|
||
|
{
|
||
|
const CSection § = Sections[curSectionIndex];
|
||
|
if (sect.StartCmdIndex + sect.NumCommands == kkk)
|
||
|
{
|
||
|
PrintSectionEnd();
|
||
|
sectionIsOpen = false;
|
||
|
curSectionIndex++;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// needComment = true;
|
||
|
// break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if (needComment)
|
||
|
s += " ;";
|
||
|
*/
|
||
|
TabString("Return");
|
||
|
AddLF();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_NOP:
|
||
|
{
|
||
|
if (params[0] == 0)
|
||
|
s += "Nop";
|
||
|
else
|
||
|
{
|
||
|
s += "Goto";
|
||
|
Add_GotoVar(params[0]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_ABORT:
|
||
|
{
|
||
|
AddOptionalParam(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_CALL:
|
||
|
{
|
||
|
if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_EXTRACTFILE)
|
||
|
{
|
||
|
UInt32 par1 = GET_CMD_PARAM(p + kCmdSize, 1);
|
||
|
|
||
|
UInt32 pluginPar = 0;
|
||
|
|
||
|
if (GetVarIndexFinished(par1, '\\', pluginPar) == kVar_PLUGINSDIR)
|
||
|
{
|
||
|
pluginPar += par1;
|
||
|
UInt32 commandId2 = GetCmd(Get32(p + kCmdSize * 2));
|
||
|
if (commandId2 == EW_SETFLAG || commandId2 == EW_UPDATETEXT)
|
||
|
{
|
||
|
UInt32 i;
|
||
|
for (i = kkk + 3; i < bh.Num; i++)
|
||
|
{
|
||
|
const Byte *pCmd = p + kCmdSize * (i - kkk);
|
||
|
UInt32 commandId3 = GetCmd(Get32(pCmd));
|
||
|
if (commandId3 != EW_PUSHPOP
|
||
|
|| GET_CMD_PARAM(pCmd, 1) != 0
|
||
|
|| GET_CMD_PARAM(pCmd, 2) != 0)
|
||
|
break;
|
||
|
}
|
||
|
if (i < bh.Num)
|
||
|
{
|
||
|
const Byte *pCmd = p + kCmdSize * (i - kkk);
|
||
|
|
||
|
// UInt32 callDll_Param = GET_CMD_PARAM(pCmd, 0);
|
||
|
// UInt32 file_Param = GET_CMD_PARAM(p + kCmdSize, 1);
|
||
|
|
||
|
if (GetCmd(Get32(pCmd)) == EW_REGISTERDLL &&
|
||
|
AreTwoParamStringsEqual(
|
||
|
GET_CMD_PARAM(pCmd, 0),
|
||
|
GET_CMD_PARAM(p + kCmdSize, 1)))
|
||
|
{
|
||
|
// params[4] = 1 means GetModuleHandle attempt before default LoadLibraryEx;
|
||
|
/// new versions of NSIS use params[4] = 1 for Plugin command
|
||
|
if (GET_CMD_PARAM(pCmd, 2) == 0
|
||
|
// && GET_CMD_PARAM(pCmd, 4) != 0
|
||
|
)
|
||
|
{
|
||
|
{
|
||
|
AString s2;
|
||
|
ReadString2(s2, pluginPar);
|
||
|
if (s2.Len() >= 4 &&
|
||
|
StringsAreEqualNoCase_Ascii(s2.RightPtr(4), ".dll"))
|
||
|
s2.DeleteFrom(s2.Len() - 4);
|
||
|
s2 += "::";
|
||
|
AString func;
|
||
|
ReadString2(func, GET_CMD_PARAM(pCmd, 1));
|
||
|
s2 += func;
|
||
|
Add_QuStr(s2);
|
||
|
|
||
|
if (GET_CMD_PARAM(pCmd, 3) == 1)
|
||
|
s += " /NOUNLOAD";
|
||
|
|
||
|
for (UInt32 j = i - 1; j >= kkk + 3; j--)
|
||
|
{
|
||
|
const Byte *pCmd = p + kCmdSize * (j - kkk);
|
||
|
AddParam(GET_CMD_PARAM(pCmd, 0));
|
||
|
}
|
||
|
NewLine();
|
||
|
Tab(true);
|
||
|
endCommentIndex = i + 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
const Byte *nextCmd = p + kCmdSize;
|
||
|
UInt32 commandId2 = GetCmd(Get32(nextCmd));
|
||
|
if (commandId2 == EW_SETFLAG
|
||
|
&& GET_CMD_PARAM(nextCmd, 0) == k_ExecFlags_DetailsPrint
|
||
|
&& GET_CMD_PARAM(nextCmd, 2) != 0) // is "lastused"
|
||
|
// || commandId2 == EW_UPDATETEXT)
|
||
|
{
|
||
|
if ((Int32)params[0] > 0 && labels[params[0] - 1] & CMD_REF_InitPluginDir)
|
||
|
{
|
||
|
s += "InitPluginsDir";
|
||
|
AddLF();
|
||
|
Tab(true);
|
||
|
endCommentIndex = kkk + 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s += "Call ";
|
||
|
if ((Int32)params[0] < 0)
|
||
|
Add_Var(-((Int32)params[0] + 1));
|
||
|
else if (params[0] == 0)
|
||
|
s += '0';
|
||
|
else
|
||
|
{
|
||
|
UInt32 val = params[0] - 1;
|
||
|
if (params[1] == 1) // it's Call :Label
|
||
|
{
|
||
|
s += ':';
|
||
|
Add_LabelName(val);
|
||
|
}
|
||
|
else // if (params[1] == 0) // it's Call Func
|
||
|
Add_FuncName(labels, val);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_UPDATETEXT:
|
||
|
case EW_SLEEP:
|
||
|
{
|
||
|
AddParam(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_CHDETAILSVIEW:
|
||
|
{
|
||
|
if (params[0] == MY__SW_SHOWNA && params[1] == MY__SW_HIDE) s += " show";
|
||
|
else if (params[1] == MY__SW_SHOWNA && params[0] == MY__SW_HIDE) s += " hide";
|
||
|
else
|
||
|
for (int i = 0; i < 2; i++)
|
||
|
{
|
||
|
Space();
|
||
|
Add_ShowWindow_Cmd(params[i]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_IFFILEEXISTS:
|
||
|
{
|
||
|
AddParam(params[0]);
|
||
|
Add_GotoVars2(¶ms[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SETFLAG:
|
||
|
{
|
||
|
AString temp;
|
||
|
ReadString2(temp, params[1]);
|
||
|
if (params[0] == k_ExecFlags_Errors && params[2] == 0)
|
||
|
{
|
||
|
s += (temp.Len() == 1 && temp[0] == '0') ? "ClearErrors" : "SetErrors";
|
||
|
break;
|
||
|
}
|
||
|
s += "Set";
|
||
|
Add_ExecFlags(params[0]);
|
||
|
|
||
|
if (params[2] != 0)
|
||
|
{
|
||
|
s += " lastused";
|
||
|
break;
|
||
|
}
|
||
|
UInt32 v;
|
||
|
if (StringToUInt32(temp, v))
|
||
|
{
|
||
|
const char *s2 = NULL;
|
||
|
switch (params[0])
|
||
|
{
|
||
|
case k_ExecFlags_AutoClose:
|
||
|
case k_ExecFlags_RebootFlag:
|
||
|
if (v < 2) s2 = (v == 0) ? "false" : "true"; break;
|
||
|
case k_ExecFlags_ShellVarContext:
|
||
|
if (v < 2) s2 = (v == 0) ? "current" : "all"; break;
|
||
|
case k_ExecFlags_Silent:
|
||
|
if (v < 2) s2 = (v == 0) ? "normal" : "silent"; break;
|
||
|
case k_ExecFlags_RegView:
|
||
|
if (v == 0) s2 = "32";
|
||
|
else if (v == 256) s2 = "64";
|
||
|
break;
|
||
|
case k_ExecFlags_DetailsPrint:
|
||
|
if (v == 0) s2 = "both";
|
||
|
else if (v == 2) s2 = "textonly";
|
||
|
else if (v == 4) s2 = "listonly";
|
||
|
else if (v == 6) s2 = "none";
|
||
|
}
|
||
|
if (s2)
|
||
|
{
|
||
|
s += ' ';
|
||
|
s += s2;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
SpaceQuStr(temp);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_IFFLAG:
|
||
|
{
|
||
|
Add_ExecFlags(params[2]);
|
||
|
Add_GotoVars2(¶ms[0]);
|
||
|
/*
|
||
|
static const unsigned kIfErrors = 2;
|
||
|
if (params[2] != kIfErrors && params[3] != 0xFFFFFFFF ||
|
||
|
params[2] == kIfErrors && params[3] != 0)
|
||
|
{
|
||
|
s += " # FLAG &= ";
|
||
|
AddParam_UInt(params[3]);
|
||
|
}
|
||
|
*/
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_GETFLAG:
|
||
|
{
|
||
|
Add_ExecFlags(params[1]);
|
||
|
AddParam_Var(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_RENAME:
|
||
|
{
|
||
|
if (params[2] != 0)
|
||
|
s += k_REBOOTOK;
|
||
|
AddParams(params, 2);
|
||
|
if (params[3] != 0)
|
||
|
{
|
||
|
SmallSpaceComment();
|
||
|
AddParam(params[3]); // rename comment for log file
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_GETFULLPATHNAME:
|
||
|
{
|
||
|
if (params[2] == 0)
|
||
|
s += " /SHORT";
|
||
|
AddParam_Var(params[1]);
|
||
|
AddParam(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SEARCHPATH:
|
||
|
case EW_STRLEN:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_GETTEMPFILENAME:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AString temp;
|
||
|
ReadString2(temp, params[1]);
|
||
|
if (temp != "$TEMP")
|
||
|
SpaceQuStr(temp);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_DELETEFILE:
|
||
|
{
|
||
|
UInt32 flag = params[1];
|
||
|
if ((flag & DEL_REBOOT) != 0)
|
||
|
s += k_REBOOTOK;
|
||
|
AddParam(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_MESSAGEBOX:
|
||
|
{
|
||
|
MessageBox_MB_Part(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
{
|
||
|
UInt32 buttonID = (params[0] >> 21); // NSIS 2.06+
|
||
|
if (buttonID != 0)
|
||
|
{
|
||
|
s += " /SD";
|
||
|
Add_ButtonID(buttonID);
|
||
|
}
|
||
|
}
|
||
|
for (int i = 2; i < 6; i += 2)
|
||
|
if (params[i] != 0)
|
||
|
{
|
||
|
Add_ButtonID(params[i]);
|
||
|
Add_GotoVar1(params[i + 1]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_RMDIR:
|
||
|
{
|
||
|
UInt32 flag = params[1];
|
||
|
if ((flag & DEL_RECURSE) != 0)
|
||
|
s += " /r";
|
||
|
if ((flag & DEL_REBOOT) != 0)
|
||
|
s += k_REBOOTOK;
|
||
|
AddParam(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_STRCMP:
|
||
|
{
|
||
|
if (params[4] != 0)
|
||
|
s += 'S';
|
||
|
AddParams(params, 2);
|
||
|
Add_GotoVars2(¶ms[2]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_READENVSTR:
|
||
|
{
|
||
|
s += (params[2] != 0) ?
|
||
|
"ReadEnvStr" :
|
||
|
"ExpandEnvStrings";
|
||
|
AddParam_Var(params[0]);
|
||
|
AString temp;
|
||
|
ReadString2(temp, params[1]);
|
||
|
if (params[2] != 0 &&temp.Len() >= 2 && temp[0] == '%' && temp.Back() == '%')
|
||
|
{
|
||
|
temp.DeleteBack();
|
||
|
temp.Delete(0);
|
||
|
}
|
||
|
SpaceQuStr(temp);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_INTCMP:
|
||
|
{
|
||
|
if (params[5] != 0)
|
||
|
s += 'U';
|
||
|
AddParams(params, 2);
|
||
|
Add_GotoVar1(params[2]);
|
||
|
if (params[3] != 0 || params[4] != 0)
|
||
|
Add_GotoVars2(params + 3);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_INTOP:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
const char *kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+
|
||
|
// "+-*/|&^!|&%"; // NSIS 2.0b4+
|
||
|
// "+-*/|&^~!|&%"; // NSIS old
|
||
|
UInt32 opIndex = params[3];
|
||
|
char c = (opIndex < 13) ? kOps[opIndex] : '?';
|
||
|
char c2 = (opIndex < 8 || opIndex == 10) ? (char)0 : c;
|
||
|
int numOps = (opIndex == 7) ? 1 : 2;
|
||
|
AddParam(params[1]);
|
||
|
if (numOps == 2 && c == '^' && IsDirectString_Equal(params[2], "0xFFFFFFFF"))
|
||
|
s += " ~ ;";
|
||
|
Space();
|
||
|
s += c;
|
||
|
if (numOps != 1)
|
||
|
{
|
||
|
if (c2 != 0)
|
||
|
s += c2;
|
||
|
AddParam(params[2]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_INTFMT:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParams(params + 1, 2);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_PUSHPOP:
|
||
|
{
|
||
|
if (params[2] != 0)
|
||
|
{
|
||
|
s += "Exch";
|
||
|
if (params[2] != 1)
|
||
|
AddParam_UInt(params[2]);
|
||
|
}
|
||
|
else if (params[1] != 0)
|
||
|
{
|
||
|
s += "Pop";
|
||
|
AddParam_Var(params[0]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (NoLabels(labels + kkk + 1, 2)
|
||
|
&& Get32(p + kCmdSize) == EW_PUSHPOP // Exch"
|
||
|
&& GET_CMD_PARAM(p + kCmdSize, 2) == 1
|
||
|
&& Get32(p + kCmdSize * 2) == EW_PUSHPOP // Pop $VAR
|
||
|
&& GET_CMD_PARAM(p + kCmdSize * 2, 1) != 0)
|
||
|
{
|
||
|
if (IsVarStr(params[0], GET_CMD_PARAM(p + kCmdSize * 2, 0)))
|
||
|
{
|
||
|
s += "Exch";
|
||
|
AddParam(params[0]);
|
||
|
NewLine();
|
||
|
Tab(true);
|
||
|
endCommentIndex = kkk + 3;
|
||
|
}
|
||
|
}
|
||
|
s += "Push";
|
||
|
AddParam(params[0]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FINDWINDOW:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
AddOptionalParams(params + 2, 3);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SENDMESSAGE:
|
||
|
{
|
||
|
// SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
|
||
|
AddParam(params[1]);
|
||
|
|
||
|
const char *w = NULL;
|
||
|
AString t;
|
||
|
ReadString2(t, params[2]);
|
||
|
UInt32 wm;
|
||
|
if (StringToUInt32(t, wm))
|
||
|
{
|
||
|
switch (wm)
|
||
|
{
|
||
|
case 0x0C: w = "SETTEXT"; break;
|
||
|
case 0x10: w = "CLOSE"; break;
|
||
|
case 0x30: w = "SETFONT"; break;
|
||
|
}
|
||
|
}
|
||
|
if (w)
|
||
|
{
|
||
|
s += " ${WM_";
|
||
|
s += w;
|
||
|
s += '}';
|
||
|
}
|
||
|
else
|
||
|
SpaceQuStr(t);
|
||
|
|
||
|
UInt32 spec = params[5];
|
||
|
for (unsigned i = 0; i < 2; i++)
|
||
|
{
|
||
|
AString s2;
|
||
|
if (spec & ((UInt32)1 << i))
|
||
|
s2 += "STR:";
|
||
|
ReadString2(s2, params[3 + i]);
|
||
|
SpaceQuStr(s2);
|
||
|
}
|
||
|
|
||
|
if ((Int32)params[0] >= 0)
|
||
|
AddParam_Var(params[0]);
|
||
|
|
||
|
spec >>= 2;
|
||
|
if (spec != 0)
|
||
|
{
|
||
|
s += " /TIMEOUT=";
|
||
|
Add_UInt(spec);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_ISWINDOW:
|
||
|
{
|
||
|
AddParam(params[0]);
|
||
|
Add_GotoVars2(¶ms[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_GETDLGITEM:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParams(params + 1, 2);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SETCTLCOLORS:
|
||
|
{
|
||
|
AddParam(params[0]);
|
||
|
|
||
|
UInt32 offset = params[1];
|
||
|
|
||
|
if (_size < bhCtlColors.Offset
|
||
|
|| _size - bhCtlColors.Offset < offset
|
||
|
|| _size - bhCtlColors.Offset - offset < k_CtlColors_Size)
|
||
|
{
|
||
|
AddError("bad offset");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
const Byte *p2 = _data + bhCtlColors.Offset + offset;
|
||
|
CNsis_CtlColors colors;
|
||
|
colors.Parse(p2);
|
||
|
|
||
|
if ((colors.flags & kColorsFlags_BK_SYS) != 0 ||
|
||
|
(colors.flags & kColorsFlags_TEXT_SYS) != 0)
|
||
|
s += " /BRANDING";
|
||
|
|
||
|
AString bk;
|
||
|
bool bkc = false;
|
||
|
if (colors.bkmode == MY__TRANSPARENT)
|
||
|
bk += " transparent";
|
||
|
else if (colors.flags & kColorsFlags_BKB)
|
||
|
{
|
||
|
if ((colors.flags & kColorsFlags_BK_SYS) == 0 &&
|
||
|
(colors.flags & kColorsFlags_BK) != 0)
|
||
|
bkc = true;
|
||
|
}
|
||
|
if ((colors.flags & kColorsFlags_TEXT) != 0 || !bk.IsEmpty() || bkc)
|
||
|
{
|
||
|
Space();
|
||
|
if ((colors.flags & kColorsFlags_TEXT_SYS) != 0 || (colors.flags & kColorsFlags_TEXT) == 0)
|
||
|
AddQuotes();
|
||
|
else
|
||
|
Add_Color(colors.text);
|
||
|
}
|
||
|
s += bk;
|
||
|
if (bkc)
|
||
|
{
|
||
|
Space();
|
||
|
Add_Color(colors.bkc);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SETBRANDINGIMAGE:
|
||
|
{
|
||
|
s += " /IMGID=";
|
||
|
Add_UInt(params[1]);
|
||
|
if (params[2] == 1)
|
||
|
s += " /RESIZETOFIT";
|
||
|
AddParam(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_CREATEFONT:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
AddOptionalParams(params + 2, 2);
|
||
|
if (params[4] & 1) s += " /ITALIC";
|
||
|
if (params[4] & 2) s += " /UNDERLINE";
|
||
|
if (params[4] & 4) s += " /STRIKE";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SHOWWINDOW:
|
||
|
{
|
||
|
AString hw, sw;
|
||
|
ReadString2(hw, params[0]);
|
||
|
ReadString2(sw, params[1]);
|
||
|
if (params[3] != 0)
|
||
|
s += "EnableWindow";
|
||
|
else
|
||
|
{
|
||
|
UInt32 val;
|
||
|
bool valDefined = false;
|
||
|
if (StringToUInt32(sw, val))
|
||
|
{
|
||
|
if (val < ARRAY_SIZE(kShowWindow_Commands))
|
||
|
{
|
||
|
sw.Empty();
|
||
|
sw += "${";
|
||
|
Add_ShowWindow_Cmd_2(sw, val);
|
||
|
sw += '}';
|
||
|
valDefined = true;
|
||
|
}
|
||
|
}
|
||
|
bool isHwndParent = IsVarStr(params[0], IsNsis225 ? kVar_HWNDPARENT_225 : kVar_HWNDPARENT);
|
||
|
if (params[2] != 0)
|
||
|
{
|
||
|
if (valDefined && val == 0 && isHwndParent)
|
||
|
{
|
||
|
s += "HideWindow";
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (valDefined && val == 5 && isHwndParent &&
|
||
|
kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_BRINGTOFRONT)
|
||
|
{
|
||
|
s += " ; ";
|
||
|
}
|
||
|
s += "ShowWindow";
|
||
|
}
|
||
|
SpaceQuStr(hw);
|
||
|
SpaceQuStr(sw);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_SHELLEXEC:
|
||
|
{
|
||
|
AddParams(params, 2);
|
||
|
if (params[2] != 0 || params[3] != MY__SW_SHOWNORMAL)
|
||
|
{
|
||
|
AddParam(params[2]);
|
||
|
if (params[3] != MY__SW_SHOWNORMAL)
|
||
|
{
|
||
|
Space();
|
||
|
Add_ShowWindow_Cmd(params[3]);
|
||
|
}
|
||
|
}
|
||
|
if (params[5] != 0)
|
||
|
{
|
||
|
s += " ;";
|
||
|
AddParam(params[5]); // it's tatus text update
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_EXECUTE:
|
||
|
{
|
||
|
if (params[2] != 0)
|
||
|
s += "Wait";
|
||
|
AddParam(params[0]);
|
||
|
if (params[2] != 0)
|
||
|
if ((Int32)params[1] >= 0)
|
||
|
AddParam_Var(params[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_GETFILETIME:
|
||
|
case EW_GETDLLVERSION:
|
||
|
{
|
||
|
AddParam(params[2]);
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam_Var(params[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_REGISTERDLL:
|
||
|
{
|
||
|
AString func;
|
||
|
ReadString2(func, params[1]);
|
||
|
bool printFunc = true;
|
||
|
// params[4] = 1; for plugin command
|
||
|
if (params[2] == 0)
|
||
|
{
|
||
|
s += "CallInstDLL";
|
||
|
AddParam(params[0]);
|
||
|
if (params[3] == 1)
|
||
|
s += " /NOUNLOAD";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (func == "DllUnregisterServer")
|
||
|
{
|
||
|
s += "UnRegDLL";
|
||
|
printFunc = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += "RegDLL";
|
||
|
if (func == "DllRegisterServer")
|
||
|
printFunc = false;
|
||
|
}
|
||
|
AddParam(params[0]);
|
||
|
}
|
||
|
if (printFunc)
|
||
|
SpaceQuStr(func);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_CREATESHORTCUT:
|
||
|
{
|
||
|
unsigned numParams;
|
||
|
for (numParams = 6; numParams > 2; numParams--)
|
||
|
if (params[numParams - 1] != 0)
|
||
|
break;
|
||
|
|
||
|
UInt32 spec = params[4];
|
||
|
if (spec & 0x8000) // NSIS 3.0b0
|
||
|
s += " /NoWorkingDir";
|
||
|
|
||
|
AddParams(params, numParams > 4 ? 4 : numParams);
|
||
|
if (numParams <= 4)
|
||
|
break;
|
||
|
|
||
|
UInt32 icon = (spec & 0xFF);
|
||
|
Space();
|
||
|
if (icon != 0)
|
||
|
Add_UInt(icon);
|
||
|
else
|
||
|
AddQuotes();
|
||
|
|
||
|
if ((spec >> 8) == 0 && numParams < 6)
|
||
|
break;
|
||
|
UInt32 sw = (spec >> 8) & 0x7F;
|
||
|
Space();
|
||
|
// NSIS encoder replaces these names:
|
||
|
if (sw == MY__SW_SHOWMINNOACTIVE)
|
||
|
sw = MY__SW_SHOWMINIMIZED;
|
||
|
if (sw == 0)
|
||
|
AddQuotes();
|
||
|
else
|
||
|
Add_ShowWindow_Cmd(sw);
|
||
|
|
||
|
UInt32 modKey = spec >> 24;
|
||
|
UInt32 key = (spec >> 16) & 0xFF;
|
||
|
|
||
|
if (modKey == 0 && key == 0)
|
||
|
{
|
||
|
if (numParams < 6)
|
||
|
break;
|
||
|
Space();
|
||
|
AddQuotes();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Space();
|
||
|
if (modKey & 1) s += "SHIFT|"; // HOTKEYF_SHIFT
|
||
|
if (modKey & 2) s += "CONTROL|";
|
||
|
if (modKey & 4) s += "ALT|";
|
||
|
if (modKey & 8) s += "EXT|";
|
||
|
|
||
|
static const unsigned kMy_VK_F1 = 0x70;
|
||
|
if (key >= kMy_VK_F1 && key <= kMy_VK_F1 + 23)
|
||
|
{
|
||
|
s += 'F';
|
||
|
Add_UInt(key - kMy_VK_F1 + 1);
|
||
|
}
|
||
|
else if (key >= 'A' && key <= 'Z' || key >= '0' && key <= '9')
|
||
|
s += (char)key;
|
||
|
else
|
||
|
{
|
||
|
s += "Char_";
|
||
|
Add_UInt(key);
|
||
|
}
|
||
|
}
|
||
|
AddOptionalParam(params[5]); // description
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_COPYFILES:
|
||
|
{
|
||
|
if (params[2] & 0x04) s += " /SILENT"; // FOF_SILENT
|
||
|
if (params[2] & 0x80) s += " /FILESONLY"; // FOF_FILESONLY
|
||
|
AddParams(params, 2);
|
||
|
if (params[3] != 0)
|
||
|
{
|
||
|
s += " ;";
|
||
|
AddParam(params[3]); // status text update
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_REBOOT:
|
||
|
{
|
||
|
if (params[0] != 0xbadf00d)
|
||
|
s += " ; Corrupted ???";
|
||
|
else if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_QUIT)
|
||
|
endCommentIndex = kkk + 2;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_WRITEINI:
|
||
|
{
|
||
|
unsigned numAlwaysParams = 0;
|
||
|
if (params[0] == 0) // Section
|
||
|
s += "FlushINI";
|
||
|
else if (params[4] != 0)
|
||
|
{
|
||
|
s += "WriteINIStr";
|
||
|
numAlwaysParams = 3;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += "DeleteINI";
|
||
|
s += (params[1] == 0) ? "Sec" : "Str";
|
||
|
numAlwaysParams = 1;
|
||
|
}
|
||
|
AddParam(params[3]); // filename
|
||
|
// Section, EntryName, Value
|
||
|
AddParams(params, numAlwaysParams);
|
||
|
AddOptionalParams(params + numAlwaysParams, 3 - numAlwaysParams);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_READINISTR:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[3]); // FileName
|
||
|
AddParams(params +1, 2); // Section, EntryName
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_DELREG:
|
||
|
{
|
||
|
// NSIS 2.00 used another scheme!
|
||
|
|
||
|
if (params[4] == 0)
|
||
|
s += "Value";
|
||
|
else
|
||
|
{
|
||
|
s += "Key";
|
||
|
if (params[4] & 2)
|
||
|
s += " /ifempty";
|
||
|
}
|
||
|
AddRegRoot(params[1]);
|
||
|
AddParam(params[2]);
|
||
|
AddOptionalParam(params[3]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_WRITEREG:
|
||
|
{
|
||
|
const char *s2 = 0;
|
||
|
switch (params[4])
|
||
|
{
|
||
|
case 1: s2 = "Str"; break;
|
||
|
case 2: s2 = "ExpandStr"; break; // maybe unused
|
||
|
case 3: s2 = "Bin"; break;
|
||
|
case 4: s2 = "DWORD"; break;
|
||
|
default:
|
||
|
s += '?';
|
||
|
Add_UInt(params[4]);
|
||
|
}
|
||
|
if (params[4] == 1 && params[5] == 2)
|
||
|
s2 = "ExpandStr";
|
||
|
if (s2)
|
||
|
s += s2;
|
||
|
AddRegRoot(params[0]);
|
||
|
AddParams(params + 1, 2); // keyName, valueName
|
||
|
if (params[4] != 3)
|
||
|
AddParam(params[3]); // value
|
||
|
else
|
||
|
{
|
||
|
// Binary data.
|
||
|
Space();
|
||
|
UInt32 offset = params[3];
|
||
|
bool isSupported = false;
|
||
|
if (AfterHeaderSize >= 4
|
||
|
&& bhData.Offset <= AfterHeaderSize - 4
|
||
|
&& offset <= AfterHeaderSize - 4 - bhData.Offset)
|
||
|
{
|
||
|
// we support it for solid archives.
|
||
|
const Byte *p2 = _afterHeader + bhData.Offset + offset;
|
||
|
UInt32 size = Get32(p2);
|
||
|
if (size <= AfterHeaderSize - 4 - bhData.Offset - offset)
|
||
|
{
|
||
|
for (UInt32 i = 0; i < size; i++)
|
||
|
{
|
||
|
Byte b = (p2 + 4)[i];
|
||
|
unsigned t;
|
||
|
t = (b >> 4); s += (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));
|
||
|
t = (b & 15); s += (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));
|
||
|
}
|
||
|
isSupported = true;
|
||
|
}
|
||
|
}
|
||
|
if (!isSupported)
|
||
|
{
|
||
|
// we must read from file here;
|
||
|
s += "data[";
|
||
|
Add_UInt(offset);
|
||
|
s += " ... ]";
|
||
|
s += " ; !!! Unsupported";
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_READREGSTR:
|
||
|
{
|
||
|
s += (params[4] == 1) ? "DWORD" : "Str";
|
||
|
AddParam_Var(params[0]);
|
||
|
AddRegRoot(params[1]);
|
||
|
AddParams(params + 2, 2);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_REGENUM:
|
||
|
{
|
||
|
s += (params[4] != 0) ? "Key" : "Value";
|
||
|
AddParam_Var(params[0]);
|
||
|
AddRegRoot(params[1]);
|
||
|
AddParams(params + 2, 2);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FCLOSE:
|
||
|
case EW_FINDCLOSE:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FOPEN:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[3]);
|
||
|
UInt32 acc = params[1]; // dwDesiredAccess
|
||
|
UInt32 creat = params[2]; // dwCreationDisposition
|
||
|
if (acc == 0 && creat == 0)
|
||
|
break;
|
||
|
char cc = 0;
|
||
|
if (acc == MY__GENERIC_READ && creat == OPEN_EXISTING)
|
||
|
cc = 'r';
|
||
|
else if (creat == CREATE_ALWAYS && acc == MY__GENERIC_WRITE)
|
||
|
cc = 'w';
|
||
|
else if (creat == OPEN_ALWAYS && (acc == (MY__GENERIC_WRITE | MY__GENERIC_READ)))
|
||
|
cc = 'a';
|
||
|
// cc = 0;
|
||
|
if (cc != 0)
|
||
|
{
|
||
|
Space();
|
||
|
s += cc;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (acc & MY__GENERIC_READ) s += " GENERIC_READ";
|
||
|
if (acc & MY__GENERIC_WRITE) s += " GENERIC_WRITE";
|
||
|
if (acc & MY__GENERIC_EXECUTE) s += " GENERIC_EXECUTE";
|
||
|
if (acc & MY__GENERIC_ALL) s += " GENERIC_ALL";
|
||
|
|
||
|
const char *s2 = NULL;
|
||
|
switch (creat)
|
||
|
{
|
||
|
case MY__CREATE_NEW: s2 = "CREATE_NEW"; break;
|
||
|
case MY__CREATE_ALWAYS: s2 = "CREATE_ALWAYS"; break;
|
||
|
case MY__OPEN_EXISTING: s2 = "OPEN_EXISTING"; break;
|
||
|
case MY__OPEN_ALWAYS: s2 = "OPEN_ALWAYS"; break;
|
||
|
case MY__TRUNCATE_EXISTING: s2 = "TRUNCATE_EXISTING"; break;
|
||
|
}
|
||
|
Space();
|
||
|
if (s2)
|
||
|
s += s2;
|
||
|
else
|
||
|
Add_UInt(creat);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FPUTS:
|
||
|
case EW_FPUTWS:
|
||
|
{
|
||
|
if (commandId == EW_FPUTWS)
|
||
|
s += (params[2] == 0) ? "UTF16LE" : "Word";
|
||
|
else if (params[2] != 0)
|
||
|
s += "Byte";
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FGETS:
|
||
|
case EW_FGETWS:
|
||
|
{
|
||
|
if (commandId == EW_FPUTWS)
|
||
|
s += (params[3] == 0) ? "UTF16LE" : "Word";
|
||
|
if (params[3] != 0)
|
||
|
s += "Byte";
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam_Var(params[1]);
|
||
|
AString maxLenStr;
|
||
|
ReadString2(maxLenStr, params[2]);
|
||
|
UInt32 maxLen;
|
||
|
if (StringToUInt32(maxLenStr, maxLen))
|
||
|
{
|
||
|
if (maxLen == 1 && params[3] != 0)
|
||
|
break;
|
||
|
if (maxLen == 1023 && params[3] == 0) // NSIS_MAX_STRLEN - 1; can be other value!!
|
||
|
break;
|
||
|
}
|
||
|
SpaceQuStr(maxLenStr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FSEEK:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[2]);
|
||
|
if (params[3] == 1) s += " CUR"; // FILE_CURRENT
|
||
|
if (params[3] == 2) s += " END"; // FILE_END
|
||
|
if ((Int32)params[1] >= 0)
|
||
|
{
|
||
|
if (params[3] == 0) s += " SET"; // FILE_BEGIN
|
||
|
AddParam_Var(params[1]);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FINDNEXT:
|
||
|
{
|
||
|
AddParam_Var(params[1]);
|
||
|
AddParam_Var(params[0]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FINDFIRST:
|
||
|
{
|
||
|
AddParam_Var(params[1]);
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[2]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_LOG:
|
||
|
{
|
||
|
if (params[0] != 0)
|
||
|
{
|
||
|
s += "Set ";
|
||
|
s += (params[1] == 0) ? "off" : "on";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += "Text";
|
||
|
AddParam(params[1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
case EW_SECTIONSET:
|
||
|
{
|
||
|
if ((Int32)params[2] >= 0)
|
||
|
{
|
||
|
s += "Get";
|
||
|
Add_SectOp(params[2]);
|
||
|
AddParam(params[0]);
|
||
|
AddParam_Var(params[1]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += "Set";
|
||
|
UInt32 t = -(Int32)params[2] - 1;
|
||
|
Add_SectOp(t);
|
||
|
AddParam(params[0]);
|
||
|
AddParam(params[t == 0 ? 4 : 1]);
|
||
|
|
||
|
// params[3] != 0 means call SectionFlagsChanged in installer
|
||
|
// used by SECTIONSETFLAGS command
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_INSTTYPESET:
|
||
|
{
|
||
|
int numQwParams = 0;
|
||
|
const char *s2;
|
||
|
if (params[3] == 0)
|
||
|
{
|
||
|
if (params[2] == 0)
|
||
|
{
|
||
|
s2 = "InstTypeGetText";
|
||
|
numQwParams = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s2 = "InstTypeSetText";
|
||
|
numQwParams = 2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (params[2] == 0)
|
||
|
s2 = "GetCurInstType";
|
||
|
else
|
||
|
{
|
||
|
s2 = "SetCurInstType";
|
||
|
numQwParams = 1;
|
||
|
}
|
||
|
}
|
||
|
s += s2;
|
||
|
AddParams(params, numQwParams);
|
||
|
if (params[2] == 0)
|
||
|
AddParam_Var(params[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_LOCKWINDOW:
|
||
|
{
|
||
|
s += (params[0] == 0) ? " on" : " off";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case EW_FINDPROC:
|
||
|
{
|
||
|
AddParam_Var(params[0]);
|
||
|
AddParam(params[1]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
numSkipParams = 0;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
unsigned numParams = kNumCommandParams;
|
||
|
|
||
|
for (; numParams > 0; numParams--)
|
||
|
if (params[numParams - 1] != 0)
|
||
|
break;
|
||
|
|
||
|
if (numParams > numSkipParams)
|
||
|
{
|
||
|
s += " ; !!!! Unknown Params: ";
|
||
|
unsigned i;
|
||
|
for (i = 0; i < numParams; i++)
|
||
|
AddParam(params[i]);
|
||
|
|
||
|
s += " ;";
|
||
|
|
||
|
for (i = 0; i < numParams; i++)
|
||
|
{
|
||
|
Space();
|
||
|
UInt32 v = params[i];
|
||
|
if (v > 0xFFF00000)
|
||
|
Add_SignedInt(s, (Int32)v);
|
||
|
else
|
||
|
Add_UInt(v);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NewLine();
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
if (sectionIsOpen)
|
||
|
{
|
||
|
if (curSectionIndex < bhSections.Num)
|
||
|
{
|
||
|
const CSection § = Sections[curSectionIndex];
|
||
|
if (sect.StartCmdIndex + sect.NumCommands + 1 == kkk)
|
||
|
{
|
||
|
PrintSectionEnd();
|
||
|
sectionIsOpen = false;
|
||
|
// lastSectionEndCmd = kkk;
|
||
|
curSectionIndex++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (curSectionIndex < bhSections.Num)
|
||
|
{
|
||
|
const CSection § = Sections[curSectionIndex];
|
||
|
if (sectionIsOpen)
|
||
|
{
|
||
|
if (sect.StartCmdIndex + sect.NumCommands != kkk)
|
||
|
AddErrorLF("SECTION ERROR");
|
||
|
PrintSectionEnd();
|
||
|
sectionIsOpen = false;
|
||
|
curSectionIndex++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (curSectionIndex == 49)
|
||
|
curSectionIndex = curSectionIndex;
|
||
|
|
||
|
if (PrintSectionBegin(sect, curSectionIndex))
|
||
|
curSectionIndex++;
|
||
|
else
|
||
|
sectionIsOpen = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
static int CompareItems(void *const *p1, void *const *p2, void *param)
|
||
|
{
|
||
|
const CItem &i1 = **(CItem **)p1;
|
||
|
const CItem &i2 = **(CItem **)p2;
|
||
|
RINOZ(MyCompare(i1.Pos, i2.Pos));
|
||
|
const CInArchive *inArchive = (const CInArchive *)param;
|
||
|
if (inArchive->IsUnicode)
|
||
|
{
|
||
|
if (i1.Prefix != i2.Prefix)
|
||
|
{
|
||
|
if (i1.Prefix < 0) return -1;
|
||
|
if (i2.Prefix < 0) return 1;
|
||
|
RINOZ(wcscmp(
|
||
|
inArchive->UPrefixes[i1.Prefix],
|
||
|
inArchive->UPrefixes[i2.Prefix]));
|
||
|
}
|
||
|
RINOZ(wcscmp(i1.NameU, i2.NameU));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (i1.Prefix != i2.Prefix)
|
||
|
{
|
||
|
if (i1.Prefix < 0) return -1;
|
||
|
if (i2.Prefix < 0) return 1;
|
||
|
RINOZ(strcmp(
|
||
|
inArchive->APrefixes[i1.Prefix],
|
||
|
inArchive->APrefixes[i2.Prefix]));
|
||
|
}
|
||
|
RINOZ(strcmp(i1.NameA, i2.NameA));
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CInArchive::SortItems()
|
||
|
{
|
||
|
{
|
||
|
Items.Sort(CompareItems, (void *)this);
|
||
|
unsigned i;
|
||
|
|
||
|
for (i = 0; i + 1 < Items.Size(); i++)
|
||
|
{
|
||
|
const CItem &i1 = Items[i];
|
||
|
const CItem &i2 = Items[i + 1];
|
||
|
if (i1.Pos != i2.Pos)
|
||
|
continue;
|
||
|
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if (i1.NameU != i2.NameU) continue;
|
||
|
if (i1.Prefix != i2.Prefix)
|
||
|
{
|
||
|
if (i1.Prefix < 0 || i2.Prefix < 0) continue;
|
||
|
if (UPrefixes[i1.Prefix] != UPrefixes[i2.Prefix]) continue;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (i1.NameA != i2.NameA) continue;
|
||
|
if (i1.Prefix != i2.Prefix)
|
||
|
{
|
||
|
if (i1.Prefix < 0 || i2.Prefix < 0) continue;
|
||
|
if (APrefixes[i1.Prefix] != APrefixes[i2.Prefix]) continue;
|
||
|
}
|
||
|
}
|
||
|
Items.Delete(i + 1);
|
||
|
i--;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < Items.Size(); i++)
|
||
|
{
|
||
|
CItem &item = Items[i];
|
||
|
UInt32 curPos = item.Pos + 4;
|
||
|
for (unsigned nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
|
||
|
{
|
||
|
UInt32 nextPos = Items[nextIndex].Pos;
|
||
|
if (curPos <= nextPos)
|
||
|
{
|
||
|
item.EstimatedSize_Defined = true;
|
||
|
item.EstimatedSize = nextPos - curPos;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!IsSolid)
|
||
|
{
|
||
|
for (i = 0; i < Items.Size(); i++)
|
||
|
{
|
||
|
CItem &item = Items[i];
|
||
|
RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL));
|
||
|
const UInt32 kSigSize = 4 + 1 + 1 + 4; // size,[flag],prop,dict
|
||
|
BYTE sig[kSigSize];
|
||
|
size_t processedSize = kSigSize;
|
||
|
RINOK(ReadStream(_stream, sig, &processedSize));
|
||
|
if (processedSize < 4)
|
||
|
return S_FALSE;
|
||
|
UInt32 size = Get32(sig);
|
||
|
if ((size & kMask_IsCompressed) != 0)
|
||
|
{
|
||
|
item.IsCompressed = true;
|
||
|
size &= ~kMask_IsCompressed;
|
||
|
if (Method == NMethodType::kLZMA)
|
||
|
{
|
||
|
if (processedSize < 9)
|
||
|
return S_FALSE;
|
||
|
/*
|
||
|
if (FilterFlag)
|
||
|
item.UseFilter = (sig[4] != 0);
|
||
|
*/
|
||
|
item.DictionarySize = Get32(sig + 4 + 1 + (FilterFlag ? 1 : 0));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
item.IsCompressed = false;
|
||
|
item.Size = size;
|
||
|
item.Size_Defined = true;
|
||
|
}
|
||
|
item.CompressedSize = size;
|
||
|
item.CompressedSize_Defined = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// Flags for common_header.flags
|
||
|
#define CH_FLAGS_DETAILS_SHOWDETAILS 1
|
||
|
#define CH_FLAGS_DETAILS_NEVERSHOW 2
|
||
|
#define CH_FLAGS_PROGRESS_COLORED 4
|
||
|
#define CH_FLAGS_SILENT 8
|
||
|
#define CH_FLAGS_SILENT_LOG 16
|
||
|
#define CH_FLAGS_AUTO_CLOSE 32
|
||
|
#define CH_FLAGS_DIR_NO_SHOW 64 // unused now
|
||
|
#define CH_FLAGS_NO_ROOT_DIR 128
|
||
|
#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256
|
||
|
#define CH_FLAGS_NO_CUSTOM 512
|
||
|
|
||
|
static const char * const k_PostStrings[] =
|
||
|
{
|
||
|
"install_directory_auto_append"
|
||
|
, "uninstchild" // NSIS 2.25+, used by uninstaller:
|
||
|
, "uninstcmd" // NSIS 2.25+, used by uninstaller:
|
||
|
, "wininit" // NSIS 2.25+, used by move file on reboot
|
||
|
};
|
||
|
|
||
|
HRESULT CInArchive::Parse()
|
||
|
{
|
||
|
// UInt32 offset = ReadUInt32();
|
||
|
// ???? offset == FirstHeader.HeaderSize
|
||
|
const Byte *p = _data;
|
||
|
|
||
|
CBlockHeader bhEntries, bhStrings, bhLangTables;
|
||
|
bhEntries.Parse(p + 4 + 8 * 2);
|
||
|
bhStrings.Parse(p + 4 + 8 * 3);
|
||
|
bhLangTables.Parse(p + 4 + 8 * 4);
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
CBlockHeader bhFont;
|
||
|
bhPages.Parse(p + 4 + 8 * 0);
|
||
|
bhSections.Parse(p + 4 + 8 * 1);
|
||
|
bhCtlColors.Parse(p + 4 + 8 * 5);
|
||
|
bhFont.Parse(p + 4 + 8 * 6);
|
||
|
bhData.Parse(p + 4 + 8 * 7);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
_stringsPos = bhStrings.Offset;
|
||
|
if (_stringsPos > _size)
|
||
|
return S_FALSE;
|
||
|
{
|
||
|
if (bhLangTables.Offset < bhStrings.Offset)
|
||
|
return S_FALSE;
|
||
|
UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset;
|
||
|
if (stringTableSize < 2)
|
||
|
return S_FALSE;
|
||
|
const Byte *strData = _data + _stringsPos;
|
||
|
if (strData[stringTableSize - 1] != 0)
|
||
|
return S_FALSE;
|
||
|
IsUnicode = (Get16(strData) == 0);
|
||
|
NumStringChars = stringTableSize;
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if ((stringTableSize & 1) != 0)
|
||
|
return S_FALSE;
|
||
|
NumStringChars >>= 1;
|
||
|
if (strData[stringTableSize - 2] != 0)
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (bhEntries.Num > (1 << 25))
|
||
|
return S_FALSE;
|
||
|
if (bhEntries.Offset > _size)
|
||
|
return S_FALSE;
|
||
|
if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset)
|
||
|
return S_FALSE;
|
||
|
|
||
|
DetectNsisType(bhEntries, _data + bhEntries.Offset);
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
{
|
||
|
AddCommentAndString("NSIS script");
|
||
|
if (IsUnicode)
|
||
|
Script += " (UTF-8)";
|
||
|
Space();
|
||
|
Script += GetFormatDescription();
|
||
|
AddLF();
|
||
|
}
|
||
|
{
|
||
|
AddCommentAndString(IsInstaller ? "Install" : "Uninstall");
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
AddLF();
|
||
|
if (IsUnicode)
|
||
|
AddStringLF("Unicode true");
|
||
|
|
||
|
if (Method != NMethodType::kCopy)
|
||
|
{
|
||
|
const char *m = NULL;
|
||
|
switch (Method)
|
||
|
{
|
||
|
case NMethodType::kDeflate: m = "zlib"; break;
|
||
|
case NMethodType::kBZip2: m = "bzip2"; break;
|
||
|
case NMethodType::kLZMA: m = "lzma"; break;
|
||
|
}
|
||
|
Script += "SetCompressor";
|
||
|
if (IsSolid)
|
||
|
Script += " /SOLID";
|
||
|
if (m)
|
||
|
{
|
||
|
Space();
|
||
|
Script += m;
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
if (Method == NMethodType::kLZMA)
|
||
|
{
|
||
|
// if (DictionarySize != (8 << 20))
|
||
|
{
|
||
|
Script += "SetCompressorDictSize";
|
||
|
AddParam_UInt(DictionarySize >> 20);
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Separator();
|
||
|
PrintNumComment("HEADER SIZE", FirstHeader.HeaderSize);
|
||
|
// if (bhPages.Offset != 300 && bhPages.Offset != 288)
|
||
|
if (bhPages.Offset != 0)
|
||
|
{
|
||
|
PrintNumComment("START HEADER SIZE", bhPages.Offset);
|
||
|
}
|
||
|
|
||
|
if (bhSections.Num > 0)
|
||
|
{
|
||
|
if (bhEntries.Offset < bhSections.Offset)
|
||
|
return S_FALSE;
|
||
|
SectionSize = (bhEntries.Offset - bhSections.Offset) / bhSections.Num;
|
||
|
if (bhSections.Offset + bhSections.Num * SectionSize != bhEntries.Offset)
|
||
|
return S_FALSE;
|
||
|
if (SectionSize < kSectionSize_base)
|
||
|
return S_FALSE;
|
||
|
UInt32 maxStringLen = SectionSize - kSectionSize_base;
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
if ((maxStringLen & 1) != 0)
|
||
|
return S_FALSE;
|
||
|
maxStringLen >>= 1;
|
||
|
}
|
||
|
// if (maxStringLen != 1024)
|
||
|
{
|
||
|
if (maxStringLen == 0)
|
||
|
PrintNumComment("SECTION SIZE", SectionSize);
|
||
|
else
|
||
|
PrintNumComment("MAX STRING LENGTH", maxStringLen);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PrintNumComment("STRING CHARS", NumStringChars);
|
||
|
// PrintNumComment("LANG TABLE SIZE", bhCtlColors.Offset - bhLangTables.Offset);
|
||
|
|
||
|
if (bhCtlColors.Offset > _size)
|
||
|
AddErrorLF("Bad COLORS TABLE");
|
||
|
// PrintNumComment("COLORS TABLE SIZE", bhFont.Offset - bhCtlColors.Offset);
|
||
|
if (bhCtlColors.Num != 0)
|
||
|
PrintNumComment("COLORS Num", bhCtlColors.Num);
|
||
|
|
||
|
// bhData uses offset in _afterHeader (not in _data)
|
||
|
// PrintNumComment("FONT TABLE SIZE", bhData.Offset - bhFont.Offset);
|
||
|
if (bhFont.Num != 0)
|
||
|
PrintNumComment("FONTS Num", bhFont.Num);
|
||
|
|
||
|
// PrintNumComment("DATA SIZE", FirstHeader.HeaderSize - bhData.Offset);
|
||
|
if (bhData.Num != 0)
|
||
|
PrintNumComment("DATA NUM", bhData.Num);
|
||
|
|
||
|
AddLF();
|
||
|
|
||
|
AddStringLF("OutFile [NSIS].exe");
|
||
|
AddStringLF("!include WinMessages.nsh");
|
||
|
|
||
|
AddLF();
|
||
|
|
||
|
strUsed.Alloc(NumStringChars);
|
||
|
memset(strUsed, 0, NumStringChars);
|
||
|
|
||
|
{
|
||
|
UInt32 ehFlags = Get32(p);
|
||
|
UInt32 showDetails = ehFlags & 3;// CH_FLAGS_DETAILS_SHOWDETAILS & CH_FLAGS_DETAILS_NEVERSHOW;
|
||
|
if (showDetails >= 1 && showDetails <= 2)
|
||
|
{
|
||
|
Script += IsInstaller ? "ShowInstDetails" : "ShowUninstDetails";
|
||
|
Script += (showDetails == 1) ? " show" : " nevershow";
|
||
|
AddLF();
|
||
|
}
|
||
|
if (ehFlags & CH_FLAGS_PROGRESS_COLORED) AddStringLF("InstProgressFlags colored" );
|
||
|
if ((ehFlags & (CH_FLAGS_SILENT | CH_FLAGS_SILENT_LOG)) != 0)
|
||
|
{
|
||
|
Script += IsInstaller ? "SilentInstall " : "SilentUnInstall ";
|
||
|
Script += (ehFlags & CH_FLAGS_SILENT_LOG) ? "silentlog" : "silent";
|
||
|
AddLF();
|
||
|
}
|
||
|
if (ehFlags & CH_FLAGS_AUTO_CLOSE) AddStringLF("AutoCloseWindow true");
|
||
|
if ((ehFlags & CH_FLAGS_NO_ROOT_DIR) == 0) AddStringLF("AllowRootDirInstall true");
|
||
|
if (ehFlags & CH_FLAGS_NO_CUSTOM) AddStringLF("InstType /NOCUSTOM");
|
||
|
if (ehFlags & CH_FLAGS_COMP_ONLY_ON_CUSTOM) AddStringLF("InstType /COMPONENTSONLYONCUSTOM");
|
||
|
}
|
||
|
|
||
|
// Separator();
|
||
|
// AddLF();
|
||
|
|
||
|
Int32 licenseLangIndex = -1;
|
||
|
{
|
||
|
const Byte *pp = _data + bhPages.Offset;
|
||
|
|
||
|
for (UInt32 pageIndex = 0; pageIndex < bhPages.Num; pageIndex++, pp += kPageSize)
|
||
|
{
|
||
|
UInt32 wndProcID = Get32(pp + 4);
|
||
|
UInt32 param1 = Get32(pp + 44 + 4 * 1);
|
||
|
if (wndProcID != PWP_LICENSE || param1 == 0)
|
||
|
continue;
|
||
|
if ((Int32)param1 < 0)
|
||
|
licenseLangIndex = - ((Int32)param1 + 1);
|
||
|
else
|
||
|
noParseStringIndexes.AddToUniqueSorted(param1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned paramsOffset = 4 + 8 * 8;
|
||
|
if (bhPages.Offset == 276)
|
||
|
paramsOffset -= 8;
|
||
|
|
||
|
const Byte *p2 = p + paramsOffset;
|
||
|
|
||
|
{
|
||
|
UInt32 rootKey = Get32(p2); // (rootKey = -1) in uninstaller by default (the bug in NSIS)
|
||
|
UInt32 subKey = Get32(p2 + 4);
|
||
|
UInt32 value = Get32(p2 + 8);
|
||
|
if ((rootKey != 0 && rootKey != (UInt32)(Int32)-1) || subKey != 0 || value != 0)
|
||
|
{
|
||
|
Script += "InstallDirRegKey";
|
||
|
AddRegRoot(rootKey);
|
||
|
AddParam(subKey);
|
||
|
AddParam(value);
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
{
|
||
|
UInt32 bg_color1 = Get32(p2 + 12);
|
||
|
UInt32 bg_color2 = Get32(p2 + 16);
|
||
|
UInt32 bg_textcolor = Get32(p2 + 20);
|
||
|
if (bg_color1 != (UInt32)(Int32)-1 || bg_color2 != (UInt32)(Int32)-1 || bg_textcolor != (UInt32)(Int32)-1)
|
||
|
{
|
||
|
Script += "BGGradient";
|
||
|
if (bg_color1 != 0 || bg_color2 != 0xFF0000 || bg_textcolor != (UInt32)(Int32)-1)
|
||
|
{
|
||
|
Add_ColorParam(bg_color1);
|
||
|
Add_ColorParam(bg_color2);
|
||
|
if (bg_textcolor != (UInt32)(Int32)-1)
|
||
|
Add_ColorParam(bg_textcolor);
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UInt32 lb_bg = Get32(p2 + 24);
|
||
|
UInt32 lb_fg = Get32(p2 + 28);
|
||
|
if ((lb_bg != (UInt32)(Int32)-1 || lb_fg != (UInt32)(Int32)-1) &&
|
||
|
(lb_bg != 0 || lb_fg != 0xFF00))
|
||
|
{
|
||
|
Script += "InstallColors";
|
||
|
Add_ColorParam(lb_fg);
|
||
|
Add_ColorParam(lb_bg);
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UInt32 license_bg = Get32(p2 + 36);
|
||
|
if (license_bg != (UInt32)(Int32)-1 && license_bg != -15) // COLOR_BTNFACE
|
||
|
{
|
||
|
Script += "LicenseBkColor";
|
||
|
if ((Int32)license_bg == -5) // COLOR_WINDOW
|
||
|
Script += " /windows";
|
||
|
/*
|
||
|
else if ((Int32)license_bg == -15)
|
||
|
Script += " /grey";
|
||
|
*/
|
||
|
else
|
||
|
Add_ColorParam(license_bg);
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
UInt32 langtable_size = Get32(p2 + 32);
|
||
|
if (bhLangTables.Num > 0)
|
||
|
{
|
||
|
if (langtable_size == (UInt32)(Int32)-1)
|
||
|
return E_NOTIMPL; // maybe it's old NSIS archive()
|
||
|
|
||
|
UInt32 numStrings = (langtable_size - 10) / 4;
|
||
|
_numLangStrings = numStrings;
|
||
|
AddLF();
|
||
|
Separator();
|
||
|
PrintNumComment("LANG TABLES", bhLangTables.Num);
|
||
|
PrintNumComment("LANG STRINGS", numStrings);
|
||
|
AddLF();
|
||
|
|
||
|
if (licenseLangIndex >= 0)
|
||
|
{
|
||
|
for (UInt32 i = 0; i < bhLangTables.Num; i++)
|
||
|
{
|
||
|
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||
|
LANGID langID = Get16(p);
|
||
|
UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4);
|
||
|
if (val != 0)
|
||
|
{
|
||
|
Script += "LicenseLangString ";
|
||
|
Add_LangStr_Simple(licenseLangIndex);
|
||
|
AddParam_UInt(langID);
|
||
|
AddLicense(val, langID);
|
||
|
noParseStringIndexes.AddToUniqueSorted(val);
|
||
|
NewLine();
|
||
|
}
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
|
||
|
UInt32 brandingText = 0;
|
||
|
UInt32 caption = 0;
|
||
|
UInt32 name = 0;
|
||
|
UInt32 i;
|
||
|
for (i = 0; i < bhLangTables.Num; i++)
|
||
|
{
|
||
|
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||
|
LANGID langID = Get16(p);
|
||
|
if (i == 0 || langID == 1033)
|
||
|
_mainLang = p + 10;
|
||
|
{
|
||
|
UInt32 v = Get32(p + 10 + 0 * 4);
|
||
|
if (v != 0 && (langID == 1033 || brandingText == 0))
|
||
|
brandingText = v;
|
||
|
}
|
||
|
{
|
||
|
UInt32 v = Get32(p + 10 + 1 * 4);
|
||
|
if (v != 0 && (langID == 1033 || caption == 0))
|
||
|
caption = v;
|
||
|
}
|
||
|
{
|
||
|
UInt32 v = Get32(p + 10 + 2 * 4);
|
||
|
if (v != 0 && (langID == 1033 || name == 0))
|
||
|
name = v;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (name != 0)
|
||
|
{
|
||
|
Script += "Name";
|
||
|
AddParam(name);
|
||
|
NewLine();
|
||
|
|
||
|
ReadString2(Name, name);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if (caption != 0)
|
||
|
{
|
||
|
Script += "Caption";
|
||
|
AddParam(caption);
|
||
|
NewLine();
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
if (brandingText != 0)
|
||
|
{
|
||
|
Script += "BrandingText";
|
||
|
AddParam(brandingText);
|
||
|
NewLine();
|
||
|
|
||
|
ReadString2(BrandingText, brandingText);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < bhLangTables.Num; i++)
|
||
|
{
|
||
|
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||
|
LANGID langID = Get16(p);
|
||
|
|
||
|
AddLF();
|
||
|
AddCommentAndString("LANG:");
|
||
|
AddParam_UInt(langID);
|
||
|
/*
|
||
|
Script += " (";
|
||
|
LangId_To_String(Script, langID);
|
||
|
Script += ')';
|
||
|
*/
|
||
|
AddLF();
|
||
|
// UInt32 dlg_offset = Get32(p + 2);
|
||
|
// UInt32 g_exec_flags_rtl = Get32(p + 6);
|
||
|
|
||
|
|
||
|
for (UInt32 j = 0; j < numStrings; j++)
|
||
|
{
|
||
|
UInt32 val = Get32(p + 10 + j * 4);
|
||
|
if (val != 0)
|
||
|
{
|
||
|
if ((Int32)j != licenseLangIndex)
|
||
|
{
|
||
|
Script += "LangString ";
|
||
|
Add_LangStr_Simple(j);
|
||
|
AddParam_UInt(langID);
|
||
|
AddParam(val);
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
ClearLangComment();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
unsigned numInternalVars = GET_NUM_INTERNAL_VARS;
|
||
|
UInt32 numUsedVars = GetNumUsedVars();
|
||
|
if (numUsedVars > numInternalVars)
|
||
|
{
|
||
|
Separator();
|
||
|
PrintNumComment("VARIABLES", numUsedVars - numInternalVars);
|
||
|
AddLF();
|
||
|
AString temp;
|
||
|
for (UInt32 i = numInternalVars; i < numUsedVars; i++)
|
||
|
{
|
||
|
Script += "Var ";
|
||
|
temp.Empty();
|
||
|
GetVar2(temp, i);
|
||
|
AddStringLF(temp);
|
||
|
}
|
||
|
AddLF();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onFuncOffset = paramsOffset + 40;
|
||
|
numOnFunc = ARRAY_SIZE(kOnFunc);
|
||
|
if (bhPages.Offset == 276)
|
||
|
numOnFunc--;
|
||
|
p2 += 40 + numOnFunc * 4;
|
||
|
|
||
|
#define NSIS_MAX_INST_TYPES 32
|
||
|
|
||
|
AddLF();
|
||
|
|
||
|
UInt32 i;
|
||
|
for (i = 0; i < NSIS_MAX_INST_TYPES + 1; i++, p2 += 4)
|
||
|
{
|
||
|
UInt32 instType = Get32(p2);
|
||
|
if (instType != 0)
|
||
|
{
|
||
|
Script += "InstType";
|
||
|
AString s2;
|
||
|
if (!IsInstaller)
|
||
|
s2 += "un.";
|
||
|
ReadString2(s2, instType);
|
||
|
SpaceQuStr(s2);
|
||
|
NewLine();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UInt32 installDir = Get32(p2);
|
||
|
p2 += 4;
|
||
|
if (installDir != 0)
|
||
|
{
|
||
|
Script += "InstallDir";
|
||
|
AddParam(installDir);
|
||
|
NewLine();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bhPages.Offset >= 288)
|
||
|
for (i = 0; i < 4; i++)
|
||
|
{
|
||
|
if (i != 0 && bhPages.Offset < 300)
|
||
|
break;
|
||
|
UInt32 param = Get32(p2 + 4 * i);
|
||
|
if (param == 0 || param == (UInt32)(Int32)-1)
|
||
|
continue;
|
||
|
|
||
|
/*
|
||
|
uninstaller:
|
||
|
UInt32 uninstChild = Get32(p2 + 8); // "$TEMP\\$1u_.exe"
|
||
|
UInt32 uninstCmd = Get32(p2 + 12); // "\"$TEMP\\$1u_.exe\" $0 _?=$INSTDIR\\"
|
||
|
int str_wininit = Get32(p2 + 16); // "$WINDIR\\wininit.ini"
|
||
|
*/
|
||
|
|
||
|
AddCommentAndString(k_PostStrings[i]);
|
||
|
Script += " =";
|
||
|
AddParam(param);
|
||
|
NewLine();
|
||
|
}
|
||
|
|
||
|
AddLF();
|
||
|
|
||
|
#endif
|
||
|
|
||
|
RINOK(ReadEntries(bhEntries));
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
|
||
|
Separator();
|
||
|
AddCommentAndString("UNREFERENCED STRINGS:");
|
||
|
AddLF();
|
||
|
AddLF();
|
||
|
CommentOpen();
|
||
|
|
||
|
for (i = 0; i < NumStringChars;)
|
||
|
{
|
||
|
if (!strUsed[i] && i != 0)
|
||
|
// Script += "!!! ";
|
||
|
{
|
||
|
Add_UInt(i);
|
||
|
AddParam(i);
|
||
|
NewLine();
|
||
|
}
|
||
|
if (IsUnicode)
|
||
|
i += GetUi16Str_Len((const Byte *)_data + _stringsPos + i * 2);
|
||
|
else
|
||
|
i += (UInt32)strlen((const char *)(const Byte *)_data + _stringsPos + i);
|
||
|
i++;
|
||
|
}
|
||
|
CommentClose();
|
||
|
#endif
|
||
|
|
||
|
return SortItems();
|
||
|
}
|
||
|
|
||
|
static bool IsLZMA(const Byte *p, UInt32 &dictionary)
|
||
|
{
|
||
|
dictionary = Get32(p + 1);
|
||
|
return (p[0] == 0x5D &&
|
||
|
p[1] == 0x00 && p[2] == 0x00 &&
|
||
|
p[5] == 0x00 && (p[6] & 0x80) == 0x00);
|
||
|
}
|
||
|
|
||
|
static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
|
||
|
{
|
||
|
if (IsLZMA(p, dictionary))
|
||
|
{
|
||
|
thereIsFlag = false;
|
||
|
return true;
|
||
|
}
|
||
|
if (p[0] <= 1 && IsLZMA(p + 1, dictionary))
|
||
|
{
|
||
|
thereIsFlag = true;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static bool IsBZip2(const Byte *p)
|
||
|
{
|
||
|
return (p[0] == 0x31 && p[1] < 14);
|
||
|
}
|
||
|
|
||
|
HRESULT CInArchive::Open2(const Byte *sig, size_t size)
|
||
|
{
|
||
|
const UInt32 kSigSize = 4 + 1 + 5 + 2; // size, flag, 5 - lzma props, 2 - lzma first bytes
|
||
|
if (size < kSigSize)
|
||
|
return S_FALSE;
|
||
|
|
||
|
_headerIsCompressed = true;
|
||
|
IsSolid = true;
|
||
|
FilterFlag = false;
|
||
|
UseFilter = false;
|
||
|
DictionarySize = 1;
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
AfterHeaderSize = 0;
|
||
|
#endif
|
||
|
|
||
|
UInt32 compressedHeaderSize = Get32(sig);
|
||
|
|
||
|
|
||
|
/*
|
||
|
XX XX XX XX XX XX XX XX == FirstHeader.HeaderSize, nonsolid, uncompressed
|
||
|
5D 00 00 dd dd 00 solid LZMA
|
||
|
00 5D 00 00 dd dd 00 solid LZMA, empty filter (there are no such archives)
|
||
|
01 5D 00 00 dd dd 00 solid LZMA, BCJ filter (only 7-Zip installer used that format)
|
||
|
|
||
|
SS SS SS 80 00 5D 00 00 dd dd 00 non-solid LZMA, empty filter
|
||
|
SS SS SS 80 01 5D 00 00 dd dd 00 non-solid LZMA, BCJ filte
|
||
|
SS SS SS 80 01 tt non-solid BZip (tt < 14
|
||
|
SS SS SS 80 non-solid deflate
|
||
|
|
||
|
01 tt solid BZip (tt < 14
|
||
|
other solid Deflate
|
||
|
*/
|
||
|
|
||
|
if (compressedHeaderSize == FirstHeader.HeaderSize)
|
||
|
{
|
||
|
_headerIsCompressed = false;
|
||
|
IsSolid = false;
|
||
|
Method = NMethodType::kCopy;
|
||
|
}
|
||
|
else if (IsLZMA(sig, DictionarySize, FilterFlag))
|
||
|
Method = NMethodType::kLZMA;
|
||
|
else if (sig[3] == 0x80)
|
||
|
{
|
||
|
IsSolid = false;
|
||
|
if (IsLZMA(sig + 4, DictionarySize, FilterFlag) && sig[3] == 0x80)
|
||
|
Method = NMethodType::kLZMA;
|
||
|
else if (IsBZip2(sig + 4))
|
||
|
Method = NMethodType::kBZip2;
|
||
|
else
|
||
|
Method = NMethodType::kDeflate;
|
||
|
}
|
||
|
else if (IsBZip2(sig))
|
||
|
Method = NMethodType::kBZip2;
|
||
|
else
|
||
|
Method = NMethodType::kDeflate;
|
||
|
|
||
|
if (IsSolid)
|
||
|
{
|
||
|
RINOK(_stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_headerIsCompressed = ((compressedHeaderSize & kMask_IsCompressed) != 0);
|
||
|
compressedHeaderSize &= ~kMask_IsCompressed;
|
||
|
_nonSolidStartOffset = compressedHeaderSize;
|
||
|
RINOK(_stream->Seek(DataStreamOffset + 4, STREAM_SEEK_SET, NULL));
|
||
|
}
|
||
|
|
||
|
_data.Alloc(FirstHeader.HeaderSize);
|
||
|
_size = (size_t)FirstHeader.HeaderSize;
|
||
|
|
||
|
Decoder.Method = Method;
|
||
|
Decoder.FilterFlag = FilterFlag;
|
||
|
Decoder.Solid = IsSolid;
|
||
|
Decoder.InputStream = _stream;
|
||
|
Decoder.Buffer.Alloc(kInputBufSize);
|
||
|
Decoder.StreamPos = 0;
|
||
|
|
||
|
if (_headerIsCompressed)
|
||
|
{
|
||
|
RINOK(Decoder.Init(_stream, UseFilter));
|
||
|
if (IsSolid)
|
||
|
{
|
||
|
size_t processedSize = 4;
|
||
|
Byte buf[4];
|
||
|
RINOK(Decoder.Read(buf, &processedSize));
|
||
|
if (processedSize != 4)
|
||
|
return S_FALSE;
|
||
|
if (Get32((const Byte *)buf) != FirstHeader.HeaderSize)
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
size_t processedSize = FirstHeader.HeaderSize;
|
||
|
RINOK(Decoder.Read(_data, &processedSize));
|
||
|
if (processedSize != FirstHeader.HeaderSize)
|
||
|
return S_FALSE;
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
if (IsSolid)
|
||
|
{
|
||
|
/* we need additional bytes for data for WriteRegBin */
|
||
|
AfterHeaderSize = (1 << 12);
|
||
|
_afterHeader.Alloc(AfterHeaderSize);
|
||
|
size_t processedSize = AfterHeaderSize;
|
||
|
RINOK(Decoder.Read(_afterHeader, &processedSize));
|
||
|
AfterHeaderSize = (UInt32)processedSize;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size_t processedSize = FirstHeader.HeaderSize;
|
||
|
RINOK(ReadStream(_stream, (Byte *)_data, &processedSize));
|
||
|
if (processedSize < FirstHeader.HeaderSize)
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
#ifdef NUM_SPEED_TESTS
|
||
|
for (unsigned i = 0; i < NUM_SPEED_TESTS; i++)
|
||
|
{
|
||
|
RINOK(Parse());
|
||
|
Clear2();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return Parse();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
NsisExe =
|
||
|
{
|
||
|
ExeStub
|
||
|
Archive // must start from 512 * N
|
||
|
#ifndef NSIS_CONFIG_CRC_ANAL
|
||
|
{
|
||
|
Some additional data
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Archive
|
||
|
{
|
||
|
FirstHeader
|
||
|
Data
|
||
|
#ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc()
|
||
|
{
|
||
|
CRC
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FirstHeader
|
||
|
{
|
||
|
UInt32 Flags;
|
||
|
Byte Signature[16];
|
||
|
// points to the header+sections+entries+stringtable in the datablock
|
||
|
UInt32 HeaderSize;
|
||
|
UInt32 ArcSize;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
|
||
|
// ---------- PE (EXE) parsing ----------
|
||
|
|
||
|
static const unsigned k_PE_StartSize = 0x40;
|
||
|
static const unsigned k_PE_HeaderSize = 4 + 20;
|
||
|
static const unsigned k_PE_OptHeader32_Size_MIN = 96;
|
||
|
|
||
|
static inline bool CheckPeOffset(UInt32 pe)
|
||
|
{
|
||
|
return (pe >= 0x40 && pe <= 0x1000 && (pe & 7) == 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
static bool IsArc_Pe(const Byte *p, size_t size)
|
||
|
{
|
||
|
if (size < 2)
|
||
|
return false;
|
||
|
if (p[0] != 'M' || p[1] != 'Z')
|
||
|
return false;
|
||
|
if (size < k_PE_StartSize)
|
||
|
return false; // k_IsArc_Res_NEED_MORE;
|
||
|
UInt32 pe = Get32(p + 0x3C);
|
||
|
if (!CheckPeOffset(pe))
|
||
|
return false;
|
||
|
if (pe + k_PE_HeaderSize > size)
|
||
|
return false; // k_IsArc_Res_NEED_MORE;
|
||
|
|
||
|
p += pe;
|
||
|
if (Get32(p) != 0x00004550)
|
||
|
return false;
|
||
|
return Get16(p + 4 + 16) >= k_PE_OptHeader32_Size_MIN;
|
||
|
}
|
||
|
|
||
|
HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition)
|
||
|
{
|
||
|
Clear();
|
||
|
|
||
|
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &StartOffset));
|
||
|
|
||
|
const UInt32 kStartHeaderSize = 4 * 7;
|
||
|
const unsigned kStep = 512; // nsis start is aligned for 512
|
||
|
Byte buf[kStep];
|
||
|
UInt64 pos = StartOffset;
|
||
|
size_t bufSize = 0;
|
||
|
UInt64 pePos = (UInt64)(Int64)-1;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
bufSize = kStep;
|
||
|
RINOK(ReadStream(inStream, buf, &bufSize));
|
||
|
if (bufSize < kStartHeaderSize)
|
||
|
return S_FALSE;
|
||
|
if (memcmp(buf + 4, kSignature, kSignatureSize) == 0)
|
||
|
break;
|
||
|
if (IsArc_Pe(buf, bufSize))
|
||
|
pePos = pos;
|
||
|
pos += kStep;
|
||
|
UInt64 proc = pos - StartOffset;
|
||
|
if (maxCheckStartPosition && proc > *maxCheckStartPosition)
|
||
|
{
|
||
|
if (pePos == 0)
|
||
|
{
|
||
|
if (proc > (1 << 20))
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pePos == (UInt64)(Int64)-1)
|
||
|
{
|
||
|
UInt64 posCur = StartOffset;
|
||
|
for (;;)
|
||
|
{
|
||
|
if (posCur < kStep)
|
||
|
break;
|
||
|
posCur -= kStep;
|
||
|
if (pos - posCur > (1 << 20))
|
||
|
break;
|
||
|
bufSize = kStep;
|
||
|
RINOK(inStream->Seek(posCur, STREAM_SEEK_SET, NULL));
|
||
|
RINOK(ReadStream(inStream, buf, &bufSize));
|
||
|
if (bufSize < kStep)
|
||
|
break;
|
||
|
if (IsArc_Pe(buf, bufSize))
|
||
|
{
|
||
|
pePos = posCur;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// restore buf to nsis header
|
||
|
bufSize = kStep;
|
||
|
RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL));
|
||
|
RINOK(ReadStream(inStream, buf, &bufSize));
|
||
|
if (bufSize < kStartHeaderSize)
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
StartOffset = pos;
|
||
|
UInt32 peSize = 0;
|
||
|
|
||
|
if (pePos != (UInt64)(Int64)-1)
|
||
|
{
|
||
|
UInt64 peSize64 = (pos - pePos);
|
||
|
if (peSize64 < (1 << 20))
|
||
|
{
|
||
|
peSize = (UInt32)peSize64;
|
||
|
StartOffset = pePos;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DataStreamOffset = pos + kStartHeaderSize;
|
||
|
FirstHeader.Flags = Get32(buf);
|
||
|
if ((FirstHeader.Flags & (~kFlagsMask)) != 0)
|
||
|
return S_FALSE;
|
||
|
IsInstaller = (FirstHeader.Flags & NFlags::kUninstall) == 0;
|
||
|
|
||
|
FirstHeader.HeaderSize = Get32(buf + kSignatureSize + 4);
|
||
|
FirstHeader.ArcSize = Get32(buf + kSignatureSize + 8);
|
||
|
if (FirstHeader.ArcSize <= kStartHeaderSize)
|
||
|
return S_FALSE;
|
||
|
|
||
|
RINOK(inStream->Seek(0, STREAM_SEEK_END, &_fileSize));
|
||
|
|
||
|
IsArc = true;
|
||
|
|
||
|
if (peSize != 0)
|
||
|
{
|
||
|
ExeStub.Alloc(peSize);
|
||
|
RINOK(inStream->Seek(pePos, STREAM_SEEK_SET, NULL));
|
||
|
RINOK(ReadStream_FALSE(inStream, ExeStub, peSize));
|
||
|
}
|
||
|
|
||
|
HRESULT res = S_FALSE;
|
||
|
try
|
||
|
{
|
||
|
CLimitedInStream *_limitedStreamSpec = new CLimitedInStream;
|
||
|
_stream = _limitedStreamSpec;
|
||
|
_limitedStreamSpec->SetStream(inStream);
|
||
|
_limitedStreamSpec->InitAndSeek(pos, FirstHeader.ArcSize);
|
||
|
DataStreamOffset -= pos;
|
||
|
res = Open2(buf + kStartHeaderSize, bufSize - kStartHeaderSize);
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
_stream.Release();
|
||
|
throw;
|
||
|
// res = S_FALSE;
|
||
|
}
|
||
|
if (res != S_OK)
|
||
|
{
|
||
|
_stream.Release();
|
||
|
// Clear();
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
UString CInArchive::ConvertToUnicode(const AString &s) const
|
||
|
{
|
||
|
if (IsUnicode)
|
||
|
{
|
||
|
UString res;
|
||
|
if (ConvertUTF8ToUnicode(s, res))
|
||
|
return res;
|
||
|
}
|
||
|
return MultiByteToUnicodeString(s);
|
||
|
}
|
||
|
|
||
|
void CInArchive::Clear2()
|
||
|
{
|
||
|
IsUnicode = false;
|
||
|
NsisType = k_NsisType_Nsis2;
|
||
|
IsNsis225 = false;
|
||
|
IsNsis200 = false;
|
||
|
LogCmdIsEnabled = false;
|
||
|
BadCmd = -1;
|
||
|
|
||
|
#ifdef NSIS_SCRIPT
|
||
|
Name.Empty();
|
||
|
BrandingText.Empty();
|
||
|
Script.Empty();
|
||
|
LicenseFiles.Clear();
|
||
|
_numRootLicenses = 0;
|
||
|
_numLangStrings = 0;
|
||
|
langStrIDs.Clear();
|
||
|
LangComment.Empty();
|
||
|
noParseStringIndexes.Clear();
|
||
|
#endif
|
||
|
|
||
|
APrefixes.Clear();
|
||
|
UPrefixes.Clear();
|
||
|
Items.Clear();
|
||
|
IsUnicode = false;
|
||
|
ExeStub.Free();
|
||
|
}
|
||
|
|
||
|
void CInArchive::Clear()
|
||
|
{
|
||
|
Clear2();
|
||
|
IsArc = false;
|
||
|
_stream.Release();
|
||
|
}
|
||
|
|
||
|
}}
|