// 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 > 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 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 coder; RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath, methodInfo.Decoder, &coder)); coder.QueryInterface(IID_ISequentialInStream, &_filterInStream); if (!_filterInStream) return E_NOTIMPL; } CMyComPtr 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 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 setInStream; _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); if (!setInStream) return E_NOTIMPL; RINOK(setInStream->SetInStream(inStream)); } { CMyComPtr setOutStreamSize; _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); if (!setOutStreamSize) return E_NOTIMPL; RINOK(setOutStreamSize->SetOutStreamSize(NULL)); } if (useFilter) { /* CMyComPtr 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);; } }}