5 #include "../../../../C/Sort.h"
\r
7 #include "Common/ComTry.h"
\r
9 #include "../Common/ArchiveExtractCallback.h"
\r
13 using namespace NWindows;
\r
15 STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
\r
17 *agentFolder = this;
\r
21 void CAgentFolder::LoadFolder(CProxyFolder *folder)
\r
25 item.Folder = folder;
\r
26 for (i = 0; i < folder->Folders.Size(); i++)
\r
30 LoadFolder(&folder->Folders[i]);
\r
32 int start = folder->Folders.Size();
\r
33 for (i = 0; i < folder->Files.Size(); i++)
\r
35 item.Index = start + i;
\r
40 STDMETHODIMP CAgentFolder::LoadItems()
\r
42 if (!_agentSpec->_archiveLink.IsOpen)
\r
46 LoadFolder(_proxyFolderItem);
\r
50 STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems)
\r
53 *numItems = _items.Size();
\r
55 *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();
\r
59 UString CAgentFolder::GetName(UInt32 index) const
\r
62 const CProxyFolder *folder;
\r
65 const CProxyItem &item = _items[index];
\r
66 folder = item.Folder;
\r
67 realIndex = item.Index;
\r
71 folder = _proxyFolderItem;
\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
80 UString CAgentFolder::GetPrefix(UInt32 index) const
\r
84 const CProxyItem &item = _items[index];
\r
85 const CProxyFolder *folder = item.Folder;
\r
87 while (folder != _proxyFolderItem)
\r
89 path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path;
\r
90 folder = folder->Parent;
\r
95 UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const
\r
97 return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);
\r
100 void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &prop) const
\r
104 prop = GetPrefix(index);
\r
108 STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
\r
110 NCOM::CPropVariant prop;
\r
111 const CProxyFolder *folder;
\r
115 const CProxyItem &item = _items[itemIndex];
\r
116 folder = item.Folder;
\r
117 realIndex = item.Index;
\r
121 folder = _proxyFolderItem;
\r
122 realIndex = itemIndex;
\r
125 if (realIndex < (UInt32)folder->Folders.Size())
\r
127 const CProxyFolder &item = folder->Folders[realIndex];
\r
128 if (!_flatMode && propID == kpidSize)
\r
130 else if (!_flatMode && propID == kpidPackSize)
\r
131 prop = item.PackSize;
\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
143 RINOK(_agentSpec->GetArchive()->GetProperty(item.Index, propID, value));
\r
145 if (item.CrcIsDefined && value->vt == VT_EMPTY)
\r
149 case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break;
\r
153 return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
\r
158 realIndex -= folder->Folders.Size();
\r
159 const CProxyFile &item = folder->Files[realIndex];
\r
162 case kpidIsDir: prop = false; break;
\r
163 case kpidName: prop = item.Name; break;
\r
164 case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break;
\r
166 return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
\r
169 prop.Detach(value);
\r
173 HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder)
\r
175 CMyComPtr<IFolderFolder> parentFolder;
\r
176 if (folder->Parent != _proxyFolderItem)
\r
178 RINOK(BindToFolder(folder->Parent, &parentFolder));
\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
189 STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
\r
193 CProxyFolder *folder;
\r
197 const CProxyItem &item = _items[index];
\r
198 folder = item.Folder;
\r
199 realIndex = item.Index;
\r
203 folder = _proxyFolderItem;
\r
206 if (realIndex >= (UInt32)folder->Folders.Size())
\r
207 return E_INVALIDARG;
\r
208 return BindToFolder(&folder->Folders[realIndex], resultFolder);
\r
212 STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
\r
215 int index = _proxyFolderItem->FindDirSubItemIndex(name);
\r
217 return E_INVALIDARG;
\r
218 return BindToFolder(index, resultFolder);
\r
222 STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)
\r
225 CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
\r
226 *resultFolder = parentFolder.Detach();
\r
231 STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)
\r
233 CMyComPtr<IInArchiveGetStream> getStream;
\r
234 _agentSpec->GetArchive()->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);
\r
238 const CProxyFolder *folder;
\r
242 const CProxyItem &item = _items[index];
\r
243 folder = item.Folder;
\r
244 realIndex = item.Index;
\r
248 folder = _proxyFolderItem;
\r
252 UInt32 indexInArchive;
\r
253 if (realIndex < (UInt32)folder->Folders.Size())
\r
255 const CProxyFolder &item = folder->Folders[realIndex];
\r
258 indexInArchive = item.Index;
\r
261 indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index;
\r
262 return getStream->GetStream(indexInArchive, stream);
\r
265 STATPROPSTG kProperties[] =
\r
267 { NULL, kpidNumSubDirs, VT_UI4},
\r
268 { NULL, kpidNumSubFiles, VT_UI4},
\r
269 { NULL, kpidPrefix, VT_BSTR}
\r
272 static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
\r
274 struct CArchiveItemPropertyTemp
\r
281 STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)
\r
284 RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps));
\r
285 *numProps += kNumProperties;
\r
288 if (!_agentSpec->_proxyArchive->ThereIsPathProp)
\r
294 STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
\r
298 _agentSpec->GetArchive()->GetNumberOfProperties(&numProps);
\r
299 if (!_agentSpec->_proxyArchive->ThereIsPathProp)
\r
303 *propID = kpidName;
\r
304 *varType = VT_BSTR;
\r
311 if (index < numProps)
\r
313 RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
\r
314 if (*propID == kpidPath)
\r
315 *propID = kpidName;
\r
319 const STATPROPSTG &srcItem = kProperties[index - numProps];
\r
320 *propID = srcItem.propid;
\r
321 *varType = srcItem.vt;
\r
328 STATPROPSTG kFolderProps[] =
\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
337 static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]);
\r
339 STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
\r
342 NWindows::NCOM::CPropVariant prop;
\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
354 prop.Detach(value);
\r
359 STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps)
\r
361 *numProps = kNumFolderProps;
\r
365 STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
\r
367 // if (index < kNumFolderProps)
\r
369 const STATPROPSTG &srcItem = kFolderProps[index];
\r
370 *propID = srcItem.propid;
\r
371 *varType = srcItem.vt;
\r
377 STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object)
\r
379 CMyComPtr<IFolderArcProps> temp = _agentSpec;
\r
380 *object = temp.Detach();
\r
384 #ifdef NEW_FOLDER_INTERFACE
\r
386 STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)
\r
388 _flatMode = IntToBool(flatMode);
\r
394 void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
\r
398 _proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
\r
401 realIndices.Clear();
\r
402 for(UInt32 i = 0; i < numItems; i++)
\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
409 realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);
\r
411 HeapSort(&realIndices.Front(), realIndices.Size());
\r
414 STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
\r
416 NExtract::NPathMode::EEnum pathMode,
\r
417 NExtract::NOverwriteMode::EEnum overwriteMode,
\r
418 const wchar_t *path,
\r
420 IFolderArchiveExtractCallback *extractCallback2)
\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
429 pathParts.Insert(0, currentProxyFolder->Name);
\r
430 currentProxyFolder = currentProxyFolder->Parent;
\r
435 pathMode = NExtract::NPathMode::kNoPathnames;
\r
438 extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);
\r
440 extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(),
\r
442 false, testMode ? true : false, false,
\r
443 (path ? path : L""),
\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
453 /////////////////////////////////////////
\r
457 _proxyArchive(NULL),
\r
464 if (_proxyArchive != NULL)
\r
465 delete _proxyArchive;
\r
468 STDMETHODIMP CAgent::Open(
\r
469 IInStream *inStream,
\r
470 const wchar_t *filePath,
\r
471 const wchar_t *arcFormat,
\r
473 IArchiveOpenCallback *openArchiveCallback)
\r
476 _archiveFilePath = filePath;
\r
477 NFile::NFind::CFileInfoW fi;
\r
480 if (!fi.Find(_archiveFilePath))
\r
481 return ::GetLastError();
\r
485 CArcInfoEx archiverInfo0, archiverInfo1;
\r
487 _compressCodecsInfo.Release();
\r
488 _codecs = new CCodecs;
\r
489 _compressCodecsInfo = _codecs;
\r
490 RINOK(_codecs->Load());
\r
492 CIntVector formatIndices;
\r
493 if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices))
\r
496 RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback));
\r
498 CArc &arc = _archiveLink.Arcs.Back();
\r
501 arc.MTimeDefined = !fi.IsDevice;
\r
502 arc.MTime = fi.MTime;
\r
505 ArchiveType = _codecs->Formats[arc.FormatIndex].Name;
\r
506 if (archiveType == 0)
\r
508 return StringToBstr(ArchiveType, archiveType);
\r
512 STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback)
\r
515 if (_proxyArchive != NULL)
\r
517 delete _proxyArchive;
\r
518 _proxyArchive = NULL;
\r
520 RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback));
\r
521 return ReadItems();
\r
525 STDMETHODIMP CAgent::Close()
\r
528 return _archiveLink.Close();
\r
533 STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
\r
535 return _archive->EnumProperties(EnumProperties);
\r
539 HRESULT CAgent::ReadItems()
\r
541 if (_proxyArchive != NULL)
\r
543 _proxyArchive = new CProxyArchive();
\r
544 return _proxyArchive->Load(GetArc(), NULL);
\r
547 STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
\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
560 STDMETHODIMP CAgent::Extract(
\r
561 NExtract::NPathMode::EEnum pathMode,
\r
562 NExtract::NOverwriteMode::EEnum overwriteMode,
\r
563 const wchar_t *path,
\r
565 IFolderArchiveExtractCallback *extractCallback2)
\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
573 false, testMode ? true : false, false,
\r
576 (UInt64)(Int64)-1);
\r
577 return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);
\r
581 STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProps)
\r
584 return GetArchive()->GetNumberOfProperties(numProps);
\r
588 STDMETHODIMP CAgent::GetPropertyInfo(UInt32 index,
\r
589 BSTR *name, PROPID *propID, VARTYPE *varType)
\r
592 RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType));
\r
593 if (*propID == kpidPath)
\r
594 *propID = kpidName;
\r
599 STDMETHODIMP CAgent::GetArcNumLevels(UInt32 *numLevels)
\r
601 *numLevels = _archiveLink.Arcs.Size();
\r
605 STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)
\r
608 NWindows::NCOM::CPropVariant prop;
\r
609 CArc &arc = _archiveLink.Arcs[level];
\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
616 prop.Detach(value);
\r
621 STDMETHODIMP CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps)
\r
623 return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps);
\r
626 STDMETHODIMP CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
\r
628 return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType);
\r
631 // MainItemProperty
\r
632 STDMETHODIMP CAgent::GetArcProp2(UInt32 level, PROPID propID, PROPVARIANT *value)
\r
634 return _archiveLink.Arcs[level - 1].Archive->GetProperty(_archiveLink.Arcs[level].SubfileIndex, propID, value);
\r
637 STDMETHODIMP CAgent::GetArcNumProps2(UInt32 level, UInt32 *numProps)
\r
639 return _archiveLink.Arcs[level - 1].Archive->GetNumberOfProperties(numProps);
\r
642 STDMETHODIMP CAgent::GetArcPropInfo2(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
\r
644 return _archiveLink.Arcs[level - 1].Archive->GetPropertyInfo(index, name, propID, varType);
\r