1*f6dc9357SAndroid Build Coastguard Worker // ChmHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/AutoPtr.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/ComTry.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/RegisterArc.h"
17*f6dc9357SAndroid Build Coastguard Worker
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/CopyCoder.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/LzxDecoder.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #include "ChmHandler.h"
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
26*f6dc9357SAndroid Build Coastguard Worker using namespace NTime;
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
29*f6dc9357SAndroid Build Coastguard Worker namespace NChm {
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker // #define CHM_DETAILS
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker #ifdef CHM_DETAILS
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker enum
36*f6dc9357SAndroid Build Coastguard Worker {
37*f6dc9357SAndroid Build Coastguard Worker kpidSection = kpidUserDefined
38*f6dc9357SAndroid Build Coastguard Worker };
39*f6dc9357SAndroid Build Coastguard Worker
40*f6dc9357SAndroid Build Coastguard Worker #endif
41*f6dc9357SAndroid Build Coastguard Worker
42*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
43*f6dc9357SAndroid Build Coastguard Worker {
44*f6dc9357SAndroid Build Coastguard Worker kpidPath,
45*f6dc9357SAndroid Build Coastguard Worker kpidSize,
46*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
47*f6dc9357SAndroid Build Coastguard Worker kpidBlock
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker #ifdef CHM_DETAILS
50*f6dc9357SAndroid Build Coastguard Worker ,
51*f6dc9357SAndroid Build Coastguard Worker L"Section", kpidSection,
52*f6dc9357SAndroid Build Coastguard Worker kpidOffset
53*f6dc9357SAndroid Build Coastguard Worker #endif
54*f6dc9357SAndroid Build Coastguard Worker };
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker /*
57*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker // kpidNumBlocks,
60*f6dc9357SAndroid Build Coastguard Worker };
61*f6dc9357SAndroid Build Coastguard Worker */
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_NO_Table
66*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))67*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
68*f6dc9357SAndroid Build Coastguard Worker {
69*f6dc9357SAndroid Build Coastguard Worker // COM_TRY_BEGIN
70*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
71*f6dc9357SAndroid Build Coastguard Worker switch (propID)
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker /*
74*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks:
75*f6dc9357SAndroid Build Coastguard Worker {
76*f6dc9357SAndroid Build Coastguard Worker UInt64 numBlocks = 0;
77*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR(i, m_Database.Sections)
78*f6dc9357SAndroid Build Coastguard Worker {
79*f6dc9357SAndroid Build Coastguard Worker const CSectionInfo &s = m_Database.Sections[i];
80*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR(j, s.Methods)
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker const CMethodInfo &m = s.Methods[j];
83*f6dc9357SAndroid Build Coastguard Worker if (m.IsLzx())
84*f6dc9357SAndroid Build Coastguard Worker numBlocks += m.LzxInfo.ResetTable.GetNumBlocks();
85*f6dc9357SAndroid Build Coastguard Worker }
86*f6dc9357SAndroid Build Coastguard Worker }
87*f6dc9357SAndroid Build Coastguard Worker prop = numBlocks;
88*f6dc9357SAndroid Build Coastguard Worker break;
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker */
91*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = m_Database.StartPosition; break;
92*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = m_Database.PhySize; break;
93*f6dc9357SAndroid Build Coastguard Worker
94*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags: prop = m_ErrorFlags; break;
95*f6dc9357SAndroid Build Coastguard Worker }
96*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
97*f6dc9357SAndroid Build Coastguard Worker return S_OK;
98*f6dc9357SAndroid Build Coastguard Worker // COM_TRY_END
99*f6dc9357SAndroid Build Coastguard Worker }
100*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))101*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
102*f6dc9357SAndroid Build Coastguard Worker {
103*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
104*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
105*f6dc9357SAndroid Build Coastguard Worker
106*f6dc9357SAndroid Build Coastguard Worker if (m_Database.NewFormat)
107*f6dc9357SAndroid Build Coastguard Worker {
108*f6dc9357SAndroid Build Coastguard Worker switch (propID)
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
111*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)m_Database.NewFormatString.Len();
112*f6dc9357SAndroid Build Coastguard Worker break;
113*f6dc9357SAndroid Build Coastguard Worker }
114*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
115*f6dc9357SAndroid Build Coastguard Worker return S_OK;
116*f6dc9357SAndroid Build Coastguard Worker }
117*f6dc9357SAndroid Build Coastguard Worker
118*f6dc9357SAndroid Build Coastguard Worker unsigned entryIndex;
119*f6dc9357SAndroid Build Coastguard Worker if (m_Database.LowLevel)
120*f6dc9357SAndroid Build Coastguard Worker entryIndex = index;
121*f6dc9357SAndroid Build Coastguard Worker else
122*f6dc9357SAndroid Build Coastguard Worker entryIndex = m_Database.Indices[index];
123*f6dc9357SAndroid Build Coastguard Worker
124*f6dc9357SAndroid Build Coastguard Worker const CItem &item = m_Database.Items[entryIndex];
125*f6dc9357SAndroid Build Coastguard Worker
126*f6dc9357SAndroid Build Coastguard Worker switch (propID)
127*f6dc9357SAndroid Build Coastguard Worker {
128*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
129*f6dc9357SAndroid Build Coastguard Worker {
130*f6dc9357SAndroid Build Coastguard Worker UString us;
131*f6dc9357SAndroid Build Coastguard Worker // if (
132*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(item.Name, us);
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker if (!m_Database.LowLevel)
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker if (us.Len() > 1 && us[0] == L'/')
137*f6dc9357SAndroid Build Coastguard Worker us.Delete(0);
138*f6dc9357SAndroid Build Coastguard Worker }
139*f6dc9357SAndroid Build Coastguard Worker NItemName::ReplaceToOsSlashes_Remove_TailSlash(us);
140*f6dc9357SAndroid Build Coastguard Worker prop = us;
141*f6dc9357SAndroid Build Coastguard Worker }
142*f6dc9357SAndroid Build Coastguard Worker break;
143*f6dc9357SAndroid Build Coastguard Worker }
144*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir(); break;
145*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = item.Size; break;
146*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir())
149*f6dc9357SAndroid Build Coastguard Worker {
150*f6dc9357SAndroid Build Coastguard Worker if (item.Section == 0)
151*f6dc9357SAndroid Build Coastguard Worker prop = "Copy";
152*f6dc9357SAndroid Build Coastguard Worker else if (item.Section < m_Database.Sections.Size())
153*f6dc9357SAndroid Build Coastguard Worker prop = m_Database.Sections[(unsigned)item.Section].GetMethodName();
154*f6dc9357SAndroid Build Coastguard Worker }
155*f6dc9357SAndroid Build Coastguard Worker break;
156*f6dc9357SAndroid Build Coastguard Worker }
157*f6dc9357SAndroid Build Coastguard Worker case kpidBlock:
158*f6dc9357SAndroid Build Coastguard Worker if (m_Database.LowLevel)
159*f6dc9357SAndroid Build Coastguard Worker prop = item.Section;
160*f6dc9357SAndroid Build Coastguard Worker else if (item.Section != 0 && item.Section < m_Database.Sections.Size())
161*f6dc9357SAndroid Build Coastguard Worker prop = m_Database.GetFolder(index);
162*f6dc9357SAndroid Build Coastguard Worker break;
163*f6dc9357SAndroid Build Coastguard Worker
164*f6dc9357SAndroid Build Coastguard Worker #ifdef CHM_DETAILS
165*f6dc9357SAndroid Build Coastguard Worker
166*f6dc9357SAndroid Build Coastguard Worker case kpidSection: prop = (UInt32)item.Section; break;
167*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = (UInt32)item.Offset; break;
168*f6dc9357SAndroid Build Coastguard Worker
169*f6dc9357SAndroid Build Coastguard Worker #endif
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
173*f6dc9357SAndroid Build Coastguard Worker return S_OK;
174*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
175*f6dc9357SAndroid Build Coastguard Worker }
176*f6dc9357SAndroid Build Coastguard Worker
177*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Open (IInStream * inStream,const UInt64 * maxCheckStartPosition,IArchiveOpenCallback *))178*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
179*f6dc9357SAndroid Build Coastguard Worker const UInt64 *maxCheckStartPosition,
180*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback * /* openArchiveCallback */))
181*f6dc9357SAndroid Build Coastguard Worker {
182*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
183*f6dc9357SAndroid Build Coastguard Worker Close();
184*f6dc9357SAndroid Build Coastguard Worker try
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker CInArchive archive(_help2);
187*f6dc9357SAndroid Build Coastguard Worker // CProgressImp progressImp(openArchiveCallback);
188*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = archive.Open(inStream, maxCheckStartPosition, m_Database);
189*f6dc9357SAndroid Build Coastguard Worker if (!archive.IsArc) m_ErrorFlags |= kpv_ErrorFlags_IsNotArc;
190*f6dc9357SAndroid Build Coastguard Worker if (archive.HeadersError) m_ErrorFlags |= kpv_ErrorFlags_HeadersError;
191*f6dc9357SAndroid Build Coastguard Worker if (archive.UnexpectedEnd) m_ErrorFlags |= kpv_ErrorFlags_UnexpectedEnd;
192*f6dc9357SAndroid Build Coastguard Worker if (archive.UnsupportedFeature) m_ErrorFlags |= kpv_ErrorFlags_UnsupportedFeature;
193*f6dc9357SAndroid Build Coastguard Worker
194*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
195*f6dc9357SAndroid Build Coastguard Worker /*
196*f6dc9357SAndroid Build Coastguard Worker if (m_Database.LowLevel)
197*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
198*f6dc9357SAndroid Build Coastguard Worker */
199*f6dc9357SAndroid Build Coastguard Worker m_Stream = inStream;
200*f6dc9357SAndroid Build Coastguard Worker }
201*f6dc9357SAndroid Build Coastguard Worker catch(...)
202*f6dc9357SAndroid Build Coastguard Worker {
203*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
204*f6dc9357SAndroid Build Coastguard Worker }
205*f6dc9357SAndroid Build Coastguard Worker return S_OK;
206*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Close ())209*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker m_ErrorFlags = 0;
212*f6dc9357SAndroid Build Coastguard Worker m_Database.Clear();
213*f6dc9357SAndroid Build Coastguard Worker m_Stream.Release();
214*f6dc9357SAndroid Build Coastguard Worker return S_OK;
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
218*f6dc9357SAndroid Build Coastguard Worker CChmFolderOutStream
219*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream
220*f6dc9357SAndroid Build Coastguard Worker )
221*f6dc9357SAndroid Build Coastguard Worker bool m_TestMode;
222*f6dc9357SAndroid Build Coastguard Worker bool m_IsOk;
223*f6dc9357SAndroid Build Coastguard Worker bool m_FileIsOpen;
224*f6dc9357SAndroid Build Coastguard Worker const CFilesDatabase *m_Database;
225*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
226*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> m_RealOutStream;
227*f6dc9357SAndroid Build Coastguard Worker UInt64 m_RemainFileSize;
228*f6dc9357SAndroid Build Coastguard Worker
229*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenFile();
230*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteEmptyFiles();
231*f6dc9357SAndroid Build Coastguard Worker HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
232*f6dc9357SAndroid Build Coastguard Worker public:
233*f6dc9357SAndroid Build Coastguard Worker
234*f6dc9357SAndroid Build Coastguard Worker UInt64 m_FolderSize;
235*f6dc9357SAndroid Build Coastguard Worker UInt64 m_PosInFolder;
236*f6dc9357SAndroid Build Coastguard Worker UInt64 m_PosInSection;
237*f6dc9357SAndroid Build Coastguard Worker const CRecordVector<bool> *m_ExtractStatuses;
238*f6dc9357SAndroid Build Coastguard Worker unsigned m_StartIndex;
239*f6dc9357SAndroid Build Coastguard Worker unsigned m_CurrentIndex;
240*f6dc9357SAndroid Build Coastguard Worker unsigned m_NumFiles;
241*f6dc9357SAndroid Build Coastguard Worker
242*f6dc9357SAndroid Build Coastguard Worker void Init(
243*f6dc9357SAndroid Build Coastguard Worker const CFilesDatabase *database,
244*f6dc9357SAndroid Build Coastguard Worker IArchiveExtractCallback *extractCallback,
245*f6dc9357SAndroid Build Coastguard Worker bool testMode);
246*f6dc9357SAndroid Build Coastguard Worker HRESULT FlushCorrupted(UInt64 maxSize);
247*f6dc9357SAndroid Build Coastguard Worker };
248*f6dc9357SAndroid Build Coastguard Worker
249*f6dc9357SAndroid Build Coastguard Worker void CChmFolderOutStream::Init(
250*f6dc9357SAndroid Build Coastguard Worker const CFilesDatabase *database,
251*f6dc9357SAndroid Build Coastguard Worker IArchiveExtractCallback *extractCallback,
252*f6dc9357SAndroid Build Coastguard Worker bool testMode)
253*f6dc9357SAndroid Build Coastguard Worker {
254*f6dc9357SAndroid Build Coastguard Worker m_Database = database;
255*f6dc9357SAndroid Build Coastguard Worker m_ExtractCallback = extractCallback;
256*f6dc9357SAndroid Build Coastguard Worker m_TestMode = testMode;
257*f6dc9357SAndroid Build Coastguard Worker
258*f6dc9357SAndroid Build Coastguard Worker m_CurrentIndex = 0;
259*f6dc9357SAndroid Build Coastguard Worker m_FileIsOpen = false;
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker
262*f6dc9357SAndroid Build Coastguard Worker HRESULT CChmFolderOutStream::OpenFile()
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? m_TestMode ?
265*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
266*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract :
267*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kSkip;
268*f6dc9357SAndroid Build Coastguard Worker m_RealOutStream.Release();
269*f6dc9357SAndroid Build Coastguard Worker RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode))
270*f6dc9357SAndroid Build Coastguard Worker if (!m_RealOutStream && !m_TestMode)
271*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kSkip;
272*f6dc9357SAndroid Build Coastguard Worker return m_ExtractCallback->PrepareOperation(askMode);
273*f6dc9357SAndroid Build Coastguard Worker }
274*f6dc9357SAndroid Build Coastguard Worker
275*f6dc9357SAndroid Build Coastguard Worker HRESULT CChmFolderOutStream::WriteEmptyFiles()
276*f6dc9357SAndroid Build Coastguard Worker {
277*f6dc9357SAndroid Build Coastguard Worker if (m_FileIsOpen)
278*f6dc9357SAndroid Build Coastguard Worker return S_OK;
279*f6dc9357SAndroid Build Coastguard Worker for (; m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
280*f6dc9357SAndroid Build Coastguard Worker {
281*f6dc9357SAndroid Build Coastguard Worker const UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);
282*f6dc9357SAndroid Build Coastguard Worker if (fileSize != 0)
283*f6dc9357SAndroid Build Coastguard Worker return S_OK;
284*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = OpenFile();
285*f6dc9357SAndroid Build Coastguard Worker m_RealOutStream.Release();
286*f6dc9357SAndroid Build Coastguard Worker RINOK(result)
287*f6dc9357SAndroid Build Coastguard Worker RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
288*f6dc9357SAndroid Build Coastguard Worker }
289*f6dc9357SAndroid Build Coastguard Worker return S_OK;
290*f6dc9357SAndroid Build Coastguard Worker }
291*f6dc9357SAndroid Build Coastguard Worker
292*f6dc9357SAndroid Build Coastguard Worker // This is WritePart function
293*f6dc9357SAndroid Build Coastguard Worker HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
294*f6dc9357SAndroid Build Coastguard Worker {
295*f6dc9357SAndroid Build Coastguard Worker UInt32 realProcessed = 0;
296*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
297*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
298*f6dc9357SAndroid Build Coastguard Worker
299*f6dc9357SAndroid Build Coastguard Worker while (size != 0)
300*f6dc9357SAndroid Build Coastguard Worker {
301*f6dc9357SAndroid Build Coastguard Worker if (m_FileIsOpen)
302*f6dc9357SAndroid Build Coastguard Worker {
303*f6dc9357SAndroid Build Coastguard Worker UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));
304*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
305*f6dc9357SAndroid Build Coastguard Worker if (numBytesToWrite > 0)
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker if (!isOK)
308*f6dc9357SAndroid Build Coastguard Worker m_IsOk = false;
309*f6dc9357SAndroid Build Coastguard Worker if (m_RealOutStream)
310*f6dc9357SAndroid Build Coastguard Worker {
311*f6dc9357SAndroid Build Coastguard Worker UInt32 processedSizeLocal = 0;
312*f6dc9357SAndroid Build Coastguard Worker res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
313*f6dc9357SAndroid Build Coastguard Worker numBytesToWrite = processedSizeLocal;
314*f6dc9357SAndroid Build Coastguard Worker }
315*f6dc9357SAndroid Build Coastguard Worker }
316*f6dc9357SAndroid Build Coastguard Worker realProcessed += numBytesToWrite;
317*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
318*f6dc9357SAndroid Build Coastguard Worker *processedSize = realProcessed;
319*f6dc9357SAndroid Build Coastguard Worker data = (const void *)((const Byte *)data + numBytesToWrite);
320*f6dc9357SAndroid Build Coastguard Worker size -= numBytesToWrite;
321*f6dc9357SAndroid Build Coastguard Worker m_RemainFileSize -= numBytesToWrite;
322*f6dc9357SAndroid Build Coastguard Worker m_PosInSection += numBytesToWrite;
323*f6dc9357SAndroid Build Coastguard Worker m_PosInFolder += numBytesToWrite;
324*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
325*f6dc9357SAndroid Build Coastguard Worker return res;
326*f6dc9357SAndroid Build Coastguard Worker if (m_RemainFileSize == 0)
327*f6dc9357SAndroid Build Coastguard Worker {
328*f6dc9357SAndroid Build Coastguard Worker m_RealOutStream.Release();
329*f6dc9357SAndroid Build Coastguard Worker RINOK(m_ExtractCallback->SetOperationResult(
330*f6dc9357SAndroid Build Coastguard Worker m_IsOk ?
331*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK:
332*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kDataError))
333*f6dc9357SAndroid Build Coastguard Worker m_FileIsOpen = false;
334*f6dc9357SAndroid Build Coastguard Worker }
335*f6dc9357SAndroid Build Coastguard Worker if (realProcessed > 0)
336*f6dc9357SAndroid Build Coastguard Worker break; // with this break this function works as write part
337*f6dc9357SAndroid Build Coastguard Worker }
338*f6dc9357SAndroid Build Coastguard Worker else
339*f6dc9357SAndroid Build Coastguard Worker {
340*f6dc9357SAndroid Build Coastguard Worker if (m_CurrentIndex >= m_NumFiles)
341*f6dc9357SAndroid Build Coastguard Worker {
342*f6dc9357SAndroid Build Coastguard Worker realProcessed += size;
343*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
344*f6dc9357SAndroid Build Coastguard Worker *processedSize = realProcessed;
345*f6dc9357SAndroid Build Coastguard Worker return S_OK;
346*f6dc9357SAndroid Build Coastguard Worker // return E_FAIL;
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker
349*f6dc9357SAndroid Build Coastguard Worker unsigned fullIndex = m_StartIndex + m_CurrentIndex;
350*f6dc9357SAndroid Build Coastguard Worker m_RemainFileSize = m_Database->GetFileSize(fullIndex);
351*f6dc9357SAndroid Build Coastguard Worker UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
352*f6dc9357SAndroid Build Coastguard Worker if (fileOffset < m_PosInSection)
353*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
354*f6dc9357SAndroid Build Coastguard Worker
355*f6dc9357SAndroid Build Coastguard Worker if (fileOffset > m_PosInSection)
356*f6dc9357SAndroid Build Coastguard Worker {
357*f6dc9357SAndroid Build Coastguard Worker UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));
358*f6dc9357SAndroid Build Coastguard Worker realProcessed += numBytesToWrite;
359*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
360*f6dc9357SAndroid Build Coastguard Worker *processedSize = realProcessed;
361*f6dc9357SAndroid Build Coastguard Worker data = (const void *)((const Byte *)data + numBytesToWrite);
362*f6dc9357SAndroid Build Coastguard Worker size -= numBytesToWrite;
363*f6dc9357SAndroid Build Coastguard Worker m_PosInSection += numBytesToWrite;
364*f6dc9357SAndroid Build Coastguard Worker m_PosInFolder += numBytesToWrite;
365*f6dc9357SAndroid Build Coastguard Worker }
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker if (fileOffset == m_PosInSection)
368*f6dc9357SAndroid Build Coastguard Worker {
369*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenFile())
370*f6dc9357SAndroid Build Coastguard Worker m_FileIsOpen = true;
371*f6dc9357SAndroid Build Coastguard Worker m_CurrentIndex++;
372*f6dc9357SAndroid Build Coastguard Worker m_IsOk = true;
373*f6dc9357SAndroid Build Coastguard Worker }
374*f6dc9357SAndroid Build Coastguard Worker }
375*f6dc9357SAndroid Build Coastguard Worker }
376*f6dc9357SAndroid Build Coastguard Worker
377*f6dc9357SAndroid Build Coastguard Worker return WriteEmptyFiles();
378*f6dc9357SAndroid Build Coastguard Worker }
379*f6dc9357SAndroid Build Coastguard Worker
380*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
381*f6dc9357SAndroid Build Coastguard Worker {
382*f6dc9357SAndroid Build Coastguard Worker return Write2(data, size, processedSize, true);
383*f6dc9357SAndroid Build Coastguard Worker }
384*f6dc9357SAndroid Build Coastguard Worker
385*f6dc9357SAndroid Build Coastguard Worker HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker const UInt32 kBufferSize = (1 << 10);
388*f6dc9357SAndroid Build Coastguard Worker Byte buffer[kBufferSize];
389*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kBufferSize; i++)
390*f6dc9357SAndroid Build Coastguard Worker buffer[i] = 0;
391*f6dc9357SAndroid Build Coastguard Worker if (maxSize > m_FolderSize)
392*f6dc9357SAndroid Build Coastguard Worker maxSize = m_FolderSize;
393*f6dc9357SAndroid Build Coastguard Worker while (m_PosInFolder < maxSize)
394*f6dc9357SAndroid Build Coastguard Worker {
395*f6dc9357SAndroid Build Coastguard Worker UInt32 size = (UInt32)MyMin(maxSize - m_PosInFolder, (UInt64)kBufferSize);
396*f6dc9357SAndroid Build Coastguard Worker UInt32 processedSizeLocal = 0;
397*f6dc9357SAndroid Build Coastguard Worker RINOK(Write2(buffer, size, &processedSizeLocal, false))
398*f6dc9357SAndroid Build Coastguard Worker if (processedSizeLocal == 0)
399*f6dc9357SAndroid Build Coastguard Worker return S_OK;
400*f6dc9357SAndroid Build Coastguard Worker }
401*f6dc9357SAndroid Build Coastguard Worker return S_OK;
402*f6dc9357SAndroid Build Coastguard Worker }
403*f6dc9357SAndroid Build Coastguard Worker
404*f6dc9357SAndroid Build Coastguard Worker
405*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
406*f6dc9357SAndroid Build Coastguard Worker Int32 testModeSpec, IArchiveExtractCallback *extractCallback))
407*f6dc9357SAndroid Build Coastguard Worker {
408*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
409*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
410*f6dc9357SAndroid Build Coastguard Worker
411*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
412*f6dc9357SAndroid Build Coastguard Worker numItems = m_Database.NewFormat ? 1:
413*f6dc9357SAndroid Build Coastguard Worker (m_Database.LowLevel ?
414*f6dc9357SAndroid Build Coastguard Worker m_Database.Items.Size():
415*f6dc9357SAndroid Build Coastguard Worker m_Database.Indices.Size());
416*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
417*f6dc9357SAndroid Build Coastguard Worker return S_OK;
418*f6dc9357SAndroid Build Coastguard Worker const bool testMode = (testModeSpec != 0);
419*f6dc9357SAndroid Build Coastguard Worker
420*f6dc9357SAndroid Build Coastguard Worker UInt64 currentTotalSize = 0;
421*f6dc9357SAndroid Build Coastguard Worker
422*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
423*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
424*f6dc9357SAndroid Build Coastguard Worker
425*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
426*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
427*f6dc9357SAndroid Build Coastguard Worker inStream->SetStream(m_Stream);
428*f6dc9357SAndroid Build Coastguard Worker
429*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
430*f6dc9357SAndroid Build Coastguard Worker
431*f6dc9357SAndroid Build Coastguard Worker if (m_Database.LowLevel)
432*f6dc9357SAndroid Build Coastguard Worker {
433*f6dc9357SAndroid Build Coastguard Worker UInt64 currentItemSize = 0;
434*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
435*f6dc9357SAndroid Build Coastguard Worker
436*f6dc9357SAndroid Build Coastguard Worker if (m_Database.NewFormat)
437*f6dc9357SAndroid Build Coastguard Worker totalSize = m_Database.NewFormatString.Len();
438*f6dc9357SAndroid Build Coastguard Worker else
439*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
440*f6dc9357SAndroid Build Coastguard Worker totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
441*f6dc9357SAndroid Build Coastguard Worker
442*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
443*f6dc9357SAndroid Build Coastguard Worker
444*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
445*f6dc9357SAndroid Build Coastguard Worker {
446*f6dc9357SAndroid Build Coastguard Worker currentItemSize = 0;
447*f6dc9357SAndroid Build Coastguard Worker lps->InSize = currentTotalSize; // Change it
448*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = currentTotalSize;
449*f6dc9357SAndroid Build Coastguard Worker
450*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
451*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
452*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode= testMode ?
453*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
454*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
455*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
456*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
457*f6dc9357SAndroid Build Coastguard Worker
458*f6dc9357SAndroid Build Coastguard Worker if (m_Database.NewFormat)
459*f6dc9357SAndroid Build Coastguard Worker {
460*f6dc9357SAndroid Build Coastguard Worker if (index != 0)
461*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
462*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
463*f6dc9357SAndroid Build Coastguard Worker continue;
464*f6dc9357SAndroid Build Coastguard Worker if (!testMode)
465*f6dc9357SAndroid Build Coastguard Worker {
466*f6dc9357SAndroid Build Coastguard Worker const unsigned size = m_Database.NewFormatString.Len();
467*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size))
468*f6dc9357SAndroid Build Coastguard Worker }
469*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
470*f6dc9357SAndroid Build Coastguard Worker continue;
471*f6dc9357SAndroid Build Coastguard Worker }
472*f6dc9357SAndroid Build Coastguard Worker
473*f6dc9357SAndroid Build Coastguard Worker const CItem &item = m_Database.Items[index];
474*f6dc9357SAndroid Build Coastguard Worker
475*f6dc9357SAndroid Build Coastguard Worker currentItemSize = item.Size;
476*f6dc9357SAndroid Build Coastguard Worker
477*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
478*f6dc9357SAndroid Build Coastguard Worker continue;
479*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
480*f6dc9357SAndroid Build Coastguard Worker if (item.Section != 0)
481*f6dc9357SAndroid Build Coastguard Worker {
482*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
483*f6dc9357SAndroid Build Coastguard Worker continue;
484*f6dc9357SAndroid Build Coastguard Worker }
485*f6dc9357SAndroid Build Coastguard Worker
486*f6dc9357SAndroid Build Coastguard Worker if (testMode)
487*f6dc9357SAndroid Build Coastguard Worker {
488*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
489*f6dc9357SAndroid Build Coastguard Worker continue;
490*f6dc9357SAndroid Build Coastguard Worker }
491*f6dc9357SAndroid Build Coastguard Worker
492*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
493*f6dc9357SAndroid Build Coastguard Worker inStream->Init(item.Size);
494*f6dc9357SAndroid Build Coastguard Worker
495*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
496*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
497*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult((copyCoder->TotalSize == item.Size) ?
498*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK:
499*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kDataError))
500*f6dc9357SAndroid Build Coastguard Worker }
501*f6dc9357SAndroid Build Coastguard Worker return S_OK;
502*f6dc9357SAndroid Build Coastguard Worker }
503*f6dc9357SAndroid Build Coastguard Worker
504*f6dc9357SAndroid Build Coastguard Worker UInt64 lastFolderIndex = (UInt64)0 - 1;
505*f6dc9357SAndroid Build Coastguard Worker
506*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
507*f6dc9357SAndroid Build Coastguard Worker {
508*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
509*f6dc9357SAndroid Build Coastguard Worker const CItem &item = m_Database.Items[m_Database.Indices[index]];
510*f6dc9357SAndroid Build Coastguard Worker const UInt64 sectionIndex = item.Section;
511*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir() || item.Size == 0)
512*f6dc9357SAndroid Build Coastguard Worker continue;
513*f6dc9357SAndroid Build Coastguard Worker if (sectionIndex == 0)
514*f6dc9357SAndroid Build Coastguard Worker {
515*f6dc9357SAndroid Build Coastguard Worker currentTotalSize += item.Size;
516*f6dc9357SAndroid Build Coastguard Worker continue;
517*f6dc9357SAndroid Build Coastguard Worker }
518*f6dc9357SAndroid Build Coastguard Worker
519*f6dc9357SAndroid Build Coastguard Worker if (sectionIndex >= m_Database.Sections.Size())
520*f6dc9357SAndroid Build Coastguard Worker continue;
521*f6dc9357SAndroid Build Coastguard Worker
522*f6dc9357SAndroid Build Coastguard Worker const CSectionInfo §ion = m_Database.Sections[(unsigned)sectionIndex];
523*f6dc9357SAndroid Build Coastguard Worker if (section.IsLzx())
524*f6dc9357SAndroid Build Coastguard Worker {
525*f6dc9357SAndroid Build Coastguard Worker const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
526*f6dc9357SAndroid Build Coastguard Worker UInt64 folderIndex = m_Database.GetFolder(index);
527*f6dc9357SAndroid Build Coastguard Worker if (lastFolderIndex == folderIndex)
528*f6dc9357SAndroid Build Coastguard Worker folderIndex++;
529*f6dc9357SAndroid Build Coastguard Worker lastFolderIndex = m_Database.GetLastFolder(index);
530*f6dc9357SAndroid Build Coastguard Worker for (; folderIndex <= lastFolderIndex; folderIndex++)
531*f6dc9357SAndroid Build Coastguard Worker currentTotalSize += lzxInfo.GetFolderSize();
532*f6dc9357SAndroid Build Coastguard Worker }
533*f6dc9357SAndroid Build Coastguard Worker }
534*f6dc9357SAndroid Build Coastguard Worker
535*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(currentTotalSize))
536*f6dc9357SAndroid Build Coastguard Worker
537*f6dc9357SAndroid Build Coastguard Worker CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;
538*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CChmFolderOutStream> chmFolderOutStream;
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker currentTotalSize = 0;
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker CRecordVector<bool> extractStatuses;
543*f6dc9357SAndroid Build Coastguard Worker
544*f6dc9357SAndroid Build Coastguard Worker CByteBuffer packBuf;
545*f6dc9357SAndroid Build Coastguard Worker
546*f6dc9357SAndroid Build Coastguard Worker for (i = 0;;)
547*f6dc9357SAndroid Build Coastguard Worker {
548*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetCompleted(¤tTotalSize))
549*f6dc9357SAndroid Build Coastguard Worker
550*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
551*f6dc9357SAndroid Build Coastguard Worker break;
552*f6dc9357SAndroid Build Coastguard Worker
553*f6dc9357SAndroid Build Coastguard Worker UInt32 index = allFilesMode ? i : indices[i];
554*f6dc9357SAndroid Build Coastguard Worker i++;
555*f6dc9357SAndroid Build Coastguard Worker const CItem &item = m_Database.Items[m_Database.Indices[index]];
556*f6dc9357SAndroid Build Coastguard Worker const UInt64 sectionIndex = item.Section;
557*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode= testMode ?
558*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
559*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
560*f6dc9357SAndroid Build Coastguard Worker
561*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir())
562*f6dc9357SAndroid Build Coastguard Worker {
563*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
564*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
565*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
566*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
567*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
568*f6dc9357SAndroid Build Coastguard Worker continue;
569*f6dc9357SAndroid Build Coastguard Worker }
570*f6dc9357SAndroid Build Coastguard Worker
571*f6dc9357SAndroid Build Coastguard Worker lps->InSize = currentTotalSize; // Change it
572*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = currentTotalSize;
573*f6dc9357SAndroid Build Coastguard Worker
574*f6dc9357SAndroid Build Coastguard Worker if (item.Size == 0 || sectionIndex == 0)
575*f6dc9357SAndroid Build Coastguard Worker {
576*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
577*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
578*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
579*f6dc9357SAndroid Build Coastguard Worker continue;
580*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
581*f6dc9357SAndroid Build Coastguard Worker Int32 opRes = NExtract::NOperationResult::kOK;
582*f6dc9357SAndroid Build Coastguard Worker if (!testMode && item.Size != 0)
583*f6dc9357SAndroid Build Coastguard Worker {
584*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
585*f6dc9357SAndroid Build Coastguard Worker inStream->Init(item.Size);
586*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
587*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize != item.Size)
588*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
589*f6dc9357SAndroid Build Coastguard Worker }
590*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
591*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
592*f6dc9357SAndroid Build Coastguard Worker currentTotalSize += item.Size;
593*f6dc9357SAndroid Build Coastguard Worker continue;
594*f6dc9357SAndroid Build Coastguard Worker }
595*f6dc9357SAndroid Build Coastguard Worker
596*f6dc9357SAndroid Build Coastguard Worker if (sectionIndex >= m_Database.Sections.Size())
597*f6dc9357SAndroid Build Coastguard Worker {
598*f6dc9357SAndroid Build Coastguard Worker // we must report error here;
599*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
600*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
601*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
602*f6dc9357SAndroid Build Coastguard Worker continue;
603*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
604*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError))
605*f6dc9357SAndroid Build Coastguard Worker continue;
606*f6dc9357SAndroid Build Coastguard Worker }
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker const CSectionInfo §ion = m_Database.Sections[(unsigned)sectionIndex];
609*f6dc9357SAndroid Build Coastguard Worker
610*f6dc9357SAndroid Build Coastguard Worker if (!section.IsLzx())
611*f6dc9357SAndroid Build Coastguard Worker {
612*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
613*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
614*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
615*f6dc9357SAndroid Build Coastguard Worker continue;
616*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
617*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
618*f6dc9357SAndroid Build Coastguard Worker continue;
619*f6dc9357SAndroid Build Coastguard Worker }
620*f6dc9357SAndroid Build Coastguard Worker
621*f6dc9357SAndroid Build Coastguard Worker const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
622*f6dc9357SAndroid Build Coastguard Worker
623*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
624*f6dc9357SAndroid Build Coastguard Worker
625*f6dc9357SAndroid Build Coastguard Worker lzxDecoder.Create_if_Empty();
626*f6dc9357SAndroid Build Coastguard Worker
627*f6dc9357SAndroid Build Coastguard Worker UInt64 folderIndex = m_Database.GetFolder(index);
628*f6dc9357SAndroid Build Coastguard Worker
629*f6dc9357SAndroid Build Coastguard Worker const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
630*f6dc9357SAndroid Build Coastguard Worker RINOK(lzxDecoder->Set_DictBits_and_Alloc(lzxInfo.GetNumDictBits()))
631*f6dc9357SAndroid Build Coastguard Worker
632*f6dc9357SAndroid Build Coastguard Worker const CItem *lastItem = &item;
633*f6dc9357SAndroid Build Coastguard Worker extractStatuses.Clear();
634*f6dc9357SAndroid Build Coastguard Worker extractStatuses.Add(true);
635*f6dc9357SAndroid Build Coastguard Worker
636*f6dc9357SAndroid Build Coastguard Worker for (;; folderIndex++)
637*f6dc9357SAndroid Build Coastguard Worker {
638*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetCompleted(¤tTotalSize))
639*f6dc9357SAndroid Build Coastguard Worker
640*f6dc9357SAndroid Build Coastguard Worker const UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
641*f6dc9357SAndroid Build Coastguard Worker UInt64 finishPos = lastItem->Offset + lastItem->Size;
642*f6dc9357SAndroid Build Coastguard Worker const UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);
643*f6dc9357SAndroid Build Coastguard Worker
644*f6dc9357SAndroid Build Coastguard Worker lastFolderIndex = m_Database.GetLastFolder(index);
645*f6dc9357SAndroid Build Coastguard Worker const UInt64 folderSize = lzxInfo.GetFolderSize();
646*f6dc9357SAndroid Build Coastguard Worker UInt64 unPackSize = folderSize;
647*f6dc9357SAndroid Build Coastguard Worker
648*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses.IsEmpty())
649*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_StartIndex = index + 1;
650*f6dc9357SAndroid Build Coastguard Worker else
651*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_StartIndex = index;
652*f6dc9357SAndroid Build Coastguard Worker
653*f6dc9357SAndroid Build Coastguard Worker if (limitFolderIndex == folderIndex)
654*f6dc9357SAndroid Build Coastguard Worker {
655*f6dc9357SAndroid Build Coastguard Worker for (; i < numItems; i++)
656*f6dc9357SAndroid Build Coastguard Worker {
657*f6dc9357SAndroid Build Coastguard Worker const UInt32 nextIndex = allFilesMode ? i : indices[i];
658*f6dc9357SAndroid Build Coastguard Worker const CItem &nextItem = m_Database.Items[m_Database.Indices[nextIndex]];
659*f6dc9357SAndroid Build Coastguard Worker if (nextItem.Section != sectionIndex)
660*f6dc9357SAndroid Build Coastguard Worker break;
661*f6dc9357SAndroid Build Coastguard Worker const UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
662*f6dc9357SAndroid Build Coastguard Worker if (nextFolderIndex != folderIndex)
663*f6dc9357SAndroid Build Coastguard Worker break;
664*f6dc9357SAndroid Build Coastguard Worker for (index++; index < nextIndex; index++)
665*f6dc9357SAndroid Build Coastguard Worker extractStatuses.Add(false);
666*f6dc9357SAndroid Build Coastguard Worker extractStatuses.Add(true);
667*f6dc9357SAndroid Build Coastguard Worker index = nextIndex;
668*f6dc9357SAndroid Build Coastguard Worker lastItem = &nextItem;
669*f6dc9357SAndroid Build Coastguard Worker if (nextItem.Size != 0)
670*f6dc9357SAndroid Build Coastguard Worker finishPos = nextItem.Offset + nextItem.Size;
671*f6dc9357SAndroid Build Coastguard Worker lastFolderIndex = m_Database.GetLastFolder(index);
672*f6dc9357SAndroid Build Coastguard Worker }
673*f6dc9357SAndroid Build Coastguard Worker }
674*f6dc9357SAndroid Build Coastguard Worker
675*f6dc9357SAndroid Build Coastguard Worker unPackSize = MyMin(finishPos - startPos, unPackSize);
676*f6dc9357SAndroid Build Coastguard Worker
677*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_FolderSize = folderSize;
678*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_PosInFolder = 0;
679*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_PosInSection = startPos;
680*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_ExtractStatuses = &extractStatuses;
681*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_NumFiles = extractStatuses.Size();
682*f6dc9357SAndroid Build Coastguard Worker chmFolderOutStream->m_CurrentIndex = 0;
683*f6dc9357SAndroid Build Coastguard Worker
684*f6dc9357SAndroid Build Coastguard Worker try
685*f6dc9357SAndroid Build Coastguard Worker {
686*f6dc9357SAndroid Build Coastguard Worker const UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
687*f6dc9357SAndroid Build Coastguard Worker const CResetTable &rt = lzxInfo.ResetTable;
688*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
689*f6dc9357SAndroid Build Coastguard Worker
690*f6dc9357SAndroid Build Coastguard Worker for (UInt32 b = 0; b < numBlocks; b++)
691*f6dc9357SAndroid Build Coastguard Worker {
692*f6dc9357SAndroid Build Coastguard Worker UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;
693*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetCompleted(&completedSize))
694*f6dc9357SAndroid Build Coastguard Worker UInt64 bCur = startBlock + b;
695*f6dc9357SAndroid Build Coastguard Worker if (bCur >= rt.ResetOffsets.Size())
696*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
697*f6dc9357SAndroid Build Coastguard Worker const UInt64 offset = rt.ResetOffsets[(unsigned)bCur];
698*f6dc9357SAndroid Build Coastguard Worker UInt64 compressedSize;
699*f6dc9357SAndroid Build Coastguard Worker rt.GetCompressedSizeOfBlock(bCur, compressedSize);
700*f6dc9357SAndroid Build Coastguard Worker
701*f6dc9357SAndroid Build Coastguard Worker // chm writes full blocks. So we don't need to use reduced size for last block
702*f6dc9357SAndroid Build Coastguard Worker
703*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(m_Stream, compressedPos + offset))
704*f6dc9357SAndroid Build Coastguard Worker inStream->Init(compressedSize);
705*f6dc9357SAndroid Build Coastguard Worker
706*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->Set_KeepHistory(b > 0);
707*f6dc9357SAndroid Build Coastguard Worker
708*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_FALSE;
709*f6dc9357SAndroid Build Coastguard Worker if (compressedSize <= (1u << 30))
710*f6dc9357SAndroid Build Coastguard Worker {
711*f6dc9357SAndroid Build Coastguard Worker const unsigned kAdditionalInputSize = 32;
712*f6dc9357SAndroid Build Coastguard Worker const size_t compressedSizeT = (size_t)compressedSize;
713*f6dc9357SAndroid Build Coastguard Worker const size_t allocSize = compressedSizeT + kAdditionalInputSize;
714*f6dc9357SAndroid Build Coastguard Worker if (allocSize <= compressedSize)
715*f6dc9357SAndroid Build Coastguard Worker throw 2;
716*f6dc9357SAndroid Build Coastguard Worker packBuf.AllocAtLeast(allocSize);
717*f6dc9357SAndroid Build Coastguard Worker res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
718*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
719*f6dc9357SAndroid Build Coastguard Worker {
720*f6dc9357SAndroid Build Coastguard Worker memset(packBuf + compressedSizeT, 0xff, kAdditionalInputSize);
721*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->Set_KeepHistoryForNext(true);
722*f6dc9357SAndroid Build Coastguard Worker res = lzxDecoder->Code_WithExceedReadWrite(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize;
723*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
724*f6dc9357SAndroid Build Coastguard Worker res = WriteStream(chmFolderOutStream,
725*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->GetUnpackData(),
726*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->GetUnpackSize());
727*f6dc9357SAndroid Build Coastguard Worker }
728*f6dc9357SAndroid Build Coastguard Worker }
729*f6dc9357SAndroid Build Coastguard Worker
730*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
731*f6dc9357SAndroid Build Coastguard Worker {
732*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
733*f6dc9357SAndroid Build Coastguard Worker return res;
734*f6dc9357SAndroid Build Coastguard Worker throw 1;
735*f6dc9357SAndroid Build Coastguard Worker }
736*f6dc9357SAndroid Build Coastguard Worker }
737*f6dc9357SAndroid Build Coastguard Worker }
738*f6dc9357SAndroid Build Coastguard Worker catch(...)
739*f6dc9357SAndroid Build Coastguard Worker {
740*f6dc9357SAndroid Build Coastguard Worker RINOK(chmFolderOutStream->FlushCorrupted(unPackSize))
741*f6dc9357SAndroid Build Coastguard Worker }
742*f6dc9357SAndroid Build Coastguard Worker
743*f6dc9357SAndroid Build Coastguard Worker currentTotalSize += folderSize;
744*f6dc9357SAndroid Build Coastguard Worker if (folderIndex == lastFolderIndex)
745*f6dc9357SAndroid Build Coastguard Worker break;
746*f6dc9357SAndroid Build Coastguard Worker extractStatuses.Clear();
747*f6dc9357SAndroid Build Coastguard Worker }
748*f6dc9357SAndroid Build Coastguard Worker }
749*f6dc9357SAndroid Build Coastguard Worker return S_OK;
750*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
751*f6dc9357SAndroid Build Coastguard Worker }
752*f6dc9357SAndroid Build Coastguard Worker
753*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
754*f6dc9357SAndroid Build Coastguard Worker {
755*f6dc9357SAndroid Build Coastguard Worker *numItems = m_Database.NewFormat ? 1:
756*f6dc9357SAndroid Build Coastguard Worker (m_Database.LowLevel ?
757*f6dc9357SAndroid Build Coastguard Worker m_Database.Items.Size():
758*f6dc9357SAndroid Build Coastguard Worker m_Database.Indices.Size());
759*f6dc9357SAndroid Build Coastguard Worker return S_OK;
760*f6dc9357SAndroid Build Coastguard Worker }
761*f6dc9357SAndroid Build Coastguard Worker
762*f6dc9357SAndroid Build Coastguard Worker namespace NChm {
763*f6dc9357SAndroid Build Coastguard Worker
764*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 };
765*f6dc9357SAndroid Build Coastguard Worker
766*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_CLS(
767*f6dc9357SAndroid Build Coastguard Worker CHandler(false),
768*f6dc9357SAndroid Build Coastguard Worker "Chm", "chm chi chq chw", NULL, 0xE9,
769*f6dc9357SAndroid Build Coastguard Worker k_Signature,
770*f6dc9357SAndroid Build Coastguard Worker 0,
771*f6dc9357SAndroid Build Coastguard Worker 0,
772*f6dc9357SAndroid Build Coastguard Worker NULL)
773*f6dc9357SAndroid Build Coastguard Worker
774*f6dc9357SAndroid Build Coastguard Worker }
775*f6dc9357SAndroid Build Coastguard Worker
776*f6dc9357SAndroid Build Coastguard Worker namespace NHxs {
777*f6dc9357SAndroid Build Coastguard Worker
778*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 };
779*f6dc9357SAndroid Build Coastguard Worker
780*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_CLS(
781*f6dc9357SAndroid Build Coastguard Worker CHandler(true),
782*f6dc9357SAndroid Build Coastguard Worker "Hxs", "hxs hxi hxr hxq hxw lit", NULL, 0xCE,
783*f6dc9357SAndroid Build Coastguard Worker k_Signature,
784*f6dc9357SAndroid Build Coastguard Worker 0,
785*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kFindSignature,
786*f6dc9357SAndroid Build Coastguard Worker NULL)
787*f6dc9357SAndroid Build Coastguard Worker
788*f6dc9357SAndroid Build Coastguard Worker }
789*f6dc9357SAndroid Build Coastguard Worker
790*f6dc9357SAndroid Build Coastguard Worker }}
791