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