xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // 7zHandlerOut.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/ComTry.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringToInt.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ParseProperties.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "7zHandler.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "7zOut.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "7zUpdate.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
21*f6dc9357SAndroid Build Coastguard Worker namespace N7z {
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_decoderCompatibilityVersion = 2301;
24*f6dc9357SAndroid Build Coastguard Worker // 7-Zip version 2301 supports ARM64 filter
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #define k_LZMA_Name "LZMA"
27*f6dc9357SAndroid Build Coastguard Worker #define kDefaultMethodName "LZMA2"
28*f6dc9357SAndroid Build Coastguard Worker #define k_Copy_Name "Copy"
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker #define k_MatchFinder_ForHeaders "BT2"
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_NumFastBytes_ForHeaders = 273;
33*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Level_ForHeaders = 5;
34*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Dictionary_ForHeaders =
35*f6dc9357SAndroid Build Coastguard Worker   #ifdef UNDER_CE
36*f6dc9357SAndroid Build Coastguard Worker   1 << 18;
37*f6dc9357SAndroid Build Coastguard Worker   #else
38*f6dc9357SAndroid Build Coastguard Worker   1 << 20;
39*f6dc9357SAndroid Build Coastguard Worker   #endif
40*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetFileTimeType (UInt32 * type))41*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker   *type = NFileTimeType::kWindows;
44*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
45*f6dc9357SAndroid Build Coastguard Worker }
46*f6dc9357SAndroid Build Coastguard Worker 
PropsMethod_To_FullMethod(CMethodFull & dest,const COneMethodInfo & m)47*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker   bool isFilter;
50*f6dc9357SAndroid Build Coastguard Worker   dest.CodecIndex = FindMethod_Index(
51*f6dc9357SAndroid Build Coastguard Worker       EXTERNAL_CODECS_VARS
52*f6dc9357SAndroid Build Coastguard Worker       m.MethodName, true,
53*f6dc9357SAndroid Build Coastguard Worker       dest.Id, dest.NumStreams, isFilter);
54*f6dc9357SAndroid Build Coastguard Worker   if (dest.CodecIndex < 0)
55*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
56*f6dc9357SAndroid Build Coastguard Worker   (CProps &)dest = (CProps &)m;
57*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
58*f6dc9357SAndroid Build Coastguard Worker }
59*f6dc9357SAndroid Build Coastguard Worker 
SetHeaderMethod(CCompressionMethodMode & headerMethod)60*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker   if (!_compressHeaders)
63*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
64*f6dc9357SAndroid Build Coastguard Worker   COneMethodInfo m;
65*f6dc9357SAndroid Build Coastguard Worker   m.MethodName = k_LZMA_Name;
66*f6dc9357SAndroid Build Coastguard Worker   m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
67*f6dc9357SAndroid Build Coastguard Worker   m.AddProp_Level(k_Level_ForHeaders);
68*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
69*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
70*f6dc9357SAndroid Build Coastguard Worker   m.AddProp_NumThreads(1);
71*f6dc9357SAndroid Build Coastguard Worker 
72*f6dc9357SAndroid Build Coastguard Worker   CMethodFull &methodFull = headerMethod.Methods.AddNew();
73*f6dc9357SAndroid Build Coastguard Worker   return PropsMethod_To_FullMethod(methodFull, m);
74*f6dc9357SAndroid Build Coastguard Worker }
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker 
SetMainMethod(CCompressionMethodMode & methodMode)77*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode)
78*f6dc9357SAndroid Build Coastguard Worker {
79*f6dc9357SAndroid Build Coastguard Worker   methodMode.Bonds = _bonds;
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker   // we create local copy of _methods. So we can modify it.
82*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<COneMethodInfo> methods = _methods;
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker   {
85*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, methods)
86*f6dc9357SAndroid Build Coastguard Worker     {
87*f6dc9357SAndroid Build Coastguard Worker       AString &methodName = methods[i].MethodName;
88*f6dc9357SAndroid Build Coastguard Worker       if (methodName.IsEmpty())
89*f6dc9357SAndroid Build Coastguard Worker         methodName = kDefaultMethodName;
90*f6dc9357SAndroid Build Coastguard Worker     }
91*f6dc9357SAndroid Build Coastguard Worker     if (methods.IsEmpty())
92*f6dc9357SAndroid Build Coastguard Worker     {
93*f6dc9357SAndroid Build Coastguard Worker       COneMethodInfo &m = methods.AddNew();
94*f6dc9357SAndroid Build Coastguard Worker       m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
95*f6dc9357SAndroid Build Coastguard Worker       methodMode.DefaultMethod_was_Inserted = true;
96*f6dc9357SAndroid Build Coastguard Worker     }
97*f6dc9357SAndroid Build Coastguard Worker   }
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker   if (!_filterMethod.MethodName.IsEmpty())
100*f6dc9357SAndroid Build Coastguard Worker   {
101*f6dc9357SAndroid Build Coastguard Worker     // if (methodMode.Bonds.IsEmpty())
102*f6dc9357SAndroid Build Coastguard Worker     {
103*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (k, methodMode.Bonds)
104*f6dc9357SAndroid Build Coastguard Worker       {
105*f6dc9357SAndroid Build Coastguard Worker         CBond2 &bond = methodMode.Bonds[k];
106*f6dc9357SAndroid Build Coastguard Worker         bond.InCoder++;
107*f6dc9357SAndroid Build Coastguard Worker         bond.OutCoder++;
108*f6dc9357SAndroid Build Coastguard Worker       }
109*f6dc9357SAndroid Build Coastguard Worker       methods.Insert(0, _filterMethod);
110*f6dc9357SAndroid Build Coastguard Worker       methodMode.Filter_was_Inserted = true;
111*f6dc9357SAndroid Build Coastguard Worker     }
112*f6dc9357SAndroid Build Coastguard Worker   }
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker   const UInt64 kSolidBytes_Min = (1 << 24);
115*f6dc9357SAndroid Build Coastguard Worker   const UInt64 kSolidBytes_Max = ((UInt64)1 << 32);
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker   bool needSolid = false;
118*f6dc9357SAndroid Build Coastguard Worker 
119*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, methods)
120*f6dc9357SAndroid Build Coastguard Worker   {
121*f6dc9357SAndroid Build Coastguard Worker     COneMethodInfo &oneMethodInfo = methods[i];
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker     SetGlobalLevelTo(oneMethodInfo);
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
126*f6dc9357SAndroid Build Coastguard Worker     const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0);
127*f6dc9357SAndroid Build Coastguard Worker     if (!numThreads_WasSpecifiedInMethod)
128*f6dc9357SAndroid Build Coastguard Worker     {
129*f6dc9357SAndroid Build Coastguard Worker       // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already
130*f6dc9357SAndroid Build Coastguard Worker       CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads);
131*f6dc9357SAndroid Build Coastguard Worker     }
132*f6dc9357SAndroid Build Coastguard Worker     #endif
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker     CMethodFull &methodFull = methodMode.Methods.AddNew();
135*f6dc9357SAndroid Build Coastguard Worker     RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo))
136*f6dc9357SAndroid Build Coastguard Worker 
137*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
138*f6dc9357SAndroid Build Coastguard Worker     methodFull.Set_NumThreads = true;
139*f6dc9357SAndroid Build Coastguard Worker     methodFull.NumThreads = methodMode.NumThreads;
140*f6dc9357SAndroid Build Coastguard Worker     #endif
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker     if (methodFull.Id != k_Copy)
143*f6dc9357SAndroid Build Coastguard Worker       needSolid = true;
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker     UInt64 dicSize;
146*f6dc9357SAndroid Build Coastguard Worker     switch (methodFull.Id)
147*f6dc9357SAndroid Build Coastguard Worker     {
148*f6dc9357SAndroid Build Coastguard Worker       case k_LZMA:
149*f6dc9357SAndroid Build Coastguard Worker       case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
150*f6dc9357SAndroid Build Coastguard Worker       case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
151*f6dc9357SAndroid Build Coastguard Worker       case k_Deflate: dicSize = (UInt32)1 << 15; break;
152*f6dc9357SAndroid Build Coastguard Worker       case k_Deflate64: dicSize = (UInt32)1 << 16; break;
153*f6dc9357SAndroid Build Coastguard Worker       case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
154*f6dc9357SAndroid Build Coastguard Worker       // case k_ZSTD: dicSize = 1 << 23; break;
155*f6dc9357SAndroid Build Coastguard Worker       default: continue;
156*f6dc9357SAndroid Build Coastguard Worker     }
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker     UInt64 numSolidBytes;
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker     /*
161*f6dc9357SAndroid Build Coastguard Worker     if (methodFull.Id == k_ZSTD)
162*f6dc9357SAndroid Build Coastguard Worker     {
163*f6dc9357SAndroid Build Coastguard Worker       // continue;
164*f6dc9357SAndroid Build Coastguard Worker       NCompress::NZstd::CEncoderProps encoderProps;
165*f6dc9357SAndroid Build Coastguard Worker       RINOK(oneMethodInfo.Set_PropsTo_zstd(encoderProps));
166*f6dc9357SAndroid Build Coastguard Worker       CZstdEncProps &zstdProps = encoderProps.EncProps;
167*f6dc9357SAndroid Build Coastguard Worker       ZstdEncProps_NormalizeFull(&zstdProps);
168*f6dc9357SAndroid Build Coastguard Worker       UInt64 cs = (UInt64)(zstdProps.jobSize);
169*f6dc9357SAndroid Build Coastguard Worker       UInt32 winSize = (UInt32)(1 << zstdProps.windowLog);
170*f6dc9357SAndroid Build Coastguard Worker       if (cs < winSize)
171*f6dc9357SAndroid Build Coastguard Worker         cs = winSize;
172*f6dc9357SAndroid Build Coastguard Worker       numSolidBytes = cs << 6;
173*f6dc9357SAndroid Build Coastguard Worker       const UInt64 kSolidBytes_Zstd_Max = ((UInt64)1 << 34);
174*f6dc9357SAndroid Build Coastguard Worker       if (numSolidBytes > kSolidBytes_Zstd_Max)
175*f6dc9357SAndroid Build Coastguard Worker         numSolidBytes = kSolidBytes_Zstd_Max;
176*f6dc9357SAndroid Build Coastguard Worker 
177*f6dc9357SAndroid Build Coastguard Worker       methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker       #ifndef Z7_ST
180*f6dc9357SAndroid Build Coastguard Worker       if (!numThreads_WasSpecifiedInMethod
181*f6dc9357SAndroid Build Coastguard Worker           && !methodMode.NumThreads_WasForced
182*f6dc9357SAndroid Build Coastguard Worker           && methodMode.MemoryUsageLimit_WasSet
183*f6dc9357SAndroid Build Coastguard Worker           )
184*f6dc9357SAndroid Build Coastguard Worker       {
185*f6dc9357SAndroid Build Coastguard Worker         const UInt32 numThreads_Original = methodMode.NumThreads;
186*f6dc9357SAndroid Build Coastguard Worker         const UInt32 numThreads_New = ZstdEncProps_GetNumThreads_for_MemUsageLimit(
187*f6dc9357SAndroid Build Coastguard Worker             &zstdProps,
188*f6dc9357SAndroid Build Coastguard Worker             methodMode.MemoryUsageLimit,
189*f6dc9357SAndroid Build Coastguard Worker             numThreads_Original);
190*f6dc9357SAndroid Build Coastguard Worker         if (numThreads_Original != numThreads_New)
191*f6dc9357SAndroid Build Coastguard Worker         {
192*f6dc9357SAndroid Build Coastguard Worker           CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New);
193*f6dc9357SAndroid Build Coastguard Worker         }
194*f6dc9357SAndroid Build Coastguard Worker       }
195*f6dc9357SAndroid Build Coastguard Worker       #endif
196*f6dc9357SAndroid Build Coastguard Worker     }
197*f6dc9357SAndroid Build Coastguard Worker     else
198*f6dc9357SAndroid Build Coastguard Worker     */
199*f6dc9357SAndroid Build Coastguard Worker     if (methodFull.Id == k_LZMA2)
200*f6dc9357SAndroid Build Coastguard Worker     {
201*f6dc9357SAndroid Build Coastguard Worker       // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code
202*f6dc9357SAndroid Build Coastguard Worker       /* lzma2 code use dictionary up to fake 4 GiB to calculate ChunkSize.
203*f6dc9357SAndroid Build Coastguard Worker          So we do same */
204*f6dc9357SAndroid Build Coastguard Worker       UInt64 cs = (UInt64)dicSize << 2;
205*f6dc9357SAndroid Build Coastguard Worker       const UInt32 kMinSize = (UInt32)1 << 20;
206*f6dc9357SAndroid Build Coastguard Worker       const UInt32 kMaxSize = (UInt32)1 << 28;
207*f6dc9357SAndroid Build Coastguard Worker       if (cs < kMinSize) cs = kMinSize;
208*f6dc9357SAndroid Build Coastguard Worker       if (cs > kMaxSize) cs = kMaxSize;
209*f6dc9357SAndroid Build Coastguard Worker       if (cs < dicSize) cs = dicSize;
210*f6dc9357SAndroid Build Coastguard Worker       cs += (kMinSize - 1);
211*f6dc9357SAndroid Build Coastguard Worker       cs &= ~(UInt64)(kMinSize - 1);
212*f6dc9357SAndroid Build Coastguard Worker       // we want to use at least 64 chunks (threads) per one solid block.
213*f6dc9357SAndroid Build Coastguard Worker 
214*f6dc9357SAndroid Build Coastguard Worker       // here we don't use chunkSize property
215*f6dc9357SAndroid Build Coastguard Worker       numSolidBytes = cs << 6;
216*f6dc9357SAndroid Build Coastguard Worker 
217*f6dc9357SAndroid Build Coastguard Worker       // here we get real chunkSize
218*f6dc9357SAndroid Build Coastguard Worker       cs = oneMethodInfo.Get_Xz_BlockSize();
219*f6dc9357SAndroid Build Coastguard Worker       if (dicSize > cs)
220*f6dc9357SAndroid Build Coastguard Worker         dicSize = cs;
221*f6dc9357SAndroid Build Coastguard Worker 
222*f6dc9357SAndroid Build Coastguard Worker       const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34);
223*f6dc9357SAndroid Build Coastguard Worker       if (numSolidBytes > kSolidBytes_Lzma2_Max)
224*f6dc9357SAndroid Build Coastguard Worker         numSolidBytes = kSolidBytes_Lzma2_Max;
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker       methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker       #ifndef Z7_ST
229*f6dc9357SAndroid Build Coastguard Worker       if (!numThreads_WasSpecifiedInMethod
230*f6dc9357SAndroid Build Coastguard Worker           && !methodMode.NumThreads_WasForced
231*f6dc9357SAndroid Build Coastguard Worker           && methodMode.MemoryUsageLimit_WasSet
232*f6dc9357SAndroid Build Coastguard Worker           )
233*f6dc9357SAndroid Build Coastguard Worker       {
234*f6dc9357SAndroid Build Coastguard Worker         const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads();
235*f6dc9357SAndroid Build Coastguard Worker         const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads;
236*f6dc9357SAndroid Build Coastguard Worker 
237*f6dc9357SAndroid Build Coastguard Worker         if (numBlockThreads_Original > 1)
238*f6dc9357SAndroid Build Coastguard Worker         {
239*f6dc9357SAndroid Build Coastguard Worker           /*
240*f6dc9357SAndroid Build Coastguard Worker             const UInt32 kNumThreads_Max = 1024;
241*f6dc9357SAndroid Build Coastguard Worker             if (numBlockThreads > kNumMaxThreads)
242*f6dc9357SAndroid Build Coastguard Worker             numBlockThreads = kNumMaxThreads;
243*f6dc9357SAndroid Build Coastguard Worker           */
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker           UInt32 numBlockThreads = numBlockThreads_Original;
246*f6dc9357SAndroid Build Coastguard Worker           const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); // solid
247*f6dc9357SAndroid Build Coastguard Worker 
248*f6dc9357SAndroid Build Coastguard Worker           for (; numBlockThreads > 1; numBlockThreads--)
249*f6dc9357SAndroid Build Coastguard Worker           {
250*f6dc9357SAndroid Build Coastguard Worker             UInt64 size = numBlockThreads * (lzmaMemUsage + cs);
251*f6dc9357SAndroid Build Coastguard Worker             UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
252*f6dc9357SAndroid Build Coastguard Worker             if (cs < ((UInt32)1 << 26)) numPackChunks++;
253*f6dc9357SAndroid Build Coastguard Worker             if (cs < ((UInt32)1 << 24)) numPackChunks++;
254*f6dc9357SAndroid Build Coastguard Worker             if (cs < ((UInt32)1 << 22)) numPackChunks++;
255*f6dc9357SAndroid Build Coastguard Worker             size += numPackChunks * cs;
256*f6dc9357SAndroid Build Coastguard Worker             // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20));
257*f6dc9357SAndroid Build Coastguard Worker             if (size <= methodMode.MemoryUsageLimit)
258*f6dc9357SAndroid Build Coastguard Worker               break;
259*f6dc9357SAndroid Build Coastguard Worker           }
260*f6dc9357SAndroid Build Coastguard Worker 
261*f6dc9357SAndroid Build Coastguard Worker           if (numBlockThreads == 0)
262*f6dc9357SAndroid Build Coastguard Worker             numBlockThreads = 1;
263*f6dc9357SAndroid Build Coastguard Worker           if (numBlockThreads != numBlockThreads_Original)
264*f6dc9357SAndroid Build Coastguard Worker           {
265*f6dc9357SAndroid Build Coastguard Worker             const UInt32 numThreads_New = numBlockThreads * lzmaThreads;
266*f6dc9357SAndroid Build Coastguard Worker             CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New);
267*f6dc9357SAndroid Build Coastguard Worker           }
268*f6dc9357SAndroid Build Coastguard Worker         }
269*f6dc9357SAndroid Build Coastguard Worker       }
270*f6dc9357SAndroid Build Coastguard Worker       #endif
271*f6dc9357SAndroid Build Coastguard Worker     }
272*f6dc9357SAndroid Build Coastguard Worker     else
273*f6dc9357SAndroid Build Coastguard Worker     {
274*f6dc9357SAndroid Build Coastguard Worker       numSolidBytes = (UInt64)dicSize << 7;
275*f6dc9357SAndroid Build Coastguard Worker       if (numSolidBytes > kSolidBytes_Max)
276*f6dc9357SAndroid Build Coastguard Worker         numSolidBytes = kSolidBytes_Max;
277*f6dc9357SAndroid Build Coastguard Worker     }
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker     if (_numSolidBytesDefined)
280*f6dc9357SAndroid Build Coastguard Worker       continue;
281*f6dc9357SAndroid Build Coastguard Worker 
282*f6dc9357SAndroid Build Coastguard Worker     if (numSolidBytes < kSolidBytes_Min)
283*f6dc9357SAndroid Build Coastguard Worker       numSolidBytes = kSolidBytes_Min;
284*f6dc9357SAndroid Build Coastguard Worker     _numSolidBytes = numSolidBytes;
285*f6dc9357SAndroid Build Coastguard Worker     _numSolidBytesDefined = true;
286*f6dc9357SAndroid Build Coastguard Worker   }
287*f6dc9357SAndroid Build Coastguard Worker 
288*f6dc9357SAndroid Build Coastguard Worker   if (!_numSolidBytesDefined)
289*f6dc9357SAndroid Build Coastguard Worker   {
290*f6dc9357SAndroid Build Coastguard Worker     if (needSolid)
291*f6dc9357SAndroid Build Coastguard Worker       _numSolidBytes = kSolidBytes_Max;
292*f6dc9357SAndroid Build Coastguard Worker     else
293*f6dc9357SAndroid Build Coastguard Worker       _numSolidBytes = 0;
294*f6dc9357SAndroid Build Coastguard Worker   }
295*f6dc9357SAndroid Build Coastguard Worker   _numSolidBytesDefined = true;
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker 
298*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
299*f6dc9357SAndroid Build Coastguard Worker }
300*f6dc9357SAndroid Build Coastguard Worker 
301*f6dc9357SAndroid Build Coastguard Worker 
302*f6dc9357SAndroid Build Coastguard Worker 
GetTime(IArchiveUpdateCallback * updateCallback,unsigned index,PROPID propID,UInt64 & ft,bool & ftDefined)303*f6dc9357SAndroid Build Coastguard Worker static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined)
304*f6dc9357SAndroid Build Coastguard Worker {
305*f6dc9357SAndroid Build Coastguard Worker   // ft = 0;
306*f6dc9357SAndroid Build Coastguard Worker   // ftDefined = false;
307*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
308*f6dc9357SAndroid Build Coastguard Worker   RINOK(updateCallback->GetProperty(index, propID, &prop))
309*f6dc9357SAndroid Build Coastguard Worker   if (prop.vt == VT_FILETIME)
310*f6dc9357SAndroid Build Coastguard Worker   {
311*f6dc9357SAndroid Build Coastguard Worker     ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);
312*f6dc9357SAndroid Build Coastguard Worker     ftDefined = true;
313*f6dc9357SAndroid Build Coastguard Worker   }
314*f6dc9357SAndroid Build Coastguard Worker   else if (prop.vt != VT_EMPTY)
315*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
316*f6dc9357SAndroid Build Coastguard Worker   else
317*f6dc9357SAndroid Build Coastguard Worker   {
318*f6dc9357SAndroid Build Coastguard Worker     ft = 0;
319*f6dc9357SAndroid Build Coastguard Worker     ftDefined = false;
320*f6dc9357SAndroid Build Coastguard Worker   }
321*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
322*f6dc9357SAndroid Build Coastguard Worker }
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker /*
325*f6dc9357SAndroid Build Coastguard Worker 
326*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
327*f6dc9357SAndroid Build Coastguard Worker static const wchar_t kDirDelimiter1 = L'\\';
328*f6dc9357SAndroid Build Coastguard Worker #endif
329*f6dc9357SAndroid Build Coastguard Worker static const wchar_t kDirDelimiter2 = L'/';
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker static inline bool IsCharDirLimiter(wchar_t c)
332*f6dc9357SAndroid Build Coastguard Worker {
333*f6dc9357SAndroid Build Coastguard Worker   return (
334*f6dc9357SAndroid Build Coastguard Worker     #ifdef _WIN32
335*f6dc9357SAndroid Build Coastguard Worker     c == kDirDelimiter1 ||
336*f6dc9357SAndroid Build Coastguard Worker     #endif
337*f6dc9357SAndroid Build Coastguard Worker     c == kDirDelimiter2);
338*f6dc9357SAndroid Build Coastguard Worker }
339*f6dc9357SAndroid Build Coastguard Worker 
340*f6dc9357SAndroid Build Coastguard Worker static int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)
341*f6dc9357SAndroid Build Coastguard Worker {
342*f6dc9357SAndroid Build Coastguard Worker   CTreeFolder &tf = treeFolders[cur];
343*f6dc9357SAndroid Build Coastguard Worker   tf.SortIndex = curSortIndex++;
344*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < tf.SubFolders.Size(); i++)
345*f6dc9357SAndroid Build Coastguard Worker     curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);
346*f6dc9357SAndroid Build Coastguard Worker   tf.SortIndexEnd = curSortIndex;
347*f6dc9357SAndroid Build Coastguard Worker   return curSortIndex;
348*f6dc9357SAndroid Build Coastguard Worker }
349*f6dc9357SAndroid Build Coastguard Worker 
350*f6dc9357SAndroid Build Coastguard Worker static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)
351*f6dc9357SAndroid Build Coastguard Worker {
352*f6dc9357SAndroid Build Coastguard Worker   const CIntVector &subFolders = treeFolders[cur].SubFolders;
353*f6dc9357SAndroid Build Coastguard Worker   int left = 0, right = subFolders.Size();
354*f6dc9357SAndroid Build Coastguard Worker   insertPos = -1;
355*f6dc9357SAndroid Build Coastguard Worker   for (;;)
356*f6dc9357SAndroid Build Coastguard Worker   {
357*f6dc9357SAndroid Build Coastguard Worker     if (left == right)
358*f6dc9357SAndroid Build Coastguard Worker     {
359*f6dc9357SAndroid Build Coastguard Worker       insertPos = left;
360*f6dc9357SAndroid Build Coastguard Worker       return -1;
361*f6dc9357SAndroid Build Coastguard Worker     }
362*f6dc9357SAndroid Build Coastguard Worker     int mid = (left + right) / 2;
363*f6dc9357SAndroid Build Coastguard Worker     int midFolder = subFolders[mid];
364*f6dc9357SAndroid Build Coastguard Worker     int compare = CompareFileNames(name, treeFolders[midFolder].Name);
365*f6dc9357SAndroid Build Coastguard Worker     if (compare == 0)
366*f6dc9357SAndroid Build Coastguard Worker       return midFolder;
367*f6dc9357SAndroid Build Coastguard Worker     if (compare < 0)
368*f6dc9357SAndroid Build Coastguard Worker       right = mid;
369*f6dc9357SAndroid Build Coastguard Worker     else
370*f6dc9357SAndroid Build Coastguard Worker       left = mid + 1;
371*f6dc9357SAndroid Build Coastguard Worker   }
372*f6dc9357SAndroid Build Coastguard Worker }
373*f6dc9357SAndroid Build Coastguard Worker 
374*f6dc9357SAndroid Build Coastguard Worker static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)
375*f6dc9357SAndroid Build Coastguard Worker {
376*f6dc9357SAndroid Build Coastguard Worker   int insertPos;
377*f6dc9357SAndroid Build Coastguard Worker   int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);
378*f6dc9357SAndroid Build Coastguard Worker   if (folderIndex < 0)
379*f6dc9357SAndroid Build Coastguard Worker   {
380*f6dc9357SAndroid Build Coastguard Worker     folderIndex = treeFolders.Size();
381*f6dc9357SAndroid Build Coastguard Worker     CTreeFolder &newFolder = treeFolders.AddNew();
382*f6dc9357SAndroid Build Coastguard Worker     newFolder.Parent = cur;
383*f6dc9357SAndroid Build Coastguard Worker     newFolder.Name = name;
384*f6dc9357SAndroid Build Coastguard Worker     treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);
385*f6dc9357SAndroid Build Coastguard Worker   }
386*f6dc9357SAndroid Build Coastguard Worker   // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;
387*f6dc9357SAndroid Build Coastguard Worker   return folderIndex;
388*f6dc9357SAndroid Build Coastguard Worker }
389*f6dc9357SAndroid Build Coastguard Worker */
390*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::UpdateItems (ISequentialOutStream * outStream,UInt32 numItems,IArchiveUpdateCallback * updateCallback))391*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
392*f6dc9357SAndroid Build Coastguard Worker     IArchiveUpdateCallback *updateCallback))
393*f6dc9357SAndroid Build Coastguard Worker {
394*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker   const CDbEx *db = NULL;
397*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_7Z_VOL
398*f6dc9357SAndroid Build Coastguard Worker   if (_volumes.Size() > 1)
399*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
400*f6dc9357SAndroid Build Coastguard Worker   const CVolume *volume = 0;
401*f6dc9357SAndroid Build Coastguard Worker   if (_volumes.Size() == 1)
402*f6dc9357SAndroid Build Coastguard Worker   {
403*f6dc9357SAndroid Build Coastguard Worker     volume = &_volumes.Front();
404*f6dc9357SAndroid Build Coastguard Worker     db = &volume->Database;
405*f6dc9357SAndroid Build Coastguard Worker   }
406*f6dc9357SAndroid Build Coastguard Worker   #else
407*f6dc9357SAndroid Build Coastguard Worker   if (_inStream)
408*f6dc9357SAndroid Build Coastguard Worker     db = &_db;
409*f6dc9357SAndroid Build Coastguard Worker   #endif
410*f6dc9357SAndroid Build Coastguard Worker 
411*f6dc9357SAndroid Build Coastguard Worker   if (db && !db->CanUpdate())
412*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
413*f6dc9357SAndroid Build Coastguard Worker 
414*f6dc9357SAndroid Build Coastguard Worker   /*
415*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
416*f6dc9357SAndroid Build Coastguard Worker       IArchiveGetRawProps,
417*f6dc9357SAndroid Build Coastguard Worker       getRawProps, updateCallback)
418*f6dc9357SAndroid Build Coastguard Worker 
419*f6dc9357SAndroid Build Coastguard Worker   CUniqBlocks secureBlocks;
420*f6dc9357SAndroid Build Coastguard Worker   secureBlocks.AddUniq(NULL, 0);
421*f6dc9357SAndroid Build Coastguard Worker 
422*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CTreeFolder> treeFolders;
423*f6dc9357SAndroid Build Coastguard Worker   {
424*f6dc9357SAndroid Build Coastguard Worker     CTreeFolder folder;
425*f6dc9357SAndroid Build Coastguard Worker     folder.Parent = -1;
426*f6dc9357SAndroid Build Coastguard Worker     treeFolders.Add(folder);
427*f6dc9357SAndroid Build Coastguard Worker   }
428*f6dc9357SAndroid Build Coastguard Worker   */
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CUpdateItem> updateItems;
431*f6dc9357SAndroid Build Coastguard Worker 
432*f6dc9357SAndroid Build Coastguard Worker   bool need_CTime = (TimeOptions.Write_CTime.Def && TimeOptions.Write_CTime.Val);
433*f6dc9357SAndroid Build Coastguard Worker   bool need_ATime = (TimeOptions.Write_ATime.Def && TimeOptions.Write_ATime.Val);
434*f6dc9357SAndroid Build Coastguard Worker   bool need_MTime = (TimeOptions.Write_MTime.Def ? TimeOptions.Write_MTime.Val : true);
435*f6dc9357SAndroid Build Coastguard Worker   bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true);
436*f6dc9357SAndroid Build Coastguard Worker 
437*f6dc9357SAndroid Build Coastguard Worker   if (db && !db->Files.IsEmpty())
438*f6dc9357SAndroid Build Coastguard Worker   {
439*f6dc9357SAndroid Build Coastguard Worker     if (!TimeOptions.Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
440*f6dc9357SAndroid Build Coastguard Worker     if (!TimeOptions.Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
441*f6dc9357SAndroid Build Coastguard Worker     if (!TimeOptions.Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
442*f6dc9357SAndroid Build Coastguard Worker     if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty();
443*f6dc9357SAndroid Build Coastguard Worker   }
444*f6dc9357SAndroid Build Coastguard Worker 
445*f6dc9357SAndroid Build Coastguard Worker   // UString s;
446*f6dc9357SAndroid Build Coastguard Worker   UString name;
447*f6dc9357SAndroid Build Coastguard Worker 
448*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numItems; i++)
449*f6dc9357SAndroid Build Coastguard Worker   {
450*f6dc9357SAndroid Build Coastguard Worker     Int32 newData, newProps;
451*f6dc9357SAndroid Build Coastguard Worker     UInt32 indexInArchive;
452*f6dc9357SAndroid Build Coastguard Worker     if (!updateCallback)
453*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
454*f6dc9357SAndroid Build Coastguard Worker     RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive))
455*f6dc9357SAndroid Build Coastguard Worker     CUpdateItem ui;
456*f6dc9357SAndroid Build Coastguard Worker     ui.NewProps = IntToBool(newProps);
457*f6dc9357SAndroid Build Coastguard Worker     ui.NewData = IntToBool(newData);
458*f6dc9357SAndroid Build Coastguard Worker     ui.IndexInArchive = (int)indexInArchive;
459*f6dc9357SAndroid Build Coastguard Worker     ui.IndexInClient = i;
460*f6dc9357SAndroid Build Coastguard Worker     ui.IsAnti = false;
461*f6dc9357SAndroid Build Coastguard Worker     ui.Size = 0;
462*f6dc9357SAndroid Build Coastguard Worker 
463*f6dc9357SAndroid Build Coastguard Worker     name.Empty();
464*f6dc9357SAndroid Build Coastguard Worker     // bool isAltStream = false;
465*f6dc9357SAndroid Build Coastguard Worker     if (ui.IndexInArchive != -1)
466*f6dc9357SAndroid Build Coastguard Worker     {
467*f6dc9357SAndroid Build Coastguard Worker       if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size())
468*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
469*f6dc9357SAndroid Build Coastguard Worker       const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive];
470*f6dc9357SAndroid Build Coastguard Worker       if (!ui.NewProps)
471*f6dc9357SAndroid Build Coastguard Worker       {
472*f6dc9357SAndroid Build Coastguard Worker         _db.GetPath((unsigned)ui.IndexInArchive, name);
473*f6dc9357SAndroid Build Coastguard Worker       }
474*f6dc9357SAndroid Build Coastguard Worker       ui.IsDir = fi.IsDir;
475*f6dc9357SAndroid Build Coastguard Worker       ui.Size = fi.Size;
476*f6dc9357SAndroid Build Coastguard Worker       // isAltStream = fi.IsAltStream;
477*f6dc9357SAndroid Build Coastguard Worker       ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive);
478*f6dc9357SAndroid Build Coastguard Worker 
479*f6dc9357SAndroid Build Coastguard Worker       if (!ui.NewProps)
480*f6dc9357SAndroid Build Coastguard Worker       {
481*f6dc9357SAndroid Build Coastguard Worker         ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime);
482*f6dc9357SAndroid Build Coastguard Worker         ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime);
483*f6dc9357SAndroid Build Coastguard Worker         ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime);
484*f6dc9357SAndroid Build Coastguard Worker       }
485*f6dc9357SAndroid Build Coastguard Worker     }
486*f6dc9357SAndroid Build Coastguard Worker 
487*f6dc9357SAndroid Build Coastguard Worker     if (ui.NewProps)
488*f6dc9357SAndroid Build Coastguard Worker     {
489*f6dc9357SAndroid Build Coastguard Worker       bool folderStatusIsDefined;
490*f6dc9357SAndroid Build Coastguard Worker       if (need_Attrib)
491*f6dc9357SAndroid Build Coastguard Worker       {
492*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
493*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop))
494*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_EMPTY)
495*f6dc9357SAndroid Build Coastguard Worker           ui.AttribDefined = false;
496*f6dc9357SAndroid Build Coastguard Worker         else if (prop.vt != VT_UI4)
497*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
498*f6dc9357SAndroid Build Coastguard Worker         else
499*f6dc9357SAndroid Build Coastguard Worker         {
500*f6dc9357SAndroid Build Coastguard Worker           ui.Attrib = prop.ulVal;
501*f6dc9357SAndroid Build Coastguard Worker           ui.AttribDefined = true;
502*f6dc9357SAndroid Build Coastguard Worker         }
503*f6dc9357SAndroid Build Coastguard Worker       }
504*f6dc9357SAndroid Build Coastguard Worker 
505*f6dc9357SAndroid Build Coastguard Worker       // we need MTime to sort files.
506*f6dc9357SAndroid Build Coastguard Worker       if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined))
507*f6dc9357SAndroid Build Coastguard Worker       if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined))
508*f6dc9357SAndroid Build Coastguard Worker       if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined))
509*f6dc9357SAndroid Build Coastguard Worker 
510*f6dc9357SAndroid Build Coastguard Worker       /*
511*f6dc9357SAndroid Build Coastguard Worker       if (getRawProps)
512*f6dc9357SAndroid Build Coastguard Worker       {
513*f6dc9357SAndroid Build Coastguard Worker         const void *data;
514*f6dc9357SAndroid Build Coastguard Worker         UInt32 dataSize;
515*f6dc9357SAndroid Build Coastguard Worker         UInt32 propType;
516*f6dc9357SAndroid Build Coastguard Worker 
517*f6dc9357SAndroid Build Coastguard Worker         getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);
518*f6dc9357SAndroid Build Coastguard Worker         if (dataSize != 0 && propType != NPropDataType::kRaw)
519*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
520*f6dc9357SAndroid Build Coastguard Worker         ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);
521*f6dc9357SAndroid Build Coastguard Worker       }
522*f6dc9357SAndroid Build Coastguard Worker       */
523*f6dc9357SAndroid Build Coastguard Worker 
524*f6dc9357SAndroid Build Coastguard Worker       {
525*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
526*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->GetProperty(i, kpidPath, &prop))
527*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_EMPTY)
528*f6dc9357SAndroid Build Coastguard Worker         {
529*f6dc9357SAndroid Build Coastguard Worker         }
530*f6dc9357SAndroid Build Coastguard Worker         else if (prop.vt != VT_BSTR)
531*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
532*f6dc9357SAndroid Build Coastguard Worker         else
533*f6dc9357SAndroid Build Coastguard Worker         {
534*f6dc9357SAndroid Build Coastguard Worker           name = prop.bstrVal;
535*f6dc9357SAndroid Build Coastguard Worker           NItemName::ReplaceSlashes_OsToUnix(name);
536*f6dc9357SAndroid Build Coastguard Worker         }
537*f6dc9357SAndroid Build Coastguard Worker       }
538*f6dc9357SAndroid Build Coastguard Worker       {
539*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
540*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop))
541*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_EMPTY)
542*f6dc9357SAndroid Build Coastguard Worker           folderStatusIsDefined = false;
543*f6dc9357SAndroid Build Coastguard Worker         else if (prop.vt != VT_BOOL)
544*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
545*f6dc9357SAndroid Build Coastguard Worker         else
546*f6dc9357SAndroid Build Coastguard Worker         {
547*f6dc9357SAndroid Build Coastguard Worker           ui.IsDir = (prop.boolVal != VARIANT_FALSE);
548*f6dc9357SAndroid Build Coastguard Worker           folderStatusIsDefined = true;
549*f6dc9357SAndroid Build Coastguard Worker         }
550*f6dc9357SAndroid Build Coastguard Worker       }
551*f6dc9357SAndroid Build Coastguard Worker 
552*f6dc9357SAndroid Build Coastguard Worker       {
553*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
554*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop))
555*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_EMPTY)
556*f6dc9357SAndroid Build Coastguard Worker           ui.IsAnti = false;
557*f6dc9357SAndroid Build Coastguard Worker         else if (prop.vt != VT_BOOL)
558*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
559*f6dc9357SAndroid Build Coastguard Worker         else
560*f6dc9357SAndroid Build Coastguard Worker           ui.IsAnti = (prop.boolVal != VARIANT_FALSE);
561*f6dc9357SAndroid Build Coastguard Worker       }
562*f6dc9357SAndroid Build Coastguard Worker 
563*f6dc9357SAndroid Build Coastguard Worker       /*
564*f6dc9357SAndroid Build Coastguard Worker       {
565*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
566*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));
567*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_EMPTY)
568*f6dc9357SAndroid Build Coastguard Worker           isAltStream = false;
569*f6dc9357SAndroid Build Coastguard Worker         else if (prop.vt != VT_BOOL)
570*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
571*f6dc9357SAndroid Build Coastguard Worker         else
572*f6dc9357SAndroid Build Coastguard Worker           isAltStream = (prop.boolVal != VARIANT_FALSE);
573*f6dc9357SAndroid Build Coastguard Worker       }
574*f6dc9357SAndroid Build Coastguard Worker       */
575*f6dc9357SAndroid Build Coastguard Worker 
576*f6dc9357SAndroid Build Coastguard Worker       if (ui.IsAnti)
577*f6dc9357SAndroid Build Coastguard Worker       {
578*f6dc9357SAndroid Build Coastguard Worker         ui.AttribDefined = false;
579*f6dc9357SAndroid Build Coastguard Worker 
580*f6dc9357SAndroid Build Coastguard Worker         ui.CTimeDefined = false;
581*f6dc9357SAndroid Build Coastguard Worker         ui.ATimeDefined = false;
582*f6dc9357SAndroid Build Coastguard Worker         ui.MTimeDefined = false;
583*f6dc9357SAndroid Build Coastguard Worker 
584*f6dc9357SAndroid Build Coastguard Worker         ui.Size = 0;
585*f6dc9357SAndroid Build Coastguard Worker       }
586*f6dc9357SAndroid Build Coastguard Worker 
587*f6dc9357SAndroid Build Coastguard Worker       if (!folderStatusIsDefined && ui.AttribDefined)
588*f6dc9357SAndroid Build Coastguard Worker         ui.SetDirStatusFromAttrib();
589*f6dc9357SAndroid Build Coastguard Worker     }
590*f6dc9357SAndroid Build Coastguard Worker     else
591*f6dc9357SAndroid Build Coastguard Worker     {
592*f6dc9357SAndroid Build Coastguard Worker       /*
593*f6dc9357SAndroid Build Coastguard Worker       if (_db.SecureIDs.IsEmpty())
594*f6dc9357SAndroid Build Coastguard Worker         ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);
595*f6dc9357SAndroid Build Coastguard Worker       else
596*f6dc9357SAndroid Build Coastguard Worker       {
597*f6dc9357SAndroid Build Coastguard Worker         int id = _db.SecureIDs[ui.IndexInArchive];
598*f6dc9357SAndroid Build Coastguard Worker         size_t offs = _db.SecureOffsets[id];
599*f6dc9357SAndroid Build Coastguard Worker         size_t size = _db.SecureOffsets[id + 1] - offs;
600*f6dc9357SAndroid Build Coastguard Worker         ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);
601*f6dc9357SAndroid Build Coastguard Worker       }
602*f6dc9357SAndroid Build Coastguard Worker       */
603*f6dc9357SAndroid Build Coastguard Worker     }
604*f6dc9357SAndroid Build Coastguard Worker 
605*f6dc9357SAndroid Build Coastguard Worker     /*
606*f6dc9357SAndroid Build Coastguard Worker     {
607*f6dc9357SAndroid Build Coastguard Worker       int folderIndex = 0;
608*f6dc9357SAndroid Build Coastguard Worker       if (_useParents)
609*f6dc9357SAndroid Build Coastguard Worker       {
610*f6dc9357SAndroid Build Coastguard Worker         int j;
611*f6dc9357SAndroid Build Coastguard Worker         s.Empty();
612*f6dc9357SAndroid Build Coastguard Worker         for (j = 0; j < name.Len(); j++)
613*f6dc9357SAndroid Build Coastguard Worker         {
614*f6dc9357SAndroid Build Coastguard Worker           wchar_t c = name[j];
615*f6dc9357SAndroid Build Coastguard Worker           if (IsCharDirLimiter(c))
616*f6dc9357SAndroid Build Coastguard Worker           {
617*f6dc9357SAndroid Build Coastguard Worker             folderIndex = AddFolder(treeFolders, folderIndex, s);
618*f6dc9357SAndroid Build Coastguard Worker             s.Empty();
619*f6dc9357SAndroid Build Coastguard Worker             continue;
620*f6dc9357SAndroid Build Coastguard Worker           }
621*f6dc9357SAndroid Build Coastguard Worker           s += c;
622*f6dc9357SAndroid Build Coastguard Worker         }
623*f6dc9357SAndroid Build Coastguard Worker         if (isAltStream)
624*f6dc9357SAndroid Build Coastguard Worker         {
625*f6dc9357SAndroid Build Coastguard Worker           int colonPos = s.Find(':');
626*f6dc9357SAndroid Build Coastguard Worker           if (colonPos < 0)
627*f6dc9357SAndroid Build Coastguard Worker           {
628*f6dc9357SAndroid Build Coastguard Worker             // isAltStream = false;
629*f6dc9357SAndroid Build Coastguard Worker             return E_INVALIDARG;
630*f6dc9357SAndroid Build Coastguard Worker           }
631*f6dc9357SAndroid Build Coastguard Worker           UString mainName = s.Left(colonPos);
632*f6dc9357SAndroid Build Coastguard Worker           int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);
633*f6dc9357SAndroid Build Coastguard Worker           if (treeFolders[newFolderIndex].UpdateItemIndex < 0)
634*f6dc9357SAndroid Build Coastguard Worker           {
635*f6dc9357SAndroid Build Coastguard Worker             for (int j = updateItems.Size() - 1; j >= 0; j--)
636*f6dc9357SAndroid Build Coastguard Worker             {
637*f6dc9357SAndroid Build Coastguard Worker               CUpdateItem &ui2 = updateItems[j];
638*f6dc9357SAndroid Build Coastguard Worker               if (ui2.ParentFolderIndex == folderIndex
639*f6dc9357SAndroid Build Coastguard Worker                   && ui2.Name == mainName)
640*f6dc9357SAndroid Build Coastguard Worker               {
641*f6dc9357SAndroid Build Coastguard Worker                 ui2.TreeFolderIndex = newFolderIndex;
642*f6dc9357SAndroid Build Coastguard Worker                 treeFolders[newFolderIndex].UpdateItemIndex = j;
643*f6dc9357SAndroid Build Coastguard Worker               }
644*f6dc9357SAndroid Build Coastguard Worker             }
645*f6dc9357SAndroid Build Coastguard Worker           }
646*f6dc9357SAndroid Build Coastguard Worker           folderIndex = newFolderIndex;
647*f6dc9357SAndroid Build Coastguard Worker           s.Delete(0, colonPos + 1);
648*f6dc9357SAndroid Build Coastguard Worker         }
649*f6dc9357SAndroid Build Coastguard Worker         ui.Name = s;
650*f6dc9357SAndroid Build Coastguard Worker       }
651*f6dc9357SAndroid Build Coastguard Worker       else
652*f6dc9357SAndroid Build Coastguard Worker         ui.Name = name;
653*f6dc9357SAndroid Build Coastguard Worker       ui.IsAltStream = isAltStream;
654*f6dc9357SAndroid Build Coastguard Worker       ui.ParentFolderIndex = folderIndex;
655*f6dc9357SAndroid Build Coastguard Worker       ui.TreeFolderIndex = -1;
656*f6dc9357SAndroid Build Coastguard Worker       if (ui.IsDir && !s.IsEmpty())
657*f6dc9357SAndroid Build Coastguard Worker       {
658*f6dc9357SAndroid Build Coastguard Worker         ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);
659*f6dc9357SAndroid Build Coastguard Worker         treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();
660*f6dc9357SAndroid Build Coastguard Worker       }
661*f6dc9357SAndroid Build Coastguard Worker     }
662*f6dc9357SAndroid Build Coastguard Worker     */
663*f6dc9357SAndroid Build Coastguard Worker     ui.Name = name;
664*f6dc9357SAndroid Build Coastguard Worker 
665*f6dc9357SAndroid Build Coastguard Worker     if (ui.NewData)
666*f6dc9357SAndroid Build Coastguard Worker     {
667*f6dc9357SAndroid Build Coastguard Worker       ui.Size = 0;
668*f6dc9357SAndroid Build Coastguard Worker       if (!ui.IsDir)
669*f6dc9357SAndroid Build Coastguard Worker       {
670*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
671*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->GetProperty(i, kpidSize, &prop))
672*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt != VT_UI8)
673*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
674*f6dc9357SAndroid Build Coastguard Worker         ui.Size = (UInt64)prop.uhVal.QuadPart;
675*f6dc9357SAndroid Build Coastguard Worker         if (ui.Size != 0 && ui.IsAnti)
676*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
677*f6dc9357SAndroid Build Coastguard Worker       }
678*f6dc9357SAndroid Build Coastguard Worker     }
679*f6dc9357SAndroid Build Coastguard Worker 
680*f6dc9357SAndroid Build Coastguard Worker     updateItems.Add(ui);
681*f6dc9357SAndroid Build Coastguard Worker   }
682*f6dc9357SAndroid Build Coastguard Worker 
683*f6dc9357SAndroid Build Coastguard Worker   /*
684*f6dc9357SAndroid Build Coastguard Worker   FillSortIndex(treeFolders, 0, 0);
685*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < (UInt32)updateItems.Size(); i++)
686*f6dc9357SAndroid Build Coastguard Worker   {
687*f6dc9357SAndroid Build Coastguard Worker     CUpdateItem &ui = updateItems[i];
688*f6dc9357SAndroid Build Coastguard Worker     ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;
689*f6dc9357SAndroid Build Coastguard Worker     ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;
690*f6dc9357SAndroid Build Coastguard Worker   }
691*f6dc9357SAndroid Build Coastguard Worker   */
692*f6dc9357SAndroid Build Coastguard Worker 
693*f6dc9357SAndroid Build Coastguard Worker   CCompressionMethodMode methodMode, headerMethod;
694*f6dc9357SAndroid Build Coastguard Worker 
695*f6dc9357SAndroid Build Coastguard Worker   methodMode.MemoryUsageLimit = _memUsage_Compress;
696*f6dc9357SAndroid Build Coastguard Worker   methodMode.MemoryUsageLimit_WasSet = _memUsage_WasSet;
697*f6dc9357SAndroid Build Coastguard Worker 
698*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
699*f6dc9357SAndroid Build Coastguard Worker   {
700*f6dc9357SAndroid Build Coastguard Worker     UInt32 numThreads = _numThreads;
701*f6dc9357SAndroid Build Coastguard Worker     const UInt32 kNumThreads_Max = 1024;
702*f6dc9357SAndroid Build Coastguard Worker     if (numThreads > kNumThreads_Max)
703*f6dc9357SAndroid Build Coastguard Worker       numThreads = kNumThreads_Max;
704*f6dc9357SAndroid Build Coastguard Worker     methodMode.NumThreads = numThreads;
705*f6dc9357SAndroid Build Coastguard Worker     methodMode.NumThreads_WasForced = _numThreads_WasForced;
706*f6dc9357SAndroid Build Coastguard Worker     methodMode.MultiThreadMixer = _useMultiThreadMixer;
707*f6dc9357SAndroid Build Coastguard Worker     // headerMethod.NumThreads = 1;
708*f6dc9357SAndroid Build Coastguard Worker     headerMethod.MultiThreadMixer = _useMultiThreadMixer;
709*f6dc9357SAndroid Build Coastguard Worker   }
710*f6dc9357SAndroid Build Coastguard Worker   #endif
711*f6dc9357SAndroid Build Coastguard Worker 
712*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = SetMainMethod(methodMode);
713*f6dc9357SAndroid Build Coastguard Worker   RINOK(res)
714*f6dc9357SAndroid Build Coastguard Worker 
715*f6dc9357SAndroid Build Coastguard Worker   RINOK(SetHeaderMethod(headerMethod))
716*f6dc9357SAndroid Build Coastguard Worker 
717*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
718*f6dc9357SAndroid Build Coastguard Worker     ICryptoGetTextPassword2,
719*f6dc9357SAndroid Build Coastguard Worker     getPassword2, updateCallback)
720*f6dc9357SAndroid Build Coastguard Worker 
721*f6dc9357SAndroid Build Coastguard Worker   methodMode.PasswordIsDefined = false;
722*f6dc9357SAndroid Build Coastguard Worker   methodMode.Password.Wipe_and_Empty();
723*f6dc9357SAndroid Build Coastguard Worker   if (getPassword2)
724*f6dc9357SAndroid Build Coastguard Worker   {
725*f6dc9357SAndroid Build Coastguard Worker     CMyComBSTR_Wipe password;
726*f6dc9357SAndroid Build Coastguard Worker     Int32 passwordIsDefined;
727*f6dc9357SAndroid Build Coastguard Worker     RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password))
728*f6dc9357SAndroid Build Coastguard Worker     methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
729*f6dc9357SAndroid Build Coastguard Worker     if (methodMode.PasswordIsDefined && password)
730*f6dc9357SAndroid Build Coastguard Worker       methodMode.Password = password;
731*f6dc9357SAndroid Build Coastguard Worker   }
732*f6dc9357SAndroid Build Coastguard Worker 
733*f6dc9357SAndroid Build Coastguard Worker   bool compressMainHeader = _compressHeaders;  // check it
734*f6dc9357SAndroid Build Coastguard Worker 
735*f6dc9357SAndroid Build Coastguard Worker   bool encryptHeaders = false;
736*f6dc9357SAndroid Build Coastguard Worker 
737*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_NO_CRYPTO
738*f6dc9357SAndroid Build Coastguard Worker   if (!methodMode.PasswordIsDefined && _passwordIsDefined)
739*f6dc9357SAndroid Build Coastguard Worker   {
740*f6dc9357SAndroid Build Coastguard Worker     // if header is compressed, we use that password for updated archive
741*f6dc9357SAndroid Build Coastguard Worker     methodMode.PasswordIsDefined = true;
742*f6dc9357SAndroid Build Coastguard Worker     methodMode.Password = _password;
743*f6dc9357SAndroid Build Coastguard Worker   }
744*f6dc9357SAndroid Build Coastguard Worker   #endif
745*f6dc9357SAndroid Build Coastguard Worker 
746*f6dc9357SAndroid Build Coastguard Worker   if (methodMode.PasswordIsDefined)
747*f6dc9357SAndroid Build Coastguard Worker   {
748*f6dc9357SAndroid Build Coastguard Worker     if (_encryptHeadersSpecified)
749*f6dc9357SAndroid Build Coastguard Worker       encryptHeaders = _encryptHeaders;
750*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_NO_CRYPTO
751*f6dc9357SAndroid Build Coastguard Worker     else
752*f6dc9357SAndroid Build Coastguard Worker       encryptHeaders = _passwordIsDefined;
753*f6dc9357SAndroid Build Coastguard Worker     #endif
754*f6dc9357SAndroid Build Coastguard Worker     compressMainHeader = true;
755*f6dc9357SAndroid Build Coastguard Worker     if (encryptHeaders)
756*f6dc9357SAndroid Build Coastguard Worker     {
757*f6dc9357SAndroid Build Coastguard Worker       headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;
758*f6dc9357SAndroid Build Coastguard Worker       headerMethod.Password = methodMode.Password;
759*f6dc9357SAndroid Build Coastguard Worker     }
760*f6dc9357SAndroid Build Coastguard Worker   }
761*f6dc9357SAndroid Build Coastguard Worker 
762*f6dc9357SAndroid Build Coastguard Worker   if (numItems < 2)
763*f6dc9357SAndroid Build Coastguard Worker     compressMainHeader = false;
764*f6dc9357SAndroid Build Coastguard Worker 
765*f6dc9357SAndroid Build Coastguard Worker   const int level = GetLevel();
766*f6dc9357SAndroid Build Coastguard Worker 
767*f6dc9357SAndroid Build Coastguard Worker   CUpdateOptions options;
768*f6dc9357SAndroid Build Coastguard Worker   options.Need_CTime = need_CTime;
769*f6dc9357SAndroid Build Coastguard Worker   options.Need_ATime = need_ATime;
770*f6dc9357SAndroid Build Coastguard Worker   options.Need_MTime = need_MTime;
771*f6dc9357SAndroid Build Coastguard Worker   options.Need_Attrib = need_Attrib;
772*f6dc9357SAndroid Build Coastguard Worker   // options.Need_Crc = (_crcSize != 0); // for debug
773*f6dc9357SAndroid Build Coastguard Worker 
774*f6dc9357SAndroid Build Coastguard Worker   options.Method = &methodMode;
775*f6dc9357SAndroid Build Coastguard Worker   options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
776*f6dc9357SAndroid Build Coastguard Worker   options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
777*f6dc9357SAndroid Build Coastguard Worker   options.MaxFilter = (level >= 8);
778*f6dc9357SAndroid Build Coastguard Worker   options.AnalysisLevel = GetAnalysisLevel();
779*f6dc9357SAndroid Build Coastguard Worker 
780*f6dc9357SAndroid Build Coastguard Worker   options.SetFilterSupporting_ver_enabled_disabled(
781*f6dc9357SAndroid Build Coastguard Worker       _decoderCompatibilityVersion,
782*f6dc9357SAndroid Build Coastguard Worker       _enabledFilters,
783*f6dc9357SAndroid Build Coastguard Worker       _disabledFilters);
784*f6dc9357SAndroid Build Coastguard Worker 
785*f6dc9357SAndroid Build Coastguard Worker   options.HeaderOptions.CompressMainHeader = compressMainHeader;
786*f6dc9357SAndroid Build Coastguard Worker   /*
787*f6dc9357SAndroid Build Coastguard Worker   options.HeaderOptions.WriteCTime = Write_CTime;
788*f6dc9357SAndroid Build Coastguard Worker   options.HeaderOptions.WriteATime = Write_ATime;
789*f6dc9357SAndroid Build Coastguard Worker   options.HeaderOptions.WriteMTime = Write_MTime;
790*f6dc9357SAndroid Build Coastguard Worker   options.HeaderOptions.WriteAttrib = Write_Attrib;
791*f6dc9357SAndroid Build Coastguard Worker   */
792*f6dc9357SAndroid Build Coastguard Worker 
793*f6dc9357SAndroid Build Coastguard Worker   options.NumSolidFiles = _numSolidFiles;
794*f6dc9357SAndroid Build Coastguard Worker   options.NumSolidBytes = _numSolidBytes;
795*f6dc9357SAndroid Build Coastguard Worker   options.SolidExtension = _solidExtension;
796*f6dc9357SAndroid Build Coastguard Worker   options.UseTypeSorting = _useTypeSorting;
797*f6dc9357SAndroid Build Coastguard Worker 
798*f6dc9357SAndroid Build Coastguard Worker   options.RemoveSfxBlock = _removeSfxBlock;
799*f6dc9357SAndroid Build Coastguard Worker   // options.VolumeMode = _volumeMode;
800*f6dc9357SAndroid Build Coastguard Worker 
801*f6dc9357SAndroid Build Coastguard Worker   options.MultiThreadMixer = _useMultiThreadMixer;
802*f6dc9357SAndroid Build Coastguard Worker 
803*f6dc9357SAndroid Build Coastguard Worker   /*
804*f6dc9357SAndroid Build Coastguard Worker   if (secureBlocks.Sorted.Size() > 1)
805*f6dc9357SAndroid Build Coastguard Worker   {
806*f6dc9357SAndroid Build Coastguard Worker     secureBlocks.GetReverseMap();
807*f6dc9357SAndroid Build Coastguard Worker     for (int i = 0; i < updateItems.Size(); i++)
808*f6dc9357SAndroid Build Coastguard Worker     {
809*f6dc9357SAndroid Build Coastguard Worker       int &secureIndex = updateItems[i].SecureIndex;
810*f6dc9357SAndroid Build Coastguard Worker       secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];
811*f6dc9357SAndroid Build Coastguard Worker     }
812*f6dc9357SAndroid Build Coastguard Worker   }
813*f6dc9357SAndroid Build Coastguard Worker   */
814*f6dc9357SAndroid Build Coastguard Worker 
815*f6dc9357SAndroid Build Coastguard Worker   return Update(
816*f6dc9357SAndroid Build Coastguard Worker       EXTERNAL_CODECS_VARS
817*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_7Z_VOL
818*f6dc9357SAndroid Build Coastguard Worker       volume ? volume->Stream: 0,
819*f6dc9357SAndroid Build Coastguard Worker       volume ? db : 0,
820*f6dc9357SAndroid Build Coastguard Worker       #else
821*f6dc9357SAndroid Build Coastguard Worker       _inStream,
822*f6dc9357SAndroid Build Coastguard Worker       db,
823*f6dc9357SAndroid Build Coastguard Worker       #endif
824*f6dc9357SAndroid Build Coastguard Worker       updateItems,
825*f6dc9357SAndroid Build Coastguard Worker       // treeFolders,
826*f6dc9357SAndroid Build Coastguard Worker       // secureBlocks,
827*f6dc9357SAndroid Build Coastguard Worker       outStream, updateCallback, options);
828*f6dc9357SAndroid Build Coastguard Worker 
829*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
830*f6dc9357SAndroid Build Coastguard Worker }
831*f6dc9357SAndroid Build Coastguard Worker 
ParseBond(UString & srcString,UInt32 & coder,UInt32 & stream)832*f6dc9357SAndroid Build Coastguard Worker static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
833*f6dc9357SAndroid Build Coastguard Worker {
834*f6dc9357SAndroid Build Coastguard Worker   stream = 0;
835*f6dc9357SAndroid Build Coastguard Worker   {
836*f6dc9357SAndroid Build Coastguard Worker     const unsigned index = ParseStringToUInt32(srcString, coder);
837*f6dc9357SAndroid Build Coastguard Worker     if (index == 0)
838*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
839*f6dc9357SAndroid Build Coastguard Worker     srcString.DeleteFrontal(index);
840*f6dc9357SAndroid Build Coastguard Worker   }
841*f6dc9357SAndroid Build Coastguard Worker   if (srcString[0] == 's')
842*f6dc9357SAndroid Build Coastguard Worker   {
843*f6dc9357SAndroid Build Coastguard Worker     srcString.Delete(0);
844*f6dc9357SAndroid Build Coastguard Worker     const unsigned index = ParseStringToUInt32(srcString, stream);
845*f6dc9357SAndroid Build Coastguard Worker     if (index == 0)
846*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
847*f6dc9357SAndroid Build Coastguard Worker     srcString.DeleteFrontal(index);
848*f6dc9357SAndroid Build Coastguard Worker   }
849*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
850*f6dc9357SAndroid Build Coastguard Worker }
851*f6dc9357SAndroid Build Coastguard Worker 
InitProps7z()852*f6dc9357SAndroid Build Coastguard Worker void COutHandler::InitProps7z()
853*f6dc9357SAndroid Build Coastguard Worker {
854*f6dc9357SAndroid Build Coastguard Worker   _removeSfxBlock = false;
855*f6dc9357SAndroid Build Coastguard Worker   _compressHeaders = true;
856*f6dc9357SAndroid Build Coastguard Worker   _encryptHeadersSpecified = false;
857*f6dc9357SAndroid Build Coastguard Worker   _encryptHeaders = false;
858*f6dc9357SAndroid Build Coastguard Worker   // _useParents = false;
859*f6dc9357SAndroid Build Coastguard Worker 
860*f6dc9357SAndroid Build Coastguard Worker   TimeOptions.Init();
861*f6dc9357SAndroid Build Coastguard Worker   Write_Attrib.Init();
862*f6dc9357SAndroid Build Coastguard Worker 
863*f6dc9357SAndroid Build Coastguard Worker   _useMultiThreadMixer = true;
864*f6dc9357SAndroid Build Coastguard Worker 
865*f6dc9357SAndroid Build Coastguard Worker   // _volumeMode = false;
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker   InitSolid();
868*f6dc9357SAndroid Build Coastguard Worker   _useTypeSorting = false;
869*f6dc9357SAndroid Build Coastguard Worker 
870*f6dc9357SAndroid Build Coastguard Worker   _decoderCompatibilityVersion = k_decoderCompatibilityVersion;
871*f6dc9357SAndroid Build Coastguard Worker   _enabledFilters.Clear();
872*f6dc9357SAndroid Build Coastguard Worker   _disabledFilters.Clear();
873*f6dc9357SAndroid Build Coastguard Worker }
874*f6dc9357SAndroid Build Coastguard Worker 
InitProps()875*f6dc9357SAndroid Build Coastguard Worker void COutHandler::InitProps()
876*f6dc9357SAndroid Build Coastguard Worker {
877*f6dc9357SAndroid Build Coastguard Worker   CMultiMethodProps::Init();
878*f6dc9357SAndroid Build Coastguard Worker   InitProps7z();
879*f6dc9357SAndroid Build Coastguard Worker }
880*f6dc9357SAndroid Build Coastguard Worker 
881*f6dc9357SAndroid Build Coastguard Worker 
882*f6dc9357SAndroid Build Coastguard Worker 
SetSolidFromString(const UString & s)883*f6dc9357SAndroid Build Coastguard Worker HRESULT COutHandler::SetSolidFromString(const UString &s)
884*f6dc9357SAndroid Build Coastguard Worker {
885*f6dc9357SAndroid Build Coastguard Worker   UString s2 = s;
886*f6dc9357SAndroid Build Coastguard Worker   s2.MakeLower_Ascii();
887*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < s2.Len();)
888*f6dc9357SAndroid Build Coastguard Worker   {
889*f6dc9357SAndroid Build Coastguard Worker     const wchar_t *start = ((const wchar_t *)s2) + i;
890*f6dc9357SAndroid Build Coastguard Worker     const wchar_t *end;
891*f6dc9357SAndroid Build Coastguard Worker     UInt64 v = ConvertStringToUInt64(start, &end);
892*f6dc9357SAndroid Build Coastguard Worker     if (start == end)
893*f6dc9357SAndroid Build Coastguard Worker     {
894*f6dc9357SAndroid Build Coastguard Worker       if (s2[i++] != 'e')
895*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
896*f6dc9357SAndroid Build Coastguard Worker       _solidExtension = true;
897*f6dc9357SAndroid Build Coastguard Worker       continue;
898*f6dc9357SAndroid Build Coastguard Worker     }
899*f6dc9357SAndroid Build Coastguard Worker     i += (unsigned)(end - start);
900*f6dc9357SAndroid Build Coastguard Worker     if (i == s2.Len())
901*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
902*f6dc9357SAndroid Build Coastguard Worker     const wchar_t c = s2[i++];
903*f6dc9357SAndroid Build Coastguard Worker     if (c == 'f')
904*f6dc9357SAndroid Build Coastguard Worker     {
905*f6dc9357SAndroid Build Coastguard Worker       if (v < 1)
906*f6dc9357SAndroid Build Coastguard Worker         v = 1;
907*f6dc9357SAndroid Build Coastguard Worker       _numSolidFiles = v;
908*f6dc9357SAndroid Build Coastguard Worker     }
909*f6dc9357SAndroid Build Coastguard Worker     else
910*f6dc9357SAndroid Build Coastguard Worker     {
911*f6dc9357SAndroid Build Coastguard Worker       unsigned numBits;
912*f6dc9357SAndroid Build Coastguard Worker       switch (c)
913*f6dc9357SAndroid Build Coastguard Worker       {
914*f6dc9357SAndroid Build Coastguard Worker         case 'b': numBits =  0; break;
915*f6dc9357SAndroid Build Coastguard Worker         case 'k': numBits = 10; break;
916*f6dc9357SAndroid Build Coastguard Worker         case 'm': numBits = 20; break;
917*f6dc9357SAndroid Build Coastguard Worker         case 'g': numBits = 30; break;
918*f6dc9357SAndroid Build Coastguard Worker         case 't': numBits = 40; break;
919*f6dc9357SAndroid Build Coastguard Worker         default: return E_INVALIDARG;
920*f6dc9357SAndroid Build Coastguard Worker       }
921*f6dc9357SAndroid Build Coastguard Worker       _numSolidBytes = (v << numBits);
922*f6dc9357SAndroid Build Coastguard Worker       _numSolidBytesDefined = true;
923*f6dc9357SAndroid Build Coastguard Worker       /*
924*f6dc9357SAndroid Build Coastguard Worker       if (_numSolidBytes == 0)
925*f6dc9357SAndroid Build Coastguard Worker         _numSolidFiles = 1;
926*f6dc9357SAndroid Build Coastguard Worker       */
927*f6dc9357SAndroid Build Coastguard Worker     }
928*f6dc9357SAndroid Build Coastguard Worker   }
929*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
930*f6dc9357SAndroid Build Coastguard Worker }
931*f6dc9357SAndroid Build Coastguard Worker 
SetSolidFromPROPVARIANT(const PROPVARIANT & value)932*f6dc9357SAndroid Build Coastguard Worker HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
933*f6dc9357SAndroid Build Coastguard Worker {
934*f6dc9357SAndroid Build Coastguard Worker   bool isSolid;
935*f6dc9357SAndroid Build Coastguard Worker   switch (value.vt)
936*f6dc9357SAndroid Build Coastguard Worker   {
937*f6dc9357SAndroid Build Coastguard Worker     case VT_EMPTY: isSolid = true; break;
938*f6dc9357SAndroid Build Coastguard Worker     case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
939*f6dc9357SAndroid Build Coastguard Worker     case VT_BSTR:
940*f6dc9357SAndroid Build Coastguard Worker       if (StringToBool(value.bstrVal, isSolid))
941*f6dc9357SAndroid Build Coastguard Worker         break;
942*f6dc9357SAndroid Build Coastguard Worker       return SetSolidFromString(value.bstrVal);
943*f6dc9357SAndroid Build Coastguard Worker     default: return E_INVALIDARG;
944*f6dc9357SAndroid Build Coastguard Worker   }
945*f6dc9357SAndroid Build Coastguard Worker   if (isSolid)
946*f6dc9357SAndroid Build Coastguard Worker     InitSolid();
947*f6dc9357SAndroid Build Coastguard Worker   else
948*f6dc9357SAndroid Build Coastguard Worker     _numSolidFiles = 1;
949*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
950*f6dc9357SAndroid Build Coastguard Worker }
951*f6dc9357SAndroid Build Coastguard Worker 
PROPVARIANT_to_BoolPair(const PROPVARIANT & prop,CBoolPair & dest)952*f6dc9357SAndroid Build Coastguard Worker static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
953*f6dc9357SAndroid Build Coastguard Worker {
954*f6dc9357SAndroid Build Coastguard Worker   RINOK(PROPVARIANT_to_bool(prop, dest.Val))
955*f6dc9357SAndroid Build Coastguard Worker   dest.Def = true;
956*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker struct C_Id_Name_pair
960*f6dc9357SAndroid Build Coastguard Worker {
961*f6dc9357SAndroid Build Coastguard Worker   UInt32 Id;
962*f6dc9357SAndroid Build Coastguard Worker   const char *Name;
963*f6dc9357SAndroid Build Coastguard Worker };
964*f6dc9357SAndroid Build Coastguard Worker 
965*f6dc9357SAndroid Build Coastguard Worker static const C_Id_Name_pair g_filter_pairs[] =
966*f6dc9357SAndroid Build Coastguard Worker {
967*f6dc9357SAndroid Build Coastguard Worker   { k_Delta, "Delta" },
968*f6dc9357SAndroid Build Coastguard Worker   { k_ARM64, "ARM64" },
969*f6dc9357SAndroid Build Coastguard Worker   { k_RISCV, "RISCV" },
970*f6dc9357SAndroid Build Coastguard Worker   { k_SWAP2, "SWAP2" },
971*f6dc9357SAndroid Build Coastguard Worker   { k_SWAP4, "SWAP4" },
972*f6dc9357SAndroid Build Coastguard Worker   { k_BCJ,   "BCJ" },
973*f6dc9357SAndroid Build Coastguard Worker   { k_BCJ2 , "BCJ2" },
974*f6dc9357SAndroid Build Coastguard Worker   { k_PPC,   "PPC" },
975*f6dc9357SAndroid Build Coastguard Worker   { k_IA64,  "IA64" },
976*f6dc9357SAndroid Build Coastguard Worker   { k_ARM,   "ARM" },
977*f6dc9357SAndroid Build Coastguard Worker   { k_ARMT,  "ARMT" },
978*f6dc9357SAndroid Build Coastguard Worker   { k_SPARC, "SPARC" }
979*f6dc9357SAndroid Build Coastguard Worker };
980*f6dc9357SAndroid Build Coastguard Worker 
981*f6dc9357SAndroid Build Coastguard Worker 
SetProperty(const wchar_t * nameSpec,const PROPVARIANT & value)982*f6dc9357SAndroid Build Coastguard Worker HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
983*f6dc9357SAndroid Build Coastguard Worker {
984*f6dc9357SAndroid Build Coastguard Worker   UString name = nameSpec;
985*f6dc9357SAndroid Build Coastguard Worker   name.MakeLower_Ascii();
986*f6dc9357SAndroid Build Coastguard Worker   if (name.IsEmpty())
987*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
988*f6dc9357SAndroid Build Coastguard Worker 
989*f6dc9357SAndroid Build Coastguard Worker   if (name[0] == L's')
990*f6dc9357SAndroid Build Coastguard Worker   {
991*f6dc9357SAndroid Build Coastguard Worker     name.Delete(0);
992*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEmpty())
993*f6dc9357SAndroid Build Coastguard Worker       return SetSolidFromPROPVARIANT(value);
994*f6dc9357SAndroid Build Coastguard Worker     if (value.vt != VT_EMPTY)
995*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
996*f6dc9357SAndroid Build Coastguard Worker     return SetSolidFromString(name);
997*f6dc9357SAndroid Build Coastguard Worker   }
998*f6dc9357SAndroid Build Coastguard Worker 
999*f6dc9357SAndroid Build Coastguard Worker   UInt32 number;
1000*f6dc9357SAndroid Build Coastguard Worker   const unsigned index = ParseStringToUInt32(name, number);
1001*f6dc9357SAndroid Build Coastguard Worker   // UString realName = name.Ptr(index);
1002*f6dc9357SAndroid Build Coastguard Worker   if (index == 0)
1003*f6dc9357SAndroid Build Coastguard Worker   {
1004*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
1005*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders);
1006*f6dc9357SAndroid Build Coastguard Worker     // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents);
1007*f6dc9357SAndroid Build Coastguard Worker 
1008*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("hcf"))
1009*f6dc9357SAndroid Build Coastguard Worker     {
1010*f6dc9357SAndroid Build Coastguard Worker       bool compressHeadersFull = true;
1011*f6dc9357SAndroid Build Coastguard Worker       RINOK(PROPVARIANT_to_bool(value, compressHeadersFull))
1012*f6dc9357SAndroid Build Coastguard Worker       return compressHeadersFull ? S_OK: E_INVALIDARG;
1013*f6dc9357SAndroid Build Coastguard Worker     }
1014*f6dc9357SAndroid Build Coastguard Worker 
1015*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("he"))
1016*f6dc9357SAndroid Build Coastguard Worker     {
1017*f6dc9357SAndroid Build Coastguard Worker       RINOK(PROPVARIANT_to_bool(value, _encryptHeaders))
1018*f6dc9357SAndroid Build Coastguard Worker       _encryptHeadersSpecified = true;
1019*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1020*f6dc9357SAndroid Build Coastguard Worker     }
1021*f6dc9357SAndroid Build Coastguard Worker 
1022*f6dc9357SAndroid Build Coastguard Worker     {
1023*f6dc9357SAndroid Build Coastguard Worker       bool processed;
1024*f6dc9357SAndroid Build Coastguard Worker       RINOK(TimeOptions.Parse(name, value, processed))
1025*f6dc9357SAndroid Build Coastguard Worker       if (processed)
1026*f6dc9357SAndroid Build Coastguard Worker       {
1027*f6dc9357SAndroid Build Coastguard Worker         if (   TimeOptions.Prec != (UInt32)(Int32)-1
1028*f6dc9357SAndroid Build Coastguard Worker             && TimeOptions.Prec != k_PropVar_TimePrec_0
1029*f6dc9357SAndroid Build Coastguard Worker             && TimeOptions.Prec != k_PropVar_TimePrec_HighPrec
1030*f6dc9357SAndroid Build Coastguard Worker             && TimeOptions.Prec != k_PropVar_TimePrec_100ns)
1031*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
1032*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1033*f6dc9357SAndroid Build Coastguard Worker       }
1034*f6dc9357SAndroid Build Coastguard Worker     }
1035*f6dc9357SAndroid Build Coastguard Worker 
1036*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib);
1037*f6dc9357SAndroid Build Coastguard Worker 
1038*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
1039*f6dc9357SAndroid Build Coastguard Worker 
1040*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
1041*f6dc9357SAndroid Build Coastguard Worker 
1042*f6dc9357SAndroid Build Coastguard Worker     if (name.IsPrefixedBy_Ascii_NoCase("yv"))
1043*f6dc9357SAndroid Build Coastguard Worker     {
1044*f6dc9357SAndroid Build Coastguard Worker       name.Delete(0, 2);
1045*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 1 << 16;  // if no number is noit specified, we use big value
1046*f6dc9357SAndroid Build Coastguard Worker       RINOK(ParsePropToUInt32(name, value, v))
1047*f6dc9357SAndroid Build Coastguard Worker       _decoderCompatibilityVersion = v;
1048*f6dc9357SAndroid Build Coastguard Worker       // if (v == 0) _decoderCompatibilityVersion = k_decoderCompatibilityVersion;
1049*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1050*f6dc9357SAndroid Build Coastguard Worker     }
1051*f6dc9357SAndroid Build Coastguard Worker 
1052*f6dc9357SAndroid Build Coastguard Worker     if (name.IsPrefixedBy_Ascii_NoCase("yf"))
1053*f6dc9357SAndroid Build Coastguard Worker     {
1054*f6dc9357SAndroid Build Coastguard Worker       name.Delete(0, 2);
1055*f6dc9357SAndroid Build Coastguard Worker       CUIntVector *vec;
1056*f6dc9357SAndroid Build Coastguard Worker            if (name.IsEqualTo_Ascii_NoCase("a")) vec = &_enabledFilters;
1057*f6dc9357SAndroid Build Coastguard Worker       else if (name.IsEqualTo_Ascii_NoCase("d")) vec = &_disabledFilters;
1058*f6dc9357SAndroid Build Coastguard Worker       else return E_INVALIDARG;
1059*f6dc9357SAndroid Build Coastguard Worker 
1060*f6dc9357SAndroid Build Coastguard Worker       if (value.vt != VT_BSTR)
1061*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1062*f6dc9357SAndroid Build Coastguard Worker       for (unsigned k = 0;; k++)
1063*f6dc9357SAndroid Build Coastguard Worker       {
1064*f6dc9357SAndroid Build Coastguard Worker         if (k == Z7_ARRAY_SIZE(g_filter_pairs))
1065*f6dc9357SAndroid Build Coastguard Worker         {
1066*f6dc9357SAndroid Build Coastguard Worker           // maybe we can ignore unsupported filter names here?
1067*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
1068*f6dc9357SAndroid Build Coastguard Worker         }
1069*f6dc9357SAndroid Build Coastguard Worker         const C_Id_Name_pair &pair = g_filter_pairs[k];
1070*f6dc9357SAndroid Build Coastguard Worker         if (StringsAreEqualNoCase_Ascii(value.bstrVal, pair.Name))
1071*f6dc9357SAndroid Build Coastguard Worker         {
1072*f6dc9357SAndroid Build Coastguard Worker           vec->AddToUniqueSorted(pair.Id);
1073*f6dc9357SAndroid Build Coastguard Worker           break;
1074*f6dc9357SAndroid Build Coastguard Worker         }
1075*f6dc9357SAndroid Build Coastguard Worker       }
1076*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1077*f6dc9357SAndroid Build Coastguard Worker     }
1078*f6dc9357SAndroid Build Coastguard Worker 
1079*f6dc9357SAndroid Build Coastguard Worker     // if (name.IsEqualTo("v"))  return PROPVARIANT_to_bool(value, _volumeMode);
1080*f6dc9357SAndroid Build Coastguard Worker   }
1081*f6dc9357SAndroid Build Coastguard Worker   return CMultiMethodProps::SetProperty(name, value);
1082*f6dc9357SAndroid Build Coastguard Worker }
1083*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::SetProperties (const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps))1084*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
1085*f6dc9357SAndroid Build Coastguard Worker {
1086*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1087*f6dc9357SAndroid Build Coastguard Worker   _bonds.Clear();
1088*f6dc9357SAndroid Build Coastguard Worker   InitProps();
1089*f6dc9357SAndroid Build Coastguard Worker 
1090*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numProps; i++)
1091*f6dc9357SAndroid Build Coastguard Worker   {
1092*f6dc9357SAndroid Build Coastguard Worker     UString name = names[i];
1093*f6dc9357SAndroid Build Coastguard Worker     name.MakeLower_Ascii();
1094*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEmpty())
1095*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
1096*f6dc9357SAndroid Build Coastguard Worker 
1097*f6dc9357SAndroid Build Coastguard Worker     const PROPVARIANT &value = values[i];
1098*f6dc9357SAndroid Build Coastguard Worker 
1099*f6dc9357SAndroid Build Coastguard Worker     if (name.Find(L':') >= 0) // 'b' was used as NCoderPropID::kBlockSize2 before v23
1100*f6dc9357SAndroid Build Coastguard Worker     if (name[0] == 'b')
1101*f6dc9357SAndroid Build Coastguard Worker     {
1102*f6dc9357SAndroid Build Coastguard Worker       if (value.vt != VT_EMPTY)
1103*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1104*f6dc9357SAndroid Build Coastguard Worker       name.Delete(0);
1105*f6dc9357SAndroid Build Coastguard Worker 
1106*f6dc9357SAndroid Build Coastguard Worker       CBond2 bond;
1107*f6dc9357SAndroid Build Coastguard Worker       RINOK(ParseBond(name, bond.OutCoder, bond.OutStream))
1108*f6dc9357SAndroid Build Coastguard Worker       if (name[0] != ':')
1109*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1110*f6dc9357SAndroid Build Coastguard Worker       name.Delete(0);
1111*f6dc9357SAndroid Build Coastguard Worker       UInt32 inStream = 0;
1112*f6dc9357SAndroid Build Coastguard Worker       RINOK(ParseBond(name, bond.InCoder, inStream))
1113*f6dc9357SAndroid Build Coastguard Worker       if (inStream != 0)
1114*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1115*f6dc9357SAndroid Build Coastguard Worker       if (!name.IsEmpty())
1116*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1117*f6dc9357SAndroid Build Coastguard Worker       _bonds.Add(bond);
1118*f6dc9357SAndroid Build Coastguard Worker       continue;
1119*f6dc9357SAndroid Build Coastguard Worker     }
1120*f6dc9357SAndroid Build Coastguard Worker 
1121*f6dc9357SAndroid Build Coastguard Worker     RINOK(SetProperty(name, value))
1122*f6dc9357SAndroid Build Coastguard Worker   }
1123*f6dc9357SAndroid Build Coastguard Worker 
1124*f6dc9357SAndroid Build Coastguard Worker   unsigned numEmptyMethods = GetNumEmptyMethods();
1125*f6dc9357SAndroid Build Coastguard Worker   if (numEmptyMethods > 0)
1126*f6dc9357SAndroid Build Coastguard Worker   {
1127*f6dc9357SAndroid Build Coastguard Worker     unsigned k;
1128*f6dc9357SAndroid Build Coastguard Worker     for (k = 0; k < _bonds.Size(); k++)
1129*f6dc9357SAndroid Build Coastguard Worker     {
1130*f6dc9357SAndroid Build Coastguard Worker       const CBond2 &bond = _bonds[k];
1131*f6dc9357SAndroid Build Coastguard Worker       if (bond.InCoder < (UInt32)numEmptyMethods ||
1132*f6dc9357SAndroid Build Coastguard Worker           bond.OutCoder < (UInt32)numEmptyMethods)
1133*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1134*f6dc9357SAndroid Build Coastguard Worker     }
1135*f6dc9357SAndroid Build Coastguard Worker     for (k = 0; k < _bonds.Size(); k++)
1136*f6dc9357SAndroid Build Coastguard Worker     {
1137*f6dc9357SAndroid Build Coastguard Worker       CBond2 &bond = _bonds[k];
1138*f6dc9357SAndroid Build Coastguard Worker       bond.InCoder -= (UInt32)numEmptyMethods;
1139*f6dc9357SAndroid Build Coastguard Worker       bond.OutCoder -= (UInt32)numEmptyMethods;
1140*f6dc9357SAndroid Build Coastguard Worker     }
1141*f6dc9357SAndroid Build Coastguard Worker     _methods.DeleteFrontal(numEmptyMethods);
1142*f6dc9357SAndroid Build Coastguard Worker   }
1143*f6dc9357SAndroid Build Coastguard Worker 
1144*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (k, _bonds)
1145*f6dc9357SAndroid Build Coastguard Worker   {
1146*f6dc9357SAndroid Build Coastguard Worker     const CBond2 &bond = _bonds[k];
1147*f6dc9357SAndroid Build Coastguard Worker     if (bond.InCoder >= (UInt32)_methods.Size() ||
1148*f6dc9357SAndroid Build Coastguard Worker         bond.OutCoder >= (UInt32)_methods.Size())
1149*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
1150*f6dc9357SAndroid Build Coastguard Worker   }
1151*f6dc9357SAndroid Build Coastguard Worker 
1152*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1153*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1154*f6dc9357SAndroid Build Coastguard Worker }
1155*f6dc9357SAndroid Build Coastguard Worker 
1156*f6dc9357SAndroid Build Coastguard Worker }}
1157*f6dc9357SAndroid Build Coastguard Worker 
1158*f6dc9357SAndroid Build Coastguard Worker #endif
1159