1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// EnumDirItems.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "EnumDirItems.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
8baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NFile;
9baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NName;
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
11baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid AddDirFileInfo(int phyParent, int logParent,
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems)
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CDirItem di;
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.Size = fi.Size;
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.CTime = fi.CTime;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.ATime = fi.ATime;
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.MTime = fi.MTime;
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.Attrib = fi.Attrib;
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.PhyParent = phyParent;
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.LogParent = logParent;
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  di.Name = fi.Name;
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dirItems.Add(di);
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
26baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString path;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int len = name.Length();
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i;
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = index; i >= 0; i = parents[i])
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    len += Prefixes[i].Length();
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int totalLen = len;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  wchar_t *p = path.GetBuffer(len);
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p[len] = 0;
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  len -= name.Length();
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t));
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = index; i >= 0; i = parents[i])
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &s = Prefixes[i];
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    len -= s.Length();
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t));
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  path.ReleaseBuffer(totalLen);
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return path;
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
48baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUString CDirItems::GetPhyPath(int index) const
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const CDirItem &di = Items[index];
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
54baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUString CDirItems::GetLogPath(int index) const
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const CDirItem &di = Items[index];
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return GetPrefixesPath(LogParents, di.LogParent, di.Name);
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
60baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CDirItems::ReserveDown()
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Prefixes.ReserveDown();
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PhyParents.ReserveDown();
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LogParents.ReserveDown();
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Items.ReserveDown();
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
68baa3858d3f5d128a5c8466b700098109edcad5f2repo syncint CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PhyParents.Add(phyParent);
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LogParents.Add(logParent);
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return Prefixes.Add(prefix);
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
75baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CDirItems::DeleteLastPrefix()
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PhyParents.DeleteBack();
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LogParents.DeleteBack();
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Prefixes.DeleteBack();
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
82baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard);
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (;;)
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFind::CFileInfoW fi;
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool found;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!enumerator.Next(fi, found))
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorCodes.Add(::GetLastError());
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorPaths.Add(phyPrefix);
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!found)
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    AddDirFileInfo(phyParent, logParent, fi, Items);
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (fi.IsDir())
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int parent = AddPrefix(phyParent, logParent, name2);
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes);
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
108baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix,
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix);
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix);
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < filePaths.Size(); i++)
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &filePath = filePaths[i];
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFind::CFileInfoW fi;
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString phyPath = phyPrefix + filePath;
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!fi.Find(phyPath))
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorCodes.Add(::GetLastError());
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorPaths.Add(phyPath);
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter);
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString phyPrefixCur;
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int phyParentCur = phyParent;
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (delimiter >= 0)
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      phyPrefixCur = filePath.Left(delimiter + 1);
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur);
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    AddDirFileInfo(phyParentCur, logParent, fi, Items);
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (fi.IsDir())
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int parent = AddPrefix(phyParentCur, logParent, name2);
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes);
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ReserveDown();
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
144baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int phyParent, int logParent, const UString &phyPrefix,
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UStringVector &addArchivePrefix,
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDirItems &dirItems,
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool enterToSubFolders,
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IEnumDirItemCallback *callback,
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector &errorPaths,
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<DWORD> &errorCodes);
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
153baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode,
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int phyParent, int logParent, const UString &curFolderName,
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &phyPrefix,
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UStringVector &addArchivePrefix,
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDirItems &dirItems,
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool enterToSubFolders,
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IEnumDirItemCallback *callback,
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector &errorPaths,
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<DWORD> &errorCodes)
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UString name2 = curFolderName + (wchar_t)kDirDelimiter;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int parent = dirItems.AddPrefix(phyParent, logParent, name2);
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numItems = dirItems.Items.Size();
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2,
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes);
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numItems == dirItems.Items.Size())
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    dirItems.DeleteLastPrefix();
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return res;
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
175baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int phyParent, int logParent, const UString &phyPrefix,
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UStringVector &addArchivePrefix,  // prefix from curNode
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDirItems &dirItems,
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool enterToSubFolders,
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IEnumDirItemCallback *callback,
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector &errorPaths,
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<DWORD> &errorCodes)
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!enterToSubFolders)
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (curNode.NeedCheckSubDirs())
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      enterToSubFolders = true;
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (callback)
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // try direct_names case at first
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // check that all names are direct
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int i;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < curNode.IncludeItems.Size(); i++)
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const NWildcard::CItem &item = curNode.IncludeItems[i];
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (item.Recursive || item.PathParts.Size() != 1)
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString &name = item.PathParts.Front();
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (name.IsEmpty() || DoesNameContainWildCard(name))
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (i == curNode.IncludeItems.Size())
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // all names are direct (no wildcards)
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // so we don't need file_system's dir enumerator
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CRecordVector<bool> needEnterVector;
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (i = 0; i < curNode.IncludeItems.Size(); i++)
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const NWildcard::CItem &item = curNode.IncludeItems[i];
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const UString &name = item.PathParts.Front();
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const UString fullPath = phyPrefix + name;
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NFind::CFileInfoW fi;
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!fi.Find(fullPath))
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorCodes.Add(::GetLastError());
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorPaths.Add(fullPath);
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        bool isDir = fi.IsDir();
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (isDir && !item.ForDir || !isDir && !item.ForFile)
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorCodes.Add((DWORD)E_FAIL);
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorPaths.Add(fullPath);
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          UStringVector pathParts;
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          pathParts.Add(fi.Name);
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (curNode.CheckPathToRoot(false, pathParts, !isDir))
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            continue;
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!isDir)
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UStringVector addArchivePrefixNew;
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const NWildcard::CCensorNode *nextNode = 0;
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        int index = curNode.FindSubNode(name);
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (index >= 0)
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          for (int t = needEnterVector.Size(); t <= index; t++)
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            needEnterVector.Add(true);
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          needEnterVector[index] = false;
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          nextNode = &curNode.SubNodes[index];
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        else
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          nextNode = &curNode;
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (i = 0; i < curNode.SubNodes.Size(); i++)
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (i < needEnterVector.Size())
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (!needEnterVector[i])
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            continue;
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const UString fullPath = phyPrefix + nextNode.Name;
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NFind::CFileInfoW fi;
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!fi.Find(fullPath))
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (!nextNode.AreThereIncludeItems())
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            continue;
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorCodes.Add(::GetLastError());
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorPaths.Add(fullPath);
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!fi.IsDir())
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorCodes.Add((DWORD)E_FAIL);
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorPaths.Add(fullPath);
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_OK;
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard));
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int ttt = 0; ; ttt++)
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFind::CFileInfoW fi;
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool found;
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!enumerator.Next(fi, found))
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorCodes.Add(::GetLastError());
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorPaths.Add(phyPrefix);
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!found)
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (callback && (ttt & 0xFF) == 0xFF)
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &name = fi.Name;
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool enterToSubFolders2 = enterToSubFolders;
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector addArchivePrefixNew = addArchivePrefix;
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    addArchivePrefixNew.Add(name);
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        continue;
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (fi.IsDir())
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        enterToSubFolders2 = true;
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!fi.IsDir())
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NWildcard::CCensorNode *nextNode = 0;
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (addArchivePrefix.IsEmpty())
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int index = curNode.FindSubNode(name);
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (index >= 0)
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        nextNode = &curNode.SubNodes[index];
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!enterToSubFolders2 && nextNode == 0)
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    addArchivePrefixNew = addArchivePrefix;
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (nextNode == 0)
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      nextNode = &curNode;
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      addArchivePrefixNew.Add(name);
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix,
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
345baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT EnumerateItems(
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NWildcard::CCensor &censor,
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDirItems &dirItems,
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IEnumDirItemCallback *callback,
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector &errorPaths,
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<DWORD> &errorCodes)
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < censor.Pairs.Size(); i++)
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NWildcard::CPair &pair = censor.Pairs[i];
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix);
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false,
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        callback, errorPaths, errorCodes));
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
359baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dirItems.ReserveDown();
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
362