xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Nsis/NsisDecode.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // NsisDecode.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "NsisDecode.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/CreateCoder.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MethodId.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/BcjCoder.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
18*f6dc9357SAndroid Build Coastguard Worker namespace NNsis {
19*f6dc9357SAndroid Build Coastguard Worker 
GetInputProcessedSize() const20*f6dc9357SAndroid Build Coastguard Worker UInt64 CDecoder::GetInputProcessedSize() const
21*f6dc9357SAndroid Build Coastguard Worker {
22*f6dc9357SAndroid Build Coastguard Worker   if (_lzmaDecoder)
23*f6dc9357SAndroid Build Coastguard Worker     return _lzmaDecoder->GetInputProcessedSize();
24*f6dc9357SAndroid Build Coastguard Worker   if (_deflateDecoder)
25*f6dc9357SAndroid Build Coastguard Worker     return _deflateDecoder->GetInputProcessedSize();
26*f6dc9357SAndroid Build Coastguard Worker   if (_bzDecoder)
27*f6dc9357SAndroid Build Coastguard Worker     return _bzDecoder->GetInputProcessedSize();
28*f6dc9357SAndroid Build Coastguard Worker   return 0;
29*f6dc9357SAndroid Build Coastguard Worker }
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker 
Init(ISequentialInStream * inStream,bool & useFilter)32*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
33*f6dc9357SAndroid Build Coastguard Worker {
34*f6dc9357SAndroid Build Coastguard Worker   useFilter = false;
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker   if (_decoderInStream)
37*f6dc9357SAndroid Build Coastguard Worker     if (Method != _curMethod)
38*f6dc9357SAndroid Build Coastguard Worker       Release();
39*f6dc9357SAndroid Build Coastguard Worker   _curMethod = Method;
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker   if (!_codecInStream)
42*f6dc9357SAndroid Build Coastguard Worker   {
43*f6dc9357SAndroid Build Coastguard Worker     switch ((int)Method)
44*f6dc9357SAndroid Build Coastguard Worker     {
45*f6dc9357SAndroid Build Coastguard Worker       // case NMethodType::kCopy: return E_NOTIMPL;
46*f6dc9357SAndroid Build Coastguard Worker       case NMethodType::kDeflate:
47*f6dc9357SAndroid Build Coastguard Worker         _deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder();
48*f6dc9357SAndroid Build Coastguard Worker         _codecInStream = _deflateDecoder;
49*f6dc9357SAndroid Build Coastguard Worker         break;
50*f6dc9357SAndroid Build Coastguard Worker       case NMethodType::kBZip2:
51*f6dc9357SAndroid Build Coastguard Worker         _bzDecoder = new NCompress::NBZip2::CNsisDecoder();
52*f6dc9357SAndroid Build Coastguard Worker         _codecInStream = _bzDecoder;
53*f6dc9357SAndroid Build Coastguard Worker         break;
54*f6dc9357SAndroid Build Coastguard Worker       case NMethodType::kLZMA:
55*f6dc9357SAndroid Build Coastguard Worker         _lzmaDecoder = new NCompress::NLzma::CDecoder();
56*f6dc9357SAndroid Build Coastguard Worker         _codecInStream = _lzmaDecoder;
57*f6dc9357SAndroid Build Coastguard Worker         break;
58*f6dc9357SAndroid Build Coastguard Worker       default: return E_NOTIMPL;
59*f6dc9357SAndroid Build Coastguard Worker     }
60*f6dc9357SAndroid Build Coastguard Worker   }
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker   if (Method == NMethodType::kDeflate)
63*f6dc9357SAndroid Build Coastguard Worker     _deflateDecoder->SetNsisMode(IsNsisDeflate);
64*f6dc9357SAndroid Build Coastguard Worker 
65*f6dc9357SAndroid Build Coastguard Worker   if (FilterFlag)
66*f6dc9357SAndroid Build Coastguard Worker   {
67*f6dc9357SAndroid Build Coastguard Worker     Byte flag;
68*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(inStream, &flag, 1))
69*f6dc9357SAndroid Build Coastguard Worker     if (flag > 1)
70*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
71*f6dc9357SAndroid Build Coastguard Worker     useFilter = (flag != 0);
72*f6dc9357SAndroid Build Coastguard Worker   }
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker   if (!useFilter)
75*f6dc9357SAndroid Build Coastguard Worker     _decoderInStream = _codecInStream;
76*f6dc9357SAndroid Build Coastguard Worker   else
77*f6dc9357SAndroid Build Coastguard Worker   {
78*f6dc9357SAndroid Build Coastguard Worker     if (!_filterInStream)
79*f6dc9357SAndroid Build Coastguard Worker     {
80*f6dc9357SAndroid Build Coastguard Worker       _filter = new CFilterCoder(false);
81*f6dc9357SAndroid Build Coastguard Worker       _filterInStream = _filter;
82*f6dc9357SAndroid Build Coastguard Worker       _filter->Filter = new NCompress::NBcj::CCoder2(z7_BranchConvSt_X86_Dec);
83*f6dc9357SAndroid Build Coastguard Worker     }
84*f6dc9357SAndroid Build Coastguard Worker     RINOK(_filter->SetInStream(_codecInStream))
85*f6dc9357SAndroid Build Coastguard Worker     _decoderInStream = _filterInStream;
86*f6dc9357SAndroid Build Coastguard Worker   }
87*f6dc9357SAndroid Build Coastguard Worker 
88*f6dc9357SAndroid Build Coastguard Worker   if (Method == NMethodType::kLZMA)
89*f6dc9357SAndroid Build Coastguard Worker   {
90*f6dc9357SAndroid Build Coastguard Worker     const unsigned kPropsSize = LZMA_PROPS_SIZE;
91*f6dc9357SAndroid Build Coastguard Worker     Byte props[kPropsSize];
92*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(inStream, props, kPropsSize))
93*f6dc9357SAndroid Build Coastguard Worker     RINOK(_lzmaDecoder->SetDecoderProperties2((const Byte *)props, kPropsSize))
94*f6dc9357SAndroid Build Coastguard Worker   }
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker   {
97*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICompressSetInStream> setInStream;
98*f6dc9357SAndroid Build Coastguard Worker     _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
99*f6dc9357SAndroid Build Coastguard Worker     if (!setInStream)
100*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
101*f6dc9357SAndroid Build Coastguard Worker     RINOK(setInStream->SetInStream(inStream))
102*f6dc9357SAndroid Build Coastguard Worker   }
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker   {
105*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
106*f6dc9357SAndroid Build Coastguard Worker     _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
107*f6dc9357SAndroid Build Coastguard Worker     if (!setOutStreamSize)
108*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
109*f6dc9357SAndroid Build Coastguard Worker     RINOK(setOutStreamSize->SetOutStreamSize(NULL))
110*f6dc9357SAndroid Build Coastguard Worker   }
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker   if (useFilter)
113*f6dc9357SAndroid Build Coastguard Worker   {
114*f6dc9357SAndroid Build Coastguard Worker     RINOK(_filter->SetOutStreamSize(NULL))
115*f6dc9357SAndroid Build Coastguard Worker   }
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker 
SetToPos(UInt64 pos,ICompressProgressInfo * progress)124*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress)
125*f6dc9357SAndroid Build Coastguard Worker {
126*f6dc9357SAndroid Build Coastguard Worker   if (StreamPos > pos)
127*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
128*f6dc9357SAndroid Build Coastguard Worker   const UInt64 inSizeStart = GetInputProcessedSize();
129*f6dc9357SAndroid Build Coastguard Worker   UInt64 offset = 0;
130*f6dc9357SAndroid Build Coastguard Worker   while (StreamPos < pos)
131*f6dc9357SAndroid Build Coastguard Worker   {
132*f6dc9357SAndroid Build Coastguard Worker     size_t size = (size_t)MyMin(pos - StreamPos, (UInt64)Buffer.Size());
133*f6dc9357SAndroid Build Coastguard Worker     RINOK(Read(Buffer, &size))
134*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
135*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
136*f6dc9357SAndroid Build Coastguard Worker     StreamPos += size;
137*f6dc9357SAndroid Build Coastguard Worker     offset += size;
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker     const UInt64 inSize = GetInputProcessedSize() - inSizeStart;
140*f6dc9357SAndroid Build Coastguard Worker     RINOK(progress->SetRatioInfo(&inSize, &offset))
141*f6dc9357SAndroid Build Coastguard Worker   }
142*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
143*f6dc9357SAndroid Build Coastguard Worker }
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker 
Decode(CByteBuffer * outBuf,bool unpackSizeDefined,UInt32 unpackSize,ISequentialOutStream * realOutStream,ICompressProgressInfo * progress,UInt32 & packSizeRes,UInt32 & unpackSizeRes)146*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,
147*f6dc9357SAndroid Build Coastguard Worker     ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
148*f6dc9357SAndroid Build Coastguard Worker     UInt32 &packSizeRes, UInt32 &unpackSizeRes)
149*f6dc9357SAndroid Build Coastguard Worker {
150*f6dc9357SAndroid Build Coastguard Worker   CLimitedSequentialInStream *limitedStreamSpec = NULL;
151*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> limitedStream;
152*f6dc9357SAndroid Build Coastguard Worker   packSizeRes = 0;
153*f6dc9357SAndroid Build Coastguard Worker   unpackSizeRes = 0;
154*f6dc9357SAndroid Build Coastguard Worker 
155*f6dc9357SAndroid Build Coastguard Worker   if (Solid)
156*f6dc9357SAndroid Build Coastguard Worker   {
157*f6dc9357SAndroid Build Coastguard Worker     Byte temp[4];
158*f6dc9357SAndroid Build Coastguard Worker     size_t processedSize = 4;
159*f6dc9357SAndroid Build Coastguard Worker     RINOK(Read(temp, &processedSize))
160*f6dc9357SAndroid Build Coastguard Worker     StreamPos += processedSize;
161*f6dc9357SAndroid Build Coastguard Worker     if (processedSize != 4)
162*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
163*f6dc9357SAndroid Build Coastguard Worker     UInt32 size = Get32(temp);
164*f6dc9357SAndroid Build Coastguard Worker     if (unpackSizeDefined && size != unpackSize)
165*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
166*f6dc9357SAndroid Build Coastguard Worker     unpackSize = size;
167*f6dc9357SAndroid Build Coastguard Worker     unpackSizeDefined = true;
168*f6dc9357SAndroid Build Coastguard Worker   }
169*f6dc9357SAndroid Build Coastguard Worker   else
170*f6dc9357SAndroid Build Coastguard Worker   {
171*f6dc9357SAndroid Build Coastguard Worker     Byte temp[4];
172*f6dc9357SAndroid Build Coastguard Worker     {
173*f6dc9357SAndroid Build Coastguard Worker       size_t processedSize = 4;
174*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadStream(InputStream, temp, &processedSize))
175*f6dc9357SAndroid Build Coastguard Worker       StreamPos += processedSize;
176*f6dc9357SAndroid Build Coastguard Worker       if (processedSize != 4)
177*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
178*f6dc9357SAndroid Build Coastguard Worker     }
179*f6dc9357SAndroid Build Coastguard Worker     UInt32 size = Get32(temp);
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker     if ((size & kMask_IsCompressed) == 0)
182*f6dc9357SAndroid Build Coastguard Worker     {
183*f6dc9357SAndroid Build Coastguard Worker       if (unpackSizeDefined && size != unpackSize)
184*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
185*f6dc9357SAndroid Build Coastguard Worker       packSizeRes = size;
186*f6dc9357SAndroid Build Coastguard Worker       if (outBuf)
187*f6dc9357SAndroid Build Coastguard Worker         outBuf->Alloc(size);
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker       UInt64 offset = 0;
190*f6dc9357SAndroid Build Coastguard Worker 
191*f6dc9357SAndroid Build Coastguard Worker       while (size > 0)
192*f6dc9357SAndroid Build Coastguard Worker       {
193*f6dc9357SAndroid Build Coastguard Worker         UInt32 curSize = (UInt32)MyMin((size_t)size, Buffer.Size());
194*f6dc9357SAndroid Build Coastguard Worker         UInt32 processedSize;
195*f6dc9357SAndroid Build Coastguard Worker         RINOK(InputStream->Read(Buffer, curSize, &processedSize))
196*f6dc9357SAndroid Build Coastguard Worker         if (processedSize == 0)
197*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
198*f6dc9357SAndroid Build Coastguard Worker         if (outBuf)
199*f6dc9357SAndroid Build Coastguard Worker           memcpy((Byte *)*outBuf + (size_t)offset, Buffer, processedSize);
200*f6dc9357SAndroid Build Coastguard Worker         offset += processedSize;
201*f6dc9357SAndroid Build Coastguard Worker         size -= processedSize;
202*f6dc9357SAndroid Build Coastguard Worker         StreamPos += processedSize;
203*f6dc9357SAndroid Build Coastguard Worker         unpackSizeRes += processedSize;
204*f6dc9357SAndroid Build Coastguard Worker         if (realOutStream)
205*f6dc9357SAndroid Build Coastguard Worker           RINOK(WriteStream(realOutStream, Buffer, processedSize))
206*f6dc9357SAndroid Build Coastguard Worker         RINOK(progress->SetRatioInfo(&offset, &offset))
207*f6dc9357SAndroid Build Coastguard Worker       }
208*f6dc9357SAndroid Build Coastguard Worker 
209*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
210*f6dc9357SAndroid Build Coastguard Worker     }
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker     size &= ~kMask_IsCompressed;
213*f6dc9357SAndroid Build Coastguard Worker     packSizeRes = size;
214*f6dc9357SAndroid Build Coastguard Worker     limitedStreamSpec = new CLimitedSequentialInStream;
215*f6dc9357SAndroid Build Coastguard Worker     limitedStream = limitedStreamSpec;
216*f6dc9357SAndroid Build Coastguard Worker     limitedStreamSpec->SetStream(InputStream);
217*f6dc9357SAndroid Build Coastguard Worker     limitedStreamSpec->Init(size);
218*f6dc9357SAndroid Build Coastguard Worker     {
219*f6dc9357SAndroid Build Coastguard Worker       bool useFilter;
220*f6dc9357SAndroid Build Coastguard Worker       RINOK(Init(limitedStream, useFilter))
221*f6dc9357SAndroid Build Coastguard Worker     }
222*f6dc9357SAndroid Build Coastguard Worker   }
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker   if (outBuf)
225*f6dc9357SAndroid Build Coastguard Worker   {
226*f6dc9357SAndroid Build Coastguard Worker     if (unpackSizeDefined)
227*f6dc9357SAndroid Build Coastguard Worker       outBuf->Alloc(unpackSize);
228*f6dc9357SAndroid Build Coastguard Worker   }
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker   const UInt64 inSizeStart = GetInputProcessedSize();
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker   // we don't allow files larger than 4 GB;
233*f6dc9357SAndroid Build Coastguard Worker   if (!unpackSizeDefined)
234*f6dc9357SAndroid Build Coastguard Worker     unpackSize = 0xFFFFFFFF;
235*f6dc9357SAndroid Build Coastguard Worker   UInt32 offset = 0;
236*f6dc9357SAndroid Build Coastguard Worker 
237*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = S_OK;
238*f6dc9357SAndroid Build Coastguard Worker 
239*f6dc9357SAndroid Build Coastguard Worker   for (;;)
240*f6dc9357SAndroid Build Coastguard Worker   {
241*f6dc9357SAndroid Build Coastguard Worker     size_t rem = unpackSize - offset;
242*f6dc9357SAndroid Build Coastguard Worker     if (rem == 0)
243*f6dc9357SAndroid Build Coastguard Worker       break;
244*f6dc9357SAndroid Build Coastguard Worker     size_t size = Buffer.Size();
245*f6dc9357SAndroid Build Coastguard Worker     if (size > rem)
246*f6dc9357SAndroid Build Coastguard Worker       size = rem;
247*f6dc9357SAndroid Build Coastguard Worker     RINOK(Read(Buffer, &size))
248*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
249*f6dc9357SAndroid Build Coastguard Worker     {
250*f6dc9357SAndroid Build Coastguard Worker       if (unpackSizeDefined)
251*f6dc9357SAndroid Build Coastguard Worker         res = S_FALSE;
252*f6dc9357SAndroid Build Coastguard Worker       break;
253*f6dc9357SAndroid Build Coastguard Worker     }
254*f6dc9357SAndroid Build Coastguard Worker 
255*f6dc9357SAndroid Build Coastguard Worker     if (outBuf)
256*f6dc9357SAndroid Build Coastguard Worker     {
257*f6dc9357SAndroid Build Coastguard Worker       size_t nextSize = offset + size;
258*f6dc9357SAndroid Build Coastguard Worker       if (outBuf->Size() < nextSize)
259*f6dc9357SAndroid Build Coastguard Worker       {
260*f6dc9357SAndroid Build Coastguard Worker         {
261*f6dc9357SAndroid Build Coastguard Worker           const size_t nextSize2 = outBuf->Size() * 2;
262*f6dc9357SAndroid Build Coastguard Worker           if (nextSize < nextSize2)
263*f6dc9357SAndroid Build Coastguard Worker             nextSize = nextSize2;
264*f6dc9357SAndroid Build Coastguard Worker         }
265*f6dc9357SAndroid Build Coastguard Worker         outBuf->ChangeSize_KeepData(nextSize, offset);
266*f6dc9357SAndroid Build Coastguard Worker       }
267*f6dc9357SAndroid Build Coastguard Worker       memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size);
268*f6dc9357SAndroid Build Coastguard Worker     }
269*f6dc9357SAndroid Build Coastguard Worker 
270*f6dc9357SAndroid Build Coastguard Worker     StreamPos += size;
271*f6dc9357SAndroid Build Coastguard Worker     offset += (UInt32)size;
272*f6dc9357SAndroid Build Coastguard Worker 
273*f6dc9357SAndroid Build Coastguard Worker     const UInt64 inSize = GetInputProcessedSize() - inSizeStart;
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker     if (Solid)
276*f6dc9357SAndroid Build Coastguard Worker       packSizeRes = (UInt32)inSize;
277*f6dc9357SAndroid Build Coastguard Worker     unpackSizeRes += (UInt32)size;
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker     UInt64 outSize = offset;
280*f6dc9357SAndroid Build Coastguard Worker     RINOK(progress->SetRatioInfo(&inSize, &outSize))
281*f6dc9357SAndroid Build Coastguard Worker     if (realOutStream)
282*f6dc9357SAndroid Build Coastguard Worker     {
283*f6dc9357SAndroid Build Coastguard Worker       res = WriteStream(realOutStream, Buffer, size);
284*f6dc9357SAndroid Build Coastguard Worker       if (res != S_OK)
285*f6dc9357SAndroid Build Coastguard Worker         break;
286*f6dc9357SAndroid Build Coastguard Worker     }
287*f6dc9357SAndroid Build Coastguard Worker   }
288*f6dc9357SAndroid Build Coastguard Worker 
289*f6dc9357SAndroid Build Coastguard Worker   if (outBuf && offset != outBuf->Size())
290*f6dc9357SAndroid Build Coastguard Worker     outBuf->ChangeSize_KeepData(offset, offset);
291*f6dc9357SAndroid Build Coastguard Worker 
292*f6dc9357SAndroid Build Coastguard Worker   return res;
293*f6dc9357SAndroid Build Coastguard Worker }
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker }}
296