1*f6dc9357SAndroid Build Coastguard Worker // Archive/WimIn.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
8*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
10*f6dc9357SAndroid Build Coastguard Worker #else
11*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
12*f6dc9357SAndroid Build Coastguard Worker #endif
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringToInt.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/XpressDecoder.h"
25*f6dc9357SAndroid Build Coastguard Worker
26*f6dc9357SAndroid Build Coastguard Worker #include "../Common/OutStreamWithSha1.h"
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker #include "WimIn.h"
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
31*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
32*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
35*f6dc9357SAndroid Build Coastguard Worker namespace NWim {
36*f6dc9357SAndroid Build Coastguard Worker
GetLog_val_min_dest(const UInt32 val,unsigned i,unsigned & dest)37*f6dc9357SAndroid Build Coastguard Worker static bool inline GetLog_val_min_dest(const UInt32 val, unsigned i, unsigned &dest)
38*f6dc9357SAndroid Build Coastguard Worker {
39*f6dc9357SAndroid Build Coastguard Worker UInt32 v = (UInt32)1 << i;
40*f6dc9357SAndroid Build Coastguard Worker for (; i < 32; i++)
41*f6dc9357SAndroid Build Coastguard Worker {
42*f6dc9357SAndroid Build Coastguard Worker if (v == val)
43*f6dc9357SAndroid Build Coastguard Worker {
44*f6dc9357SAndroid Build Coastguard Worker dest = i;
45*f6dc9357SAndroid Build Coastguard Worker return true;
46*f6dc9357SAndroid Build Coastguard Worker }
47*f6dc9357SAndroid Build Coastguard Worker v += v;
48*f6dc9357SAndroid Build Coastguard Worker }
49*f6dc9357SAndroid Build Coastguard Worker return false;
50*f6dc9357SAndroid Build Coastguard Worker }
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker
UnpackChunk(ISequentialInStream * inStream,unsigned method,unsigned chunkSizeBits,size_t inSize,size_t outSize,ISequentialOutStream * outStream)53*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::UnpackChunk(
54*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *inStream,
55*f6dc9357SAndroid Build Coastguard Worker unsigned method, unsigned chunkSizeBits,
56*f6dc9357SAndroid Build Coastguard Worker size_t inSize, size_t outSize,
57*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *outStream)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker if (inSize == outSize)
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker }
62*f6dc9357SAndroid Build Coastguard Worker else if (method == NMethod::kXPRESS)
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker }
65*f6dc9357SAndroid Build Coastguard Worker else if (method == NMethod::kLZX)
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker lzxDecoder.Create_if_Empty();
68*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->Set_WimMode(true);
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker else if (method == NMethod::kLZMS)
71*f6dc9357SAndroid Build Coastguard Worker {
72*f6dc9357SAndroid Build Coastguard Worker lzmsDecoder.Create_if_Empty();
73*f6dc9357SAndroid Build Coastguard Worker }
74*f6dc9357SAndroid Build Coastguard Worker else
75*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
76*f6dc9357SAndroid Build Coastguard Worker
77*f6dc9357SAndroid Build Coastguard Worker const size_t chunkSize = (size_t)1 << chunkSizeBits;
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker {
80*f6dc9357SAndroid Build Coastguard Worker const unsigned
81*f6dc9357SAndroid Build Coastguard Worker kAdditionalOutputBufSize = MyMax(NCompress::NLzx::
82*f6dc9357SAndroid Build Coastguard Worker kAdditionalOutputBufSize, NCompress::NXpress::
83*f6dc9357SAndroid Build Coastguard Worker kAdditionalOutputBufSize);
84*f6dc9357SAndroid Build Coastguard Worker unpackBuf.EnsureCapacity(chunkSize + kAdditionalOutputBufSize);
85*f6dc9357SAndroid Build Coastguard Worker if (!unpackBuf.Data)
86*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker
89*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_FALSE;
90*f6dc9357SAndroid Build Coastguard Worker size_t unpackedSize = 0;
91*f6dc9357SAndroid Build Coastguard Worker
92*f6dc9357SAndroid Build Coastguard Worker if (inSize == outSize)
93*f6dc9357SAndroid Build Coastguard Worker {
94*f6dc9357SAndroid Build Coastguard Worker unpackedSize = outSize;
95*f6dc9357SAndroid Build Coastguard Worker res = ReadStream(inStream, unpackBuf.Data, &unpackedSize);
96*f6dc9357SAndroid Build Coastguard Worker TotalPacked += unpackedSize;
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker else if (inSize < chunkSize)
99*f6dc9357SAndroid Build Coastguard Worker {
100*f6dc9357SAndroid Build Coastguard Worker const unsigned kAdditionalInputSize = 32;
101*f6dc9357SAndroid Build Coastguard Worker packBuf.EnsureCapacity(chunkSize + kAdditionalInputSize);
102*f6dc9357SAndroid Build Coastguard Worker if (!packBuf.Data)
103*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
104*f6dc9357SAndroid Build Coastguard Worker
105*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, packBuf.Data, inSize))
106*f6dc9357SAndroid Build Coastguard Worker memset(packBuf.Data + inSize, 0xff, kAdditionalInputSize);
107*f6dc9357SAndroid Build Coastguard Worker
108*f6dc9357SAndroid Build Coastguard Worker TotalPacked += inSize;
109*f6dc9357SAndroid Build Coastguard Worker
110*f6dc9357SAndroid Build Coastguard Worker if (method == NMethod::kXPRESS)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker res = NCompress::NXpress::Decode_WithExceedWrite(packBuf.Data, inSize, unpackBuf.Data, outSize);
113*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
114*f6dc9357SAndroid Build Coastguard Worker unpackedSize = outSize;
115*f6dc9357SAndroid Build Coastguard Worker }
116*f6dc9357SAndroid Build Coastguard Worker else if (method == NMethod::kLZX)
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker res = lzxDecoder->Set_ExternalWindow_DictBits(unpackBuf.Data, chunkSizeBits);
119*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
120*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
121*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->Set_KeepHistoryForNext(false);
122*f6dc9357SAndroid Build Coastguard Worker lzxDecoder->Set_KeepHistory(false);
123*f6dc9357SAndroid Build Coastguard Worker res = lzxDecoder->Code_WithExceedReadWrite(packBuf.Data, inSize, (UInt32)outSize);
124*f6dc9357SAndroid Build Coastguard Worker unpackedSize = lzxDecoder->GetUnpackSize();
125*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && !lzxDecoder->WasBlockFinished())
126*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker else
129*f6dc9357SAndroid Build Coastguard Worker {
130*f6dc9357SAndroid Build Coastguard Worker res = lzmsDecoder->Code(packBuf.Data, inSize, unpackBuf.Data, outSize);
131*f6dc9357SAndroid Build Coastguard Worker unpackedSize = lzmsDecoder->GetUnpackSize();
132*f6dc9357SAndroid Build Coastguard Worker }
133*f6dc9357SAndroid Build Coastguard Worker }
134*f6dc9357SAndroid Build Coastguard Worker
135*f6dc9357SAndroid Build Coastguard Worker if (unpackedSize != outSize)
136*f6dc9357SAndroid Build Coastguard Worker {
137*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
138*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
139*f6dc9357SAndroid Build Coastguard Worker
140*f6dc9357SAndroid Build Coastguard Worker if (unpackedSize > outSize)
141*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
142*f6dc9357SAndroid Build Coastguard Worker else
143*f6dc9357SAndroid Build Coastguard Worker memset(unpackBuf.Data + unpackedSize, 0, outSize - unpackedSize);
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker
146*f6dc9357SAndroid Build Coastguard Worker if (outStream)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, unpackBuf.Data, outSize))
149*f6dc9357SAndroid Build Coastguard Worker }
150*f6dc9357SAndroid Build Coastguard Worker
151*f6dc9357SAndroid Build Coastguard Worker return res;
152*f6dc9357SAndroid Build Coastguard Worker }
153*f6dc9357SAndroid Build Coastguard Worker
154*f6dc9357SAndroid Build Coastguard Worker
Unpack2(IInStream * inStream,const CResource & resource,const CHeader & header,const CDatabase * db,ISequentialOutStream * outStream,ICompressProgressInfo * progress)155*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::Unpack2(
156*f6dc9357SAndroid Build Coastguard Worker IInStream *inStream,
157*f6dc9357SAndroid Build Coastguard Worker const CResource &resource,
158*f6dc9357SAndroid Build Coastguard Worker const CHeader &header,
159*f6dc9357SAndroid Build Coastguard Worker const CDatabase *db,
160*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *outStream,
161*f6dc9357SAndroid Build Coastguard Worker ICompressProgressInfo *progress)
162*f6dc9357SAndroid Build Coastguard Worker {
163*f6dc9357SAndroid Build Coastguard Worker if (!resource.IsCompressed() && !resource.IsSolid())
164*f6dc9357SAndroid Build Coastguard Worker {
165*f6dc9357SAndroid Build Coastguard Worker copyCoder.Create_if_Empty();
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> limitedStream;
168*f6dc9357SAndroid Build Coastguard Worker limitedStream->SetStream(inStream);
169*f6dc9357SAndroid Build Coastguard Worker
170*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, resource.Offset))
171*f6dc9357SAndroid Build Coastguard Worker if (resource.PackSize != resource.UnpackSize)
172*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
173*f6dc9357SAndroid Build Coastguard Worker
174*f6dc9357SAndroid Build Coastguard Worker limitedStream->Init(resource.PackSize);
175*f6dc9357SAndroid Build Coastguard Worker TotalPacked += resource.PackSize;
176*f6dc9357SAndroid Build Coastguard Worker
177*f6dc9357SAndroid Build Coastguard Worker HRESULT res = copyCoder.Interface()->Code(limitedStream, outStream, NULL, NULL, progress);
178*f6dc9357SAndroid Build Coastguard Worker
179*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && copyCoder->TotalSize != resource.UnpackSize)
180*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
181*f6dc9357SAndroid Build Coastguard Worker return res;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker
184*f6dc9357SAndroid Build Coastguard Worker if (resource.IsSolid())
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker if (!db || resource.SolidIndex < 0)
187*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
188*f6dc9357SAndroid Build Coastguard Worker if (resource.IsCompressed())
189*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
190*f6dc9357SAndroid Build Coastguard Worker
191*f6dc9357SAndroid Build Coastguard Worker const CSolid &ss = db->Solids[resource.SolidIndex];
192*f6dc9357SAndroid Build Coastguard Worker
193*f6dc9357SAndroid Build Coastguard Worker const unsigned chunkSizeBits = ss.ChunkSizeBits;
194*f6dc9357SAndroid Build Coastguard Worker const size_t chunkSize = (size_t)1 << chunkSizeBits;
195*f6dc9357SAndroid Build Coastguard Worker
196*f6dc9357SAndroid Build Coastguard Worker size_t chunkIndex = 0;
197*f6dc9357SAndroid Build Coastguard Worker UInt64 rem = ss.UnpackSize;
198*f6dc9357SAndroid Build Coastguard Worker size_t offsetInChunk = 0;
199*f6dc9357SAndroid Build Coastguard Worker
200*f6dc9357SAndroid Build Coastguard Worker if (resource.IsSolidSmall())
201*f6dc9357SAndroid Build Coastguard Worker {
202*f6dc9357SAndroid Build Coastguard Worker UInt64 offs = resource.Offset;
203*f6dc9357SAndroid Build Coastguard Worker if (offs < ss.SolidOffset)
204*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
205*f6dc9357SAndroid Build Coastguard Worker offs -= ss.SolidOffset;
206*f6dc9357SAndroid Build Coastguard Worker if (offs > ss.UnpackSize)
207*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
208*f6dc9357SAndroid Build Coastguard Worker rem = resource.PackSize;
209*f6dc9357SAndroid Build Coastguard Worker if (rem > ss.UnpackSize - offs)
210*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
211*f6dc9357SAndroid Build Coastguard Worker chunkIndex = (size_t)(offs >> chunkSizeBits);
212*f6dc9357SAndroid Build Coastguard Worker offsetInChunk = (size_t)offs & (chunkSize - 1);
213*f6dc9357SAndroid Build Coastguard Worker }
214*f6dc9357SAndroid Build Coastguard Worker
215*f6dc9357SAndroid Build Coastguard Worker UInt64 packProcessed = 0;
216*f6dc9357SAndroid Build Coastguard Worker UInt64 outProcessed = 0;
217*f6dc9357SAndroid Build Coastguard Worker
218*f6dc9357SAndroid Build Coastguard Worker if (_solidIndex == resource.SolidIndex && _unpackedChunkIndex == chunkIndex)
219*f6dc9357SAndroid Build Coastguard Worker {
220*f6dc9357SAndroid Build Coastguard Worker size_t cur = chunkSize - offsetInChunk;
221*f6dc9357SAndroid Build Coastguard Worker if (cur > rem)
222*f6dc9357SAndroid Build Coastguard Worker cur = (size_t)rem;
223*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, unpackBuf.Data + offsetInChunk, cur))
224*f6dc9357SAndroid Build Coastguard Worker outProcessed += cur;
225*f6dc9357SAndroid Build Coastguard Worker rem -= cur;
226*f6dc9357SAndroid Build Coastguard Worker offsetInChunk = 0;
227*f6dc9357SAndroid Build Coastguard Worker chunkIndex++;
228*f6dc9357SAndroid Build Coastguard Worker }
229*f6dc9357SAndroid Build Coastguard Worker
230*f6dc9357SAndroid Build Coastguard Worker for (;;)
231*f6dc9357SAndroid Build Coastguard Worker {
232*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
233*f6dc9357SAndroid Build Coastguard Worker return S_OK;
234*f6dc9357SAndroid Build Coastguard Worker
235*f6dc9357SAndroid Build Coastguard Worker const UInt64 offset = ss.Chunks[chunkIndex];
236*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSize = ss.GetChunkPackSize(chunkIndex);
237*f6dc9357SAndroid Build Coastguard Worker const CResource &rs = db->DataStreams[ss.StreamIndex].Resource;
238*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, rs.Offset + ss.HeadersSize + offset))
239*f6dc9357SAndroid Build Coastguard Worker
240*f6dc9357SAndroid Build Coastguard Worker size_t cur = chunkSize;
241*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackRem = ss.UnpackSize - ((UInt64)chunkIndex << chunkSizeBits);
242*f6dc9357SAndroid Build Coastguard Worker if (cur > unpackRem)
243*f6dc9357SAndroid Build Coastguard Worker cur = (size_t)unpackRem;
244*f6dc9357SAndroid Build Coastguard Worker
245*f6dc9357SAndroid Build Coastguard Worker _solidIndex = -1;
246*f6dc9357SAndroid Build Coastguard Worker _unpackedChunkIndex = 0;
247*f6dc9357SAndroid Build Coastguard Worker
248*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = UnpackChunk(inStream, (unsigned)ss.Method, chunkSizeBits, (size_t)packSize, cur, NULL);
249*f6dc9357SAndroid Build Coastguard Worker
250*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
251*f6dc9357SAndroid Build Coastguard Worker {
252*f6dc9357SAndroid Build Coastguard Worker // We ignore data errors in solid stream. SHA will show what files are bad.
253*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
254*f6dc9357SAndroid Build Coastguard Worker return res;
255*f6dc9357SAndroid Build Coastguard Worker }
256*f6dc9357SAndroid Build Coastguard Worker
257*f6dc9357SAndroid Build Coastguard Worker _solidIndex = resource.SolidIndex;
258*f6dc9357SAndroid Build Coastguard Worker _unpackedChunkIndex = chunkIndex;
259*f6dc9357SAndroid Build Coastguard Worker
260*f6dc9357SAndroid Build Coastguard Worker if (cur < offsetInChunk)
261*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
262*f6dc9357SAndroid Build Coastguard Worker
263*f6dc9357SAndroid Build Coastguard Worker cur -= offsetInChunk;
264*f6dc9357SAndroid Build Coastguard Worker
265*f6dc9357SAndroid Build Coastguard Worker if (cur > rem)
266*f6dc9357SAndroid Build Coastguard Worker cur = (size_t)rem;
267*f6dc9357SAndroid Build Coastguard Worker
268*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, unpackBuf.Data + offsetInChunk, cur))
269*f6dc9357SAndroid Build Coastguard Worker
270*f6dc9357SAndroid Build Coastguard Worker if (progress)
271*f6dc9357SAndroid Build Coastguard Worker {
272*f6dc9357SAndroid Build Coastguard Worker RINOK(progress->SetRatioInfo(&packProcessed, &outProcessed))
273*f6dc9357SAndroid Build Coastguard Worker packProcessed += packSize;
274*f6dc9357SAndroid Build Coastguard Worker outProcessed += cur;
275*f6dc9357SAndroid Build Coastguard Worker }
276*f6dc9357SAndroid Build Coastguard Worker
277*f6dc9357SAndroid Build Coastguard Worker rem -= cur;
278*f6dc9357SAndroid Build Coastguard Worker offsetInChunk = 0;
279*f6dc9357SAndroid Build Coastguard Worker chunkIndex++;
280*f6dc9357SAndroid Build Coastguard Worker }
281*f6dc9357SAndroid Build Coastguard Worker }
282*f6dc9357SAndroid Build Coastguard Worker
283*f6dc9357SAndroid Build Coastguard Worker
284*f6dc9357SAndroid Build Coastguard Worker // ---------- NON Solid ----------
285*f6dc9357SAndroid Build Coastguard Worker
286*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize = resource.UnpackSize;
287*f6dc9357SAndroid Build Coastguard Worker if (unpackSize == 0)
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker if (resource.PackSize == 0)
290*f6dc9357SAndroid Build Coastguard Worker return S_OK;
291*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
292*f6dc9357SAndroid Build Coastguard Worker }
293*f6dc9357SAndroid Build Coastguard Worker
294*f6dc9357SAndroid Build Coastguard Worker if (unpackSize > ((UInt64)1 << 63))
295*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
296*f6dc9357SAndroid Build Coastguard Worker
297*f6dc9357SAndroid Build Coastguard Worker const unsigned chunkSizeBits = header.ChunkSizeBits;
298*f6dc9357SAndroid Build Coastguard Worker const unsigned entrySizeShifts = (resource.UnpackSize < ((UInt64)1 << 32) ? 2 : 3);
299*f6dc9357SAndroid Build Coastguard Worker
300*f6dc9357SAndroid Build Coastguard Worker UInt64 baseOffset = resource.Offset;
301*f6dc9357SAndroid Build Coastguard Worker UInt64 packDataSize;
302*f6dc9357SAndroid Build Coastguard Worker size_t numChunks;
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker const UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits;
305*f6dc9357SAndroid Build Coastguard Worker const UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts;
306*f6dc9357SAndroid Build Coastguard Worker if (sizesBufSize64 > resource.PackSize)
307*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
308*f6dc9357SAndroid Build Coastguard Worker packDataSize = resource.PackSize - sizesBufSize64;
309*f6dc9357SAndroid Build Coastguard Worker const size_t sizesBufSize = (size_t)sizesBufSize64;
310*f6dc9357SAndroid Build Coastguard Worker if (sizesBufSize != sizesBufSize64)
311*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
312*f6dc9357SAndroid Build Coastguard Worker sizesBuf.AllocAtLeast(sizesBufSize);
313*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, baseOffset))
314*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, sizesBuf, sizesBufSize))
315*f6dc9357SAndroid Build Coastguard Worker baseOffset += sizesBufSize64;
316*f6dc9357SAndroid Build Coastguard Worker numChunks = (size_t)numChunks64;
317*f6dc9357SAndroid Build Coastguard Worker }
318*f6dc9357SAndroid Build Coastguard Worker
319*f6dc9357SAndroid Build Coastguard Worker _solidIndex = -1;
320*f6dc9357SAndroid Build Coastguard Worker _unpackedChunkIndex = 0;
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker UInt64 outProcessed = 0;
323*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = 0;
324*f6dc9357SAndroid Build Coastguard Worker
325*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < numChunks; i++)
326*f6dc9357SAndroid Build Coastguard Worker {
327*f6dc9357SAndroid Build Coastguard Worker UInt64 nextOffset = packDataSize;
328*f6dc9357SAndroid Build Coastguard Worker
329*f6dc9357SAndroid Build Coastguard Worker if (i + 1 < numChunks)
330*f6dc9357SAndroid Build Coastguard Worker {
331*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)sizesBuf + (i << entrySizeShifts);
332*f6dc9357SAndroid Build Coastguard Worker nextOffset = (entrySizeShifts == 2) ? Get32(p): Get64(p);
333*f6dc9357SAndroid Build Coastguard Worker }
334*f6dc9357SAndroid Build Coastguard Worker
335*f6dc9357SAndroid Build Coastguard Worker if (nextOffset < offset)
336*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
337*f6dc9357SAndroid Build Coastguard Worker
338*f6dc9357SAndroid Build Coastguard Worker UInt64 inSize64 = nextOffset - offset;
339*f6dc9357SAndroid Build Coastguard Worker size_t inSize = (size_t)inSize64;
340*f6dc9357SAndroid Build Coastguard Worker if (inSize != inSize64)
341*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
342*f6dc9357SAndroid Build Coastguard Worker
343*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, baseOffset + offset))
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker if (progress)
346*f6dc9357SAndroid Build Coastguard Worker {
347*f6dc9357SAndroid Build Coastguard Worker RINOK(progress->SetRatioInfo(&offset, &outProcessed))
348*f6dc9357SAndroid Build Coastguard Worker }
349*f6dc9357SAndroid Build Coastguard Worker
350*f6dc9357SAndroid Build Coastguard Worker size_t outSize = (size_t)1 << chunkSizeBits;
351*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = unpackSize - outProcessed;
352*f6dc9357SAndroid Build Coastguard Worker if (outSize > rem)
353*f6dc9357SAndroid Build Coastguard Worker outSize = (size_t)rem;
354*f6dc9357SAndroid Build Coastguard Worker
355*f6dc9357SAndroid Build Coastguard Worker RINOK(UnpackChunk(inStream, header.GetMethod(), chunkSizeBits, inSize, outSize, outStream))
356*f6dc9357SAndroid Build Coastguard Worker
357*f6dc9357SAndroid Build Coastguard Worker outProcessed += outSize;
358*f6dc9357SAndroid Build Coastguard Worker offset = nextOffset;
359*f6dc9357SAndroid Build Coastguard Worker }
360*f6dc9357SAndroid Build Coastguard Worker
361*f6dc9357SAndroid Build Coastguard Worker return S_OK;
362*f6dc9357SAndroid Build Coastguard Worker }
363*f6dc9357SAndroid Build Coastguard Worker
364*f6dc9357SAndroid Build Coastguard Worker
Unpack(IInStream * inStream,const CResource & resource,const CHeader & header,const CDatabase * db,ISequentialOutStream * outStream,ICompressProgressInfo * progress,Byte * digest)365*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, const CHeader &header, const CDatabase *db,
366*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)
367*f6dc9357SAndroid Build Coastguard Worker {
368*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha1> shaStream;
369*f6dc9357SAndroid Build Coastguard Worker // outStream can be NULL, so we use COutStreamWithSha1 even if sha1 is not required
370*f6dc9357SAndroid Build Coastguard Worker shaStream->SetStream(outStream);
371*f6dc9357SAndroid Build Coastguard Worker shaStream->Init(digest != NULL);
372*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = Unpack2(inStream, resource, header, db, shaStream, progress);
373*f6dc9357SAndroid Build Coastguard Worker if (digest)
374*f6dc9357SAndroid Build Coastguard Worker shaStream->Final(digest);
375*f6dc9357SAndroid Build Coastguard Worker return res;
376*f6dc9357SAndroid Build Coastguard Worker }
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker
UnpackData(IInStream * inStream,const CResource & resource,const CHeader & header,const CDatabase * db,CByteBuffer & buf,Byte * digest)379*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::UnpackData(IInStream *inStream,
380*f6dc9357SAndroid Build Coastguard Worker const CResource &resource, const CHeader &header,
381*f6dc9357SAndroid Build Coastguard Worker const CDatabase *db,
382*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buf, Byte *digest)
383*f6dc9357SAndroid Build Coastguard Worker {
384*f6dc9357SAndroid Build Coastguard Worker // if (resource.IsSolid()) return E_NOTIMPL;
385*f6dc9357SAndroid Build Coastguard Worker UInt64 unpackSize64 = resource.UnpackSize;
386*f6dc9357SAndroid Build Coastguard Worker if (db)
387*f6dc9357SAndroid Build Coastguard Worker unpackSize64 = db->Get_UnpackSize_of_Resource(resource);
388*f6dc9357SAndroid Build Coastguard Worker const size_t size = (size_t)unpackSize64;
389*f6dc9357SAndroid Build Coastguard Worker if (size != unpackSize64)
390*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
391*f6dc9357SAndroid Build Coastguard Worker buf.Alloc(size);
392*f6dc9357SAndroid Build Coastguard Worker
393*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
394*f6dc9357SAndroid Build Coastguard Worker outStream->Init((Byte *)buf, size);
395*f6dc9357SAndroid Build Coastguard Worker return Unpack(inStream, resource, header, db, outStream, NULL, digest);
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker
398*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)399*f6dc9357SAndroid Build Coastguard Worker void CResource::Parse(const Byte *p)
400*f6dc9357SAndroid Build Coastguard Worker {
401*f6dc9357SAndroid Build Coastguard Worker Flags = p[7];
402*f6dc9357SAndroid Build Coastguard Worker PackSize = Get64(p) & (((UInt64)1 << 56) - 1);
403*f6dc9357SAndroid Build Coastguard Worker Offset = Get64(p + 8);
404*f6dc9357SAndroid Build Coastguard Worker UnpackSize = Get64(p + 16);
405*f6dc9357SAndroid Build Coastguard Worker KeepSolid = false;
406*f6dc9357SAndroid Build Coastguard Worker SolidIndex = -1;
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker
409*f6dc9357SAndroid Build Coastguard Worker #define GET_RESOURCE(_p_, res) res.ParseAndUpdatePhySize(_p_, phySize)
410*f6dc9357SAndroid Build Coastguard Worker
ParseStream(bool oldVersion,const Byte * p,CStreamInfo & s)411*f6dc9357SAndroid Build Coastguard Worker static inline void ParseStream(bool oldVersion, const Byte *p, CStreamInfo &s)
412*f6dc9357SAndroid Build Coastguard Worker {
413*f6dc9357SAndroid Build Coastguard Worker s.Resource.Parse(p);
414*f6dc9357SAndroid Build Coastguard Worker if (oldVersion)
415*f6dc9357SAndroid Build Coastguard Worker {
416*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = 1;
417*f6dc9357SAndroid Build Coastguard Worker s.Id = Get32(p + 24);
418*f6dc9357SAndroid Build Coastguard Worker p += 28;
419*f6dc9357SAndroid Build Coastguard Worker }
420*f6dc9357SAndroid Build Coastguard Worker else
421*f6dc9357SAndroid Build Coastguard Worker {
422*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = Get16(p + 24);
423*f6dc9357SAndroid Build Coastguard Worker p += 26;
424*f6dc9357SAndroid Build Coastguard Worker }
425*f6dc9357SAndroid Build Coastguard Worker s.RefCount = Get32(p);
426*f6dc9357SAndroid Build Coastguard Worker memcpy(s.Hash, p + 4, kHashSize);
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker
429*f6dc9357SAndroid Build Coastguard Worker
430*f6dc9357SAndroid Build Coastguard Worker #define kLongPath "[LongPath]"
431*f6dc9357SAndroid Build Coastguard Worker
GetShortName(unsigned index,NWindows::NCOM::CPropVariant & name) const432*f6dc9357SAndroid Build Coastguard Worker void CDatabase::GetShortName(unsigned index, NWindows::NCOM::CPropVariant &name) const
433*f6dc9357SAndroid Build Coastguard Worker {
434*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
435*f6dc9357SAndroid Build Coastguard Worker const CImage &image = Images[item.ImageIndex];
436*f6dc9357SAndroid Build Coastguard Worker if (item.Parent < 0 && image.NumEmptyRootItems != 0)
437*f6dc9357SAndroid Build Coastguard Worker {
438*f6dc9357SAndroid Build Coastguard Worker name.Clear();
439*f6dc9357SAndroid Build Coastguard Worker return;
440*f6dc9357SAndroid Build Coastguard Worker }
441*f6dc9357SAndroid Build Coastguard Worker const Byte *meta = image.Meta + item.Offset +
442*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? kDirRecordSizeOld : kDirRecordSize);
443*f6dc9357SAndroid Build Coastguard Worker UInt32 fileNameLen = Get16(meta - 2);
444*f6dc9357SAndroid Build Coastguard Worker UInt32 shortLen = Get16(meta - 4) / 2;
445*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = name.AllocBstr(shortLen);
446*f6dc9357SAndroid Build Coastguard Worker if (fileNameLen != 0)
447*f6dc9357SAndroid Build Coastguard Worker meta += fileNameLen + 2;
448*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < shortLen; i++)
449*f6dc9357SAndroid Build Coastguard Worker s[i] = Get16(meta + i * 2);
450*f6dc9357SAndroid Build Coastguard Worker s[shortLen] = 0;
451*f6dc9357SAndroid Build Coastguard Worker // empty shortName has no ZERO at the end ?
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker
454*f6dc9357SAndroid Build Coastguard Worker
GetItemName(unsigned index,NWindows::NCOM::CPropVariant & name) const455*f6dc9357SAndroid Build Coastguard Worker void CDatabase::GetItemName(unsigned index, NWindows::NCOM::CPropVariant &name) const
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
458*f6dc9357SAndroid Build Coastguard Worker const CImage &image = Images[item.ImageIndex];
459*f6dc9357SAndroid Build Coastguard Worker if (item.Parent < 0 && image.NumEmptyRootItems != 0)
460*f6dc9357SAndroid Build Coastguard Worker {
461*f6dc9357SAndroid Build Coastguard Worker name = image.RootName;
462*f6dc9357SAndroid Build Coastguard Worker return;
463*f6dc9357SAndroid Build Coastguard Worker }
464*f6dc9357SAndroid Build Coastguard Worker const Byte *meta = image.Meta + item.Offset +
465*f6dc9357SAndroid Build Coastguard Worker (item.IsAltStream ?
466*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? 0x10 : 0x24) :
467*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2));
468*f6dc9357SAndroid Build Coastguard Worker UInt32 len = Get16(meta) / 2;
469*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = name.AllocBstr(len);
470*f6dc9357SAndroid Build Coastguard Worker meta += 2;
471*f6dc9357SAndroid Build Coastguard Worker len++;
472*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < len; i++)
473*f6dc9357SAndroid Build Coastguard Worker s[i] = Get16(meta + i * 2);
474*f6dc9357SAndroid Build Coastguard Worker }
475*f6dc9357SAndroid Build Coastguard Worker
476*f6dc9357SAndroid Build Coastguard Worker
GetItemPath(unsigned index1,bool showImageNumber,NWindows::NCOM::CPropVariant & path) const477*f6dc9357SAndroid Build Coastguard Worker void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCOM::CPropVariant &path) const
478*f6dc9357SAndroid Build Coastguard Worker {
479*f6dc9357SAndroid Build Coastguard Worker unsigned size = 0;
480*f6dc9357SAndroid Build Coastguard Worker int index = (int)index1;
481*f6dc9357SAndroid Build Coastguard Worker const int imageIndex = Items[index].ImageIndex;
482*f6dc9357SAndroid Build Coastguard Worker const CImage &image = Images[imageIndex];
483*f6dc9357SAndroid Build Coastguard Worker
484*f6dc9357SAndroid Build Coastguard Worker unsigned newLevel = 0;
485*f6dc9357SAndroid Build Coastguard Worker bool needColon = false;
486*f6dc9357SAndroid Build Coastguard Worker
487*f6dc9357SAndroid Build Coastguard Worker for (;;)
488*f6dc9357SAndroid Build Coastguard Worker {
489*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
490*f6dc9357SAndroid Build Coastguard Worker index = item.Parent;
491*f6dc9357SAndroid Build Coastguard Worker if (index >= 0 || image.NumEmptyRootItems == 0)
492*f6dc9357SAndroid Build Coastguard Worker {
493*f6dc9357SAndroid Build Coastguard Worker const Byte *meta = image.Meta + item.Offset;
494*f6dc9357SAndroid Build Coastguard Worker meta += item.IsAltStream ?
495*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? 0x10 : 0x24) :
496*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
497*f6dc9357SAndroid Build Coastguard Worker needColon = item.IsAltStream;
498*f6dc9357SAndroid Build Coastguard Worker size += Get16(meta) / 2;
499*f6dc9357SAndroid Build Coastguard Worker size += newLevel;
500*f6dc9357SAndroid Build Coastguard Worker newLevel = 1;
501*f6dc9357SAndroid Build Coastguard Worker if (size >= ((UInt32)1 << 15))
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker path = kLongPath;
504*f6dc9357SAndroid Build Coastguard Worker return;
505*f6dc9357SAndroid Build Coastguard Worker }
506*f6dc9357SAndroid Build Coastguard Worker }
507*f6dc9357SAndroid Build Coastguard Worker if (index < 0)
508*f6dc9357SAndroid Build Coastguard Worker break;
509*f6dc9357SAndroid Build Coastguard Worker }
510*f6dc9357SAndroid Build Coastguard Worker
511*f6dc9357SAndroid Build Coastguard Worker if (showImageNumber)
512*f6dc9357SAndroid Build Coastguard Worker {
513*f6dc9357SAndroid Build Coastguard Worker size += image.RootName.Len();
514*f6dc9357SAndroid Build Coastguard Worker size += newLevel;
515*f6dc9357SAndroid Build Coastguard Worker }
516*f6dc9357SAndroid Build Coastguard Worker else if (needColon)
517*f6dc9357SAndroid Build Coastguard Worker size++;
518*f6dc9357SAndroid Build Coastguard Worker
519*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path.AllocBstr(size);
520*f6dc9357SAndroid Build Coastguard Worker s[size] = 0;
521*f6dc9357SAndroid Build Coastguard Worker
522*f6dc9357SAndroid Build Coastguard Worker if (showImageNumber)
523*f6dc9357SAndroid Build Coastguard Worker {
524*f6dc9357SAndroid Build Coastguard Worker MyStringCopy(s, (const wchar_t *)image.RootName);
525*f6dc9357SAndroid Build Coastguard Worker if (newLevel)
526*f6dc9357SAndroid Build Coastguard Worker s[image.RootName.Len()] = (wchar_t)(needColon ? L':' : WCHAR_PATH_SEPARATOR);
527*f6dc9357SAndroid Build Coastguard Worker }
528*f6dc9357SAndroid Build Coastguard Worker else if (needColon)
529*f6dc9357SAndroid Build Coastguard Worker s[0] = L':';
530*f6dc9357SAndroid Build Coastguard Worker
531*f6dc9357SAndroid Build Coastguard Worker index = (int)index1;
532*f6dc9357SAndroid Build Coastguard Worker wchar_t separator = 0;
533*f6dc9357SAndroid Build Coastguard Worker
534*f6dc9357SAndroid Build Coastguard Worker for (;;)
535*f6dc9357SAndroid Build Coastguard Worker {
536*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[index];
537*f6dc9357SAndroid Build Coastguard Worker index = item.Parent;
538*f6dc9357SAndroid Build Coastguard Worker if (index >= 0 || image.NumEmptyRootItems == 0)
539*f6dc9357SAndroid Build Coastguard Worker {
540*f6dc9357SAndroid Build Coastguard Worker if (separator != 0)
541*f6dc9357SAndroid Build Coastguard Worker s[--size] = separator;
542*f6dc9357SAndroid Build Coastguard Worker const Byte *meta = image.Meta + item.Offset;
543*f6dc9357SAndroid Build Coastguard Worker meta += (item.IsAltStream) ?
544*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? 0x10: 0x24) :
545*f6dc9357SAndroid Build Coastguard Worker (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
546*f6dc9357SAndroid Build Coastguard Worker unsigned len = Get16(meta) / 2;
547*f6dc9357SAndroid Build Coastguard Worker size -= len;
548*f6dc9357SAndroid Build Coastguard Worker wchar_t *dest = s + size;
549*f6dc9357SAndroid Build Coastguard Worker meta += 2;
550*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < len; i++)
551*f6dc9357SAndroid Build Coastguard Worker {
552*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(meta + i * 2);
553*f6dc9357SAndroid Build Coastguard Worker if (c == L'/')
554*f6dc9357SAndroid Build Coastguard Worker c = L'_';
555*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_PATH_SEPARATOR != L'/'
556*f6dc9357SAndroid Build Coastguard Worker else if (c == L'\\')
557*f6dc9357SAndroid Build Coastguard Worker c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // 22.00 : WSL scheme
558*f6dc9357SAndroid Build Coastguard Worker #endif
559*f6dc9357SAndroid Build Coastguard Worker dest[i] = c;
560*f6dc9357SAndroid Build Coastguard Worker }
561*f6dc9357SAndroid Build Coastguard Worker }
562*f6dc9357SAndroid Build Coastguard Worker if (index < 0)
563*f6dc9357SAndroid Build Coastguard Worker return;
564*f6dc9357SAndroid Build Coastguard Worker separator = item.IsAltStream ? L':' : WCHAR_PATH_SEPARATOR;
565*f6dc9357SAndroid Build Coastguard Worker }
566*f6dc9357SAndroid Build Coastguard Worker }
567*f6dc9357SAndroid Build Coastguard Worker
568*f6dc9357SAndroid Build Coastguard Worker
569*f6dc9357SAndroid Build Coastguard Worker // if (ver <= 1.10), root folder contains real items.
570*f6dc9357SAndroid Build Coastguard Worker // if (ver >= 1.12), root folder contains only one folder with empty name.
571*f6dc9357SAndroid Build Coastguard Worker
ParseDirItem(size_t pos,int parent)572*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
573*f6dc9357SAndroid Build Coastguard Worker {
574*f6dc9357SAndroid Build Coastguard Worker const unsigned align = GetDirAlignMask();
575*f6dc9357SAndroid Build Coastguard Worker if ((pos & align) != 0)
576*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
577*f6dc9357SAndroid Build Coastguard Worker
578*f6dc9357SAndroid Build Coastguard Worker for (unsigned numItems = 0;; numItems++)
579*f6dc9357SAndroid Build Coastguard Worker {
580*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback && (Items.Size() & 0xFFFF) == 0)
581*f6dc9357SAndroid Build Coastguard Worker {
582*f6dc9357SAndroid Build Coastguard Worker UInt64 numFiles = Items.Size();
583*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenCallback->SetCompleted(&numFiles, NULL))
584*f6dc9357SAndroid Build Coastguard Worker }
585*f6dc9357SAndroid Build Coastguard Worker
586*f6dc9357SAndroid Build Coastguard Worker const size_t rem = DirSize - pos;
587*f6dc9357SAndroid Build Coastguard Worker if (pos < DirStartOffset || pos > DirSize || rem < 8)
588*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
589*f6dc9357SAndroid Build Coastguard Worker
590*f6dc9357SAndroid Build Coastguard Worker const Byte *p = DirData + pos;
591*f6dc9357SAndroid Build Coastguard Worker
592*f6dc9357SAndroid Build Coastguard Worker UInt64 len = Get64(p);
593*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
594*f6dc9357SAndroid Build Coastguard Worker {
595*f6dc9357SAndroid Build Coastguard Worker DirProcessed += 8;
596*f6dc9357SAndroid Build Coastguard Worker return S_OK;
597*f6dc9357SAndroid Build Coastguard Worker }
598*f6dc9357SAndroid Build Coastguard Worker
599*f6dc9357SAndroid Build Coastguard Worker if ((len & align) != 0 || rem < len)
600*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
601*f6dc9357SAndroid Build Coastguard Worker
602*f6dc9357SAndroid Build Coastguard Worker DirProcessed += (size_t)len;
603*f6dc9357SAndroid Build Coastguard Worker if (DirProcessed > DirSize)
604*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
605*f6dc9357SAndroid Build Coastguard Worker
606*f6dc9357SAndroid Build Coastguard Worker const unsigned dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
607*f6dc9357SAndroid Build Coastguard Worker if (len < dirRecordSize)
608*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
609*f6dc9357SAndroid Build Coastguard Worker
610*f6dc9357SAndroid Build Coastguard Worker CItem item;
611*f6dc9357SAndroid Build Coastguard Worker UInt32 attrib = Get32(p + 8);
612*f6dc9357SAndroid Build Coastguard Worker item.IsDir = ((attrib & 0x10) != 0);
613*f6dc9357SAndroid Build Coastguard Worker UInt64 subdirOffset = Get64(p + 0x10);
614*f6dc9357SAndroid Build Coastguard Worker
615*f6dc9357SAndroid Build Coastguard Worker const UInt32 numAltStreams = Get16(p + dirRecordSize - 6);
616*f6dc9357SAndroid Build Coastguard Worker const UInt32 shortNameLen = Get16(p + dirRecordSize - 4);
617*f6dc9357SAndroid Build Coastguard Worker const UInt32 fileNameLen = Get16(p + dirRecordSize - 2);
618*f6dc9357SAndroid Build Coastguard Worker if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
619*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
620*f6dc9357SAndroid Build Coastguard Worker const UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
621*f6dc9357SAndroid Build Coastguard Worker const UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
622*f6dc9357SAndroid Build Coastguard Worker if (((dirRecordSize + fileNameLen2 + shortNameLen2 + align) & ~align) > len)
623*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
624*f6dc9357SAndroid Build Coastguard Worker
625*f6dc9357SAndroid Build Coastguard Worker p += dirRecordSize;
626*f6dc9357SAndroid Build Coastguard Worker
627*f6dc9357SAndroid Build Coastguard Worker {
628*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt16 *)(const void *)(p + fileNameLen) != 0)
629*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
630*f6dc9357SAndroid Build Coastguard Worker for (UInt32 j = 0; j < fileNameLen; j += 2)
631*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt16 *)(const void *)(p + j) == 0)
632*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
633*f6dc9357SAndroid Build Coastguard Worker }
634*f6dc9357SAndroid Build Coastguard Worker
635*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\n%S", p));
636*f6dc9357SAndroid Build Coastguard Worker
637*f6dc9357SAndroid Build Coastguard Worker if (shortNameLen != 0)
638*f6dc9357SAndroid Build Coastguard Worker {
639*f6dc9357SAndroid Build Coastguard Worker // empty shortName has no ZERO at the end ?
640*f6dc9357SAndroid Build Coastguard Worker const Byte *p2 = p + fileNameLen2;
641*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt16 *)(const void *)(p2 + shortNameLen) != 0)
642*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
643*f6dc9357SAndroid Build Coastguard Worker for (UInt32 j = 0; j < shortNameLen; j += 2)
644*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt16 *)(const void *)(p2 + j) == 0)
645*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
646*f6dc9357SAndroid Build Coastguard Worker }
647*f6dc9357SAndroid Build Coastguard Worker
648*f6dc9357SAndroid Build Coastguard Worker item.Offset = pos;
649*f6dc9357SAndroid Build Coastguard Worker item.Parent = parent;
650*f6dc9357SAndroid Build Coastguard Worker item.ImageIndex = (int)Images.Size() - 1;
651*f6dc9357SAndroid Build Coastguard Worker
652*f6dc9357SAndroid Build Coastguard Worker const unsigned prevIndex = Items.Add(item);
653*f6dc9357SAndroid Build Coastguard Worker
654*f6dc9357SAndroid Build Coastguard Worker pos += (size_t)len;
655*f6dc9357SAndroid Build Coastguard Worker
656*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numAltStreams; i++)
657*f6dc9357SAndroid Build Coastguard Worker {
658*f6dc9357SAndroid Build Coastguard Worker const size_t rem2 = DirSize - pos;
659*f6dc9357SAndroid Build Coastguard Worker if (pos < DirStartOffset || pos > DirSize || rem2 < 8)
660*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
661*f6dc9357SAndroid Build Coastguard Worker const Byte *p2 = DirData + pos;
662*f6dc9357SAndroid Build Coastguard Worker const UInt64 len2 = Get64(p2);
663*f6dc9357SAndroid Build Coastguard Worker if ((len2 & align) != 0 || rem2 < len2
664*f6dc9357SAndroid Build Coastguard Worker || len2 < (unsigned)(IsOldVersion ? 0x18 : 0x28))
665*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
666*f6dc9357SAndroid Build Coastguard Worker
667*f6dc9357SAndroid Build Coastguard Worker DirProcessed += (size_t)len2;
668*f6dc9357SAndroid Build Coastguard Worker if (DirProcessed > DirSize)
669*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
670*f6dc9357SAndroid Build Coastguard Worker
671*f6dc9357SAndroid Build Coastguard Worker unsigned extraOffset = 0;
672*f6dc9357SAndroid Build Coastguard Worker
673*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
674*f6dc9357SAndroid Build Coastguard Worker extraOffset = 0x10;
675*f6dc9357SAndroid Build Coastguard Worker else
676*f6dc9357SAndroid Build Coastguard Worker {
677*f6dc9357SAndroid Build Coastguard Worker if (Get64(p2 + 8) != 0)
678*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
679*f6dc9357SAndroid Build Coastguard Worker extraOffset = 0x24;
680*f6dc9357SAndroid Build Coastguard Worker }
681*f6dc9357SAndroid Build Coastguard Worker
682*f6dc9357SAndroid Build Coastguard Worker const UInt32 fileNameLen111 = Get16(p2 + extraOffset);
683*f6dc9357SAndroid Build Coastguard Worker if ((fileNameLen111 & 1) != 0)
684*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
685*f6dc9357SAndroid Build Coastguard Worker /* Probably different versions of ImageX can use different number of
686*f6dc9357SAndroid Build Coastguard Worker additional ZEROs. So we don't use exact check. */
687*f6dc9357SAndroid Build Coastguard Worker const UInt32 fileNameLen222 = (fileNameLen111 == 0 ? fileNameLen111 : fileNameLen111 + 2);
688*f6dc9357SAndroid Build Coastguard Worker if (((extraOffset + 2 + fileNameLen222 + align) & ~align) > len2)
689*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
690*f6dc9357SAndroid Build Coastguard Worker
691*f6dc9357SAndroid Build Coastguard Worker {
692*f6dc9357SAndroid Build Coastguard Worker const Byte *p3 = p2 + extraOffset + 2;
693*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt16 *)(const void *)(p3 + fileNameLen111) != 0)
694*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
695*f6dc9357SAndroid Build Coastguard Worker for (UInt32 j = 0; j < fileNameLen111; j += 2)
696*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt16 *)(const void *)(p3 + j) == 0)
697*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
698*f6dc9357SAndroid Build Coastguard Worker
699*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\n %S", p3));
700*f6dc9357SAndroid Build Coastguard Worker }
701*f6dc9357SAndroid Build Coastguard Worker
702*f6dc9357SAndroid Build Coastguard Worker
703*f6dc9357SAndroid Build Coastguard Worker /* wim uses alt sreams list, if there is at least one alt stream.
704*f6dc9357SAndroid Build Coastguard Worker And alt stream without name is main stream. */
705*f6dc9357SAndroid Build Coastguard Worker
706*f6dc9357SAndroid Build Coastguard Worker // Why wimlib writes two alt streams for REPARSE_POINT, with empty second alt stream?
707*f6dc9357SAndroid Build Coastguard Worker
708*f6dc9357SAndroid Build Coastguard Worker Byte *prevMeta = DirData + item.Offset;
709*f6dc9357SAndroid Build Coastguard Worker
710*f6dc9357SAndroid Build Coastguard Worker if (fileNameLen111 == 0 &&
711*f6dc9357SAndroid Build Coastguard Worker ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) || !item.IsDir)
712*f6dc9357SAndroid Build Coastguard Worker && (IsOldVersion || IsEmptySha(prevMeta + 0x40)))
713*f6dc9357SAndroid Build Coastguard Worker {
714*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
715*f6dc9357SAndroid Build Coastguard Worker memcpy(prevMeta + 0x10, p2 + 8, 4); // It's 32-bit Id
716*f6dc9357SAndroid Build Coastguard Worker else if (!IsEmptySha(p2 + 0x10))
717*f6dc9357SAndroid Build Coastguard Worker {
718*f6dc9357SAndroid Build Coastguard Worker // if (IsEmptySha(prevMeta + 0x40))
719*f6dc9357SAndroid Build Coastguard Worker memcpy(prevMeta + 0x40, p2 + 0x10, kHashSize);
720*f6dc9357SAndroid Build Coastguard Worker // else HeadersError = true;
721*f6dc9357SAndroid Build Coastguard Worker }
722*f6dc9357SAndroid Build Coastguard Worker }
723*f6dc9357SAndroid Build Coastguard Worker else
724*f6dc9357SAndroid Build Coastguard Worker {
725*f6dc9357SAndroid Build Coastguard Worker ThereAreAltStreams = true;
726*f6dc9357SAndroid Build Coastguard Worker CItem item2;
727*f6dc9357SAndroid Build Coastguard Worker item2.Offset = pos;
728*f6dc9357SAndroid Build Coastguard Worker item2.IsAltStream = true;
729*f6dc9357SAndroid Build Coastguard Worker item2.Parent = (int)prevIndex;
730*f6dc9357SAndroid Build Coastguard Worker item2.ImageIndex = (int)Images.Size() - 1;
731*f6dc9357SAndroid Build Coastguard Worker Items.Add(item2);
732*f6dc9357SAndroid Build Coastguard Worker }
733*f6dc9357SAndroid Build Coastguard Worker
734*f6dc9357SAndroid Build Coastguard Worker pos += (size_t)len2;
735*f6dc9357SAndroid Build Coastguard Worker }
736*f6dc9357SAndroid Build Coastguard Worker
737*f6dc9357SAndroid Build Coastguard Worker if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir)
738*f6dc9357SAndroid Build Coastguard Worker {
739*f6dc9357SAndroid Build Coastguard Worker const Byte *p2 = DirData + pos;
740*f6dc9357SAndroid Build Coastguard Worker if (DirSize - pos >= 8 && Get64(p2) == 0)
741*f6dc9357SAndroid Build Coastguard Worker {
742*f6dc9357SAndroid Build Coastguard Worker CImage &image = Images.Back();
743*f6dc9357SAndroid Build Coastguard Worker image.NumEmptyRootItems = 1;
744*f6dc9357SAndroid Build Coastguard Worker
745*f6dc9357SAndroid Build Coastguard Worker if (subdirOffset != 0
746*f6dc9357SAndroid Build Coastguard Worker && DirSize - pos >= 16
747*f6dc9357SAndroid Build Coastguard Worker && Get64(p2 + 8) != 0
748*f6dc9357SAndroid Build Coastguard Worker && pos + 8 < subdirOffset)
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker // Longhorn.4093 contains hidden files after empty root folder and before items of next folder. Why?
751*f6dc9357SAndroid Build Coastguard Worker // That code shows them. If we want to ignore them, we need to update DirProcessed.
752*f6dc9357SAndroid Build Coastguard Worker // DirProcessed += (size_t)(subdirOffset - (pos + 8));
753*f6dc9357SAndroid Build Coastguard Worker // printf("\ndirOffset = %5d hiddenOffset = %5d\n", (int)subdirOffset, (int)pos + 8);
754*f6dc9357SAndroid Build Coastguard Worker subdirOffset = pos + 8;
755*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
756*f6dc9357SAndroid Build Coastguard Worker }
757*f6dc9357SAndroid Build Coastguard Worker }
758*f6dc9357SAndroid Build Coastguard Worker }
759*f6dc9357SAndroid Build Coastguard Worker
760*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir && subdirOffset != 0)
761*f6dc9357SAndroid Build Coastguard Worker {
762*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseDirItem((size_t)subdirOffset, (int)prevIndex))
763*f6dc9357SAndroid Build Coastguard Worker }
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker }
766*f6dc9357SAndroid Build Coastguard Worker
767*f6dc9357SAndroid Build Coastguard Worker
ParseImageDirs(CByteBuffer & buf,int parent)768*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::ParseImageDirs(CByteBuffer &buf, int parent)
769*f6dc9357SAndroid Build Coastguard Worker {
770*f6dc9357SAndroid Build Coastguard Worker DirData = buf;
771*f6dc9357SAndroid Build Coastguard Worker DirSize = buf.Size();
772*f6dc9357SAndroid Build Coastguard Worker if (DirSize < 8)
773*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
774*f6dc9357SAndroid Build Coastguard Worker const Byte *p = DirData;
775*f6dc9357SAndroid Build Coastguard Worker size_t pos = 0;
776*f6dc9357SAndroid Build Coastguard Worker CImage &image = Images.Back();
777*f6dc9357SAndroid Build Coastguard Worker
778*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
779*f6dc9357SAndroid Build Coastguard Worker {
780*f6dc9357SAndroid Build Coastguard Worker UInt32 numEntries = Get32(p + 4);
781*f6dc9357SAndroid Build Coastguard Worker
782*f6dc9357SAndroid Build Coastguard Worker if (numEntries > (1 << 28) ||
783*f6dc9357SAndroid Build Coastguard Worker numEntries > (DirSize >> 3))
784*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
785*f6dc9357SAndroid Build Coastguard Worker
786*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = 8;
787*f6dc9357SAndroid Build Coastguard Worker if (numEntries != 0)
788*f6dc9357SAndroid Build Coastguard Worker sum = numEntries * 8;
789*f6dc9357SAndroid Build Coastguard Worker
790*f6dc9357SAndroid Build Coastguard Worker image.SecurOffsets.ClearAndReserve(numEntries + 1);
791*f6dc9357SAndroid Build Coastguard Worker image.SecurOffsets.AddInReserved(sum);
792*f6dc9357SAndroid Build Coastguard Worker
793*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numEntries; i++)
794*f6dc9357SAndroid Build Coastguard Worker {
795*f6dc9357SAndroid Build Coastguard Worker const Byte *pp = p + (size_t)i * 8;
796*f6dc9357SAndroid Build Coastguard Worker UInt32 len = Get32(pp);
797*f6dc9357SAndroid Build Coastguard Worker if (i != 0 && Get32(pp + 4) != 0)
798*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
799*f6dc9357SAndroid Build Coastguard Worker if (len > DirSize - sum)
800*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
801*f6dc9357SAndroid Build Coastguard Worker sum += len;
802*f6dc9357SAndroid Build Coastguard Worker if (sum < len)
803*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
804*f6dc9357SAndroid Build Coastguard Worker image.SecurOffsets.AddInReserved(sum);
805*f6dc9357SAndroid Build Coastguard Worker }
806*f6dc9357SAndroid Build Coastguard Worker
807*f6dc9357SAndroid Build Coastguard Worker pos = sum;
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker const size_t align = GetDirAlignMask();
810*f6dc9357SAndroid Build Coastguard Worker pos = (pos + align) & ~(size_t)align;
811*f6dc9357SAndroid Build Coastguard Worker }
812*f6dc9357SAndroid Build Coastguard Worker else
813*f6dc9357SAndroid Build Coastguard Worker {
814*f6dc9357SAndroid Build Coastguard Worker UInt32 totalLen = Get32(p);
815*f6dc9357SAndroid Build Coastguard Worker if (totalLen == 0)
816*f6dc9357SAndroid Build Coastguard Worker pos = 8;
817*f6dc9357SAndroid Build Coastguard Worker else
818*f6dc9357SAndroid Build Coastguard Worker {
819*f6dc9357SAndroid Build Coastguard Worker if (totalLen < 8)
820*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
821*f6dc9357SAndroid Build Coastguard Worker UInt32 numEntries = Get32(p + 4);
822*f6dc9357SAndroid Build Coastguard Worker pos = 8;
823*f6dc9357SAndroid Build Coastguard Worker if (totalLen > DirSize || numEntries > ((totalLen - 8) >> 3))
824*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
825*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = (UInt32)pos + numEntries * 8;
826*f6dc9357SAndroid Build Coastguard Worker image.SecurOffsets.ClearAndReserve(numEntries + 1);
827*f6dc9357SAndroid Build Coastguard Worker image.SecurOffsets.AddInReserved(sum);
828*f6dc9357SAndroid Build Coastguard Worker
829*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numEntries; i++, pos += 8)
830*f6dc9357SAndroid Build Coastguard Worker {
831*f6dc9357SAndroid Build Coastguard Worker UInt64 len = Get64(p + pos);
832*f6dc9357SAndroid Build Coastguard Worker if (len > totalLen - sum)
833*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
834*f6dc9357SAndroid Build Coastguard Worker sum += (UInt32)len;
835*f6dc9357SAndroid Build Coastguard Worker image.SecurOffsets.AddInReserved(sum);
836*f6dc9357SAndroid Build Coastguard Worker }
837*f6dc9357SAndroid Build Coastguard Worker
838*f6dc9357SAndroid Build Coastguard Worker pos = sum;
839*f6dc9357SAndroid Build Coastguard Worker pos = (pos + 7) & ~(size_t)7;
840*f6dc9357SAndroid Build Coastguard Worker if (pos != (((size_t)totalLen + 7) & ~(size_t)7))
841*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
842*f6dc9357SAndroid Build Coastguard Worker }
843*f6dc9357SAndroid Build Coastguard Worker }
844*f6dc9357SAndroid Build Coastguard Worker
845*f6dc9357SAndroid Build Coastguard Worker if (pos > DirSize)
846*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
847*f6dc9357SAndroid Build Coastguard Worker
848*f6dc9357SAndroid Build Coastguard Worker DirStartOffset = DirProcessed = pos;
849*f6dc9357SAndroid Build Coastguard Worker image.StartItem = Items.Size();
850*f6dc9357SAndroid Build Coastguard Worker
851*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseDirItem(pos, parent))
852*f6dc9357SAndroid Build Coastguard Worker
853*f6dc9357SAndroid Build Coastguard Worker image.NumItems = Items.Size() - image.StartItem;
854*f6dc9357SAndroid Build Coastguard Worker if (DirProcessed == DirSize)
855*f6dc9357SAndroid Build Coastguard Worker return S_OK;
856*f6dc9357SAndroid Build Coastguard Worker
857*f6dc9357SAndroid Build Coastguard Worker /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER),
858*f6dc9357SAndroid Build Coastguard Worker but the reference to that folder is empty */
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker // we can't use DirProcessed - DirStartOffset == 112 check if there is alt stream in root
861*f6dc9357SAndroid Build Coastguard Worker if (DirProcessed == DirSize - 8 && Get64(p + DirSize - 8) != 0)
862*f6dc9357SAndroid Build Coastguard Worker return S_OK;
863*f6dc9357SAndroid Build Coastguard Worker
864*f6dc9357SAndroid Build Coastguard Worker // 18.06: we support cases, when some old dism can capture images
865*f6dc9357SAndroid Build Coastguard Worker // where DirProcessed much smaller than DirSize
866*f6dc9357SAndroid Build Coastguard Worker HeadersError = true;
867*f6dc9357SAndroid Build Coastguard Worker return S_OK;
868*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
869*f6dc9357SAndroid Build Coastguard Worker }
870*f6dc9357SAndroid Build Coastguard Worker
871*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,UInt64 & phySize)872*f6dc9357SAndroid Build Coastguard Worker HRESULT CHeader::Parse(const Byte *p, UInt64 &phySize)
873*f6dc9357SAndroid Build Coastguard Worker {
874*f6dc9357SAndroid Build Coastguard Worker UInt32 headerSize = Get32(p + 8);
875*f6dc9357SAndroid Build Coastguard Worker phySize = headerSize;
876*f6dc9357SAndroid Build Coastguard Worker Version = Get32(p + 0x0C);
877*f6dc9357SAndroid Build Coastguard Worker Flags = Get32(p + 0x10);
878*f6dc9357SAndroid Build Coastguard Worker if (!IsSupported())
879*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
880*f6dc9357SAndroid Build Coastguard Worker
881*f6dc9357SAndroid Build Coastguard Worker {
882*f6dc9357SAndroid Build Coastguard Worker ChunkSize = Get32(p + 0x14);
883*f6dc9357SAndroid Build Coastguard Worker ChunkSizeBits = kChunkSizeBits;
884*f6dc9357SAndroid Build Coastguard Worker if (ChunkSize != 0)
885*f6dc9357SAndroid Build Coastguard Worker {
886*f6dc9357SAndroid Build Coastguard Worker if (!GetLog_val_min_dest(ChunkSize, 12, ChunkSizeBits))
887*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
888*f6dc9357SAndroid Build Coastguard Worker }
889*f6dc9357SAndroid Build Coastguard Worker }
890*f6dc9357SAndroid Build Coastguard Worker
891*f6dc9357SAndroid Build Coastguard Worker _isOldVersion = false;
892*f6dc9357SAndroid Build Coastguard Worker _isNewVersion = false;
893*f6dc9357SAndroid Build Coastguard Worker
894*f6dc9357SAndroid Build Coastguard Worker if (IsSolidVersion())
895*f6dc9357SAndroid Build Coastguard Worker _isNewVersion = true;
896*f6dc9357SAndroid Build Coastguard Worker else
897*f6dc9357SAndroid Build Coastguard Worker {
898*f6dc9357SAndroid Build Coastguard Worker if (Version < 0x010900)
899*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
900*f6dc9357SAndroid Build Coastguard Worker _isOldVersion = (Version <= 0x010A00);
901*f6dc9357SAndroid Build Coastguard Worker // We don't know details about 1.11 version. So we use headerSize to guess exact features.
902*f6dc9357SAndroid Build Coastguard Worker if (Version == 0x010B00 && headerSize == 0x60)
903*f6dc9357SAndroid Build Coastguard Worker _isOldVersion = true;
904*f6dc9357SAndroid Build Coastguard Worker _isNewVersion = (Version >= 0x010D00);
905*f6dc9357SAndroid Build Coastguard Worker }
906*f6dc9357SAndroid Build Coastguard Worker
907*f6dc9357SAndroid Build Coastguard Worker unsigned offset;
908*f6dc9357SAndroid Build Coastguard Worker
909*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion())
910*f6dc9357SAndroid Build Coastguard Worker {
911*f6dc9357SAndroid Build Coastguard Worker if (headerSize != 0x60)
912*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
913*f6dc9357SAndroid Build Coastguard Worker memset(Guid, 0, 16);
914*f6dc9357SAndroid Build Coastguard Worker offset = 0x18;
915*f6dc9357SAndroid Build Coastguard Worker PartNumber = 1;
916*f6dc9357SAndroid Build Coastguard Worker NumParts = 1;
917*f6dc9357SAndroid Build Coastguard Worker }
918*f6dc9357SAndroid Build Coastguard Worker else
919*f6dc9357SAndroid Build Coastguard Worker {
920*f6dc9357SAndroid Build Coastguard Worker if (headerSize < 0x74)
921*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
922*f6dc9357SAndroid Build Coastguard Worker memcpy(Guid, p + 0x18, 16);
923*f6dc9357SAndroid Build Coastguard Worker PartNumber = Get16(p + 0x28);
924*f6dc9357SAndroid Build Coastguard Worker NumParts = Get16(p + 0x2A);
925*f6dc9357SAndroid Build Coastguard Worker if (PartNumber == 0 || PartNumber > NumParts)
926*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
927*f6dc9357SAndroid Build Coastguard Worker offset = 0x2C;
928*f6dc9357SAndroid Build Coastguard Worker if (IsNewVersion())
929*f6dc9357SAndroid Build Coastguard Worker {
930*f6dc9357SAndroid Build Coastguard Worker // if (headerSize < 0xD0)
931*f6dc9357SAndroid Build Coastguard Worker if (headerSize != 0xD0)
932*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
933*f6dc9357SAndroid Build Coastguard Worker NumImages = Get32(p + offset);
934*f6dc9357SAndroid Build Coastguard Worker offset += 4;
935*f6dc9357SAndroid Build Coastguard Worker }
936*f6dc9357SAndroid Build Coastguard Worker }
937*f6dc9357SAndroid Build Coastguard Worker
938*f6dc9357SAndroid Build Coastguard Worker GET_RESOURCE(p + offset , OffsetResource);
939*f6dc9357SAndroid Build Coastguard Worker GET_RESOURCE(p + offset + 0x18, XmlResource);
940*f6dc9357SAndroid Build Coastguard Worker GET_RESOURCE(p + offset + 0x30, MetadataResource);
941*f6dc9357SAndroid Build Coastguard Worker BootIndex = 0;
942*f6dc9357SAndroid Build Coastguard Worker
943*f6dc9357SAndroid Build Coastguard Worker if (IsNewVersion())
944*f6dc9357SAndroid Build Coastguard Worker {
945*f6dc9357SAndroid Build Coastguard Worker BootIndex = Get32(p + offset + 0x48);
946*f6dc9357SAndroid Build Coastguard Worker GET_RESOURCE(p + offset + 0x4C, IntegrityResource);
947*f6dc9357SAndroid Build Coastguard Worker }
948*f6dc9357SAndroid Build Coastguard Worker
949*f6dc9357SAndroid Build Coastguard Worker return S_OK;
950*f6dc9357SAndroid Build Coastguard Worker }
951*f6dc9357SAndroid Build Coastguard Worker
952*f6dc9357SAndroid Build Coastguard Worker
953*f6dc9357SAndroid Build Coastguard Worker const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
954*f6dc9357SAndroid Build Coastguard Worker
ReadHeader(IInStream * inStream,CHeader & h,UInt64 & phySize)955*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadHeader(IInStream *inStream, CHeader &h, UInt64 &phySize)
956*f6dc9357SAndroid Build Coastguard Worker {
957*f6dc9357SAndroid Build Coastguard Worker Byte p[kHeaderSizeMax];
958*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax))
959*f6dc9357SAndroid Build Coastguard Worker if (memcmp(p, kSignature, kSignatureSize) != 0)
960*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
961*f6dc9357SAndroid Build Coastguard Worker return h.Parse(p, phySize);
962*f6dc9357SAndroid Build Coastguard Worker }
963*f6dc9357SAndroid Build Coastguard Worker
964*f6dc9357SAndroid Build Coastguard Worker
ReadStreams(IInStream * inStream,const CHeader & h,CDatabase & db)965*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
966*f6dc9357SAndroid Build Coastguard Worker {
967*f6dc9357SAndroid Build Coastguard Worker CByteBuffer offsetBuf;
968*f6dc9357SAndroid Build Coastguard Worker
969*f6dc9357SAndroid Build Coastguard Worker CUnpacker unpacker;
970*f6dc9357SAndroid Build Coastguard Worker RINOK(unpacker.UnpackData(inStream, h.OffsetResource, h, NULL, offsetBuf, NULL))
971*f6dc9357SAndroid Build Coastguard Worker
972*f6dc9357SAndroid Build Coastguard Worker const size_t streamInfoSize = h.IsOldVersion() ? kStreamInfoSize + 2 : kStreamInfoSize;
973*f6dc9357SAndroid Build Coastguard Worker {
974*f6dc9357SAndroid Build Coastguard Worker const unsigned numItems = (unsigned)(offsetBuf.Size() / streamInfoSize);
975*f6dc9357SAndroid Build Coastguard Worker if ((size_t)numItems * streamInfoSize != offsetBuf.Size())
976*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
977*f6dc9357SAndroid Build Coastguard Worker const unsigned numItems2 = db.DataStreams.Size() + numItems;
978*f6dc9357SAndroid Build Coastguard Worker if (numItems2 < numItems)
979*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
980*f6dc9357SAndroid Build Coastguard Worker db.DataStreams.Reserve(numItems2);
981*f6dc9357SAndroid Build Coastguard Worker }
982*f6dc9357SAndroid Build Coastguard Worker
983*f6dc9357SAndroid Build Coastguard Worker bool keepSolid = false;
984*f6dc9357SAndroid Build Coastguard Worker
985*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < offsetBuf.Size(); i += streamInfoSize)
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker CStreamInfo s;
988*f6dc9357SAndroid Build Coastguard Worker ParseStream(h.IsOldVersion(), (const Byte *)offsetBuf + i, s);
989*f6dc9357SAndroid Build Coastguard Worker
990*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n"));
991*f6dc9357SAndroid Build Coastguard Worker PRF(printf(s.Resource.IsMetadata() ? "### META" : " DATA"));
992*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" %2X", s.Resource.Flags));
993*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" %9I64X", s.Resource.Offset));
994*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" %9I64X", s.Resource.PackSize));
995*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" %9I64X", s.Resource.UnpackSize));
996*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" %d", s.RefCount));
997*f6dc9357SAndroid Build Coastguard Worker
998*f6dc9357SAndroid Build Coastguard Worker if (s.PartNumber != h.PartNumber)
999*f6dc9357SAndroid Build Coastguard Worker continue;
1000*f6dc9357SAndroid Build Coastguard Worker
1001*f6dc9357SAndroid Build Coastguard Worker if (s.Resource.IsSolid())
1002*f6dc9357SAndroid Build Coastguard Worker {
1003*f6dc9357SAndroid Build Coastguard Worker s.Resource.KeepSolid = keepSolid;
1004*f6dc9357SAndroid Build Coastguard Worker keepSolid = true;
1005*f6dc9357SAndroid Build Coastguard Worker }
1006*f6dc9357SAndroid Build Coastguard Worker else
1007*f6dc9357SAndroid Build Coastguard Worker {
1008*f6dc9357SAndroid Build Coastguard Worker s.Resource.KeepSolid = false;
1009*f6dc9357SAndroid Build Coastguard Worker keepSolid = false;
1010*f6dc9357SAndroid Build Coastguard Worker }
1011*f6dc9357SAndroid Build Coastguard Worker
1012*f6dc9357SAndroid Build Coastguard Worker if (!s.Resource.IsMetadata())
1013*f6dc9357SAndroid Build Coastguard Worker db.DataStreams.AddInReserved(s);
1014*f6dc9357SAndroid Build Coastguard Worker else
1015*f6dc9357SAndroid Build Coastguard Worker {
1016*f6dc9357SAndroid Build Coastguard Worker if (s.Resource.IsSolid())
1017*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1018*f6dc9357SAndroid Build Coastguard Worker if (s.RefCount == 0)
1019*f6dc9357SAndroid Build Coastguard Worker {
1020*f6dc9357SAndroid Build Coastguard Worker // some wims have such (deleted?) metadata stream.
1021*f6dc9357SAndroid Build Coastguard Worker // examples: boot.wim in VistaBeta2, WinPE.wim from WAIK.
1022*f6dc9357SAndroid Build Coastguard Worker // db.DataStreams.Add(s);
1023*f6dc9357SAndroid Build Coastguard Worker // we can show these delete images, if we comment "continue" command;
1024*f6dc9357SAndroid Build Coastguard Worker continue;
1025*f6dc9357SAndroid Build Coastguard Worker }
1026*f6dc9357SAndroid Build Coastguard Worker
1027*f6dc9357SAndroid Build Coastguard Worker if (s.RefCount > 1)
1028*f6dc9357SAndroid Build Coastguard Worker {
1029*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1030*f6dc9357SAndroid Build Coastguard Worker // s.RefCount--;
1031*f6dc9357SAndroid Build Coastguard Worker // db.DataStreams.Add(s);
1032*f6dc9357SAndroid Build Coastguard Worker }
1033*f6dc9357SAndroid Build Coastguard Worker
1034*f6dc9357SAndroid Build Coastguard Worker db.MetaStreams.Add(s);
1035*f6dc9357SAndroid Build Coastguard Worker }
1036*f6dc9357SAndroid Build Coastguard Worker }
1037*f6dc9357SAndroid Build Coastguard Worker
1038*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n"));
1039*f6dc9357SAndroid Build Coastguard Worker
1040*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1041*f6dc9357SAndroid Build Coastguard Worker }
1042*f6dc9357SAndroid Build Coastguard Worker
1043*f6dc9357SAndroid Build Coastguard Worker
OpenXml(IInStream * inStream,const CHeader & h,CByteBuffer & xml)1044*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml)
1045*f6dc9357SAndroid Build Coastguard Worker {
1046*f6dc9357SAndroid Build Coastguard Worker CUnpacker unpacker;
1047*f6dc9357SAndroid Build Coastguard Worker return unpacker.UnpackData(inStream, h.XmlResource, h, this, xml, NULL);
1048*f6dc9357SAndroid Build Coastguard Worker }
1049*f6dc9357SAndroid Build Coastguard Worker
SetRootNames(CImage & image,unsigned value)1050*f6dc9357SAndroid Build Coastguard Worker static void SetRootNames(CImage &image, unsigned value)
1051*f6dc9357SAndroid Build Coastguard Worker {
1052*f6dc9357SAndroid Build Coastguard Worker wchar_t temp[16];
1053*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(value, temp);
1054*f6dc9357SAndroid Build Coastguard Worker image.RootName = temp;
1055*f6dc9357SAndroid Build Coastguard Worker image.RootNameBuf.Alloc(image.RootName.Len() * 2 + 2);
1056*f6dc9357SAndroid Build Coastguard Worker Byte *p = image.RootNameBuf;
1057*f6dc9357SAndroid Build Coastguard Worker unsigned len = image.RootName.Len() + 1;
1058*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = 0; k < len; k++)
1059*f6dc9357SAndroid Build Coastguard Worker {
1060*f6dc9357SAndroid Build Coastguard Worker p[k * 2] = (Byte)temp[k];
1061*f6dc9357SAndroid Build Coastguard Worker p[k * 2 + 1] = 0;
1062*f6dc9357SAndroid Build Coastguard Worker }
1063*f6dc9357SAndroid Build Coastguard Worker }
1064*f6dc9357SAndroid Build Coastguard Worker
1065*f6dc9357SAndroid Build Coastguard Worker
Open(IInStream * inStream,const CHeader & h,unsigned numItemsReserve,IArchiveOpenCallback * openCallback)1066*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, unsigned numItemsReserve, IArchiveOpenCallback *openCallback)
1067*f6dc9357SAndroid Build Coastguard Worker {
1068*f6dc9357SAndroid Build Coastguard Worker OpenCallback = openCallback;
1069*f6dc9357SAndroid Build Coastguard Worker IsOldVersion = h.IsOldVersion();
1070*f6dc9357SAndroid Build Coastguard Worker IsOldVersion9 = (h.Version == 0x10900);
1071*f6dc9357SAndroid Build Coastguard Worker
1072*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStreams(inStream, h, *this))
1073*f6dc9357SAndroid Build Coastguard Worker
1074*f6dc9357SAndroid Build Coastguard Worker bool needBootMetadata = !h.MetadataResource.IsEmpty();
1075*f6dc9357SAndroid Build Coastguard Worker unsigned numNonDeletedImages = 0;
1076*f6dc9357SAndroid Build Coastguard Worker
1077*f6dc9357SAndroid Build Coastguard Worker CUnpacker unpacker;
1078*f6dc9357SAndroid Build Coastguard Worker
1079*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, MetaStreams)
1080*f6dc9357SAndroid Build Coastguard Worker {
1081*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &si = MetaStreams[i];
1082*f6dc9357SAndroid Build Coastguard Worker
1083*f6dc9357SAndroid Build Coastguard Worker if (h.PartNumber != 1 || si.PartNumber != h.PartNumber)
1084*f6dc9357SAndroid Build Coastguard Worker continue;
1085*f6dc9357SAndroid Build Coastguard Worker
1086*f6dc9357SAndroid Build Coastguard Worker const unsigned userImage = Images.Size() + GetStartImageIndex();
1087*f6dc9357SAndroid Build Coastguard Worker CImage &image = Images.AddNew();
1088*f6dc9357SAndroid Build Coastguard Worker SetRootNames(image, userImage);
1089*f6dc9357SAndroid Build Coastguard Worker
1090*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &metadata = image.Meta;
1091*f6dc9357SAndroid Build Coastguard Worker Byte hash[kHashSize];
1092*f6dc9357SAndroid Build Coastguard Worker
1093*f6dc9357SAndroid Build Coastguard Worker RINOK(unpacker.UnpackData(inStream, si.Resource, h, this, metadata, hash))
1094*f6dc9357SAndroid Build Coastguard Worker
1095*f6dc9357SAndroid Build Coastguard Worker if (memcmp(hash, si.Hash, kHashSize) != 0 &&
1096*f6dc9357SAndroid Build Coastguard Worker !(h.IsOldVersion() && IsEmptySha(si.Hash)))
1097*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1098*f6dc9357SAndroid Build Coastguard Worker
1099*f6dc9357SAndroid Build Coastguard Worker image.NumEmptyRootItems = 0;
1100*f6dc9357SAndroid Build Coastguard Worker
1101*f6dc9357SAndroid Build Coastguard Worker if (Items.IsEmpty())
1102*f6dc9357SAndroid Build Coastguard Worker Items.ClearAndReserve(numItemsReserve);
1103*f6dc9357SAndroid Build Coastguard Worker
1104*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseImageDirs(metadata, -1))
1105*f6dc9357SAndroid Build Coastguard Worker
1106*f6dc9357SAndroid Build Coastguard Worker if (needBootMetadata)
1107*f6dc9357SAndroid Build Coastguard Worker {
1108*f6dc9357SAndroid Build Coastguard Worker bool sameRes = (h.MetadataResource.Offset == si.Resource.Offset);
1109*f6dc9357SAndroid Build Coastguard Worker if (sameRes)
1110*f6dc9357SAndroid Build Coastguard Worker needBootMetadata = false;
1111*f6dc9357SAndroid Build Coastguard Worker if (h.IsNewVersion())
1112*f6dc9357SAndroid Build Coastguard Worker {
1113*f6dc9357SAndroid Build Coastguard Worker if (si.RefCount == 1)
1114*f6dc9357SAndroid Build Coastguard Worker {
1115*f6dc9357SAndroid Build Coastguard Worker numNonDeletedImages++;
1116*f6dc9357SAndroid Build Coastguard Worker bool isBootIndex = (h.BootIndex == numNonDeletedImages);
1117*f6dc9357SAndroid Build Coastguard Worker if (sameRes && !isBootIndex)
1118*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1119*f6dc9357SAndroid Build Coastguard Worker if (isBootIndex && !sameRes)
1120*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1121*f6dc9357SAndroid Build Coastguard Worker }
1122*f6dc9357SAndroid Build Coastguard Worker }
1123*f6dc9357SAndroid Build Coastguard Worker }
1124*f6dc9357SAndroid Build Coastguard Worker }
1125*f6dc9357SAndroid Build Coastguard Worker
1126*f6dc9357SAndroid Build Coastguard Worker if (needBootMetadata)
1127*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1128*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1129*f6dc9357SAndroid Build Coastguard Worker }
1130*f6dc9357SAndroid Build Coastguard Worker
1131*f6dc9357SAndroid Build Coastguard Worker
ItemHasStream(const CItem & item) const1132*f6dc9357SAndroid Build Coastguard Worker bool CDatabase::ItemHasStream(const CItem &item) const
1133*f6dc9357SAndroid Build Coastguard Worker {
1134*f6dc9357SAndroid Build Coastguard Worker if (item.ImageIndex < 0)
1135*f6dc9357SAndroid Build Coastguard Worker return true;
1136*f6dc9357SAndroid Build Coastguard Worker const Byte *meta = Images[item.ImageIndex].Meta + item.Offset;
1137*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
1138*f6dc9357SAndroid Build Coastguard Worker {
1139*f6dc9357SAndroid Build Coastguard Worker // old wim use same field for file_id and dir_offset;
1140*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir)
1141*f6dc9357SAndroid Build Coastguard Worker return false;
1142*f6dc9357SAndroid Build Coastguard Worker meta += (item.IsAltStream ? 0x8 : 0x10);
1143*f6dc9357SAndroid Build Coastguard Worker UInt32 id = GetUi32(meta);
1144*f6dc9357SAndroid Build Coastguard Worker return id != 0;
1145*f6dc9357SAndroid Build Coastguard Worker }
1146*f6dc9357SAndroid Build Coastguard Worker meta += (item.IsAltStream ? 0x10 : 0x40);
1147*f6dc9357SAndroid Build Coastguard Worker return !IsEmptySha(meta);
1148*f6dc9357SAndroid Build Coastguard Worker }
1149*f6dc9357SAndroid Build Coastguard Worker
1150*f6dc9357SAndroid Build Coastguard Worker
1151*f6dc9357SAndroid Build Coastguard Worker #define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }
1152*f6dc9357SAndroid Build Coastguard Worker
CompareStreamsByPos(const CStreamInfo * p1,const CStreamInfo * p2,void *)1153*f6dc9357SAndroid Build Coastguard Worker static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
1154*f6dc9357SAndroid Build Coastguard Worker {
1155*f6dc9357SAndroid Build Coastguard Worker RINOZ(MyCompare(p1->PartNumber, p2->PartNumber))
1156*f6dc9357SAndroid Build Coastguard Worker RINOZ(MyCompare(p1->Resource.Offset, p2->Resource.Offset))
1157*f6dc9357SAndroid Build Coastguard Worker return MyCompare(p1->Resource.PackSize, p2->Resource.PackSize);
1158*f6dc9357SAndroid Build Coastguard Worker }
1159*f6dc9357SAndroid Build Coastguard Worker
CompareIDs(const unsigned * p1,const unsigned * p2,void * param)1160*f6dc9357SAndroid Build Coastguard Worker static int CompareIDs(const unsigned *p1, const unsigned *p2, void *param)
1161*f6dc9357SAndroid Build Coastguard Worker {
1162*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo *streams = (const CStreamInfo *)param;
1163*f6dc9357SAndroid Build Coastguard Worker return MyCompare(streams[*p1].Id, streams[*p2].Id);
1164*f6dc9357SAndroid Build Coastguard Worker }
1165*f6dc9357SAndroid Build Coastguard Worker
CompareHashRefs(const unsigned * p1,const unsigned * p2,void * param)1166*f6dc9357SAndroid Build Coastguard Worker static int CompareHashRefs(const unsigned *p1, const unsigned *p2, void *param)
1167*f6dc9357SAndroid Build Coastguard Worker {
1168*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo *streams = (const CStreamInfo *)param;
1169*f6dc9357SAndroid Build Coastguard Worker return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
1170*f6dc9357SAndroid Build Coastguard Worker }
1171*f6dc9357SAndroid Build Coastguard Worker
FindId(const CStreamInfo * streams,const CUIntVector & sorted,UInt32 id)1172*f6dc9357SAndroid Build Coastguard Worker static int FindId(const CStreamInfo *streams, const CUIntVector &sorted, UInt32 id)
1173*f6dc9357SAndroid Build Coastguard Worker {
1174*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = sorted.Size();
1175*f6dc9357SAndroid Build Coastguard Worker while (left != right)
1176*f6dc9357SAndroid Build Coastguard Worker {
1177*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (left + right) / 2;
1178*f6dc9357SAndroid Build Coastguard Worker const unsigned streamIndex = sorted[mid];
1179*f6dc9357SAndroid Build Coastguard Worker const UInt32 id2 = streams[streamIndex].Id;
1180*f6dc9357SAndroid Build Coastguard Worker if (id == id2)
1181*f6dc9357SAndroid Build Coastguard Worker return (int)streamIndex;
1182*f6dc9357SAndroid Build Coastguard Worker if (id < id2)
1183*f6dc9357SAndroid Build Coastguard Worker right = mid;
1184*f6dc9357SAndroid Build Coastguard Worker else
1185*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
1186*f6dc9357SAndroid Build Coastguard Worker }
1187*f6dc9357SAndroid Build Coastguard Worker return -1;
1188*f6dc9357SAndroid Build Coastguard Worker }
1189*f6dc9357SAndroid Build Coastguard Worker
FindHash(const CStreamInfo * streams,const CUIntVector & sorted,const Byte * hash)1190*f6dc9357SAndroid Build Coastguard Worker static int FindHash(const CStreamInfo *streams, const CUIntVector &sorted, const Byte *hash)
1191*f6dc9357SAndroid Build Coastguard Worker {
1192*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = sorted.Size();
1193*f6dc9357SAndroid Build Coastguard Worker while (left != right)
1194*f6dc9357SAndroid Build Coastguard Worker {
1195*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (left + right) / 2;
1196*f6dc9357SAndroid Build Coastguard Worker const unsigned streamIndex = sorted[mid];
1197*f6dc9357SAndroid Build Coastguard Worker const Byte *hash2 = streams[streamIndex].Hash;
1198*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1199*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kHashSize; i++)
1200*f6dc9357SAndroid Build Coastguard Worker if (hash[i] != hash2[i])
1201*f6dc9357SAndroid Build Coastguard Worker break;
1202*f6dc9357SAndroid Build Coastguard Worker if (i == kHashSize)
1203*f6dc9357SAndroid Build Coastguard Worker return (int)streamIndex;
1204*f6dc9357SAndroid Build Coastguard Worker if (hash[i] < hash2[i])
1205*f6dc9357SAndroid Build Coastguard Worker right = mid;
1206*f6dc9357SAndroid Build Coastguard Worker else
1207*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
1208*f6dc9357SAndroid Build Coastguard Worker }
1209*f6dc9357SAndroid Build Coastguard Worker return -1;
1210*f6dc9357SAndroid Build Coastguard Worker }
1211*f6dc9357SAndroid Build Coastguard Worker
CompareItems(const unsigned * a1,const unsigned * a2,void * param)1212*f6dc9357SAndroid Build Coastguard Worker static int CompareItems(const unsigned *a1, const unsigned *a2, void *param)
1213*f6dc9357SAndroid Build Coastguard Worker {
1214*f6dc9357SAndroid Build Coastguard Worker const CRecordVector<CItem> &items = ((CDatabase *)param)->Items;
1215*f6dc9357SAndroid Build Coastguard Worker const CItem &i1 = items[*a1];
1216*f6dc9357SAndroid Build Coastguard Worker const CItem &i2 = items[*a2];
1217*f6dc9357SAndroid Build Coastguard Worker
1218*f6dc9357SAndroid Build Coastguard Worker if (i1.IsDir != i2.IsDir)
1219*f6dc9357SAndroid Build Coastguard Worker return i1.IsDir ? -1 : 1;
1220*f6dc9357SAndroid Build Coastguard Worker if (i1.IsAltStream != i2.IsAltStream)
1221*f6dc9357SAndroid Build Coastguard Worker return i1.IsAltStream ? 1 : -1;
1222*f6dc9357SAndroid Build Coastguard Worker RINOZ(MyCompare(i1.StreamIndex, i2.StreamIndex))
1223*f6dc9357SAndroid Build Coastguard Worker RINOZ(MyCompare(i1.ImageIndex, i2.ImageIndex))
1224*f6dc9357SAndroid Build Coastguard Worker return MyCompare(i1.Offset, i2.Offset);
1225*f6dc9357SAndroid Build Coastguard Worker }
1226*f6dc9357SAndroid Build Coastguard Worker
1227*f6dc9357SAndroid Build Coastguard Worker
FillAndCheck(const CObjectVector<CVolume> & volumes)1228*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)
1229*f6dc9357SAndroid Build Coastguard Worker {
1230*f6dc9357SAndroid Build Coastguard Worker CUIntVector sortedByHash;
1231*f6dc9357SAndroid Build Coastguard Worker sortedByHash.Reserve(DataStreams.Size());
1232*f6dc9357SAndroid Build Coastguard Worker {
1233*f6dc9357SAndroid Build Coastguard Worker CByteBuffer sizesBuf;
1234*f6dc9357SAndroid Build Coastguard Worker
1235*f6dc9357SAndroid Build Coastguard Worker for (unsigned iii = 0; iii < DataStreams.Size();)
1236*f6dc9357SAndroid Build Coastguard Worker {
1237*f6dc9357SAndroid Build Coastguard Worker {
1238*f6dc9357SAndroid Build Coastguard Worker const CResource &r = DataStreams[iii].Resource;
1239*f6dc9357SAndroid Build Coastguard Worker if (!r.IsSolid())
1240*f6dc9357SAndroid Build Coastguard Worker {
1241*f6dc9357SAndroid Build Coastguard Worker sortedByHash.AddInReserved(iii++);
1242*f6dc9357SAndroid Build Coastguard Worker continue;
1243*f6dc9357SAndroid Build Coastguard Worker }
1244*f6dc9357SAndroid Build Coastguard Worker }
1245*f6dc9357SAndroid Build Coastguard Worker
1246*f6dc9357SAndroid Build Coastguard Worker UInt64 solidRunOffset = 0;
1247*f6dc9357SAndroid Build Coastguard Worker unsigned k;
1248*f6dc9357SAndroid Build Coastguard Worker unsigned numSolidsStart = Solids.Size();
1249*f6dc9357SAndroid Build Coastguard Worker
1250*f6dc9357SAndroid Build Coastguard Worker for (k = iii; k < DataStreams.Size(); k++)
1251*f6dc9357SAndroid Build Coastguard Worker {
1252*f6dc9357SAndroid Build Coastguard Worker CStreamInfo &si = DataStreams[k];
1253*f6dc9357SAndroid Build Coastguard Worker CResource &r = si.Resource;
1254*f6dc9357SAndroid Build Coastguard Worker
1255*f6dc9357SAndroid Build Coastguard Worker if (!r.IsSolid())
1256*f6dc9357SAndroid Build Coastguard Worker break;
1257*f6dc9357SAndroid Build Coastguard Worker if (!r.KeepSolid && k != iii)
1258*f6dc9357SAndroid Build Coastguard Worker break;
1259*f6dc9357SAndroid Build Coastguard Worker
1260*f6dc9357SAndroid Build Coastguard Worker if (r.Flags != NResourceFlags::kSolid)
1261*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1262*f6dc9357SAndroid Build Coastguard Worker
1263*f6dc9357SAndroid Build Coastguard Worker if (!r.IsSolidBig())
1264*f6dc9357SAndroid Build Coastguard Worker continue;
1265*f6dc9357SAndroid Build Coastguard Worker
1266*f6dc9357SAndroid Build Coastguard Worker if (!si.IsEmptyHash())
1267*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1268*f6dc9357SAndroid Build Coastguard Worker if (si.RefCount != 1)
1269*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1270*f6dc9357SAndroid Build Coastguard Worker
1271*f6dc9357SAndroid Build Coastguard Worker r.SolidIndex = (int)Solids.Size();
1272*f6dc9357SAndroid Build Coastguard Worker
1273*f6dc9357SAndroid Build Coastguard Worker CSolid &ss = Solids.AddNew();
1274*f6dc9357SAndroid Build Coastguard Worker ss.StreamIndex = k;
1275*f6dc9357SAndroid Build Coastguard Worker ss.SolidOffset = solidRunOffset;
1276*f6dc9357SAndroid Build Coastguard Worker {
1277*f6dc9357SAndroid Build Coastguard Worker const size_t kSolidHeaderSize = 8 + 4 + 4;
1278*f6dc9357SAndroid Build Coastguard Worker Byte header[kSolidHeaderSize];
1279*f6dc9357SAndroid Build Coastguard Worker
1280*f6dc9357SAndroid Build Coastguard Worker if (si.PartNumber >= volumes.Size())
1281*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1282*f6dc9357SAndroid Build Coastguard Worker
1283*f6dc9357SAndroid Build Coastguard Worker const CVolume &vol = volumes[si.PartNumber];
1284*f6dc9357SAndroid Build Coastguard Worker IInStream *inStream = vol.Stream;
1285*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, r.Offset))
1286*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, (Byte *)header, kSolidHeaderSize))
1287*f6dc9357SAndroid Build Coastguard Worker
1288*f6dc9357SAndroid Build Coastguard Worker ss.UnpackSize = GetUi64(header);
1289*f6dc9357SAndroid Build Coastguard Worker
1290*f6dc9357SAndroid Build Coastguard Worker if (ss.UnpackSize > ((UInt64)1 << 63))
1291*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1292*f6dc9357SAndroid Build Coastguard Worker
1293*f6dc9357SAndroid Build Coastguard Worker solidRunOffset += ss.UnpackSize;
1294*f6dc9357SAndroid Build Coastguard Worker if (solidRunOffset < ss.UnpackSize)
1295*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1296*f6dc9357SAndroid Build Coastguard Worker
1297*f6dc9357SAndroid Build Coastguard Worker const UInt32 solidChunkSize = GetUi32(header + 8);
1298*f6dc9357SAndroid Build Coastguard Worker if (!GetLog_val_min_dest(solidChunkSize, 8, ss.ChunkSizeBits))
1299*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1300*f6dc9357SAndroid Build Coastguard Worker ss.Method = (Int32)GetUi32(header + 12);
1301*f6dc9357SAndroid Build Coastguard Worker
1302*f6dc9357SAndroid Build Coastguard Worker const UInt64 numChunks64 = (ss.UnpackSize + (((UInt32)1 << ss.ChunkSizeBits) - 1)) >> ss.ChunkSizeBits;
1303*f6dc9357SAndroid Build Coastguard Worker const UInt64 sizesBufSize64 = 4 * numChunks64;
1304*f6dc9357SAndroid Build Coastguard Worker ss.HeadersSize = kSolidHeaderSize + sizesBufSize64;
1305*f6dc9357SAndroid Build Coastguard Worker const size_t sizesBufSize = (size_t)sizesBufSize64;
1306*f6dc9357SAndroid Build Coastguard Worker if (sizesBufSize != sizesBufSize64)
1307*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
1308*f6dc9357SAndroid Build Coastguard Worker sizesBuf.AllocAtLeast(sizesBufSize);
1309*f6dc9357SAndroid Build Coastguard Worker
1310*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, sizesBuf, sizesBufSize))
1311*f6dc9357SAndroid Build Coastguard Worker
1312*f6dc9357SAndroid Build Coastguard Worker const size_t numChunks = (size_t)numChunks64;
1313*f6dc9357SAndroid Build Coastguard Worker ss.Chunks.Alloc(numChunks + 1);
1314*f6dc9357SAndroid Build Coastguard Worker
1315*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = 0;
1316*f6dc9357SAndroid Build Coastguard Worker
1317*f6dc9357SAndroid Build Coastguard Worker size_t c;
1318*f6dc9357SAndroid Build Coastguard Worker for (c = 0; c < numChunks; c++)
1319*f6dc9357SAndroid Build Coastguard Worker {
1320*f6dc9357SAndroid Build Coastguard Worker ss.Chunks[c] = offset;
1321*f6dc9357SAndroid Build Coastguard Worker UInt32 packSize = GetUi32((const Byte *)sizesBuf + c * 4);
1322*f6dc9357SAndroid Build Coastguard Worker offset += packSize;
1323*f6dc9357SAndroid Build Coastguard Worker if (offset < packSize)
1324*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1325*f6dc9357SAndroid Build Coastguard Worker }
1326*f6dc9357SAndroid Build Coastguard Worker ss.Chunks[c] = offset;
1327*f6dc9357SAndroid Build Coastguard Worker
1328*f6dc9357SAndroid Build Coastguard Worker if (ss.Chunks[0] != 0)
1329*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1330*f6dc9357SAndroid Build Coastguard Worker if (ss.HeadersSize + offset != r.PackSize)
1331*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1332*f6dc9357SAndroid Build Coastguard Worker }
1333*f6dc9357SAndroid Build Coastguard Worker }
1334*f6dc9357SAndroid Build Coastguard Worker
1335*f6dc9357SAndroid Build Coastguard Worker unsigned solidLim = k;
1336*f6dc9357SAndroid Build Coastguard Worker
1337*f6dc9357SAndroid Build Coastguard Worker for (k = iii; k < solidLim; k++)
1338*f6dc9357SAndroid Build Coastguard Worker {
1339*f6dc9357SAndroid Build Coastguard Worker CStreamInfo &si = DataStreams[k];
1340*f6dc9357SAndroid Build Coastguard Worker CResource &r = si.Resource;
1341*f6dc9357SAndroid Build Coastguard Worker
1342*f6dc9357SAndroid Build Coastguard Worker if (!r.IsSolidSmall())
1343*f6dc9357SAndroid Build Coastguard Worker continue;
1344*f6dc9357SAndroid Build Coastguard Worker
1345*f6dc9357SAndroid Build Coastguard Worker if (si.IsEmptyHash())
1346*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1347*f6dc9357SAndroid Build Coastguard Worker
1348*f6dc9357SAndroid Build Coastguard Worker unsigned solidIndex;
1349*f6dc9357SAndroid Build Coastguard Worker {
1350*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = r.Offset;
1351*f6dc9357SAndroid Build Coastguard Worker for (solidIndex = numSolidsStart;; solidIndex++)
1352*f6dc9357SAndroid Build Coastguard Worker {
1353*f6dc9357SAndroid Build Coastguard Worker if (solidIndex == Solids.Size())
1354*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1355*f6dc9357SAndroid Build Coastguard Worker UInt64 unpackSize = Solids[solidIndex].UnpackSize;
1356*f6dc9357SAndroid Build Coastguard Worker if (offset < unpackSize)
1357*f6dc9357SAndroid Build Coastguard Worker break;
1358*f6dc9357SAndroid Build Coastguard Worker offset -= unpackSize;
1359*f6dc9357SAndroid Build Coastguard Worker }
1360*f6dc9357SAndroid Build Coastguard Worker }
1361*f6dc9357SAndroid Build Coastguard Worker CSolid &ss = Solids[solidIndex];
1362*f6dc9357SAndroid Build Coastguard Worker if (r.Offset < ss.SolidOffset)
1363*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1364*f6dc9357SAndroid Build Coastguard Worker const UInt64 relat = r.Offset - ss.SolidOffset;
1365*f6dc9357SAndroid Build Coastguard Worker if (relat > ss.UnpackSize)
1366*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1367*f6dc9357SAndroid Build Coastguard Worker if (r.PackSize > ss.UnpackSize - relat)
1368*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1369*f6dc9357SAndroid Build Coastguard Worker r.SolidIndex = (int)solidIndex;
1370*f6dc9357SAndroid Build Coastguard Worker if (ss.FirstSmallStream < 0)
1371*f6dc9357SAndroid Build Coastguard Worker ss.FirstSmallStream = (int)k;
1372*f6dc9357SAndroid Build Coastguard Worker
1373*f6dc9357SAndroid Build Coastguard Worker sortedByHash.AddInReserved(k);
1374*f6dc9357SAndroid Build Coastguard Worker // ss.NumRefs++;
1375*f6dc9357SAndroid Build Coastguard Worker }
1376*f6dc9357SAndroid Build Coastguard Worker
1377*f6dc9357SAndroid Build Coastguard Worker iii = solidLim;
1378*f6dc9357SAndroid Build Coastguard Worker }
1379*f6dc9357SAndroid Build Coastguard Worker }
1380*f6dc9357SAndroid Build Coastguard Worker
1381*f6dc9357SAndroid Build Coastguard Worker if (Solids.IsEmpty())
1382*f6dc9357SAndroid Build Coastguard Worker {
1383*f6dc9357SAndroid Build Coastguard Worker /* We want to check that streams layout is OK.
1384*f6dc9357SAndroid Build Coastguard Worker So we need resources sorted by offset.
1385*f6dc9357SAndroid Build Coastguard Worker Another code can work with non-sorted streams.
1386*f6dc9357SAndroid Build Coastguard Worker NOTE: all WIM programs probably create wim archives with
1387*f6dc9357SAndroid Build Coastguard Worker sorted data streams. So it doesn't call Sort() here. */
1388*f6dc9357SAndroid Build Coastguard Worker
1389*f6dc9357SAndroid Build Coastguard Worker {
1390*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1391*f6dc9357SAndroid Build Coastguard Worker for (i = 1; i < DataStreams.Size(); i++)
1392*f6dc9357SAndroid Build Coastguard Worker {
1393*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &s0 = DataStreams[i - 1];
1394*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &s1 = DataStreams[i];
1395*f6dc9357SAndroid Build Coastguard Worker if (s0.PartNumber < s1.PartNumber) continue;
1396*f6dc9357SAndroid Build Coastguard Worker if (s0.PartNumber > s1.PartNumber) break;
1397*f6dc9357SAndroid Build Coastguard Worker if (s0.Resource.Offset < s1.Resource.Offset) continue;
1398*f6dc9357SAndroid Build Coastguard Worker if (s0.Resource.Offset > s1.Resource.Offset) break;
1399*f6dc9357SAndroid Build Coastguard Worker if (s0.Resource.PackSize > s1.Resource.PackSize) break;
1400*f6dc9357SAndroid Build Coastguard Worker }
1401*f6dc9357SAndroid Build Coastguard Worker
1402*f6dc9357SAndroid Build Coastguard Worker if (i < DataStreams.Size())
1403*f6dc9357SAndroid Build Coastguard Worker {
1404*f6dc9357SAndroid Build Coastguard Worker // return E_FAIL;
1405*f6dc9357SAndroid Build Coastguard Worker DataStreams.Sort(CompareStreamsByPos, NULL);
1406*f6dc9357SAndroid Build Coastguard Worker }
1407*f6dc9357SAndroid Build Coastguard Worker }
1408*f6dc9357SAndroid Build Coastguard Worker
1409*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 1; i < DataStreams.Size(); i++)
1410*f6dc9357SAndroid Build Coastguard Worker {
1411*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &s0 = DataStreams[i - 1];
1412*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &s1 = DataStreams[i];
1413*f6dc9357SAndroid Build Coastguard Worker if (s0.PartNumber == s1.PartNumber)
1414*f6dc9357SAndroid Build Coastguard Worker if (s0.Resource.GetEndLimit() > s1.Resource.Offset)
1415*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1416*f6dc9357SAndroid Build Coastguard Worker }
1417*f6dc9357SAndroid Build Coastguard Worker }
1418*f6dc9357SAndroid Build Coastguard Worker
1419*f6dc9357SAndroid Build Coastguard Worker {
1420*f6dc9357SAndroid Build Coastguard Worker {
1421*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo *streams = DataStreams.ConstData();
1422*f6dc9357SAndroid Build Coastguard Worker
1423*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
1424*f6dc9357SAndroid Build Coastguard Worker {
1425*f6dc9357SAndroid Build Coastguard Worker sortedByHash.Sort(CompareIDs, (void *)streams);
1426*f6dc9357SAndroid Build Coastguard Worker
1427*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 1; i < sortedByHash.Size(); i++)
1428*f6dc9357SAndroid Build Coastguard Worker if (streams[sortedByHash[i - 1]].Id >=
1429*f6dc9357SAndroid Build Coastguard Worker streams[sortedByHash[i]].Id)
1430*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1431*f6dc9357SAndroid Build Coastguard Worker }
1432*f6dc9357SAndroid Build Coastguard Worker else
1433*f6dc9357SAndroid Build Coastguard Worker {
1434*f6dc9357SAndroid Build Coastguard Worker sortedByHash.Sort(CompareHashRefs, (void *)streams);
1435*f6dc9357SAndroid Build Coastguard Worker
1436*f6dc9357SAndroid Build Coastguard Worker if (!sortedByHash.IsEmpty())
1437*f6dc9357SAndroid Build Coastguard Worker {
1438*f6dc9357SAndroid Build Coastguard Worker if (IsEmptySha(streams[sortedByHash[0]].Hash))
1439*f6dc9357SAndroid Build Coastguard Worker HeadersError = true;
1440*f6dc9357SAndroid Build Coastguard Worker
1441*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 1; i < sortedByHash.Size(); i++)
1442*f6dc9357SAndroid Build Coastguard Worker if (memcmp(
1443*f6dc9357SAndroid Build Coastguard Worker streams[sortedByHash[i - 1]].Hash,
1444*f6dc9357SAndroid Build Coastguard Worker streams[sortedByHash[i]].Hash,
1445*f6dc9357SAndroid Build Coastguard Worker kHashSize) >= 0)
1446*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1447*f6dc9357SAndroid Build Coastguard Worker }
1448*f6dc9357SAndroid Build Coastguard Worker }
1449*f6dc9357SAndroid Build Coastguard Worker }
1450*f6dc9357SAndroid Build Coastguard Worker
1451*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Items)
1452*f6dc9357SAndroid Build Coastguard Worker {
1453*f6dc9357SAndroid Build Coastguard Worker CItem &item = Items[i];
1454*f6dc9357SAndroid Build Coastguard Worker item.StreamIndex = -1;
1455*f6dc9357SAndroid Build Coastguard Worker const Byte *hash = Images[item.ImageIndex].Meta + item.Offset;
1456*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
1457*f6dc9357SAndroid Build Coastguard Worker {
1458*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir)
1459*f6dc9357SAndroid Build Coastguard Worker {
1460*f6dc9357SAndroid Build Coastguard Worker hash += (item.IsAltStream ? 0x8 : 0x10);
1461*f6dc9357SAndroid Build Coastguard Worker UInt32 id = GetUi32(hash);
1462*f6dc9357SAndroid Build Coastguard Worker if (id != 0)
1463*f6dc9357SAndroid Build Coastguard Worker item.StreamIndex = FindId(DataStreams.ConstData(), sortedByHash, id);
1464*f6dc9357SAndroid Build Coastguard Worker }
1465*f6dc9357SAndroid Build Coastguard Worker }
1466*f6dc9357SAndroid Build Coastguard Worker /*
1467*f6dc9357SAndroid Build Coastguard Worker else if (item.IsDir)
1468*f6dc9357SAndroid Build Coastguard Worker {
1469*f6dc9357SAndroid Build Coastguard Worker // reparse points can have dirs some dir
1470*f6dc9357SAndroid Build Coastguard Worker }
1471*f6dc9357SAndroid Build Coastguard Worker */
1472*f6dc9357SAndroid Build Coastguard Worker else
1473*f6dc9357SAndroid Build Coastguard Worker {
1474*f6dc9357SAndroid Build Coastguard Worker hash += (item.IsAltStream ? 0x10 : 0x40);
1475*f6dc9357SAndroid Build Coastguard Worker if (!IsEmptySha(hash))
1476*f6dc9357SAndroid Build Coastguard Worker {
1477*f6dc9357SAndroid Build Coastguard Worker item.StreamIndex = FindHash(DataStreams.ConstData(), sortedByHash, hash);
1478*f6dc9357SAndroid Build Coastguard Worker }
1479*f6dc9357SAndroid Build Coastguard Worker }
1480*f6dc9357SAndroid Build Coastguard Worker }
1481*f6dc9357SAndroid Build Coastguard Worker }
1482*f6dc9357SAndroid Build Coastguard Worker {
1483*f6dc9357SAndroid Build Coastguard Worker CUIntVector refCounts;
1484*f6dc9357SAndroid Build Coastguard Worker refCounts.ClearAndSetSize(DataStreams.Size());
1485*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1486*f6dc9357SAndroid Build Coastguard Worker
1487*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < DataStreams.Size(); i++)
1488*f6dc9357SAndroid Build Coastguard Worker {
1489*f6dc9357SAndroid Build Coastguard Worker UInt32 startVal = 0;
1490*f6dc9357SAndroid Build Coastguard Worker // const CStreamInfo &s = DataStreams[i];
1491*f6dc9357SAndroid Build Coastguard Worker /*
1492*f6dc9357SAndroid Build Coastguard Worker if (s.Resource.IsMetadata() && s.PartNumber == 1)
1493*f6dc9357SAndroid Build Coastguard Worker startVal = 1;
1494*f6dc9357SAndroid Build Coastguard Worker */
1495*f6dc9357SAndroid Build Coastguard Worker refCounts[i] = startVal;
1496*f6dc9357SAndroid Build Coastguard Worker }
1497*f6dc9357SAndroid Build Coastguard Worker
1498*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Items.Size(); i++)
1499*f6dc9357SAndroid Build Coastguard Worker {
1500*f6dc9357SAndroid Build Coastguard Worker const int streamIndex = Items[i].StreamIndex;
1501*f6dc9357SAndroid Build Coastguard Worker if (streamIndex >= 0)
1502*f6dc9357SAndroid Build Coastguard Worker refCounts[streamIndex]++;
1503*f6dc9357SAndroid Build Coastguard Worker }
1504*f6dc9357SAndroid Build Coastguard Worker
1505*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < DataStreams.Size(); i++)
1506*f6dc9357SAndroid Build Coastguard Worker {
1507*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &s = DataStreams[i];
1508*f6dc9357SAndroid Build Coastguard Worker if (s.RefCount != refCounts[i]
1509*f6dc9357SAndroid Build Coastguard Worker && !s.Resource.IsSolidBig())
1510*f6dc9357SAndroid Build Coastguard Worker {
1511*f6dc9357SAndroid Build Coastguard Worker /*
1512*f6dc9357SAndroid Build Coastguard Worker printf("\ni=%5d si.Ref=%2d realRefs=%2d size=%8d offset=%8x id=%4d ",
1513*f6dc9357SAndroid Build Coastguard Worker i, s.RefCount, refCounts[i], (unsigned)s.Resource.UnpackSize, (unsigned)s.Resource.Offset, s.Id);
1514*f6dc9357SAndroid Build Coastguard Worker */
1515*f6dc9357SAndroid Build Coastguard Worker RefCountError = true;
1516*f6dc9357SAndroid Build Coastguard Worker }
1517*f6dc9357SAndroid Build Coastguard Worker
1518*f6dc9357SAndroid Build Coastguard Worker if (refCounts[i] == 0)
1519*f6dc9357SAndroid Build Coastguard Worker {
1520*f6dc9357SAndroid Build Coastguard Worker const CResource &r = DataStreams[i].Resource;
1521*f6dc9357SAndroid Build Coastguard Worker if (!r.IsSolidBig() || Solids[r.SolidIndex].FirstSmallStream < 0)
1522*f6dc9357SAndroid Build Coastguard Worker {
1523*f6dc9357SAndroid Build Coastguard Worker CItem item;
1524*f6dc9357SAndroid Build Coastguard Worker item.Offset = 0;
1525*f6dc9357SAndroid Build Coastguard Worker item.StreamIndex = (int)i;
1526*f6dc9357SAndroid Build Coastguard Worker item.ImageIndex = -1;
1527*f6dc9357SAndroid Build Coastguard Worker Items.Add(item);
1528*f6dc9357SAndroid Build Coastguard Worker ThereAreDeletedStreams = true;
1529*f6dc9357SAndroid Build Coastguard Worker }
1530*f6dc9357SAndroid Build Coastguard Worker }
1531*f6dc9357SAndroid Build Coastguard Worker }
1532*f6dc9357SAndroid Build Coastguard Worker }
1533*f6dc9357SAndroid Build Coastguard Worker
1534*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1535*f6dc9357SAndroid Build Coastguard Worker }
1536*f6dc9357SAndroid Build Coastguard Worker
1537*f6dc9357SAndroid Build Coastguard Worker
GenerateSortedItems(int imageIndex,bool showImageNumber)1538*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
1539*f6dc9357SAndroid Build Coastguard Worker {
1540*f6dc9357SAndroid Build Coastguard Worker SortedItems.Clear();
1541*f6dc9357SAndroid Build Coastguard Worker VirtualRoots.Clear();
1542*f6dc9357SAndroid Build Coastguard Worker IndexOfUserImage = imageIndex;
1543*f6dc9357SAndroid Build Coastguard Worker NumExcludededItems = 0;
1544*f6dc9357SAndroid Build Coastguard Worker ExludedItem = -1;
1545*f6dc9357SAndroid Build Coastguard Worker
1546*f6dc9357SAndroid Build Coastguard Worker if (Images.Size() != 1 && imageIndex < 0)
1547*f6dc9357SAndroid Build Coastguard Worker showImageNumber = true;
1548*f6dc9357SAndroid Build Coastguard Worker
1549*f6dc9357SAndroid Build Coastguard Worker unsigned startItem = 0;
1550*f6dc9357SAndroid Build Coastguard Worker unsigned endItem = 0;
1551*f6dc9357SAndroid Build Coastguard Worker
1552*f6dc9357SAndroid Build Coastguard Worker if (imageIndex < 0)
1553*f6dc9357SAndroid Build Coastguard Worker {
1554*f6dc9357SAndroid Build Coastguard Worker endItem = Items.Size();
1555*f6dc9357SAndroid Build Coastguard Worker if (Images.Size() == 1)
1556*f6dc9357SAndroid Build Coastguard Worker {
1557*f6dc9357SAndroid Build Coastguard Worker IndexOfUserImage = 0;
1558*f6dc9357SAndroid Build Coastguard Worker const CImage &image = Images[0];
1559*f6dc9357SAndroid Build Coastguard Worker if (!showImageNumber)
1560*f6dc9357SAndroid Build Coastguard Worker NumExcludededItems = image.NumEmptyRootItems;
1561*f6dc9357SAndroid Build Coastguard Worker }
1562*f6dc9357SAndroid Build Coastguard Worker }
1563*f6dc9357SAndroid Build Coastguard Worker else if ((unsigned)imageIndex < Images.Size())
1564*f6dc9357SAndroid Build Coastguard Worker {
1565*f6dc9357SAndroid Build Coastguard Worker const CImage &image = Images[imageIndex];
1566*f6dc9357SAndroid Build Coastguard Worker startItem = image.StartItem;
1567*f6dc9357SAndroid Build Coastguard Worker endItem = startItem + image.NumItems;
1568*f6dc9357SAndroid Build Coastguard Worker if (!showImageNumber)
1569*f6dc9357SAndroid Build Coastguard Worker NumExcludededItems = image.NumEmptyRootItems;
1570*f6dc9357SAndroid Build Coastguard Worker }
1571*f6dc9357SAndroid Build Coastguard Worker
1572*f6dc9357SAndroid Build Coastguard Worker if (NumExcludededItems != 0)
1573*f6dc9357SAndroid Build Coastguard Worker {
1574*f6dc9357SAndroid Build Coastguard Worker ExludedItem = (int)startItem;
1575*f6dc9357SAndroid Build Coastguard Worker startItem += NumExcludededItems;
1576*f6dc9357SAndroid Build Coastguard Worker }
1577*f6dc9357SAndroid Build Coastguard Worker
1578*f6dc9357SAndroid Build Coastguard Worker unsigned num = endItem - startItem;
1579*f6dc9357SAndroid Build Coastguard Worker SortedItems.ClearAndSetSize(num);
1580*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1581*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
1582*f6dc9357SAndroid Build Coastguard Worker SortedItems[i] = startItem + i;
1583*f6dc9357SAndroid Build Coastguard Worker
1584*f6dc9357SAndroid Build Coastguard Worker SortedItems.Sort(CompareItems, this);
1585*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < SortedItems.Size(); i++)
1586*f6dc9357SAndroid Build Coastguard Worker Items[SortedItems[i]].IndexInSorted = (int)i;
1587*f6dc9357SAndroid Build Coastguard Worker
1588*f6dc9357SAndroid Build Coastguard Worker if (showImageNumber)
1589*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Images.Size(); i++)
1590*f6dc9357SAndroid Build Coastguard Worker {
1591*f6dc9357SAndroid Build Coastguard Worker CImage &image = Images[i];
1592*f6dc9357SAndroid Build Coastguard Worker if (image.NumEmptyRootItems != 0)
1593*f6dc9357SAndroid Build Coastguard Worker continue;
1594*f6dc9357SAndroid Build Coastguard Worker image.VirtualRootIndex = (int)VirtualRoots.Size();
1595*f6dc9357SAndroid Build Coastguard Worker VirtualRoots.Add(i);
1596*f6dc9357SAndroid Build Coastguard Worker }
1597*f6dc9357SAndroid Build Coastguard Worker
1598*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1599*f6dc9357SAndroid Build Coastguard Worker }
1600*f6dc9357SAndroid Build Coastguard Worker
1601*f6dc9357SAndroid Build Coastguard Worker
IntVector_SetMinusOne_IfNeed(CIntVector & v,unsigned size)1602*f6dc9357SAndroid Build Coastguard Worker static void IntVector_SetMinusOne_IfNeed(CIntVector &v, unsigned size)
1603*f6dc9357SAndroid Build Coastguard Worker {
1604*f6dc9357SAndroid Build Coastguard Worker if (v.Size() == size)
1605*f6dc9357SAndroid Build Coastguard Worker return;
1606*f6dc9357SAndroid Build Coastguard Worker v.ClearAndSetSize(size);
1607*f6dc9357SAndroid Build Coastguard Worker int *vals = &v[0];
1608*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < size; i++)
1609*f6dc9357SAndroid Build Coastguard Worker vals[i] = -1;
1610*f6dc9357SAndroid Build Coastguard Worker }
1611*f6dc9357SAndroid Build Coastguard Worker
1612*f6dc9357SAndroid Build Coastguard Worker
ExtractReparseStreams(const CObjectVector<CVolume> & volumes,IArchiveOpenCallback * openCallback)1613*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback)
1614*f6dc9357SAndroid Build Coastguard Worker {
1615*f6dc9357SAndroid Build Coastguard Worker ItemToReparse.Clear();
1616*f6dc9357SAndroid Build Coastguard Worker ReparseItems.Clear();
1617*f6dc9357SAndroid Build Coastguard Worker
1618*f6dc9357SAndroid Build Coastguard Worker // we don't know about Reparse field for OLD WIM format
1619*f6dc9357SAndroid Build Coastguard Worker if (IsOldVersion)
1620*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1621*f6dc9357SAndroid Build Coastguard Worker
1622*f6dc9357SAndroid Build Coastguard Worker CIntVector streamToReparse;
1623*f6dc9357SAndroid Build Coastguard Worker CUnpacker unpacker;
1624*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackedPrev = 0;
1625*f6dc9357SAndroid Build Coastguard Worker
1626*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR(indexInSorted, SortedItems)
1627*f6dc9357SAndroid Build Coastguard Worker {
1628*f6dc9357SAndroid Build Coastguard Worker // we use sorted items for faster access
1629*f6dc9357SAndroid Build Coastguard Worker unsigned itemIndex = SortedItems[indexInSorted];
1630*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[itemIndex];
1631*f6dc9357SAndroid Build Coastguard Worker
1632*f6dc9357SAndroid Build Coastguard Worker if (!item.HasMetadata() || item.IsAltStream)
1633*f6dc9357SAndroid Build Coastguard Worker continue;
1634*f6dc9357SAndroid Build Coastguard Worker
1635*f6dc9357SAndroid Build Coastguard Worker if (item.ImageIndex < 0)
1636*f6dc9357SAndroid Build Coastguard Worker continue;
1637*f6dc9357SAndroid Build Coastguard Worker
1638*f6dc9357SAndroid Build Coastguard Worker const Byte *metadata = Images[item.ImageIndex].Meta + item.Offset;
1639*f6dc9357SAndroid Build Coastguard Worker
1640*f6dc9357SAndroid Build Coastguard Worker const UInt32 attrib = Get32(metadata + 8);
1641*f6dc9357SAndroid Build Coastguard Worker if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1642*f6dc9357SAndroid Build Coastguard Worker continue;
1643*f6dc9357SAndroid Build Coastguard Worker
1644*f6dc9357SAndroid Build Coastguard Worker if (item.StreamIndex < 0)
1645*f6dc9357SAndroid Build Coastguard Worker continue; // it's ERROR
1646*f6dc9357SAndroid Build Coastguard Worker
1647*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &si = DataStreams[item.StreamIndex];
1648*f6dc9357SAndroid Build Coastguard Worker if (si.Resource.UnpackSize >= (1 << 16))
1649*f6dc9357SAndroid Build Coastguard Worker continue; // reparse data can not be larger than 64 KB
1650*f6dc9357SAndroid Build Coastguard Worker
1651*f6dc9357SAndroid Build Coastguard Worker IntVector_SetMinusOne_IfNeed(streamToReparse, DataStreams.Size());
1652*f6dc9357SAndroid Build Coastguard Worker IntVector_SetMinusOne_IfNeed(ItemToReparse, Items.Size());
1653*f6dc9357SAndroid Build Coastguard Worker
1654*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = 0x58; // we don't know about Reparse field for OLD WIM format
1655*f6dc9357SAndroid Build Coastguard Worker UInt32 tag = Get32(metadata + offset);
1656*f6dc9357SAndroid Build Coastguard Worker int reparseIndex = streamToReparse[item.StreamIndex];
1657*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buf;
1658*f6dc9357SAndroid Build Coastguard Worker
1659*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
1660*f6dc9357SAndroid Build Coastguard Worker {
1661*f6dc9357SAndroid Build Coastguard Worker if ((unpacker.TotalPacked - totalPackedPrev) >= ((UInt32)1 << 16))
1662*f6dc9357SAndroid Build Coastguard Worker {
1663*f6dc9357SAndroid Build Coastguard Worker UInt64 numFiles = Items.Size();
1664*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetCompleted(&numFiles, &unpacker.TotalPacked))
1665*f6dc9357SAndroid Build Coastguard Worker totalPackedPrev = unpacker.TotalPacked;
1666*f6dc9357SAndroid Build Coastguard Worker }
1667*f6dc9357SAndroid Build Coastguard Worker }
1668*f6dc9357SAndroid Build Coastguard Worker
1669*f6dc9357SAndroid Build Coastguard Worker if (reparseIndex >= 0)
1670*f6dc9357SAndroid Build Coastguard Worker {
1671*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &reparse = ReparseItems[reparseIndex];
1672*f6dc9357SAndroid Build Coastguard Worker if (tag == Get32(reparse))
1673*f6dc9357SAndroid Build Coastguard Worker {
1674*f6dc9357SAndroid Build Coastguard Worker ItemToReparse[itemIndex] = reparseIndex;
1675*f6dc9357SAndroid Build Coastguard Worker continue;
1676*f6dc9357SAndroid Build Coastguard Worker }
1677*f6dc9357SAndroid Build Coastguard Worker buf = reparse;
1678*f6dc9357SAndroid Build Coastguard Worker // we support that strange and unusual situation with different tags and same reparse data.
1679*f6dc9357SAndroid Build Coastguard Worker }
1680*f6dc9357SAndroid Build Coastguard Worker else
1681*f6dc9357SAndroid Build Coastguard Worker {
1682*f6dc9357SAndroid Build Coastguard Worker /*
1683*f6dc9357SAndroid Build Coastguard Worker if (si.PartNumber >= volumes.Size())
1684*f6dc9357SAndroid Build Coastguard Worker continue;
1685*f6dc9357SAndroid Build Coastguard Worker */
1686*f6dc9357SAndroid Build Coastguard Worker const CVolume &vol = volumes[si.PartNumber];
1687*f6dc9357SAndroid Build Coastguard Worker /*
1688*f6dc9357SAndroid Build Coastguard Worker if (!vol.Stream)
1689*f6dc9357SAndroid Build Coastguard Worker continue;
1690*f6dc9357SAndroid Build Coastguard Worker */
1691*f6dc9357SAndroid Build Coastguard Worker
1692*f6dc9357SAndroid Build Coastguard Worker Byte digest[kHashSize];
1693*f6dc9357SAndroid Build Coastguard Worker HRESULT res = unpacker.UnpackData(vol.Stream, si.Resource, vol.Header, this, buf, digest);
1694*f6dc9357SAndroid Build Coastguard Worker
1695*f6dc9357SAndroid Build Coastguard Worker if (res == S_FALSE)
1696*f6dc9357SAndroid Build Coastguard Worker continue;
1697*f6dc9357SAndroid Build Coastguard Worker
1698*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
1699*f6dc9357SAndroid Build Coastguard Worker
1700*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, si.Hash, kHashSize) != 0
1701*f6dc9357SAndroid Build Coastguard Worker // && !(h.IsOldVersion() && IsEmptySha(si.Hash))
1702*f6dc9357SAndroid Build Coastguard Worker )
1703*f6dc9357SAndroid Build Coastguard Worker {
1704*f6dc9357SAndroid Build Coastguard Worker // setErrorStatus;
1705*f6dc9357SAndroid Build Coastguard Worker continue;
1706*f6dc9357SAndroid Build Coastguard Worker }
1707*f6dc9357SAndroid Build Coastguard Worker }
1708*f6dc9357SAndroid Build Coastguard Worker
1709*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &reparse = ReparseItems.AddNew();
1710*f6dc9357SAndroid Build Coastguard Worker reparse.Alloc(8 + buf.Size());
1711*f6dc9357SAndroid Build Coastguard Worker Byte *dest = (Byte *)reparse;
1712*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest, tag)
1713*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 4, (UInt32)buf.Size())
1714*f6dc9357SAndroid Build Coastguard Worker if (buf.Size() != 0)
1715*f6dc9357SAndroid Build Coastguard Worker memcpy(dest + 8, buf, buf.Size());
1716*f6dc9357SAndroid Build Coastguard Worker ItemToReparse[itemIndex] = (int)ReparseItems.Size() - 1;
1717*f6dc9357SAndroid Build Coastguard Worker }
1718*f6dc9357SAndroid Build Coastguard Worker
1719*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1720*f6dc9357SAndroid Build Coastguard Worker }
1721*f6dc9357SAndroid Build Coastguard Worker
1722*f6dc9357SAndroid Build Coastguard Worker
1723*f6dc9357SAndroid Build Coastguard Worker
ParseNumber64(const AString & s,UInt64 & res)1724*f6dc9357SAndroid Build Coastguard Worker static bool ParseNumber64(const AString &s, UInt64 &res)
1725*f6dc9357SAndroid Build Coastguard Worker {
1726*f6dc9357SAndroid Build Coastguard Worker const char *end;
1727*f6dc9357SAndroid Build Coastguard Worker if (s.IsPrefixedBy("0x"))
1728*f6dc9357SAndroid Build Coastguard Worker {
1729*f6dc9357SAndroid Build Coastguard Worker if (s.Len() == 2)
1730*f6dc9357SAndroid Build Coastguard Worker return false;
1731*f6dc9357SAndroid Build Coastguard Worker res = ConvertHexStringToUInt64(s.Ptr(2), &end);
1732*f6dc9357SAndroid Build Coastguard Worker }
1733*f6dc9357SAndroid Build Coastguard Worker else
1734*f6dc9357SAndroid Build Coastguard Worker {
1735*f6dc9357SAndroid Build Coastguard Worker if (s.IsEmpty())
1736*f6dc9357SAndroid Build Coastguard Worker return false;
1737*f6dc9357SAndroid Build Coastguard Worker res = ConvertStringToUInt64(s, &end);
1738*f6dc9357SAndroid Build Coastguard Worker }
1739*f6dc9357SAndroid Build Coastguard Worker return *end == 0;
1740*f6dc9357SAndroid Build Coastguard Worker }
1741*f6dc9357SAndroid Build Coastguard Worker
1742*f6dc9357SAndroid Build Coastguard Worker
ParseNumber32(const AString & s,UInt32 & res)1743*f6dc9357SAndroid Build Coastguard Worker static bool ParseNumber32(const AString &s, UInt32 &res)
1744*f6dc9357SAndroid Build Coastguard Worker {
1745*f6dc9357SAndroid Build Coastguard Worker UInt64 res64;
1746*f6dc9357SAndroid Build Coastguard Worker if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32))
1747*f6dc9357SAndroid Build Coastguard Worker return false;
1748*f6dc9357SAndroid Build Coastguard Worker res = (UInt32)res64;
1749*f6dc9357SAndroid Build Coastguard Worker return true;
1750*f6dc9357SAndroid Build Coastguard Worker }
1751*f6dc9357SAndroid Build Coastguard Worker
1752*f6dc9357SAndroid Build Coastguard Worker
ParseTime(const CXmlItem & item,FILETIME & ft,const char * tag)1753*f6dc9357SAndroid Build Coastguard Worker static bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)
1754*f6dc9357SAndroid Build Coastguard Worker {
1755*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *timeItem = item.FindSubTag_GetPtr(tag);
1756*f6dc9357SAndroid Build Coastguard Worker if (timeItem)
1757*f6dc9357SAndroid Build Coastguard Worker {
1758*f6dc9357SAndroid Build Coastguard Worker UInt32 low = 0, high = 0;
1759*f6dc9357SAndroid Build Coastguard Worker if (ParseNumber32(timeItem->GetSubStringForTag("LOWPART"), low) &&
1760*f6dc9357SAndroid Build Coastguard Worker ParseNumber32(timeItem->GetSubStringForTag("HIGHPART"), high))
1761*f6dc9357SAndroid Build Coastguard Worker {
1762*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = low;
1763*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = high;
1764*f6dc9357SAndroid Build Coastguard Worker return true;
1765*f6dc9357SAndroid Build Coastguard Worker }
1766*f6dc9357SAndroid Build Coastguard Worker }
1767*f6dc9357SAndroid Build Coastguard Worker return false;
1768*f6dc9357SAndroid Build Coastguard Worker }
1769*f6dc9357SAndroid Build Coastguard Worker
1770*f6dc9357SAndroid Build Coastguard Worker
Parse(const CXmlItem & item)1771*f6dc9357SAndroid Build Coastguard Worker void CImageInfo::Parse(const CXmlItem &item)
1772*f6dc9357SAndroid Build Coastguard Worker {
1773*f6dc9357SAndroid Build Coastguard Worker CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");
1774*f6dc9357SAndroid Build Coastguard Worker MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");
1775*f6dc9357SAndroid Build Coastguard Worker NameDefined = true;
1776*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
1777*f6dc9357SAndroid Build Coastguard Worker
1778*f6dc9357SAndroid Build Coastguard Worker ParseNumber64(item.GetSubStringForTag("DIRCOUNT"), DirCount);
1779*f6dc9357SAndroid Build Coastguard Worker ParseNumber64(item.GetSubStringForTag("FILECOUNT"), FileCount);
1780*f6dc9357SAndroid Build Coastguard Worker IndexDefined = ParseNumber32(item.GetPropVal("INDEX"), Index);
1781*f6dc9357SAndroid Build Coastguard Worker }
1782*f6dc9357SAndroid Build Coastguard Worker
ToUnicode(UString & s)1783*f6dc9357SAndroid Build Coastguard Worker void CWimXml::ToUnicode(UString &s)
1784*f6dc9357SAndroid Build Coastguard Worker {
1785*f6dc9357SAndroid Build Coastguard Worker size_t size = Data.Size();
1786*f6dc9357SAndroid Build Coastguard Worker if (size < 2 || (size & 1) != 0 || size > (1 << 24))
1787*f6dc9357SAndroid Build Coastguard Worker return;
1788*f6dc9357SAndroid Build Coastguard Worker const Byte *p = Data;
1789*f6dc9357SAndroid Build Coastguard Worker if (Get16(p) != 0xFEFF)
1790*f6dc9357SAndroid Build Coastguard Worker return;
1791*f6dc9357SAndroid Build Coastguard Worker wchar_t *chars = s.GetBuf((unsigned)(size / 2));
1792*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 2; i < size; i += 2)
1793*f6dc9357SAndroid Build Coastguard Worker {
1794*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(p + i);
1795*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1796*f6dc9357SAndroid Build Coastguard Worker break;
1797*f6dc9357SAndroid Build Coastguard Worker *chars++ = c;
1798*f6dc9357SAndroid Build Coastguard Worker }
1799*f6dc9357SAndroid Build Coastguard Worker *chars = 0;
1800*f6dc9357SAndroid Build Coastguard Worker s.ReleaseBuf_SetLen((unsigned)(chars - (const wchar_t *)s));
1801*f6dc9357SAndroid Build Coastguard Worker }
1802*f6dc9357SAndroid Build Coastguard Worker
1803*f6dc9357SAndroid Build Coastguard Worker
Parse()1804*f6dc9357SAndroid Build Coastguard Worker bool CWimXml::Parse()
1805*f6dc9357SAndroid Build Coastguard Worker {
1806*f6dc9357SAndroid Build Coastguard Worker IsEncrypted = false;
1807*f6dc9357SAndroid Build Coastguard Worker AString utf;
1808*f6dc9357SAndroid Build Coastguard Worker {
1809*f6dc9357SAndroid Build Coastguard Worker UString s;
1810*f6dc9357SAndroid Build Coastguard Worker ToUnicode(s);
1811*f6dc9357SAndroid Build Coastguard Worker // if (!ConvertUnicodeToUTF8(s, utf)) return false;
1812*f6dc9357SAndroid Build Coastguard Worker ConvertUnicodeToUTF8(s, utf);
1813*f6dc9357SAndroid Build Coastguard Worker }
1814*f6dc9357SAndroid Build Coastguard Worker
1815*f6dc9357SAndroid Build Coastguard Worker if (!Xml.Parse(utf))
1816*f6dc9357SAndroid Build Coastguard Worker return false;
1817*f6dc9357SAndroid Build Coastguard Worker if (Xml.Root.Name != "WIM")
1818*f6dc9357SAndroid Build Coastguard Worker return false;
1819*f6dc9357SAndroid Build Coastguard Worker
1820*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Xml.Root.SubItems)
1821*f6dc9357SAndroid Build Coastguard Worker {
1822*f6dc9357SAndroid Build Coastguard Worker const CXmlItem &item = Xml.Root.SubItems[i];
1823*f6dc9357SAndroid Build Coastguard Worker
1824*f6dc9357SAndroid Build Coastguard Worker if (item.IsTagged("IMAGE"))
1825*f6dc9357SAndroid Build Coastguard Worker {
1826*f6dc9357SAndroid Build Coastguard Worker CImageInfo imageInfo;
1827*f6dc9357SAndroid Build Coastguard Worker imageInfo.Parse(item);
1828*f6dc9357SAndroid Build Coastguard Worker if (!imageInfo.IndexDefined)
1829*f6dc9357SAndroid Build Coastguard Worker return false;
1830*f6dc9357SAndroid Build Coastguard Worker
1831*f6dc9357SAndroid Build Coastguard Worker if (imageInfo.Index != (UInt32)Images.Size() + 1)
1832*f6dc9357SAndroid Build Coastguard Worker {
1833*f6dc9357SAndroid Build Coastguard Worker // old wim (1.09) uses zero based image index
1834*f6dc9357SAndroid Build Coastguard Worker if (imageInfo.Index != (UInt32)Images.Size())
1835*f6dc9357SAndroid Build Coastguard Worker return false;
1836*f6dc9357SAndroid Build Coastguard Worker }
1837*f6dc9357SAndroid Build Coastguard Worker
1838*f6dc9357SAndroid Build Coastguard Worker imageInfo.ItemIndexInXml = (int)i;
1839*f6dc9357SAndroid Build Coastguard Worker Images.Add(imageInfo);
1840*f6dc9357SAndroid Build Coastguard Worker }
1841*f6dc9357SAndroid Build Coastguard Worker
1842*f6dc9357SAndroid Build Coastguard Worker if (item.IsTagged("ESD"))
1843*f6dc9357SAndroid Build Coastguard Worker {
1844*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (k, item.SubItems)
1845*f6dc9357SAndroid Build Coastguard Worker {
1846*f6dc9357SAndroid Build Coastguard Worker const CXmlItem &item2 = item.SubItems[k];
1847*f6dc9357SAndroid Build Coastguard Worker if (item2.IsTagged("ENCRYPTED"))
1848*f6dc9357SAndroid Build Coastguard Worker IsEncrypted = true;
1849*f6dc9357SAndroid Build Coastguard Worker }
1850*f6dc9357SAndroid Build Coastguard Worker }
1851*f6dc9357SAndroid Build Coastguard Worker }
1852*f6dc9357SAndroid Build Coastguard Worker
1853*f6dc9357SAndroid Build Coastguard Worker return true;
1854*f6dc9357SAndroid Build Coastguard Worker }
1855*f6dc9357SAndroid Build Coastguard Worker
1856*f6dc9357SAndroid Build Coastguard Worker }}
1857