1 // Agent.cpp
2
3 #include "StdAfx.h"
4
5 #include <wchar.h>
6
7 #include "../../../../C/Sort.h"
8
9 #include "../../../Common/ComTry.h"
10
11 #include "../../../Windows/FileDir.h"
12 #include "../../../Windows/FileName.h"
13 #include "../../../Windows/PropVariantConv.h"
14
15 #ifndef Z7_ST
16 #include "../../../Windows/Synchronization.h"
17 #endif
18
19 #include "../Common/ArchiveExtractCallback.h"
20 #include "../FileManager/RegistryUtils.h"
21
22 #include "Agent.h"
23
24 using namespace NWindows;
25
26 CCodecs *g_CodecsObj;
27
28 static const bool k_keepEmptyDirPrefixes =
29 false; // 22.00
30 // true; // 21.07
31
32 #ifdef Z7_EXTERNAL_CODECS
33 extern
34 CExternalCodecs g_ExternalCodecs;
35 CExternalCodecs g_ExternalCodecs;
36 extern
37 const CExternalCodecs *g_ExternalCodecs_Ptr;
38 const CExternalCodecs *g_ExternalCodecs_Ptr;
39 static CCodecs::CReleaser g_CodecsReleaser;
40 #else
41 extern
42 CMyComPtr<IUnknown> g_CodecsRef;
43 CMyComPtr<IUnknown> g_CodecsRef;
44 #endif
45
46 #ifndef Z7_ST
47 static NSynchronization::CCriticalSection g_CriticalSection;
48 #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
49 #else
50 #define MT_LOCK
51 #endif
52
FreeGlobalCodecs()53 void FreeGlobalCodecs()
54 {
55 MT_LOCK
56
57 #ifdef Z7_EXTERNAL_CODECS
58 if (g_CodecsObj)
59 {
60 g_CodecsObj->CloseLibs();
61 }
62 g_CodecsReleaser.Set(NULL);
63 g_CodecsObj = NULL;
64 g_ExternalCodecs.ClearAndRelease();
65 g_ExternalCodecs_Ptr = NULL;
66 #else
67 g_CodecsRef.Release();
68 #endif
69 }
70
LoadGlobalCodecs()71 HRESULT LoadGlobalCodecs()
72 {
73 MT_LOCK
74
75 if (g_CodecsObj)
76 return S_OK;
77
78 g_CodecsObj = new CCodecs;
79
80 #ifdef Z7_EXTERNAL_CODECS
81 g_ExternalCodecs.GetCodecs = g_CodecsObj;
82 g_ExternalCodecs.GetHashers = g_CodecsObj;
83 g_CodecsReleaser.Set(g_CodecsObj);
84 #else
85 g_CodecsRef.Release();
86 g_CodecsRef = g_CodecsObj;
87 #endif
88
89 RINOK(g_CodecsObj->Load())
90 if (g_CodecsObj->Formats.IsEmpty())
91 {
92 FreeGlobalCodecs();
93 return E_NOTIMPL;
94 }
95
96 Codecs_AddHashArcHandler(g_CodecsObj);
97
98 #ifdef Z7_EXTERNAL_CODECS
99 RINOK(g_ExternalCodecs.Load())
100 g_ExternalCodecs_Ptr = &g_ExternalCodecs;
101 #endif
102
103 return S_OK;
104 }
105
Z7_COM7F_IMF(CAgentFolder::GetAgentFolder (CAgentFolder ** agentFolder))106 Z7_COM7F_IMF(CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder))
107 {
108 *agentFolder = this;
109 return S_OK;
110 }
111
LoadFolder(unsigned proxyDirIndex)112 void CAgentFolder::LoadFolder(unsigned proxyDirIndex)
113 {
114 CProxyItem item;
115 item.DirIndex = proxyDirIndex;
116
117 if (_proxy2)
118 {
119 const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex];
120 FOR_VECTOR (i, dir.Items)
121 {
122 item.Index = i;
123 _items.Add(item);
124 const CProxyFile2 &file = _proxy2->Files[dir.Items[i]];
125 if (file.DirIndex != -1)
126 LoadFolder((unsigned)file.DirIndex);
127 if (_loadAltStreams && file.AltDirIndex != -1)
128 LoadFolder((unsigned)file.AltDirIndex);
129 }
130 return;
131 }
132
133 const CProxyDir &dir = _proxy->Dirs[proxyDirIndex];
134 unsigned i;
135 for (i = 0; i < dir.SubDirs.Size(); i++)
136 {
137 item.Index = i;
138 _items.Add(item);
139 LoadFolder(dir.SubDirs[i]);
140 }
141
142 unsigned start = dir.SubDirs.Size();
143 for (i = 0; i < dir.SubFiles.Size(); i++)
144 {
145 item.Index = start + i;
146 _items.Add(item);
147 }
148 }
149
Z7_COM7F_IMF(CAgentFolder::LoadItems ())150 Z7_COM7F_IMF(CAgentFolder::LoadItems())
151 {
152 if (!_agentSpec->_archiveLink.IsOpen)
153 return E_FAIL;
154 _items.Clear();
155 if (_flatMode)
156 {
157 LoadFolder(_proxyDirIndex);
158 if (_proxy2 && _loadAltStreams)
159 {
160 if (_proxyDirIndex == k_Proxy2_RootDirIndex)
161 LoadFolder(k_Proxy2_AltRootDirIndex);
162 }
163 }
164 return S_OK;
165 }
166
Z7_COM7F_IMF(CAgentFolder::GetNumberOfItems (UInt32 * numItems))167 Z7_COM7F_IMF(CAgentFolder::GetNumberOfItems(UInt32 *numItems))
168 {
169 if (_flatMode)
170 *numItems = _items.Size();
171 else if (_proxy2)
172 *numItems = _proxy2->Dirs[_proxyDirIndex].Items.Size();
173 else
174 {
175 const CProxyDir *dir = &_proxy->Dirs[_proxyDirIndex];
176 *numItems = dir->SubDirs.Size() + dir->SubFiles.Size();
177 }
178 return S_OK;
179 }
180
181 #define SET_realIndex_AND_dir \
182 unsigned realIndex; const CProxyDir *dir; \
183 if (_flatMode) { const CProxyItem &item = _items[index]; dir = &_proxy->Dirs[item.DirIndex]; realIndex = item.Index; } \
184 else { dir = &_proxy->Dirs[_proxyDirIndex]; realIndex = index; }
185
186 #define SET_realIndex_AND_dir_2 \
187 unsigned realIndex; const CProxyDir2 *dir; \
188 if (_flatMode) { const CProxyItem &item = _items[index]; dir = &_proxy2->Dirs[item.DirIndex]; realIndex = item.Index; } \
189 else { dir = &_proxy2->Dirs[_proxyDirIndex]; realIndex = index; }
190
GetName(UInt32 index) const191 UString CAgentFolder::GetName(UInt32 index) const
192 {
193 if (_proxy2)
194 {
195 SET_realIndex_AND_dir_2
196 return _proxy2->Files[dir->Items[realIndex]].Name;
197 }
198 SET_realIndex_AND_dir
199 if (realIndex < dir->SubDirs.Size())
200 return _proxy->Dirs[dir->SubDirs[realIndex]].Name;
201 return _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]].Name;
202 }
203
GetPrefix(UInt32 index,UString & prefix) const204 void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const
205 {
206 if (!_flatMode)
207 {
208 prefix.Empty();
209 return;
210 }
211
212 const CProxyItem &item = _items[index];
213 unsigned proxyIndex = item.DirIndex;
214
215 if (_proxy2)
216 {
217 // that code is unused. 7-Zip gets prefix via GetItemPrefix() .
218
219 unsigned len = 0;
220 while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs)
221 {
222 const CProxyFile2 &file = _proxy2->Files[(unsigned)_proxy2->Dirs[proxyIndex].ArcIndex];
223 len += file.NameLen + 1;
224 proxyIndex = (file.Parent == -1) ? 0 : (unsigned)_proxy2->Files[(unsigned)file.Parent].GetDirIndex(file.IsAltStream);
225 }
226
227 wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
228 proxyIndex = item.DirIndex;
229 while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs)
230 {
231 const CProxyFile2 &file = _proxy2->Files[(unsigned)_proxy2->Dirs[proxyIndex].ArcIndex];
232 p--;
233 *p = WCHAR_PATH_SEPARATOR;
234 p -= file.NameLen;
235 wmemcpy(p, file.Name, file.NameLen);
236 proxyIndex = (file.Parent == -1) ? 0 : (unsigned)_proxy2->Files[(unsigned)file.Parent].GetDirIndex(file.IsAltStream);
237 }
238 }
239 else
240 {
241 unsigned len = 0;
242 while (proxyIndex != _proxyDirIndex)
243 {
244 const CProxyDir *dir = &_proxy->Dirs[proxyIndex];
245 len += dir->NameLen + 1;
246 proxyIndex = (unsigned)dir->ParentDir;
247 }
248
249 wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
250 proxyIndex = item.DirIndex;
251 while (proxyIndex != _proxyDirIndex)
252 {
253 const CProxyDir *dir = &_proxy->Dirs[proxyIndex];
254 p--;
255 *p = WCHAR_PATH_SEPARATOR;
256 p -= dir->NameLen;
257 wmemcpy(p, dir->Name, dir->NameLen);
258 proxyIndex = (unsigned)dir->ParentDir;
259 }
260 }
261 }
262
GetFullPrefix(UInt32 index) const263 UString CAgentFolder::GetFullPrefix(UInt32 index) const
264 {
265 unsigned foldIndex = _proxyDirIndex;
266
267 if (_flatMode)
268 foldIndex = _items[index].DirIndex;
269
270 if (_proxy2)
271 return _proxy2->Dirs[foldIndex].PathPrefix;
272 else
273 return _proxy->GetDirPath_as_Prefix(foldIndex);
274 }
275
Z7_COM7F_IMF2(UInt64,CAgentFolder::GetItemSize (UInt32 index))276 Z7_COM7F_IMF2(UInt64, CAgentFolder::GetItemSize(UInt32 index))
277 {
278 unsigned arcIndex;
279 if (_proxy2)
280 {
281 SET_realIndex_AND_dir_2
282 arcIndex = dir->Items[realIndex];
283 const CProxyFile2 &item = _proxy2->Files[arcIndex];
284 if (item.IsDir())
285 {
286 const CProxyDir2 &itemFolder = _proxy2->Dirs[item.DirIndex];
287 if (!_flatMode)
288 return itemFolder.Size;
289 }
290 }
291 else
292 {
293 SET_realIndex_AND_dir
294 if (realIndex < dir->SubDirs.Size())
295 {
296 const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
297 if (!_flatMode)
298 return item.Size;
299 if (!item.IsLeaf())
300 return 0;
301 arcIndex = (unsigned)item.ArcIndex;
302 }
303 else
304 {
305 arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
306 }
307 }
308 NCOM::CPropVariant prop;
309 _agentSpec->GetArchive()->GetProperty(arcIndex, kpidSize, &prop);
310 if (prop.vt == VT_UI8)
311 return prop.uhVal.QuadPart;
312 else
313 return 0;
314 }
315
Z7_COM7F_IMF(CAgentFolder::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))316 Z7_COM7F_IMF(CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
317 {
318 COM_TRY_BEGIN
319 NCOM::CPropVariant prop;
320
321 if (propID == kpidPrefix)
322 {
323 if (_flatMode)
324 {
325 UString prefix;
326 GetPrefix(index, prefix);
327 prop = prefix;
328 }
329 }
330 else if (_proxy2)
331 {
332 SET_realIndex_AND_dir_2
333 unsigned arcIndex = dir->Items[realIndex];
334 const CProxyFile2 &item = _proxy2->Files[arcIndex];
335 /*
336 if (propID == kpidNumAltStreams)
337 {
338 if (item.AltDirIndex != -1)
339 prop = _proxy2->Dirs[item.AltDirIndex].Items.Size();
340 }
341 else
342 */
343 if (!item.IsDir())
344 {
345 switch (propID)
346 {
347 case kpidIsDir: prop = false; break;
348 case kpidName: prop = item.Name; break;
349 default: return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value);
350 }
351 }
352 else
353 {
354 const CProxyDir2 &itemFolder = _proxy2->Dirs[item.DirIndex];
355 if (!_flatMode && propID == kpidSize)
356 prop = itemFolder.Size;
357 else if (!_flatMode && propID == kpidPackSize)
358 prop = itemFolder.PackSize;
359 else switch (propID)
360 {
361 case kpidIsDir: prop = true; break;
362 case kpidNumSubDirs: prop = itemFolder.NumSubDirs; break;
363 case kpidNumSubFiles: prop = itemFolder.NumSubFiles; break;
364 case kpidName: prop = item.Name; break;
365 case kpidCRC:
366 {
367 // if (itemFolder.IsLeaf)
368 if (!item.Ignore)
369 {
370 RINOK(_agentSpec->GetArchive()->GetProperty(arcIndex, propID, value))
371 }
372 if (itemFolder.CrcIsDefined && value->vt == VT_EMPTY)
373 prop = itemFolder.Crc;
374 break;
375 }
376 default:
377 // if (itemFolder.IsLeaf)
378 if (!item.Ignore)
379 return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value);
380 }
381 }
382 }
383 else
384 {
385 SET_realIndex_AND_dir
386 if (realIndex < dir->SubDirs.Size())
387 {
388 const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
389 if (!_flatMode && propID == kpidSize)
390 prop = item.Size;
391 else if (!_flatMode && propID == kpidPackSize)
392 prop = item.PackSize;
393 else
394 switch (propID)
395 {
396 case kpidIsDir: prop = true; break;
397 case kpidNumSubDirs: prop = item.NumSubDirs; break;
398 case kpidNumSubFiles: prop = item.NumSubFiles; break;
399 case kpidName: prop = item.Name; break;
400 case kpidCRC:
401 {
402 if (item.IsLeaf())
403 {
404 RINOK(_agentSpec->GetArchive()->GetProperty((unsigned)item.ArcIndex, propID, value))
405 }
406 if (item.CrcIsDefined && value->vt == VT_EMPTY)
407 prop = item.Crc;
408 break;
409 }
410 default:
411 if (item.IsLeaf())
412 return _agentSpec->GetArchive()->GetProperty((unsigned)item.ArcIndex, propID, value);
413 }
414 }
415 else
416 {
417 unsigned arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
418 switch (propID)
419 {
420 case kpidIsDir: prop = false; break;
421 case kpidName: prop = _proxy->Files[arcIndex].Name; break;
422 default:
423 return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value);
424 }
425 }
426 }
427 prop.Detach(value);
428 return S_OK;
429 COM_TRY_END
430 }
431
GetUInt64Prop(IInArchive * archive,UInt32 index,PROPID propID)432 static UInt64 GetUInt64Prop(IInArchive *archive, UInt32 index, PROPID propID)
433 {
434 NCOM::CPropVariant prop;
435 if (archive->GetProperty(index, propID, &prop) != S_OK)
436 throw 111233443;
437 UInt64 v = 0;
438 if (ConvertPropVariantToUInt64(prop, v))
439 return v;
440 return 0;
441 }
442
Z7_COM7F_IMF(CAgentFolder::GetItemName (UInt32 index,const wchar_t ** name,unsigned * len))443 Z7_COM7F_IMF(CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len))
444 {
445 if (_proxy2)
446 {
447 SET_realIndex_AND_dir_2
448 unsigned arcIndex = dir->Items[realIndex];
449 const CProxyFile2 &item = _proxy2->Files[arcIndex];
450 *name = item.Name;
451 *len = item.NameLen;
452 return S_OK;
453 }
454 else
455 {
456 SET_realIndex_AND_dir
457 if (realIndex < dir->SubDirs.Size())
458 {
459 const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
460 *name = item.Name;
461 *len = item.NameLen;
462 return S_OK;
463 }
464 else
465 {
466 const CProxyFile &item = _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]];
467 *name = item.Name;
468 *len = item.NameLen;
469 return S_OK;
470 }
471 }
472 }
473
Z7_COM7F_IMF(CAgentFolder::GetItemPrefix (UInt32 index,const wchar_t ** name,unsigned * len))474 Z7_COM7F_IMF(CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len))
475 {
476 *name = NULL;
477 *len = 0;
478 if (!_flatMode)
479 return S_OK;
480
481 if (_proxy2)
482 {
483 const CProxyItem &item = _items[index];
484 const UString &s = _proxy2->Dirs[item.DirIndex].PathPrefix;
485 unsigned baseLen = _proxy2->Dirs[_proxyDirIndex].PathPrefix.Len();
486 if (baseLen <= s.Len())
487 {
488 *name = (const wchar_t *)s + baseLen;
489 *len = s.Len() - baseLen;
490 }
491 else
492 {
493 return E_FAIL;
494 // throw 111l;
495 }
496 }
497 return S_OK;
498 }
499
CompareRawProps(IArchiveGetRawProps * rawProps,unsigned arcIndex1,unsigned arcIndex2,PROPID propID)500 static int CompareRawProps(IArchiveGetRawProps *rawProps, unsigned arcIndex1, unsigned arcIndex2, PROPID propID)
501 {
502 // if (propID == kpidSha1)
503 if (rawProps)
504 {
505 const void *p1, *p2;
506 UInt32 size1, size2;
507 UInt32 propType1, propType2;
508 const HRESULT res1 = rawProps->GetRawProp(arcIndex1, propID, &p1, &size1, &propType1);
509 const HRESULT res2 = rawProps->GetRawProp(arcIndex2, propID, &p2, &size2, &propType2);
510 if (res1 == S_OK && res2 == S_OK)
511 {
512 for (UInt32 i = 0; i < size1 && i < size2; i++)
513 {
514 const Byte b1 = ((const Byte *)p1)[i];
515 const Byte b2 = ((const Byte *)p2)[i];
516 if (b1 < b2) return -1;
517 if (b1 > b2) return 1;
518 }
519 if (size1 < size2) return -1;
520 if (size1 > size2) return 1;
521 return 0;
522 }
523 }
524 return 0;
525 }
526
527 // returns pointer to extension including '.'
528
GetExtension(const wchar_t * name)529 static const wchar_t *GetExtension(const wchar_t *name)
530 {
531 for (const wchar_t *dotPtr = NULL;; name++)
532 {
533 wchar_t c = *name;
534 if (c == 0)
535 return dotPtr ? dotPtr : name;
536 if (c == '.')
537 dotPtr = name;
538 }
539 }
540
541
CompareItems3(UInt32 index1,UInt32 index2,PROPID propID)542 int CAgentFolder::CompareItems3(UInt32 index1, UInt32 index2, PROPID propID)
543 {
544 NCOM::CPropVariant prop1, prop2;
545 // Name must be first property
546 GetProperty(index1, propID, &prop1);
547 GetProperty(index2, propID, &prop2);
548 if (prop1.vt != prop2.vt)
549 return MyCompare(prop1.vt, prop2.vt);
550 if (prop1.vt == VT_BSTR)
551 return MyStringCompareNoCase(prop1.bstrVal, prop2.bstrVal);
552 return prop1.Compare(prop2);
553 }
554
555
CompareItems2(UInt32 index1,UInt32 index2,PROPID propID,Int32 propIsRaw)556 int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw)
557 {
558 unsigned realIndex1, realIndex2;
559 const CProxyDir2 *dir1, *dir2;
560
561 if (_flatMode)
562 {
563 const CProxyItem &item1 = _items[index1];
564 const CProxyItem &item2 = _items[index2];
565 dir1 = &_proxy2->Dirs[item1.DirIndex];
566 dir2 = &_proxy2->Dirs[item2.DirIndex];
567 realIndex1 = item1.Index;
568 realIndex2 = item2.Index;
569 }
570 else
571 {
572 dir2 = dir1 = &_proxy2->Dirs[_proxyDirIndex];
573 realIndex1 = index1;
574 realIndex2 = index2;
575 }
576
577 UInt32 arcIndex1;
578 UInt32 arcIndex2;
579 bool isDir1, isDir2;
580 arcIndex1 = dir1->Items[realIndex1];
581 arcIndex2 = dir2->Items[realIndex2];
582 const CProxyFile2 &prox1 = _proxy2->Files[arcIndex1];
583 const CProxyFile2 &prox2 = _proxy2->Files[arcIndex2];
584
585 if (propID == kpidName)
586 {
587 return CompareFileNames_ForFolderList(prox1.Name, prox2.Name);
588 }
589
590 if (propID == kpidPrefix)
591 {
592 if (!_flatMode)
593 return 0;
594 return CompareFileNames_ForFolderList(
595 _proxy2->Dirs[_items[index1].DirIndex].PathPrefix,
596 _proxy2->Dirs[_items[index2].DirIndex].PathPrefix);
597 }
598
599 if (propID == kpidExtension)
600 {
601 return CompareFileNames_ForFolderList(
602 GetExtension(prox1.Name),
603 GetExtension(prox2.Name));
604 }
605
606 isDir1 = prox1.IsDir();
607 isDir2 = prox2.IsDir();
608
609 if (propID == kpidIsDir)
610 {
611 if (isDir1 == isDir2)
612 return 0;
613 return isDir1 ? -1 : 1;
614 }
615
616 const CProxyDir2 *proxFolder1 = NULL;
617 const CProxyDir2 *proxFolder2 = NULL;
618 if (isDir1) proxFolder1 = &_proxy2->Dirs[prox1.DirIndex];
619 if (isDir2) proxFolder2 = &_proxy2->Dirs[prox2.DirIndex];
620
621 if (propID == kpidNumSubDirs)
622 {
623 UInt32 n1 = 0;
624 UInt32 n2 = 0;
625 if (isDir1) n1 = proxFolder1->NumSubDirs;
626 if (isDir2) n2 = proxFolder2->NumSubDirs;
627 return MyCompare(n1, n2);
628 }
629
630 if (propID == kpidNumSubFiles)
631 {
632 UInt32 n1 = 0;
633 UInt32 n2 = 0;
634 if (isDir1) n1 = proxFolder1->NumSubFiles;
635 if (isDir2) n2 = proxFolder2->NumSubFiles;
636 return MyCompare(n1, n2);
637 }
638
639 if (propID == kpidSize)
640 {
641 UInt64 n1, n2;
642 if (isDir1)
643 n1 = _flatMode ? 0 : proxFolder1->Size;
644 else
645 n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize);
646 if (isDir2)
647 n2 = _flatMode ? 0 : proxFolder2->Size;
648 else
649 n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize);
650 return MyCompare(n1, n2);
651 }
652
653 if (propID == kpidPackSize)
654 {
655 UInt64 n1, n2;
656 if (isDir1)
657 n1 = _flatMode ? 0 : proxFolder1->PackSize;
658 else
659 n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize);
660 if (isDir2)
661 n2 = _flatMode ? 0 : proxFolder2->PackSize;
662 else
663 n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize);
664 return MyCompare(n1, n2);
665 }
666
667 if (propID == kpidCRC)
668 {
669 UInt64 n1, n2;
670 if (!isDir1 || !prox1.Ignore)
671 n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC);
672 else
673 n1 = proxFolder1->Crc;
674 if (!isDir2 || !prox2.Ignore)
675 n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC);
676 else
677 n2 = proxFolder2->Crc;
678 return MyCompare(n1, n2);
679 }
680
681 if (propIsRaw)
682 return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID);
683
684 return CompareItems3(index1, index2, propID);
685 }
686
687
Z7_COM7F_IMF2(Int32,CAgentFolder::CompareItems (UInt32 index1,UInt32 index2,PROPID propID,Int32 propIsRaw))688 Z7_COM7F_IMF2(Int32, CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw))
689 {
690 try {
691 if (_proxy2)
692 return CompareItems2(index1, index2, propID, propIsRaw);
693
694 unsigned realIndex1, realIndex2;
695 const CProxyDir *dir1, *dir2;
696
697 if (_flatMode)
698 {
699 const CProxyItem &item1 = _items[index1];
700 const CProxyItem &item2 = _items[index2];
701 dir1 = &_proxy->Dirs[item1.DirIndex];
702 dir2 = &_proxy->Dirs[item2.DirIndex];
703 realIndex1 = item1.Index;
704 realIndex2 = item2.Index;
705 }
706 else
707 {
708 dir2 = dir1 = &_proxy->Dirs[_proxyDirIndex];
709 realIndex1 = index1;
710 realIndex2 = index2;
711 }
712
713 if (propID == kpidPrefix)
714 {
715 if (!_flatMode)
716 return 0;
717 UString prefix1, prefix2;
718 GetPrefix(index1, prefix1);
719 GetPrefix(index2, prefix2);
720 return CompareFileNames_ForFolderList(prefix1, prefix2);
721 }
722
723 UInt32 arcIndex1;
724 UInt32 arcIndex2;
725
726 const CProxyDir *proxFolder1 = NULL;
727 const CProxyDir *proxFolder2 = NULL;
728
729 if (realIndex1 < dir1->SubDirs.Size())
730 {
731 proxFolder1 = &_proxy->Dirs[dir1->SubDirs[realIndex1]];
732 arcIndex1 = (unsigned)proxFolder1->ArcIndex;
733 }
734 else
735 arcIndex1 = dir1->SubFiles[realIndex1 - dir1->SubDirs.Size()];
736
737 if (realIndex2 < dir2->SubDirs.Size())
738 {
739 proxFolder2 = &_proxy->Dirs[dir2->SubDirs[realIndex2]];
740 arcIndex2 = (unsigned)proxFolder2->ArcIndex;
741 }
742 else
743 arcIndex2 = dir2->SubFiles[realIndex2 - dir2->SubDirs.Size()];
744
745 if (propID == kpidName)
746 return CompareFileNames_ForFolderList(
747 proxFolder1 ? proxFolder1->Name : _proxy->Files[arcIndex1].Name,
748 proxFolder2 ? proxFolder2->Name : _proxy->Files[arcIndex2].Name);
749
750 if (propID == kpidExtension)
751 return CompareFileNames_ForFolderList(
752 GetExtension(proxFolder1 ? proxFolder1->Name : _proxy->Files[arcIndex1].Name),
753 GetExtension(proxFolder2 ? proxFolder2->Name : _proxy->Files[arcIndex2].Name));
754
755 if (propID == kpidIsDir)
756 {
757 if (proxFolder1)
758 return proxFolder2 ? 0 : -1;
759 return proxFolder2 ? 1 : 0;
760 }
761
762 if (propID == kpidNumSubDirs)
763 {
764 UInt32 n1 = 0;
765 UInt32 n2 = 0;
766 if (proxFolder1) n1 = proxFolder1->NumSubDirs;
767 if (proxFolder2) n2 = proxFolder2->NumSubDirs;
768 return MyCompare(n1, n2);
769 }
770
771 if (propID == kpidNumSubFiles)
772 {
773 UInt32 n1 = 0;
774 UInt32 n2 = 0;
775 if (proxFolder1) n1 = proxFolder1->NumSubFiles;
776 if (proxFolder2) n2 = proxFolder2->NumSubFiles;
777 return MyCompare(n1, n2);
778 }
779
780 if (propID == kpidSize)
781 {
782 UInt64 n1, n2;
783 if (proxFolder1)
784 n1 = _flatMode ? 0 : proxFolder1->Size;
785 else
786 n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize);
787 if (proxFolder2)
788 n2 = _flatMode ? 0 : proxFolder2->Size;
789 else
790 n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize);
791 return MyCompare(n1, n2);
792 }
793
794 if (propID == kpidPackSize)
795 {
796 UInt64 n1, n2;
797 if (proxFolder1)
798 n1 = _flatMode ? 0 : proxFolder1->PackSize;
799 else
800 n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize);
801 if (proxFolder2)
802 n2 = _flatMode ? 0 : proxFolder2->PackSize;
803 else
804 n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize);
805 return MyCompare(n1, n2);
806 }
807
808 if (propID == kpidCRC)
809 {
810 UInt64 n1, n2;
811 if (proxFolder1 && !proxFolder1->IsLeaf())
812 n1 = proxFolder1->Crc;
813 else
814 n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC);
815 if (proxFolder2 && !proxFolder2->IsLeaf())
816 n2 = proxFolder2->Crc;
817 else
818 n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC);
819 return MyCompare(n1, n2);
820 }
821
822 if (propIsRaw)
823 {
824 bool isVirt1 = (proxFolder1 && !proxFolder1->IsLeaf());
825 bool isVirt2 = (proxFolder2 && !proxFolder2->IsLeaf());
826 if (isVirt1)
827 return isVirt2 ? 0 : -1;
828 if (isVirt2)
829 return 1;
830 return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID);
831 }
832
833 return CompareItems3(index1, index2, propID);
834
835 } catch(...) { return 0; }
836 }
837
838
BindToFolder_Internal(unsigned proxyDirIndex,IFolderFolder ** resultFolder)839 HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder)
840 {
841 /*
842 CMyComPtr<IFolderFolder> parentFolder;
843
844 if (_proxy2)
845 {
846 const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex];
847 int par = _proxy2->GetParentFolderOfFile(dir.ArcIndex);
848 if (par != (int)_proxyDirIndex)
849 {
850 RINOK(BindToFolder_Internal(par, &parentFolder));
851 }
852 else
853 parentFolder = this;
854 }
855 else
856 {
857 const CProxyDir &dir = _proxy->Dirs[proxyDirIndex];
858 if (dir.Parent != (int)_proxyDirIndex)
859 {
860 RINOK(BindToFolder_Internal(dir.Parent, &parentFolder));
861 }
862 else
863 parentFolder = this;
864 }
865 */
866 CAgentFolder *folderSpec = new CAgentFolder;
867 CMyComPtr<IFolderFolder> agentFolder = folderSpec;
868 folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec);
869 *resultFolder = agentFolder.Detach();
870 return S_OK;
871 }
872
Z7_COM7F_IMF(CAgentFolder::BindToFolder (UInt32 index,IFolderFolder ** resultFolder))873 Z7_COM7F_IMF(CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder))
874 {
875 COM_TRY_BEGIN
876 if (_proxy2)
877 {
878 SET_realIndex_AND_dir_2
879 const unsigned arcIndex = dir->Items[realIndex];
880 const CProxyFile2 &item = _proxy2->Files[arcIndex];
881 if (!item.IsDir())
882 return E_INVALIDARG;
883 return BindToFolder_Internal((unsigned)item.DirIndex, resultFolder);
884 }
885 SET_realIndex_AND_dir
886 if (realIndex >= (UInt32)dir->SubDirs.Size())
887 return E_INVALIDARG;
888 return BindToFolder_Internal(dir->SubDirs[realIndex], resultFolder);
889 COM_TRY_END
890 }
891
Z7_COM7F_IMF(CAgentFolder::BindToFolder (const wchar_t * name,IFolderFolder ** resultFolder))892 Z7_COM7F_IMF(CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder))
893 {
894 COM_TRY_BEGIN
895 if (_proxy2)
896 {
897 const int index = _proxy2->FindItem(_proxyDirIndex, name, true);
898 if (index == -1)
899 return E_INVALIDARG;
900 return BindToFolder_Internal((unsigned)_proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]].DirIndex, resultFolder);
901 }
902 const int index = _proxy->FindSubDir(_proxyDirIndex, name);
903 if (index == -1)
904 return E_INVALIDARG;
905 return BindToFolder_Internal((unsigned)index, resultFolder);
906 COM_TRY_END
907 }
908
909
910
911 // ---------- IFolderAltStreams ----------
912
BindToAltStreams_Internal(unsigned proxyDirIndex,IFolderFolder ** resultFolder)913 HRESULT CAgentFolder::BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder)
914 {
915 *resultFolder = NULL;
916 if (!_proxy2)
917 return S_OK;
918
919 /*
920 CMyComPtr<IFolderFolder> parentFolder;
921
922 int par = _proxy2->GetParentFolderOfFile(_proxy2->Dirs[proxyDirIndex].ArcIndex);
923 if (par != (int)_proxyDirIndex)
924 {
925 RINOK(BindToFolder_Internal(par, &parentFolder));
926 if (!parentFolder)
927 return S_OK;
928 }
929 else
930 parentFolder = this;
931 */
932
933 CAgentFolder *folderSpec = new CAgentFolder;
934 CMyComPtr<IFolderFolder> agentFolder = folderSpec;
935 folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec);
936 *resultFolder = agentFolder.Detach();
937 return S_OK;
938 }
939
Z7_COM7F_IMF(CAgentFolder::BindToAltStreams (UInt32 index,IFolderFolder ** resultFolder))940 Z7_COM7F_IMF(CAgentFolder::BindToAltStreams(UInt32 index, IFolderFolder **resultFolder))
941 {
942 COM_TRY_BEGIN
943
944 *resultFolder = NULL;
945
946 if (!_proxy2)
947 return S_OK;
948
949 if (_proxy2->IsAltDir(_proxyDirIndex))
950 return S_OK;
951
952 {
953 if (index == (UInt32)(Int32)-1)
954 {
955 unsigned altDirIndex;
956 // IFolderFolder *parentFolder;
957
958 if (_proxyDirIndex == k_Proxy2_RootDirIndex)
959 {
960 altDirIndex = k_Proxy2_AltRootDirIndex;
961 // parentFolder = this; // we want to use Root dir as parent for alt root
962 }
963 else
964 {
965 const unsigned arcIndex = (unsigned)_proxy2->Dirs[_proxyDirIndex].ArcIndex;
966 const CProxyFile2 &item = _proxy2->Files[arcIndex];
967 if (item.AltDirIndex == -1)
968 return S_OK;
969 altDirIndex = (unsigned)item.AltDirIndex;
970 // parentFolder = _parentFolder;
971 }
972
973 CAgentFolder *folderSpec = new CAgentFolder;
974 CMyComPtr<IFolderFolder> agentFolder = folderSpec;
975 folderSpec->Init(_proxy, _proxy2, altDirIndex, /* parentFolder, */ _agentSpec);
976 *resultFolder = agentFolder.Detach();
977 return S_OK;
978 }
979
980 SET_realIndex_AND_dir_2
981 const unsigned arcIndex = dir->Items[realIndex];
982 const CProxyFile2 &item = _proxy2->Files[arcIndex];
983 if (item.AltDirIndex == -1)
984 return S_OK;
985 return BindToAltStreams_Internal((unsigned)item.AltDirIndex, resultFolder);
986 }
987
988 COM_TRY_END
989 }
990
Z7_COM7F_IMF(CAgentFolder::BindToAltStreams (const wchar_t * name,IFolderFolder ** resultFolder))991 Z7_COM7F_IMF(CAgentFolder::BindToAltStreams(const wchar_t *name, IFolderFolder **resultFolder))
992 {
993 COM_TRY_BEGIN
994
995 *resultFolder = NULL;
996
997 if (!_proxy2)
998 return S_OK;
999
1000 if (_proxy2->IsAltDir(_proxyDirIndex))
1001 return S_OK;
1002
1003 if (name[0] == 0)
1004 return BindToAltStreams((UInt32)(Int32)-1, resultFolder);
1005
1006 {
1007 const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
1008 FOR_VECTOR (i, dir.Items)
1009 {
1010 const CProxyFile2 &file = _proxy2->Files[dir.Items[i]];
1011 if (file.AltDirIndex != -1)
1012 if (CompareFileNames(file.Name, name) == 0)
1013 return BindToAltStreams_Internal((unsigned)file.AltDirIndex, resultFolder);
1014 }
1015 return E_INVALIDARG;
1016 }
1017 COM_TRY_END
1018 }
1019
Z7_COM7F_IMF(CAgentFolder::AreAltStreamsSupported (UInt32 index,Int32 * isSupported))1020 Z7_COM7F_IMF(CAgentFolder::AreAltStreamsSupported(UInt32 index, Int32 *isSupported))
1021 {
1022 *isSupported = BoolToInt(false);
1023
1024 if (!_proxy2)
1025 return S_OK;
1026
1027 if (_proxy2->IsAltDir(_proxyDirIndex))
1028 return S_OK;
1029
1030 unsigned arcIndex;
1031
1032 if (index == (UInt32)(Int32)-1)
1033 {
1034 if (_proxyDirIndex == k_Proxy2_RootDirIndex)
1035 {
1036 *isSupported = BoolToInt(true);
1037 return S_OK;
1038 }
1039 arcIndex = (unsigned)_proxy2->Dirs[_proxyDirIndex].ArcIndex;
1040 }
1041 else
1042 {
1043 SET_realIndex_AND_dir_2
1044 arcIndex = dir->Items[realIndex];
1045 }
1046
1047 if (_proxy2->Files[arcIndex].AltDirIndex != -1)
1048 *isSupported = BoolToInt(true);
1049 return S_OK;
1050 }
1051
1052
Z7_COM7F_IMF(CAgentFolder::BindToParentFolder (IFolderFolder ** resultFolder))1053 Z7_COM7F_IMF(CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder))
1054 {
1055 COM_TRY_BEGIN
1056 /*
1057 CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
1058 *resultFolder = parentFolder.Detach();
1059 */
1060 *resultFolder = NULL;
1061
1062 unsigned proxyDirIndex;
1063
1064 if (_proxy2)
1065 {
1066 if (_proxyDirIndex == k_Proxy2_RootDirIndex)
1067 return S_OK;
1068 if (_proxyDirIndex == k_Proxy2_AltRootDirIndex)
1069 proxyDirIndex = k_Proxy2_RootDirIndex;
1070 else
1071 {
1072 const CProxyDir2 &fold = _proxy2->Dirs[_proxyDirIndex];
1073 const CProxyFile2 &file = _proxy2->Files[(unsigned)fold.ArcIndex];
1074 const int parentIndex = file.Parent;
1075 if (parentIndex == -1)
1076 proxyDirIndex = k_Proxy2_RootDirIndex;
1077 else
1078 proxyDirIndex = (unsigned)_proxy2->Files[(unsigned)parentIndex].DirIndex;
1079 }
1080 }
1081 else
1082 {
1083 const int parent = _proxy->Dirs[_proxyDirIndex].ParentDir;
1084 if (parent == -1)
1085 return S_OK;
1086 proxyDirIndex = (unsigned)parent;
1087 }
1088
1089 CAgentFolder *folderSpec = new CAgentFolder;
1090 CMyComPtr<IFolderFolder> agentFolder = folderSpec;
1091 folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec);
1092 *resultFolder = agentFolder.Detach();
1093
1094 return S_OK;
1095 COM_TRY_END
1096 }
1097
Z7_COM7F_IMF(CAgentFolder::GetStream (UInt32 index,ISequentialInStream ** stream))1098 Z7_COM7F_IMF(CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream))
1099 {
1100 Z7_DECL_CMyComPtr_QI_FROM(
1101 IInArchiveGetStream,
1102 getStream, _agentSpec->GetArchive())
1103 if (!getStream)
1104 return S_OK;
1105
1106 UInt32 arcIndex;
1107 if (_proxy2)
1108 {
1109 SET_realIndex_AND_dir_2
1110 arcIndex = dir->Items[realIndex];
1111 }
1112 else
1113 {
1114 SET_realIndex_AND_dir
1115
1116 if (realIndex < dir->SubDirs.Size())
1117 {
1118 const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
1119 if (!item.IsLeaf())
1120 return S_OK;
1121 arcIndex = (unsigned)item.ArcIndex;
1122 }
1123 else
1124 arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
1125 }
1126 return getStream->GetStream(arcIndex, stream);
1127 }
1128
1129 // static const unsigned k_FirstOptionalProp = 2;
1130
1131 static const PROPID kProps[] =
1132 {
1133 kpidNumSubDirs,
1134 kpidNumSubFiles,
1135
1136 // kpidNumAltStreams,
1137 kpidPrefix
1138 };
1139
1140 struct CArchiveItemPropertyTemp
1141 {
1142 UString Name;
1143 PROPID ID;
1144 VARTYPE Type;
1145 };
1146
Z7_COM7F_IMF(CAgentFolder::GetNumberOfProperties (UInt32 * numProps))1147 Z7_COM7F_IMF(CAgentFolder::GetNumberOfProperties(UInt32 *numProps))
1148 {
1149 COM_TRY_BEGIN
1150 RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps))
1151 *numProps += Z7_ARRAY_SIZE(kProps);
1152 if (!_flatMode)
1153 (*numProps)--;
1154 /*
1155 if (!_agentSpec->ThereIsAltStreamProp)
1156 (*numProps)--;
1157 */
1158 /*
1159 bool thereIsPathProp = _proxy2 ?
1160 _agentSpec->_proxy2->ThereIsPathProp :
1161 _agentSpec->_proxy->ThereIsPathProp;
1162 */
1163
1164 // if there is kpidPath, we change kpidPath to kpidName
1165 // if there is no kpidPath, we add kpidName.
1166 if (!_agentSpec->ThereIsPathProp)
1167 (*numProps)++;
1168 return S_OK;
1169 COM_TRY_END
1170 }
1171
Z7_COM7F_IMF(CAgentFolder::GetPropertyInfo (UInt32 index,BSTR * name,PROPID * propID,VARTYPE * varType))1172 Z7_COM7F_IMF(CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType))
1173 {
1174 COM_TRY_BEGIN
1175 UInt32 numProps;
1176 _agentSpec->GetArchive()->GetNumberOfProperties(&numProps);
1177
1178 /*
1179 bool thereIsPathProp = _proxy2 ?
1180 _agentSpec->_proxy2->ThereIsPathProp :
1181 _agentSpec->_proxy->ThereIsPathProp;
1182 */
1183
1184 if (!_agentSpec->ThereIsPathProp)
1185 {
1186 if (index == 0)
1187 {
1188 *propID = kpidName;
1189 *varType = VT_BSTR;
1190 *name = NULL;
1191 return S_OK;
1192 }
1193 index--;
1194 }
1195
1196 if (index < numProps)
1197 {
1198 RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType))
1199 if (*propID == kpidPath)
1200 *propID = kpidName;
1201 }
1202 else
1203 {
1204 index -= numProps;
1205 /*
1206 if (index >= k_FirstOptionalProp)
1207 {
1208 if (!_agentSpec->ThereIsAltStreamProp)
1209 index++;
1210 }
1211 */
1212 *propID = kProps[index];
1213 *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID];
1214 *name = NULL;
1215 }
1216 return S_OK;
1217 COM_TRY_END
1218 }
1219
1220 static const PROPID kFolderProps[] =
1221 {
1222 kpidSize,
1223 kpidPackSize,
1224 kpidNumSubDirs,
1225 kpidNumSubFiles,
1226 kpidCRC
1227 };
1228
Z7_COM7F_IMF(CAgentFolder::GetFolderProperty (PROPID propID,PROPVARIANT * value))1229 Z7_COM7F_IMF(CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value))
1230 {
1231 COM_TRY_BEGIN
1232
1233 NWindows::NCOM::CPropVariant prop;
1234
1235 if (propID == kpidReadOnly)
1236 {
1237 if (_agentSpec->Is_Attrib_ReadOnly())
1238 prop = true;
1239 else
1240 prop = _agentSpec->IsThere_ReadOnlyArc();
1241 }
1242 else if (propID == kpidIsHash)
1243 {
1244 prop = _agentSpec->_isHashHandler;
1245 }
1246 else if (_proxy2)
1247 {
1248 const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
1249 if (propID == kpidName)
1250 {
1251 if (dir.ArcIndex != -1)
1252 prop = _proxy2->Files[(unsigned)dir.ArcIndex].Name;
1253 }
1254 else if (propID == kpidPath)
1255 {
1256 bool isAltStreamFolder = false;
1257 prop = _proxy2->GetDirPath_as_Prefix(_proxyDirIndex, isAltStreamFolder);
1258 }
1259 else switch (propID)
1260 {
1261 case kpidSize: prop = dir.Size; break;
1262 case kpidPackSize: prop = dir.PackSize; break;
1263 case kpidNumSubDirs: prop = dir.NumSubDirs; break;
1264 case kpidNumSubFiles: prop = dir.NumSubFiles; break;
1265 // case kpidName: prop = dir.Name; break;
1266 // case kpidPath: prop = _proxy2->GetFullPathPrefix(_proxyDirIndex); break;
1267 case kpidType: prop = UString("7-Zip.") + _agentSpec->ArchiveType; break;
1268 case kpidCRC: if (dir.CrcIsDefined) { prop = dir.Crc; } break;
1269 }
1270
1271 }
1272 else
1273 {
1274 const CProxyDir &dir = _proxy->Dirs[_proxyDirIndex];
1275 switch (propID)
1276 {
1277 case kpidSize: prop = dir.Size; break;
1278 case kpidPackSize: prop = dir.PackSize; break;
1279 case kpidNumSubDirs: prop = dir.NumSubDirs; break;
1280 case kpidNumSubFiles: prop = dir.NumSubFiles; break;
1281 case kpidName: prop = dir.Name; break;
1282 case kpidPath: prop = _proxy->GetDirPath_as_Prefix(_proxyDirIndex); break;
1283 case kpidType: prop = UString("7-Zip.") + _agentSpec->ArchiveType; break;
1284 case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break;
1285 }
1286 }
1287 prop.Detach(value);
1288 return S_OK;
1289 COM_TRY_END
1290 }
1291
Z7_COM7F_IMF(CAgentFolder::GetNumberOfFolderProperties (UInt32 * numProps))1292 Z7_COM7F_IMF(CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps))
1293 {
1294 *numProps = Z7_ARRAY_SIZE(kFolderProps);
1295 return S_OK;
1296 }
1297
IMP_IFolderFolder_GetProp(CAgentFolder::GetFolderPropertyInfo,kFolderProps)1298 IMP_IFolderFolder_GetProp(
1299 CAgentFolder::GetFolderPropertyInfo,
1300 kFolderProps)
1301
1302 Z7_COM7F_IMF(CAgentFolder::GetParent(UInt32 /* index */, UInt32 * /* parent */, UInt32 * /* parentType */))
1303 {
1304 return E_FAIL;
1305 }
1306
1307
Z7_COM7F_IMF(CAgentFolder::GetNumRawProps (UInt32 * numProps))1308 Z7_COM7F_IMF(CAgentFolder::GetNumRawProps(UInt32 *numProps))
1309 {
1310 IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps();
1311 if (rawProps)
1312 return rawProps->GetNumRawProps(numProps);
1313 *numProps = 0;
1314 return S_OK;
1315 }
1316
Z7_COM7F_IMF(CAgentFolder::GetRawPropInfo (UInt32 index,BSTR * name,PROPID * propID))1317 Z7_COM7F_IMF(CAgentFolder::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))
1318 {
1319 IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps();
1320 if (rawProps)
1321 return rawProps->GetRawPropInfo(index, name, propID);
1322 return E_FAIL;
1323 }
1324
Z7_COM7F_IMF(CAgentFolder::GetRawProp (UInt32 index,PROPID propID,const void ** data,UInt32 * dataSize,UInt32 * propType))1325 Z7_COM7F_IMF(CAgentFolder::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
1326 {
1327 IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps();
1328 if (rawProps)
1329 {
1330 unsigned arcIndex;
1331 if (_proxy2)
1332 {
1333 SET_realIndex_AND_dir_2
1334 arcIndex = dir->Items[realIndex];
1335 }
1336 else
1337 {
1338 SET_realIndex_AND_dir
1339 if (realIndex < dir->SubDirs.Size())
1340 {
1341 const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
1342 if (!item.IsLeaf())
1343 {
1344 *data = NULL;
1345 *dataSize = 0;
1346 *propType = 0;
1347 return S_OK;
1348 }
1349 arcIndex = (unsigned)item.ArcIndex;
1350 }
1351 else
1352 arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
1353 }
1354 return rawProps->GetRawProp(arcIndex, propID, data, dataSize, propType);
1355 }
1356 *data = NULL;
1357 *dataSize = 0;
1358 *propType = 0;
1359 return S_OK;
1360 }
1361
Z7_COM7F_IMF(CAgentFolder::GetFolderArcProps (IFolderArcProps ** object))1362 Z7_COM7F_IMF(CAgentFolder::GetFolderArcProps(IFolderArcProps **object))
1363 {
1364 CMyComPtr<IFolderArcProps> temp = _agentSpec;
1365 *object = temp.Detach();
1366 return S_OK;
1367 }
1368
1369
Z7_COM7F_IMF(CAgentFolder::SetFlatMode (Int32 flatMode))1370 Z7_COM7F_IMF(CAgentFolder::SetFlatMode(Int32 flatMode))
1371 {
1372 _flatMode = IntToBool(flatMode);
1373 return S_OK;
1374 }
1375
1376
GetRealIndex(unsigned index) const1377 int CAgentFolder::GetRealIndex(unsigned index) const
1378 {
1379 if (!_flatMode)
1380 {
1381 if (_proxy2)
1382 return (int)_proxy2->GetRealIndex(_proxyDirIndex, index);
1383 else
1384 return _proxy->GetRealIndex(_proxyDirIndex, index);
1385 }
1386 {
1387 const CProxyItem &item = _items[index];
1388 if (_proxy2)
1389 {
1390 const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex];
1391 return (int)dir->Items[item.Index];
1392 }
1393 else
1394 {
1395 const CProxyDir *dir = &_proxy->Dirs[item.DirIndex];
1396 const unsigned realIndex = item.Index;
1397 if (realIndex < dir->SubDirs.Size())
1398 {
1399 const CProxyDir &f = _proxy->Dirs[dir->SubDirs[realIndex]];
1400 if (!f.IsLeaf())
1401 return -1;
1402 return f.ArcIndex;
1403 }
1404 return (int)dir->SubFiles[realIndex - dir->SubDirs.Size()];
1405 }
1406 }
1407 }
1408
GetRealIndices(const UInt32 * indices,UInt32 numItems,bool includeAltStreams,bool includeFolderSubItemsInFlatMode,CUIntVector & realIndices) const1409 void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const
1410 {
1411 if (!_flatMode)
1412 {
1413 if (_proxy2)
1414 _proxy2->GetRealIndices(_proxyDirIndex, indices, numItems, includeAltStreams, realIndices);
1415 else
1416 _proxy->GetRealIndices(_proxyDirIndex, indices, numItems, realIndices);
1417 return;
1418 }
1419
1420 realIndices.Clear();
1421
1422 for (UInt32 i = 0; i < numItems; i++)
1423 {
1424 const CProxyItem &item = _items[indices[i]];
1425 if (_proxy2)
1426 {
1427 const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex];
1428 _proxy2->AddRealIndices_of_ArcItem(dir->Items[item.Index], includeAltStreams, realIndices);
1429 continue;
1430 }
1431 UInt32 arcIndex;
1432 {
1433 const CProxyDir *dir = &_proxy->Dirs[item.DirIndex];
1434 unsigned realIndex = item.Index;
1435 if (realIndex < dir->SubDirs.Size())
1436 {
1437 if (includeFolderSubItemsInFlatMode)
1438 {
1439 _proxy->AddRealIndices(dir->SubDirs[realIndex], realIndices);
1440 continue;
1441 }
1442 const CProxyDir &f = _proxy->Dirs[dir->SubDirs[realIndex]];
1443 if (!f.IsLeaf())
1444 continue;
1445 arcIndex = (unsigned)f.ArcIndex;
1446 }
1447 else
1448 arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
1449 }
1450 realIndices.Add(arcIndex);
1451 }
1452
1453 HeapSort(realIndices.NonConstData(), realIndices.Size());
1454 }
1455
Z7_COM7F_IMF(CAgentFolder::Extract (const UInt32 * indices,UInt32 numItems,Int32 includeAltStreams,Int32 replaceAltStreamColon,NExtract::NPathMode::EEnum pathMode,NExtract::NOverwriteMode::EEnum overwriteMode,const wchar_t * path,Int32 testMode,IFolderArchiveExtractCallback * extractCallback2))1456 Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices,
1457 UInt32 numItems,
1458 Int32 includeAltStreams,
1459 Int32 replaceAltStreamColon,
1460 NExtract::NPathMode::EEnum pathMode,
1461 NExtract::NOverwriteMode::EEnum overwriteMode,
1462 const wchar_t *path,
1463 Int32 testMode,
1464 IFolderArchiveExtractCallback *extractCallback2))
1465 {
1466 COM_TRY_BEGIN
1467
1468 if (!testMode && _agentSpec->_isHashHandler)
1469 return E_NOTIMPL;
1470
1471 CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
1472 CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
1473 UStringVector pathParts;
1474 bool isAltStreamFolder = false;
1475 if (_proxy2)
1476 _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder);
1477 else
1478 _proxy->GetDirPathParts(_proxyDirIndex, pathParts);
1479
1480 /*
1481 if (_flatMode)
1482 pathMode = NExtract::NPathMode::kNoPathnames;
1483 */
1484
1485 extractCallbackSpec->InitForMulti(
1486 false, // multiArchives
1487 pathMode,
1488 overwriteMode,
1489 _zoneMode,
1490 k_keepEmptyDirPrefixes);
1491
1492 if (extractCallback2)
1493 extractCallback2->SetTotal(_agentSpec->GetArc().GetEstmatedPhySize());
1494
1495 FString pathU;
1496 if (path)
1497 {
1498 pathU = us2fs(path);
1499 if (!pathU.IsEmpty()
1500 && !NFile::NName::IsAltStreamPrefixWithColon(path))
1501 {
1502 NFile::NName::NormalizeDirPathPrefix(pathU);
1503 NFile::NDir::CreateComplexDir(pathU);
1504 }
1505 }
1506
1507 CExtractNtOptions extractNtOptions;
1508 extractNtOptions.AltStreams.Val = IntToBool(includeAltStreams); // change it!!!
1509 extractNtOptions.AltStreams.Def = true;
1510
1511 extractNtOptions.ReplaceColonForAltStream = IntToBool(replaceAltStreamColon);
1512
1513 extractCallbackSpec->InitBeforeNewArchive();
1514
1515 #if defined(_WIN32) && !defined(UNDER_CE)
1516 if (_zoneMode != NExtract::NZoneIdMode::kNone)
1517 {
1518 ReadZoneFile_Of_BaseFile(us2fs(_agentSpec->_archiveFilePath), extractCallbackSpec->ZoneBuf);
1519 if (_zoneBuf.Size() != 0)
1520 extractCallbackSpec->ZoneBuf = _zoneBuf;
1521 }
1522 #endif
1523
1524 extractCallbackSpec->Init(
1525 extractNtOptions,
1526 NULL, &_agentSpec->GetArc(),
1527 extractCallback2,
1528 false, // stdOutMode
1529 IntToBool(testMode),
1530 pathU,
1531 pathParts, isAltStreamFolder,
1532 (UInt64)(Int64)-1);
1533
1534 if (_proxy2)
1535 extractCallbackSpec->SetBaseParentFolderIndex((unsigned)_proxy2->Dirs[_proxyDirIndex].ArcIndex);
1536
1537 // do we need another base folder for subfolders ?
1538 extractCallbackSpec->DirPathPrefix_for_HashFiles = _agentSpec->_hashBaseFolderPrefix;
1539
1540 CUIntVector realIndices;
1541 GetRealIndices(indices, numItems, IntToBool(includeAltStreams),
1542 false, // includeFolderSubItemsInFlatMode
1543 realIndices); //
1544
1545 #ifdef SUPPORT_LINKS
1546
1547 if (!testMode)
1548 {
1549 RINOK(extractCallbackSpec->PrepareHardLinks(&realIndices))
1550 }
1551
1552 #endif
1553
1554 {
1555 CArchiveExtractCallback_Closer ecsCloser(extractCallbackSpec);
1556
1557 HRESULT res = _agentSpec->GetArchive()->Extract(realIndices.ConstData(),
1558 realIndices.Size(), testMode, extractCallback);
1559
1560 const HRESULT res2 = ecsCloser.Close();
1561 if (res == S_OK)
1562 res = res2;
1563 return res;
1564 }
1565
1566 COM_TRY_END
1567 }
1568
1569 /////////////////////////////////////////
1570 // CAgent
1571
CAgent()1572 CAgent::CAgent():
1573 _proxy(NULL),
1574 _proxy2(NULL),
1575 _updatePathPrefix_is_AltFolder(false),
1576 _isDeviceFile(false),
1577 _isHashHandler(false)
1578 {
1579 }
1580
~CAgent()1581 CAgent::~CAgent()
1582 {
1583 if (_proxy)
1584 delete _proxy;
1585 if (_proxy2)
1586 delete _proxy2;
1587 }
1588
CanUpdate() const1589 bool CAgent::CanUpdate() const
1590 {
1591 // FAR plugin uses empty agent to create new archive !!!
1592 if (_archiveLink.Arcs.Size() == 0)
1593 return true;
1594 if (_isDeviceFile)
1595 return false;
1596 if (_archiveLink.Arcs.Size() != 1)
1597 return false;
1598 if (_archiveLink.Arcs[0].ErrorInfo.ThereIsTail)
1599 return false;
1600 return true;
1601 }
1602
Z7_COM7F_IMF(CAgent::Open (IInStream * inStream,const wchar_t * filePath,const wchar_t * arcFormat,BSTR * archiveType,IArchiveOpenCallback * openArchiveCallback))1603 Z7_COM7F_IMF(CAgent::Open(
1604 IInStream *inStream,
1605 const wchar_t *filePath,
1606 const wchar_t *arcFormat,
1607 BSTR *archiveType,
1608 IArchiveOpenCallback *openArchiveCallback))
1609 {
1610 COM_TRY_BEGIN
1611 _archiveFilePath = filePath;
1612 _hashBaseFolderPrefix.Empty();
1613 _attrib = 0;
1614 _isDeviceFile = false;
1615 _isHashHandler = false;
1616 NFile::NFind::CFileInfo fi;
1617 if (!inStream)
1618 {
1619 if (!fi.Find(us2fs(_archiveFilePath)))
1620 return GetLastError_noZero_HRESULT();
1621 if (fi.IsDir())
1622 return E_FAIL;
1623 _attrib = fi.Attrib;
1624 _isDeviceFile = fi.IsDevice;
1625 FString dirPrefix, fileName;
1626 if (NFile::NDir::GetFullPathAndSplit(us2fs(_archiveFilePath), dirPrefix, fileName))
1627 {
1628 NFile::NName::NormalizeDirPathPrefix(dirPrefix);
1629 _hashBaseFolderPrefix = dirPrefix;
1630 }
1631 }
1632 CArcInfoEx archiverInfo0, archiverInfo1;
1633
1634 RINOK(LoadGlobalCodecs())
1635
1636 CObjectVector<COpenType> types;
1637 if (!ParseOpenTypes(*g_CodecsObj, arcFormat, types))
1638 return S_FALSE;
1639
1640 /*
1641 CObjectVector<COptionalOpenProperties> optProps;
1642 if (Read_ShowDeleted())
1643 {
1644 COptionalOpenProperties &optPair = optProps.AddNew();
1645 optPair.FormatName = "ntfs";
1646 // optPair.Props.AddNew().Name = "LS";
1647 optPair.Props.AddNew().Name = "LD";
1648 }
1649 */
1650
1651 COpenOptions options;
1652 options.props = NULL;
1653 options.codecs = g_CodecsObj;
1654 options.types = &types;
1655 CIntVector exl;
1656 options.excludedFormats = &exl;
1657 options.stdInMode = false;
1658 options.stream = inStream;
1659 options.filePath = _archiveFilePath;
1660 options.callback = openArchiveCallback;
1661
1662 HRESULT res = _archiveLink.Open(options);
1663
1664 if (!_archiveLink.Arcs.IsEmpty())
1665 {
1666 CArc &arc = _archiveLink.Arcs.Back();
1667 if (!inStream)
1668 {
1669 arc.MTime.Set_From_FiTime(fi.MTime);
1670 arc.MTime.Def = !fi.IsDevice;
1671 }
1672
1673 ArchiveType = GetTypeOfArc(arc);
1674 if (archiveType)
1675 {
1676 RINOK(StringToBstr(ArchiveType, archiveType))
1677 }
1678
1679 if (arc.IsHashHandler(options))
1680 _isHashHandler = true;
1681 }
1682
1683 return res;
1684
1685 COM_TRY_END
1686 }
1687
1688
Z7_COM7F_IMF(CAgent::ReOpen (IArchiveOpenCallback * openArchiveCallback))1689 Z7_COM7F_IMF(CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback))
1690 {
1691 COM_TRY_BEGIN
1692 if (_proxy2)
1693 {
1694 delete _proxy2;
1695 _proxy2 = NULL;
1696 }
1697 if (_proxy)
1698 {
1699 delete _proxy;
1700 _proxy = NULL;
1701 }
1702
1703 CObjectVector<COpenType> incl;
1704 CIntVector exl;
1705
1706 COpenOptions options;
1707 options.props = NULL;
1708 options.codecs = g_CodecsObj;
1709 options.types = &incl;
1710 options.excludedFormats = &exl;
1711 options.stdInMode = false;
1712 options.filePath = _archiveFilePath;
1713 options.callback = openArchiveCallback;
1714
1715 RINOK(_archiveLink.ReOpen(options))
1716 return ReadItems();
1717 COM_TRY_END
1718 }
1719
Z7_COM7F_IMF(CAgent::Close ())1720 Z7_COM7F_IMF(CAgent::Close())
1721 {
1722 COM_TRY_BEGIN
1723 return _archiveLink.Close();
1724 COM_TRY_END
1725 }
1726
1727 /*
1728 Z7_COM7F_IMF(CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
1729 {
1730 return _archive->EnumProperties(EnumProperties);
1731 }
1732 */
1733
ReadItems()1734 HRESULT CAgent::ReadItems()
1735 {
1736 if (_proxy || _proxy2)
1737 return S_OK;
1738
1739 const CArc &arc = GetArc();
1740 bool useProxy2 = (arc.GetRawProps && arc.IsTree);
1741
1742 // useProxy2 = false;
1743
1744 if (useProxy2)
1745 _proxy2 = new CProxyArc2();
1746 else
1747 _proxy = new CProxyArc();
1748
1749 {
1750 ThereIsPathProp = false;
1751 // ThereIsAltStreamProp = false;
1752 UInt32 numProps;
1753 arc.Archive->GetNumberOfProperties(&numProps);
1754 for (UInt32 i = 0; i < numProps; i++)
1755 {
1756 CMyComBSTR name;
1757 PROPID propID;
1758 VARTYPE varType;
1759 RINOK(arc.Archive->GetPropertyInfo(i, &name, &propID, &varType))
1760 if (propID == kpidPath)
1761 ThereIsPathProp = true;
1762 /*
1763 if (propID == kpidIsAltStream)
1764 ThereIsAltStreamProp = true;
1765 */
1766 }
1767 }
1768
1769 if (_proxy2)
1770 return _proxy2->Load(GetArc(), NULL);
1771 return _proxy->Load(GetArc(), NULL);
1772 }
1773
Z7_COM7F_IMF(CAgent::BindToRootFolder (IFolderFolder ** resultFolder))1774 Z7_COM7F_IMF(CAgent::BindToRootFolder(IFolderFolder **resultFolder))
1775 {
1776 COM_TRY_BEGIN
1777 if (!_archiveLink.Arcs.IsEmpty())
1778 {
1779 RINOK(ReadItems())
1780 }
1781 CAgentFolder *folderSpec = new CAgentFolder;
1782 CMyComPtr<IFolderFolder> rootFolder = folderSpec;
1783 folderSpec->Init(_proxy, _proxy2, k_Proxy_RootDirIndex, /* NULL, */ this);
1784 *resultFolder = rootFolder.Detach();
1785 return S_OK;
1786 COM_TRY_END
1787 }
1788
Z7_COM7F_IMF(CAgent::Extract (NExtract::NPathMode::EEnum pathMode,NExtract::NOverwriteMode::EEnum overwriteMode,const wchar_t * path,Int32 testMode,IFolderArchiveExtractCallback * extractCallback2))1789 Z7_COM7F_IMF(CAgent::Extract(
1790 NExtract::NPathMode::EEnum pathMode,
1791 NExtract::NOverwriteMode::EEnum overwriteMode,
1792 const wchar_t *path,
1793 Int32 testMode,
1794 IFolderArchiveExtractCallback *extractCallback2))
1795 {
1796 COM_TRY_BEGIN
1797
1798 if (!testMode && _isHashHandler)
1799 return E_NOTIMPL;
1800
1801 CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
1802 CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
1803 extractCallbackSpec->InitForMulti(
1804 false, // multiArchives
1805 pathMode,
1806 overwriteMode,
1807 NExtract::NZoneIdMode::kNone,
1808 k_keepEmptyDirPrefixes);
1809
1810 CExtractNtOptions extractNtOptions;
1811 extractNtOptions.AltStreams.Val = true; // change it!!!
1812 extractNtOptions.AltStreams.Def = true; // change it!!!
1813 extractNtOptions.ReplaceColonForAltStream = false; // change it!!!
1814
1815 extractCallbackSpec->Init(
1816 extractNtOptions,
1817 NULL, &GetArc(),
1818 extractCallback2,
1819 false, // stdOutMode
1820 IntToBool(testMode),
1821 us2fs(path),
1822 UStringVector(), false,
1823 (UInt64)(Int64)-1);
1824
1825 extractCallbackSpec->DirPathPrefix_for_HashFiles = _hashBaseFolderPrefix;
1826
1827 #ifdef SUPPORT_LINKS
1828
1829 if (!testMode)
1830 {
1831 RINOK(extractCallbackSpec->PrepareHardLinks(NULL)) // NULL means all items
1832 }
1833
1834 #endif
1835
1836 return GetArchive()->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallback);
1837 COM_TRY_END
1838 }
1839
Z7_COM7F_IMF(CAgent::GetNumberOfProperties (UInt32 * numProps))1840 Z7_COM7F_IMF(CAgent::GetNumberOfProperties(UInt32 *numProps))
1841 {
1842 COM_TRY_BEGIN
1843 return GetArchive()->GetNumberOfProperties(numProps);
1844 COM_TRY_END
1845 }
1846
Z7_COM7F_IMF(CAgent::GetPropertyInfo (UInt32 index,BSTR * name,PROPID * propID,VARTYPE * varType))1847 Z7_COM7F_IMF(CAgent::GetPropertyInfo(UInt32 index,
1848 BSTR *name, PROPID *propID, VARTYPE *varType))
1849 {
1850 COM_TRY_BEGIN
1851 RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType))
1852 if (*propID == kpidPath)
1853 *propID = kpidName;
1854 return S_OK;
1855 COM_TRY_END
1856 }
1857
Z7_COM7F_IMF(CAgent::GetArcNumLevels (UInt32 * numLevels))1858 Z7_COM7F_IMF(CAgent::GetArcNumLevels(UInt32 *numLevels))
1859 {
1860 *numLevels = _archiveLink.Arcs.Size();
1861 return S_OK;
1862 }
1863
Z7_COM7F_IMF(CAgent::GetArcProp (UInt32 level,PROPID propID,PROPVARIANT * value))1864 Z7_COM7F_IMF(CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value))
1865 {
1866 COM_TRY_BEGIN
1867 NWindows::NCOM::CPropVariant prop;
1868 if (level > (UInt32)_archiveLink.Arcs.Size())
1869 return E_INVALIDARG;
1870 if (level == (UInt32)_archiveLink.Arcs.Size())
1871 {
1872 switch (propID)
1873 {
1874 case kpidPath:
1875 if (!_archiveLink.NonOpen_ArcPath.IsEmpty())
1876 prop = _archiveLink.NonOpen_ArcPath;
1877 break;
1878 case kpidErrorType:
1879 if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
1880 prop = g_CodecsObj->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;
1881 break;
1882 case kpidErrorFlags:
1883 {
1884 UInt32 flags = _archiveLink.NonOpen_ErrorInfo.GetErrorFlags();
1885 if (flags != 0)
1886 prop = flags;
1887 break;
1888 }
1889 case kpidWarningFlags:
1890 {
1891 UInt32 flags = _archiveLink.NonOpen_ErrorInfo.GetWarningFlags();
1892 if (flags != 0)
1893 prop = flags;
1894 break;
1895 }
1896 }
1897 }
1898 else
1899 {
1900 const CArc &arc = _archiveLink.Arcs[level];
1901 switch (propID)
1902 {
1903 case kpidType: prop = GetTypeOfArc(arc); break;
1904 case kpidPath: prop = arc.Path; break;
1905 case kpidErrorType:
1906 if (arc.ErrorInfo.ErrorFormatIndex >= 0)
1907 prop = g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name;
1908 break;
1909 case kpidErrorFlags:
1910 {
1911 const UInt32 flags = arc.ErrorInfo.GetErrorFlags();
1912 if (flags != 0)
1913 prop = flags;
1914 break;
1915 }
1916 case kpidWarningFlags:
1917 {
1918 const UInt32 flags = arc.ErrorInfo.GetWarningFlags();
1919 if (flags != 0)
1920 prop = flags;
1921 break;
1922 }
1923 case kpidOffset:
1924 {
1925 const Int64 v = arc.GetGlobalOffset();
1926 if (v != 0)
1927 prop.Set_Int64(v);
1928 break;
1929 }
1930 case kpidTailSize:
1931 {
1932 if (arc.ErrorInfo.TailSize != 0)
1933 prop = arc.ErrorInfo.TailSize;
1934 break;
1935 }
1936 default: return arc.Archive->GetArchiveProperty(propID, value);
1937 }
1938 }
1939 prop.Detach(value);
1940 return S_OK;
1941 COM_TRY_END
1942 }
1943
Z7_COM7F_IMF(CAgent::GetArcNumProps (UInt32 level,UInt32 * numProps))1944 Z7_COM7F_IMF(CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps))
1945 {
1946 return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps);
1947 }
1948
Z7_COM7F_IMF(CAgent::GetArcPropInfo (UInt32 level,UInt32 index,BSTR * name,PROPID * propID,VARTYPE * varType))1949 Z7_COM7F_IMF(CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType))
1950 {
1951 return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType);
1952 }
1953
1954 // MainItemProperty
Z7_COM7F_IMF(CAgent::GetArcProp2 (UInt32 level,PROPID propID,PROPVARIANT * value))1955 Z7_COM7F_IMF(CAgent::GetArcProp2(UInt32 level, PROPID propID, PROPVARIANT *value))
1956 {
1957 return _archiveLink.Arcs[level - 1].Archive->GetProperty(_archiveLink.Arcs[level].SubfileIndex, propID, value);
1958 }
1959
Z7_COM7F_IMF(CAgent::GetArcNumProps2 (UInt32 level,UInt32 * numProps))1960 Z7_COM7F_IMF(CAgent::GetArcNumProps2(UInt32 level, UInt32 *numProps))
1961 {
1962 return _archiveLink.Arcs[level - 1].Archive->GetNumberOfProperties(numProps);
1963 }
1964
Z7_COM7F_IMF(CAgent::GetArcPropInfo2 (UInt32 level,UInt32 index,BSTR * name,PROPID * propID,VARTYPE * varType))1965 Z7_COM7F_IMF(CAgent::GetArcPropInfo2(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType))
1966 {
1967 return _archiveLink.Arcs[level - 1].Archive->GetPropertyInfo(index, name, propID, varType);
1968 }
1969