| OLD | NEW |
| (Empty) |
| 1 // LzmaHandler.cpp | |
| 2 | |
| 3 #include "StdAfx.h" | |
| 4 | |
| 5 #include "LzmaHandler.h" | |
| 6 | |
| 7 #include "Common/Defs.h" | |
| 8 #include "Common/StringConvert.h" | |
| 9 #include "Common/ComTry.h" | |
| 10 #include "Common/IntToString.h" | |
| 11 | |
| 12 #include "Windows/PropVariant.h" | |
| 13 | |
| 14 #include "../../Common/ProgressUtils.h" | |
| 15 #include "../../Common/StreamUtils.h" | |
| 16 #include "../Common/DummyOutStream.h" | |
| 17 | |
| 18 #include "LzmaFiltersDecode.h" | |
| 19 | |
| 20 namespace NArchive { | |
| 21 namespace NLzma { | |
| 22 | |
| 23 STATPROPSTG kProps[] = | |
| 24 { | |
| 25 { NULL, kpidSize, VT_UI8}, | |
| 26 { NULL, kpidPackSize, VT_UI8}, | |
| 27 { NULL, kpidMethod, VT_UI1} | |
| 28 }; | |
| 29 | |
| 30 IMP_IInArchive_Props | |
| 31 IMP_IInArchive_ArcProps_NO | |
| 32 | |
| 33 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
| 34 { | |
| 35 *numItems = 1; | |
| 36 return S_OK; | |
| 37 } | |
| 38 | |
| 39 static void ConvertUInt32ToString(UInt32 value, wchar_t *s) | |
| 40 { | |
| 41 ConvertUInt64ToString(value, s + MyStringLen(s)); | |
| 42 } | |
| 43 | |
| 44 static void DictSizeToString(UInt32 value, wchar_t *s) | |
| 45 { | |
| 46 for (int i = 0; i <= 31; i++) | |
| 47 if ((UInt32(1) << i) == value) | |
| 48 { | |
| 49 ConvertUInt32ToString(i, s); | |
| 50 return; | |
| 51 } | |
| 52 wchar_t c = L'b'; | |
| 53 if ((value & ((1 << 20) - 1)) == 0) | |
| 54 { | |
| 55 value >>= 20; | |
| 56 c = L'm'; | |
| 57 } | |
| 58 else if ((value & ((1 << 10) - 1)) == 0) | |
| 59 { | |
| 60 value >>= 10; | |
| 61 c = L'k'; | |
| 62 } | |
| 63 ConvertUInt32ToString(value, s); | |
| 64 int p = MyStringLen(s); | |
| 65 s[p++] = c; | |
| 66 s[p++] = L'\0'; | |
| 67 } | |
| 68 | |
| 69 static void MyStrCat(wchar_t *d, const wchar_t *s) | |
| 70 { | |
| 71 MyStringCopy(d + MyStringLen(d), s); | |
| 72 } | |
| 73 | |
| 74 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
lue) | |
| 75 { | |
| 76 if (index != 0) | |
| 77 return E_INVALIDARG; | |
| 78 NWindows::NCOM::CPropVariant propVariant; | |
| 79 switch(propID) | |
| 80 { | |
| 81 case kpidSize: | |
| 82 if (m_StreamInfo.HasUnpackSize()) | |
| 83 propVariant = (UInt64)m_StreamInfo.UnpackSize; | |
| 84 break; | |
| 85 case kpidPackSize: | |
| 86 propVariant = (UInt64)m_PackSize; | |
| 87 break; | |
| 88 case kpidMethod: | |
| 89 { | |
| 90 wchar_t s[64]; | |
| 91 s[0] = '\0'; | |
| 92 if (m_StreamInfo.IsThereFilter) | |
| 93 { | |
| 94 const wchar_t *f; | |
| 95 if (m_StreamInfo.FilterMethod == 0) | |
| 96 f = L"Copy"; | |
| 97 else if (m_StreamInfo.FilterMethod == 1) | |
| 98 f = L"BCJ"; | |
| 99 else | |
| 100 f = L"Unknown"; | |
| 101 MyStrCat(s, f); | |
| 102 MyStrCat(s, L" "); | |
| 103 } | |
| 104 MyStrCat(s, L"LZMA:"); | |
| 105 DictSizeToString(m_StreamInfo.GetDicSize(), s); | |
| 106 propVariant = s; | |
| 107 break; | |
| 108 } | |
| 109 } | |
| 110 propVariant.Detach(value); | |
| 111 return S_OK; | |
| 112 } | |
| 113 | |
| 114 STDMETHODIMP CHandler::Open(IInStream *inStream, | |
| 115 const UInt64 * /* maxCheckStartPosition */, | |
| 116 IArchiveOpenCallback * /* openArchiveCallback */) | |
| 117 { | |
| 118 { | |
| 119 RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); | |
| 120 | |
| 121 HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); | |
| 122 if (res != S_OK) | |
| 123 return S_FALSE; | |
| 124 | |
| 125 Byte b; | |
| 126 RINOK(ReadStream_FALSE(inStream, &b, 1)); | |
| 127 if (b != 0) | |
| 128 return S_FALSE; | |
| 129 | |
| 130 UInt64 endPos; | |
| 131 RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); | |
| 132 m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); | |
| 133 | |
| 134 m_Stream = inStream; | |
| 135 } | |
| 136 return S_OK; | |
| 137 } | |
| 138 | |
| 139 STDMETHODIMP CHandler::Close() | |
| 140 { | |
| 141 m_Stream.Release(); | |
| 142 return S_OK; | |
| 143 } | |
| 144 | |
| 145 | |
| 146 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
| 147 Int32 _aTestMode, IArchiveExtractCallback *extractCallback) | |
| 148 { | |
| 149 COM_TRY_BEGIN | |
| 150 bool allFilesMode = (numItems == UInt32(-1)); | |
| 151 if (!allFilesMode) | |
| 152 { | |
| 153 if (numItems == 0) | |
| 154 return S_OK; | |
| 155 if (numItems != 1) | |
| 156 return E_INVALIDARG; | |
| 157 if (indices[0] != 0) | |
| 158 return E_INVALIDARG; | |
| 159 } | |
| 160 | |
| 161 bool testMode = (_aTestMode != 0); | |
| 162 | |
| 163 RINOK(extractCallback->SetTotal(m_PackSize)); | |
| 164 | |
| 165 UInt64 currentTotalPacked = 0; | |
| 166 | |
| 167 CDummyOutStream *outStreamSpec = new CDummyOutStream; | |
| 168 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | |
| 169 | |
| 170 { | |
| 171 CMyComPtr<ISequentialOutStream> realOutStream; | |
| 172 Int32 askMode = testMode ? | |
| 173 NArchive::NExtract::NAskMode::kTest : | |
| 174 NArchive::NExtract::NAskMode::kExtract; | |
| 175 | |
| 176 RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); | |
| 177 | |
| 178 outStreamSpec->SetStream(realOutStream); | |
| 179 outStreamSpec->Init(); | |
| 180 if(!testMode && !realOutStream) | |
| 181 return S_OK; | |
| 182 extractCallback->PrepareOperation(askMode); | |
| 183 } | |
| 184 | |
| 185 CLocalProgress *lps = new CLocalProgress; | |
| 186 CMyComPtr<ICompressProgressInfo> progress = lps; | |
| 187 lps->Init(extractCallback, true); | |
| 188 | |
| 189 CDecoder decoder; | |
| 190 RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); | |
| 191 UInt64 streamPos = m_StreamStartPosition; | |
| 192 Int32 opRes = NArchive::NExtract::NOperationResult::kOK; | |
| 193 bool firstItem = true; | |
| 194 for (;;) | |
| 195 { | |
| 196 CHeader st; | |
| 197 HRESULT result = ReadStreamHeader(m_Stream, st); | |
| 198 if (result != S_OK) | |
| 199 { | |
| 200 if (firstItem) | |
| 201 return E_FAIL; | |
| 202 break; | |
| 203 } | |
| 204 firstItem = false; | |
| 205 | |
| 206 lps->OutSize = outStreamSpec->GetSize(); | |
| 207 lps->InSize = currentTotalPacked; | |
| 208 RINOK(lps->SetCur()); | |
| 209 | |
| 210 streamPos += st.GetHeaderSize(); | |
| 211 UInt64 packProcessed; | |
| 212 | |
| 213 { | |
| 214 result = decoder.Code( | |
| 215 EXTERNAL_CODECS_VARS | |
| 216 st, m_Stream, outStream, &packProcessed, progress); | |
| 217 if (result == E_NOTIMPL) | |
| 218 { | |
| 219 opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; | |
| 220 break; | |
| 221 } | |
| 222 if (result == S_FALSE) | |
| 223 { | |
| 224 opRes = NArchive::NExtract::NOperationResult::kDataError; | |
| 225 break; | |
| 226 } | |
| 227 RINOK(result); | |
| 228 } | |
| 229 | |
| 230 if (packProcessed == (UInt64)(Int64)-1) | |
| 231 break; | |
| 232 RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); | |
| 233 currentTotalPacked += packProcessed; | |
| 234 streamPos += packProcessed; | |
| 235 } | |
| 236 outStream.Release(); | |
| 237 return extractCallback->SetOperationResult(opRes); | |
| 238 COM_TRY_END | |
| 239 } | |
| 240 | |
| 241 IMPL_ISetCompressCodecsInfo | |
| 242 | |
| 243 }} | |
| OLD | NEW |