xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Agent/AgentProxy.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // AgentProxy.cpp
2 
3 #include "StdAfx.h"
4 
5 // #include <stdio.h>
6 #ifdef _WIN32
7 #include <wchar.h>
8 #else
9 #include <ctype.h>
10 #endif
11 
12 #include "../../../../C/Sort.h"
13 #include "../../../../C/CpuArch.h"
14 
15 #include "../../../Common/UTFConvert.h"
16 #include "../../../Common/Wildcard.h"
17 
18 #include "../../../Windows/PropVariant.h"
19 #include "../../../Windows/PropVariantConv.h"
20 
21 #include "../../Archive/Common/ItemNameUtils.h"
22 
23 #include "AgentProxy.h"
24 
25 using namespace NWindows;
26 
FindSubDir(unsigned dirIndex,const wchar_t * name,unsigned & insertPos) const27 int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const
28 {
29   const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs;
30   unsigned left = 0, right = subDirs.Size();
31   for (;;)
32   {
33     if (left == right)
34     {
35       insertPos = left;
36       return -1;
37     }
38     const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
39     const unsigned dirIndex2 = subDirs[mid];
40     const int comp = CompareFileNames(name, Dirs[dirIndex2].Name);
41     if (comp == 0)
42       return (int)dirIndex2;
43     if (comp < 0)
44       right = mid;
45     else
46       left = mid + 1;
47   }
48 }
49 
FindSubDir(unsigned dirIndex,const wchar_t * name) const50 int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const
51 {
52   unsigned insertPos;
53   return FindSubDir(dirIndex, name, insertPos);
54 }
55 
AllocStringAndCopy(const wchar_t * s,size_t len)56 static const wchar_t *AllocStringAndCopy(const wchar_t *s, size_t len)
57 {
58   wchar_t *p = new wchar_t[len + 1];
59   MyStringCopy(p, s);
60   return p;
61 }
62 
AllocStringAndCopy(const UString & s)63 static const wchar_t *AllocStringAndCopy(const UString &s)
64 {
65   return AllocStringAndCopy(s, s.Len());
66 }
67 
AddDir(unsigned dirIndex,int arcIndex,const UString & name)68 unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name)
69 {
70   unsigned insertPos;
71   int subDirIndex = FindSubDir(dirIndex, name, insertPos);
72   if (subDirIndex != -1)
73   {
74     if (arcIndex != -1)
75     {
76       CProxyDir &item = Dirs[(unsigned)subDirIndex];
77       if (item.ArcIndex == -1)
78         item.ArcIndex = arcIndex;
79     }
80     return (unsigned)subDirIndex;
81   }
82   subDirIndex = (int)Dirs.Size();
83   Dirs[dirIndex].SubDirs.Insert(insertPos, (unsigned)subDirIndex);
84   CProxyDir &item = Dirs.AddNew();
85 
86   item.NameLen = name.Len();
87   item.Name = AllocStringAndCopy(name);
88 
89   item.ArcIndex = arcIndex;
90   item.ParentDir = (int)dirIndex;
91   return (unsigned)subDirIndex;
92 }
93 
Clear()94 void CProxyDir::Clear()
95 {
96   SubDirs.Clear();
97   SubFiles.Clear();
98 }
99 
GetDirPathParts(unsigned dirIndex,UStringVector & pathParts) const100 void CProxyArc::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const
101 {
102   pathParts.Clear();
103   // while (dirIndex != -1)
104   for (;;)
105   {
106     const CProxyDir &dir = Dirs[dirIndex];
107     dirIndex = (unsigned)dir.ParentDir;
108     if (dir.ParentDir == -1)
109       break;
110     pathParts.Insert(0, dir.Name);
111     // 22.00: we normalize name
112     NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(pathParts[0]);
113   }
114 }
115 
GetDirPath_as_Prefix(unsigned dirIndex) const116 UString CProxyArc::GetDirPath_as_Prefix(unsigned dirIndex) const
117 {
118   UString s;
119   // while (dirIndex != -1)
120   for (;;)
121   {
122     const CProxyDir &dir = Dirs[dirIndex];
123     dirIndex = (unsigned)dir.ParentDir;
124     if (dir.ParentDir == -1)
125       break;
126     s.InsertAtFront(WCHAR_PATH_SEPARATOR);
127     s.Insert(0, dir.Name);
128     // 22.00: we normalize name
129     NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s.GetBuf(), MyStringLen(dir.Name));
130   }
131   return s;
132 }
133 
AddRealIndices(unsigned dirIndex,CUIntVector & realIndices) const134 void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const
135 {
136   const CProxyDir &dir = Dirs[dirIndex];
137   if (dir.IsLeaf())
138     realIndices.Add((unsigned)dir.ArcIndex);
139   unsigned i;
140   for (i = 0; i < dir.SubDirs.Size(); i++)
141     AddRealIndices(dir.SubDirs[i], realIndices);
142   for (i = 0; i < dir.SubFiles.Size(); i++)
143     realIndices.Add(dir.SubFiles[i]);
144 }
145 
GetRealIndex(unsigned dirIndex,unsigned index) const146 int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const
147 {
148   const CProxyDir &dir = Dirs[dirIndex];
149   const unsigned numDirItems = dir.SubDirs.Size();
150   if (index < numDirItems)
151   {
152     const CProxyDir &f = Dirs[dir.SubDirs[index]];
153     if (f.IsLeaf())
154       return f.ArcIndex;
155     return -1;
156   }
157   return (int)dir.SubFiles[index - numDirItems];
158 }
159 
GetRealIndices(unsigned dirIndex,const UInt32 * indices,UInt32 numItems,CUIntVector & realIndices) const160 void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
161 {
162   const CProxyDir &dir = Dirs[dirIndex];
163   realIndices.Clear();
164   for (UInt32 i = 0; i < numItems; i++)
165   {
166     const UInt32 index = indices[i];
167     const unsigned numDirItems = dir.SubDirs.Size();
168     if (index < numDirItems)
169       AddRealIndices(dir.SubDirs[index], realIndices);
170     else
171       realIndices.Add(dir.SubFiles[index - numDirItems]);
172   }
173   HeapSort(realIndices.NonConstData(), realIndices.Size());
174 }
175 
176 ///////////////////////////////////////////////
177 // CProxyArc
178 
GetSize(IInArchive * archive,UInt32 index,PROPID propID,UInt64 & size)179 static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size)
180 {
181   size = 0;
182   NCOM::CPropVariant prop;
183   if (archive->GetProperty(index, propID, &prop) != S_OK)
184     throw 20120228;
185   return ConvertPropVariantToUInt64(prop, size);
186 }
187 
CalculateSizes(unsigned dirIndex,IInArchive * archive)188 void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive)
189 {
190   CProxyDir &dir = Dirs[dirIndex];
191   dir.Size = dir.PackSize = 0;
192   dir.NumSubDirs = dir.SubDirs.Size();
193   dir.NumSubFiles = dir.SubFiles.Size();
194   dir.CrcIsDefined = true;
195   dir.Crc = 0;
196 
197   unsigned i;
198 
199   for (i = 0; i < dir.SubFiles.Size(); i++)
200   {
201     const UInt32 index = (UInt32)dir.SubFiles[i];
202     UInt64 size, packSize;
203     const bool sizeDefined = GetSize(archive, index, kpidSize, size);
204     dir.Size += size;
205     GetSize(archive, index, kpidPackSize, packSize);
206     dir.PackSize += packSize;
207     {
208       NCOM::CPropVariant prop;
209       if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
210       {
211         if (prop.vt == VT_UI4)
212           dir.Crc += prop.ulVal;
213         else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
214           dir.CrcIsDefined = false;
215       }
216       else
217         dir.CrcIsDefined = false;
218     }
219   }
220 
221   for (i = 0; i < dir.SubDirs.Size(); i++)
222   {
223     unsigned subDirIndex = dir.SubDirs[i];
224     CalculateSizes(subDirIndex, archive);
225     CProxyDir &f = Dirs[subDirIndex];
226     dir.Size += f.Size;
227     dir.PackSize += f.PackSize;
228     dir.NumSubFiles += f.NumSubFiles;
229     dir.NumSubDirs += f.NumSubDirs;
230     dir.Crc += f.Crc;
231     if (!f.CrcIsDefined)
232       dir.CrcIsDefined = false;
233   }
234 }
235 
Load(const CArc & arc,IProgress * progress)236 HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
237 {
238   // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
239 
240   Files.Free();
241   Dirs.Clear();
242 
243   Dirs.AddNew();
244   IInArchive *archive = arc.Archive;
245 
246   UInt32 numItems;
247   RINOK(archive->GetNumberOfItems(&numItems))
248 
249   if (progress)
250     RINOK(progress->SetTotal(numItems))
251 
252   Files.Alloc(numItems);
253 
254   UString path;
255   UString name;
256   NCOM::CPropVariant prop;
257 
258   for (UInt32 i = 0; i < numItems; i++)
259   {
260     if (progress && (i & 0xFFFF) == 0)
261     {
262       const UInt64 currentItemIndex = i;
263       RINOK(progress->SetCompleted(&currentItemIndex))
264     }
265 
266     const wchar_t *s = NULL;
267     unsigned len = 0;
268     bool isPtrName = false;
269 
270    #if WCHAR_PATH_SEPARATOR != L'/'
271     wchar_t separatorChar = WCHAR_PATH_SEPARATOR;
272    #endif
273 
274     #if defined(MY_CPU_LE) && defined(_WIN32)
275     // it works only if (sizeof(wchar_t) == 2)
276     if (arc.GetRawProps)
277     {
278       const void *p;
279       UInt32 size;
280       UInt32 propType;
281       if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK
282           && propType == NPropDataType::kUtf16z
283           && size > 2)
284       {
285         // is (size <= 2), it's empty name, and we call default arc.GetItemPath();
286         len = size / 2 - 1;
287         s = (const wchar_t *)p;
288         isPtrName = true;
289        #if WCHAR_PATH_SEPARATOR != L'/'
290         separatorChar = L'/';  // 0
291        #endif
292       }
293     }
294     if (!s)
295     #endif
296     {
297       prop.Clear();
298       RINOK(arc.Archive->GetProperty(i, kpidPath, &prop))
299       if (prop.vt == VT_BSTR)
300       {
301         s = prop.bstrVal;
302         len = ::SysStringLen(prop.bstrVal);
303       }
304       else if (prop.vt != VT_EMPTY)
305         return E_FAIL;
306       if (len == 0)
307       {
308         RINOK(arc.GetItem_DefaultPath(i, path))
309         len = path.Len();
310         s = path;
311       }
312 
313       /*
314       RINOK(arc.GetItemPath(i, path));
315       len = path.Len();
316       s = path;
317       */
318     }
319 
320     unsigned curItem = 0;
321 
322     /*
323     if (arc.Ask_Deleted)
324     {
325       bool isDeleted = false;
326       RINOK(Archive_IsItem_Deleted(archive, i, isDeleted));
327       if (isDeleted)
328         curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
329     }
330     */
331 
332     unsigned namePos = 0;
333 
334     unsigned numLevels = 0;
335 
336     for (unsigned j = 0; j < len; j++)
337     {
338       const wchar_t c = s[j];
339       if (c == L'/'
340         #if WCHAR_PATH_SEPARATOR != L'/'
341           || (c == separatorChar)
342         #endif
343           )
344       {
345         const unsigned kLevelLimit = 1 << 10;
346         if (numLevels <= kLevelLimit)
347         {
348           if (numLevels == kLevelLimit)
349             name = "[LONG_PATH]";
350           else
351             name.SetFrom(s + namePos, j - namePos);
352           // 22.00: we can normalize dir here
353           // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
354           curItem = AddDir(curItem, -1, name);
355         }
356         namePos = j + 1;
357         numLevels++;
358       }
359     }
360 
361     /*
362     that code must be implemeted to hide alt streams in list.
363     if (arc.Ask_AltStreams)
364     {
365       bool isAltStream;
366       RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
367       if (isAltStream)
368       {
369 
370       }
371     }
372     */
373 
374     bool isDir;
375     RINOK(Archive_IsItem_Dir(archive, i, isDir))
376 
377     CProxyFile &f = Files[i];
378 
379     f.NameLen = len - namePos;
380     s += namePos;
381 
382     if (isPtrName)
383       f.Name = s;
384     else
385     {
386       f.Name = AllocStringAndCopy(s, f.NameLen);
387       f.NeedDeleteName = true;
388     }
389 
390     if (isDir)
391     {
392       name = s;
393       // 22.00: we can normalize dir here
394       // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
395       AddDir(curItem, (int)i, name);
396     }
397     else
398       Dirs[curItem].SubFiles.Add(i);
399   }
400 
401   CalculateSizes(0, archive);
402 
403   // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
404 
405   return S_OK;
406 }
407 
408 
409 
410 // ---------- for Tree-mode archive ----------
411 
GetDirPathParts(unsigned dirIndex,UStringVector & pathParts,bool & isAltStreamDir) const412 void CProxyArc2::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const
413 {
414   pathParts.Clear();
415 
416   isAltStreamDir = false;
417 
418   if (dirIndex == k_Proxy2_RootDirIndex)
419     return;
420   if (dirIndex == k_Proxy2_AltRootDirIndex)
421   {
422     isAltStreamDir = true;
423     return;
424   }
425 
426   while (dirIndex >= k_Proxy2_NumRootDirs)
427   {
428     const CProxyDir2 &dir = Dirs[dirIndex];
429     const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
430     if (pathParts.IsEmpty() && (int)dirIndex == file.AltDirIndex)
431       isAltStreamDir = true;
432     pathParts.Insert(0, file.Name);
433     const int par = file.Parent;
434     if (par == -1)
435       break;
436     dirIndex = (unsigned)Files[(unsigned)par].DirIndex;
437     // if ((int)dirIndex == -1) break;
438   }
439 }
440 
IsAltDir(unsigned dirIndex) const441 bool CProxyArc2::IsAltDir(unsigned dirIndex) const
442 {
443   if (dirIndex == k_Proxy2_RootDirIndex)
444     return false;
445   if (dirIndex == k_Proxy2_AltRootDirIndex)
446     return true;
447   const CProxyDir2 &dir = Dirs[dirIndex];
448   const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
449   return ((int)dirIndex == file.AltDirIndex);
450 }
451 
GetDirPath_as_Prefix(unsigned dirIndex,bool & isAltStreamDir) const452 UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const
453 {
454   isAltStreamDir = false;
455   const CProxyDir2 &dir = Dirs[dirIndex];
456   if (dirIndex == k_Proxy2_AltRootDirIndex)
457     isAltStreamDir = true;
458   else if (dirIndex >= k_Proxy2_NumRootDirs)
459   {
460     const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
461     isAltStreamDir = ((int)dirIndex == file.AltDirIndex);
462   }
463   return dir.PathPrefix;
464 }
465 
AddRealIndices_of_ArcItem(unsigned arcIndex,bool includeAltStreams,CUIntVector & realIndices) const466 void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const
467 {
468   realIndices.Add(arcIndex);
469   const CProxyFile2 &file = Files[arcIndex];
470   if (file.DirIndex != -1)
471     AddRealIndices_of_Dir((unsigned)file.DirIndex, includeAltStreams, realIndices);
472   if (includeAltStreams && file.AltDirIndex != -1)
473     AddRealIndices_of_Dir((unsigned)file.AltDirIndex, includeAltStreams, realIndices);
474 }
475 
AddRealIndices_of_Dir(unsigned dirIndex,bool includeAltStreams,CUIntVector & realIndices) const476 void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const
477 {
478   const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
479   FOR_VECTOR (i, subFiles)
480   {
481     AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices);
482   }
483 }
484 
GetRealIndex(unsigned dirIndex,unsigned index) const485 unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const
486 {
487   return Dirs[dirIndex].Items[index];
488 }
489 
GetRealIndices(unsigned dirIndex,const UInt32 * indices,UInt32 numItems,bool includeAltStreams,CUIntVector & realIndices) const490 void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
491 {
492   const CProxyDir2 &dir = Dirs[dirIndex];
493   realIndices.Clear();
494   for (UInt32 i = 0; i < numItems; i++)
495   {
496     AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices);
497   }
498   HeapSort(realIndices.NonConstData(), realIndices.Size());
499 }
500 
CalculateSizes(unsigned dirIndex,IInArchive * archive)501 void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
502 {
503   CProxyDir2 &dir = Dirs[dirIndex];
504   dir.Size = dir.PackSize = 0;
505   dir.NumSubDirs = 0; // dir.SubDirs.Size();
506   dir.NumSubFiles = 0; // dir.Files.Size();
507   dir.CrcIsDefined = true;
508   dir.Crc = 0;
509 
510   FOR_VECTOR (i, dir.Items)
511   {
512     UInt32 index = dir.Items[i];
513     UInt64 size, packSize;
514     const bool sizeDefined = GetSize(archive, index, kpidSize, size);
515     dir.Size += size;
516     GetSize(archive, index, kpidPackSize, packSize);
517     dir.PackSize += packSize;
518     {
519       NCOM::CPropVariant prop;
520       if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
521       {
522         if (prop.vt == VT_UI4)
523           dir.Crc += prop.ulVal;
524         else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
525           dir.CrcIsDefined = false;
526       }
527       else
528         dir.CrcIsDefined = false;
529     }
530 
531     const CProxyFile2 &subFile = Files[index];
532     if (subFile.DirIndex == -1)
533     {
534       dir.NumSubFiles++;
535     }
536     else
537     {
538       // 22.00: we normalize name
539       UString s = subFile.Name;
540       NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s);
541       dir.NumSubDirs++;
542       CProxyDir2 &f = Dirs[subFile.DirIndex];
543       f.PathPrefix = dir.PathPrefix + s + WCHAR_PATH_SEPARATOR;
544       CalculateSizes((unsigned)subFile.DirIndex, archive);
545       dir.Size += f.Size;
546       dir.PackSize += f.PackSize;
547       dir.NumSubFiles += f.NumSubFiles;
548       dir.NumSubDirs += f.NumSubDirs;
549       dir.Crc += f.Crc;
550       if (!f.CrcIsDefined)
551         dir.CrcIsDefined = false;
552     }
553 
554     if (subFile.AltDirIndex == -1)
555     {
556       // dir.NumSubFiles++;
557     }
558     else
559     {
560       // dir.NumSubDirs++;
561       CProxyDir2 &f = Dirs[subFile.AltDirIndex];
562       f.PathPrefix = dir.PathPrefix + subFile.Name + L':';
563       CalculateSizes((unsigned)subFile.AltDirIndex, archive);
564     }
565   }
566 }
567 
568 
IsThere_SubDir(unsigned dirIndex,const UString & name) const569 bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const
570 {
571   const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
572   FOR_VECTOR (i, subFiles)
573   {
574     const CProxyFile2 &file = Files[subFiles[i]];
575     if (file.IsDir())
576       if (CompareFileNames(name, file.Name) == 0)
577         return true;
578   }
579   return false;
580 }
581 
Load(const CArc & arc,IProgress * progress)582 HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress)
583 {
584   if (!arc.GetRawProps)
585     return E_FAIL;
586 
587   // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
588 
589   Dirs.Clear();
590   Files.Free();
591 
592   IInArchive *archive = arc.Archive;
593 
594   UInt32 numItems;
595   RINOK(archive->GetNumberOfItems(&numItems))
596   if (progress)
597     RINOK(progress->SetTotal(numItems))
598   UString fileName;
599 
600 
601   {
602     // Dirs[0] - root dir
603     /* CProxyDir2 &dir = */ Dirs.AddNew();
604   }
605 
606   {
607     // Dirs[1] - for alt streams of root dir
608     CProxyDir2 &dir = Dirs.AddNew();
609     dir.PathPrefix = ':';
610   }
611 
612   Files.Alloc(numItems);
613 
614   UString tempUString;
615   AString tempAString;
616 
617   UInt32 i;
618   for (i = 0; i < numItems; i++)
619   {
620     if (progress && (i & 0xFFFFF) == 0)
621     {
622       UInt64 currentItemIndex = i;
623       RINOK(progress->SetCompleted(&currentItemIndex))
624     }
625 
626     CProxyFile2 &file = Files[i];
627 
628     const void *p;
629     UInt32 size;
630     UInt32 propType;
631     RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType))
632 
633     #ifdef MY_CPU_LE
634     if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
635     {
636       file.Name = (const wchar_t *)p;
637       file.NameLen = 0;
638       if (size >= sizeof(wchar_t))
639         file.NameLen = size / sizeof(wchar_t) - 1;
640     }
641     else
642     #endif
643     if (p && propType == NPropDataType::kUtf8z)
644     {
645       tempAString = (const char *)p;
646       ConvertUTF8ToUnicode(tempAString, tempUString);
647       file.NameLen = tempUString.Len();
648       file.Name = AllocStringAndCopy(tempUString);
649       file.NeedDeleteName = true;
650     }
651     else
652     {
653       NCOM::CPropVariant prop;
654       RINOK(arc.Archive->GetProperty(i, kpidName, &prop))
655       const wchar_t *s;
656       if (prop.vt == VT_BSTR)
657         s = prop.bstrVal;
658       else if (prop.vt == VT_EMPTY)
659         s = L"[Content]";
660       else
661         return E_FAIL;
662       file.NameLen = MyStringLen(s);
663       file.Name = AllocStringAndCopy(s, file.NameLen);
664       file.NeedDeleteName = true;
665     }
666 
667     UInt32 parent = (UInt32)(Int32)-1;
668     UInt32 parentType = 0;
669     RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType))
670     file.Parent = (Int32)parent;
671 
672     if (arc.Ask_Deleted)
673     {
674       bool isDeleted = false;
675       RINOK(Archive_IsItem_Deleted(archive, i, isDeleted))
676       if (isDeleted)
677       {
678         // continue;
679         // curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
680       }
681     }
682 
683     bool isDir;
684     RINOK(Archive_IsItem_Dir(archive, i, isDir))
685 
686     if (isDir)
687     {
688       file.DirIndex = (int)Dirs.Size();
689       CProxyDir2 &dir = Dirs.AddNew();
690       dir.ArcIndex = (int)i;
691     }
692     if (arc.Ask_AltStream)
693       RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream))
694   }
695 
696   for (i = 0; i < numItems; i++)
697   {
698     CProxyFile2 &file = Files[i];
699     int dirIndex;
700 
701     if (file.IsAltStream)
702     {
703       if (file.Parent == -1)
704         dirIndex = k_Proxy2_AltRootDirIndex;
705       else
706       {
707         int &folderIndex2 = Files[(unsigned)file.Parent].AltDirIndex;
708         if (folderIndex2 == -1)
709         {
710           folderIndex2 = (int)Dirs.Size();
711           CProxyDir2 &dir = Dirs.AddNew();
712           dir.ArcIndex = file.Parent;
713         }
714         dirIndex = folderIndex2;
715       }
716     }
717     else
718     {
719       if (file.Parent == -1)
720         dirIndex = k_Proxy2_RootDirIndex;
721       else
722       {
723         dirIndex = Files[(unsigned)file.Parent].DirIndex;
724         if (dirIndex == -1)
725           return E_FAIL;
726       }
727     }
728 
729     Dirs[dirIndex].Items.Add(i);
730   }
731 
732   for (i = 0; i < k_Proxy2_NumRootDirs; i++)
733     CalculateSizes(i, archive);
734 
735   // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
736 
737   return S_OK;
738 }
739 
FindItem(unsigned dirIndex,const wchar_t * name,bool foldersOnly) const740 int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const
741 {
742   const CProxyDir2 &dir = Dirs[dirIndex];
743   FOR_VECTOR (i, dir.Items)
744   {
745     const CProxyFile2 &file = Files[dir.Items[i]];
746     if (foldersOnly && file.DirIndex == -1)
747       continue;
748     if (CompareFileNames(file.Name, name) == 0)
749       return (int)i;
750   }
751   return -1;
752 }
753