diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2007-01-20 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:49 +0300 |
commit | d9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch) | |
tree | c722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/Nsis | |
parent | 804edc5756fede54dbb1aefda6d39d306111938d (diff) |
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/Nsis')
-rwxr-xr-x | CPP/7zip/Archive/Nsis/DllExports.cpp | 110 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/Nsis.dsp | 337 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/Nsis.dsw | 29 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisDecode.cpp | 150 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisDecode.h | 47 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisHandler.cpp | 484 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisHandler.h | 41 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisIn.cpp | 1169 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisIn.h | 166 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/StdAfx.cpp | 3 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/StdAfx.h | 9 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/makefile | 67 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/resource.rc | 3 |
13 files changed, 2615 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Nsis/DllExports.cpp b/CPP/7zip/Archive/Nsis/DllExports.cpp new file mode 100755 index 00000000..f10f56ea --- /dev/null +++ b/CPP/7zip/Archive/Nsis/DllExports.cpp @@ -0,0 +1,110 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" +#include "Windows/PropVariant.h" +#include "../../ICoder.h" +#include "NsisHandler.h" + +// {23170F69-40C1-278A-1000-000110090000} +DEFINE_GUID(CLSID_CNsisHandler, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x09, 0x00, 0x00); + +HINSTANCE g_hInstance; +#ifndef _UNICODE +bool g_IsNT = false; +static bool IsItWindowsNT() +{ + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); +} +#endif + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = hInstance; + #ifndef _UNICODE + g_IsNT = IsItWindowsNT(); + #endif + } + return TRUE; +} + +STDAPI CreateObject( + const GUID *classID, + const GUID *interfaceID, + void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + if (*classID != CLSID_CNsisHandler) + return CLASS_E_CLASSNOTAVAILABLE; + int needIn = *interfaceID == IID_IInArchive; + // int needOut = *interfaceID == IID_IOutArchive; + if (needIn /*|| needOut */) + { + NArchive::NNsis::CHandler *temp = new NArchive::NNsis::CHandler; + if (needIn) + { + CMyComPtr<IInArchive> inArchive = (IInArchive *)temp; + *outObject = inArchive.Detach(); + } + /* + else + { + CMyComPtr<IOutArchive> outArchive = (IOutArchive *)temp; + *outObject = outArchive.Detach(); + } + */ + } + else + return E_NOINTERFACE; + COM_TRY_END + return S_OK; +} + +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant propVariant; + switch(propID) + { + case NArchive::kName: + propVariant = L"Nsis"; + break; + case NArchive::kClassID: + { + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CNsisHandler, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NArchive::kExtension: + propVariant = L"exe"; + break; + case NArchive::kUpdate: + propVariant = false; + break; + case NArchive::kStartSignature: + { + if ((value->bstrVal = ::SysAllocStringByteLen((const char *)NArchive::NNsis::kSignature, + NArchive::NNsis::kSignatureSize)) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NArchive::kAssociate: + { + propVariant = false; + break; + } + } + propVariant.Detach(value); + return S_OK; +} diff --git a/CPP/7zip/Archive/Nsis/Nsis.dsp b/CPP/7zip/Archive/Nsis/Nsis.dsp new file mode 100755 index 00000000..45ce0386 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/Nsis.dsp @@ -0,0 +1,337 @@ +# Microsoft Developer Studio Project File - Name="Nsis" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Nsis - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Nsis.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Nsis.mak" CFG="Nsis - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Nsis - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Nsis - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Nsis - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Formats\nsis.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Nsis - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Formats\nsis.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Nsis - Win32 Release" +# Name "Nsis - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Archive.def +# End Source File +# Begin Source File + +SOURCE=.\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\Nsis.ico +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\NsisDecode.cpp +# End Source File +# Begin Source File + +SOURCE=.\NsisDecode.h +# End Source File +# Begin Source File + +SOURCE=.\NsisHandler.cpp +# End Source File +# Begin Source File + +SOURCE=.\NsisHandler.h +# End Source File +# Begin Source File + +SOURCE=.\NsisIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\NsisIn.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\CodecsPath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CodecsPath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderLoader.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderLoader.h +# End Source File +# Begin Source File + +SOURCE=..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "7z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\7z\7zMethodID.cpp +# End Source File +# Begin Source File + +SOURCE=..\7z\7zMethodID.h +# End Source File +# Begin Source File + +SOURCE=..\7z\7zMethods.cpp +# End Source File +# Begin Source File + +SOURCE=..\7z\7zMethods.h +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/Archive/Nsis/Nsis.dsw b/CPP/7zip/Archive/Nsis/Nsis.dsw new file mode 100755 index 00000000..d3df6d27 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/Nsis.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Nsis"=.\Nsis.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp new file mode 100755 index 00000000..d49b2312 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -0,0 +1,150 @@ +// NsisDecode.cpp + +#include "StdAfx.h" + +#include "NsisDecode.h" + +#include "../../Common/StreamUtils.h" + +#include "../7z/7zMethods.h" + +namespace NArchive { +namespace NNsis { + +static const N7z::CMethodID k_Copy = { { 0x0 }, 1 }; +static const N7z::CMethodID k_Deflate = { { 0x4, 0x9, 0x1 }, 3 }; +static const N7z::CMethodID k_BZip2 = { { 0x4, 0x9, 0x2 }, 3 }; +static const N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; +static const N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 }; + +CDecoder::CDecoder() +{ + N7z::LoadMethodMap(); +} + +HRESULT CDecoder::Init(IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter) +{ + useFilter = false; + CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; + + if (_decoderInStream) + if (method != _method) + Release(); + _method = method; + if (!_codecInStream) + { + const NArchive::N7z::CMethodID *methodID = 0; + switch (method) + { + case NMethodType::kCopy: + methodID = &k_Copy; + break; + case NMethodType::kDeflate: + methodID = &k_Deflate; + break; + case NMethodType::kBZip2: + methodID = &k_BZip2; + break; + case NMethodType::kLZMA: + methodID = &k_LZMA; + break; + default: + return E_NOTIMPL; + } + N7z::CMethodInfo methodInfo; + if (!N7z::GetMethodInfo(*methodID, methodInfo)) + return E_NOTIMPL; + CMyComPtr<ICompressCoder> coder; + RINOK(_libraries.CreateCoder(methodInfo.FilePath, methodInfo.Decoder, &coder)); + coder.QueryInterface(IID_ISequentialInStream, &_codecInStream); + if (!_codecInStream) + return E_NOTIMPL; + } + + if (thereIsFilterFlag) + { + UInt32 processedSize; + BYTE flag; + RINOK(inStream->Read(&flag, 1, &processedSize)); + if (processedSize != 1) + return E_FAIL; + if (flag > 1) + return E_NOTIMPL; + useFilter = (flag != 0); + } + + if (useFilter) + { + if (!_filterInStream) + { + N7z::CMethodInfo methodInfo; + if (!N7z::GetMethodInfo(k_BCJ_X86, methodInfo)) + return E_NOTIMPL; + CMyComPtr<ICompressCoder> coder; + RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath, methodInfo.Decoder, &coder)); + coder.QueryInterface(IID_ISequentialInStream, &_filterInStream); + if (!_filterInStream) + return E_NOTIMPL; + } + CMyComPtr<ICompressSetInStream> setInStream; + _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); + if (!setInStream) + return E_NOTIMPL; + RINOK(setInStream->SetInStream(_codecInStream)); + _decoderInStream = _filterInStream; + } + else + _decoderInStream = _codecInStream; + + if (method == NMethodType::kLZMA) + { + CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; + _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + if (setDecoderProperties) + { + static const UInt32 kPropertiesSize = 5; + BYTE properties[kPropertiesSize]; + UInt32 processedSize; + RINOK(inStream->Read(properties, kPropertiesSize, &processedSize)); + if (processedSize != kPropertiesSize) + return E_FAIL; + RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize)); + } + } + + { + CMyComPtr<ICompressSetInStream> setInStream; + _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); + if (!setInStream) + return E_NOTIMPL; + RINOK(setInStream->SetInStream(inStream)); + } + + { + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; + _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + if (!setOutStreamSize) + return E_NOTIMPL; + RINOK(setOutStreamSize->SetOutStreamSize(NULL)); + } + + if (useFilter) + { + /* + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; + _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + if (!setOutStreamSize) + return E_NOTIMPL; + RINOK(setOutStreamSize->SetOutStreamSize(NULL)); + */ + } + + return S_OK; +} + +HRESULT CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return ReadStream(_decoderInStream, data, size, processedSize);; +} + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h new file mode 100755 index 00000000..1bec178f --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -0,0 +1,47 @@ +// NsisDecode.h + +#ifndef __NSIS_DECODE_H +#define __NSIS_DECODE_H + +#include "../../IStream.h" + +#include "../Common/CoderLoader.h" + +namespace NArchive { +namespace NNsis { + +namespace NMethodType +{ + enum EEnum + { + kCopy, + kDeflate, + kBZip2, + kLZMA + }; +} + +class CDecoder +{ + NMethodType::EEnum _method; + CCoderLibraries _libraries; + + CMyComPtr<ISequentialInStream> _filterInStream; + CMyComPtr<ISequentialInStream> _codecInStream; + CMyComPtr<ISequentialInStream> _decoderInStream; + +public: + CDecoder(); + void Release() + { + _filterInStream.Release(); + _codecInStream.Release(); + _decoderInStream.Release(); + } + HRESULT Init(IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter); + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp new file mode 100755 index 00000000..0d840479 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -0,0 +1,484 @@ +// NSisHandler.cpp + +#include "StdAfx.h" + +#include "NsisHandler.h" + +#include "Common/StringConvert.h" +#include "Common/IntToString.h" +#include "Common/NewHandler.h" +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" + +#include "../Common/ItemNameUtils.h" + +using namespace NWindows; + +namespace NArchive { +namespace NNsis { + +static const wchar_t *kBcjMethod = L"BCJ"; +static const wchar_t *kUnknownMethod = L"Unknown"; + +static const wchar_t *kMethods[] = +{ + L"Copy", + L"Deflate", + L"BZip2", + L"LZMA" +}; + +static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); + +STATPROPSTG kProperties[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsFolder, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackedSize, VT_UI8}, + { NULL, kpidLastWriteTime, VT_FILETIME}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidSolid, VT_BOOL} +}; + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value) +{ + value->vt = VT_EMPTY; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +{ + *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + if(index >= sizeof(kProperties) / sizeof(kProperties[0])) + return E_INVALIDARG; + const STATPROPSTG &srcItem = kProperties[index]; + *propID = srcItem.propid; + *varType = srcItem.vt; + *name = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) +{ + *numProperties = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */, + BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + { + if(_archive.Open(stream, maxCheckStartPosition) != S_OK) + return S_FALSE; + _inStream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _archive.Clear(); + _archive.Release(); + _inStream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _archive.Items.Size() + #ifdef NSIS_SCRIPT + + 1 + #endif + ; + return S_OK; +} + +static UString ConvertUInt32ToString(UInt32 value) +{ + wchar_t buffer[32]; + ConvertUInt64ToString(value, buffer); + return buffer; +} + +static UString GetStringForSizeValue(UInt32 value) +{ + for (int i = 31; i >= 0; i--) + if ((UInt32(1) << i) == value) + return ConvertUInt32ToString(i); + UString result; + if (value % (1 << 20) == 0) + { + result += ConvertUInt32ToString(value >> 20); + result += L"m"; + } + else if (value % (1 << 10) == 0) + { + result += ConvertUInt32ToString(value >> 10); + result += L"k"; + } + else + { + result += ConvertUInt32ToString(value); + result += L"b"; + } + return result; +} + +bool CHandler::GetUncompressedSize(int index, UInt32 &size) +{ + size = 0; + const CItem &item = _archive.Items[index]; + if (item.SizeIsDefined) + size = item.Size; + else if (_archive.IsSolid && item.EstimatedSizeIsDefined) + size = item.EstimatedSize; + else + return false; + return true; +} + +bool CHandler::GetCompressedSize(int index, UInt32 &size) +{ + size = 0; + const CItem &item = _archive.Items[index]; + if (item.CompressedSizeIsDefined) + size = item.CompressedSize; + else + { + if (_archive.IsSolid) + { + if (index == 0) + size = _archive.FirstHeader.GetDataSize(); + else + return false; + } + else + { + if (!item.IsCompressed) + size = item.Size; + else + return false; + } + } + return true; +} + + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant propVariant; + #ifdef NSIS_SCRIPT + if (index >= (UInt32)_archive.Items.Size()) + { + switch(propID) + { + case kpidPath: + propVariant = L"[NSIS].nsi"; + break; + case kpidIsFolder: + propVariant = false; + break; + case kpidSize: + case kpidPackedSize: + propVariant = (UInt64)_archive.Script.Length(); + break; + case kpidSolid: + propVariant = false; + break; + } + } + else + #endif + { + const CItem &item = _archive.Items[index]; + switch(propID) + { + case kpidPath: + { + const UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetReducedName(), CP_ACP)); + propVariant = (const wchar_t *)s; + break; + } + case kpidIsFolder: + propVariant = false; + break; + case kpidSize: + { + UInt32 size; + if (GetUncompressedSize(index, size)) + propVariant = (UInt64)size; + break; + } + case kpidPackedSize: + { + UInt32 size; + if (GetCompressedSize(index, size)) + propVariant = (UInt64)size; + break; + } + case kpidLastWriteTime: + { + if (item.DateTime.dwHighDateTime > 0x01000000 && + item.DateTime.dwHighDateTime < 0xFF000000) + propVariant = item.DateTime; + break; + } + case kpidMethod: + { + NMethodType::EEnum methodIndex = _archive.Method; + UString method; + if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && item.UseFilter) + { + method += kBcjMethod; + method += L" "; + } + method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod; + if (methodIndex == NMethodType::kLZMA) + { + method += L":"; + method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: item.DictionarySize); + } + propVariant = method; + break; + } + case kpidSolid: + propVariant = _archive.IsSolid; + break; + } + } + propVariant.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (_aTestMode != 0); + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + GetNumberOfItems(&numItems); + if(numItems == 0) + return S_OK; + UInt64 totalSize = 0; + + UInt32 i; + for(i = 0; i < numItems; i++) + { + UInt32 index = (allFilesMode ? i : indices[i]); + #ifdef NSIS_SCRIPT + if (index >= (UInt32)_archive.Items.Size()) + totalSize += _archive.Script.Length(); + else + #endif + { + UInt32 size; + if (_archive.IsSolid) + { + GetUncompressedSize(index, size); + UInt64 pos = _archive.GetPosOfSolidItem(index); + if (pos > totalSize) + totalSize = pos + size; + } + else + { + GetCompressedSize(index, size); + totalSize += size; + } + } + } + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt32 currentItemSize = 0; + + UInt64 streamPos = 0; + if (_archive.IsSolid) + { + RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL)); + bool useFilter; + RINOK(_archive.Decoder.Init(_inStream, _archive.Method, _archive.FilterFlag, useFilter)); + } + + bool dataError = false; + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + currentItemSize = 0; + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode; + askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + #ifdef NSIS_SCRIPT + if (index >= (UInt32)_archive.Items.Size()) + { + currentItemSize = _archive.Script.Length(); + if(!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (!testMode) + RINOK(realOutStream->Write((const char *)_archive.Script, (UInt32)_archive.Script.Length(), NULL)); + } + else + #endif + { + const CItem &item = _archive.Items[index]; + + if (_archive.IsSolid) + GetUncompressedSize(index, currentItemSize); + else + GetCompressedSize(index, currentItemSize); + + if(!testMode && (!realOutStream)) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + + if (!dataError) + { + bool needDecompress = false; + bool sizeIsKnown = false; + UInt32 fullSize = 0; + + const UInt32 kBufferLength = 1 << 11; + Byte buffer[kBufferLength]; + + if (_archive.IsSolid) + { + UInt64 pos = _archive.GetPosOfSolidItem(index); + while(streamPos < pos) + { + UInt32 curSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength); + UInt32 processedSize; + HRESULT res = _archive.Decoder.Read(buffer, curSize, &processedSize); + if (res != S_OK) + { + if (res != S_FALSE) + return res; + dataError = true; + break; + } + if (processedSize == 0) + { + dataError = true; + break; + } + streamPos += processedSize; + } + if (streamPos == pos) + { + UInt32 processedSize; + RINOK(_archive.Decoder.Read(buffer, 4, &processedSize)); + if (processedSize != 4) + return E_FAIL; + streamPos += processedSize; + fullSize = GetUInt32FromMemLE(buffer); + sizeIsKnown = true; + needDecompress = true; + } + } + else + { + RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL)); + if (item.IsCompressed) + { + needDecompress = true; + bool useFilter; + RINOK(_archive.Decoder.Init(_inStream, _archive.Method, _archive.FilterFlag, useFilter)); + fullSize = GetUInt32FromMemLE(buffer); + } + else + fullSize = item.Size; + } + if (!dataError) + { + if (needDecompress) + { + UInt64 offset = 0; + while(!sizeIsKnown || fullSize > 0) + { + UInt32 curSize = kBufferLength; + if (sizeIsKnown && curSize > fullSize) + curSize = fullSize; + UInt32 processedSize; + HRESULT res = _archive.Decoder.Read(buffer, curSize, &processedSize); + if (res != S_OK) + { + if (res != S_FALSE) + return res; + dataError = true; + break; + } + if (processedSize == 0) + { + if (sizeIsKnown) + dataError = true; + break; + } + + fullSize -= processedSize; + streamPos += processedSize; + offset += processedSize; + + UInt64 completed; + if (_archive.IsSolid) + completed = streamPos; + else + completed = currentTotalSize + offset; + RINOK(extractCallback->SetCompleted(&completed)); + if (!testMode) + RINOK(realOutStream->Write(buffer, processedSize, NULL)); + } + } + else + { + while(fullSize > 0) + { + UInt32 curSize = MyMin(fullSize, kBufferLength); + UInt32 processedSize; + RINOK(_inStream->Read(buffer, curSize, &processedSize)); + if (processedSize == 0) + { + dataError = true; + break; + } + fullSize -= processedSize; + streamPos += processedSize; + if (!testMode) + RINOK(realOutStream->Write(buffer, processedSize, 0)); + } + } + } + } + } + if (!testMode) + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(dataError ? + NArchive::NExtract::NOperationResult::kDataError : + NArchive::NExtract::NOperationResult::kOK)); + } + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.h b/CPP/7zip/Archive/Nsis/NsisHandler.h new file mode 100755 index 00000000..1ff8b776 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisHandler.h @@ -0,0 +1,41 @@ +// NSisHandler.h + +#ifndef __NSIS_HANDLER_H +#define __NSIS_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" + +#include "NsisIn.h" + +namespace NArchive { +namespace NNsis { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr<IInStream> _inStream; + CInArchive _archive; + + bool GetUncompressedSize(int index, UInt32 &size); + bool GetCompressedSize(int index, UInt32 &size); + +public: + MY_UNKNOWN_IMP1(IInArchive) + + STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback); + STDMETHOD(Close)(); + STDMETHOD(GetNumberOfItems)(UInt32 *numItems); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback); + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp new file mode 100755 index 00000000..0db6ccfd --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -0,0 +1,1169 @@ +// Archive/NsisIn.cpp + +#include "StdAfx.h" + +#include "NsisIn.h" +#include "NsisDecode.h" + +#include "Windows/Defs.h" + +#include "../../Common/StreamUtils.h" + +#include "Common/IntToString.h" + +namespace NArchive { +namespace NNsis { + +Byte kSignature[kSignatureSize] = { 0xEF + 1, 0xBE, 0xAD, 0xDE, +0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74}; + +class SignatureInitializer +{ +public: + SignatureInitializer() { kSignature[0]--; }; +} g_SignatureInitializer; + +static const char *kCrLf = "\x0D\x0A"; + +UInt32 GetUInt32FromMemLE(const Byte *p) +{ + return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); +} + +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 */) +{ + RINOZ(MyCompare( + (**(const CItem **)p1).Pos, + (**(const CItem **)p2).Pos)); + return 0; +} + +AString CInArchive::ReadString(UInt32 pos) +{ + AString s; + UInt32 offset = GetOffset() + _stringsPos + pos; + for (;;) + { + if (offset >= _size) + throw 1; + char c = _data[offset++]; + 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 +}; + +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, "Assign" }, + { 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" } +}; + + +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", + "HWNDPARENT", + "_CLICK", + "_OUTDIR" +}; + +static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[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; +} + +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; +} + +// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value. +#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 + +// 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) + { + UInt32 index = c1; + bool needPrint = true; + res += "$"; + if (index < kNumShellStrings) + { + const char *sz = kShellStrings[index]; + if (sz[0] != 0) + { + res += sz; + needPrint = false; + } + } + if (needPrint) + { + res += "SHELL["; + res += UIntToString(index); + res += "]"; + } + } + 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; +} + +AString CInArchive::ReadString2(UInt32 pos) +{ + return GetNsisString(ReadString(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; +} + +HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) +{ + _posInData = bh.Offset + GetOffset(); + AString prefix; + 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: + { + prefix.Empty(); + prefix = ReadString2(e.Params[0]); + #ifdef NSIS_SCRIPT + Script += " "; + Script += prefix; + #endif + break; + } + + case EW_EXTRACTFILE: + { + CItem item; + item.Prefix = prefix; + /* UInt32 overwriteFlag = e.Params[0]; */ + item.Name = ReadString2(e.Params[1]); + item.Pos = e.Params[2]; + item.DateTime.dwLowDateTime = e.Params[3]; + item.DateTime.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 += " "; + Script += item.Name; + #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_ASSIGNVAR: + { + Script += " "; + Script += GetVar(e.Params[0]);; + Script += " \""; + AString maxLen, startOffset; + Script += ReadString2(e.Params[1]); + Script += "\""; + if (e.Params[2] != 0) + maxLen = ReadString(e.Params[2]); + if (e.Params[3] != 0) + startOffset = ReadString(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 += ReadString2(e.Params[0]); + Script += "\""; + + Script += " \""; + Script += ReadString2(e.Params[1]); + Script += "\""; + + for (int j = 2; j < 5; j++) + { + Script += " "; + Script += UIntToString(e.Params[j]); + } + 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: + { + Script += " "; + Script += IntToString(e.Params[0]); + Script += " "; + Script += GetVar(e.Params[1]); + Script += " "; + Script += ReadString2(e.Params[2]); + Script += " "; + Script += UIntToString(e.Params[3]); + Script += " "; + Script += IntToString(e.Params[4]); + Script += " "; + Script += UIntToString(e.Params[5]); + 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 += " \""; + Script += ReadString2(e.Params[0]); + Script += " \""; + + Script += " "; + Script += " \""; + Script += ReadString2(e.Params[1]); + Script += " \""; + + 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_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; + for (i = 0; i + 1 < Items.Size();) + { + if (Items[i].Pos == Items[i + 1].Pos) + Items.Delete(i + 1); + else + i++; + } + for (i = 0; i + 1 < Items.Size(); i++) + { + CItem &item = Items[i]; + item.EstimatedSizeIsDefined = true; + item.EstimatedSize = Items[i + 1].Pos - item.Pos - 4; + } + 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]; + UInt32 processedSize; + RINOK(ReadStream(_stream, sig, kSigSize, &processedSize)); + if (processedSize < 4) + return S_FALSE; + UInt32 size = GetUInt32FromMemLE(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 = GetUInt32FromMemLE(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; + + return ReadEntries(bhEntries); +} + +static bool IsLZMA(const Byte *p, UInt32 &dictionary) +{ + dictionary = GetUInt32FromMemLE(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; +} + +HRESULT CInArchive::Open2() +{ + 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]; + UInt32 processedSize; + RINOK(ReadStream(_stream, sig, kSigSize, &processedSize)); + if (processedSize != kSigSize) + return S_FALSE; + UInt64 position; + RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position)); + + _headerIsCompressed = true; + IsSolid = true; + FilterFlag = false; + + UInt32 compressedHeaderSize = GetUInt32FromMemLE(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; + Method = NMethodType::kDeflate; + } + 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(_stream, Method, FilterFlag, UseFilter)); + UInt32 processedSize; + RINOK(Decoder.Read(_data, unpackSize, &processedSize)); + if (processedSize != unpackSize) + return S_FALSE; + _size = (size_t)processedSize; + if (IsSolid) + { + UInt32 size2 = ReadUInt32(); + if (size2 < _size) + _size = size2; + } + } + else + { + _data.SetCapacity(unpackSize); + _size = (size_t)unpackSize; + RINOK(ReadStream(_stream, (Byte *)_data, unpackSize, &processedSize)); + if (processedSize != unpackSize) + return S_FALSE; + } + 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(IInStream *inStream, const UInt64 *maxCheckStartPosition) +{ + Clear(); + UInt64 pos; + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &pos)); + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_archiveSize)); + UInt64 position; + RINOK(inStream->Seek(pos, STREAM_SEEK_SET, &position)); + UInt64 maxSize = (maxCheckStartPosition != 0) ? *maxCheckStartPosition : (1 << 20); + const UInt32 kStep = 512; + const UInt32 kStartHeaderSize = 4 * 7; + Byte buffer[kStep]; + bool found = false; + + UInt64 headerPosition = 0; + while (position <= maxSize) + { + UInt32 processedSize; + RINOK(ReadStream(inStream, buffer, kStartHeaderSize, &processedSize)); + if (processedSize != kStartHeaderSize) + return S_FALSE; + headerPosition = position; + position += processedSize; + if(memcmp(buffer + 4, kSignature, kSignatureSize) == 0) + { + found = true; + break; + } + const UInt32 kRem = kStep - kStartHeaderSize; + RINOK(ReadStream(inStream, buffer + kStartHeaderSize, kRem, &processedSize)); + if (processedSize != kRem) + return S_FALSE; + position += processedSize; + } + if (!found) + return S_FALSE; + FirstHeader.Flags = GetUInt32FromMemLE(buffer); + FirstHeader.HeaderLength = GetUInt32FromMemLE(buffer + kSignatureSize + 4); + FirstHeader.ArchiveSize = GetUInt32FromMemLE(buffer + kSignatureSize + 8); + if (_archiveSize - headerPosition < FirstHeader.ArchiveSize) + return S_FALSE; + + _stream = inStream; + HRESULT res = S_FALSE; + try { res = Open2(); } + catch(...) { Clear(); res = S_FALSE; } + _stream.Release(); + return res; +} + +void CInArchive::Clear() +{ + #ifdef NSIS_SCRIPT + Script.Empty(); + #endif + Items.Clear(); +} + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h new file mode 100755 index 00000000..d75a9e6e --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -0,0 +1,166 @@ +// Archive/NsisIn.h + +#ifndef __ARCHIVE_NSIS_IN_H +#define __ARCHIVE_NSIS_IN_H + +#include "Common/MyCom.h" +#include "Common/IntToString.h" +#include "Common/Buffer.h" + +#include "../../IStream.h" + +#include "NsisDecode.h" + +// #define NSIS_SCRIPT + +namespace NArchive { +namespace NNsis { + +const int kSignatureSize = 16; +extern Byte kSignature[kSignatureSize]; + +const UInt32 kFlagsMask = 0xF; +namespace NFlags +{ + const UInt32 kUninstall = 1; + const UInt32 kSilent = 2; + const UInt32 kNoCrc = 4; + const UInt32 kForceCrc = 8; +} + +struct CFirstHeader +{ + UInt32 Flags; + UInt32 HeaderLength; + + UInt32 ArchiveSize; + + bool ThereIsCrc() const + { + if ((Flags & NFlags::kForceCrc ) != 0) + return true; + return ((Flags & NFlags::kNoCrc) == 0); + } + + UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); } +}; + + +struct CBlockHeader +{ + UInt32 Offset; + UInt32 Num; +}; + +struct CItem +{ + AString Prefix; + AString Name; + UInt32 Pos; + bool SizeIsDefined; + bool CompressedSizeIsDefined; + bool EstimatedSizeIsDefined; + UInt32 Size; + UInt32 CompressedSize; + UInt32 EstimatedSize; + FILETIME DateTime; + UInt32 DictionarySize; + bool IsCompressed; + bool UseFilter; + CItem(): UseFilter(false), SizeIsDefined(false), EstimatedSizeIsDefined(false), + IsCompressed(true), CompressedSizeIsDefined(false), Size(0) {} + + bool IsINSTDIR() const + { + if (Prefix.Length() < 3) + return false; + return true; + } + + AString GetReducedName() const + { + AString prefix = Prefix; + if (prefix.Length() > 0) + if (prefix[prefix.Length() - 1] != '\\') + prefix += '\\'; + AString s2 = prefix + Name; + const int len = 9; + if (s2.Left(len).CompareNoCase("$INSTDIR\\") == 0) + s2 = s2.Mid(len); + return s2; + } + +}; + +class CInArchive +{ + UInt64 _archiveSize; + CMyComPtr<IInStream> _stream; + + Byte ReadByte(); + UInt32 ReadUInt32(); + HRESULT Open2(); + void ReadBlockHeader(CBlockHeader &bh); + AString ReadString(UInt32 pos); + AString ReadString2(UInt32 pos); + HRESULT ReadEntries(const CBlockHeader &bh); + HRESULT Parse(); + + CByteBuffer _data; + UInt64 _size; + + size_t _posInData; + + UInt32 _stringsPos; + + + bool _headerIsCompressed; + UInt32 _nonSolidStartOffset; +public: + HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition); + void Clear(); + + UInt64 StreamOffset; + CDecoder Decoder; + CObjectVector<CItem> Items; + bool IsSolid; + CFirstHeader FirstHeader; + NMethodType::EEnum Method; + bool UseFilter; + UInt32 DictionarySize; + bool FilterFlag; + + #ifdef NSIS_SCRIPT + AString Script; + #endif + UInt32 GetOffset() const { return IsSolid ? 4 : 0; } + UInt64 GetDataPos(int index) + { + const CItem &item = Items[index]; + return GetOffset() + FirstHeader.HeaderLength + item.Pos; + } + + UInt64 GetPosOfSolidItem(int index) const + { + const CItem &item = Items[index]; + return 4 + FirstHeader.HeaderLength + item.Pos; + } + + UInt64 GetPosOfNonSolidItem(int index) const + { + const CItem &item = Items[index]; + return StreamOffset + _nonSolidStartOffset + 4 + item.Pos; + } + + void Release() + { + Decoder.Release(); + } + +}; + +UInt32 GetUInt32FromMemLE(const Byte *p); + +}} + +#endif diff --git a/CPP/7zip/Archive/Nsis/StdAfx.cpp b/CPP/7zip/Archive/Nsis/StdAfx.cpp new file mode 100755 index 00000000..d0feea85 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Archive/Nsis/StdAfx.h b/CPP/7zip/Archive/Nsis/StdAfx.h new file mode 100755 index 00000000..2e4be10b --- /dev/null +++ b/CPP/7zip/Archive/Nsis/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/Nsis/makefile b/CPP/7zip/Archive/Nsis/makefile new file mode 100755 index 00000000..69fcf523 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/makefile @@ -0,0 +1,67 @@ +PROG = nsis.dll +DEF_FILE = ../Archive.def +CFLAGS = $(CFLAGS) -I ../../../ +LIBS = $(LIBS) oleaut32.lib user32.lib + +TAR_OBJS = \ + $O\DllExports.obj \ + $O\NsisDecode.obj \ + $O\NsisHandler.obj \ + $O\NsisIn.obj \ + +COMMON_OBJS = \ + $O\Alloc.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\String.obj \ + $O\StringConvert.obj \ + $O\Vector.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\FileFind.obj \ + $O\PropVariant.obj \ + +7ZIP_COMMON_OBJS = \ + $O\LimitedStreams.obj \ + $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ + +AR_COMMON_OBJS = \ + $O\CodecsPath.obj \ + $O\CoderLoader.obj \ + $O\ItemNameUtils.obj \ + $O\FilterCoder.obj \ + +7Z_OBJS = \ + $O\7zMethodID.obj \ + $O\7zMethods.obj \ + +OBJS = \ + $O\StdAfx.obj \ + $(TAR_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_TAR_OBJS) \ + $O\CopyCoder.obj \ + $O\resource.res + +!include "../../../Build.mak" + +$(TAR_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(7Z_OBJS): ../7z/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp + $(COMPL) diff --git a/CPP/7zip/Archive/Nsis/resource.rc b/CPP/7zip/Archive/Nsis/resource.rc new file mode 100755 index 00000000..487eb4ee --- /dev/null +++ b/CPP/7zip/Archive/Nsis/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("Nsis Plugin", "nsis") |