1 // NsisIn.h 2 3 #ifndef __ARCHIVE_NSIS_IN_H 4 #define __ARCHIVE_NSIS_IN_H 5 6 #include "../../../../C/CpuArch.h" 7 8 #include "../../../Common/DynLimBuf.h" 9 #include "../../../Common/MyBuffer.h" 10 #include "../../../Common/MyCom.h" 11 #include "../../../Common/StringConvert.h" 12 #include "../../../Common/UTFConvert.h" 13 14 #include "NsisDecode.h" 15 16 /* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file. 17 The code is much larger in that case. */ 18 19 // #define NSIS_SCRIPT 20 21 namespace NArchive { 22 namespace NNsis { 23 24 const size_t kScriptSizeLimit = 1 << 27; 25 26 const unsigned kSignatureSize = 16; 27 extern const Byte kSignature[kSignatureSize]; 28 #define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' } 29 30 const UInt32 kFlagsMask = 0xF; 31 namespace NFlags 32 { 33 const UInt32 kUninstall = 1; 34 const UInt32 kSilent = 2; 35 const UInt32 kNoCrc = 4; 36 const UInt32 kForceCrc = 8; 37 } 38 39 struct CFirstHeader 40 { 41 UInt32 Flags; 42 UInt32 HeaderSize; 43 UInt32 ArcSize; 44 ThereIsCrcCFirstHeader45 bool ThereIsCrc() const 46 { 47 return 48 (Flags & NFlags::kForceCrc) != 0 || 49 (Flags & NFlags::kNoCrc) == 0; 50 } 51 GetDataSizeCFirstHeader52 UInt32 GetDataSize() const { return ArcSize - (ThereIsCrc() ? 4 : 0); } 53 }; 54 55 56 struct CBlockHeader 57 { 58 UInt32 Offset; 59 UInt32 Num; 60 ParseCBlockHeader61 void Parse(const Byte *p) 62 { 63 Offset = GetUi32(p); 64 Num = GetUi32(p + 4); 65 } 66 }; 67 68 struct CItem 69 { 70 bool IsCompressed; 71 bool Size_Defined; 72 bool CompressedSize_Defined; 73 bool EstimatedSize_Defined; 74 bool Attrib_Defined; 75 bool IsUninstaller; 76 // bool UseFilter; 77 78 UInt32 Attrib; 79 UInt32 Pos; 80 UInt32 Size; 81 UInt32 CompressedSize; 82 UInt32 EstimatedSize; 83 UInt32 DictionarySize; 84 UInt32 PatchSize; // for Uninstaller.exe 85 int Prefix; // - 1 means no prefix 86 87 FILETIME MTime; 88 AString NameA; 89 UString NameU; 90 CItemCItem91 CItem(): 92 IsCompressed(true), 93 Size_Defined(false), 94 CompressedSize_Defined(false), 95 EstimatedSize_Defined(false), 96 Attrib_Defined(false), 97 IsUninstaller(false), 98 // UseFilter(false), 99 Attrib(0), 100 Pos(0), 101 Size(0), 102 CompressedSize(0), 103 EstimatedSize(0), 104 DictionarySize(1), 105 PatchSize(0), 106 Prefix(-1) 107 { 108 MTime.dwLowDateTime = 0; 109 MTime.dwHighDateTime = 0; 110 } 111 112 /* 113 bool IsINSTDIR() const 114 { 115 return (PrefixA.Len() >= 3 || PrefixU.Len() >= 3); 116 } 117 */ 118 }; 119 120 enum ENsisType 121 { 122 k_NsisType_Nsis2, 123 k_NsisType_Nsis3, 124 k_NsisType_Park1, // Park 2.46.1- 125 k_NsisType_Park2, // Park 2.46.2 : GetFontVersion 126 k_NsisType_Park3 // Park 2.46.3+ : GetFontName 127 }; 128 129 #ifdef NSIS_SCRIPT 130 131 struct CSection 132 { 133 UInt32 InstallTypes; // bits set for each of the different install_types, if any. 134 UInt32 Flags; // SF_* - defined above 135 UInt32 StartCmdIndex; // code; 136 UInt32 NumCommands; // code_size; 137 UInt32 SizeKB; 138 UInt32 Name; 139 140 void Parse(const Byte *data); 141 }; 142 143 struct CLicenseFile 144 { 145 UInt32 Offset; 146 UInt32 Size; 147 AString Name; 148 CByteBuffer Text; 149 }; 150 151 #endif 152 153 class CInArchive 154 { 155 public: 156 #ifdef NSIS_SCRIPT 157 CDynLimBuf Script; 158 #endif 159 CByteBuffer _data; 160 CObjectVector<CItem> Items; 161 bool IsUnicode; 162 private: 163 UInt32 _stringsPos; // relative to _data 164 UInt32 NumStringChars; 165 size_t _size; // it's Header Size 166 167 AString Raw_AString; 168 UString Raw_UString; 169 170 ENsisType NsisType; 171 bool IsNsis200; // NSIS 2.03 and before 172 bool IsNsis225; // NSIS 2.25 and before 173 174 bool LogCmdIsEnabled; 175 int BadCmd; // -1: no bad command; in another cases lowest bad command id 176 IsPark()177 bool IsPark() const { return NsisType >= k_NsisType_Park1; } 178 179 UInt64 _fileSize; 180 181 bool _headerIsCompressed; 182 UInt32 _nonSolidStartOffset; 183 184 #ifdef NSIS_SCRIPT 185 186 CByteBuffer strUsed; 187 188 CBlockHeader bhPages; 189 CBlockHeader bhSections; 190 CBlockHeader bhCtlColors; 191 CBlockHeader bhData; 192 UInt32 AfterHeaderSize; 193 CByteBuffer _afterHeader; 194 195 UInt32 SectionSize; 196 const Byte *_mainLang; 197 UInt32 _numLangStrings; 198 AString LangComment; 199 CRecordVector<UInt32> langStrIDs; 200 UInt32 numOnFunc; 201 UInt32 onFuncOffset; 202 // CRecordVector<UInt32> OnFuncs; 203 unsigned _numRootLicenses; 204 CRecordVector<UInt32> noParseStringIndexes; 205 AString _tempString_for_GetVar; 206 AString _tempString_for_AddFuncName; 207 AString _tempString; 208 209 #endif 210 211 212 public: 213 CMyComPtr<IInStream> _stream; // it's limited stream that contains only NSIS archive 214 UInt64 StartOffset; // offset in original stream. 215 UInt64 DataStreamOffset; // = sizeof(FirstHeader) = offset of Header in _stream 216 217 bool IsArc; 218 219 CDecoder Decoder; 220 CByteBuffer ExeStub; 221 CFirstHeader FirstHeader; 222 NMethodType::EEnum Method; 223 UInt32 DictionarySize; 224 bool IsSolid; 225 bool UseFilter; 226 bool FilterFlag; 227 228 bool IsInstaller; 229 AString Name; 230 AString BrandingText; 231 UStringVector UPrefixes; 232 AStringVector APrefixes; 233 234 #ifdef NSIS_SCRIPT 235 CObjectVector<CLicenseFile> LicenseFiles; 236 #endif 237 238 private: 239 void GetShellString(AString &s, unsigned index1, unsigned index2); 240 void GetNsisString_Raw(const Byte *s); 241 void GetNsisString_Unicode_Raw(const Byte *s); 242 void ReadString2_Raw(UInt32 pos); 243 bool IsGoodString(UInt32 param) const; 244 bool AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const; 245 246 void Add_LangStr(AString &res, UInt32 id); 247 248 #ifdef NSIS_SCRIPT 249 250 void Add_UInt(UInt32 v); 251 void AddLicense(UInt32 param, Int32 langID); 252 253 void Add_LangStr_Simple(UInt32 id); 254 void Add_FuncName(const UInt32 *labels, UInt32 index); 255 void AddParam_Func(const UInt32 *labels, UInt32 index); 256 void Add_LabelName(UInt32 index); 257 258 void Add_Color2(UInt32 v); 259 void Add_ColorParam(UInt32 v); 260 void Add_Color(UInt32 index); 261 262 void Add_ButtonID(UInt32 buttonID); 263 264 void Add_ShowWindow_Cmd(UInt32 cmd); 265 void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type); 266 void Add_ExecFlags(UInt32 flagsType); 267 void Add_SectOp(UInt32 opType); 268 269 void Add_Var(UInt32 index); 270 void AddParam_Var(UInt32 value); 271 void AddParam_UInt(UInt32 value); 272 273 void Add_GotoVar(UInt32 param); 274 void Add_GotoVar1(UInt32 param); 275 void Add_GotoVars2(const UInt32 *params); 276 277 278 279 bool PrintSectionBegin(const CSection §, unsigned index); 280 void PrintSectionEnd(); 281 282 void GetNsisString(AString &res, const Byte *s); 283 void GetNsisString_Unicode(AString &res, const Byte *s); 284 UInt32 GetNumUsedVars() const; 285 void ReadString2(AString &s, UInt32 pos); 286 287 void MessageBox_MB_Part(UInt32 param); 288 void AddParam(UInt32 pos); 289 void AddOptionalParam(UInt32 pos); 290 void AddParams(const UInt32 *params, unsigned num); 291 void AddPageOption1(UInt32 param, const char *name); 292 void AddPageOption(const UInt32 *params, unsigned num, const char *name); 293 void AddOptionalParams(const UInt32 *params, unsigned num); 294 void AddRegRoot(UInt32 value); 295 296 297 void ClearLangComment(); 298 void Separator(); 299 void Space(); 300 void Tab(); 301 void Tab(bool commented); 302 void BigSpaceComment(); 303 void SmallSpaceComment(); 304 void AddCommentAndString(const char *s); 305 void AddError(const char *s); 306 void AddErrorLF(const char *s); 307 void CommentOpen(); 308 void CommentClose(); 309 void AddLF(); 310 void AddQuotes(); 311 void TabString(const char *s); 312 void AddStringLF(const char *s); 313 void NewLine(); 314 void PrintNumComment(const char *name, UInt32 value); 315 void Add_QuStr(const AString &s); 316 void SpaceQuStr(const AString &s); 317 bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands); 318 319 #endif 320 321 #ifdef NSIS_SCRIPT 322 unsigned GetNumSupportedCommands() const; 323 #endif 324 325 UInt32 GetCmd(UInt32 a); 326 void FindBadCmd(const CBlockHeader &bh, const Byte *); 327 void DetectNsisType(const CBlockHeader &bh, const Byte *); 328 329 HRESULT ReadEntries(const CBlockHeader &bh); 330 HRESULT SortItems(); 331 HRESULT Parse(); 332 HRESULT Open2(const Byte *data, size_t size); 333 void Clear2(); 334 335 void GetVar2(AString &res, UInt32 index); 336 void GetVar(AString &res, UInt32 index); 337 Int32 GetVarIndex(UInt32 strPos) const; 338 Int32 GetVarIndex(UInt32 strPos, UInt32 &resOffset) const; 339 Int32 GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const; 340 bool IsVarStr(UInt32 strPos, UInt32 varIndex) const; 341 bool IsAbsolutePathVar(UInt32 strPos) const; 342 void SetItemName(CItem &item, UInt32 strPos); 343 344 public: 345 HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition); 346 AString GetFormatDescription() const; InitDecoder()347 HRESULT InitDecoder() 348 { 349 bool useFilter; 350 return Decoder.Init(_stream, useFilter); 351 } 352 SeekTo(UInt64 pos)353 HRESULT SeekTo(UInt64 pos) 354 { 355 return _stream->Seek(pos, STREAM_SEEK_SET, NULL); 356 } 357 SeekTo_DataStreamOffset()358 HRESULT SeekTo_DataStreamOffset() 359 { 360 return SeekTo(DataStreamOffset); 361 } 362 SeekToNonSolidItem(unsigned index)363 HRESULT SeekToNonSolidItem(unsigned index) 364 { 365 return SeekTo(GetPosOfNonSolidItem(index)); 366 } 367 368 void Clear(); 369 370 bool IsDirectString_Equal(UInt32 offset, const char *s) const; 371 /* 372 UInt64 GetDataPos(unsigned index) 373 { 374 const CItem &item = Items[index]; 375 return GetOffset() + FirstHeader.HeaderSize + item.Pos; 376 } 377 */ 378 GetPosOfSolidItem(unsigned index)379 UInt64 GetPosOfSolidItem(unsigned index) const 380 { 381 const CItem &item = Items[index]; 382 return 4 + (UInt64)FirstHeader.HeaderSize + item.Pos; 383 } 384 GetPosOfNonSolidItem(unsigned index)385 UInt64 GetPosOfNonSolidItem(unsigned index) const 386 { 387 const CItem &item = Items[index]; 388 return DataStreamOffset + _nonSolidStartOffset + 4 + item.Pos; 389 } 390 Release()391 void Release() 392 { 393 Decoder.Release(); 394 } 395 IsTruncated()396 bool IsTruncated() const { return (_fileSize - StartOffset < FirstHeader.ArcSize); } 397 GetReducedName(unsigned index)398 UString GetReducedName(unsigned index) const 399 { 400 const CItem &item = Items[index]; 401 402 UString s; 403 if (item.Prefix >= 0) 404 { 405 if (IsUnicode) 406 s = UPrefixes[item.Prefix]; 407 else 408 s = MultiByteToUnicodeString(APrefixes[item.Prefix]); 409 if (s.Len() > 0) 410 if (s.Back() != L'\\') 411 s += '\\'; 412 } 413 414 if (IsUnicode) 415 { 416 s += item.NameU; 417 if (item.NameU.IsEmpty()) 418 s += "file"; 419 } 420 else 421 { 422 s += MultiByteToUnicodeString(item.NameA); 423 if (item.NameA.IsEmpty()) 424 s += "file"; 425 } 426 427 const char * const kRemoveStr = "$INSTDIR\\"; 428 if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr)) 429 { 430 s.Delete(0, MyStringLen(kRemoveStr)); 431 if (s[0] == L'\\') 432 s.DeleteFrontal(1); 433 } 434 if (item.IsUninstaller && ExeStub.Size() == 0) 435 s += ".nsis"; 436 return s; 437 } 438 439 UString ConvertToUnicode(const AString &s) const; 440 CInArchive()441 CInArchive() 442 #ifdef NSIS_SCRIPT 443 : Script(kScriptSizeLimit) 444 #endif 445 {} 446 }; 447 448 }} 449 450 #endif 451