chore: initial commit (extracted from Launchers monorepo)

Plugin: ns7zip v2.0.0
Architectures: x86-ansi, x86-unicode, amd64-unicode
License: LGPL-2.1-or-later
This commit is contained in:
Simone
2026-04-29 14:07:51 +02:00
commit d074cc7c07
3848 changed files with 1076682 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+358
View File
@@ -0,0 +1,358 @@
// Agent/Agent.h
#ifndef ZIP7_INC_AGENT_AGENT_H
#define ZIP7_INC_AGENT_AGENT_H
#include "../../../Common/MyCom.h"
#include "../../../Windows/PropVariant.h"
#include "../Common/LoadCodecs.h"
#include "../Common/OpenArchive.h"
#include "../Common/UpdateAction.h"
#include "../FileManager/IFolder.h"
#include "AgentProxy.h"
#include "IFolderArchive.h"
extern CCodecs *g_CodecsObj;
HRESULT LoadGlobalCodecs();
void FreeGlobalCodecs();
class CAgentFolder;
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACEM_IArchiveFolderInternal(x) \
x(GetAgentFolder(CAgentFolder **agentFolder))
Z7_IFACE_CONSTR_FOLDERARC(IArchiveFolderInternal, 0xC)
Z7_PURE_INTERFACES_END
struct CProxyItem
{
unsigned DirIndex;
unsigned Index;
};
class CAgent;
enum AGENT_OP
{
AGENT_OP_Uni,
AGENT_OP_Delete,
AGENT_OP_CreateFolder,
AGENT_OP_Rename,
AGENT_OP_CopyFromFile,
AGENT_OP_Comment
};
class CAgentFolder Z7_final:
public IFolderFolder,
public IFolderAltStreams,
public IFolderProperties,
public IArchiveGetRawProps,
public IGetFolderArcProps,
public IFolderCompare,
public IFolderGetItemName,
public IArchiveFolder,
public IArchiveFolderInternal,
public IInArchiveGetStream,
public IFolderSetZoneIdMode,
public IFolderSetZoneIdFile,
public IFolderOperations,
public IFolderSetFlatMode,
public CMyUnknownImp
{
Z7_COM_QI_BEGIN2(IFolderFolder)
Z7_COM_QI_ENTRY(IFolderAltStreams)
Z7_COM_QI_ENTRY(IFolderProperties)
Z7_COM_QI_ENTRY(IArchiveGetRawProps)
Z7_COM_QI_ENTRY(IGetFolderArcProps)
Z7_COM_QI_ENTRY(IFolderCompare)
Z7_COM_QI_ENTRY(IFolderGetItemName)
Z7_COM_QI_ENTRY(IArchiveFolder)
Z7_COM_QI_ENTRY(IArchiveFolderInternal)
Z7_COM_QI_ENTRY(IInArchiveGetStream)
Z7_COM_QI_ENTRY(IFolderSetZoneIdMode)
Z7_COM_QI_ENTRY(IFolderSetZoneIdFile)
Z7_COM_QI_ENTRY(IFolderOperations)
Z7_COM_QI_ENTRY(IFolderSetFlatMode)
Z7_COM_QI_END
Z7_COM_ADDREF_RELEASE
Z7_IFACE_COM7_IMP(IFolderFolder)
Z7_IFACE_COM7_IMP(IFolderAltStreams)
Z7_IFACE_COM7_IMP(IFolderProperties)
Z7_IFACE_COM7_IMP(IArchiveGetRawProps)
Z7_IFACE_COM7_IMP(IGetFolderArcProps)
Z7_IFACE_COM7_IMP(IFolderCompare)
Z7_IFACE_COM7_IMP(IFolderGetItemName)
Z7_IFACE_COM7_IMP(IArchiveFolder)
Z7_IFACE_COM7_IMP(IArchiveFolderInternal)
Z7_IFACE_COM7_IMP(IInArchiveGetStream)
Z7_IFACE_COM7_IMP(IFolderSetZoneIdMode)
Z7_IFACE_COM7_IMP(IFolderSetZoneIdFile)
Z7_IFACE_COM7_IMP(IFolderOperations)
Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
void LoadFolder(unsigned proxyDirIndex);
public:
HRESULT BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder);
HRESULT BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder);
int GetRealIndex(unsigned index) const;
void GetRealIndices(const UInt32 *indices, UInt32 numItems,
bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const;
int CompareItems3(UInt32 index1, UInt32 index2, PROPID propID);
int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
CAgentFolder():
_isAltStreamFolder(false),
_flatMode(false),
_loadAltStreams(false), // _loadAltStreams alt streams works in flat mode, but we don't use it now
_proxyDirIndex(0),
_zoneMode(NExtract::NZoneIdMode::kNone)
/* , _replaceAltStreamCharsMode(0) */
{}
void Init(const CProxyArc *proxy, const CProxyArc2 *proxy2,
unsigned proxyDirIndex,
/* IFolderFolder *parentFolder, */
CAgent *agent)
{
_proxy = proxy;
_proxy2 = proxy2;
_proxyDirIndex = proxyDirIndex;
_isAltStreamFolder = false;
if (_proxy2)
_isAltStreamFolder = _proxy2->IsAltDir(proxyDirIndex);
// _parentFolder = parentFolder;
_agent = (IInFolderArchive *)agent;
_agentSpec = agent;
}
void GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder);
HRESULT CommonUpdateOperation(
AGENT_OP operation,
bool moveMode,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UInt32 *indices, UInt32 numItems,
IProgress *progress);
void GetPrefix(UInt32 index, UString &prefix) const;
UString GetName(UInt32 index) const;
UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive
public:
bool _isAltStreamFolder;
bool _flatMode;
bool _loadAltStreams; // in Flat mode
const CProxyArc *_proxy;
const CProxyArc2 *_proxy2;
unsigned _proxyDirIndex;
NExtract::NZoneIdMode::EEnum _zoneMode;
CByteBuffer _zoneBuf;
// Int32 _replaceAltStreamCharsMode;
// CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
CRecordVector<CProxyItem> _items;
};
class CAgent Z7_final:
public IInFolderArchive,
public IFolderArcProps,
#ifndef Z7_EXTRACT_ONLY
public IOutFolderArchive,
public ISetProperties,
#endif
public CMyUnknownImp
{
Z7_COM_QI_BEGIN2(IInFolderArchive)
Z7_COM_QI_ENTRY(IFolderArcProps)
#ifndef Z7_EXTRACT_ONLY
Z7_COM_QI_ENTRY(IOutFolderArchive)
Z7_COM_QI_ENTRY(ISetProperties)
#endif
Z7_COM_QI_END
Z7_COM_ADDREF_RELEASE
Z7_IFACE_COM7_IMP(IInFolderArchive)
Z7_IFACE_COM7_IMP(IFolderArcProps)
#ifndef Z7_EXTRACT_ONLY
Z7_IFACE_COM7_IMP(ISetProperties)
public:
Z7_IFACE_COM7_IMP(IOutFolderArchive)
HRESULT CommonUpdate(ISequentialOutStream *outArchiveStream,
unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback);
HRESULT CreateFolder(ISequentialOutStream *outArchiveStream,
const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100);
HRESULT RenameItem(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100);
HRESULT CommentItem(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100);
HRESULT UpdateOneFile(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath,
IFolderArchiveUpdateCallback *updateCallback100);
#endif
private:
HRESULT ReadItems();
public:
CProxyArc *_proxy;
CProxyArc2 *_proxy2;
CArchiveLink _archiveLink;
UString ArchiveType;
FStringVector _names;
FString _folderPrefix; // for new files from disk
UString _updatePathPrefix;
CAgentFolder *_agentFolder;
UString _archiveFilePath; // it can be path of non-existing file if file is virtual
DWORD _attrib;
bool _updatePathPrefix_is_AltFolder;
bool ThereIsPathProp;
bool _isDeviceFile;
bool _isHashHandler;
FString _hashBaseFolderPrefix;
#ifndef Z7_EXTRACT_ONLY
CObjectVector<UString> m_PropNames;
CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues;
#endif
CAgent();
~CAgent();
const CArc &GetArc() const { return _archiveLink.Arcs.Back(); }
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return NULL; return GetArc().Archive; }
bool CanUpdate() const;
bool Is_Attrib_ReadOnly() const
{
return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
}
bool IsThere_ReadOnlyArc() const
{
FOR_VECTOR (i, _archiveLink.Arcs)
{
const CArc &arc = _archiveLink.Arcs[i];
if (arc.FormatIndex < 0
|| arc.IsReadOnly
|| !g_CodecsObj->Formats[arc.FormatIndex].UpdateEnabled)
return true;
}
return false;
}
UString GetTypeOfArc(const CArc &arc) const
{
if (arc.FormatIndex < 0)
return UString("Parser");
return g_CodecsObj->GetFormatNamePtr(arc.FormatIndex);
}
UString GetErrorMessage() const
{
UString s;
for (int i = (int)_archiveLink.Arcs.Size() - 1; i >= 0; i--)
{
const CArc &arc = _archiveLink.Arcs[i];
UString s2;
if (arc.ErrorInfo.ErrorFormatIndex >= 0)
{
if (arc.ErrorInfo.ErrorFormatIndex == arc.FormatIndex)
s2 += "Warning: The archive is open with offset";
else
{
s2 += "Cannot open the file as [";
s2 += g_CodecsObj->GetFormatNamePtr(arc.ErrorInfo.ErrorFormatIndex);
s2 += "] archive";
}
}
if (!arc.ErrorInfo.ErrorMessage.IsEmpty())
{
if (!s2.IsEmpty())
s2.Add_LF();
s2 += "\n[";
s2 += GetTypeOfArc(arc);
s2 += "]: ";
s2 += arc.ErrorInfo.ErrorMessage;
}
if (!s2.IsEmpty())
{
if (!s.IsEmpty())
s += "--------------------\n";
s += arc.Path;
s.Add_LF();
s += s2;
s.Add_LF();
}
}
return s;
}
void KeepModeForNextOpen() { _archiveLink.KeepModeForNextOpen(); }
};
// #ifdef NEW_FOLDER_INTERFACE
struct CCodecIcons
{
struct CIconPair
{
UString Ext;
int IconIndex;
};
CObjectVector<CIconPair> IconPairs;
// void Clear() { IconPairs.Clear(); }
void LoadIcons(HMODULE m);
bool FindIconIndex(const UString &ext, int &iconIndex) const;
};
Z7_CLASS_IMP_COM_1(
CArchiveFolderManager
, IFolderManager
)
CObjectVector<CCodecIcons> CodecIconsVector;
CCodecIcons InternalIcons;
bool WasLoaded;
void LoadFormats();
// int FindFormat(const UString &type);
public:
CArchiveFolderManager():
WasLoaded(false)
{}
};
// #endif
#endif
@@ -0,0 +1,718 @@
// AgentOut.cpp
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/TimeUtils.h"
#include "../../Compress/CopyCoder.h"
#include "../../Common/FileStreams.h"
#include "../../Archive/Common/ItemNameUtils.h"
#include "Agent.h"
#include "UpdateCallbackAgent.h"
using namespace NWindows;
using namespace NCOM;
Z7_COM7F_IMF(CAgent::SetFolder(IFolderFolder *folder))
{
_updatePathPrefix.Empty();
_updatePathPrefix_is_AltFolder = false;
_agentFolder = NULL;
if (!folder)
return S_OK;
{
Z7_DECL_CMyComPtr_QI_FROM(
IArchiveFolderInternal,
afi, folder)
if (afi)
{
RINOK(afi->GetAgentFolder(&_agentFolder))
}
if (!_agentFolder)
return E_FAIL;
}
if (_proxy2)
_updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder);
else
_updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
return S_OK;
}
Z7_COM7F_IMF(CAgent::SetFiles(const wchar_t *folderPrefix,
const wchar_t * const *names, UInt32 numNames))
{
_folderPrefix = us2fs(folderPrefix);
_names.ClearAndReserve(numNames);
for (UInt32 i = 0; i < numNames; i++)
_names.AddInReserved(us2fs(names[i]));
return S_OK;
}
static HRESULT EnumerateArchiveItems(CAgent *agent,
const CProxyDir &item,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
unsigned i;
for (i = 0; i < item.SubFiles.Size(); i++)
{
unsigned arcIndex = item.SubFiles[i];
const CProxyFile &fileItem = agent->_proxy->Files[arcIndex];
CArcItem ai;
RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime))
RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined))
ai.IsDir = false;
ai.Name = prefix + fileItem.Name;
ai.Censored = true; // test it
ai.IndexInServer = arcIndex;
arcItems.Add(ai);
}
for (i = 0; i < item.SubDirs.Size(); i++)
{
const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]];
UString fullName = prefix + dirItem.Name;
if (dirItem.IsLeaf())
{
CArcItem ai;
RINOK(agent->GetArc().GetItem_MTime((unsigned)dirItem.ArcIndex, ai.MTime))
ai.IsDir = true;
ai.Size_Defined = false;
ai.Name = fullName;
ai.Censored = true; // test it
ai.IndexInServer = (unsigned)dirItem.ArcIndex;
arcItems.Add(ai);
}
RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems))
}
return S_OK;
}
static HRESULT EnumerateArchiveItems2(const CAgent *agent,
unsigned dirIndex,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex];
FOR_VECTOR (i, dir.Items)
{
unsigned arcIndex = dir.Items[i];
const CProxyFile2 &file = agent->_proxy2->Files[arcIndex];
CArcItem ai;
ai.IndexInServer = arcIndex;
ai.Name = prefix + file.Name;
ai.Censored = true; // test it
RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime))
ai.IsDir = file.IsDir();
ai.Size_Defined = false;
ai.IsAltStream = file.IsAltStream;
if (!ai.IsDir)
{
RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined))
ai.IsDir = false;
}
arcItems.Add(ai);
if (file.AltDirIndex != -1)
{
RINOK(EnumerateArchiveItems2(agent, (unsigned)file.AltDirIndex, ai.Name + L':', arcItems))
}
if (ai.IsDir)
{
RINOK(EnumerateArchiveItems2(agent, (unsigned)file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems))
}
}
return S_OK;
}
struct CAgUpCallbackImp Z7_final: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
IFolderArchiveUpdateCallback *_callback;
CAgUpCallbackImp(const CObjectVector<CArcItem> *a,
IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}
HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override;
};
HRESULT CAgUpCallbackImp::ShowDeleteFile(unsigned arcIndex)
{
return _callback->DeleteOperation((*_arcItems)[arcIndex].Name);
}
static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd)
{
if (agent->_archiveLink.Arcs.IsEmpty())
return;
const CArc &arc = agent->GetArc();
upd->Arc = &arc;
upd->Archive = arc.Archive;
upd->ArcFileName = ExtractFileNameFromPath(arc.Path);
}
struct CDirItemsCallback_AgentOut Z7_final: public IDirItemsCallback
{
CMyComPtr<IFolderScanProgress> FolderScanProgress;
IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback;
HRESULT ErrorCode;
CDirItemsCallback_AgentOut(): FolderArchiveUpdateCallback(NULL), ErrorCode(S_OK) {}
HRESULT ScanError(const FString &name, DWORD systemError) Z7_override
{
const HRESULT hres = HRESULT_FROM_WIN32(systemError);
if (FolderArchiveUpdateCallback)
return FolderScanProgress->ScanError(fs2us(name), hres);
ErrorCode = hres;
return ErrorCode;
}
HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) Z7_override
{
if (FolderScanProgress)
return FolderScanProgress->ScanProgress(st.NumDirs, st.NumFiles + st.NumAltStreams,
st.GetTotalBytes(), fs2us(path), BoolToInt(isDir));
if (FolderArchiveUpdateCallback)
return FolderArchiveUpdateCallback->SetNumFiles(st.NumFiles);
return S_OK;
}
};
Z7_COM7F_IMF(CAgent::DoOperation(
FStringVector *requestedPaths,
FStringVector *processedPaths,
CCodecs *codecs,
int formatIndex,
ISequentialOutStream *outArchiveStream,
const Byte *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback100))
{
if (!CanUpdate())
return E_NOTIMPL;
NUpdateArchive::CActionSet actionSet;
{
for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
}
CDirItemsCallback_AgentOut enumCallback;
if (updateCallback100)
{
enumCallback.FolderArchiveUpdateCallback = updateCallback100;
updateCallback100->QueryInterface(IID_IFolderScanProgress, (void **)&enumCallback.FolderScanProgress);
}
CDirItems dirItems;
dirItems.Callback = &enumCallback;
{
FString folderPrefix = _folderPrefix;
if (!NFile::NName::IsAltStreamPrefixWithColon(fs2us(folderPrefix)))
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
RINOK(dirItems.EnumerateItems2(folderPrefix, _updatePathPrefix, _names, requestedPaths))
if (_updatePathPrefix_is_AltFolder)
{
FOR_VECTOR(i, dirItems.Items)
{
CDirItem &item = dirItems.Items[i];
if (item.IsDir())
return E_NOTIMPL;
item.IsAltStream = true;
}
}
}
CMyComPtr<IOutArchive> outArchive;
if (GetArchive())
{
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive))
}
else
{
if (formatIndex < 0)
return E_FAIL;
RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive))
#ifdef Z7_EXTERNAL_CODECS
{
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs))
}
}
#endif
}
NFileTimeType::EEnum fileTimeType = NFileTimeType::kNotDefined;
UInt32 value;
RINOK(outArchive->GetFileTimeType(&value))
// we support any future fileType here.
// 22.00:
fileTimeType = (NFileTimeType::EEnum)value;
/*
switch (value)
{
case NFileTimeType::kWindows:
case NFileTimeType::kDOS:
case NFileTimeType::kUnix:
fileTimeType = NFileTimeType::EEnum(value);
break;
default:
{
return E_FAIL;
}
}
*/
CObjectVector<CArcItem> arcItems;
if (GetArchive())
{
RINOK(ReadItems())
if (_proxy2)
{
RINOK(EnumerateArchiveItems2(this, k_Proxy2_RootDirIndex, L"", arcItems))
RINOK(EnumerateArchiveItems2(this, k_Proxy2_AltRootDirIndex, L":", arcItems))
}
else
{
RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems))
}
}
CRecordVector<CUpdatePair2> updatePairs2;
{
CRecordVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs);
CAgUpCallbackImp upCallback(&arcItems, updateCallback100);
UpdateProduce(updatePairs, actionSet, updatePairs2, &upCallback);
}
UInt32 numFiles = 0;
{
FOR_VECTOR (i, updatePairs2)
if (updatePairs2[i].NewData)
numFiles++;
}
if (updateCallback100)
{
RINOK(updateCallback100->SetNumFiles(numFiles))
}
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
updateCallback->DirItems = &dirItems;
updateCallback->ArcItems = &arcItems;
updateCallback->UpdatePairs = &updatePairs2;
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
updateCallback->Callback = &updateCallbackAgent;
CByteBuffer processedItems;
if (processedPaths)
{
unsigned num = dirItems.Items.Size();
processedItems.Alloc(num);
for (unsigned i = 0; i < num; i++)
processedItems[i] = 0;
updateCallback->ProcessedItemsStatuses = processedItems;
}
Z7_DECL_CMyComPtr_QI_FROM(
ISetProperties,
setProperties, outArchive)
if (setProperties)
{
if (m_PropNames.Size() == 0)
{
RINOK(setProperties->SetProperties(NULL, NULL, 0))
}
else
{
CRecordVector<const wchar_t *> names;
FOR_VECTOR (i, m_PropNames)
names.Add((const wchar_t *)m_PropNames[i]);
CPropVariant *propValues = new CPropVariant[m_PropValues.Size()];
try
{
FOR_VECTOR (i, m_PropValues)
propValues[i] = m_PropValues[i];
RINOK(setProperties->SetProperties(names.ConstData(), propValues, names.Size()))
}
catch(...)
{
delete []propValues;
return E_FAIL;
}
delete []propValues;
}
}
m_PropNames.Clear();
m_PropValues.Clear();
if (sfxModule != NULL)
{
CMyComPtr2_Create<IInStream, CInFileStream> sfxStream;
if (!sfxStream->Open(us2fs(sfxModule)))
return E_FAIL;
// throw "Can't open sfx module";
RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL))
}
const HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
if (res == S_OK && processedPaths)
{
{
/* OutHandler for 7z archives doesn't report compression operation for empty files.
So we must include these files manually */
FOR_VECTOR(i, updatePairs2)
{
const CUpdatePair2 &up = updatePairs2[i];
if (up.DirIndex != -1 && up.NewData)
{
const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
if (!di.IsDir() && di.Size == 0)
processedItems[(unsigned)up.DirIndex] = 1;
}
}
}
FOR_VECTOR (i, dirItems.Items)
if (processedItems[i] != 0)
processedPaths->Add(dirItems.GetPhyPath(i));
}
return res;
}
Z7_COM7F_IMF(CAgent::DoOperation2(
FStringVector *requestedPaths,
FStringVector *processedPaths,
ISequentialOutStream *outArchiveStream,
const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100))
{
return DoOperation(requestedPaths, processedPaths, g_CodecsObj, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
}
HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream,
unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback)
{
if (!CanUpdate())
return E_NOTIMPL;
CMyComPtr<IOutArchive> outArchive;
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive))
return outArchive->UpdateItems(outArchiveStream, numUpdateItems, updateCallback);
}
Z7_COM7F_IMF(CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems,
IFolderArchiveUpdateCallback *updateCallback100))
{
if (!CanUpdate())
return E_NOTIMPL;
CRecordVector<CUpdatePair2> updatePairs;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
CUIntVector realIndices;
_agentFolder->GetRealIndices(indices, numItems,
true, // includeAltStreams
false, // includeFolderSubItemsInFlatMode, we don't want to delete subItems in Flat Mode
realIndices);
unsigned curIndex = 0;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
UString deletePath;
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
if (curIndex < realIndices.Size())
if (realIndices[curIndex] == i)
{
RINOK(GetArc().GetItem_Path2(i, deletePath))
RINOK(updateCallback100->DeleteOperation(deletePath))
curIndex++;
continue;
}
CUpdatePair2 up2;
up2.SetAs_NoChangeArcItem(i);
updatePairs.Add(up2);
}
updateCallback->UpdatePairs = &updatePairs;
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
updateCallback->Callback = &updateCallbackAgent;
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
CRecordVector<CUpdatePair2> updatePairs;
CDirItems dirItems;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
up2.SetAs_NoChangeArcItem(i);
updatePairs.Add(up2);
}
CUpdatePair2 up2;
up2.NewData = up2.NewProps = true;
up2.UseArcProps = false;
up2.DirIndex = 0;
updatePairs.Add(up2);
updatePairs.ReserveDown();
CDirItem di;
di.Attrib = FILE_ATTRIBUTE_DIRECTORY;
di.Size = 0;
bool isAltStreamFolder = false;
if (_proxy2)
di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder);
else
di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
di.Name += folderName;
FILETIME ft;
NTime::GetCurUtcFileTime(ft);
di.CTime = di.ATime = di.MTime = ft;
dirItems.Items.Add(di);
updateCallback->Callback = &updateCallbackAgent;
updateCallback->DirItems = &dirItems;
updateCallback->UpdatePairs = &updatePairs;
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
if (numItems != 1)
return E_INVALIDARG;
if (!_archiveLink.IsOpen)
return E_FAIL;
CRecordVector<CUpdatePair2> updatePairs;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
CUIntVector realIndices;
_agentFolder->GetRealIndices(indices, numItems,
true, // includeAltStreams
true, // includeFolderSubItemsInFlatMode
realIndices);
const UInt32 ind0 = indices[0];
const int mainRealIndex = _agentFolder->GetRealIndex(ind0);
const UString fullPrefix = _agentFolder->GetFullPrefix(ind0);
UString name = _agentFolder->GetName(ind0);
// 22.00 : we normalize name
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
const UString oldItemPath = fullPrefix + name;
const UString newItemPath = fullPrefix + newItemName;
UStringVector newNames;
unsigned curIndex = 0;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
up2.SetAs_NoChangeArcItem(i);
if (curIndex < realIndices.Size())
if (realIndices[curIndex] == i)
{
up2.NewProps = true;
RINOK(GetArc().IsItem_Anti(i, up2.IsAnti)) // it must work without that line too.
UString oldFullPath;
RINOK(GetArc().GetItem_Path2(i, oldFullPath))
if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath))
return E_INVALIDARG;
up2.NewNameIndex = (int)newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
up2.IsMainRenameItem = (mainRealIndex == (int)i);
curIndex++;
}
updatePairs.Add(up2);
}
updateCallback->Callback = &updateCallbackAgent;
updateCallback->UpdatePairs = &updatePairs;
updateCallback->NewNames = &newNames;
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
HRESULT CAgent::CommentItem(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
if (numItems != 1)
return E_INVALIDARG;
if (!_archiveLink.IsOpen)
return E_FAIL;
CRecordVector<CUpdatePair2> updatePairs;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
const int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
if (mainRealIndex < 0)
return E_NOTIMPL;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
UString newName = newItemName;
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
up2.SetAs_NoChangeArcItem(i);
if ((int)i == mainRealIndex)
up2.NewProps = true;
updatePairs.Add(up2);
}
updateCallback->Callback = &updateCallbackAgent;
updateCallback->UpdatePairs = &updatePairs;
updateCallback->CommentIndex = mainRealIndex;
updateCallback->Comment = &newName;
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
CRecordVector<CUpdatePair2> updatePairs;
CDirItems dirItems;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
UInt32 realIndex;
{
CUIntVector realIndices;
_agentFolder->GetRealIndices(indices, numItems,
false, // includeAltStreams // we update only main stream of file
false, // includeFolderSubItemsInFlatMode
realIndices);
if (realIndices.Size() != 1)
return E_FAIL;
realIndex = realIndices[0];
}
{
FStringVector filePaths;
filePaths.Add(us2fs(diskFilePath));
dirItems.EnumerateItems2(FString(), UString(), filePaths, NULL);
if (dirItems.Items.Size() != 1)
return E_FAIL;
}
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
up2.SetAs_NoChangeArcItem(i);
if (realIndex == i)
{
up2.DirIndex = 0;
up2.NewData = true;
up2.NewProps = true;
up2.UseArcProps = false;
}
updatePairs.Add(up2);
}
updateCallback->DirItems = &dirItems;
updateCallback->Callback = &updateCallbackAgent;
updateCallback->UpdatePairs = &updatePairs;
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
updateCallback->KeepOriginalItemNames = true;
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
Z7_COM7F_IMF(CAgent::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
{
m_PropNames.Clear();
m_PropValues.Clear();
for (UInt32 i = 0; i < numProps; i++)
{
m_PropNames.Add(names[i]);
m_PropValues.Add(values[i]);
}
return S_OK;
}
@@ -0,0 +1,752 @@
// AgentProxy.cpp
#include "StdAfx.h"
// #include <stdio.h>
#ifdef _WIN32
#include <wchar.h>
#else
#include <ctype.h>
#endif
#include "../../../../C/Sort.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/UTFConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/PropVariantConv.h"
#include "../../Archive/Common/ItemNameUtils.h"
#include "AgentProxy.h"
using namespace NWindows;
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const
{
const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs;
unsigned left = 0, right = subDirs.Size();
for (;;)
{
if (left == right)
{
insertPos = left;
return -1;
}
const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned dirIndex2 = subDirs[mid];
const int comp = CompareFileNames(name, Dirs[dirIndex2].Name);
if (comp == 0)
return (int)dirIndex2;
if (comp < 0)
right = mid;
else
left = mid + 1;
}
}
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const
{
unsigned insertPos;
return FindSubDir(dirIndex, name, insertPos);
}
static const wchar_t *AllocStringAndCopy(const wchar_t *s, size_t len)
{
wchar_t *p = new wchar_t[len + 1];
MyStringCopy(p, s);
return p;
}
static const wchar_t *AllocStringAndCopy(const UString &s)
{
return AllocStringAndCopy(s, s.Len());
}
unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name)
{
unsigned insertPos;
int subDirIndex = FindSubDir(dirIndex, name, insertPos);
if (subDirIndex != -1)
{
if (arcIndex != -1)
{
CProxyDir &item = Dirs[(unsigned)subDirIndex];
if (item.ArcIndex == -1)
item.ArcIndex = arcIndex;
}
return (unsigned)subDirIndex;
}
subDirIndex = (int)Dirs.Size();
Dirs[dirIndex].SubDirs.Insert(insertPos, (unsigned)subDirIndex);
CProxyDir &item = Dirs.AddNew();
item.NameLen = name.Len();
item.Name = AllocStringAndCopy(name);
item.ArcIndex = arcIndex;
item.ParentDir = (int)dirIndex;
return (unsigned)subDirIndex;
}
void CProxyDir::Clear()
{
SubDirs.Clear();
SubFiles.Clear();
}
void CProxyArc::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const
{
pathParts.Clear();
// while (dirIndex != -1)
for (;;)
{
const CProxyDir &dir = Dirs[dirIndex];
dirIndex = (unsigned)dir.ParentDir;
if (dir.ParentDir == -1)
break;
pathParts.Insert(0, dir.Name);
// 22.00: we normalize name
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(pathParts[0]);
}
}
UString CProxyArc::GetDirPath_as_Prefix(unsigned dirIndex) const
{
UString s;
// while (dirIndex != -1)
for (;;)
{
const CProxyDir &dir = Dirs[dirIndex];
dirIndex = (unsigned)dir.ParentDir;
if (dir.ParentDir == -1)
break;
s.InsertAtFront(WCHAR_PATH_SEPARATOR);
s.Insert(0, dir.Name);
// 22.00: we normalize name
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s.GetBuf(), MyStringLen(dir.Name));
}
return s;
}
void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const
{
const CProxyDir &dir = Dirs[dirIndex];
if (dir.IsLeaf())
realIndices.Add((unsigned)dir.ArcIndex);
unsigned i;
for (i = 0; i < dir.SubDirs.Size(); i++)
AddRealIndices(dir.SubDirs[i], realIndices);
for (i = 0; i < dir.SubFiles.Size(); i++)
realIndices.Add(dir.SubFiles[i]);
}
int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const
{
const CProxyDir &dir = Dirs[dirIndex];
const unsigned numDirItems = dir.SubDirs.Size();
if (index < numDirItems)
{
const CProxyDir &f = Dirs[dir.SubDirs[index]];
if (f.IsLeaf())
return f.ArcIndex;
return -1;
}
return (int)dir.SubFiles[index - numDirItems];
}
void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
{
const CProxyDir &dir = Dirs[dirIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
const UInt32 index = indices[i];
const unsigned numDirItems = dir.SubDirs.Size();
if (index < numDirItems)
AddRealIndices(dir.SubDirs[index], realIndices);
else
realIndices.Add(dir.SubFiles[index - numDirItems]);
}
HeapSort(realIndices.NonConstData(), realIndices.Size());
}
///////////////////////////////////////////////
// CProxyArc
static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size)
{
size = 0;
NCOM::CPropVariant prop;
if (archive->GetProperty(index, propID, &prop) != S_OK)
throw 20120228;
return ConvertPropVariantToUInt64(prop, size);
}
void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive)
{
CProxyDir &dir = Dirs[dirIndex];
dir.Size = dir.PackSize = 0;
dir.NumSubDirs = dir.SubDirs.Size();
dir.NumSubFiles = dir.SubFiles.Size();
dir.CrcIsDefined = true;
dir.Crc = 0;
unsigned i;
for (i = 0; i < dir.SubFiles.Size(); i++)
{
const UInt32 index = (UInt32)dir.SubFiles[i];
UInt64 size, packSize;
const bool sizeDefined = GetSize(archive, index, kpidSize, size);
dir.Size += size;
GetSize(archive, index, kpidPackSize, packSize);
dir.PackSize += packSize;
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
{
if (prop.vt == VT_UI4)
dir.Crc += prop.ulVal;
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
dir.CrcIsDefined = false;
}
else
dir.CrcIsDefined = false;
}
}
for (i = 0; i < dir.SubDirs.Size(); i++)
{
unsigned subDirIndex = dir.SubDirs[i];
CalculateSizes(subDirIndex, archive);
CProxyDir &f = Dirs[subDirIndex];
dir.Size += f.Size;
dir.PackSize += f.PackSize;
dir.NumSubFiles += f.NumSubFiles;
dir.NumSubDirs += f.NumSubDirs;
dir.Crc += f.Crc;
if (!f.CrcIsDefined)
dir.CrcIsDefined = false;
}
}
HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
{
// DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
Files.Free();
Dirs.Clear();
Dirs.AddNew();
IInArchive *archive = arc.Archive;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems))
if (progress)
RINOK(progress->SetTotal(numItems))
Files.Alloc(numItems);
UString path;
UString name;
NCOM::CPropVariant prop;
for (UInt32 i = 0; i < numItems; i++)
{
if (progress && (i & 0xFFFF) == 0)
{
const UInt64 currentItemIndex = i;
RINOK(progress->SetCompleted(&currentItemIndex))
}
const wchar_t *s = NULL;
unsigned len = 0;
bool isPtrName = false;
#if WCHAR_PATH_SEPARATOR != L'/'
wchar_t separatorChar = WCHAR_PATH_SEPARATOR;
#endif
#if defined(MY_CPU_LE) && defined(_WIN32)
// it works only if (sizeof(wchar_t) == 2)
if (arc.GetRawProps)
{
const void *p;
UInt32 size;
UInt32 propType;
if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK
&& propType == NPropDataType::kUtf16z
&& size > 2)
{
// is (size <= 2), it's empty name, and we call default arc.GetItemPath();
len = size / 2 - 1;
s = (const wchar_t *)p;
isPtrName = true;
#if WCHAR_PATH_SEPARATOR != L'/'
separatorChar = L'/'; // 0
#endif
}
}
if (!s)
#endif
{
prop.Clear();
RINOK(arc.Archive->GetProperty(i, kpidPath, &prop))
if (prop.vt == VT_BSTR)
{
s = prop.bstrVal;
len = ::SysStringLen(prop.bstrVal);
}
else if (prop.vt != VT_EMPTY)
return E_FAIL;
if (len == 0)
{
RINOK(arc.GetItem_DefaultPath(i, path))
len = path.Len();
s = path;
}
/*
RINOK(arc.GetItemPath(i, path));
len = path.Len();
s = path;
*/
}
unsigned curItem = 0;
/*
if (arc.Ask_Deleted)
{
bool isDeleted = false;
RINOK(Archive_IsItem_Deleted(archive, i, isDeleted));
if (isDeleted)
curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
}
*/
unsigned namePos = 0;
unsigned numLevels = 0;
for (unsigned j = 0; j < len; j++)
{
const wchar_t c = s[j];
if (c == L'/'
#if WCHAR_PATH_SEPARATOR != L'/'
|| (c == separatorChar)
#endif
)
{
const unsigned kLevelLimit = 1 << 10;
if (numLevels <= kLevelLimit)
{
if (numLevels == kLevelLimit)
name = "[LONG_PATH]";
else
name.SetFrom(s + namePos, j - namePos);
// 22.00: we can normalize dir here
// NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
curItem = AddDir(curItem, -1, name);
}
namePos = j + 1;
numLevels++;
}
}
/*
that code must be implemeted to hide alt streams in list.
if (arc.Ask_AltStreams)
{
bool isAltStream;
RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
if (isAltStream)
{
}
}
*/
bool isDir;
RINOK(Archive_IsItem_Dir(archive, i, isDir))
CProxyFile &f = Files[i];
f.NameLen = len - namePos;
s += namePos;
if (isPtrName)
f.Name = s;
else
{
f.Name = AllocStringAndCopy(s, f.NameLen);
f.NeedDeleteName = true;
}
if (isDir)
{
name = s;
// 22.00: we can normalize dir here
// NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
AddDir(curItem, (int)i, name);
}
else
Dirs[curItem].SubFiles.Add(i);
}
CalculateSizes(0, archive);
// } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
return S_OK;
}
// ---------- for Tree-mode archive ----------
void CProxyArc2::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const
{
pathParts.Clear();
isAltStreamDir = false;
if (dirIndex == k_Proxy2_RootDirIndex)
return;
if (dirIndex == k_Proxy2_AltRootDirIndex)
{
isAltStreamDir = true;
return;
}
while (dirIndex >= k_Proxy2_NumRootDirs)
{
const CProxyDir2 &dir = Dirs[dirIndex];
const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
if (pathParts.IsEmpty() && (int)dirIndex == file.AltDirIndex)
isAltStreamDir = true;
pathParts.Insert(0, file.Name);
const int par = file.Parent;
if (par == -1)
break;
dirIndex = (unsigned)Files[(unsigned)par].DirIndex;
// if ((int)dirIndex == -1) break;
}
}
bool CProxyArc2::IsAltDir(unsigned dirIndex) const
{
if (dirIndex == k_Proxy2_RootDirIndex)
return false;
if (dirIndex == k_Proxy2_AltRootDirIndex)
return true;
const CProxyDir2 &dir = Dirs[dirIndex];
const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
return ((int)dirIndex == file.AltDirIndex);
}
UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const
{
isAltStreamDir = false;
const CProxyDir2 &dir = Dirs[dirIndex];
if (dirIndex == k_Proxy2_AltRootDirIndex)
isAltStreamDir = true;
else if (dirIndex >= k_Proxy2_NumRootDirs)
{
const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
isAltStreamDir = ((int)dirIndex == file.AltDirIndex);
}
return dir.PathPrefix;
}
void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const
{
realIndices.Add(arcIndex);
const CProxyFile2 &file = Files[arcIndex];
if (file.DirIndex != -1)
AddRealIndices_of_Dir((unsigned)file.DirIndex, includeAltStreams, realIndices);
if (includeAltStreams && file.AltDirIndex != -1)
AddRealIndices_of_Dir((unsigned)file.AltDirIndex, includeAltStreams, realIndices);
}
void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const
{
const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
FOR_VECTOR (i, subFiles)
{
AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices);
}
}
unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const
{
return Dirs[dirIndex].Items[index];
}
void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
{
const CProxyDir2 &dir = Dirs[dirIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices);
}
HeapSort(realIndices.NonConstData(), realIndices.Size());
}
void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
{
CProxyDir2 &dir = Dirs[dirIndex];
dir.Size = dir.PackSize = 0;
dir.NumSubDirs = 0; // dir.SubDirs.Size();
dir.NumSubFiles = 0; // dir.Files.Size();
dir.CrcIsDefined = true;
dir.Crc = 0;
FOR_VECTOR (i, dir.Items)
{
UInt32 index = dir.Items[i];
UInt64 size, packSize;
const bool sizeDefined = GetSize(archive, index, kpidSize, size);
dir.Size += size;
GetSize(archive, index, kpidPackSize, packSize);
dir.PackSize += packSize;
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
{
if (prop.vt == VT_UI4)
dir.Crc += prop.ulVal;
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
dir.CrcIsDefined = false;
}
else
dir.CrcIsDefined = false;
}
const CProxyFile2 &subFile = Files[index];
if (subFile.DirIndex == -1)
{
dir.NumSubFiles++;
}
else
{
// 22.00: we normalize name
UString s = subFile.Name;
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s);
dir.NumSubDirs++;
CProxyDir2 &f = Dirs[subFile.DirIndex];
f.PathPrefix = dir.PathPrefix + s + WCHAR_PATH_SEPARATOR;
CalculateSizes((unsigned)subFile.DirIndex, archive);
dir.Size += f.Size;
dir.PackSize += f.PackSize;
dir.NumSubFiles += f.NumSubFiles;
dir.NumSubDirs += f.NumSubDirs;
dir.Crc += f.Crc;
if (!f.CrcIsDefined)
dir.CrcIsDefined = false;
}
if (subFile.AltDirIndex == -1)
{
// dir.NumSubFiles++;
}
else
{
// dir.NumSubDirs++;
CProxyDir2 &f = Dirs[subFile.AltDirIndex];
f.PathPrefix = dir.PathPrefix + subFile.Name + L':';
CalculateSizes((unsigned)subFile.AltDirIndex, archive);
}
}
}
bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const
{
const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
FOR_VECTOR (i, subFiles)
{
const CProxyFile2 &file = Files[subFiles[i]];
if (file.IsDir())
if (CompareFileNames(name, file.Name) == 0)
return true;
}
return false;
}
HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress)
{
if (!arc.GetRawProps)
return E_FAIL;
// DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
Dirs.Clear();
Files.Free();
IInArchive *archive = arc.Archive;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems))
if (progress)
RINOK(progress->SetTotal(numItems))
UString fileName;
{
// Dirs[0] - root dir
/* CProxyDir2 &dir = */ Dirs.AddNew();
}
{
// Dirs[1] - for alt streams of root dir
CProxyDir2 &dir = Dirs.AddNew();
dir.PathPrefix = ':';
}
Files.Alloc(numItems);
UString tempUString;
AString tempAString;
UInt32 i;
for (i = 0; i < numItems; i++)
{
if (progress && (i & 0xFFFFF) == 0)
{
UInt64 currentItemIndex = i;
RINOK(progress->SetCompleted(&currentItemIndex))
}
CProxyFile2 &file = Files[i];
const void *p;
UInt32 size;
UInt32 propType;
RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType))
#ifdef MY_CPU_LE
if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
{
file.Name = (const wchar_t *)p;
file.NameLen = 0;
if (size >= sizeof(wchar_t))
file.NameLen = size / (unsigned)sizeof(wchar_t) - 1;
}
else
#endif
if (p && propType == NPropDataType::kUtf8z)
{
tempAString = (const char *)p;
ConvertUTF8ToUnicode(tempAString, tempUString);
file.NameLen = tempUString.Len();
file.Name = AllocStringAndCopy(tempUString);
file.NeedDeleteName = true;
}
else
{
NCOM::CPropVariant prop;
RINOK(arc.Archive->GetProperty(i, kpidName, &prop))
const wchar_t *s;
if (prop.vt == VT_BSTR)
s = prop.bstrVal;
else if (prop.vt == VT_EMPTY)
s = L"[Content]";
else
return E_FAIL;
file.NameLen = MyStringLen(s);
file.Name = AllocStringAndCopy(s, file.NameLen);
file.NeedDeleteName = true;
}
UInt32 parent = (UInt32)(Int32)-1;
UInt32 parentType = 0;
RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType))
file.Parent = (Int32)parent;
if (arc.Ask_Deleted)
{
bool isDeleted = false;
RINOK(Archive_IsItem_Deleted(archive, i, isDeleted))
if (isDeleted)
{
// continue;
// curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
}
}
bool isDir;
RINOK(Archive_IsItem_Dir(archive, i, isDir))
if (isDir)
{
file.DirIndex = (int)Dirs.Size();
CProxyDir2 &dir = Dirs.AddNew();
dir.ArcIndex = (int)i;
}
if (arc.Ask_AltStream)
RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream))
}
for (i = 0; i < numItems; i++)
{
CProxyFile2 &file = Files[i];
int dirIndex;
if (file.IsAltStream)
{
if (file.Parent == -1)
dirIndex = k_Proxy2_AltRootDirIndex;
else
{
int &folderIndex2 = Files[(unsigned)file.Parent].AltDirIndex;
if (folderIndex2 == -1)
{
folderIndex2 = (int)Dirs.Size();
CProxyDir2 &dir = Dirs.AddNew();
dir.ArcIndex = file.Parent;
}
dirIndex = folderIndex2;
}
}
else
{
if (file.Parent == -1)
dirIndex = k_Proxy2_RootDirIndex;
else
{
dirIndex = Files[(unsigned)file.Parent].DirIndex;
if (dirIndex == -1)
return E_FAIL;
}
}
Dirs[dirIndex].Items.Add(i);
}
for (i = 0; i < k_Proxy2_NumRootDirs; i++)
CalculateSizes(i, archive);
// } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
return S_OK;
}
int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const
{
const CProxyDir2 &dir = Dirs[dirIndex];
FOR_VECTOR (i, dir.Items)
{
const CProxyFile2 &file = Files[dir.Items[i]];
if (foldersOnly && file.DirIndex == -1)
continue;
if (CompareFileNames(file.Name, name) == 0)
return (int)i;
}
return -1;
}
@@ -0,0 +1,162 @@
// AgentProxy.h
#ifndef ZIP7_INC_AGENT_PROXY_H
#define ZIP7_INC_AGENT_PROXY_H
#include "../Common/OpenArchive.h"
struct CProxyFile
{
const wchar_t *Name;
unsigned NameLen;
bool NeedDeleteName;
CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {}
~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)(void *)Name; } // delete [](wchar_t *)Name;
};
const unsigned k_Proxy_RootDirIndex = 0;
struct CProxyDir
{
const wchar_t *Name;
unsigned NameLen;
int ArcIndex; // index in proxy->Files[] ; -1 if there is no item for that folder
int ParentDir; // index in proxy->Dirs[] ; -1 for root folder; ;
CRecordVector<unsigned> SubDirs;
CRecordVector<unsigned> SubFiles;
UInt64 Size;
UInt64 PackSize;
UInt32 Crc;
UInt32 NumSubDirs;
UInt32 NumSubFiles;
bool CrcIsDefined;
CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {}
~CProxyDir() { delete [](wchar_t *)(void *)Name; }
void Clear();
bool IsLeaf() const { return ArcIndex != -1; }
};
class CProxyArc
{
int FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const;
void CalculateSizes(unsigned dirIndex, IInArchive *archive);
unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name);
public:
CObjectVector<CProxyDir> Dirs; // Dirs[0] - root
CObjArray<CProxyFile> Files; // all items from archive in same order
// returns index in Dirs[], or -1,
int FindSubDir(unsigned dirIndex, const wchar_t *name) const;
void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const;
// returns full path of Dirs[dirIndex], including back slash
UString GetDirPath_as_Prefix(unsigned dirIndex) const;
// AddRealIndices DOES ADD also item represented by dirIndex (if it's Leaf)
void AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const;
int GetRealIndex(unsigned dirIndex, unsigned index) const;
void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const;
HRESULT Load(const CArc &arc, IProgress *progress);
};
// ---------- for Tree-mode archive ----------
struct CProxyFile2
{
int DirIndex; // >= 0 for dir. (index in ProxyArchive2->Dirs)
int AltDirIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Dirs)
int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files)
const wchar_t *Name;
unsigned NameLen;
bool NeedDeleteName;
bool Ignore;
bool IsAltStream;
int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; }
bool IsDir() const { return DirIndex != -1; }
CProxyFile2():
DirIndex(-1), AltDirIndex(-1), Parent(-1),
Name(NULL), NameLen(0),
NeedDeleteName(false),
Ignore(false),
IsAltStream(false)
{}
~CProxyFile2()
{
if (NeedDeleteName)
delete [](wchar_t *)(void *)Name;
}
};
struct CProxyDir2
{
int ArcIndex; // = -1 for root folders, index in proxy->Files[]
CRecordVector<unsigned> Items;
UString PathPrefix;
UInt64 Size;
UInt64 PackSize;
bool CrcIsDefined;
UInt32 Crc;
UInt32 NumSubDirs;
UInt32 NumSubFiles;
CProxyDir2(): ArcIndex(-1) {}
void AddFileSubItem(UInt32 index, const UString &name);
void Clear();
};
const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex;
const unsigned k_Proxy2_AltRootDirIndex = 1;
const unsigned k_Proxy2_NumRootDirs = 2;
class CProxyArc2
{
void CalculateSizes(unsigned dirIndex, IInArchive *archive);
// AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex
void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const;
public:
CObjectVector<CProxyDir2> Dirs; // Dirs[0] - root folder
// Dirs[1] - for alt streams of root dir
CObjArray<CProxyFile2> Files; // all items from archive in same order
bool IsThere_SubDir(unsigned dirIndex, const UString &name) const;
void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const;
UString GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const;
bool IsAltDir(unsigned dirIndex) const;
// AddRealIndices_of_ArcItem DOES ADD item and subItems
void AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const;
unsigned GetRealIndex(unsigned dirIndex, unsigned index) const;
void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const;
HRESULT Load(const CArc &arc, IProgress *progress);
int GetParentDirOfFile(UInt32 arcIndex) const
{
const CProxyFile2 &file = Files[arcIndex];
if (file.Parent == -1)
return file.IsAltStream ?
k_Proxy2_AltRootDirIndex :
k_Proxy2_RootDirIndex;
const CProxyFile2 &parentFile = Files[file.Parent];
return file.IsAltStream ?
parentFile.AltDirIndex :
parentFile.DirIndex;
}
int FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const;
};
#endif
@@ -0,0 +1,57 @@
// Agent/ArchiveFolder.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../Common/ArchiveExtractCallback.h"
#include "Agent.h"
/*
Z7_COM7F_IMF(CAgentFolder::SetReplaceAltStreamCharsMode(Int32 replaceAltStreamCharsMode))
{
_replaceAltStreamCharsMode = replaceAltStreamCharsMode;
return S_OK;
}
*/
Z7_COM7F_IMF(CAgentFolder::SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode))
{
_zoneMode = zoneMode;
return S_OK;
}
Z7_COM7F_IMF(CAgentFolder::SetZoneIdFile(const Byte *data, UInt32 size))
{
_zoneBuf.CopyFrom(data, size);
return S_OK;
}
Z7_COM7F_IMF(CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
Int32 includeAltStreams, Int32 replaceAltStreamCharsMode,
const wchar_t *path, IFolderOperationsExtractCallback *callback))
{
if (moveMode)
return E_NOTIMPL;
COM_TRY_BEGIN
CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
{
CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2))
}
NExtract::NPathMode::EEnum pathMode;
if (!_flatMode)
pathMode = NExtract::NPathMode::kCurPaths;
else
pathMode = (_proxy2 && _loadAltStreams) ?
NExtract::NPathMode::kNoPathsAlt :
NExtract::NPathMode::kNoPaths;
return Extract(indices, numItems,
includeAltStreams, replaceAltStreamCharsMode,
pathMode, NExtract::NOverwriteMode::kAsk,
path, BoolToInt(false), extractCallback2);
COM_TRY_END
}
@@ -0,0 +1,231 @@
// Agent/ArchiveFolderOpen.cpp
#include "StdAfx.h"
// #ifdef NEW_FOLDER_INTERFACE
#include "../../../Common/StringToInt.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/ResourceString.h"
#include "Agent.h"
extern HINSTANCE g_hInstance;
static const UINT kIconTypesResId = 100;
void CCodecIcons::LoadIcons(HMODULE m)
{
IconPairs.Clear();
UString iconTypes;
NWindows::MyLoadString(m, kIconTypesResId, iconTypes);
UStringVector pairs;
SplitString(iconTypes, pairs);
FOR_VECTOR (i, pairs)
{
const UString &s = pairs[i];
int pos = s.Find(L':');
CIconPair iconPair;
iconPair.IconIndex = -1;
if (pos < 0)
pos = (int)s.Len();
else
{
const UString num = s.Ptr((unsigned)pos + 1);
if (!num.IsEmpty())
{
const wchar_t *end;
iconPair.IconIndex = (int)ConvertStringToUInt32(num, &end);
if (*end != 0)
continue;
}
}
iconPair.Ext = s.Left((unsigned)pos);
IconPairs.Add(iconPair);
}
}
bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
{
iconIndex = -1;
FOR_VECTOR (i, IconPairs)
{
const CIconPair &pair = IconPairs[i];
if (ext.IsEqualTo_NoCase(pair.Ext))
{
iconIndex = pair.IconIndex;
return true;
}
}
return false;
}
void CArchiveFolderManager::LoadFormats()
{
if (WasLoaded)
return;
LoadGlobalCodecs();
#ifdef Z7_EXTERNAL_CODECS
CodecIconsVector.Clear();
FOR_VECTOR (i, g_CodecsObj->Libs)
{
CCodecIcons &ci = CodecIconsVector.AddNew();
ci.LoadIcons(g_CodecsObj->Libs[i].Lib.Get_HMODULE());
}
#endif
InternalIcons.LoadIcons(g_hInstance);
WasLoaded = true;
}
/*
int CArchiveFolderManager::FindFormat(const UString &type)
{
FOR_VECTOR (i, g_CodecsObj->Formats)
if (type.IsEqualTo_NoCase(g_CodecsObj->Formats[i].Name))
return (int)i;
return -1;
}
*/
Z7_COM7F_IMF(CArchiveFolderManager::OpenFolderFile(IInStream *inStream,
const wchar_t *filePath, const wchar_t *arcFormat,
IFolderFolder **resultFolder, IProgress *progress))
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallback;
if (progress)
{
CMyComPtr<IProgress> progressWrapper = progress;
progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback);
}
CAgent *agent = new CAgent();
CMyComPtr<IInFolderArchive> archive = agent;
const HRESULT res = archive->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback);
if (res != S_OK)
{
if (res != S_FALSE)
return res;
/* 20.01: we create folder even for Non-Open cases, if there is NonOpen_ErrorInfo information.
So we can get error information from that IFolderFolder later. */
if (!agent->_archiveLink.NonOpen_ErrorInfo.IsThereErrorOrWarning())
return res;
}
RINOK(archive->BindToRootFolder(resultFolder))
return res;
}
/*
HRESULT CAgent::FolderReOpen(
IArchiveOpenCallback *openArchiveCallback)
{
return ReOpenArchive(_archive, _archiveFilePath);
}
*/
/*
Z7_COM7F_IMF(CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *extensions))
{
*extensions = 0;
int formatIndex = FindFormat(type);
if (formatIndex < 0)
return E_INVALIDARG;
// Exts[0].Ext;
return StringToBstr(g_CodecsObj.Formats[formatIndex].GetAllExtensions(), extensions);
}
*/
static void AddIconExt(const CCodecIcons &lib, UString &dest)
{
FOR_VECTOR (i, lib.IconPairs)
{
dest.Add_Space_if_NotEmpty();
dest += lib.IconPairs[i].Ext;
}
}
Z7_COM7F_IMF(CArchiveFolderManager::GetExtensions(BSTR *extensions))
{
*extensions = NULL;
LoadFormats();
UString res;
#ifdef Z7_EXTERNAL_CODECS
/*
FOR_VECTOR (i, g_CodecsObj->Libs)
AddIconExt(g_CodecsObj->Libs[i].CodecIcons, res);
*/
FOR_VECTOR (i, CodecIconsVector)
AddIconExt(CodecIconsVector[i], res);
#endif
AddIconExt(
// g_CodecsObj->
InternalIcons, res);
return StringToBstr(res, extensions);
}
Z7_COM7F_IMF(CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex))
{
*iconPath = NULL;
*iconIndex = 0;
LoadFormats();
#ifdef Z7_EXTERNAL_CODECS
// FOR_VECTOR (i, g_CodecsObj->Libs)
FOR_VECTOR (i, CodecIconsVector)
{
int ii;
if (CodecIconsVector[i].FindIconIndex(ext, ii))
{
const CCodecLib &lib = g_CodecsObj->Libs[i];
*iconIndex = ii;
return StringToBstr(fs2us(lib.Path), iconPath);
}
}
#endif
int ii;
if (InternalIcons.FindIconIndex(ext, ii))
{
FString path;
if (NWindows::NDLL::MyGetModuleFileName(path))
{
*iconIndex = ii;
return StringToBstr(fs2us(path), iconPath);
}
}
return S_OK;
}
/*
Z7_COM7F_IMF(CArchiveFolderManager::GetTypes(BSTR *types))
{
LoadFormats();
UString typesStrings;
FOR_VECTOR(i, g_CodecsObj.Formats)
{
const CArcInfoEx &ai = g_CodecsObj.Formats[i];
if (ai.AssociateExts.Size() == 0)
continue;
if (i != 0)
typesStrings.Add_Space();
typesStrings += ai.Name;
}
return StringToBstr(typesStrings, types);
}
Z7_COM7F_IMF(CArchiveFolderManager::CreateFolderFile(const wchar_t * type,
const wchar_t * filePath, IProgress progress))
{
return E_NOTIMPL;
}
*/
// #endif
@@ -0,0 +1,456 @@
// ArchiveFolderOut.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../../Windows/FileDir.h"
#include "../../Common/FileStreams.h"
#include "../../Common/LimitedStreams.h"
#include "../../Compress/CopyCoder.h"
#include "../Common/WorkDir.h"
#include "Agent.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder)
{
if (_proxy2)
_proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder);
else
_proxy->GetDirPathParts(_proxyDirIndex, pathParts);
}
static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path)
{
{
const FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
CObjectVector<FString> names;
{
NFind::CDirEntry fileInfo;
NFind::CEnumerator enumerator;
enumerator.SetDirPrefix(pathPrefix);
for (;;)
{
bool found;
if (!enumerator.Next(fileInfo, found))
return false;
if (!found)
break;
if (fileInfo.IsDir())
names.Add(fileInfo.Name);
}
}
bool res = true;
FOR_VECTOR (i, names)
{
if (!Delete_EmptyFolder_And_EmptySubFolders(pathPrefix + names[i]))
res = false;
}
if (!res)
return false;
}
// we clear read-only attrib to remove read-only dir
if (!SetFileAttrib(path, 0))
return false;
return RemoveDir(path);
}
struct C_CopyFileProgress_to_FolderCallback_MoveArc Z7_final:
public ICopyFileProgress
{
IFolderArchiveUpdateCallback_MoveArc *Callback;
HRESULT CallbackResult;
virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override
{
HRESULT res = Callback->MoveArc_Progress(total, current);
CallbackResult = res;
// we can ignore E_ABORT here, because we update archive,
// and we want to get correct archive after updating
if (res == E_ABORT)
res = S_OK;
return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL;
}
C_CopyFileProgress_to_FolderCallback_MoveArc(
IFolderArchiveUpdateCallback_MoveArc *callback) :
Callback(callback),
CallbackResult(S_OK)
{}
};
HRESULT CAgentFolder::CommonUpdateOperation(
AGENT_OP operation,
bool moveMode,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UInt32 *indices, UInt32 numItems,
IProgress *progress)
{
if (moveMode && _agentSpec->_isHashHandler)
return E_NOTIMPL;
if (!_agentSpec->CanUpdate())
return E_NOTIMPL;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100);
try
{
RINOK(_agentSpec->SetFolder(this))
// ---------- Save FolderItem ----------
UStringVector pathParts;
bool isAltStreamFolder = false;
GetPathParts(pathParts, isAltStreamFolder);
FStringVector requestedPaths;
FStringVector processedPaths;
CWorkDirTempFile tempFile;
RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)))
{
CMyComPtr<IOutStream> tailStream;
const CArc &arc = *_agentSpec->_archiveLink.GetArc();
if (arc.ArcStreamOffset == 0)
tailStream = tempFile.OutStream;
else
{
if (arc.Offset < 0)
return E_NOTIMPL;
RINOK(arc.InStream->Seek(0, STREAM_SEEK_SET, NULL))
RINOK(NCompress::CopyStream_ExactSize(arc.InStream, tempFile.OutStream, arc.ArcStreamOffset, NULL))
CTailOutStream *tailStreamSpec = new CTailOutStream;
tailStream = tailStreamSpec;
tailStreamSpec->Stream = tempFile.OutStream;
tailStreamSpec->Offset = arc.ArcStreamOffset;
tailStreamSpec->Init();
}
HRESULT result;
switch ((int)operation)
{
case AGENT_OP_Delete:
result = _agentSpec->DeleteItems(tailStream, indices, numItems, updateCallback100);
break;
case AGENT_OP_CreateFolder:
result = _agentSpec->CreateFolder(tailStream, newItemName, updateCallback100);
break;
case AGENT_OP_Rename:
result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100);
break;
case AGENT_OP_Comment:
result = _agentSpec->CommentItem(tailStream, indices, numItems, newItemName, updateCallback100);
break;
case AGENT_OP_CopyFromFile:
result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100);
break;
case AGENT_OP_Uni:
{
Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSetByte[i] = (Byte)actionSet->StateActions[i];
result = _agentSpec->DoOperation2(
moveMode ? &requestedPaths : NULL,
moveMode ? &processedPaths : NULL,
tailStream, actionSetByte, NULL, updateCallback100);
break;
}
default:
return E_FAIL;
}
RINOK(result)
}
_agentSpec->KeepModeForNextOpen();
_agent->Close();
// before 9.26: if there was error for MoveToOriginal archive was closed.
// now: we reopen archive after close
// m_FolderItem = NULL;
_items.Clear();
_proxyDirIndex = k_Proxy_RootDirIndex;
CMyComPtr<IFolderArchiveUpdateCallback_MoveArc> updateCallback_MoveArc;
if (progress)
progress->QueryInterface(IID_IFolderArchiveUpdateCallback_MoveArc, (void **)&updateCallback_MoveArc);
HRESULT res;
if (updateCallback_MoveArc)
{
const FString &tempFilePath = tempFile.Get_TempFilePath();
UInt64 totalSize = 0;
{
NFind::CFileInfo fi;
if (fi.Find(tempFilePath))
totalSize = fi.Size;
}
RINOK(updateCallback_MoveArc->MoveArc_Start(
fs2us(tempFilePath),
fs2us(tempFile.Get_OriginalFilePath()),
totalSize,
1)) // updateMode
C_CopyFileProgress_to_FolderCallback_MoveArc prox(updateCallback_MoveArc);
res = tempFile.MoveToOriginal(
true, // deleteOriginal
&prox);
if (res == S_OK)
{
res = updateCallback_MoveArc->MoveArc_Finish();
// we don't return after E_ABORT here, because
// we want to reopen new archive still.
}
else if (prox.CallbackResult != S_OK)
res = prox.CallbackResult;
// if updating callback returned E_ABORT,
// then openCallback still can return E_ABORT also.
// So ReOpen() will return with E_ABORT.
// But we want to open archive still.
// And Before_ArcReopen() call will clear user break status in that case.
RINOK(updateCallback_MoveArc->Before_ArcReopen())
}
else
res = tempFile.MoveToOriginal(true); // deleteOriginal
// RINOK(res);
if (res == S_OK)
{
if (moveMode)
{
unsigned i;
for (i = 0; i < processedPaths.Size(); i++)
{
DeleteFileAlways(processedPaths[i]);
}
for (i = 0; i < requestedPaths.Size(); i++)
{
const FString &fs = requestedPaths[i];
if (NFind::DoesDirExist(fs))
Delete_EmptyFolder_And_EmptySubFolders(fs);
}
}
}
{
CMyComPtr<IArchiveOpenCallback> openCallback;
if (updateCallback100)
updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback);
RINOK(_agent->ReOpen(openCallback))
}
// CAgent::ReOpen() deletes _proxy and _proxy2
// _items.Clear();
_proxy = NULL;
_proxy2 = NULL;
// _proxyDirIndex = k_Proxy_RootDirIndex;
_isAltStreamFolder = false;
// ---------- Restore FolderItem ----------
CMyComPtr<IFolderFolder> archiveFolder;
RINOK(_agent->BindToRootFolder(&archiveFolder))
// CAgent::BindToRootFolder() changes _proxy and _proxy2
_proxy = _agentSpec->_proxy;
_proxy2 = _agentSpec->_proxy2;
if (_proxy)
{
FOR_VECTOR (i, pathParts)
{
const int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]);
if (next == -1)
break;
_proxyDirIndex = (unsigned)next;
}
}
if (_proxy2)
{
if (pathParts.IsEmpty() && isAltStreamFolder)
{
_proxyDirIndex = k_Proxy2_AltRootDirIndex;
}
else FOR_VECTOR (i, pathParts)
{
const bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder);
const int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly);
if (index == -1)
break;
const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]];
if (dirOnly)
_proxyDirIndex = (unsigned)file.DirIndex;
else
{
if (file.AltDirIndex != -1)
_proxyDirIndex = (unsigned)file.AltDirIndex;
break;
}
}
}
/*
if (pathParts.IsEmpty() && isAltStreamFolder)
{
CMyComPtr<IFolderAltStreams> folderAltStreams;
archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams);
if (folderAltStreams)
{
CMyComPtr<IFolderFolder> newFolder;
folderAltStreams->BindToAltStreams((UInt32)(Int32)-1, &newFolder);
if (newFolder)
archiveFolder = newFolder;
}
}
FOR_VECTOR (i, pathParts)
{
CMyComPtr<IFolderFolder> newFolder;
if (isAltStreamFolder && i == pathParts.Size() - 1)
{
CMyComPtr<IFolderAltStreams> folderAltStreams;
archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams);
if (folderAltStreams)
folderAltStreams->BindToAltStreams(pathParts[i], &newFolder);
}
else
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));
_proxyDirIndex = agentFolder->_proxyDirIndex;
// _parentFolder = agentFolder->_parentFolder;
*/
if (_proxy2)
_isAltStreamFolder = _proxy2->IsAltDir(_proxyDirIndex);
return res;
}
catch(const UString &s)
{
if (updateCallback100)
{
UString s2 ("Error: ");
s2 += s;
RINOK(updateCallback100->UpdateErrorMessage(s2))
return E_FAIL;
}
throw;
}
}
Z7_COM7F_IMF(CAgentFolder::CopyFrom(Int32 moveMode,
const wchar_t *fromFolderPath, /* test it */
const wchar_t * const *itemsPaths,
UInt32 numItems,
IProgress *progress))
{
COM_TRY_BEGIN
{
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems))
return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL,
&NUpdateArchive::k_ActionSet_Add,
NULL, 0, progress);
}
COM_TRY_END
}
Z7_COM7F_IMF(CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress *progress))
{
COM_TRY_BEGIN
return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath,
&NUpdateArchive::k_ActionSet_Add,
&destIndex, 1, progress);
COM_TRY_END
}
Z7_COM7F_IMF(CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress))
{
COM_TRY_BEGIN
return CommonUpdateOperation(AGENT_OP_Delete, false, NULL,
&NUpdateArchive::k_ActionSet_Delete, indices, numItems, progress);
COM_TRY_END
}
Z7_COM7F_IMF(CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress))
{
COM_TRY_BEGIN
if (_isAltStreamFolder)
return E_NOTIMPL;
if (_proxy2)
{
if (_proxy2->IsThere_SubDir(_proxyDirIndex, name))
return ERROR_ALREADY_EXISTS;
}
else
{
if (_proxy->FindSubDir(_proxyDirIndex, name) != -1)
return ERROR_ALREADY_EXISTS;
}
return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, progress);
COM_TRY_END
}
Z7_COM7F_IMF(CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress))
{
COM_TRY_BEGIN
return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL,
&index, 1, progress);
COM_TRY_END
}
Z7_COM7F_IMF(CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */))
{
return E_NOTIMPL;
}
Z7_COM7F_IMF(CAgentFolder::SetProperty(UInt32 index, PROPID propID,
const PROPVARIANT *value, IProgress *progress))
{
COM_TRY_BEGIN
if (propID != kpidComment || value->vt != VT_BSTR)
return E_NOTIMPL;
if (!_agentSpec || !_agentSpec->GetTypeOfArc(_agentSpec->GetArc()).IsEqualTo_Ascii_NoCase("zip"))
return E_NOTIMPL;
return CommonUpdateOperation(AGENT_OP_Comment, false, value->bstrVal, NULL,
&index, 1, progress);
COM_TRY_END
}
@@ -0,0 +1,123 @@
// IFolderArchive.h
#ifndef ZIP7_INC_IFOLDER_ARCHIVE_H
#define ZIP7_INC_IFOLDER_ARCHIVE_H
#include "../../../Common/MyString.h"
#include "../../Archive/IArchive.h"
#include "../../UI/Common/LoadCodecs.h"
#include "../../UI/FileManager/IFolder.h"
#include "../Common/ExtractMode.h"
#include "../Common/IFileExtractCallback.h"
Z7_PURE_INTERFACES_BEGIN
/* ---------- IArchiveFolder ----------
IArchiveFolder is implemented by CAgentFolder (Agent/Agent.h)
IArchiveFolder is used by:
- FileManager/PanelCopy.cpp
CPanel::CopyTo(), if (options->testMode)
- FAR/PluginRead.cpp
CPlugin::ExtractFiles
*/
#define Z7_IFACEM_IArchiveFolder(x) \
x(Extract(const UInt32 *indices, UInt32 numItems, \
Int32 includeAltStreams, \
Int32 replaceAltStreamCharsMode, \
NExtract::NPathMode::EEnum pathMode, \
NExtract::NOverwriteMode::EEnum overwriteMode, \
const wchar_t *path, Int32 testMode, \
IFolderArchiveExtractCallback *extractCallback2)) \
Z7_IFACE_CONSTR_FOLDERARC(IArchiveFolder, 0x0D)
/* ---------- IInFolderArchive ----------
IInFolderArchive is implemented by CAgent (Agent/Agent.h)
IInFolderArchive Is used by FAR/Plugin
*/
#define Z7_IFACEM_IInFolderArchive(x) \
x(Open(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback)) \
x(ReOpen(IArchiveOpenCallback *openArchiveCallback)) \
x(Close()) \
x(GetNumberOfProperties(UInt32 *numProperties)) \
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
x(BindToRootFolder(IFolderFolder **resultFolder)) \
x(Extract(NExtract::NPathMode::EEnum pathMode, \
NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \
Int32 testMode, IFolderArchiveExtractCallback *extractCallback2)) \
Z7_IFACE_CONSTR_FOLDERARC(IInFolderArchive, 0x0E)
#define Z7_IFACEM_IFolderArchiveUpdateCallback(x) \
x(CompressOperation(const wchar_t *name)) \
x(DeleteOperation(const wchar_t *name)) \
x(OperationResult(Int32 opRes)) \
x(UpdateErrorMessage(const wchar_t *message)) \
x(SetNumFiles(UInt64 numFiles)) \
Z7_IFACE_CONSTR_FOLDERARC_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)
#define Z7_IFACEM_IOutFolderArchive(x) \
x(SetFolder(IFolderFolder *folder)) \
x(SetFiles(const wchar_t *folderPrefix, const wchar_t * const *names, UInt32 numNames)) \
x(DeleteItems(ISequentialOutStream *outArchiveStream, \
const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback)) \
x(DoOperation( \
FStringVector *requestedPaths, \
FStringVector *processedPaths, \
CCodecs *codecs, int index, \
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
IFolderArchiveUpdateCallback *updateCallback)) \
x(DoOperation2( \
FStringVector *requestedPaths, \
FStringVector *processedPaths, \
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
IFolderArchiveUpdateCallback *updateCallback)) \
Z7_IFACE_CONSTR_FOLDERARC(IOutFolderArchive, 0x0F)
#define Z7_IFACEM_IFolderArchiveUpdateCallback2(x) \
x(OpenFileError(const wchar_t *path, HRESULT errorCode)) \
x(ReadingFileError(const wchar_t *path, HRESULT errorCode)) \
x(ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *path)) \
x(ReportUpdateOperation(UInt32 notifyOp, const wchar_t *path, Int32 isDir)) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveUpdateCallback2, 0x10)
#define Z7_IFACEM_IFolderScanProgress(x) \
x(ScanError(const wchar_t *path, HRESULT errorCode)) \
x(ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 isDir)) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderScanProgress, 0x11)
#define Z7_IFACEM_IFolderSetZoneIdMode(x) \
x(SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode)) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdMode, 0x12)
#define Z7_IFACEM_IFolderSetZoneIdFile(x) \
x(SetZoneIdFile(const Byte *data, UInt32 size)) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdFile, 0x13)
// if the caller calls Before_ArcReopen(), the callee must
// clear user break status, because the caller want to open archive still.
#define Z7_IFACEM_IFolderArchiveUpdateCallback_MoveArc(x) \
x(MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode)) \
x(MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)) \
x(MoveArc_Finish()) \
x(Before_ArcReopen()) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveUpdateCallback_MoveArc, 0x14)
Z7_PURE_INTERFACES_END
#endif
+11
View File
@@ -0,0 +1,11 @@
// StdAfx.h
#ifndef ZIP7_INC_STDAFX_H
#define ZIP7_INC_STDAFX_H
#if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..'
#endif
#include "../../../Common/Common.h"
#endif
@@ -0,0 +1,208 @@
// UpdateCallbackAgent.h
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Windows/ErrorMsg.h"
#include "UpdateCallbackAgent.h"
using namespace NWindows;
void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback)
{
Callback = callback;
_compressProgress.Release();
Callback2.Release();
if (Callback)
{
Callback.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
Callback.QueryInterface(IID_IFolderArchiveUpdateCallback2, &Callback2);
}
}
HRESULT CUpdateCallbackAgent::SetNumItems(const CArcToDoStat &stat)
{
if (Callback)
return Callback->SetNumFiles(stat.Get_NumDataItems_Total());
return S_OK;
}
HRESULT CUpdateCallbackAgent::WriteSfx(const wchar_t * /* name */, UInt64 /* size */)
{
return S_OK;
}
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::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
if (_compressProgress)
return _compressProgress->SetRatioInfo(inSize, outSize);
return S_OK;
}
HRESULT CUpdateCallbackAgent::CheckBreak()
{
return S_OK;
}
/*
HRESULT CUpdateCallbackAgent::Finalize()
{
return S_OK;
}
*/
HRESULT CUpdateCallbackAgent::OpenFileError(const FString &path, DWORD systemError)
{
const HRESULT hres = HRESULT_FROM_WIN32(systemError);
// if (systemError == ERROR_SHARING_VIOLATION)
{
if (Callback2)
{
RINOK(Callback2->OpenFileError(fs2us(path), hres))
return S_FALSE;
}
if (Callback)
{
UString s ("WARNING: ");
s += NError::MyFormatMessage(systemError);
s += ": ";
s += fs2us(path);
RINOK(Callback->UpdateErrorMessage(s))
return S_FALSE;
}
}
// FailedFiles.Add(name);
return hres;
}
HRESULT CUpdateCallbackAgent::ReadingFileError(const FString &path, DWORD systemError)
{
const HRESULT hres = HRESULT_FROM_WIN32(systemError);
// if (systemError == ERROR_SHARING_VIOLATION)
{
if (Callback2)
{
RINOK(Callback2->ReadingFileError(fs2us(path), hres))
}
else if (Callback)
{
UString s ("ERROR: ");
s += NError::MyFormatMessage(systemError);
s += ": ";
s += fs2us(path);
RINOK(Callback->UpdateErrorMessage(s))
}
}
// FailedFiles.Add(name);
return hres;
}
HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool isDir, bool /* isAnti */, UInt32 mode)
{
if (Callback2)
return Callback2->ReportUpdateOperation(mode, name, BoolToInt(isDir));
if (Callback)
return Callback->CompressOperation(name);
return S_OK;
}
HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult)
{
if (Callback)
return Callback->OperationResult(operationResult);
return S_OK;
}
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
HRESULT CUpdateCallbackAgent::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
{
if (Callback2)
{
return Callback2->ReportExtractResult(opRes, isEncrypted, name);
}
/*
if (mode != NArchive::NExtract::NOperationResult::kOK)
{
Int32 encrypted = 0;
UString s;
SetExtractErrorMessage(mode, encrypted, name, s);
// ProgressDialog->Sync.AddError_Message(s);
}
*/
return S_OK;
}
HRESULT CUpdateCallbackAgent::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir)
{
if (Callback2)
{
return Callback2->ReportUpdateOperation(op, name, BoolToInt(isDir));
}
return S_OK;
}
/*
HRESULT CUpdateCallbackAgent::SetPassword(const UString &
#ifndef Z7_NO_CRYPTO
password
#endif
)
{
#ifndef Z7_NO_CRYPTO
PasswordIsDefined = true;
Password = password;
#endif
return S_OK;
}
*/
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
*password = NULL;
*passwordIsDefined = BoolToInt(false);
if (!_cryptoGetTextPassword)
{
if (!Callback)
return S_OK;
Callback.QueryInterface(IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);
if (!_cryptoGetTextPassword)
return S_OK;
}
return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);
}
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password)
{
*password = NULL;
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
Callback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
if (!getTextPassword)
return E_NOTIMPL;
return getTextPassword->CryptoGetTextPassword(password);
}
HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
{
return Callback->DeleteOperation(name);
}
@@ -0,0 +1,22 @@
// UpdateCallbackAgent.h
#ifndef ZIP7_INC_UPDATE_CALLBACK_AGENT_H
#define ZIP7_INC_UPDATE_CALLBACK_AGENT_H
#include "../Common/UpdateCallback.h"
#include "IFolderArchive.h"
class CUpdateCallbackAgent Z7_final: public IUpdateCallbackUI
{
Z7_IFACE_IMP(IUpdateCallbackUI)
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
CMyComPtr<IFolderArchiveUpdateCallback> Callback;
CMyComPtr<IFolderArchiveUpdateCallback2> Callback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
public:
void SetCallback(IFolderArchiveUpdateCallback *callback);
};
#endif