From d9666cf046a8453b33b3e2fbf4d82295a9f87df3 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Sat, 20 Jan 2007 00:00:00 +0000 Subject: 4.44 beta --- CPP/7zip/UI/Agent/Agent.cpp | 578 ++++++++++++++++++++++++++++++ CPP/7zip/UI/Agent/Agent.h | 314 ++++++++++++++++ CPP/7zip/UI/Agent/AgentOut.cpp | 518 ++++++++++++++++++++++++++ CPP/7zip/UI/Agent/AgentProxy.cpp | 203 +++++++++++ CPP/7zip/UI/Agent/AgentProxy.h | 56 +++ CPP/7zip/UI/Agent/ArchiveFolder.cpp | 72 ++++ CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp | 98 +++++ CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | 215 +++++++++++ CPP/7zip/UI/Agent/IFolderArchive.h | 90 +++++ CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp | 80 +++++ CPP/7zip/UI/Agent/UpdateCallbackAgent.h | 24 ++ 11 files changed, 2248 insertions(+) create mode 100755 CPP/7zip/UI/Agent/Agent.cpp create mode 100755 CPP/7zip/UI/Agent/Agent.h create mode 100755 CPP/7zip/UI/Agent/AgentOut.cpp create mode 100755 CPP/7zip/UI/Agent/AgentProxy.cpp create mode 100755 CPP/7zip/UI/Agent/AgentProxy.h create mode 100755 CPP/7zip/UI/Agent/ArchiveFolder.cpp create mode 100755 CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp create mode 100755 CPP/7zip/UI/Agent/ArchiveFolderOut.cpp create mode 100755 CPP/7zip/UI/Agent/IFolderArchive.h create mode 100755 CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp create mode 100755 CPP/7zip/UI/Agent/UpdateCallbackAgent.h (limited to 'CPP/7zip/UI/Agent') 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 parentFolder; + if (folder->Parent != _proxyFolderItem) + { + RINOK(BindToFolder(folder->Parent, &parentFolder)); + } + else + parentFolder = this; + CAgentFolder *folderSpec = new CAgentFolder; + CMyComPtr 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 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 currentFolder = this; + for (;;) + { + CMyComPtr 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 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 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 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 _parentFolder; + CMyComPtr _agent; + CAgent *_agentSpec; + + CRecordVector _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 m_RootFolder; + + UString DefaultName; + + FILETIME DefaultTime; + UINT32 DefaultAttributes; + + UString ArchiveType; + + UStringVector _names; + UString _folderPrefix; + + UString _archiveNamePrefix; + CAgentFolder *_agentFolder; + + UString _archiveFilePath; + + #ifndef EXTRACT_ONLY + CObjectVector m_PropNames; + CObjectVector 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 _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 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 archiveFolder = folder; + CMyComPtr archiveFolderInternal; + RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal)); + RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder)); + } + + UStringVector pathParts; + pathParts.Clear(); + CMyComPtr folderItem = folder; + if (folderItem != NULL) + for (;;) + { + CMyComPtr 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 &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 dirItems; + + UString folderPrefix = _folderPrefix; + NFile::NName::NormalizeDirPathPrefix(folderPrefix); + UStringVector errorPaths; + CRecordVector errorCodes; + ::EnumerateDirItems(folderPrefix, _names, _archiveNamePrefix, dirItems, errorPaths, errorCodes); + if (errorCodes.Size() > 0) + { + return errorCodes.Front(); + } + + NWindows::NDLL::CLibrary library; + + CMyComPtr 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 updatePairs; + + CObjectVector archiveItems; + if (GetArchive()) + { + RINOK(ReadItems()); + EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", archiveItems); + } + + GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); + + CObjectVector updatePairs2; + UpdateProduce(updatePairs, actionSet, updatePairs2); + + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.Callback = updateCallback100; + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr 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 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 setProperties; + if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) + { + if (m_PropNames.Size() == 0) + { + RINOK(setProperties->SetProperties(0, 0, 0)); + } + else + { + CRecordVector 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 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 outArchive; + RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive)); + + COutFileStream *outStreamSpec = new COutFileStream; + CMyComPtr 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 updateCallback(updateCallbackSpec); + + CUIntVector realIndices; + _agentFolder->GetRealIndices(indices, numItems, realIndices); + CObjectVector 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 updateCallback(updateCallbackSpec); + + CObjectVector 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 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 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 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(¤tItemIndex)); + } + 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 Folders; + CObjectVector 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 extractCallback = extractCallbackSpec; + UStringVector pathParts; + CProxyFolder *currentProxyFolder = _proxyFolderItem; + while (currentProxyFolder->Parent) + { + pathParts.Insert(0, currentProxyFolder->Name); + currentProxyFolder = currentProxyFolder->Parent; + } + + CMyComPtr extractCallback2; + { + CMyComPtr 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 openArchiveCallback; + if (progress != 0) + { + CMyComPtr progressWrapper = progress; + progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback); + } + CAgent *agent = new CAgent(); + CMyComPtr 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 folder = this; + for (;;) + { + CMyComPtr 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 archiveFolder; + RINOK(_agentSpec->BindToRootFolder(&archiveFolder)); + for (int i = 0; i < pathParts.Size(); i++) + { + CMyComPtr newFolder; + archiveFolder->BindToFolder(pathParts[i], &newFolder); + if(!newFolder) + break; + archiveFolder = newFolder; + } + + CMyComPtr 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 updateCallback100; + if (progress != 0) + { + CMyComPtr 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 updateCallback100; + if (progress != 0) + { + CMyComPtr 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 updateCallback100; + if (progress != 0) + { + CMyComPtr 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 updateCallback100; + if (progress != 0) + { + CMyComPtr 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 _cryptoGetTextPassword; +public: + CMyComPtr Callback; +}; + +#endif -- cgit v1.2.3