diff options
Diffstat (limited to 'CPP/7zip/UI/Agent/Agent.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/Agent.cpp | 1184 |
1 files changed, 1080 insertions, 104 deletions
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index c11bd490..e4f46f0a 100755..100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -4,9 +4,12 @@ #include "../../../../C/Sort.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" + +#include "../../../Windows/PropVariantConv.h" #include "../Common/ArchiveExtractCallback.h" +#include "../FileManager/RegistryUtils.h" #include "Agent.h" @@ -18,19 +21,37 @@ STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder) return S_OK; } -void CAgentFolder::LoadFolder(const CProxyFolder *folder) +void CAgentFolder::LoadFolder(unsigned proxyFolderIndex) { - int i; + unsigned i; CProxyItem item; - item.Folder = folder; - for (i = 0; i < folder->Folders.Size(); i++) + item.ProxyFolderIndex = proxyFolderIndex; + if (_proxyArchive2) + { + const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex]; + for (i = 0; i < folder.SubFiles.Size(); i++) + { + item.Index = i; + _items.Add(item); + const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]]; + int subFolderIndex = file.FolderIndex; + if (subFolderIndex >= 0) + LoadFolder(subFolderIndex); + subFolderIndex = file.AltStreamsFolderIndex; + if (subFolderIndex >= 0) + LoadFolder(subFolderIndex); + } + return; + } + const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex]; + for (i = 0; i < folder.Folders.Size(); i++) { item.Index = i; _items.Add(item); - LoadFolder(&folder->Folders[i]); + LoadFolder(folder.Folders[i]); } - int start = folder->Folders.Size(); - for (i = 0; i < folder->Files.Size(); i++) + unsigned start = folder.Folders.Size(); + for (i = 0; i < folder.Files.Size(); i++) { item.Index = start + i; _items.Add(item); @@ -51,58 +72,210 @@ STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems) { if (_flatMode) *numItems = _items.Size(); + else if (_proxyArchive2) + *numItems = _proxyArchive2->Folders[_proxyFolderItem].SubFiles.Size(); else - *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size(); + { + const CProxyFolder *folder = &_proxyArchive->Folders[_proxyFolderItem]; + *numItems = folder->Folders.Size() + folder ->Files.Size(); + } return S_OK; } #define SET_realIndex_AND_folder \ UInt32 realIndex; const CProxyFolder *folder; \ - if (_flatMode) { const CProxyItem &item = _items[index]; folder = item.Folder; realIndex = item.Index; } \ - else { folder = _proxyFolderItem; realIndex = index; } + if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \ + else { folder = &_proxyArchive->Folders[_proxyFolderItem]; realIndex = index; } +#define SET_realIndex_AND_folder_2 \ + UInt32 realIndex; const CProxyFolder2 *folder; \ + if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \ + else { folder = &_proxyArchive2->Folders[_proxyFolderItem]; realIndex = index; } UString CAgentFolder::GetName(UInt32 index) const { + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + return _proxyArchive2->Files[folder->SubFiles[realIndex]].Name; + } SET_realIndex_AND_folder if (realIndex < (UInt32)folder->Folders.Size()) - return folder->Folders[realIndex].Name; + return _proxyArchive->Folders[folder->Folders[realIndex]].Name; return folder->Files[realIndex - folder->Folders.Size()].Name; } -UString CAgentFolder::GetPrefix(UInt32 index) const +void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const { if (!_flatMode) - return UString(); + { + prefix.Empty(); + return; + } const CProxyItem &item = _items[index]; - const CProxyFolder *folder = item.Folder; - UString path; - while (folder != _proxyFolderItem) + unsigned proxyIndex = item.ProxyFolderIndex; + unsigned totalLen; + if (_proxyArchive2) { - path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path; - folder = folder->Parent; + unsigned len = 0; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex]; + len += file.NameSize + 1; + proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream); + } + totalLen = len; + + wchar_t *p = prefix.GetBuffer(len); + proxyIndex = item.ProxyFolderIndex; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex]; + MyStringCopy(p + len - file.NameSize - 1, file.Name); + p[--len] = WCHAR_PATH_SEPARATOR; + len -= file.NameSize; + proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream); + } + } + else + { + unsigned len = 0; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex]; + len += folder->Name.Len() + 1; + proxyIndex = folder->Parent; + } + totalLen = len; + + wchar_t *p = prefix.GetBuffer(len); + proxyIndex = item.ProxyFolderIndex; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex]; + MyStringCopy(p + len - folder->Name.Len() - 1, (const wchar_t *)folder->Name); + p[--len] = WCHAR_PATH_SEPARATOR; + len -= folder->Name.Len(); + proxyIndex = folder->Parent; + } } - return path; + prefix.ReleaseBuffer(totalLen); } UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const { - return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index); + UString prefix; + GetPrefix(index, prefix); + if (_proxyArchive2) + return _proxyArchive2->GetFullPathPrefix(_proxyFolderItem) + prefix; + else + return _proxyArchive->GetFullPathPrefix(_proxyFolderItem) + prefix; +} + +STDMETHODIMP_(UInt64) CAgentFolder::GetItemSize(UInt32 index) +{ + unsigned arcIndex; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (item.IsDir()) + { + const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex]; + if (!_flatMode) + return itemFolder.Size; + } + } + else + { + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!_flatMode) + return item.Size; + arcIndex = item.Index; + } + else + { + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + arcIndex = item.Index; + } + } + NCOM::CPropVariant prop; + _agentSpec->GetArchive()->GetProperty(arcIndex, kpidSize, &prop); + if (prop.vt == VT_UI8) + return prop.uhVal.QuadPart; + else + return 0; } STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - SET_realIndex_AND_folder + if (propID == kpidPrefix) { if (_flatMode) - prop = GetPrefix(index); + { + UString prefix; + GetPrefix(index, prefix); + prop = prefix; + } + } + else if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (!item.IsDir()) + { + switch (propID) + { + case kpidIsDir: prop = false; break; + case kpidName: prop = item.Name; break; + default: return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value); + } + } + else + { + const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex]; + if (!_flatMode && propID == kpidSize) + prop = itemFolder.Size; + else if (!_flatMode && propID == kpidPackSize) + prop = itemFolder.PackSize; + else switch (propID) + { + case kpidIsDir: prop = true; break; + case kpidNumSubDirs: prop = itemFolder.NumSubFolders; break; + case kpidNumSubFiles: prop = itemFolder.NumSubFiles; break; + case kpidName: prop = item.Name; break; + case kpidCRC: + { + // if (itemFolder.IsLeaf) + if (!item.Ignore) + { + RINOK(_agentSpec->GetArchive()->GetProperty(arcIndex, propID, value)); + } + if (itemFolder.CrcIsDefined && value->vt == VT_EMPTY) + prop = itemFolder.Crc; + break; + } + default: + // if (itemFolder.IsLeaf) + if (!item.Ignore) + return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value); + } + } } - else if (realIndex < (UInt32)folder->Folders.Size()) + else { - const CProxyFolder &item = folder->Folders[realIndex]; + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; if (!_flatMode && propID == kpidSize) prop = item.Size; else if (!_flatMode && propID == kpidPackSize) @@ -140,23 +313,457 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); } } + } prop.Detach(value); return S_OK; COM_TRY_END } -HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder) +static UInt64 GetUInt64Prop(IInArchive *archive, UInt32 index, PROPID propID) +{ + NCOM::CPropVariant prop; + if (archive->GetProperty(index, propID, &prop) != S_OK) + throw 111233443; + UInt64 v = 0; + if (ConvertPropVariantToUInt64(prop, v)) + return v; + return 0; +} + +STDMETHODIMP CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len) +{ + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + *name = item.Name; + *len = item.NameSize; + return S_OK; + } + else + { + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + *name = item.Name; + *len = item.Name.Len(); + return S_OK; + } + else + { + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + *name = item.Name; + *len = item.Name.Len(); + return S_OK; + } + } +} + +STDMETHODIMP CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len) +{ + *name = 0; + *len = 0; + if (!_flatMode) + return S_OK; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (item.Parent >= 0) + { + const CProxyFile2 &item2 = _proxyArchive2->Files[item.Parent]; + int foldInd = item2.GetFolderIndex(item.IsAltStream); + if (foldInd >= 0) + { + const UString &s = _proxyArchive2->Folders[foldInd].PathPrefix; + unsigned baseLen = _proxyArchive2->Folders[_proxyFolderItem].PathPrefix.Len(); + if (baseLen <= s.Len()) + { + *name = (const wchar_t *)s + baseLen; + *len = s.Len() - baseLen; + } + } + } + } + return S_OK; +} + +static int CompareRawProps(IArchiveGetRawProps *rawProps, int arcIndex1, int arcIndex2, PROPID propID) +{ + // if (propID == kpidSha1) + if (rawProps) + { + const void *p1, *p2; + UInt32 size1, size2; + UInt32 propType1, propType2; + HRESULT res1 = rawProps->GetRawProp(arcIndex1, propID, &p1, &size1, &propType1); + HRESULT res2 = rawProps->GetRawProp(arcIndex2, propID, &p2, &size2, &propType2); + if (res1 == S_OK && res2 == S_OK) + { + for (UInt32 i = 0; i < size1 && i < size2; i++) + { + Byte b1 = ((const Byte *)p1)[i]; + Byte b2 = ((const Byte *)p2)[i]; + if (b1 < b2) return -1; + if (b1 > b2) return 1; + } + if (size1 < size2) return -1; + if (size1 > size2) return 1; + return 0; + } + } + return 0; +} + +// returns pointer to extension including '.' + +static const wchar_t *GetExtension(const wchar_t *name) +{ + for (const wchar_t *dotPtr = NULL;; name++) + { + wchar_t c = *name; + if (c == 0) + return dotPtr ? dotPtr : name; + if (c == '.') + dotPtr = name; + } +} + +int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) +{ + UInt32 realIndex1, realIndex2; + const CProxyFolder2 *folder1, *folder2; + + if (_flatMode) + { + const CProxyItem &item1 = _items[index1]; + const CProxyItem &item2 = _items[index2]; + folder1 = &_proxyArchive2->Folders[item1.ProxyFolderIndex]; + folder2 = &_proxyArchive2->Folders[item2.ProxyFolderIndex]; + realIndex1 = item1.Index; + realIndex2 = item2.Index; + } + else + { + folder2 = folder1 = &_proxyArchive2->Folders[_proxyFolderItem]; + realIndex1 = index1; + realIndex2 = index2; + } + + UInt32 arcIndex1; + UInt32 arcIndex2; + bool isDir1, isDir2; + arcIndex1 = folder1->SubFiles[realIndex1]; + arcIndex2 = folder2->SubFiles[realIndex2]; + const CProxyFile2 &prox1 = _proxyArchive2->Files[arcIndex1]; + const CProxyFile2 &prox2 = _proxyArchive2->Files[arcIndex2]; + + if (propID == kpidName) + { + return CompareFileNames_ForFolderList(prox1.Name, prox2.Name); + } + + if (propID == kpidPrefix) + { + if (!_flatMode) + return 0; + if (prox1.Parent < 0) return prox2.Parent < 0 ? 0 : -1; + if (prox2.Parent < 0) return 1; + + const CProxyFile2 &proxPar1 = _proxyArchive2->Files[prox1.Parent]; + const CProxyFile2 &proxPar2 = _proxyArchive2->Files[prox2.Parent]; + return CompareFileNames_ForFolderList( + _proxyArchive2->Folders[proxPar1.GetFolderIndex(prox1.IsAltStream)].PathPrefix, + _proxyArchive2->Folders[proxPar2.GetFolderIndex(prox2.IsAltStream)].PathPrefix); + } + + if (propID == kpidExtension) + { + return CompareFileNames_ForFolderList( + GetExtension(prox1.Name), + GetExtension(prox2.Name)); + } + + isDir1 = prox1.IsDir(); + isDir2 = prox2.IsDir(); + + if (propID == kpidIsDir) + { + if (isDir1 == isDir2) + return 0; + return isDir1 ? -1 : 1; + } + + const CProxyFolder2 *proxFolder1 = NULL; + const CProxyFolder2 *proxFolder2 = NULL; + if (isDir1) proxFolder1 = &_proxyArchive2->Folders[prox1.FolderIndex]; + if (isDir2) proxFolder2 = &_proxyArchive2->Folders[prox2.FolderIndex]; + + if (propID == kpidNumSubDirs) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFolders; + if (isDir2) n2 = proxFolder2->NumSubFolders; + return MyCompare(n1, n2); + } + + if (propID == kpidNumSubFiles) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFiles; + if (isDir2) n2 = proxFolder2->NumSubFiles; + return MyCompare(n1, n2); + } + + if (propID == kpidSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->Size; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->Size; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize); + return MyCompare(n1, n2); + } + + if (propID == kpidPackSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->PackSize; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->PackSize; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize); + return MyCompare(n1, n2); + } + + if (propID == kpidCRC) + { + UInt64 n1, n2; + if (!isDir1 || !prox1.Ignore) + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC); + else + n1 = proxFolder1->Crc; + if (!isDir2 || !prox2.Ignore) + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC); + else + n2 = proxFolder2->Crc; + return MyCompare(n1, n2); + } + + if (propIsRaw) + return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID); + + NCOM::CPropVariant prop1, prop2; + // Name must be first property + GetProperty(index1, propID, &prop1); + GetProperty(index2, propID, &prop2); + if (prop1.vt != prop2.vt) + { + return MyCompare(prop1.vt, prop2.vt); + } + if (prop1.vt == VT_BSTR) + { + return _wcsicmp(prop1.bstrVal, prop2.bstrVal); + } + return prop1.Compare(prop2); +} + +STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) +{ + COM_TRY_BEGIN + if (_proxyArchive2) + return CompareItems2(index1, index2, propID, propIsRaw); + UInt32 realIndex1, realIndex2; + const CProxyFolder *folder1, *folder2; + + if (_flatMode) + { + const CProxyItem &item1 = _items[index1]; + const CProxyItem &item2 = _items[index2]; + folder1 = &_proxyArchive->Folders[item1.ProxyFolderIndex]; + folder2 = &_proxyArchive->Folders[item2.ProxyFolderIndex]; + realIndex1 = item1.Index; + realIndex2 = item2.Index; + } + else + { + folder2 = folder1 = &_proxyArchive->Folders[_proxyFolderItem]; + realIndex1 = index1; + realIndex2 = index2; + } + if (propID == kpidPrefix) + { + if (!_flatMode) + return 0; + UString prefix1, prefix2; + GetPrefix(index1, prefix1); + GetPrefix(index2, prefix2); + return CompareFileNames_ForFolderList(prefix1, prefix2); + } + const CProxyFile *prox1; + const CProxyFile *prox2; + const CProxyFolder *proxFolder1 = NULL; + const CProxyFolder *proxFolder2 = NULL; + bool isDir1, isDir2; + if (realIndex1 < (UInt32)folder1->Folders.Size()) + { + isDir1 = true; + prox1 = proxFolder1 = &_proxyArchive->Folders[folder1->Folders[realIndex1]]; + } + else + { + isDir1 = false; + prox1 = &folder1->Files[realIndex1 - folder1->Folders.Size()]; + } + + if (realIndex2 < (UInt32)folder2->Folders.Size()) + { + isDir2 = true; + prox2 = proxFolder2 = &_proxyArchive->Folders[folder2->Folders[realIndex2]]; + } + else + { + isDir2 = false; + prox2 = &folder2->Files[realIndex2 - folder2->Folders.Size()]; + } + + if (propID == kpidName) + { + return CompareFileNames_ForFolderList(prox1->Name, prox2->Name); + } + if (propID == kpidExtension) + { + return CompareFileNames_ForFolderList( + GetExtension(prox1->Name), + GetExtension(prox2->Name)); + } + + if (propID == kpidIsDir) + { + if (isDir1 == isDir2) + return 0; + return isDir1 ? -1 : 1; + } + if (propID == kpidNumSubDirs) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFolders; + if (isDir2) n2 = proxFolder2->NumSubFolders; + return MyCompare(n1, n2); + } + if (propID == kpidNumSubFiles) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFiles; + if (isDir2) n2 = proxFolder2->NumSubFiles; + return MyCompare(n1, n2); + } + if (propID == kpidSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->Size; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->Size; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidSize); + return MyCompare(n1, n2); + } + if (propID == kpidPackSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->PackSize; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidPackSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->PackSize; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidPackSize); + return MyCompare(n1, n2); + } + + if (propID == kpidCRC) + { + UInt64 n1, n2; + if (!isDir1 || proxFolder1->IsLeaf) + n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidCRC); + else + n1 = proxFolder1->Crc; + if (!isDir2 || proxFolder2->IsLeaf) + n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidCRC); + else + n2 = proxFolder2->Crc; + return MyCompare(n1, n2); + } + + if (propIsRaw) + return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), prox1->Index, prox2->Index, propID); + + NCOM::CPropVariant prop1, prop2; + // Name must be first property + GetProperty(index1, propID, &prop1); + GetProperty(index2, propID, &prop2); + if (prop1.vt != prop2.vt) + { + return MyCompare(prop1.vt, prop2.vt); + } + if (prop1.vt == VT_BSTR) + { + return _wcsicmp(prop1.bstrVal, prop2.bstrVal); + } + return prop1.Compare(prop2); + + COM_TRY_END +} + +HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder) { CMyComPtr<IFolderFolder> parentFolder; - if (folder->Parent != _proxyFolderItem) + + if (_proxyArchive2) { - RINOK(BindToFolder(folder->Parent, &parentFolder)); + parentFolder = NULL; // Change it; + const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex]; + int par = _proxyArchive2->GetParentFolderOfFile(folder.ArcIndex); + if (par != (int)_proxyFolderItem) + { + // return E_FAIL; + RINOK(BindToFolder_Internal(par, &parentFolder)); + } + else + parentFolder = this; } else - parentFolder = this; + { + const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex]; + if (folder.Parent != (int)_proxyFolderItem) + { + RINOK(BindToFolder_Internal(folder.Parent, &parentFolder)); + } + else + parentFolder = this; + } CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr<IFolderFolder> agentFolder = folderSpec; - folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec); + folderSpec->Init(_proxyArchive, _proxyArchive2, proxyFolderIndex, parentFolder, _agentSpec); *resultFolder = agentFolder.Detach(); return S_OK; } @@ -164,30 +771,51 @@ HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **r STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) { COM_TRY_BEGIN + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (!item.IsDir()) + return E_INVALIDARG; + return BindToFolder_Internal(item.FolderIndex, resultFolder); + } SET_realIndex_AND_folder if (realIndex >= (UInt32)folder->Folders.Size()) return E_INVALIDARG; - return BindToFolder(&folder->Folders[realIndex], resultFolder); + return BindToFolder_Internal(folder->Folders[realIndex], resultFolder); COM_TRY_END } STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) { COM_TRY_BEGIN - int index = _proxyFolderItem->FindDirSubItemIndex(name); + if (_proxyArchive2) + { + const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem]; + FOR_VECTOR (i, folder.SubFiles) + { + const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]]; + if (file.FolderIndex >= 0) + if (StringsAreEqualNoCase(file.Name, name)) + return BindToFolder_Internal(file.FolderIndex, resultFolder); + } + return E_INVALIDARG; + } + int index = _proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name); if (index < 0) return E_INVALIDARG; - return BindToFolder(index, resultFolder); + return BindToFolder_Internal(index, resultFolder); COM_TRY_END } STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder) { - COM_TRY_BEGIN + // COM_TRY_BEGIN CMyComPtr<IFolderFolder> parentFolder = _parentFolder; *resultFolder = parentFolder.Detach(); return S_OK; - COM_TRY_END + // COM_TRY_END } STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) @@ -197,30 +825,36 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) if (!getStream) return S_OK; + UInt32 indexInArchive; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + indexInArchive = folder->SubFiles[realIndex]; + } + else + { SET_realIndex_AND_folder - UInt32 indexInArchive; if (realIndex < (UInt32)folder->Folders.Size()) { - const CProxyFolder &item = folder->Folders[realIndex]; + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; if (!item.IsLeaf) return S_OK; indexInArchive = item.Index; } else indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index; + } return getStream->GetStream(indexInArchive, stream); } -static const STATPROPSTG kProperties[] = +static const PROPID kProps[] = { - { NULL, kpidNumSubDirs, VT_UI4}, - { NULL, kpidNumSubFiles, VT_UI4}, - { NULL, kpidPrefix, VT_BSTR} + kpidNumSubDirs, + kpidNumSubFiles, + kpidPrefix }; -static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]); - struct CArchiveItemPropertyTemp { UString Name; @@ -232,10 +866,18 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps) { COM_TRY_BEGIN RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps)); - *numProps += kNumProperties; + *numProps += ARRAY_SIZE(kProps); if (!_flatMode) (*numProps)--; - if (!_agentSpec->_proxyArchive->ThereIsPathProp) + /* + bool thereIsPathProp = _proxyArchive2 ? + _agentSpec->_proxyArchive2->ThereIsPathProp : + _agentSpec->_proxyArchive->ThereIsPathProp; + */ + + // if there is kpidPath, we change kpidPath to kpidName + // if there is no kpidPath, we add kpidName. + if (!_agentSpec->ThereIsPathProp) (*numProps)++; return S_OK; COM_TRY_END @@ -246,7 +888,14 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro COM_TRY_BEGIN UInt32 numProps; _agentSpec->GetArchive()->GetNumberOfProperties(&numProps); - if (!_agentSpec->_proxyArchive->ThereIsPathProp) + + /* + bool thereIsPathProp = _proxyArchive2 ? + _agentSpec->_proxyArchive2->ThereIsPathProp : + _agentSpec->_proxyArchive->ThereIsPathProp; + */ + + if (!_agentSpec->ThereIsPathProp) { if (index == 0) { @@ -266,40 +915,68 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro } else { - const STATPROPSTG &srcItem = kProperties[index - numProps]; - *propID = srcItem.propid; - *varType = srcItem.vt; + *propID = kProps[index - numProps]; + *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; } return S_OK; COM_TRY_END } -static const STATPROPSTG kFolderProps[] = +static const PROPID kFolderProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidNumSubDirs, VT_UI4}, - { NULL, kpidNumSubFiles, VT_UI4}, - { NULL, kpidCRC, VT_UI4} + kpidSize, + kpidPackSize, + kpidNumSubDirs, + kpidNumSubFiles, + kpidCRC }; -static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]); - STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + if (_proxyArchive2) + { + const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem]; + if (propID == kpidName) + { + if (folder.ArcIndex >= 0) + prop = _proxyArchive2->Files[folder.ArcIndex].Name; + } + else if (propID == kpidPath) + { + prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); + } + else switch (propID) + { + case kpidSize: prop = folder.Size; break; + case kpidPackSize: prop = folder.PackSize; break; + case kpidNumSubDirs: prop = folder.NumSubFolders; break; + case kpidNumSubFiles: prop = folder.NumSubFiles; break; + // case kpidName: prop = folder.Name; break; + // case kpidPath: prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); break; + case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; + case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break; + } + + } + else + { + const CProxyFolder &folder = _proxyArchive->Folders[_proxyFolderItem]; switch (propID) { - case kpidSize: prop = _proxyFolderItem->Size; break; - case kpidPackSize: prop = _proxyFolderItem->PackSize; break; - case kpidNumSubDirs: prop = _proxyFolderItem->NumSubFolders; break; - case kpidNumSubFiles: prop = _proxyFolderItem->NumSubFiles; break; - case kpidName: prop = _proxyFolderItem->Name; break; - case kpidPath: prop = _proxyFolderItem->GetFullPathPrefix(); break; + case kpidSize: prop = folder.Size; break; + case kpidPackSize: prop = folder.PackSize; break; + case kpidNumSubDirs: prop = folder.NumSubFolders; break; + case kpidNumSubFiles: prop = folder.NumSubFiles; break; + case kpidName: prop = folder.Name; break; + case kpidPath: prop = _proxyArchive->GetFullPathPrefix(_proxyFolderItem); break; case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; - case kpidCRC: if (_proxyFolderItem->CrcIsDefined) prop = _proxyFolderItem->Crc; break; + case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break; + } } prop.Detach(value); return S_OK; @@ -308,20 +985,73 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps) { - *numProps = kNumFolderProps; + *numProps = ARRAY_SIZE(kFolderProps); return S_OK; } -STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +STDMETHODIMP CAgentFolder::GetFolderPropertyInfo IMP_IFolderFolder_GetProp(kFolderProps) + +STDMETHODIMP CAgentFolder::GetParent(UInt32 /* index */, UInt32 * /* parent */, UInt32 * /* parentType */) { - // if (index < kNumFolderProps) + return E_FAIL; +} + + +STDMETHODIMP CAgentFolder::GetNumRawProps(UInt32 *numProps) +{ + IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps(); + if (rawProps) + return rawProps->GetNumRawProps(numProps); + *numProps = 0; + return S_OK; +} + +STDMETHODIMP CAgentFolder::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) +{ + IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps(); + if (rawProps) + return rawProps->GetRawPropInfo(index, name, propID); + return E_FAIL; +} + +STDMETHODIMP CAgentFolder::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps(); + if (rawProps) { - const STATPROPSTG &srcItem = kFolderProps[index]; - *propID = srcItem.propid; - *varType = srcItem.vt; - *name = 0; - return S_OK; + unsigned arcIndex; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + arcIndex = folder->SubFiles[realIndex]; + } + else + { + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!item.IsLeaf) + { + *data = NULL; + *dataSize = 0; + *propType = 0; + return S_OK; + } + arcIndex = item.Index; + } + else + { + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + arcIndex = item.Index; + } + } + return rawProps->GetRawProp(arcIndex, propID, data, dataSize, propType); } + *data = NULL; + *dataSize = 0; + *propType = 0; + return S_OK; } STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object) @@ -341,28 +1071,86 @@ STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode) #endif -void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +int CAgentFolder::GetRealIndex(unsigned index) const { if (!_flatMode) { - _proxyFolderItem->GetRealIndices(indices, numItems, realIndices); + if (_proxyArchive2) + return _proxyArchive2->GetRealIndex(_proxyFolderItem, index); + else + return _proxyArchive->GetRealIndex(_proxyFolderItem, index); + } + { + const CProxyItem &item = _items[index]; + if (_proxyArchive2) + { + const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; + return folder->SubFiles[item.Index]; + } + else + { + const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; + unsigned realIndex = item.Index; + if (realIndex < folder->Folders.Size()) + { + const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!f.IsLeaf) + return -1; + return f.Index; + } + return folder->Files[realIndex - folder->Folders.Size()].Index; + } + } +} + +void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const +{ + if (!_flatMode) + { + if (_proxyArchive2) + _proxyArchive2->GetRealIndices(_proxyFolderItem, indices, numItems, includeAltStreams, realIndices); + else + _proxyArchive->GetRealIndices(_proxyFolderItem, indices, numItems, realIndices); return; } realIndices.Clear(); for (UInt32 i = 0; i < numItems; i++) { const CProxyItem &item = _items[indices[i]]; - const CProxyFolder *folder = item.Folder; - UInt32 realIndex = item.Index; - if (realIndex < (UInt32)folder->Folders.Size()) + if (_proxyArchive2) + { + const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; + _proxyArchive2->AddRealIndices_of_ArcItem(folder->SubFiles[item.Index], includeAltStreams, realIndices); continue; - realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index); + } + UInt32 arcIndex; + { + const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; + unsigned realIndex = item.Index; + if (realIndex < folder->Folders.Size()) + { + if (includeFolderSubItemsInFlatMode) + { + _proxyArchive->AddRealIndices(folder->Folders[realIndex], realIndices); + continue; + } + const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!f.IsLeaf) + continue; + arcIndex = f.Index; + } + else + arcIndex = folder->Files[realIndex - folder->Folders.Size()].Index; + } + realIndices.Add(arcIndex); } HeapSort(&realIndices.Front(), realIndices.Size()); } STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, UInt32 numItems, + Int32 includeAltStreams, + Int32 replaceAltStreamColon, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, @@ -373,7 +1161,10 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UStringVector pathParts; - _proxyFolderItem->GetPathParts(pathParts); + if (_proxyArchive2) + _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts); + else + _proxyArchive->GetPathParts(_proxyFolderItem, pathParts); /* if (_flatMode) @@ -385,16 +1176,45 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, FString pathU; if (path) pathU = us2fs(path); - extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), + + CExtractNtOptions extractNtOptions; + extractNtOptions.AltStreams.Val = IntToBool(includeAltStreams); // change it!!! + extractNtOptions.AltStreams.Def = true; + + extractNtOptions.ReplaceColonForAltStream = IntToBool(replaceAltStreamColon); + + extractCallbackSpec->Init( + extractNtOptions, + NULL, &_agentSpec->GetArc(), extractCallback2, - false, testMode ? true : false, false, + false, // stdOutMode + IntToBool(testMode), path ? pathU : FTEXT(""), pathParts, (UInt64)(Int64)-1); + + if (_proxyArchive2) + extractCallbackSpec->SetBaseParentFolderIndex(_proxyArchive2->Folders[_proxyFolderItem].ArcIndex); + CUIntVector realIndices; - GetRealIndices(indices, numItems, realIndices); - return _agentSpec->GetArchive()->Extract(&realIndices.Front(), + GetRealIndices(indices, numItems, IntToBool(includeAltStreams), + false, // includeFolderSubItemsInFlatMode + realIndices); // + + #ifdef SUPPORT_LINKS + + if (!testMode) + { + RINOK(extractCallbackSpec->PrepareHardLinks(&realIndices)); + } + + #endif + + HRESULT result = _agentSpec->GetArchive()->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallback); + if (result == S_OK) + result = extractCallbackSpec->SetDirsTimes(); + return result; COM_TRY_END } @@ -403,14 +1223,32 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CAgent::CAgent(): _proxyArchive(NULL), + _proxyArchive2(NULL), + _isDeviceFile(false), _codecs(0) { } CAgent::~CAgent() { - if (_proxyArchive != NULL) + if (_proxyArchive) delete _proxyArchive; + if (_proxyArchive2) + delete _proxyArchive2; +} + +bool CAgent::CanUpdate() const +{ + // FAR plugin uses empty agent to create new archive !!! + if (_archiveLink.Arcs.Size() == 0) + return true; + if (_isDeviceFile) + return false; + if (_archiveLink.Arcs.Size() != 1) + return false; + if (_archiveLink.Arcs[0].ErrorInfo.ThereIsTail) + return false; + return true; } STDMETHODIMP CAgent::Open( @@ -423,12 +1261,14 @@ STDMETHODIMP CAgent::Open( COM_TRY_BEGIN _archiveFilePath = filePath; NFile::NFind::CFileInfo fi; + _isDeviceFile = false; if (!inStream) { if (!fi.Find(us2fs(_archiveFilePath))) return ::GetLastError(); if (fi.IsDir()) return E_FAIL; + _isDeviceFile = fi.IsDevice; } CArcInfoEx archiverInfo0, archiverInfo1; @@ -437,11 +1277,33 @@ STDMETHODIMP CAgent::Open( _compressCodecsInfo = _codecs; RINOK(_codecs->Load()); - CIntVector formatIndices; - if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices)) + CObjectVector<COpenType> types; + if (!ParseOpenTypes(*_codecs, arcFormat, types)) return S_FALSE; - RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback)); + /* + CObjectVector<COptionalOpenProperties> optProps; + if (Read_ShowDeleted()) + { + COptionalOpenProperties &optPair = optProps.AddNew(); + optPair.FormatName = L"ntfs"; + // optPair.Props.AddNew().Name = L"LS"; + optPair.Props.AddNew().Name = L"LD"; + } + */ + + COpenOptions options; + options.props = NULL; + options.codecs = _codecs; + options.types = &types; + CIntVector exl; + options.excludedFormats = &exl; + options.stdInMode = false; + options.stream = inStream; + options.filePath = _archiveFilePath; + options.callback = openArchiveCallback; + + RINOK(_archiveLink.Open(options)); CArc &arc = _archiveLink.Arcs.Back(); if (!inStream) @@ -450,22 +1312,42 @@ STDMETHODIMP CAgent::Open( arc.MTime = fi.MTime; } - ArchiveType = _codecs->Formats[arc.FormatIndex].Name; - if (archiveType == 0) - return S_OK; - return StringToBstr(ArchiveType, archiveType); + ArchiveType = GetTypeOfArc(arc); + if (archiveType) + { + RINOK(StringToBstr(ArchiveType, archiveType)); + } + return S_OK; COM_TRY_END } STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN - if (_proxyArchive != NULL) + if (_proxyArchive2) + { + delete _proxyArchive2; + _proxyArchive2 = NULL; + } + if (_proxyArchive) { delete _proxyArchive; _proxyArchive = NULL; } - RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback)); + + CObjectVector<COpenType> incl; + CIntVector exl; + + COpenOptions options; + options.props = NULL; + options.codecs = _codecs; + options.types = &incl; + options.excludedFormats = &exl; + options.stdInMode = false; + options.filePath = _archiveFilePath; + options.callback = openArchiveCallback; + + RINOK(_archiveLink.ReOpen(options)); return ReadItems(); COM_TRY_END } @@ -486,9 +1368,38 @@ STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties) HRESULT CAgent::ReadItems() { - if (_proxyArchive != NULL) + if (_proxyArchive || _proxyArchive2) return S_OK; - _proxyArchive = new CProxyArchive(); + + const CArc &arc = GetArc(); + bool useProxy2 = (arc.GetRawProps && arc.IsTree); + // useProxy2 = false; + + if (useProxy2) + _proxyArchive2 = new CProxyArchive2(); + else + _proxyArchive = new CProxyArchive(); + + { + ThereIsPathProp = false; + UInt32 numProps; + arc.Archive->GetNumberOfProperties(&numProps); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + RINOK(arc.Archive->GetPropertyInfo(i, &name, &propID, &varType)); + if (propID == kpidPath) + { + ThereIsPathProp = true; + break; + } + } + } + + if (_proxyArchive2) + return _proxyArchive2->Load(GetArc(), NULL); return _proxyArchive->Load(GetArc(), NULL); } @@ -498,13 +1409,12 @@ STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) RINOK(ReadItems()); CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr<IFolderFolder> rootFolder = folderSpec; - folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this); + folderSpec->Init(_proxyArchive, _proxyArchive2, 0, NULL, this); *resultFolder = rootFolder.Detach(); return S_OK; COM_TRY_END } - STDMETHODIMP CAgent::Extract( NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, @@ -516,12 +1426,31 @@ STDMETHODIMP CAgent::Extract( CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); - extractCallbackSpec->Init(NULL, &GetArc(), + + CExtractNtOptions extractNtOptions; + extractNtOptions.AltStreams.Val = true; // change it!!! + extractNtOptions.AltStreams.Def = true; // change it!!! + extractNtOptions.ReplaceColonForAltStream = false; // change it!!! + + extractCallbackSpec->Init( + extractNtOptions, + NULL, &GetArc(), extractCallback2, - false, testMode ? true : false, false, + false, // stdOutMode + IntToBool(testMode), us2fs(path), UStringVector(), (UInt64)(Int64)-1); + + #ifdef SUPPORT_LINKS + + if (!testMode) + { + RINOK(extractCallbackSpec->PrepareHardLinks(NULL)); // NULL means all items + } + + #endif + return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback); COM_TRY_END } @@ -554,12 +1483,59 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - CArc &arc = _archiveLink.Arcs[level]; - switch (propID) + if (level > (UInt32)_archiveLink.Arcs.Size()) + return E_INVALIDARG; + if (level == (UInt32)_archiveLink.Arcs.Size()) + { + switch (propID) + { + case kpidPath: + if (!_archiveLink.NonOpen_ArcPath.IsEmpty()) + prop = _archiveLink.NonOpen_ArcPath; + break; + case kpidErrorType: + if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + prop = _codecs->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; + break; + } + } + else { - case kpidType: prop = GetTypeOfArc(arc); break; - case kpidPath: prop = arc.Path; break; - default: return arc.Archive->GetArchiveProperty(propID, value); + const CArc &arc = _archiveLink.Arcs[level]; + switch (propID) + { + case kpidType: prop = GetTypeOfArc(arc); break; + case kpidPath: prop = arc.Path; break; + case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break; + case kpidErrorFlags: + { + UInt32 flags = arc.ErrorInfo.GetErrorFlags(); + if (flags != 0) + prop = flags; + break; + } + case kpidWarningFlags: + { + UInt32 flags = arc.ErrorInfo.GetWarningFlags(); + if (flags != 0) + prop = flags; + break; + } + case kpidOffset: + { + Int64 v = arc.GetGlobalOffset(); + if (v != 0) + prop = v; + break; + } + case kpidTailSize: + { + if (arc.ErrorInfo.TailSize != 0) + prop = arc.ErrorInfo.TailSize; + break; + } + default: return arc.Archive->GetArchiveProperty(propID, value); + } } prop.Detach(value); return S_OK; |