Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/UI/Agent
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/UI/Agent')
-rwxr-xr-xCPP/7zip/UI/Agent/Agent.cpp578
-rwxr-xr-xCPP/7zip/UI/Agent/Agent.h314
-rwxr-xr-xCPP/7zip/UI/Agent/AgentOut.cpp518
-rwxr-xr-xCPP/7zip/UI/Agent/AgentProxy.cpp203
-rwxr-xr-xCPP/7zip/UI/Agent/AgentProxy.h56
-rwxr-xr-xCPP/7zip/UI/Agent/ArchiveFolder.cpp72
-rwxr-xr-xCPP/7zip/UI/Agent/ArchiveFolderOpen.cpp98
-rwxr-xr-xCPP/7zip/UI/Agent/ArchiveFolderOut.cpp215
-rwxr-xr-xCPP/7zip/UI/Agent/IFolderArchive.h90
-rwxr-xr-xCPP/7zip/UI/Agent/UpdateCallbackAgent.cpp80
-rwxr-xr-xCPP/7zip/UI/Agent/UpdateCallbackAgent.h24
11 files changed, 2248 insertions, 0 deletions
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
new file mode 100755
index 00000000..f983e2f9
--- /dev/null
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -0,0 +1,578 @@
+// Agent.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/FileFind.h"
+
+#include "../Common/DefaultName.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+#include "Agent.h"
+
+#ifdef FORMAT_7Z
+#include "../../Archive/7z/7zHandler.h"
+#endif
+
+extern "C"
+{
+ #include "../../../../C/Sort.h"
+}
+
+
+using namespace NWindows;
+
+STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
+{
+ *agentFolder = this;
+ return S_OK;
+}
+
+void CAgentFolder::LoadFolder(CProxyFolder *folder)
+{
+ int i;
+ CProxyItem item;
+ item.Folder = folder;
+ for (i = 0; i < folder->Folders.Size(); i++)
+ {
+ item.Index = i;
+ _items.Add(item);
+ LoadFolder(&folder->Folders[i]);
+ }
+ int start = folder->Folders.Size();
+ for (i = 0; i < folder->Files.Size(); i++)
+ {
+ item.Index = start + i;
+ _items.Add(item);
+ }
+}
+
+
+STDMETHODIMP CAgentFolder::LoadItems()
+{
+ _items.Clear();
+ if (_flatMode)
+ LoadFolder(_proxyFolderItem);
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::GetNumberOfItems(UINT32 *numItems)
+{
+ if (_flatMode)
+ *numItems = _items.Size();
+ else
+ *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();
+ return S_OK;
+}
+
+/*
+STDMETHODIMP CAgentFolder::GetNumberOfSubFolders(UINT32 *aNumSubFolders)
+{
+ *aNumSubFolders = _proxyFolderItem->Folders.Size();
+ return S_OK;
+}
+*/
+
+UString CAgentFolder::GetName(UInt32 index) const
+{
+ UInt32 realIndex;
+ const CProxyFolder *folder;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[index];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = index;
+ }
+
+ if (realIndex < (UINT32)folder->Folders.Size())
+ return folder->Folders[realIndex].Name;
+ return folder->Files[realIndex - folder->Folders.Size()].Name;
+}
+
+UString CAgentFolder::GetPrefix(UInt32 index) const
+{
+ if (!_flatMode)
+ return UString();
+ const CProxyItem &item = _items[index];
+ const CProxyFolder *folder = item.Folder;
+ UString path;
+ while(folder != _proxyFolderItem)
+ {
+ path = folder->Name + UString(L"\\") + path;
+ folder = folder->Parent;
+ }
+ return path;
+}
+
+UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const
+{
+ return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);
+}
+
+void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &propVariant) const
+{
+ if (!_flatMode)
+ return;
+ propVariant = GetPrefix(index);
+}
+
+
+STDMETHODIMP CAgentFolder::GetProperty(UINT32 itemIndex, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant propVariant;
+ const CProxyFolder *folder;
+ UInt32 realIndex;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[itemIndex];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = itemIndex;
+ }
+
+ if (realIndex < (UINT32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = folder->Folders[realIndex];
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = true;
+ break;
+ case kpidName:
+ propVariant = item.Name;
+ break;
+ case kpidPrefix:
+ GetPrefixIfAny(itemIndex, propVariant);
+ break;
+ default:
+ if (item.IsLeaf)
+ return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ }
+ }
+ else
+ {
+ realIndex -= folder->Folders.Size();
+ const CProxyFile &item = folder->Files[realIndex];
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidName:
+ propVariant = item.Name;
+ break;
+ case kpidPrefix:
+ GetPrefixIfAny(itemIndex, propVariant);
+ break;
+ default:
+ return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
+
+HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder)
+{
+ CMyComPtr<IFolderFolder> parentFolder;
+ if (folder->Parent != _proxyFolderItem)
+ {
+ RINOK(BindToFolder(folder->Parent, &parentFolder));
+ }
+ else
+ parentFolder = this;
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> agentFolder = folderSpec;
+ folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec);
+ *resultFolder = agentFolder.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::BindToFolder(UINT32 index, IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+
+ CProxyFolder *folder;
+ UInt32 realIndex;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[index];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = index;
+ }
+ if (realIndex >= (UINT32)folder->Folders.Size())
+ return E_INVALIDARG;
+ return BindToFolder(&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 (index < 0)
+ return E_INVALIDARG;
+ return BindToFolder(index, resultFolder);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+ CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
+ *resultFolder = parentFolder.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetName(BSTR *name)
+{
+ CMyComBSTR temp = _proxyFolderItem->Name;
+ *name = temp.Detach();
+ return S_OK;
+}
+
+
+#ifdef NEW_FOLDER_INTERFACE
+
+struct CArchiveItemPropertyTemp
+{
+ UString Name;
+ PROPID ID;
+ VARTYPE Type;
+};
+
+STDMETHODIMP CAgentFolder::GetNumberOfProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProperties));
+ if (_flatMode)
+ (*numProperties)++;
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetPropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ UINT32 numProperties;
+ _agentSpec->GetArchive()->GetNumberOfProperties(&numProperties);
+ if (index < numProperties)
+ {
+ RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
+ if (*propID == kpidPath)
+ *propID = kpidName;
+ }
+ else
+ {
+ *name = NULL;
+ *propID = kpidPrefix;
+ *varType = VT_BSTR;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetTypeID(BSTR *name)
+{
+ COM_TRY_BEGIN
+ UString temp = UString(L"7-Zip.") + _agentSpec->ArchiveType;
+ CMyComBSTR bstrTemp = temp;
+ *name = bstrTemp.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetPath(BSTR *path)
+{
+ COM_TRY_BEGIN
+ UStringVector pathParts;
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> currentFolder = this;
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ currentFolder->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR aName;
+ currentFolder->GetName(&aName);
+ pathParts.Insert(0, (const wchar_t *)aName);
+ currentFolder = newFolder;
+ }
+
+ UString prefix;
+ for(int i = 0; i < pathParts.Size(); i++)
+ {
+ prefix += pathParts[i];
+ prefix += L'\\';
+ }
+
+ CMyComBSTR tempPath = prefix;
+ *path = tempPath.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)
+{
+ _flatMode = IntToBool(flatMode);
+ return S_OK;
+}
+
+#endif
+
+void CAgentFolder::GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const
+{
+ if (!_flatMode)
+ {
+ _proxyFolderItem->GetRealIndices(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())
+ continue;
+ realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);
+ }
+ HeapSort(&realIndices.Front(), realIndices.Size());
+}
+
+STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
+ UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ UStringVector pathParts;
+ CProxyFolder *currentProxyFolder = _proxyFolderItem;
+ while (currentProxyFolder->Parent)
+ {
+ pathParts.Insert(0, currentProxyFolder->Name);
+ currentProxyFolder = currentProxyFolder->Parent;
+ }
+
+ /*
+ if (_flatMode)
+ pathMode = NExtract::NPathMode::kNoPathnames;
+ */
+
+ extractCallbackSpec->Init(_agentSpec->GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ overwriteMode,
+ pathParts,
+ _agentSpec->DefaultName,
+ _agentSpec->DefaultTime,
+ _agentSpec->DefaultAttributes
+ // ,_agentSpec->_srcDirectoryPrefix
+ );
+ CUIntVector realIndices;
+ GetRealIndices(indices, numItems, realIndices);
+ return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
+ realIndices.Size(), testMode, extractCallback);
+ COM_TRY_END
+}
+
+/////////////////////////////////////////
+// CAgent
+
+CAgent::CAgent():
+ _proxyArchive(NULL)
+{
+}
+
+CAgent::~CAgent()
+{
+ if (_proxyArchive != NULL)
+ delete _proxyArchive;
+}
+
+STDMETHODIMP CAgent::Open(
+ const wchar_t *filePath,
+ BSTR *archiveType,
+ // CLSID *clsIDResult,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ _archiveFilePath = filePath;
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(_archiveFilePath, fileInfo))
+ return ::GetLastError();
+ if (fileInfo.IsDirectory())
+ return E_FAIL;
+ CArchiverInfo archiverInfo0, archiverInfo1;
+ HRESULT res = OpenArchive(_archiveFilePath, _archiveLink, openArchiveCallback);
+ // _archive = _archiveLink.GetArchive();
+ DefaultName = _archiveLink.GetDefaultItemName();
+ const CArchiverInfo &ai = _archiveLink.GetArchiverInfo();
+
+ RINOK(res);
+ DefaultTime = fileInfo.LastWriteTime;
+ DefaultAttributes = fileInfo.Attributes;
+ ArchiveType = ai.Name;
+ if (archiveType != 0)
+ {
+ CMyComBSTR name = ArchiveType;
+ *archiveType = name.Detach();
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::ReOpen(
+ // const wchar_t *filePath,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ if (_proxyArchive != NULL)
+ {
+ delete _proxyArchive;
+ _proxyArchive = NULL;
+ }
+ RINOK(ReOpenArchive(_archiveLink, _archiveFilePath));
+ return ReadItems();
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::Close()
+{
+ COM_TRY_BEGIN
+ RINOK(_archiveLink.Close());
+ if (_archiveLink.GetNumLevels() > 1)
+ {
+ // return S_OK;
+ }
+ // _archive->Close();
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
+{
+ return _archive->EnumProperties(EnumProperties);
+}
+*/
+
+HRESULT CAgent::ReadItems()
+{
+ if (_proxyArchive != NULL)
+ return S_OK;
+ _proxyArchive = new CProxyArchive();
+ return _proxyArchive->Load(GetArchive(),
+ DefaultName,
+ // _defaultTime,
+ // _defaultAttributes,
+ NULL);
+}
+
+STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+ RINOK(ReadItems());
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> rootFolder = folderSpec;
+ folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this);
+ *resultFolder = rootFolder.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CAgent::Extract(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ extractCallbackSpec->Init(GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ overwriteMode,
+ UStringVector(),
+ DefaultName,
+ DefaultTime,
+ DefaultAttributes
+ // ,_srcDirectoryPrefix
+ );
+ return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetNumberOfProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetNumberOfProperties(numProperties);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetPropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType));
+ if (*propID == kpidPath)
+ *propID = kpidName;
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetArchiveProperty(propID, value);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetNumberOfArchiveProperties(numProperties);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetArchivePropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetArchivePropertyInfo(index,
+ name, propID, varType);
+ COM_TRY_END
+}
+
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
new file mode 100755
index 00000000..41f80266
--- /dev/null
+++ b/CPP/7zip/UI/Agent/Agent.h
@@ -0,0 +1,314 @@
+// Agent/Agent.h
+
+#ifndef __AGENT_AGENT_H
+#define __AGENT_AGENT_H
+
+#include "Common/MyCom.h"
+#include "Windows/PropVariant.h"
+
+#include "../Common/UpdateAction.h"
+#include "../Common/ArchiverInfo.h"
+#include "../Common/OpenArchive.h"
+
+#include "IFolderArchive.h"
+#include "AgentProxy.h"
+
+#ifndef EXCLUDE_COM
+#include "Windows/DLL.h"
+#endif
+#ifdef NEW_FOLDER_INTERFACE
+#include "../../FileManager/IFolder.h"
+#endif
+
+class CAgentFolder;
+
+// {23170F69-40C1-278A-0000-000100050001}
+DEFINE_GUID(IID_IArchiveFolderInternal,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100050001")
+IArchiveFolderInternal: public IUnknown
+{
+public:
+ STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder) PURE;
+};
+
+struct CProxyItem
+{
+ CProxyFolder *Folder;
+ UInt32 Index;
+};
+
+class CAgent;
+
+class CAgentFolder:
+ public IFolderFolder,
+ public IArchiveFolder,
+ public IArchiveFolderInternal,
+#ifdef NEW_FOLDER_INTERFACE
+ public IEnumProperties,
+ public IFolderGetTypeID,
+ public IFolderGetPath,
+ public IFolderOperations,
+ public IFolderSetFlatMode,
+#endif
+ public CMyUnknownImp
+{
+public:
+
+ MY_QUERYINTERFACE_BEGIN
+ MY_QUERYINTERFACE_ENTRY(IFolderFolder)
+ MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
+ MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
+ #ifdef NEW_FOLDER_INTERFACE
+ MY_QUERYINTERFACE_ENTRY(IEnumProperties)
+ MY_QUERYINTERFACE_ENTRY(IFolderGetTypeID)
+ MY_QUERYINTERFACE_ENTRY(IFolderGetPath)
+ MY_QUERYINTERFACE_ENTRY(IFolderOperations)
+ MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ // IFolderFolder
+
+ void LoadFolder(CProxyFolder *folder);
+ HRESULT BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder);
+ void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const;
+
+ STDMETHOD(LoadItems)();
+ STDMETHOD(GetNumberOfItems)(UINT32 *numItems);
+ STDMETHOD(GetProperty)(UINT32 itemIndex, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(BindToFolder)(UINT32 index, IFolderFolder **resultFolder);
+ STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder);
+ STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder);
+ STDMETHOD(GetName)(BSTR *name);
+
+ // IArchiveFolder
+ STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback);
+
+ STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder);
+
+ #ifdef NEW_FOLDER_INTERFACE
+ STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
+ STDMETHOD(GetPropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType);
+ STDMETHOD(GetTypeID)(BSTR *name);
+ STDMETHOD(GetPath)(BSTR *path);
+
+
+ // IFolderOperations
+ STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress);
+ STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress);
+ STDMETHOD(Rename)(UINT32 index, const wchar_t *newName, IProgress *progress);
+ STDMETHOD(Delete)(const UINT32 *indices, UINT32 numItems, IProgress *progress);
+ STDMETHOD(CopyTo)(const UINT32 *indices, UINT32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback);
+ STDMETHOD(MoveTo)(const UINT32 *indices, UINT32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback);
+ STDMETHOD(CopyFrom)(const wchar_t *fromFolderPath,
+ const wchar_t **itemsPaths, UINT32 numItems, IProgress *progress);
+ STDMETHOD(SetProperty)(UINT32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress);
+
+ STDMETHOD(SetFlatMode)(Int32 flatMode);
+ #endif
+
+ CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {}
+
+ void Init(CProxyArchive *proxyHandler,
+ CProxyFolder *proxyFolderItem,
+ IFolderFolder *parentFolder,
+ CAgent *agent)
+ {
+ _proxyArchive = proxyHandler;
+ _proxyFolderItem = proxyFolderItem;
+ _parentFolder = parentFolder;
+ _agent = (IInFolderArchive *)agent;
+ _agentSpec = agent;
+ }
+
+ void GetPathParts(UStringVector &pathParts);
+ HRESULT CommonUpdateOperation(
+ bool deleteOperation,
+ bool createFolderOperation,
+ bool renameOperation,
+ const wchar_t *newItemName,
+ const NUpdateArchive::CActionSet *actionSet,
+ const UINT32 *indices, UINT32 numItems,
+ IFolderArchiveUpdateCallback *updateCallback100);
+
+
+ UString GetPrefix(UInt32 index) const;
+ UString GetName(UInt32 index) const;
+ UString GetFullPathPrefixPlusPrefix(UInt32 index) const;
+ void GetPrefixIfAny(UInt32 index, NWindows::NCOM::CPropVariant &propVariant) const;
+
+public:
+ CProxyArchive *_proxyArchive;
+ CProxyFolder *_proxyFolderItem;
+ CMyComPtr<IFolderFolder> _parentFolder;
+ CMyComPtr<IInFolderArchive> _agent;
+ CAgent *_agentSpec;
+
+ CRecordVector<CProxyItem> _items;
+ bool _flatMode;
+private:
+};
+
+// {23170F69-40C1-278A-1000-000100030000}
+DEFINE_GUID(CLSID_CAgentArchiveHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);
+
+class CAgent:
+ public IInFolderArchive,
+ #ifndef EXTRACT_ONLY
+ public IOutFolderArchive,
+ public ISetProperties,
+ #endif
+ public CMyUnknownImp
+{
+public:
+
+ MY_QUERYINTERFACE_BEGIN
+ MY_QUERYINTERFACE_ENTRY(IInFolderArchive)
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ STDMETHOD(Open)(
+ const wchar_t *filePath,
+ // CLSID *clsIDResult,
+ BSTR *archiveType,
+ IArchiveOpenCallback *openArchiveCallback);
+
+ STDMETHOD(ReOpen)(
+ // const wchar_t *filePath,
+ IArchiveOpenCallback *openArchiveCallback);
+ /*
+ STDMETHOD(ReOpen)(IInStream *stream,
+ const wchar_t *defaultName,
+ const FILETIME *defaultTime,
+ UINT32 defaultAttributes,
+ const UINT64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ */
+ STDMETHOD(Close)();
+ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
+ STDMETHOD(GetPropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType);
+ STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties);
+ STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType);
+ STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder);
+ STDMETHOD(Extract)(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2);
+
+ #ifndef EXTRACT_ONLY
+ STDMETHOD(SetFolder)(IFolderFolder *folder);
+ STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UINT32 numNames);
+ STDMETHOD(DeleteItems)(const wchar_t *newArchiveName, const UINT32 *indices,
+ UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback);
+ STDMETHOD(DoOperation)(
+ const wchar_t *filePath,
+ const CLSID *clsID,
+ const wchar_t *newArchiveName,
+ const Byte *stateActions,
+ const wchar_t *sfxModule,
+ IFolderArchiveUpdateCallback *updateCallback);
+
+ HRESULT CommonUpdate(
+ const wchar_t *newArchiveName,
+ int numUpdateItems,
+ IArchiveUpdateCallback *updateCallback);
+
+ HRESULT CreateFolder(
+ const wchar_t *newArchiveName,
+ const wchar_t *folderName,
+ IFolderArchiveUpdateCallback *updateCallback100);
+
+ HRESULT RenameItem(
+ const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems,
+ const wchar_t *newItemName,
+ IFolderArchiveUpdateCallback *updateCallback100);
+
+ // ISetProperties
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, INT32 numProperties);
+ #endif
+
+ CAgent();
+ ~CAgent();
+private:
+ HRESULT ReadItems();
+public:
+ CProxyArchive *_proxyArchive;
+
+ CArchiveLink _archiveLink;
+ // IInArchive *_archive2;
+
+ // CLSID _CLSID;
+ // CMyComPtr<IArchiveFolder> m_RootFolder;
+
+ UString DefaultName;
+
+ FILETIME DefaultTime;
+ UINT32 DefaultAttributes;
+
+ UString ArchiveType;
+
+ UStringVector _names;
+ UString _folderPrefix;
+
+ UString _archiveNamePrefix;
+ CAgentFolder *_agentFolder;
+
+ UString _archiveFilePath;
+
+ #ifndef EXTRACT_ONLY
+ CObjectVector<UString> m_PropNames;
+ CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues;
+ #endif
+
+ IInArchive *GetArchive() { return _archiveLink.GetArchive(); }
+ bool CanUpdate() const { return _archiveLink.GetNumLevels() <= 1; }
+};
+
+#ifdef NEW_FOLDER_INTERFACE
+class CArchiveFolderManager:
+ public IFolderManager,
+ public IFolderManagerGetIconPath,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(
+ IFolderManager,
+ IFolderManagerGetIconPath
+ )
+ // IFolderManager
+ STDMETHOD(OpenFolderFile)(const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress);
+ STDMETHOD(GetTypes)(BSTR *types);
+ STDMETHOD(GetExtension)(const wchar_t *type, BSTR *extension);
+ STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress);
+ STDMETHOD(GetIconPath)(const wchar_t *type, BSTR *iconPath);
+ CArchiveFolderManager(): _formatsLoaded(false) {}
+private:
+ void LoadFormats();
+ int FindFormat(const UString &type);
+ bool _formatsLoaded;
+ CObjectVector<CArchiverInfo> _formats;
+};
+#endif
+
+#endif
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
new file mode 100755
index 00000000..25d65bb2
--- /dev/null
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -0,0 +1,518 @@
+// AgentOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileDir.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Common/FileStreams.h"
+
+#include "../Common/UpdatePair.h"
+#include "../Common/EnumDirItems.h"
+#include "../Common/HandlerLoader.h"
+#include "../Common/UpdateCallback.h"
+#include "../Common/OpenArchive.h"
+
+#include "Agent.h"
+#include "UpdateCallbackAgent.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
+}
+
+STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
+{
+ _archiveNamePrefix.Empty();
+ if (folder == NULL)
+ {
+ _agentFolder = NULL;
+ return S_OK;
+ }
+ else
+ {
+ CMyComPtr<IFolderFolder> archiveFolder = folder;
+ CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
+ RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
+ RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder));
+ }
+
+ UStringVector pathParts;
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> folderItem = folder;
+ if (folderItem != NULL)
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ folderItem->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR name;
+ folderItem->GetName(&name);
+ pathParts.Insert(0, (const wchar_t *)name);
+ folderItem = newFolder;
+ }
+
+ for(int i = 0; i < pathParts.Size(); i++)
+ {
+ _archiveNamePrefix += pathParts[i];
+ _archiveNamePrefix += L'\\';
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
+ const wchar_t **names, UINT32 numNames)
+{
+ _folderPrefix = folderPrefix;
+ _names.Clear();
+ _names.Reserve(numNames);
+ for (UINT32 i = 0; i < numNames; i++)
+ _names.Add(names[i]);
+ return S_OK;
+}
+
+
+static HRESULT GetFileTime(CAgent *agent, UINT32 itemIndex, FILETIME &fileTime)
+{
+ CPropVariant property;
+ RINOK(agent->GetArchive()->GetProperty(itemIndex, kpidLastWriteTime, &property));
+ if (property.vt == VT_FILETIME)
+ fileTime = property.filetime;
+ else if (property.vt == VT_EMPTY)
+ fileTime = agent->DefaultTime;
+ else
+ throw 4190407;
+ return S_OK;
+}
+
+static HRESULT EnumerateArchiveItems(CAgent *agent,
+ const CProxyFolder &item,
+ const UString &prefix,
+ CObjectVector<CArchiveItem> &archiveItems)
+{
+ int i;
+ for(i = 0; i < item.Files.Size(); i++)
+ {
+ const CProxyFile &fileItem = item.Files[i];
+ CArchiveItem archiveItem;
+
+ RINOK(::GetFileTime(agent, fileItem.Index, archiveItem.LastWriteTime));
+
+ CPropVariant property;
+ agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property);
+ archiveItem.SizeIsDefined = (property.vt != VT_EMPTY);
+ if (archiveItem.SizeIsDefined)
+ archiveItem.Size = ConvertPropVariantToUInt64(property);
+ archiveItem.IsDirectory = false;
+ archiveItem.Name = prefix + fileItem.Name;
+ archiveItem.Censored = true; // test it
+ archiveItem.IndexInServer = fileItem.Index;
+ archiveItems.Add(archiveItem);
+ }
+ for(i = 0; i < item.Folders.Size(); i++)
+ {
+ const CProxyFolder &dirItem = item.Folders[i];
+ UString fullName = prefix + dirItem.Name;
+ if(dirItem.IsLeaf)
+ {
+ CArchiveItem archiveItem;
+ RINOK(::GetFileTime(agent, dirItem.Index, archiveItem.LastWriteTime));
+ archiveItem.IsDirectory = true;
+ archiveItem.SizeIsDefined = false;
+ archiveItem.Name = fullName;
+ archiveItem.Censored = true; // test it
+ archiveItem.IndexInServer = dirItem.Index;
+ archiveItems.Add(archiveItem);
+ }
+ RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(L'\\'), archiveItems));
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CAgent::DoOperation(
+ const wchar_t *filePath,
+ const CLSID *clsID,
+ const wchar_t *newArchiveName,
+ const Byte *stateActions,
+ const wchar_t *sfxModule,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ NUpdateArchive::CActionSet actionSet;
+ int i;
+ for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
+
+ CObjectVector<CDirItem> dirItems;
+
+ UString folderPrefix = _folderPrefix;
+ NFile::NName::NormalizeDirPathPrefix(folderPrefix);
+ UStringVector errorPaths;
+ CRecordVector<DWORD> errorCodes;
+ ::EnumerateDirItems(folderPrefix, _names, _archiveNamePrefix, dirItems, errorPaths, errorCodes);
+ if (errorCodes.Size() > 0)
+ {
+ return errorCodes.Front();
+ }
+
+ NWindows::NDLL::CLibrary library;
+
+ CMyComPtr<IOutArchive> outArchive;
+ if (GetArchive())
+ {
+ RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
+ }
+ else
+ {
+ CHandlerLoader loader;
+ RINOK(loader.CreateHandler(filePath, *clsID, (void **)&outArchive, true));
+ library.Attach(loader.Detach());
+ }
+
+ NFileTimeType::EEnum fileTimeType;
+ UINT32 value;
+ RINOK(outArchive->GetFileTimeType(&value));
+
+ switch(value)
+ {
+ case NFileTimeType::kWindows:
+ case NFileTimeType::kDOS:
+ case NFileTimeType::kUnix:
+ fileTimeType = NFileTimeType::EEnum(value);
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ CObjectVector<CUpdatePair> updatePairs;
+
+ CObjectVector<CArchiveItem> archiveItems;
+ if (GetArchive())
+ {
+ RINOK(ReadItems());
+ EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", archiveItems);
+ }
+
+ GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs);
+
+ CObjectVector<CUpdatePair2> updatePairs2;
+ UpdateProduce(updatePairs, actionSet, updatePairs2);
+
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
+
+ updateCallbackSpec->DirPrefix = folderPrefix;
+ updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->ArchiveItems = &archiveItems;
+ updateCallbackSpec->UpdatePairs = &updatePairs2;
+ updateCallbackSpec->Archive = GetArchive();
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+
+ COutFileStream *outStreamSpec = new COutFileStream;
+ CMyComPtr<IOutStream> outStream(outStreamSpec);
+ UString archiveName = newArchiveName;
+ {
+ UString resultPath;
+ int pos;
+ if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
+ throw 141716;
+ NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+ }
+ if (!outStreamSpec->Create(archiveName, true))
+ {
+ // ShowLastErrorMessage();
+ return E_FAIL;
+ }
+
+ CMyComPtr<ISetProperties> setProperties;
+ if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)
+ {
+ if (m_PropNames.Size() == 0)
+ {
+ RINOK(setProperties->SetProperties(0, 0, 0));
+ }
+ else
+ {
+ CRecordVector<const wchar_t *> names;
+ for(i = 0; i < m_PropNames.Size(); i++)
+ names.Add((const wchar_t *)m_PropNames[i]);
+
+ NWindows::NCOM::CPropVariant *propValues = new NWindows::NCOM::CPropVariant[m_PropValues.Size()];
+ try
+ {
+ for (int i = 0; i < m_PropValues.Size(); i++)
+ propValues[i] = m_PropValues[i];
+ RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size()));
+ }
+ catch(...)
+ {
+ delete []propValues;
+ throw;
+ }
+ delete []propValues;
+ }
+ }
+ m_PropNames.Clear();
+ m_PropValues.Clear();
+
+ if (sfxModule != NULL)
+ {
+ CInFileStream *sfxStreamSpec = new CInFileStream;
+ CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
+ if (!sfxStreamSpec->Open(sfxModule))
+ throw "Can't open sfx module";
+ RINOK(CopyBlock(sfxStream, outStream));
+ }
+
+ return outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback);
+}
+
+
+HRESULT CAgent::CommonUpdate(
+ const wchar_t *newArchiveName,
+ int numUpdateItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ CMyComPtr<IOutArchive> outArchive;
+ RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
+
+ COutFileStream *outStreamSpec = new COutFileStream;
+ CMyComPtr<IOutStream> outStream(outStreamSpec);
+
+ UString archiveName = newArchiveName;
+ {
+ UString resultPath;
+ int pos;
+ if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
+ throw 141716;
+ NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+ }
+
+ /*
+ bool isOK = false;
+ for (int i = 0; i < (1 << 16); i++)
+ {
+ resultName = newArchiveName;
+ if (i > 0)
+ {
+ wchar_t s[32];
+ ConvertUInt64ToString(i, s);
+ resultName += s;
+ }
+ if (outStreamSpec->Open(realPath))
+ {
+ isOK = true;
+ break;
+ }
+ if (::GetLastError() != ERROR_FILE_EXISTS)
+ return ::GetLastError();
+ }
+ if (!isOK)
+ return ::GetLastError();
+ */
+ if (!outStreamSpec->Create(archiveName, true))
+ {
+ // ShowLastErrorMessage();
+ return E_FAIL;
+ }
+
+ return outArchive->UpdateItems(outStream, numUpdateItems, updateCallback);
+}
+
+
+STDMETHODIMP CAgent::DeleteItems(
+ const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ CUIntVector realIndices;
+ _agentFolder->GetRealIndices(indices, numItems, realIndices);
+ CObjectVector<CUpdatePair2> updatePairs;
+ int curIndex = 0;
+ UInt32 numItemsInArchive;
+ RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+ for (UInt32 i = 0; i < numItemsInArchive; i++)
+ {
+ if (curIndex < realIndices.Size())
+ if (realIndices[curIndex] == i)
+ {
+ curIndex++;
+ continue;
+ }
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = false;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ updatePair.IsAnti = false; // check it. Maybe it can be undefined
+ updatePair.ArchiveItemIndex = i;
+ updatePairs.Add(updatePair);
+ }
+ updateCallbackSpec->UpdatePairs = &updatePairs;
+ updateCallbackSpec->Archive = GetArchive();
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+ return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
+}
+
+HRESULT CAgent::CreateFolder(
+ const wchar_t *newArchiveName,
+ const wchar_t *folderName,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ CObjectVector<CUpdatePair2> updatePairs;
+ UINT32 numItemsInArchive;
+ RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+ for (UInt32 i = 0; i < numItemsInArchive; i++)
+ {
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = false;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ updatePair.IsAnti = false; // check it.
+ updatePair.ArchiveItemIndex = i;
+ updatePairs.Add(updatePair);
+ }
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = true;
+ updatePair.ExistInArchive = false;
+ updatePair.ExistOnDisk = true;
+ updatePair.IsAnti = false;
+ updatePair.ArchiveItemIndex = -1;
+ updatePair.DirItemIndex = 0;
+
+ updatePairs.Add(updatePair);
+
+ CObjectVector<CDirItem> dirItems;
+ CDirItem dirItem;
+
+ dirItem.Attributes = FILE_ATTRIBUTE_DIRECTORY;
+ dirItem.Size = 0;
+ dirItem.Name = _agentFolder->_proxyFolderItem->GetFullPathPrefix() + folderName;
+
+ SYSTEMTIME systemTime;
+ FILETIME fileTime;
+ ::GetSystemTime(&systemTime);
+ ::SystemTimeToFileTime(&systemTime, &fileTime);
+ dirItem.LastAccessTime = dirItem.LastWriteTime =
+ dirItem.CreationTime = fileTime;
+
+ dirItems.Add(dirItem);
+
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+ updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->UpdatePairs = &updatePairs;
+ updateCallbackSpec->Archive = GetArchive();
+ return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
+}
+
+
+HRESULT CAgent::RenameItem(
+ const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems,
+ const wchar_t *newItemName,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ if (numItems != 1)
+ return E_INVALIDARG;
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ CUIntVector realIndices;
+ _agentFolder->GetRealIndices(indices, numItems, realIndices);
+
+ UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]);
+ UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);
+ UString newItemPath = fullPrefix + newItemName;
+
+ CObjectVector<CUpdatePair2> updatePairs;
+ int curIndex = 0;
+ UINT32 numItemsInArchive;
+ RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+ for (UInt32 i = 0; i < numItemsInArchive; i++)
+ {
+ if (curIndex < realIndices.Size())
+ if (realIndices[curIndex] == i)
+ {
+ CUpdatePair2 updatePair;
+ updatePair.NewData = false;
+ updatePair.NewProperties = true;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ RINOK(IsArchiveItemAnti(GetArchive(), i, updatePair.IsAnti));
+ updatePair.ArchiveItemIndex = i;
+ updatePair.NewNameIsDefined = true;
+
+ updatePair.NewName = newItemName;
+
+ UString oldFullPath;
+ RINOK(GetArchiveItemPath(GetArchive(), i, DefaultName, oldFullPath));
+
+ if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0)
+ return E_INVALIDARG;
+
+ updatePair.NewName = newItemPath + oldFullPath.Mid(oldItemPath.Length());
+ updatePairs.Add(updatePair);
+ curIndex++;
+ continue;
+ }
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = false;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ updatePair.IsAnti = false;
+ updatePair.ArchiveItemIndex = i;
+ updatePairs.Add(updatePair);
+ }
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+ updateCallbackSpec->UpdatePairs = &updatePairs;
+ updateCallbackSpec->Archive = GetArchive();
+ return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
+}
+
+STDMETHODIMP CAgent::SetProperties(const wchar_t **names,
+ const PROPVARIANT *values, INT32 numProperties)
+{
+ m_PropNames.Clear();
+ m_PropValues.Clear();
+ for (int i = 0; i < numProperties; i++)
+ {
+ m_PropNames.Add(names[i]);
+ m_PropValues.Add(values[i]);
+ }
+ return S_OK;
+}
+
+
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
new file mode 100755
index 00000000..42063e67
--- /dev/null
+++ b/CPP/7zip/UI/Agent/AgentProxy.cpp
@@ -0,0 +1,203 @@
+// AgentProxy.cpp
+
+#include "StdAfx.h"
+
+#include "AgentProxy.h"
+
+#include "Common/MyCom.h"
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+#include "../Common/OpenArchive.h"
+
+extern "C"
+{
+ #include "../../../../C/Sort.h"
+}
+
+using namespace NWindows;
+
+int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
+{
+ int left = 0, right = Folders.Size();
+ for (;;)
+ {
+ if (left == right)
+ {
+ insertPos = left;
+ return -1;
+ }
+ int mid = (left + right) / 2;
+ int compare = name.CompareNoCase(Folders[mid].Name);
+ if (compare == 0)
+ return mid;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+int CProxyFolder::FindDirSubItemIndex(const UString &name) const
+{
+ int insertPos;
+ return FindDirSubItemIndex(name, insertPos);
+}
+
+void CProxyFolder::AddFileSubItem(UINT32 index, const UString &name)
+{
+ Files.Add(CProxyFile());
+ Files.Back().Name = name;
+ Files.Back().Index = index;
+}
+
+CProxyFolder* CProxyFolder::AddDirSubItem(UINT32 index, bool leaf,
+ const UString &name)
+{
+ int insertPos;
+ int folderIndex = FindDirSubItemIndex(name, insertPos);
+ if (folderIndex >= 0)
+ {
+ CProxyFolder *item = &Folders[folderIndex];
+ if(leaf)
+ {
+ item->Index = index;
+ item->IsLeaf = true;
+ }
+ return item;
+ }
+ Folders.Insert(insertPos, CProxyFolder());
+ CProxyFolder *item = &Folders[insertPos];
+ item->Name = name;
+ item->Index = index;
+ item->Parent = this;
+ item->IsLeaf = leaf;
+ return item;
+}
+
+void CProxyFolder::Clear()
+{
+ Folders.Clear();
+ Files.Clear();
+}
+
+UString CProxyFolder::GetFullPathPrefix() const
+{
+ UString result;
+ const CProxyFolder *current = this;
+ while (current->Parent != NULL)
+ {
+ result = current->Name + UString(L'\\') + result;
+ current = current->Parent;
+ }
+ return result;
+}
+
+UString CProxyFolder::GetItemName(UINT32 index) const
+{
+ if (index < (UINT32)Folders.Size())
+ return Folders[index].Name;
+ return Files[index - Folders.Size()].Name;
+}
+
+void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const
+{
+ if (IsLeaf)
+ realIndices.Add(Index);
+ int i;
+ for(i = 0; i < Folders.Size(); i++)
+ Folders[i].AddRealIndices(realIndices);
+ for(i = 0; i < Files.Size(); i++)
+ realIndices.Add(Files[i].Index);
+}
+
+void CProxyFolder::GetRealIndices(const UINT32 *indices,
+ UINT32 numItems, CUIntVector &realIndices) const
+{
+ realIndices.Clear();
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ int index = indices[i];
+ int numDirItems = Folders.Size();
+ if (index < numDirItems)
+ Folders[index].AddRealIndices(realIndices);
+ else
+ realIndices.Add(Files[index - numDirItems].Index);
+ }
+ HeapSort(&realIndices.Front(), realIndices.Size());
+}
+
+///////////////////////////////////////////////
+// CProxyArchive
+
+HRESULT CProxyArchive::Reload(IInArchive *archive, IProgress *progress)
+{
+ RootFolder.Clear();
+ return ReadObjects(archive, progress);
+}
+
+HRESULT CProxyArchive::Load(IInArchive *archive,
+ const UString &defaultName,
+ // const FILETIME &defaultTime,
+ // UINT32 defaultAttributes,
+ IProgress *progress)
+{
+ DefaultName = defaultName;
+ // DefaultTime = defaultTime;
+ // DefaultAttributes = defaultAttributes;
+ return Reload(archive, progress);
+}
+
+
+HRESULT CProxyArchive::ReadObjects(IInArchive *archiveHandler, IProgress *progress)
+{
+ UINT32 numItems;
+ RINOK(archiveHandler->GetNumberOfItems(&numItems));
+ if (progress != NULL)
+ {
+ UINT64 totalItems = numItems;
+ RINOK(progress->SetTotal(totalItems));
+ }
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ if (progress != NULL)
+ {
+ UINT64 currentItemIndex = i;
+ RINOK(progress->SetCompleted(&currentItemIndex));
+ }
+ NCOM::CPropVariant propVariantPath;
+ RINOK(archiveHandler->GetProperty(i, kpidPath, &propVariantPath));
+ CProxyFolder *currentItem = &RootFolder;
+ UString fileName;
+ if(propVariantPath.vt == VT_EMPTY)
+ fileName = DefaultName;
+ else
+ {
+ if(propVariantPath.vt != VT_BSTR)
+ return E_FAIL;
+ UString filePath = propVariantPath.bstrVal;
+
+ int len = filePath.Length();
+ for (int i = 0; i < len; i++)
+ {
+ wchar_t c = filePath[i];
+ if (c == '\\' || c == '/')
+ {
+ currentItem = currentItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName);
+ fileName.Empty();
+ }
+ else
+ fileName += c;
+ }
+ }
+
+ NCOM::CPropVariant propVariantIsFolder;
+ bool isFolder;
+ RINOK(IsArchiveItemFolder(archiveHandler, i, isFolder));
+ if(isFolder)
+ currentItem->AddDirSubItem(i, true, fileName);
+ else
+ currentItem->AddFileSubItem(i, fileName);
+ }
+ return S_OK;
+}
+
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h
new file mode 100755
index 00000000..9402cfdd
--- /dev/null
+++ b/CPP/7zip/UI/Agent/AgentProxy.h
@@ -0,0 +1,56 @@
+// AgentProxy.h
+
+#ifndef __AGENT_PROXY_H
+#define __AGENT_PROXY_H
+
+#include "Common/String.h"
+
+#include "../../Archive/IArchive.h"
+
+class CProxyFile
+{
+public:
+ UINT32 Index;
+ UString Name;
+};
+
+class CProxyFolder: public CProxyFile
+{
+public:
+ CProxyFolder *Parent;
+ CObjectVector<CProxyFolder> Folders;
+ CObjectVector<CProxyFile> Files;
+ bool IsLeaf;
+
+ CProxyFolder(): Parent(NULL) {};
+ int FindDirSubItemIndex(const UString &name, int &insertPos) const;
+ int FindDirSubItemIndex(const UString &name) const;
+ CProxyFolder* AddDirSubItem(UINT32 index,
+ bool leaf, const UString &name);
+ void AddFileSubItem(UINT32 index, const UString &name);
+ void Clear();
+
+ UString GetFullPathPrefix() const;
+ UString GetItemName(UINT32 index) const;
+ void AddRealIndices(CUIntVector &realIndices) const;
+ void GetRealIndices(const UINT32 *indices, UINT32 numItems,
+ CUIntVector &realIndices) const;
+};
+
+class CProxyArchive
+{
+ HRESULT ReadObjects(IInArchive *inArchive, IProgress *progress);
+public:
+ UString DefaultName;
+ // FILETIME DefaultTime;
+ // UINT32 DefaultAttributes;
+ CProxyFolder RootFolder;
+ HRESULT Reload(IInArchive *archive, IProgress *progress);
+ HRESULT Load(IInArchive *archive,
+ const UString &defaultName,
+ // const FILETIME &defaultTime,
+ // UINT32 defaultAttributes,
+ IProgress *progress);
+};
+
+#endif \ No newline at end of file
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
new file mode 100755
index 00000000..0ce553dc
--- /dev/null
+++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
@@ -0,0 +1,72 @@
+// Zip/ArchiveFolder.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileDir.h"
+
+#include "../../Common/FileStreams.h"
+
+#include "../Common/UpdatePair.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+#include "Agent.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new
+ CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ UStringVector pathParts;
+ CProxyFolder *currentProxyFolder = _proxyFolderItem;
+ while (currentProxyFolder->Parent)
+ {
+ pathParts.Insert(0, currentProxyFolder->Name);
+ currentProxyFolder = currentProxyFolder->Parent;
+ }
+
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
+ {
+ CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
+ RINOK(callbackWrap.QueryInterface(
+ IID_IFolderArchiveExtractCallback, &extractCallback2));
+ }
+
+ NExtract::NPathMode::EEnum pathMode = _flatMode ?
+ NExtract::NPathMode::kNoPathnames :
+ NExtract::NPathMode::kCurrentPathnames;
+
+ extractCallbackSpec->Init(_agentSpec->GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ NExtract::NOverwriteMode::kAskBefore,
+ pathParts,
+ _agentSpec->DefaultName,
+ _agentSpec->DefaultTime,
+ _agentSpec->DefaultAttributes
+ // ,_agentSpec->_srcDirectoryPrefix
+ );
+ CUIntVector realIndices;
+ GetRealIndices(indices, numItems, realIndices);
+ return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
+ realIndices.Size(), BoolToInt(false), extractCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::MoveTo(const UINT32 * /* indices */, UINT32 /* numItems */,
+ const wchar_t * /* path */, IFolderOperationsExtractCallback * /* callback */)
+{
+ return E_NOTIMPL;
+}
+
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
new file mode 100755
index 00000000..ce423941
--- /dev/null
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
@@ -0,0 +1,98 @@
+// Zip/ArchiveFolder.cpp
+
+#include "StdAfx.h"
+
+#include "Agent.h"
+
+#include "Common/StringConvert.h"
+
+#include "../Common/OpenArchive.h"
+
+static const UInt64 kMaxCheckStartPosition = 1 << 20;
+
+static inline UINT GetCurrentFileCodePage()
+ { return AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
+
+void CArchiveFolderManager::LoadFormats()
+{
+ if (!_formatsLoaded)
+ ReadArchiverInfoList(_formats);
+}
+
+int CArchiveFolderManager::FindFormat(const UString &type)
+{
+ // LoadFormats();
+ for (int i = 0; i < _formats.Size(); i++)
+ if (type.CompareNoCase(_formats[i].Name) == 0)
+ return i;
+ return -1;
+}
+
+STDMETHODIMP CArchiveFolderManager::OpenFolderFile(const wchar_t *filePath,
+ IFolderFolder **resultFolder, IProgress *progress)
+{
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallback;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback);
+ }
+ CAgent *agent = new CAgent();
+ CMyComPtr<IInFolderArchive> archive = agent;
+ RINOK(agent->Open(filePath, NULL, openArchiveCallback));
+ return agent->BindToRootFolder(resultFolder);
+}
+
+/*
+HRESULT CAgent::FolderReOpen(
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ return ReOpenArchive(_archive, _archiveFilePath);
+}
+*/
+
+STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)
+{
+ LoadFormats();
+ UString typesStrings;
+ for(int i = 0; i < _formats.Size(); i++)
+ {
+ const CArchiverInfo &ai = _formats[i];
+ if (!ai.Associate)
+ continue;
+ if (i != 0)
+ typesStrings += L' ';
+ typesStrings += ai.Name;
+ }
+ CMyComBSTR valueTemp = typesStrings;
+ *types = valueTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveFolderManager::GetExtension(const wchar_t *type, BSTR *extension)
+{
+ *extension = 0;
+ int formatIndex = FindFormat(type);
+ if (formatIndex < 0)
+ return E_INVALIDARG;
+ CMyComBSTR valueTemp = _formats[formatIndex].Extensions[0].Ext;
+ *extension = valueTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *type, BSTR *iconPath)
+{
+ *iconPath = 0;
+ int formatIndex = FindFormat(type);
+ if (formatIndex < 0)
+ return E_INVALIDARG;
+ CMyComBSTR iconPathTemp = _formats[formatIndex].FilePath;
+ *iconPath = iconPathTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveFolderManager::CreateFolderFile(const wchar_t * /* type */,
+ const wchar_t * /* filePath */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
new file mode 100755
index 00000000..4d66d86d
--- /dev/null
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
@@ -0,0 +1,215 @@
+// FolderOut.cpp
+
+#include "StdAfx.h"
+#include "Agent.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/FileDir.h"
+
+// #include "../Common/CompressEngineCommon.h"
+#include "../Common/ZipRegistry.h"
+#include "../Common/UpdateAction.h"
+#include "../Common/WorkDir.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+
+static LPCWSTR kTempArcivePrefix = L"7zA";
+
+void CAgentFolder::GetPathParts(UStringVector &pathParts)
+{
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> folder = this;
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ folder->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR name;
+ folder->GetName(&name);
+ pathParts.Insert(0, (const wchar_t *)name);
+ folder = newFolder;
+ }
+}
+
+HRESULT CAgentFolder::CommonUpdateOperation(
+ bool deleteOperation,
+ bool createFolderOperation,
+ bool renameOperation,
+ const wchar_t *newItemName,
+ const NUpdateArchive::CActionSet *actionSet,
+ const UINT32 *indices, UINT32 numItems,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ NWorkDir::CInfo workDirInfo;
+ ReadWorkDirInfo(workDirInfo);
+ UString archiveFilePath = _agentSpec->_archiveFilePath;
+ UString workDir = GetWorkDir(workDirInfo, archiveFilePath );
+ CreateComplexDirectory(workDir);
+
+ CTempFileW tempFile;
+ UString tempFileName;
+ if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)
+ return E_FAIL;
+
+ /*
+ if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK)
+ return NFileOperationReturnCode::kError;
+ */
+
+ ////////////////////////////
+ // Save FolderItem;
+
+ UStringVector pathParts;
+ GetPathParts(pathParts);
+
+ HRESULT result;
+ if (deleteOperation)
+ result = _agentSpec->DeleteItems(tempFileName,
+ indices, numItems, updateCallback100);
+ else if (createFolderOperation)
+ {
+ result = _agentSpec->CreateFolder(tempFileName,
+ newItemName, updateCallback100);
+ }
+ else if (renameOperation)
+ {
+ result = _agentSpec->RenameItem(
+ tempFileName,
+ indices, numItems,
+ newItemName,
+ updateCallback100);
+ }
+ else
+ {
+ Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
+ for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSetByte[i] = (Byte)actionSet->StateActions[i];
+ result = _agentSpec->DoOperation(NULL, NULL,
+ tempFileName, actionSetByte, NULL, updateCallback100);
+ }
+
+ if (result != S_OK)
+ return result;
+
+ _agentSpec->Close();
+
+ // m_FolderItem = NULL;
+
+ if (!DeleteFileAlways(archiveFilePath ))
+ return GetLastError();
+
+ tempFile.DisableDeleting();
+ if (!MyMoveFile(tempFileName, archiveFilePath ))
+ return GetLastError();
+
+ RINOK(_agentSpec->ReOpen(NULL));
+
+ ////////////////////////////
+ // Restore FolderItem;
+
+ CMyComPtr<IFolderFolder> archiveFolder;
+ RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
+ for (int i = 0; i < pathParts.Size(); i++)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ archiveFolder->BindToFolder(pathParts[i], &newFolder);
+ if(!newFolder)
+ break;
+ archiveFolder = newFolder;
+ }
+
+ CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
+ RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
+ CAgentFolder *agentFolder;
+ RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
+ _proxyFolderItem = agentFolder->_proxyFolderItem;
+ _proxyArchive = agentFolder->_proxyArchive;
+ _parentFolder = agentFolder->_parentFolder;
+
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::CopyFrom(
+ const wchar_t *fromFolderPath, // test it
+ const wchar_t **itemsPaths,
+ UINT32 numItems,
+ IProgress *progress)
+{
+ COM_TRY_BEGIN
+ RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(
+ IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(false, false, false, NULL,
+ &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress)
+{
+ COM_TRY_BEGIN
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(
+ IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(true, false, false, NULL,
+ &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
+{
+ COM_TRY_BEGIN
+ if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0)
+ return ERROR_ALREADY_EXISTS;
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(false, true, false, name, NULL, NULL, 0, updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress)
+{
+ COM_TRY_BEGIN
+ CUIntVector indices;
+ indices.Add(index);
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(false, false, true, newName, NULL, &indices.Front(),
+ indices.Size(), updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */,
+ const PROPVARIANT * /* value */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h
new file mode 100755
index 00000000..41d9eb22
--- /dev/null
+++ b/CPP/7zip/UI/Agent/IFolderArchive.h
@@ -0,0 +1,90 @@
+// IFolderArchive.h
+
+#ifndef __IFOLDER_ARCHIVE_H
+#define __IFOLDER_ARCHIVE_H
+
+#include "../../Archive/IArchive.h"
+// #include "../Format/Common/ArchiveInterface.h"
+#include "../../FileManager/IFolder.h"
+#include "../Common/IFileExtractCallback.h"
+#include "../Common/ExtractMode.h"
+
+// {23170F69-40C1-278A-0000-000100050000}
+DEFINE_GUID(IID_IArchiveFolder,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100050000")
+IArchiveFolder: public IUnknown
+{
+public:
+ STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2) PURE;
+};
+
+// {23170F69-40C1-278A-0000-000100060000}
+DEFINE_GUID(IID_IInFolderArchive,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100060000")
+IInFolderArchive: public IUnknown
+{
+public:
+ STDMETHOD(Open)(const wchar_t *filePath,
+ // CLSID *clsIDResult,
+ BSTR *archiveType,
+ IArchiveOpenCallback *openArchiveCallback) PURE;
+ STDMETHOD(ReOpen)(
+ // const wchar_t *filePath,
+ IArchiveOpenCallback *openArchiveCallback) PURE;
+ STDMETHOD(Close)() PURE;
+ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) PURE;
+ STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties) PURE;
+ STDMETHOD(GetPropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
+ STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties) PURE;
+ STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
+ STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) PURE;
+ STDMETHOD(Extract)(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2) PURE;
+};
+
+// {23170F69-40C1-278A-0000-0001000B0000}
+DEFINE_GUID(IID_IFolderArchiveUpdateCallback,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000B0000")
+IFolderArchiveUpdateCallback: public IProgress
+{
+public:
+ STDMETHOD(CompressOperation)(const wchar_t *name) PURE;
+ STDMETHOD(DeleteOperation)(const wchar_t *name) PURE;
+ STDMETHOD(OperationResult)(INT32 operationResult) PURE;
+ STDMETHOD(UpdateErrorMessage)(const wchar_t *message) PURE;
+};
+
+// {23170F69-40C1-278A-0000-0001000A0000}
+DEFINE_GUID(IID_IOutFolderArchive,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000A0000")
+IOutFolderArchive: public IUnknown
+{
+ STDMETHOD(SetFolder)(IFolderFolder *folder) PURE;
+ STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UINT32 numNames) PURE;
+ STDMETHOD(DeleteItems)(const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback) PURE;
+ STDMETHOD(DoOperation)(
+ const wchar_t *filePath,
+ const CLSID *clsID,
+ const wchar_t *newArchiveName,
+ const Byte *stateActions,
+ const wchar_t *sfxModule,
+ IFolderArchiveUpdateCallback *updateCallback) PURE;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
new file mode 100755
index 00000000..0d57307c
--- /dev/null
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
@@ -0,0 +1,80 @@
+// UpdateCallbackAgent.h
+
+#include "StdAfx.h"
+
+#include "Windows/Error.h"
+
+#include "UpdateCallbackAgent.h"
+
+using namespace NWindows;
+
+HRESULT CUpdateCallbackAgent::SetTotal(UINT64 size)
+{
+ if (Callback)
+ return Callback->SetTotal(size);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::SetCompleted(const UINT64 *completeValue)
+{
+ if (Callback)
+ return Callback->SetCompleted(completeValue);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::CheckBreak()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::Finilize()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError)
+{
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ if (Callback)
+ {
+ RINOK(Callback->UpdateErrorMessage(
+ UString(L"WARNING: ") +
+ NError::MyFormatMessageW(systemError) +
+ UString(L": ") +
+ UString(name)));
+ return S_FALSE;
+ }
+ }
+ // FailedFiles.Add(name);
+ return systemError;
+}
+
+HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */)
+{
+ if (Callback)
+ return Callback->CompressOperation(name);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::SetOperationResult(INT32 operationResult)
+{
+ if (Callback)
+ return Callback->OperationResult(operationResult);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password)
+{
+ *passwordIsDefined = BoolToInt(false);
+ if (!_cryptoGetTextPassword)
+ {
+ if (!Callback)
+ return S_OK;
+ HRESULT result = Callback.QueryInterface(
+ IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);
+ if (result != S_OK)
+ return S_OK;
+ }
+ return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);
+}
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
new file mode 100755
index 00000000..1cff501a
--- /dev/null
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
@@ -0,0 +1,24 @@
+// UpdateCallbackAgent.h
+
+#ifndef __UPDATECALLBACKAGENT_H
+#define __UPDATECALLBACKAGENT_H
+
+#include "../Common/UpdateCallback.h"
+#include "IFolderArchive.h"
+
+class CUpdateCallbackAgent: public IUpdateCallbackUI
+{
+ virtual HRESULT SetTotal(UINT64 size);
+ virtual HRESULT SetCompleted(const UINT64 *completeValue);
+ virtual HRESULT CheckBreak();
+ virtual HRESULT Finilize();
+ virtual HRESULT GetStream(const wchar_t *name, bool isAnti);
+ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError);
+ virtual HRESULT SetOperationResult(INT32 operationResult);
+ virtual HRESULT CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password);
+ CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
+public:
+ CMyComPtr<IFolderArchiveUpdateCallback> Callback;
+};
+
+#endif