summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Archive/Nsis/NsisIn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Nsis/NsisIn.cpp')
-rw-r--r--src/libs/7zip/win/CPP/7zip/Archive/Nsis/NsisIn.cpp1461
1 files changed, 1461 insertions, 0 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Nsis/NsisIn.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Nsis/NsisIn.cpp
new file mode 100644
index 000000000..407560085
--- /dev/null
+++ b/src/libs/7zip/win/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -0,0 +1,1461 @@
+// NsisIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/IntToString.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "NsisIn.h"
+
+#define Get32(p) GetUi32(p)
+
+namespace NArchive {
+namespace NNsis {
+
+Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
+
+#ifdef NSIS_SCRIPT
+static const char *kCrLf = "\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
+
+Byte CInArchive::ReadByte()
+{
+ if (_posInData >= _size)
+ throw 1;
+ return _data[_posInData++];
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ value |= ((UInt32)(ReadByte()) << (8 * i));
+ return value;
+}
+
+void CInArchive::ReadBlockHeader(CBlockHeader &bh)
+{
+ bh.Offset = ReadUInt32();
+ bh.Num = ReadUInt32();
+}
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+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));
+ if (i1.IsUnicode)
+ {
+ RINOZ(i1.PrefixU.Compare(i2.PrefixU));
+ RINOZ(i1.NameU.Compare(i2.NameU));
+ }
+ else
+ {
+ RINOZ(i1.PrefixA.Compare(i2.PrefixA));
+ RINOZ(i1.NameA.Compare(i2.NameA));
+ }
+ return 0;
+}
+
+static AString UIntToString(UInt32 v)
+{
+ char sz[32];
+ ConvertUInt64ToString(v, sz);
+ return sz;
+}
+
+static AString IntToString(Int32 v)
+{
+ char sz[32];
+ ConvertInt64ToString(v, sz);
+ return sz;
+}
+
+AString CInArchive::ReadStringA(UInt32 pos) const
+{
+ AString s;
+ if (pos >= _size)
+ return IntToString((Int32)pos);
+ UInt32 offset = GetOffset() + _stringsPos + pos;
+ for (;;)
+ {
+ if (offset >= _size)
+ break; // throw 1;
+ char c = _data[offset++];
+ if (c == 0)
+ break;
+ s += c;
+ }
+ return s;
+}
+
+UString CInArchive::ReadStringU(UInt32 pos) const
+{
+ 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));
+ if (c == 0)
+ break;
+ s += c;
+ }
+ return s;
+}
+
+/*
+static AString ParsePrefix(const AString &prefix)
+{
+ AString res = prefix;
+ if (prefix.Length() >= 3)
+ {
+ 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);
+ }
+ return res;
+}
+*/
+
+#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"
+
+/*
+# 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
+*/
+
+struct CCommandPair
+{
+ int NumParams;
+ const char *Name;
+};
+
+enum
+{
+ // 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,
+
+ EW_LOCKWINDOW
+};
+
+#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" }
+};
+
+#endif
+
+static const char *kShellStrings[] =
+{
+ "",
+ "",
+
+ "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"
+};
+
+static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]);
+
+/*
+# 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
+*/
+
+static const char *kVarStrings[] =
+{
+ "CMDLINE",
+ "INSTDIR",
+ "OUTDIR",
+ "EXEDIR",
+ "LANGUAGE",
+ "TEMP",
+ "PLUGINSDIR",
+ "EXEPATH", // test it
+ "EXEFILE", // test it
+ "HWNDPARENT",
+ "_CLICK",
+ "_OUTDIR"
+};
+
+static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]);
+
+
+static AString GetVar(UInt32 index)
+{
+ AString res = "$";
+ if (index < 10)
+ res += UIntToString(index);
+ else if (index < 20)
+ {
+ res += "R";
+ res += UIntToString(index - 10);
+ }
+ else if (index < 20 + kNumVarStrings)
+ res += kVarStrings[index - 20];
+ else
+ {
+ res += "[";
+ res += UIntToString(index);
+ res += "]";
+ }
+ return res;
+}
+
+#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
+
+static AString GetShellString(int index)
+{
+ AString res = "$";
+ if (index < kNumShellStrings)
+ {
+ const char *sz = kShellStrings[index];
+ if (sz[0] != 0)
+ return res + sz;
+ }
+ res += "SHELL[";
+ res += UIntToString(index);
+ res += "]";
+ return res;
+}
+
+// Based on Dave Laundon's simplified process_string
+AString GetNsisString(const AString &s)
+{
+ AString res;
+ for (int i = 0; i < s.Length();)
+ {
+ unsigned char nVarIdx = s[i++];
+ if (nVarIdx > NS_CODES_START && i + 2 <= s.Length())
+ {
+ int nData = s[i++] & 0x7F;
+ unsigned char c1 = s[i++];
+ nData |= (((int)(c1 & 0x7F)) << 7);
+
+ 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";
+ }
+ else if (nVarIdx == NS_SKIP_CODE)
+ {
+ if (i < s.Length())
+ res += s[i++];
+ }
+ else // Normal char
+ res += (char)nVarIdx;
+ }
+ return res;
+}
+
+UString GetNsisString(const UString &s)
+{
+ UString res;
+ for (int i = 0; i < s.Length();)
+ {
+ wchar_t nVarIdx = s[i++];
+ if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END)
+ {
+ if (i == s.Length())
+ break;
+ int nData = s[i++] & 0x7FFF;
+
+ 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";
+ }
+ else if (nVarIdx == NS_UN_SKIP_CODE)
+ {
+ if (i == s.Length())
+ break;
+ res += s[i++];
+ }
+ else // Normal char
+ res += (char)nVarIdx;
+ }
+ return res;
+}
+
+AString CInArchive::ReadString2A(UInt32 pos) const
+{
+ return GetNsisString(ReadStringA(pos));
+}
+
+UString CInArchive::ReadString2U(UInt32 pos) const
+{
+ return GetNsisString(ReadStringU(pos));
+}
+
+AString CInArchive::ReadString2(UInt32 pos) const
+{
+ if (IsUnicode)
+ return UnicodeStringToMultiByte(ReadString2U(pos));
+ else
+ return ReadString2A(pos);
+}
+
+AString CInArchive::ReadString2Qw(UInt32 pos) const
+{
+ return "\"" + ReadString2(pos) + "\"";
+}
+
+#define DEL_DIR 1
+#define DEL_RECURSE 2
+#define DEL_REBOOT 4
+// #define DEL_SIMPLE 8
+
+static const int kNumEntryParams = 6;
+
+struct CEntry
+{
+ UInt32 Which;
+ UInt32 Params[kNumEntryParams];
+ AString GetParamsString(int numParams);
+ CEntry()
+ {
+ Which = 0;
+ for (UInt32 j = 0; j < kNumEntryParams; j++)
+ Params[j] = 0;
+ }
+};
+
+AString CEntry::GetParamsString(int numParams)
+{
+ AString s;
+ for (int i = 0; i < numParams; i++)
+ {
+ s += " ";
+ UInt32 v = Params[i];
+ if (v > 0xFFF00000)
+ s += IntToString((Int32)Params[i]);
+ else
+ s += UIntToString(Params[i]);
+ }
+ return s;
+}
+
+#ifdef NSIS_SCRIPT
+
+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;
+ }
+ return s;
+}
+
+#endif
+
+HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
+{
+ _posInData = bh.Offset + GetOffset();
+ AString prefixA;
+ UString prefixU;
+ for (UInt32 i = 0; i < bh.Num; i++)
+ {
+ CEntry e;
+ e.Which = ReadUInt32();
+ for (UInt32 j = 0; j < kNumEntryParams; j++)
+ e.Params[j] = ReadUInt32();
+ #ifdef NSIS_SCRIPT
+ if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+ {
+ const CCommandPair &pair = kCommandPairs[e.Which];
+ Script += pair.Name;
+ }
+ #endif
+
+ switch (e.Which)
+ {
+ case EW_CREATEDIR:
+ {
+ if (IsUnicode)
+ {
+ prefixU.Empty();
+ prefixU = ReadString2U(e.Params[0]);
+ }
+ else
+ {
+ prefixA.Empty();
+ prefixA = ReadString2A(e.Params[0]);
+ }
+ #ifdef NSIS_SCRIPT
+ Script += " ";
+ if (IsUnicode)
+ Script += UnicodeStringToMultiByte(prefixU);
+ else
+ Script += prefixA;
+ #endif
+ break;
+ }
+
+ case EW_EXTRACTFILE:
+ {
+ CItem item;
+ item.IsUnicode = IsUnicode;
+ if (IsUnicode)
+ {
+ item.PrefixU = prefixU;
+ item.NameU = ReadString2U(e.Params[1]);
+ }
+ else
+ {
+ item.PrefixA = prefixA;
+ item.NameA = ReadString2A(e.Params[1]);
+ }
+ /* 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)
+ {
+ /*
+ if (item.Pos == Items.Back().Pos)
+ continue;
+ */
+ }
+ Items.Add(item);
+ #ifdef NSIS_SCRIPT
+ Script += " ";
+
+ if (IsUnicode)
+ Script += UnicodeStringToMultiByte(item.NameU);
+ else
+ Script += item.NameA;
+ #endif
+ break;
+ }
+
+
+ #ifdef NSIS_SCRIPT
+ case EW_UPDATETEXT:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += UIntToString(e.Params[1]);
+ break;
+ }
+ case EW_SETFILEATTRIBUTES:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += UIntToString(e.Params[1]);
+ break;
+ }
+ case EW_IFFILEEXISTS:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += UIntToString(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+ case EW_RENAME:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+ case EW_GETFULLPATHNAME:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+ case EW_SEARCHPATH:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ break;
+ }
+ case EW_GETTEMPFILENAME:
+ {
+ AString s;
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ break;
+ }
+
+ case EW_DELETEFILE:
+ {
+ UInt64 flag = e.Params[1];
+ if (flag != 0)
+ {
+ Script += " ";
+ if (flag == DEL_REBOOT)
+ Script += "/REBOOTOK";
+ else
+ Script += UIntToString(e.Params[1]);
+ }
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ break;
+ }
+ case EW_RMDIR:
+ {
+ UInt64 flag = e.Params[1];
+ if (flag != 0)
+ {
+ if ((flag & DEL_REBOOT) != 0)
+ Script += " /REBOOTOK";
+ if ((flag & DEL_RECURSE) != 0)
+ Script += " /r";
+ }
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ break;
+ }
+ case EW_STRLEN:
+ {
+ Script += " ";
+ Script += GetVar(e.Params[0]);;
+ Script += " ";
+ Script += ReadString2Qw(e.Params[1]);
+ break;
+ }
+ case EW_ASSIGNVAR:
+ {
+ 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())
+ {
+ Script += " ";
+ Script += startOffset;
+ }
+ }
+ break;
+ }
+ case EW_STRCMP:
+ {
+ Script += " ";
+
+ Script += " ";
+ Script += ReadString2Qw(e.Params[0]);
+
+ Script += " ";
+ Script += ReadString2Qw(e.Params[1]);
+
+ for (int j = 2; j < 5; j++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[j]);
+ }
+ break;
+ }
+ case EW_INTCMP:
+ {
+ if (e.Params[5] != 0)
+ Script += "U";
+
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+
+ for (int i = 2; i < 5; i++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[i]);
+ }
+ break;
+ }
+ case EW_INTOP:
+ {
+ 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;
+ }
+ else
+ {
+ Script += p1;
+ Script += " ";
+ Script += op;
+ Script += " ";
+ Script += ReadString2(e.Params[2]);
+ }
+ break;
+ }
+
+ case EW_PUSHPOP:
+ {
+ int isPop = (e.Params[1] != 0);
+ if (isPop)
+ {
+ Script += "Pop";
+ Script += " ";
+ Script += GetVar(e.Params[0]);;
+ }
+ else
+ {
+ int isExch = (e.Params[2] != 0);
+ if (isExch)
+ {
+ Script += "Exch";
+ }
+ else
+ {
+ Script += "Push";
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ }
+ }
+ break;
+ }
+
+ case EW_SENDMESSAGE:
+ {
+ // 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]);
+
+ Script += " ";
+ // if (spec & 2)
+ Script += IntToString(e.Params[4]);
+ // else
+ // Script += ReadString2(e.Params[4]);
+
+ if ((Int32)e.Params[0] >= 0)
+ {
+ Script += " ";
+ Script += GetVar(e.Params[1]);
+ }
+
+ spec >>= 2;
+ if (spec != 0)
+ {
+ Script += " /TIMEOUT=";
+ Script += IntToString(spec);
+ }
+ break;
+ }
+
+ case EW_GETDLGITEM:
+ {
+ Script += " ";
+ Script += GetVar(e.Params[0]);;
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += ReadString2(e.Params[2]);
+ break;
+ }
+
+
+ case EW_REGISTERDLL:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+
+ case EW_CREATESHORTCUT:
+ {
+ AString s;
+
+ Script += " ";
+ Script += ReadString2Qw(e.Params[0]);
+
+ Script += " ";
+ Script += ReadString2Qw(e.Params[1]);
+
+ for (int j = 2; j < 5; j++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[j]);
+ }
+ break;
+ }
+
+ /*
+ case EW_DELREG:
+ {
+ AString keyName, valueName;
+ keyName = ReadString2(e.Params[1]);
+ bool isValue = (e.Params[2] != -1);
+ if (isValue)
+ {
+ valueName = ReadString2(e.Params[2]);
+ Script += "Key";
+ }
+ else
+ Script += "Value";
+ Script += " ";
+ Script += UIntToString(e.Params[0]);
+ Script += " ";
+ Script += keyName;
+ if (isValue)
+ {
+ Script += " ";
+ Script += valueName;
+ }
+ Script += " ";
+ Script += UIntToString(e.Params[3]);
+ break;
+ }
+ */
+
+ case EW_WRITEREG:
+ {
+ AString s;
+ switch(e.Params[4])
+ {
+ 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;
+ }
+ Script += s;
+ Script += " ";
+ Script += GetRegRootID(e.Params[0]);
+ Script += " ";
+
+ AString keyName, valueName;
+ keyName = ReadString2Qw(e.Params[1]);
+ Script += keyName;
+ Script += " ";
+
+ valueName = ReadString2Qw(e.Params[2]);
+ Script += valueName;
+ Script += " ";
+
+ valueName = ReadString2Qw(e.Params[3]);
+ Script += valueName;
+ Script += " ";
+
+ break;
+ }
+
+ case EW_WRITEUNINSTALLER:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ for (int j = 1; j < 3; j++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[j]);
+ }
+ break;
+ }
+
+ default:
+ {
+ int numParams = kNumEntryParams;
+ if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+ {
+ const CCommandPair &pair = kCommandPairs[e.Which];
+ // Script += pair.Name;
+ numParams = pair.NumParams;
+ }
+ else
+ {
+ Script += "Unknown";
+ Script += UIntToString(e.Which);
+ }
+ Script += e.GetParamsString(numParams);
+ }
+ #endif
+ }
+ #ifdef NSIS_SCRIPT
+ Script += kCrLf;
+ #endif
+ }
+
+ {
+ Items.Sort(CompareItems, 0);
+ int i;
+ // if (IsSolid)
+ for (i = 0; i + 1 < Items.Size();)
+ {
+ 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);
+ else
+ 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++)
+ {
+ UInt32 nextPos = Items[nextIndex].Pos;
+ if (curPos <= nextPos)
+ {
+ item.EstimatedSizeIsDefined = 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;
+ 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)
+ {
+ item.IsCompressed = true;
+ // is compressed;
+ size &= ~0x80000000;
+ 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));
+ }
+ }
+ else
+ {
+ item.IsCompressed = false;
+ item.Size = size;
+ item.SizeIsDefined = true;
+ }
+ item.CompressedSize = size;
+ item.CompressedSizeIsDefined = true;
+ }
+ }
+ }
+ return S_OK;
+}
+
+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);
+
+ _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 (c >= NS_UN_CODES_START && c < NS_UN_CODES_END)
+ {
+ if (pos >= _size || pos + 1 >= _size)
+ break;
+ pos += 2;
+ numZeros1++;
+ }
+ else
+ {
+ if (c0 == 0 && c1 != 0)
+ numZeros0++;
+ if (c1 == 0)
+ numZeros1++;
+ }
+ // printf("\nnumZeros0 = %2x %2x", _data[pos + 0], _data[pos + 1]);
+ }
+ IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16);
+ // printf("\nnumZeros0 = %3d numZeros1 = %3d", numZeros0, numZeros1);
+ return ReadEntries(bhEntries);
+}
+
+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);
+}
+
+static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
+{
+ if (IsLZMA(p, dictionary))
+ {
+ thereIsFlag = false;
+ return true;
+ }
+ if (IsLZMA(p + 1, dictionary))
+ {
+ thereIsFlag = true;
+ return true;
+ }
+ return false;
+}
+
+static bool IsBZip2(const Byte *p)
+{
+ return (p[0] == 0x31 && p[1] < 14);
+}
+
+HRESULT CInArchive::Open2(
+ DECL_EXTERNAL_CODECS_LOC_VARS2
+ )
+{
+ 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));
+
+ _headerIsCompressed = true;
+ IsSolid = true;
+ FilterFlag = false;
+ DictionarySize = 1;
+
+ UInt32 compressedHeaderSize = Get32(sig);
+
+ if (compressedHeaderSize == FirstHeader.HeaderLength)
+ {
+ _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))
+ Method = NMethodType::kBZip2;
+ else
+ Method = NMethodType::kDeflate;
+ }
+ else if (IsBZip2(sig))
+ {
+ Method = NMethodType::kBZip2;
+ }
+ else
+ {
+ Method = NMethodType::kDeflate;
+ }
+
+ _posInData = 0;
+ if (!IsSolid)
+ {
+ _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);
+ if (_headerIsCompressed)
+ compressedHeaderSize &= ~0x80000000;
+ _nonSolidStartOffset = compressedHeaderSize;
+ RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL));
+ }
+ UInt32 unpackSize = FirstHeader.HeaderLength;
+ 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.Read(_data, &processedSize));
+ if (processedSize != unpackSize)
+ return S_FALSE;
+ _size = processedSize;
+ if (IsSolid)
+ {
+ UInt32 size2 = ReadUInt32();
+ if (size2 < _size)
+ _size = size2;
+ }
+ }
+ else
+ {
+ _data.SetCapacity(unpackSize);
+ _size = (size_t)unpackSize;
+ RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize));
+ }
+ return Parse();
+}
+
+/*
+NsisExe =
+{
+ ExeStub
+ Archive // must start from 512 * N
+ #ifndef NSIS_CONFIG_CRC_ANAL
+ {
+ Some additional data
+ }
+}
+
+Archive
+{
+ FirstHeader
+ Data
+ #ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc()
+ {
+ CRC
+ }
+}
+
+FirstHeader
+{
+ UInt32 Flags;
+ Byte Signature[16];
+ // points to the header+sections+entries+stringtable in the datablock
+ UInt32 HeaderLength;
+ UInt32 ArchiveSize;
+}
+*/
+
+HRESULT CInArchive::Open(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ 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(ReadStream_FALSE(inStream, buffer, kStep));
+ if (memcmp(buffer + 4, kSignature, kSignatureSize) == 0)
+ break;
+ }
+ if (position > maxSize)
+ 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)
+ return S_FALSE;
+
+ try
+ {
+ _stream = inStream;
+ HRESULT res = Open2(EXTERNAL_CODECS_LOC_VARS2);
+ if (res != S_OK)
+ Clear();
+ _stream.Release();
+ return res;
+ }
+ catch(...) { Clear(); return S_FALSE; }
+}
+
+void CInArchive::Clear()
+{
+ #ifdef NSIS_SCRIPT
+ Script.Empty();
+ #endif
+ Items.Clear();
+ _stream.Release();
+}
+
+}}