Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Nsis/NsisIn.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisIn.cpp6343
1 files changed, 5403 insertions, 940 deletions
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
index 40756008..71791c03 100755..100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -2,1271 +2,5540 @@
#include "StdAfx.h"
-#include "../../../../C/CpuArch.h"
-
-#include "Common/IntToString.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 {
-Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
+static const size_t kInputBufSize = 1 << 20;
+
+static 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
-static const char *kCrLf = "\x0D\x0A";
+#define CR_LF "\x0D\x0A"
#endif
-#define NS_UN_SKIP_CODE 0xE000
-#define NS_UN_VAR_CODE 0xE001
-#define NS_UN_SHELL_CODE 0xE002
-#define NS_UN_LANG_CODE 0xE003
-#define NS_UN_CODES_START NS_UN_SKIP_CODE
-#define NS_UN_CODES_END NS_UN_LANG_CODE
+static const char *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
-Byte CInArchive::ReadByte()
+ 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
{
- if (_posInData >= _size)
- throw 1;
- return _data[_posInData++];
+ 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, // SerCtlColors
+ 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 *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 *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;
}
-UInt32 CInArchive::ReadUInt32()
+#ifdef NSIS_SCRIPT
+
+void CInArchive::Add_UInt(UInt32 v)
{
- UInt32 value = 0;
- for (int i = 0; i < 4; i++)
- value |= ((UInt32)(ReadByte()) << (8 * i));
- return value;
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ Script += sz;
}
-void CInArchive::ReadBlockHeader(CBlockHeader &bh)
+static void Add_SignedInt(CDynLimBuf &s, Int32 v)
{
- bh.Offset = ReadUInt32();
- bh.Num = ReadUInt32();
+ char sz[32];
+ ConvertInt64ToString(v, sz);
+ s += sz;
}
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+static void Add_Hex(CDynLimBuf &s, UInt32 v)
+{
+ char sz[16];
+ sz[0] = '0';
+ sz[1] = 'x';
+ ConvertUInt32ToHex(v, sz + 2);
+ s += sz;
+}
-static int CompareItems(void *const *p1, void *const *p2, void * /* param */)
+static UInt32 GetUi16Str_Len(const Byte *p)
{
- const CItem &i1 = **(CItem **)p1;
- const CItem &i2 = **(CItem **)p2;
- RINOZ(MyCompare(i1.Pos, i2.Pos));
- if (i1.IsUnicode)
+ 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)
{
- RINOZ(i1.PrefixU.Compare(i2.PrefixU));
- RINOZ(i1.NameU.Compare(i2.NameU));
+ 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
{
- RINOZ(i1.PrefixA.Compare(i2.PrefixA));
- RINOZ(i1.NameA.Compare(i2.NameA));
+ 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;
+ }
}
- return 0;
}
-static AString UIntToString(UInt32 v)
+#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 *kVarStrings[] =
{
- char sz[32];
- ConvertUInt64ToString(v, sz);
- return sz;
+ "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 += '_';
+ }
+ }
}
-static AString IntToString(Int32 v)
+void CInArchive::GetVar(AString &res, UInt32 index)
{
- char sz[32];
- ConvertInt64ToString(v, sz);
- return sz;
+ 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;
+ }
+ }
}
-AString CInArchive::ReadStringA(UInt32 pos) const
+#endif
+
+void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
{
- AString s;
- if (pos >= _size)
- return IntToString((Int32)pos);
- UInt32 offset = GetOffset() + _stringsPos + pos;
+ 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);
+ }
+ for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
+ Raw_UString += *s;
+ continue;
+ }
+ c = n;
+ }
+
+ Raw_UString += (wchar_t)c;
+ }
+
+ return;
+ }
+
+ // NSIS-3 Unicode
for (;;)
{
- if (offset >= _size)
- break; // throw 1;
- char c = _data[offset++];
+ unsigned c = Get16(p);
+ p += 2;
+ if (c > NS_3_CODE_SKIP)
+ {
+ Raw_UString += (wchar_t)c;
+ continue;
+ }
if (c == 0)
break;
- s += c;
+
+ 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);
+ }
+ for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
+ Raw_UString += (wchar_t)*s;
}
- return s;
}
-UString CInArchive::ReadStringU(UInt32 pos) const
+#ifdef NSIS_SCRIPT
+
+static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+void CInArchive::GetNsisString_Unicode(AString &res, const Byte *p)
{
- UString s;
- UInt32 offset = GetOffset() + _stringsPos + (pos * 2);
for (;;)
{
- if (offset >= _size || offset + 1 >= _size)
- return s; // throw 1;
- char c0 = _data[offset++];
- char c1 = _data[offset++];
- wchar_t c = (c0 | ((wchar_t)c1 << 8));
+ unsigned c = Get16(p);
+ p += 2;
if (c == 0)
break;
- s += c;
+ 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);
}
- return s;
}
-/*
-static AString ParsePrefix(const AString &prefix)
+#endif
+
+void CInArchive::ReadString2_Raw(UInt32 pos)
{
- AString res = prefix;
- if (prefix.Length() >= 3)
+ Raw_AString.Empty();
+ Raw_UString.Empty();
+ if ((Int32)pos < 0)
+ Add_LangStr(Raw_AString, -((Int32)pos + 1));
+ else if (pos >= NumStringChars)
{
- if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x95 && (Byte)prefix[2] == 0x80)
- res = "$INSTDIR" + prefix.Mid(3);
- else if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x96 && (Byte)prefix[2] == 0x80)
- res = "$OUTDIR" + prefix.Mid(3);
+ Raw_AString += kErrorStr;
+ // UIntToString(Raw_AString, pos);
}
- return res;
+ else
+ {
+ if (IsUnicode)
+ GetNsisString_Unicode_Raw(_data + _stringsPos + pos * 2);
+ else
+ GetNsisString_Raw(_data + _stringsPos + pos);
+ return;
+ }
+ for (const char *s = (const char *)Raw_AString; *s != 0; s++)
+ Raw_UString += *s;
}
-*/
-#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"
+bool CInArchive::IsGoodString(UInt32 param) const
+{
+ if (param >= NumStringChars)
+ return false;
+ if (param == 0)
+ return true;
+ const Byte *p = _data + _stringsPos;
+ if (IsUnicode)
+ return (Get16(p + param * 2 - 2)) == 0;
+ return p[param - 1] == 0;
+}
-/*
-# define CSIDL_PROGRAMS 0x2
-# define CSIDL_PRINTERS 0x4
-# define CSIDL_PERSONAL 0x5
-# define CSIDL_FAVORITES 0x6
-# define CSIDL_STARTUP 0x7
-# define CSIDL_RECENT 0x8
-# define CSIDL_SENDTO 0x9
-# define CSIDL_STARTMENU 0xB
-# define CSIDL_MYMUSIC 0xD
-# define CSIDL_MYVIDEO 0xE
-
-# define CSIDL_DESKTOPDIRECTORY 0x10
-# define CSIDL_NETHOOD 0x13
-# define CSIDL_FONTS 0x14
-# define CSIDL_TEMPLATES 0x15
-# define CSIDL_COMMON_STARTMENU 0x16
-# define CSIDL_COMMON_PROGRAMS 0x17
-# define CSIDL_COMMON_STARTUP 0x18
-# define CSIDL_COMMON_DESKTOPDIRECTORY 0x19
-# define CSIDL_APPDATA 0x1A
-# define CSIDL_PRINTHOOD 0x1B
-# define CSIDL_LOCAL_APPDATA 0x1C
-# define CSIDL_ALTSTARTUP 0x1D
-# define CSIDL_COMMON_ALTSTARTUP 0x1E
-# define CSIDL_COMMON_FAVORITES 0x1F
-
-# define CSIDL_INTERNET_CACHE 0x20
-# define CSIDL_COOKIES 0x21
-# define CSIDL_HISTORY 0x22
-# define CSIDL_COMMON_APPDATA 0x23
-# define CSIDL_WINDOWS 0x24
-# define CSIDL_SYSTEM 0x25
-# define CSIDL_PROGRAM_FILES 0x26
-# define CSIDL_MYPICTURES 0x27
-# define CSIDL_PROFILE 0x28
-# define CSIDL_PROGRAM_FILES_COMMON 0x2B
-# define CSIDL_COMMON_TEMPLATES 0x2D
-# define CSIDL_COMMON_DOCUMENTS 0x2E
-# define CSIDL_COMMON_ADMINTOOLS 0x2F
-
-# define CSIDL_ADMINTOOLS 0x30
-# define CSIDL_COMMON_MUSIC 0x35
-# define CSIDL_COMMON_PICTURES 0x36
-# define CSIDL_COMMON_VIDEO 0x37
-# define CSIDL_RESOURCES 0x38
-# define CSIDL_RESOURCES_LOCALIZED 0x39
-# define CSIDL_CDBURN_AREA 0x3B
-*/
+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;
+}
-struct CCommandPair
+static const char *g_WinAttrib[] =
{
- int NumParams;
- const char *Name;
+ "READONLY"
+ , "HIDDEN"
+ , "SYSTEM"
+ , NULL
+ , "DIRECTORY"
+ , "ARCHIVE"
+ , "DEVICE"
+ , "NORMAL"
+ , "TEMPORARY"
+ , "SPARSE_FILE"
+ , "REPARSE_POINT"
+ , "COMPRESSED"
+ , "OFFLINE"
+ , "NOT_CONTENT_INDEXED"
+ , "ENCRYPTED"
+ , NULL
+ , "VIRTUAL"
};
-enum
+#define FLAGS_DELIMITER '|'
+
+static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags)
{
- // 0
- EW_INVALID_OPCODE, // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction
- // does nothing, which is easily ignored but means something is wrong.
- EW_RET, // return from function call
- EW_NOP, // Nop/Jump, do nothing: 1, [?new address+1:advance one]
- EW_ABORT, // Abort: 1 [status]
- EW_QUIT, // Quit: 0
- EW_CALL, // Call: 1 [new address+1]
- EW_UPDATETEXT, // Update status text: 2 [update str, ui_st_updateflag=?ui_st_updateflag:this]
- EW_SLEEP, // Sleep: 1 [sleep time in milliseconds]
- EW_BRINGTOFRONT, // BringToFront: 0
- EW_CHDETAILSVIEW, // SetDetailsView: 2 [listaction,buttonaction]
-
- // 10
- EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes]
- EW_CREATEDIR, // Create directory: 2, [path, ?update$INSTDIR]
- EW_IFFILEEXISTS, // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists]
- EW_SETFLAG, // Sets a flag: 2 [id, data]
- EW_IFFLAG, // If a flag: 4 [on, off, id, new value mask]
- EW_GETFLAG, // Gets a flag: 2 [output, id]
- EW_RENAME, // Rename: 3 [old, new, rebootok]
- EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn]
- EW_SEARCHPATH, // SearchPath: 2 [output, filename]
- EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir]
-
- // 20
- EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore]
- // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer
- EW_DELETEFILE, // Delete File: 2, [filename, rebootok]
- EW_MESSAGEBOX, // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2]
- EW_RMDIR, // RMDir: 2 [path, recursiveflag]
- EW_STRLEN, // StrLen: 2 [output, input]
- EW_ASSIGNVAR, // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos]
- EW_STRCMP, // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?]
- EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead]
- EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1<val2, val1>val2, unsigned?]
- EW_INTOP, // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lnot input1, 9=lor, 10=land], 11=1%2
-
- // 30
- EW_INTFMT, // IntFmt: [output, format, input]
- EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch]
- EW_FINDWINDOW, // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after]
- EW_SENDMESSAGE, // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
- EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow]
- EW_GETDLGITEM, // GetDlgItem: 3: [outputvar, dialog, item_id]
- EW_SETCTLCOLORS, // SerCtlColors: 3: [hwnd, pointer to struct colors]
- EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file]
- EW_CREATEFONT, // CreateFont: 5: [handle output, face name, height, weight, flags]
- EW_SHOWWINDOW, // ShowWindow: 2: [hwnd, show state]
-
- // 40
- EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]
- EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode]
- EW_GETFILETIME, // GetFileTime; 3 [file highout lowout]
- EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout]
- EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload]
- EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16]
- EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags]
- EW_REBOOT, // Reboot: 0
- EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File]
- EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file]
-
- // 50
- EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key
- EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen]
- // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str
- EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str]
- EW_REGENUM, // RegEnum: 5 [output, rootkey, keyname, index, ?key:value]
- EW_FCLOSE, // FileClose: 1 [handle]
- EW_FOPEN, // FileOpen: 4 [name, openmode, createmode, outputhandle]
- EW_FPUTS, // FileWrite: 3 [handle, string, ?int:string]
- EW_FGETS, // FileRead: 4 [handle, output, maxlen, ?getchar:gets]
- EW_FSEEK, // FileSeek: 4 [handle, offset, mode, >=0?positionoutput]
- EW_FINDCLOSE, // FindClose: 1 [handle]
-
- // 60
- EW_FINDNEXT, // FindNext: 2 [output, handle]
- EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput]
- EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size]
- EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate]
- EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text]
- // SectionGetText: 3: [idx, 1, output]
- // SectionSetFlags: 3: [idx, 2, flags]
- // SectionGetFlags: 3: [idx, 3, output]
- EW_INSTTYPESET, // InstTypeSetFlags: 3: [idx, 0, flags]
- // InstTypeGetFlags: 3: [idx, 1, output]
- // instructions not actually implemented in exehead, but used in compiler.
- EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR
- EW_GETFUNCTIONADDR,
+ 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);
+}
- EW_LOCKWINDOW
+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 *kOnFunc[] =
+{
+ "Init"
+ , "InstSuccess"
+ , "InstFailed"
+ , "UserAbort"
+ , "GUIInit"
+ , "GUIEnd"
+ , "MouseOverSection"
+ , "VerifyInstDir"
+ , "SelChange"
+ , "RebootFailed"
};
-#ifdef NSIS_SCRIPT
-static CCommandPair kCommandPairs[] =
-{
- { 0, "Invalid" },
- { 0, "Return" },
- { 1, "Goto" },
- { 0, "Abort" },
- { 0, "Quit" },
- { 1, "Call" },
- { 2, "UpdateSatusText" },
- { 1, "Sleep" },
- { 0, "BringToFront" },
- { 2, "SetDetailsView" },
-
- { 2, "SetFileAttributes" },
- { 2, "SetOutPath" },
- { 3, "IfFileExists" },
- { 2, "SetFlag" },
- { 4, "IfFlag" },
- { 2, "GetFlag" },
- { 3, "Rename" },
- { 2, "GetFullPathName" },
- { 2, "SearchPath" },
- { 2, "GetTempFileName" },
-
- { 6, "File" },
- { 2, "Delete" },
- { 5, "MessageBox" },
- { 2, "RMDir" },
- { 2, "StrLen" },
- { 4, "StrCpy" },
- { 5, "StrCmp" },
- { 3, "ReadEnvStr" },
- { 6, "IntCmp" },
- { 4, "IntOp" },
-
- { 3, "IntFmt" },
- { 3, "PushPop" },
- { 5, "FindWindow" },
- { 6, "SendMessage" },
- { 3, "IsWindow" },
- { 3, "GetDlgItem" },
- { 3, "SerCtlColors" },
- { 1, "SetBrandingImage" },
- { 5, "CreateFont" },
- { 2, "ShowWindow" },
-
- { 4, "ShellExecute" },
- { 3, "Execute" },
- { 3, "GetFileTime" },
- { 3, "GetDLLVersion" },
- { 3, "RegisterDLL" },
- { 5, "CreateShortCut" },
- { 3, "CopyFiles" },
- { 0, "Reboot" },
- { 4, "WriteINIStr" },
- { 4, "ReadINIStr" },
-
- { 4, "DelReg" },
- { 5, "WriteReg" },
- { 5, "ReadRegStr" },
- { 5, "RegEnum" },
- { 1, "FileClose" },
- { 4, "FileOpen" },
- { 3, "FileWrite" },
- { 4, "FileRead" },
- { 4, "FileSeek" },
- { 1, "FindClose" },
-
- { 2, "FindNext" },
- { 2, "FindFirst" },
- { 3, "WriteUninstaller" },
- { 2, "LogText" },
- { 3, "Section?etText" },
- { 3, "InstType?etFlags" },
- { 6, "GetLabelAddr" },
- { 2, "GetFunctionAddress" },
- { 6, "LockWindow" }
+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 *k_REBOOTOK = " /REBOOTOK";
+
+#define MY__MB_ABORTRETRYIGNORE 2
+#define MY__MB_RETRYCANCEL 5
+
+static const char *k_MB_Buttons[] =
+{
+ "OK"
+ , "OKCANCEL"
+ , "ABORTRETRYIGNORE"
+ , "YESNOCANCEL"
+ , "YESNO"
+ , "RETRYCANCEL"
+ , "CANCELTRYCONTINUE"
};
-#endif
+#define MY__MB_ICONSTOP (1 << 4)
-static const char *kShellStrings[] =
+static const char *k_MB_Icons[] =
+{
+ NULL
+ , "ICONSTOP"
+ , "ICONQUESTION"
+ , "ICONEXCLAMATION"
+ , "ICONINFORMATION"
+};
+
+static const char *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 *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 UInt32 ConvertHexStringToUInt32(const char *s, const char **end)
+{
+ UInt32 result = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ char c = *s;
+ UInt32 v;
+ if (c >= '0' && c <= '9') v = (c - '0');
+ else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
+ else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
+ else
+ {
+ if (end != NULL)
+ *end = s;
+ return result;
+ }
+ result <<= 4;
+ result |= v;
+ s++;
+ }
+ if (end != NULL)
+ *end = s;
+ return 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 *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)
{
- "",
- "",
-
- "SMPROGRAMS",
- "",
- "PRINTERS",
- "DOCUMENTS",
- "FAVORITES",
- "SMSTARTUP",
- "RECENT",
- "SENDTO",
- "",
- "STARTMENU",
- "",
- "MUSIC",
- "VIDEO",
- "",
-
- "DESKTOP",
- "",
- "",
- "NETHOOD",
- "FONTS",
- "TEMPLATES",
- "COMMONSTARTMENU",
- "COMMONFILES",
- "COMMON_STARTUP",
- "COMMON_DESKTOPDIRECTORY",
- "QUICKLAUNCH",
- "PRINTHOOD",
- "LOCALAPPDATA",
- "ALTSTARTUP",
- "ALTSTARTUP",
- "FAVORITES",
-
- "INTERNET_CACHE",
- "COOKIES",
- "HISTORY",
- "APPDATA",
- "WINDIR",
- "SYSDIR",
- "PROGRAMFILES",
- "PICTURES",
- "PROFILE",
- "",
- "",
- "COMMONFILES",
- "",
- "TEMPLATES",
- "DOCUMENTS",
- "ADMINTOOLS",
-
- "ADMINTOOLS",
- "",
- "",
- "",
- "",
- "MUSIC",
- "PICTURES",
- "VIDEO",
- "RESOURCES",
- "RESOURCES_LOCALIZED",
- "",
- "CDBURN_AREA"
+ 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 **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,
};
-static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]);
+// Names for NSIS exec_flags_t structure vars
+static const char *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 CMDLINE 20 // everything before here doesn't have trailing slash removal
-# define INSTDIR 21
-# define OUTDIR 22
-# define EXEDIR 23
-# define LANGUAGE 24
-# define TEMP 25
-# define PLUGINSDIR 26
-# define HWNDPARENT 27
-# define _CLICK 28
-# define _OUTDIR 29
+#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
*/
-static const char *kVarStrings[] =
+// page window proc
+enum
+{
+ PWP_LICENSE,
+ PWP_SELCOM,
+ PWP_DIR,
+ PWP_INSTFILES,
+ PWP_UNINST,
+ PWP_COMPLETED,
+ PWP_CUSTOM
+};
+
+static const char *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 *kSection_VarsNames[] =
{
- "CMDLINE",
- "INSTDIR",
- "OUTDIR",
- "EXEDIR",
- "LANGUAGE",
- "TEMP",
- "PLUGINSDIR",
- "EXEPATH", // test it
- "EXEFILE", // test it
- "HWNDPARENT",
- "_CLICK",
- "_OUTDIR"
+ "Text"
+ , "InstTypes"
+ , "Flags"
+ , "Code"
+ , "CodeSize"
+ , "Size" // size in KB
};
-static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]);
+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)
-static AString GetVar(UInt32 index)
+bool CInArchive::PrintSectionBegin(const CSection &sect, unsigned index)
{
- AString res = "$";
- if (index < 10)
- res += UIntToString(index);
- else if (index < 20)
+ AString name;
+ if (sect.Flags & SF_BOLD)
+ name += '!';
+ AString s2;
+ ReadString2(s2, sect.Name);
+ if (!IsInstaller)
{
- res += "R";
- res += UIntToString(index - 10);
+ if (!StringsAreEqualNoCase_Ascii(s2, "uninstall"))
+ name += "un.";
}
- else if (index < 20 + kNumVarStrings)
- res += kVarStrings[index - 20];
+ 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)
{
- res += "[";
- res += UIntToString(index);
- res += "]";
+ // probably we must show AddSize, only if there is additional size.
+ Tab();
+ AddCommentAndString("AddSize");
+ AddParam_UInt(sect.SizeKB);
+ AddLF();
}
- return res;
+
+ 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;
}
-#define NS_SKIP_CODE 252
-#define NS_VAR_CODE 253
-#define NS_SHELL_CODE 254
-#define NS_LANG_CODE 255
-#define NS_CODES_START NS_SKIP_CODE
+void CInArchive::PrintSectionEnd()
+{
+ AddStringLF("SectionEnd");
+ AddLF();
+}
+
+// static const unsigned kOnFuncShift = 4;
-static AString GetShellString(int index)
+void CInArchive::ClearLangComment()
{
- AString res = "$";
- if (index < kNumShellStrings)
+ 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())
{
- const char *sz = kShellStrings[index];
- if (sz[0] != 0)
- return res + sz;
+ 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();
}
- res += "SHELL[";
- res += UIntToString(index);
- res += "]";
- return res;
+ AddLF();
}
-// Based on Dave Laundon's simplified process_string
-AString GetNsisString(const AString &s)
+static const UInt32 kPageSize = 16 * 4;
+
+static const char *k_SetOverwrite_Modes[] =
+{
+ "on"
+ , "off"
+ , "try"
+ , "ifnewer"
+ , "ifdiff"
+ // "lastused"
+};
+
+
+void CInArchive::MessageBox_MB_Part(UInt32 param)
{
- AString res;
- for (int i = 0; i < s.Length();)
{
- unsigned char nVarIdx = s[i++];
- if (nVarIdx > NS_CODES_START && i + 2 <= s.Length())
+ UInt32 v = param & 0xF;
+ Script += " MB_";
+ if (v < ARRAY_SIZE(k_MB_Buttons))
+ Script += k_MB_Buttons[v];
+ else
{
- int nData = s[i++] & 0x7F;
- unsigned char c1 = s[i++];
- nData |= (((int)(c1 & 0x7F)) << 7);
+ 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 (int 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)
+{
+ if (!dest.IsEmpty())
+ dest += ' ';
+ 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 (nVarIdx == NS_SHELL_CODE)
- res += GetShellString(c1);
- else if (nVarIdx == NS_VAR_CODE)
- res += GetVar(nData);
- else if (nVarIdx == NS_LANG_CODE)
- res += "NS_LANG_CODE";
+ 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;
}
- else if (nVarIdx == NS_SKIP_CODE)
+
+ if (a >= EW_SECTIONSET && LogCmdIsEnabled)
{
- if (i < s.Length())
- res += s[i++];
+ if (a == EW_SECTIONSET)
+ return EW_LOG;
+ return a - 1;
}
- else // Normal char
- res += (char)nVarIdx;
+ if (a == EW_FPUTWS)
+ return EW_FINDPROC;
+ // if (a > EW_FPUTWS) return 0;
}
- return res;
+ return a;
}
-UString GetNsisString(const UString &s)
+void CInArchive::FindBadCmd(const CBlockHeader &bh, const Byte *p)
{
- UString res;
- for (int i = 0; i < s.Length();)
+ BadCmd = -1;
+
+ for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)
{
- wchar_t nVarIdx = s[i++];
- if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END)
+ 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)
{
- if (i == s.Length())
+ BadCmd = id;
+ continue;
+ }
+ for (i = 6; i != 0; i--)
+ {
+ UInt32 param = Get32(p + i * 4);
+ if (param != 0)
break;
- int nData = s[i++] & 0x7FFF;
+ }
+ if (id == EW_FINDPROC && i == 0)
+ {
+ BadCmd = id;
+ continue;
+ }
+ if (k_Commands[id].NumParams < i)
+ BadCmd = id;
+ }
+}
- if (nVarIdx == NS_UN_SHELL_CODE)
- res += GetUnicodeString(GetShellString(nData >> 8));
- else if (nVarIdx == NS_UN_VAR_CODE)
- res += GetUnicodeString(GetVar(nData));
- else if (nVarIdx == NS_UN_LANG_CODE)
- res += L"NS_LANG_CODE";
+/* 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 if (nVarIdx == NS_UN_SKIP_CODE)
+ else
{
- if (i == s.Length())
- break;
- res += s[i++];
+ 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);
}
- else // Normal char
- res += (char)nVarIdx;
}
- return res;
}
-AString CInArchive::ReadString2A(UInt32 pos) const
+Int32 CInArchive::GetVarIndex(UInt32 strPos) const
{
- return GetNsisString(ReadStringA(pos));
+ 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);
}
-UString CInArchive::ReadString2U(UInt32 pos) const
+Int32 CInArchive::GetVarIndex(UInt32 strPos, UInt32 &resOffset) const
{
- return GetNsisString(ReadStringU(pos));
+ 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;
}
-AString CInArchive::ReadString2(UInt32 pos) const
+Int32 CInArchive::GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const
{
+ resOffset = 0;
+ Int32 varIndex = GetVarIndex(strPos);
+ if (varIndex < 0)
+ return varIndex;
if (IsUnicode)
- return UnicodeStringToMultiByte(ReadString2U(pos));
+ {
+ if (NumStringChars - strPos < 3 * 2)
+ return -1;
+ const Byte *p = _data + _stringsPos + strPos * 2;
+ if (Get16(p + 4) != endChar)
+ return -1;
+ resOffset = 3;
+ }
else
- return ReadString2A(pos);
+ {
+ if (NumStringChars - strPos < 4)
+ return -1;
+ const Byte *p = _data + _stringsPos + strPos;
+ if (p[3] != endChar)
+ return -1;
+ resOffset = 4;
+ }
+ return varIndex;
}
-AString CInArchive::ReadString2Qw(UInt32 pos) const
+bool CInArchive::IsVarStr(UInt32 strPos, UInt32 varIndex) const
{
- return "\"" + ReadString2(pos) + "\"";
+ if (varIndex > (UInt32)0x7FFF)
+ return false;
+ UInt32 resOffset;
+ return GetVarIndexFinished(strPos, 0, resOffset) == (Int32)varIndex;
}
-#define DEL_DIR 1
-#define DEL_RECURSE 2
-#define DEL_REBOOT 4
-// #define DEL_SIMPLE 8
+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')
-static const int kNumEntryParams = 6;
+// 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);
+}
-struct CEntry
+void CInArchive::SetItemName(CItem &item, UInt32 strPos)
{
- UInt32 Which;
- UInt32 Params[kNumEntryParams];
- AString GetParamsString(int numParams);
- CEntry()
+ ReadString2_Raw(strPos);
+ bool isAbs = IsAbsolutePathVar(strPos);
+ if (IsUnicode)
{
- Which = 0;
- for (UInt32 j = 0; j < kNumEntryParams; j++)
- Params[j] = 0;
+ 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;
+ }
+}
-AString CEntry::GetParamsString(int numParams)
+HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
{
- AString s;
- for (int i = 0; i < numParams; i++)
+ #ifdef NSIS_SCRIPT
+ CDynLimBuf &s = Script;
+
+ CObjArray<UInt32> labels;
+ labels.Alloc(bh.Num);
+ memset(labels, 0, bh.Num * sizeof(UInt32));
+
{
- s += " ";
- UInt32 v = Params[i];
- if (v > 0xFFF00000)
- s += IntToString((Int32)Params[i]);
+ 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
- s += UIntToString(Params[i]);
+ {
+
+ 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();
+ }
+ }
}
- return s;
-}
-#ifdef NSIS_SCRIPT
+ CObjArray<CSection> Sections;
-static AString GetRegRootID(UInt32 val)
-{
- 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:
- return UIntToString(val); break;
+ 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 &section = Sections[i];
+ section.Parse(p);
+ if (section.StartCmdIndex < bh.Num)
+ labels[section.StartCmdIndex] |= CMD_REF_Section;
+ }
+ }
}
- return s;
-}
-#endif
+ #endif
-HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
-{
- _posInData = bh.Offset + GetOffset();
- AString prefixA;
- UString prefixU;
- for (UInt32 i = 0; i < bh.Num; i++)
+ 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 (int 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)
{
- CEntry e;
- e.Which = ReadUInt32();
- for (UInt32 j = 0; j < kNumEntryParams; j++)
- e.Params[j] = ReadUInt32();
+ 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
- if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+
+ bool IsSectionGroup = false;
+ while (curSectionIndex < bhSections.Num)
{
- const CCommandPair &pair = kCommandPairs[e.Which];
- Script += pair.Name;
+ const CSection &sect = 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 (e.Which)
+ switch (commandId)
{
case EW_CREATEDIR:
{
- if (IsUnicode)
+ bool isSetOutPath = (params[1] != 0);
+
+ if (isSetOutPath)
{
- prefixU.Empty();
- prefixU = ReadString2U(e.Params[0]);
+ 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);
+ }
}
- else
+
+ #ifdef NSIS_SCRIPT
+ s += isSetOutPath ? "SetOutPath" : "CreateDirectory";
+ AddParam(params[0]);
+ #endif
+
+ break;
+ }
+
+
+ case EW_ASSIGNVAR:
+ {
+ if (params[0] == spec_outdir_VarIndex)
{
- prefixA.Empty();
- prefixA = ReadString2A(e.Params[0]);
+ 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
- Script += " ";
- if (IsUnicode)
- Script += UnicodeStringToMultiByte(prefixU);
- else
- Script += prefixA;
+
+ 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;
- item.IsUnicode = IsUnicode;
- if (IsUnicode)
+ 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
+
{
- item.PrefixU = prefixU;
- item.NameU = ReadString2U(e.Params[1]);
+ 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);
+ }
}
- else
+
{
- item.PrefixA = prefixA;
- item.NameA = ReadString2A(e.Params[1]);
+ 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;
+ }
}
- /* UInt32 overwriteFlag = e.Params[0]; */
- item.Pos = e.Params[2];
- item.MTime.dwLowDateTime = e.Params[3];
- item.MTime.dwHighDateTime = e.Params[4];
- /* UInt32 allowIgnore = e.Params[5]; */
- if (Items.Size() > 0)
+
+ 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
{
- /*
- if (item.Pos == Items.Back().Pos)
- continue;
- */
+ // 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
+ {
+ ReadString2_Raw(pars[1]);
+ if (IsUnicode)
+ {
+ if (!Raw_UString.IsEmpty())
+ item.NameU = Raw_UString;
+ }
+ else
+ {
+ if (!Raw_AString.IsEmpty())
+ item.NameA = Raw_AString;
+ }
+ }
+ }
+ }
}
- Items.Add(item);
- #ifdef NSIS_SCRIPT
- Script += " ";
+ /* UInt32 allowIgnore = params[5]; */
+ break;
+ }
- if (IsUnicode)
- Script += UnicodeStringToMultiByte(item.NameU);
- else
- Script += item.NameA;
+ 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]);
+
+ SmallSpaceComment();
+
+ /*
+ for (int i = 1; i < 3; i++)
+ AddParam_UInt(params[i]);
+ */
+
+ if (params[3] != 0)
+ 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 &sect = 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 * (kkk - j);
+ 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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += UIntToString(e.Params[1]);
+ AddParam(params[0]);
break;
}
- case EW_SETFILEATTRIBUTES:
+
+ case EW_CHDETAILSVIEW:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += UIntToString(e.Params[1]);
+ 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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += UIntToString(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ AddParam(params[0]);
+ Add_GotoVars2(&params[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(&params[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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ 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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ if (params[2] == 0)
+ s += " /SHORT";
+ AddParam_Var(params[1]);
+ AddParam(params[0]);
break;
}
+
case EW_SEARCHPATH:
+ case EW_STRLEN:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
+ AddParam_Var(params[0]);
+ AddParam(params[1]);
break;
}
+
case EW_GETTEMPFILENAME:
{
- AString s;
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
+ AddParam_Var(params[0]);
+ AString temp;
+ ReadString2(temp, params[1]);
+ if (temp != "$TEMP")
+ SpaceQuStr(temp);
break;
}
case EW_DELETEFILE:
{
- UInt64 flag = e.Params[1];
- if (flag != 0)
+ 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]);
{
- Script += " ";
- if (flag == DEL_REBOOT)
- Script += "/REBOOTOK";
- else
- Script += UIntToString(e.Params[1]);
+ UInt32 buttonID = (params[0] >> 21); // NSIS 2.06+
+ if (buttonID != 0)
+ {
+ s += " /SD";
+ Add_ButtonID(buttonID);
+ }
}
- Script += " ";
- Script += ReadString2(e.Params[0]);
+ 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:
{
- UInt64 flag = e.Params[1];
- if (flag != 0)
+ 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(&params[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() == '%')
{
- if ((flag & DEL_REBOOT) != 0)
- Script += " /REBOOTOK";
- if ((flag & DEL_RECURSE) != 0)
- Script += " /r";
+ temp.DeleteBack();
+ temp.Delete(0);
}
- Script += " ";
- Script += ReadString2(e.Params[0]);
+ SpaceQuStr(temp);
break;
}
- case EW_STRLEN:
+
+ case EW_INTCMP:
{
- Script += " ";
- Script += GetVar(e.Params[0]);;
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
+ 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_ASSIGNVAR:
+
+ case EW_INTOP:
{
- Script += " ";
- Script += GetVar(e.Params[0]);;
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
- AString maxLen, startOffset;
- if (e.Params[2] != 0)
- maxLen = ReadString2(e.Params[2]);
- if (e.Params[3] != 0)
- startOffset = ReadString2(e.Params[3]);
- if (!maxLen.IsEmpty() || !startOffset.IsEmpty())
- {
- Script += " ";
- if (maxLen.IsEmpty())
- Script += "\"\"";
- else
- Script += maxLen;
- if (!startOffset.IsEmpty())
+ 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)
{
- Script += " ";
- Script += startOffset;
+ 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_STRCMP:
+
+ case EW_FINDWINDOW:
{
- Script += " ";
+ AddParam_Var(params[0]);
+ AddParam(params[1]);
+ AddOptionalParams(params + 2, 3);
+ break;
+ }
- Script += " ";
- Script += ReadString2Qw(e.Params[0]);
+ 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);
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
+ 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);
+ }
- for (int j = 2; j < 5; j++)
+ if ((Int32)params[0] >= 0)
+ AddParam_Var(params[0]);
+
+ spec >>= 2;
+ if (spec != 0)
{
- Script += " ";
- Script += UIntToString(e.Params[j]);
+ s += " /TIMEOUT=";
+ Add_UInt(spec);
}
break;
}
- case EW_INTCMP:
+
+ case EW_ISWINDOW:
{
- if (e.Params[5] != 0)
- Script += "U";
+ AddParam(params[0]);
+ Add_GotoVars2(&params[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;
+ }
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
+ const Byte *p2 = _data + bhCtlColors.Offset + offset;
+ CNsis_CtlColors colors;
+ colors.Parse(p2);
- for (int i = 2; i < 5; i++)
+ 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)
{
- Script += " ";
- Script += UIntToString(e.Params[i]);
+ 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_INTOP:
+
+ case EW_SETBRANDINGIMAGE:
{
- Script += " ";
- Script += GetVar(e.Params[0]);
- Script += " ";
- int numOps = 2;
- AString op;
- switch (e.Params[3])
- {
- case 0: op = '+'; break;
- case 1: op = '-'; break;
- case 2: op = '*'; break;
- case 3: op = '/'; break;
- case 4: op = '|'; break;
- case 5: op = '&'; break;
- case 6: op = '^'; break;
- case 7: op = '~'; numOps = 1; break;
- case 8: op = '!'; numOps = 1; break;
- case 9: op = "||"; break;
- case 10: op = "&&"; break;
- case 11: op = '%'; break;
- default: op = UIntToString(e.Params[3]);
- }
- AString p1 = ReadString2(e.Params[1]);
- if (numOps == 1)
- {
- Script += op;
- Script += p1;
- }
+ 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
{
- Script += p1;
- Script += " ";
- Script += op;
- Script += " ";
- Script += ReadString2(e.Params[2]);
+ 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_PUSHPOP:
+ case EW_SHELLEXEC:
{
- int isPop = (e.Params[1] != 0);
- if (isPop)
+ AddParams(params, 2);
+ if (params[2] != 0 || params[3] != MY__SW_SHOWNORMAL)
{
- Script += "Pop";
- Script += " ";
- Script += GetVar(e.Params[0]);;
+ 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
{
- int isExch = (e.Params[2] != 0);
- if (isExch)
+ if (func == "DllUnregisterServer")
{
- Script += "Exch";
+ s += "UnRegDLL";
+ printFunc = false;
}
else
{
- Script += "Push";
- Script += " ";
- Script += ReadString2(e.Params[0]);
+ s += "RegDLL";
+ if (func == "DllRegisterServer")
+ printFunc = false;
}
+ AddParam(params[0]);
}
+ if (printFunc)
+ SpaceQuStr(func);
break;
}
- case EW_SENDMESSAGE:
+ case EW_CREATESHORTCUT:
{
- // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
- Script += " ";
- // Script += ReadString2(e.Params[0]);
- // Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += ReadString2(e.Params[2]);
-
- Script += " ";
- UInt32 spec = e.Params[5];
- // if (spec & 1)
- Script += IntToString(e.Params[3]);
- // else
- // Script += ReadString2(e.Params[3]);
+ 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);
- Script += " ";
- // if (spec & 2)
- Script += IntToString(e.Params[4]);
- // else
- // Script += ReadString2(e.Params[4]);
+ UInt32 modKey = spec >> 24;
+ UInt32 key = (spec >> 16) & 0xFF;
- if ((Int32)e.Params[0] >= 0)
+ if (modKey == 0 && key == 0)
{
- Script += " ";
- Script += GetVar(e.Params[1]);
+ if (numParams < 6)
+ break;
+ Space();
+ AddQuotes();
}
-
- spec >>= 2;
- if (spec != 0)
+ else
{
- Script += " /TIMEOUT=";
- Script += IntToString(spec);
+ 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_GETDLGITEM:
+ case EW_COPYFILES:
{
- Script += " ";
- Script += GetVar(e.Params[0]);;
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += ReadString2(e.Params[2]);
+ 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_REGISTERDLL:
+ case EW_REBOOT:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ if (params[0] != 0xbadf00d)
+ s += " ; Corrupted ???";
+ else if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_QUIT)
+ endCommentIndex = kkk + 2;
break;
}
- case EW_CREATESHORTCUT:
+ case EW_WRITEINI:
{
- AString s;
-
- Script += " ";
- Script += ReadString2Qw(e.Params[0]);
+ 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;
+ }
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
+ case EW_READINISTR:
+ {
+ AddParam_Var(params[0]);
+ AddParam(params[3]); // FileName
+ AddParams(params +1, 2); // Section, EntryName
+ break;
+ }
- for (int j = 2; j < 5; j++)
+ case EW_DELREG:
+ {
+ // NSIS 2.00 used another scheme!
+
+ if (params[4] == 0)
+ s += "Value";
+ else
{
- Script += " ";
- Script += UIntToString(e.Params[j]);
+ s += "Key";
+ if (params[4] & 2)
+ s += " /ifempty";
}
+ AddRegRoot(params[1]);
+ AddParam(params[2]);
+ AddOptionalParam(params[3]);
break;
}
- /*
- case EW_DELREG:
+ case EW_WRITEREG:
{
- AString keyName, valueName;
- keyName = ReadString2(e.Params[1]);
- bool isValue = (e.Params[2] != -1);
- if (isValue)
+ const char *s2 = 0;
+ switch (params[4])
{
- valueName = ReadString2(e.Params[2]);
- Script += "Key";
+ 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
- Script += "Value";
- Script += " ";
- Script += UIntToString(e.Params[0]);
- Script += " ";
- Script += keyName;
- if (isValue)
{
- Script += " ";
- Script += valueName;
+ // 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";
+ }
}
- Script += " ";
- Script += UIntToString(e.Params[3]);
break;
}
- */
- case EW_WRITEREG:
+ 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:
{
- AString s;
- switch(e.Params[4])
+ 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)
{
- case 1: s = "Str"; break;
- case 2: s = "ExpandStr"; break;
- case 3: s = "Bin"; break;
- case 4: s = "DWORD"; break;
- default: s = "?" + UIntToString(e.Params[4]); break;
+ Space();
+ s += cc;
+ break;
}
- Script += s;
- Script += " ";
- Script += GetRegRootID(e.Params[0]);
- Script += " ";
- AString keyName, valueName;
- keyName = ReadString2Qw(e.Params[1]);
- Script += keyName;
- Script += " ";
+ 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";
- valueName = ReadString2Qw(e.Params[2]);
- Script += valueName;
- Script += " ";
+ 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;
+ }
- valueName = ReadString2Qw(e.Params[3]);
- Script += valueName;
- Script += " ";
+ 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_WRITEUNINSTALLER:
+ case EW_FSEEK:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- for (int j = 1; j < 3; j++)
+ 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)
{
- Script += " ";
- Script += UIntToString(e.Params[j]);
+ if (params[3] == 0) s += " SET"; // FILE_BEGIN
+ AddParam_Var(params[1]);
}
break;
}
- default:
+ 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:
{
- int numParams = kNumEntryParams;
- if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+ if (params[0] != 0)
{
- const CCommandPair &pair = kCommandPairs[e.Which];
- // Script += pair.Name;
- numParams = pair.NumParams;
+ s += "Set ";
+ s += (params[1] == 0) ? "off" : "on";
}
else
{
- Script += "Unknown";
- Script += UIntToString(e.Which);
+ s += "Text";
+ AddParam(params[1]);
}
- Script += e.GetParamsString(numParams);
+ }
+
+ 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
- Script += kCrLf;
+
+ 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 &sect = Sections[curSectionIndex];
+ if (sect.StartCmdIndex + sect.NumCommands + 1 == kkk)
+ {
+ PrintSectionEnd();
+ sectionIsOpen = false;
+ // lastSectionEndCmd = kkk;
+ curSectionIndex++;
+ }
+ }
+ }
+
+ while (curSectionIndex < bhSections.Num)
+ {
+ const CSection &sect = 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, 0);
- int i;
- // if (IsSolid)
- for (i = 0; i + 1 < Items.Size();)
+ Items.Sort(CompareItems, (void *)this);
+ unsigned i;
+
+ for (i = 0; i + 1 < Items.Size(); i++)
{
- bool sameName = IsUnicode ?
- (Items[i].NameU == Items[i + 1].NameU) :
- (Items[i].NameA == Items[i + 1].NameA);
- if (Items[i].Pos == Items[i + 1].Pos && sameName)
- Items.Delete(i + 1);
+ 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
- i++;
+ {
+ 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 (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
+ for (unsigned nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
{
UInt32 nextPos = Items[nextIndex].Pos;
if (curPos <= nextPos)
{
- item.EstimatedSizeIsDefined = true;
+ 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 + 5;
+ 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 & 0x80000000) != 0)
+ if ((size & kMask_IsCompressed) != 0)
{
item.IsCompressed = true;
- // is compressed;
- size &= ~0x80000000;
+ size &= ~kMask_IsCompressed;
if (Method == NMethodType::kLZMA)
{
if (processedSize < 9)
return S_FALSE;
+ /*
if (FilterFlag)
item.UseFilter = (sig[4] != 0);
- item.DictionarySize = Get32(sig + 5 + (FilterFlag ? 1 : 0));
+ */
+ item.DictionarySize = Get32(sig + 4 + 1 + (FilterFlag ? 1 : 0));
}
}
else
{
item.IsCompressed = false;
item.Size = size;
- item.SizeIsDefined = true;
+ item.Size_Defined = true;
}
item.CompressedSize = size;
- item.CompressedSizeIsDefined = true;
+ 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 *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.HeaderLength
- /* UInt32 ehFlags = */ ReadUInt32();
- CBlockHeader bhPages, bhSections, bhEntries, bhStrings, bhLangTables, bhCtlColors, bhData;
- // CBlockHeader bgFont;
- ReadBlockHeader(bhPages);
- ReadBlockHeader(bhSections);
- ReadBlockHeader(bhEntries);
- ReadBlockHeader(bhStrings);
- ReadBlockHeader(bhLangTables);
- ReadBlockHeader(bhCtlColors);
- // ReadBlockHeader(bgFont);
- ReadBlockHeader(bhData);
+ // ???? 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;
- UInt32 pos = GetOffset() + _stringsPos;
- int numZeros0 = 0;
- int numZeros1 = 0;
- int i;
- const int kBlockSize = 256;
- for (i = 0; i < kBlockSize; i++)
- {
- if (pos >= _size || pos + 1 >= _size)
- break;
- char c0 = _data[pos++];
- char c1 = _data[pos++];
- wchar_t c = (c0 | ((wchar_t)c1 << 8));
+ 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 (c >= NS_UN_CODES_START && c < NS_UN_CODES_END)
+ }
+
+ 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)
{
- if (pos >= _size || pos + 1 >= _size)
- break;
- pos += 2;
- numZeros1++;
+ 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);
+ NewLine();
+ }
+ }
+
+
+ {
+ 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)
+ {
+ 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 + 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)
{
- if (c0 == 0 && c1 != 0)
- numZeros0++;
- if (c1 == 0)
- numZeros1++;
+ 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);
}
- // printf("\nnumZeros0 = %2x %2x", _data[pos + 0], _data[pos + 1]);
+
+ 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();
}
- IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16);
- // printf("\nnumZeros0 = %3d numZeros1 = %3d", numZeros0, numZeros1);
- return ReadEntries(bhEntries);
+
+ {
+ 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);
+ 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)
@@ -1276,7 +5545,7 @@ static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
thereIsFlag = false;
return true;
}
- if (IsLZMA(p + 1, dictionary))
+ if (p[0] <= 1 && IsLZMA(p + 1, dictionary))
{
thereIsFlag = true;
return true;
@@ -1289,92 +5558,131 @@ static bool IsBZip2(const Byte *p)
return (p[0] == 0x31 && p[1] < 14);
}
-HRESULT CInArchive::Open2(
- DECL_EXTERNAL_CODECS_LOC_VARS2
- )
+HRESULT CInArchive::Open2(const Byte *sig, size_t size)
{
- RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &StreamOffset));
-
- const UInt32 kSigSize = 4 + 1 + 5 + 1; // size, flag, lzma props, lzma first byte
- BYTE sig[kSigSize];
- RINOK(ReadStream_FALSE(_stream, sig, kSigSize));
- UInt64 position;
- RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position));
+ 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);
- if (compressedHeaderSize == FirstHeader.HeaderLength)
+
+ /*
+ 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 (IsLZMA(sig + 4, DictionarySize, FilterFlag))
- {
- IsSolid = false;
- Method = NMethodType::kLZMA;
- }
else if (sig[3] == 0x80)
{
IsSolid = false;
- if (IsBZip2(sig + 4))
+ 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;
- }
- _posInData = 0;
- if (!IsSolid)
+ if (IsSolid)
+ {
+ RINOK(_stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL));
+ }
+ else
{
- _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);
- if (_headerIsCompressed)
- compressedHeaderSize &= ~0x80000000;
+ _headerIsCompressed = ((compressedHeaderSize & kMask_IsCompressed) != 0);
+ compressedHeaderSize &= ~kMask_IsCompressed;
_nonSolidStartOffset = compressedHeaderSize;
- RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL));
+ RINOK(_stream->Seek(DataStreamOffset + 4, STREAM_SEEK_SET, NULL));
}
- UInt32 unpackSize = FirstHeader.HeaderLength;
+
+ _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)
{
- // unpackSize = (1 << 23);
- _data.SetCapacity(unpackSize);
- RINOK(Decoder.Init(
- EXTERNAL_CODECS_LOC_VARS
- _stream, Method, FilterFlag, UseFilter));
- size_t processedSize = unpackSize;
+ 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 != unpackSize)
+ if (processedSize != FirstHeader.HeaderSize)
return S_FALSE;
- _size = processedSize;
+
+ #ifdef NSIS_SCRIPT
if (IsSolid)
{
- UInt32 size2 = ReadUInt32();
- if (size2 < _size)
- _size = size2;
+ /* 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
{
- _data.SetCapacity(unpackSize);
- _size = (size_t)unpackSize;
- RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize));
+ 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();
}
@@ -1404,57 +5712,212 @@ FirstHeader
UInt32 Flags;
Byte Signature[16];
// points to the header+sections+entries+stringtable in the datablock
- UInt32 HeaderLength;
- UInt32 ArchiveSize;
+ UInt32 HeaderSize;
+ UInt32 ArcSize;
}
*/
-HRESULT CInArchive::Open(
- DECL_EXTERNAL_CODECS_LOC_VARS
- IInStream *inStream, const UInt64 *maxCheckStartPosition)
+
+// ---------- 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_SET, NULL));
- UInt64 maxSize = ((maxCheckStartPosition != 0) ? *maxCheckStartPosition : 0);
- const UInt32 kStep = 512;
- Byte buffer[kStep];
- UInt64 position = 0;
- for (; position <= maxSize; position += kStep)
+ 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 (;;)
{
- RINOK(ReadStream_FALSE(inStream, buffer, kStep));
- if (memcmp(buffer + 4, kSignature, kSignatureSize) == 0)
+ 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;
+ }
}
- if (position > maxSize)
+
+ DataStreamOffset = pos + kStartHeaderSize;
+ FirstHeader.Flags = Get32(buf);
+ if ((FirstHeader.Flags & (~kFlagsMask)) != 0)
return S_FALSE;
- const UInt32 kStartHeaderSize = 4 * 7;
- RINOK(inStream->Seek(0, STREAM_SEEK_END, &_archiveSize));
- RINOK(inStream->Seek(position + kStartHeaderSize, STREAM_SEEK_SET, 0));
- FirstHeader.Flags = Get32(buffer);
- FirstHeader.HeaderLength = Get32(buffer + kSignatureSize + 4);
- FirstHeader.ArchiveSize = Get32(buffer + kSignatureSize + 8);
- if (_archiveSize - position < FirstHeader.ArchiveSize)
+ 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
{
- _stream = inStream;
- HRESULT res = Open2(EXTERNAL_CODECS_LOC_VARS2);
- if (res != S_OK)
- Clear();
+ 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();
- return res;
+ // Clear();
}
- catch(...) { Clear(); return S_FALSE; }
+ return res;
}
-void CInArchive::Clear()
+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;
+ 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();
}