Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Archive/BZip2/BZip2Handler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // BZip2Handler.cpp3 #include "StdAfx.h"5 #include "Common/ComTry.h"7 #include "Windows/PropVariant.h"9 #include "../../Common/CreateCoder.h"10 #include "../../Common/ProgressUtils.h"11 #include "../../Common/StreamUtils.h"13 #include "../Common/DummyOutStream.h"15 #include "BZip2Handler.h"17 using namespace NWindows;19 namespace NArchive {20 namespace NBZip2 {22 static const CMethodId kMethodId_BZip2 = 0x040202;24 STATPROPSTG kProps[] =25 {26 { NULL, kpidPackSize, VT_UI8}27 };29 IMP_IInArchive_Props30 IMP_IInArchive_ArcProps_NO32 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)33 {34 *numItems = 1;35 return S_OK;36 }38 STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)39 {40 NWindows::NCOM::CPropVariant prop;41 switch(propID)42 {43 case kpidPackSize: prop = _item.PackSize; break;44 }45 prop.Detach(value);46 return S_OK;47 }49 STDMETHODIMP CHandler::Open(IInStream *stream,50 const UInt64 * /* maxCheckStartPosition */,51 IArchiveOpenCallback * /* openArchiveCallback */)52 {53 COM_TRY_BEGIN54 try55 {56 RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));57 const int kSignatureSize = 3;58 Byte buffer[kSignatureSize];59 RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize));60 if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')61 return S_FALSE;63 UInt64 endPosition;64 RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));65 _item.PackSize = endPosition - _streamStartPosition;67 _stream = stream;68 }69 catch(...)70 {71 return S_FALSE;72 }73 return S_OK;74 COM_TRY_END75 }77 STDMETHODIMP CHandler::Close()78 {79 _stream.Release();80 return S_OK;81 }84 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,85 Int32 testModeSpec, IArchiveExtractCallback *extractCallback)86 {87 COM_TRY_BEGIN88 bool allFilesMode = (numItems == UInt32(-1));89 if (!allFilesMode)90 {91 if (numItems == 0)92 return S_OK;93 if (numItems != 1)94 return E_INVALIDARG;95 if (indices[0] != 0)96 return E_INVALIDARG;97 }99 bool testMode = (testModeSpec != 0);101 extractCallback->SetTotal(_item.PackSize);103 UInt64 currentTotalPacked = 0;105 RINOK(extractCallback->SetCompleted(¤tTotalPacked));107 CMyComPtr<ISequentialOutStream> realOutStream;108 Int32 askMode;109 askMode = testMode ? NExtract::NAskMode::kTest :110 NExtract::NAskMode::kExtract;112 RINOK(extractCallback->GetStream(0, &realOutStream, askMode));114 if(!testMode && !realOutStream)115 return S_OK;118 extractCallback->PrepareOperation(askMode);120 CMyComPtr<ICompressCoder> decoder;121 HRESULT loadResult = CreateCoder(122 EXTERNAL_CODECS_VARS123 kMethodId_BZip2, decoder, false);124 if (loadResult != S_OK || !decoder)125 {126 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));127 return S_OK;128 }130 #ifdef COMPRESS_MT131 {132 CMyComPtr<ICompressSetCoderMt> setCoderMt;133 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);134 if (setCoderMt)135 {136 RINOK(setCoderMt->SetNumberOfThreads(_numThreads));137 }138 }139 #endif141 CDummyOutStream *outStreamSpec = new CDummyOutStream;142 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);143 outStreamSpec->SetStream(realOutStream);144 outStreamSpec->Init();146 realOutStream.Release();148 CLocalProgress *lps = new CLocalProgress;149 CMyComPtr<ICompressProgressInfo> progress = lps;150 lps->Init(extractCallback, true);152 RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));154 HRESULT result = S_OK;156 bool firstItem = true;157 for (;;)158 {159 lps->InSize = currentTotalPacked;160 lps->OutSize = outStreamSpec->GetSize();162 RINOK(lps->SetCur());164 const int kSignatureSize = 3;165 Byte buffer[kSignatureSize];166 size_t processedSize = kSignatureSize;167 RINOK(ReadStream(_stream, buffer, &processedSize));168 if (processedSize != kSignatureSize)169 {170 if (firstItem)171 return E_FAIL;172 break;173 }174 if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')175 {176 if (firstItem)177 return E_FAIL;178 break;179 }180 firstItem = false;182 UInt64 dataStartPos;183 RINOK(_stream->Seek((UInt64)(Int64)(-3), STREAM_SEEK_CUR, &dataStartPos));185 result = decoder->Code(_stream, outStream, NULL, NULL, progress);187 if (result != S_OK)188 break;190 CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;191 decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize);192 if (!getInStreamProcessedSize)193 break;194 UInt64 packSize;195 RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize));196 UInt64 pos;197 RINOK(_stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos));198 currentTotalPacked = pos - _streamStartPosition;199 }200 outStream.Release();202 Int32 retResult;203 if (result == S_OK)204 retResult = NExtract::NOperationResult::kOK;205 else if (result == S_FALSE)206 retResult = NExtract::NOperationResult::kDataError;207 else208 return result;209 return extractCallback->SetOperationResult(retResult);211 COM_TRY_END212 }214 IMPL_ISetCompressCodecsInfo216 }}