Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / Agent / Agent.cpp
1 // Agent.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "../../../../C/Sort.h"\r
6 \r
7 #include "Common/ComTry.h"\r
8 \r
9 #include "../Common/ArchiveExtractCallback.h"\r
10 \r
11 #include "Agent.h"\r
12 \r
13 using namespace NWindows;\r
14 \r
15 STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)\r
16 {\r
17   *agentFolder = this;\r
18   return S_OK;\r
19 }\r
20 \r
21 void CAgentFolder::LoadFolder(CProxyFolder *folder)\r
22 {\r
23   int i;\r
24   CProxyItem item;\r
25   item.Folder = folder;\r
26   for (i = 0; i < folder->Folders.Size(); i++)\r
27   {\r
28     item.Index = i;\r
29     _items.Add(item);\r
30     LoadFolder(&folder->Folders[i]);\r
31   }\r
32   int start = folder->Folders.Size();\r
33   for (i = 0; i < folder->Files.Size(); i++)\r
34   {\r
35     item.Index = start + i;\r
36     _items.Add(item);\r
37   }\r
38 }\r
39 \r
40 STDMETHODIMP CAgentFolder::LoadItems()\r
41 {\r
42   if (!_agentSpec->_archiveLink.IsOpen)\r
43     return E_FAIL;\r
44   _items.Clear();\r
45   if (_flatMode)\r
46     LoadFolder(_proxyFolderItem);\r
47   return S_OK;\r
48 }\r
49 \r
50 STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems)\r
51 {\r
52   if (_flatMode)\r
53     *numItems = _items.Size();\r
54   else\r
55     *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();\r
56   return S_OK;\r
57 }\r
58 \r
59 UString CAgentFolder::GetName(UInt32 index) const\r
60 {\r
61   UInt32 realIndex;\r
62   const CProxyFolder *folder;\r
63   if (_flatMode)\r
64   {\r
65     const CProxyItem &item = _items[index];\r
66     folder = item.Folder;\r
67     realIndex = item.Index;\r
68   }\r
69   else\r
70   {\r
71     folder = _proxyFolderItem;\r
72     realIndex = index;\r
73   }\r
74 \r
75   if (realIndex < (UInt32)folder->Folders.Size())\r
76     return folder->Folders[realIndex].Name;\r
77   return folder->Files[realIndex - folder->Folders.Size()].Name;\r
78 }\r
79 \r
80 UString CAgentFolder::GetPrefix(UInt32 index) const\r
81 {\r
82   if (!_flatMode)\r
83     return UString();\r
84   const CProxyItem &item = _items[index];\r
85   const CProxyFolder *folder = item.Folder;\r
86   UString path;\r
87   while (folder != _proxyFolderItem)\r
88   {\r
89     path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path;\r
90     folder = folder->Parent;\r
91   }\r
92   return path;\r
93 }\r
94 \r
95 UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const\r
96 {\r
97   return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);\r
98 }\r
99 \r
100 void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &prop) const\r
101 {\r
102   if (!_flatMode)\r
103     return;\r
104   prop = GetPrefix(index);\r
105 }\r
106 \r
107 \r
108 STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)\r
109 {\r
110   NCOM::CPropVariant prop;\r
111   const CProxyFolder *folder;\r
112   UInt32 realIndex;\r
113   if (_flatMode)\r
114   {\r
115     const CProxyItem &item = _items[itemIndex];\r
116     folder = item.Folder;\r
117     realIndex = item.Index;\r
118   }\r
119   else\r
120   {\r
121     folder = _proxyFolderItem;\r
122     realIndex = itemIndex;\r
123   }\r
124 \r
125   if (realIndex < (UInt32)folder->Folders.Size())\r
126   {\r
127     const CProxyFolder &item = folder->Folders[realIndex];\r
128     if (!_flatMode && propID == kpidSize)\r
129       prop = item.Size;\r
130     else if (!_flatMode && propID == kpidPackSize)\r
131       prop = item.PackSize;\r
132     else\r
133     switch(propID)\r
134     {\r
135       case kpidIsDir:      prop = true; break;\r
136       case kpidNumSubDirs: prop = item.NumSubFolders; break;\r
137       case kpidNumSubFiles:   prop = item.NumSubFiles; break;\r
138       case kpidName:          prop = item.Name; break;\r
139       case kpidCRC:\r
140       {\r
141         if (item.IsLeaf)\r
142         {\r
143           RINOK(_agentSpec->GetArchive()->GetProperty(item.Index, propID, value));\r
144         }\r
145         if (item.CrcIsDefined && value->vt == VT_EMPTY)\r
146           prop = item.Crc;\r
147         break;\r
148       }\r
149       case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break;\r
150 \r
151       default:\r
152         if (item.IsLeaf)\r
153           return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);\r
154     }\r
155   }\r
156   else\r
157   {\r
158     realIndex -= folder->Folders.Size();\r
159     const CProxyFile &item = folder->Files[realIndex];\r
160     switch(propID)\r
161     {\r
162       case kpidIsDir: prop = false; break;\r
163       case kpidName: prop = item.Name; break;\r
164       case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break;\r
165       default:\r
166         return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);\r
167     }\r
168   }\r
169   prop.Detach(value);\r
170   return S_OK;\r
171 }\r
172 \r
173 HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder)\r
174 {\r
175   CMyComPtr<IFolderFolder> parentFolder;\r
176   if (folder->Parent != _proxyFolderItem)\r
177   {\r
178     RINOK(BindToFolder(folder->Parent, &parentFolder));\r
179   }\r
180   else\r
181     parentFolder = this;\r
182   CAgentFolder *folderSpec = new CAgentFolder;\r
183   CMyComPtr<IFolderFolder> agentFolder = folderSpec;\r
184   folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec);\r
185   *resultFolder = agentFolder.Detach();\r
186   return S_OK;\r
187 }\r
188 \r
189 STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)\r
190 {\r
191   COM_TRY_BEGIN\r
192 \r
193   CProxyFolder *folder;\r
194   UInt32 realIndex;\r
195   if (_flatMode)\r
196   {\r
197     const CProxyItem &item = _items[index];\r
198     folder = item.Folder;\r
199     realIndex = item.Index;\r
200   }\r
201   else\r
202   {\r
203     folder = _proxyFolderItem;\r
204     realIndex = index;\r
205   }\r
206   if (realIndex >= (UInt32)folder->Folders.Size())\r
207     return E_INVALIDARG;\r
208   return BindToFolder(&folder->Folders[realIndex], resultFolder);\r
209   COM_TRY_END\r
210 }\r
211 \r
212 STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)\r
213 {\r
214   COM_TRY_BEGIN\r
215   int index = _proxyFolderItem->FindDirSubItemIndex(name);\r
216   if (index < 0)\r
217     return E_INVALIDARG;\r
218   return BindToFolder(index, resultFolder);\r
219   COM_TRY_END\r
220 }\r
221 \r
222 STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)\r
223 {\r
224   COM_TRY_BEGIN\r
225   CMyComPtr<IFolderFolder> parentFolder = _parentFolder;\r
226   *resultFolder = parentFolder.Detach();\r
227   return S_OK;\r
228   COM_TRY_END\r
229 }\r
230 \r
231 STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)\r
232 {\r
233   CMyComPtr<IInArchiveGetStream> getStream;\r
234   _agentSpec->GetArchive()->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);\r
235   if (!getStream)\r
236     return S_OK;\r
237 \r
238   const CProxyFolder *folder;\r
239   UInt32 realIndex;\r
240   if (_flatMode)\r
241   {\r
242     const CProxyItem &item = _items[index];\r
243     folder = item.Folder;\r
244     realIndex = item.Index;\r
245   }\r
246   else\r
247   {\r
248     folder = _proxyFolderItem;\r
249     realIndex = index;\r
250   }\r
251 \r
252   UInt32 indexInArchive;\r
253   if (realIndex < (UInt32)folder->Folders.Size())\r
254   {\r
255     const CProxyFolder &item = folder->Folders[realIndex];\r
256     if (!item.IsLeaf)\r
257       return S_OK;\r
258     indexInArchive = item.Index;\r
259   }\r
260   else\r
261     indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index;\r
262   return getStream->GetStream(indexInArchive, stream);\r
263 }\r
264 \r
265 STATPROPSTG kProperties[] =\r
266 {\r
267   { NULL, kpidNumSubDirs, VT_UI4},\r
268   { NULL, kpidNumSubFiles, VT_UI4},\r
269   { NULL, kpidPrefix, VT_BSTR}\r
270 };\r
271 \r
272 static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);\r
273 \r
274 struct CArchiveItemPropertyTemp\r
275 {\r
276   UString Name;\r
277   PROPID ID;\r
278   VARTYPE Type;\r
279 };\r
280 \r
281 STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)\r
282 {\r
283   COM_TRY_BEGIN\r
284   RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps));\r
285   *numProps += kNumProperties;\r
286   if (!_flatMode)\r
287     (*numProps)--;\r
288   if (!_agentSpec->_proxyArchive->ThereIsPathProp)\r
289     (*numProps)++;\r
290   return S_OK;\r
291   COM_TRY_END\r
292 }\r
293 \r
294 STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
295 {\r
296   COM_TRY_BEGIN\r
297   UInt32 numProps;\r
298   _agentSpec->GetArchive()->GetNumberOfProperties(&numProps);\r
299   if (!_agentSpec->_proxyArchive->ThereIsPathProp)\r
300   {\r
301     if (index == 0)\r
302     {\r
303       *propID = kpidName;\r
304       *varType = VT_BSTR;\r
305       *name = 0;\r
306       return S_OK;\r
307     }\r
308     index--;\r
309   }\r
310 \r
311   if (index < numProps)\r
312   {\r
313     RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));\r
314     if (*propID == kpidPath)\r
315       *propID = kpidName;\r
316   }\r
317   else\r
318   {\r
319     const STATPROPSTG &srcItem = kProperties[index - numProps];\r
320     *propID = srcItem.propid;\r
321     *varType = srcItem.vt;\r
322     *name = 0;\r
323   }\r
324   return S_OK;\r
325   COM_TRY_END\r
326 }\r
327 \r
328 STATPROPSTG kFolderProps[] =\r
329 {\r
330   { NULL, kpidSize, VT_UI8},\r
331   { NULL, kpidPackSize, VT_UI8},\r
332   { NULL, kpidNumSubDirs, VT_UI4},\r
333   { NULL, kpidNumSubFiles, VT_UI4},\r
334   { NULL, kpidCRC, VT_UI4}\r
335 };\r
336 \r
337 static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]);\r
338 \r
339 STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)\r
340 {\r
341   COM_TRY_BEGIN\r
342   NWindows::NCOM::CPropVariant prop;\r
343   switch(propID)\r
344   {\r
345     case kpidSize:         prop = _proxyFolderItem->Size; break;\r
346     case kpidPackSize:     prop = _proxyFolderItem->PackSize; break;\r
347     case kpidNumSubDirs:   prop = _proxyFolderItem->NumSubFolders; break;\r
348     case kpidNumSubFiles:  prop = _proxyFolderItem->NumSubFiles; break;\r
349     case kpidName:         prop = _proxyFolderItem->Name; break;\r
350     case kpidPath:         prop = _proxyFolderItem->GetFullPathPrefix(); break;\r
351     case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break;\r
352     case kpidCRC: if (_proxyFolderItem->CrcIsDefined) prop = _proxyFolderItem->Crc; break;\r
353   }\r
354   prop.Detach(value);\r
355   return S_OK;\r
356   COM_TRY_END\r
357 }\r
358 \r
359 STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps)\r
360 {\r
361   *numProps = kNumFolderProps;\r
362   return S_OK;\r
363 }\r
364 \r
365 STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
366 {\r
367   // if (index < kNumFolderProps)\r
368   {\r
369     const STATPROPSTG &srcItem = kFolderProps[index];\r
370     *propID = srcItem.propid;\r
371     *varType = srcItem.vt;\r
372     *name = 0;\r
373     return S_OK;\r
374   }\r
375 }\r
376 \r
377 STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object)\r
378 {\r
379   CMyComPtr<IFolderArcProps> temp = _agentSpec;\r
380   *object = temp.Detach();\r
381   return S_OK;\r
382 }\r
383 \r
384 #ifdef NEW_FOLDER_INTERFACE\r
385 \r
386 STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)\r
387 {\r
388   _flatMode = IntToBool(flatMode);\r
389   return S_OK;\r
390 }\r
391 \r
392 #endif\r
393 \r
394 void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const\r
395 {\r
396   if (!_flatMode)\r
397   {\r
398     _proxyFolderItem->GetRealIndices(indices, numItems, realIndices);\r
399     return;\r
400   }\r
401   realIndices.Clear();\r
402   for(UInt32 i = 0; i < numItems; i++)\r
403   {\r
404     const CProxyItem &item = _items[indices[i]];\r
405     const CProxyFolder *folder = item.Folder;\r
406     UInt32 realIndex = item.Index;\r
407     if (realIndex < (UInt32)folder->Folders.Size())\r
408       continue;\r
409     realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);\r
410   }\r
411   HeapSort(&realIndices.Front(), realIndices.Size());\r
412 }\r
413 \r
414 STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,\r
415     UInt32 numItems,\r
416     NExtract::NPathMode::EEnum pathMode,\r
417     NExtract::NOverwriteMode::EEnum overwriteMode,\r
418     const wchar_t *path,\r
419     Int32 testMode,\r
420     IFolderArchiveExtractCallback *extractCallback2)\r
421 {\r
422   COM_TRY_BEGIN\r
423   CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;\r
424   CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\r
425   UStringVector pathParts;\r
426   CProxyFolder *currentProxyFolder = _proxyFolderItem;\r
427   while (currentProxyFolder->Parent)\r
428   {\r
429     pathParts.Insert(0, currentProxyFolder->Name);\r
430     currentProxyFolder = currentProxyFolder->Parent;\r
431   }\r
432   \r
433   /*\r
434   if (_flatMode)\r
435     pathMode = NExtract::NPathMode::kNoPathnames;\r
436   */\r
437 \r
438   extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);\r
439 \r
440   extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(),\r
441       extractCallback2,\r
442       false, testMode ? true : false, false,\r
443       (path ? path : L""),\r
444       pathParts,\r
445       (UInt64)(Int64)-1);\r
446   CUIntVector realIndices;\r
447   GetRealIndices(indices, numItems, realIndices);\r
448   return _agentSpec->GetArchive()->Extract(&realIndices.Front(),\r
449       realIndices.Size(), testMode, extractCallback);\r
450   COM_TRY_END\r
451 }\r
452 \r
453 /////////////////////////////////////////\r
454 // CAgent\r
455 \r
456 CAgent::CAgent():\r
457   _proxyArchive(NULL),\r
458   _codecs(0)\r
459 {\r
460 }\r
461 \r
462 CAgent::~CAgent()\r
463 {\r
464   if (_proxyArchive != NULL)\r
465     delete _proxyArchive;\r
466 }\r
467 \r
468 STDMETHODIMP CAgent::Open(\r
469     IInStream *inStream,\r
470     const wchar_t *filePath,\r
471     const wchar_t *arcFormat,\r
472     BSTR *archiveType,\r
473     IArchiveOpenCallback *openArchiveCallback)\r
474 {\r
475   COM_TRY_BEGIN\r
476   _archiveFilePath = filePath;\r
477   NFile::NFind::CFileInfoW fi;\r
478   if (!inStream)\r
479   {\r
480     if (!fi.Find(_archiveFilePath))\r
481       return ::GetLastError();\r
482     if (fi.IsDir())\r
483       return E_FAIL;\r
484   }\r
485   CArcInfoEx archiverInfo0, archiverInfo1;\r
486 \r
487   _compressCodecsInfo.Release();\r
488   _codecs = new CCodecs;\r
489   _compressCodecsInfo = _codecs;\r
490   RINOK(_codecs->Load());\r
491 \r
492   CIntVector formatIndices;\r
493   if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices))\r
494     return S_FALSE;\r
495 \r
496   RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback));\r
497 \r
498   CArc &arc = _archiveLink.Arcs.Back();\r
499   if (!inStream)\r
500   {\r
501     arc.MTimeDefined = !fi.IsDevice;\r
502     arc.MTime = fi.MTime;\r
503   }\r
504 \r
505   ArchiveType = _codecs->Formats[arc.FormatIndex].Name;\r
506   if (archiveType == 0)\r
507     return S_OK;\r
508   return StringToBstr(ArchiveType, archiveType);\r
509   COM_TRY_END\r
510 }\r
511 \r
512 STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback)\r
513 {\r
514   COM_TRY_BEGIN\r
515   if (_proxyArchive != NULL)\r
516   {\r
517     delete _proxyArchive;\r
518     _proxyArchive = NULL;\r
519   }\r
520   RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback));\r
521   return ReadItems();\r
522   COM_TRY_END\r
523 }\r
524 \r
525 STDMETHODIMP CAgent::Close()\r
526 {\r
527   COM_TRY_BEGIN\r
528   return _archiveLink.Close();\r
529   COM_TRY_END\r
530 }\r
531 \r
532 /*\r
533 STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)\r
534 {\r
535   return _archive->EnumProperties(EnumProperties);\r
536 }\r
537 */\r
538 \r
539 HRESULT CAgent::ReadItems()\r
540 {\r
541   if (_proxyArchive != NULL)\r
542     return S_OK;\r
543   _proxyArchive = new CProxyArchive();\r
544   return _proxyArchive->Load(GetArc(), NULL);\r
545 }\r
546 \r
547 STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)\r
548 {\r
549   COM_TRY_BEGIN\r
550   RINOK(ReadItems());\r
551   CAgentFolder *folderSpec = new CAgentFolder;\r
552   CMyComPtr<IFolderFolder> rootFolder = folderSpec;\r
553   folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this);\r
554   *resultFolder = rootFolder.Detach();\r
555   return S_OK;\r
556   COM_TRY_END\r
557 }\r
558 \r
559 \r
560 STDMETHODIMP CAgent::Extract(\r
561     NExtract::NPathMode::EEnum pathMode,\r
562     NExtract::NOverwriteMode::EEnum overwriteMode,\r
563     const wchar_t *path,\r
564     Int32 testMode,\r
565     IFolderArchiveExtractCallback *extractCallback2)\r
566 {\r
567   COM_TRY_BEGIN\r
568   CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;\r
569   CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\r
570   extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);\r
571   extractCallbackSpec->Init(NULL, &GetArc(),\r
572       extractCallback2,\r
573       false, testMode ? true : false, false,\r
574       path,\r
575       UStringVector(),\r
576       (UInt64)(Int64)-1);\r
577   return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);\r
578   COM_TRY_END\r
579 }\r
580 \r
581 STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProps)\r
582 {\r
583   COM_TRY_BEGIN\r
584   return GetArchive()->GetNumberOfProperties(numProps);\r
585   COM_TRY_END\r
586 }\r
587 \r
588 STDMETHODIMP CAgent::GetPropertyInfo(UInt32 index,\r
589       BSTR *name, PROPID *propID, VARTYPE *varType)\r
590 {\r
591   COM_TRY_BEGIN\r
592   RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType));\r
593   if (*propID == kpidPath)\r
594     *propID = kpidName;\r
595   return S_OK;\r
596   COM_TRY_END\r
597 }\r
598 \r
599 STDMETHODIMP CAgent::GetArcNumLevels(UInt32 *numLevels)\r
600 {\r
601   *numLevels = _archiveLink.Arcs.Size();\r
602   return S_OK;\r
603 }\r
604 \r
605 STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)\r
606 {\r
607   COM_TRY_BEGIN\r
608   NWindows::NCOM::CPropVariant prop;\r
609   CArc &arc = _archiveLink.Arcs[level];\r
610   switch(propID)\r
611   {\r
612     case kpidType: prop = GetTypeOfArc(arc); break;\r
613     case kpidPath: prop = arc.Path; break;\r
614     default: return arc.Archive->GetArchiveProperty(propID, value);\r
615   }\r
616   prop.Detach(value);\r
617   return S_OK;\r
618   COM_TRY_END\r
619 }\r
620 \r
621 STDMETHODIMP CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps)\r
622 {\r
623   return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps);\r
624 }\r
625 \r
626 STDMETHODIMP CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
627 {\r
628   return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType);\r
629 }\r
630 \r
631 // MainItemProperty\r
632 STDMETHODIMP CAgent::GetArcProp2(UInt32 level, PROPID propID, PROPVARIANT *value)\r
633 {\r
634   return _archiveLink.Arcs[level - 1].Archive->GetProperty(_archiveLink.Arcs[level].SubfileIndex, propID, value);\r
635 }\r
636 \r
637 STDMETHODIMP CAgent::GetArcNumProps2(UInt32 level, UInt32 *numProps)\r
638 {\r
639   return _archiveLink.Arcs[level - 1].Archive->GetNumberOfProperties(numProps);\r
640 }\r
641 \r
642 STDMETHODIMP CAgent::GetArcPropInfo2(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
643 {\r
644   return _archiveLink.Arcs[level - 1].Archive->GetPropertyInfo(index, name, propID, varType);\r
645 }\r