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:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
// Agent/Agent.h
|
||||
|
||||
#ifndef __AGENT_AGENT_H
|
||||
#define __AGENT_AGENT_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/OpenArchive.h"
|
||||
#include "../Common/UpdateAction.h"
|
||||
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
#include "../FileManager/IFolder.h"
|
||||
#include "../Common/LoadCodecs.h"
|
||||
#endif
|
||||
|
||||
#include "AgentProxy.h"
|
||||
#include "IFolderArchive.h"
|
||||
|
||||
extern CCodecs *g_CodecsObj;
|
||||
HRESULT LoadGlobalCodecs();
|
||||
void FreeGlobalCodecs();
|
||||
|
||||
class CAgentFolder;
|
||||
|
||||
DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)
|
||||
{
|
||||
STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder) PURE;
|
||||
};
|
||||
|
||||
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:
|
||||
public IFolderFolder,
|
||||
public IFolderAltStreams,
|
||||
public IFolderProperties,
|
||||
public IArchiveGetRawProps,
|
||||
public IGetFolderArcProps,
|
||||
public IFolderCompare,
|
||||
public IFolderGetItemName,
|
||||
public IArchiveFolder,
|
||||
public IArchiveFolderInternal,
|
||||
public IInArchiveGetStream,
|
||||
// public IFolderSetReplaceAltStreamCharsMode,
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
public IFolderOperations,
|
||||
public IFolderSetFlatMode,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
void LoadFolder(unsigned proxyDirIndex);
|
||||
public:
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderAltStreams)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderProperties)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderCompare)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
|
||||
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
|
||||
// MY_QUERYINTERFACE_ENTRY(IFolderSetReplaceAltStreamCharsMode)
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderOperations)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
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;
|
||||
|
||||
// INTERFACE_FolderSetReplaceAltStreamCharsMode(;)
|
||||
|
||||
INTERFACE_FolderFolder(;)
|
||||
INTERFACE_FolderAltStreams(;)
|
||||
INTERFACE_FolderProperties(;)
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
INTERFACE_IFolderGetItemName(;)
|
||||
|
||||
STDMETHOD(GetFolderArcProps)(IFolderArcProps **object);
|
||||
STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
|
||||
int CompareItems3(UInt32 index1, UInt32 index2, PROPID propID);
|
||||
int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
|
||||
|
||||
// IArchiveFolder
|
||||
INTERFACE_IArchiveFolder(;)
|
||||
|
||||
STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder);
|
||||
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
INTERFACE_FolderOperations(;)
|
||||
|
||||
STDMETHOD(SetFlatMode)(Int32 flatMode);
|
||||
#endif
|
||||
|
||||
CAgentFolder():
|
||||
_proxyDirIndex(0),
|
||||
_isAltStreamFolder(false),
|
||||
_flatMode(false),
|
||||
_loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now
|
||||
/* , _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:
|
||||
const CProxyArc *_proxy;
|
||||
const CProxyArc2 *_proxy2;
|
||||
unsigned _proxyDirIndex;
|
||||
bool _isAltStreamFolder;
|
||||
// CMyComPtr<IFolderFolder> _parentFolder;
|
||||
CMyComPtr<IInFolderArchive> _agent;
|
||||
CAgent *_agentSpec;
|
||||
|
||||
CRecordVector<CProxyItem> _items;
|
||||
bool _flatMode;
|
||||
bool _loadAltStreams; // in Flat mode
|
||||
// Int32 _replaceAltStreamCharsMode;
|
||||
};
|
||||
|
||||
class CAgent:
|
||||
public IInFolderArchive,
|
||||
public IFolderArcProps,
|
||||
#ifndef EXTRACT_ONLY
|
||||
public IOutFolderArchive,
|
||||
public ISetProperties,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(IInFolderArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderArcProps)
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInFolderArchive(;)
|
||||
INTERFACE_IFolderArcProps(;)
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
INTERFACE_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);
|
||||
|
||||
// ISetProperties
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
#endif
|
||||
|
||||
CAgent();
|
||||
~CAgent();
|
||||
private:
|
||||
HRESULT ReadItems();
|
||||
public:
|
||||
CProxyArc *_proxy;
|
||||
CProxyArc2 *_proxy2;
|
||||
CArchiveLink _archiveLink;
|
||||
|
||||
bool ThereIsPathProp;
|
||||
// bool ThereIsAltStreamProp;
|
||||
|
||||
UString ArchiveType;
|
||||
|
||||
FStringVector _names;
|
||||
FString _folderPrefix;
|
||||
|
||||
bool _updatePathPrefix_is_AltFolder;
|
||||
UString _updatePathPrefix;
|
||||
CAgentFolder *_agentFolder;
|
||||
|
||||
UString _archiveFilePath;
|
||||
DWORD _attrib;
|
||||
bool _isDeviceFile;
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
CObjectVector<UString> m_PropNames;
|
||||
CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues;
|
||||
#endif
|
||||
|
||||
const CArc &GetArc() const { return _archiveLink.Arcs.Back(); }
|
||||
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
|
||||
bool CanUpdate() const;
|
||||
|
||||
bool Is_Attrib_ReadOnly() const
|
||||
{
|
||||
return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
|
||||
}
|
||||
|
||||
bool IsThereReadOnlyArc() 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 = _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 += "Can not 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
|
||||
|
||||
class CArchiveFolderManager:
|
||||
public IFolderManager,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
void LoadFormats();
|
||||
int FindFormat(const UString &type);
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(IFolderManager)
|
||||
INTERFACE_IFolderManager(;)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,709 @@
|
||||
// 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 "Agent.h"
|
||||
#include "UpdateCallbackAgent.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
|
||||
{
|
||||
_updatePathPrefix.Empty();
|
||||
_updatePathPrefix_is_AltFolder = false;
|
||||
_agentFolder = NULL;
|
||||
|
||||
if (!folder)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
CMyComPtr<IArchiveFolderInternal> afi;
|
||||
RINOK(folder->QueryInterface(IID_IArchiveFolderInternal, (void **)&afi));
|
||||
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;
|
||||
}
|
||||
|
||||
STDMETHODIMP 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().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
|
||||
RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
|
||||
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().GetItemMTime(dirItem.ArcIndex, ai.MTime, ai.MTimeDefined));
|
||||
ai.IsDir = true;
|
||||
ai.SizeDefined = false;
|
||||
ai.Name = fullName;
|
||||
ai.Censored = true; // test it
|
||||
ai.IndexInServer = 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().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
|
||||
ai.IsDir = file.IsDir();
|
||||
ai.SizeDefined = false;
|
||||
ai.IsAltStream = file.IsAltStream;
|
||||
if (!ai.IsDir)
|
||||
{
|
||||
RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
|
||||
ai.IsDir = false;
|
||||
}
|
||||
arcItems.Add(ai);
|
||||
|
||||
if (file.AltDirIndex >= 0)
|
||||
{
|
||||
RINOK(EnumerateArchiveItems2(agent, file.AltDirIndex, ai.Name + L':', arcItems));
|
||||
}
|
||||
|
||||
if (ai.IsDir)
|
||||
{
|
||||
RINOK(EnumerateArchiveItems2(agent, file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct CAgUpCallbackImp: public IUpdateProduceCallback
|
||||
{
|
||||
const CObjectVector<CArcItem> *_arcItems;
|
||||
IFolderArchiveUpdateCallback *_callback;
|
||||
|
||||
CAgUpCallbackImp(const CObjectVector<CArcItem> *a,
|
||||
IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}
|
||||
HRESULT ShowDeleteFile(unsigned arcIndex);
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
struct CDirItemsCallback_AgentOut: public IDirItemsCallback
|
||||
{
|
||||
CMyComPtr<IFolderScanProgress> FolderScanProgress;
|
||||
IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback;
|
||||
HRESULT ErrorCode;
|
||||
|
||||
CDirItemsCallback_AgentOut(): ErrorCode(S_OK), FolderArchiveUpdateCallback(NULL) {}
|
||||
|
||||
HRESULT ScanError(const FString &name, DWORD systemError)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
STDMETHODIMP 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;
|
||||
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(formatIndex, outArchive));
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
{
|
||||
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
|
||||
outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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<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);
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
|
||||
|
||||
updateCallbackSpec->DirItems = &dirItems;
|
||||
updateCallbackSpec->ArcItems = &arcItems;
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs2;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallbackSpec);
|
||||
|
||||
updateCallbackSpec->Callback = &updateCallbackAgent;
|
||||
|
||||
CByteBuffer processedItems;
|
||||
if (processedPaths)
|
||||
{
|
||||
unsigned num = dirItems.Items.Size();
|
||||
processedItems.Alloc(num);
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
processedItems[i] = 0;
|
||||
updateCallbackSpec->ProcessedItemsStatuses = processedItems;
|
||||
}
|
||||
|
||||
CMyComPtr<ISetProperties> setProperties;
|
||||
if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)
|
||||
{
|
||||
if (m_PropNames.Size() == 0)
|
||||
{
|
||||
RINOK(setProperties->SetProperties(0, 0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
CRecordVector<const wchar_t *> names;
|
||||
FOR_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.Front(), propValues, names.Size()));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
delete []propValues;
|
||||
return E_FAIL;
|
||||
}
|
||||
delete []propValues;
|
||||
}
|
||||
}
|
||||
m_PropNames.Clear();
|
||||
m_PropValues.Clear();
|
||||
|
||||
if (sfxModule != NULL)
|
||||
{
|
||||
CInFileStream *sfxStreamSpec = new CInFileStream;
|
||||
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
|
||||
if (!sfxStreamSpec->Open(us2fs(sfxModule)))
|
||||
return E_FAIL;
|
||||
// throw "Can't open sfx module";
|
||||
RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL));
|
||||
}
|
||||
|
||||
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 >= 0 && up.NewData)
|
||||
{
|
||||
const CDirItem &di = dirItems.Items[up.DirIndex];
|
||||
if (!di.IsDir() && di.Size == 0)
|
||||
processedItems[up.DirIndex] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, dirItems.Items)
|
||||
if (processedItems[i] != 0)
|
||||
processedPaths->Add(dirItems.GetPhyPath(i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP 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);
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems,
|
||||
IFolderArchiveUpdateCallback *updateCallback100)
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
CRecordVector<CUpdatePair2> updatePairs;
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
|
||||
|
||||
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().GetItemPath2(i, deletePath));
|
||||
RINOK(updateCallback100->DeleteOperation(deletePath));
|
||||
|
||||
curIndex++;
|
||||
continue;
|
||||
}
|
||||
CUpdatePair2 up2;
|
||||
up2.SetAs_NoChangeArcItem(i);
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallbackSpec);
|
||||
|
||||
updateCallbackSpec->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);
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
|
||||
|
||||
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);
|
||||
|
||||
updateCallbackSpec->Callback = &updateCallbackAgent;
|
||||
updateCallbackSpec->DirItems = &dirItems;
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallbackSpec);
|
||||
|
||||
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);
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
|
||||
|
||||
CUIntVector realIndices;
|
||||
_agentFolder->GetRealIndices(indices, numItems,
|
||||
true, // includeAltStreams
|
||||
true, // includeFolderSubItemsInFlatMode
|
||||
realIndices);
|
||||
|
||||
int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
|
||||
|
||||
UString fullPrefix = _agentFolder->GetFullPrefix(indices[0]);
|
||||
UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);
|
||||
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().IsItemAnti(i, up2.IsAnti)); // it must work without that line too.
|
||||
|
||||
UString oldFullPath;
|
||||
RINOK(GetArc().GetItemPath2(i, oldFullPath));
|
||||
|
||||
if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath))
|
||||
return E_INVALIDARG;
|
||||
|
||||
up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
|
||||
up2.IsMainRenameItem = (mainRealIndex == (int)i);
|
||||
curIndex++;
|
||||
}
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
|
||||
updateCallbackSpec->Callback = &updateCallbackAgent;
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs;
|
||||
updateCallbackSpec->NewNames = &newNames;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallbackSpec);
|
||||
|
||||
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);
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
updateCallbackSpec->Callback = &updateCallbackAgent;
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs;
|
||||
updateCallbackSpec->CommentIndex = mainRealIndex;
|
||||
updateCallbackSpec->Comment = &newName;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallbackSpec);
|
||||
|
||||
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);
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
|
||||
|
||||
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);
|
||||
}
|
||||
updateCallbackSpec->DirItems = &dirItems;
|
||||
updateCallbackSpec->Callback = &updateCallbackAgent;
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallbackSpec);
|
||||
|
||||
updateCallbackSpec->KeepOriginalItemNames = true;
|
||||
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
|
||||
}
|
||||
|
||||
STDMETHODIMP 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,717 @@
|
||||
// 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 "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;
|
||||
}
|
||||
unsigned mid = (left + right) / 2;
|
||||
unsigned dirIndex2 = subDirs[mid];
|
||||
int compare = CompareFileNames(name, Dirs[dirIndex2].Name);
|
||||
if (compare == 0)
|
||||
return dirIndex2;
|
||||
if (compare < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const
|
||||
{
|
||||
unsigned insertPos;
|
||||
return FindSubDir(dirIndex, name, insertPos);
|
||||
}
|
||||
|
||||
unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name)
|
||||
{
|
||||
unsigned insertPos;
|
||||
int subDirIndex = FindSubDir(dirIndex, name, insertPos);
|
||||
if (subDirIndex >= 0)
|
||||
{
|
||||
if (arcIndex >= 0)
|
||||
{
|
||||
CProxyDir &item = Dirs[subDirIndex];
|
||||
if (item.ArcIndex < 0)
|
||||
item.ArcIndex = arcIndex;
|
||||
}
|
||||
return subDirIndex;
|
||||
}
|
||||
subDirIndex = Dirs.Size();
|
||||
Dirs[dirIndex].SubDirs.Insert(insertPos, subDirIndex);
|
||||
CProxyDir &item = Dirs.AddNew();
|
||||
|
||||
item.NameLen = name.Len();
|
||||
item.Name = new wchar_t[item.NameLen + 1];
|
||||
MyStringCopy((wchar_t *)item.Name, name);
|
||||
|
||||
item.ArcIndex = arcIndex;
|
||||
item.ParentDir = dirIndex;
|
||||
return subDirIndex;
|
||||
}
|
||||
|
||||
void CProxyDir::Clear()
|
||||
{
|
||||
SubDirs.Clear();
|
||||
SubFiles.Clear();
|
||||
}
|
||||
|
||||
void CProxyArc::GetDirPathParts(int dirIndex, UStringVector &pathParts) const
|
||||
{
|
||||
pathParts.Clear();
|
||||
while (dirIndex >= 0)
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
dirIndex = dir.ParentDir;
|
||||
if (dirIndex < 0)
|
||||
break;
|
||||
pathParts.Insert(0, dir.Name);
|
||||
}
|
||||
}
|
||||
|
||||
UString CProxyArc::GetDirPath_as_Prefix(int dirIndex) const
|
||||
{
|
||||
UString s;
|
||||
while (dirIndex >= 0)
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
dirIndex = dir.ParentDir;
|
||||
if (dirIndex < 0)
|
||||
break;
|
||||
s.InsertAtFront(WCHAR_PATH_SEPARATOR);
|
||||
s.Insert(0, dir.Name);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
if (dir.IsLeaf())
|
||||
realIndices.Add(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];
|
||||
unsigned numDirItems = dir.SubDirs.Size();
|
||||
if (index < numDirItems)
|
||||
{
|
||||
const CProxyDir &f = Dirs[dir.SubDirs[index]];
|
||||
if (f.IsLeaf())
|
||||
return f.ArcIndex;
|
||||
return -1;
|
||||
}
|
||||
return 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++)
|
||||
{
|
||||
UInt32 index = indices[i];
|
||||
unsigned numDirItems = dir.SubDirs.Size();
|
||||
if (index < numDirItems)
|
||||
AddRealIndices(dir.SubDirs[index], realIndices);
|
||||
else
|
||||
realIndices.Add(dir.SubFiles[index - numDirItems]);
|
||||
}
|
||||
HeapSort(&realIndices.Front(), 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++)
|
||||
{
|
||||
UInt32 index = (UInt32)dir.SubFiles[i];
|
||||
UInt64 size, packSize;
|
||||
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)
|
||||
{
|
||||
UInt64 currentItemIndex = i;
|
||||
RINOK(progress->SetCompleted(¤tItemIndex));
|
||||
}
|
||||
|
||||
const wchar_t *s = NULL;
|
||||
unsigned len = 0;
|
||||
bool isPtrName = false;
|
||||
|
||||
#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 (!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.GetDefaultItemPath(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++)
|
||||
{
|
||||
wchar_t c = s[j];
|
||||
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
|
||||
{
|
||||
const unsigned kLevelLimit = 1 << 10;
|
||||
if (numLevels <= kLevelLimit)
|
||||
{
|
||||
if (numLevels == kLevelLimit)
|
||||
name = "[LONG_PATH]";
|
||||
else
|
||||
name.SetFrom(s + namePos, j - namePos);
|
||||
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 = new wchar_t[f.NameLen + 1];
|
||||
f.NeedDeleteName = true;
|
||||
MyStringCopy((wchar_t *)f.Name, s);
|
||||
}
|
||||
|
||||
if (isDir)
|
||||
{
|
||||
name = s;
|
||||
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(int 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[dir.ArcIndex];
|
||||
if (pathParts.IsEmpty() && dirIndex == file.AltDirIndex)
|
||||
isAltStreamDir = true;
|
||||
pathParts.Insert(0, file.Name);
|
||||
int par = file.Parent;
|
||||
if (par < 0)
|
||||
break;
|
||||
dirIndex = Files[par].DirIndex;
|
||||
}
|
||||
}
|
||||
|
||||
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[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[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 >= 0)
|
||||
AddRealIndices_of_Dir(file.DirIndex, includeAltStreams, realIndices);
|
||||
if (includeAltStreams && file.AltDirIndex >= 0)
|
||||
AddRealIndices_of_Dir(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.Front(), 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;
|
||||
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 < 0)
|
||||
{
|
||||
dir.NumSubFiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir.NumSubDirs++;
|
||||
CProxyDir2 &f = Dirs[subFile.DirIndex];
|
||||
f.PathPrefix = dir.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR;
|
||||
CalculateSizes(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 < 0)
|
||||
{
|
||||
// dir.NumSubFiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dir.NumSubDirs++;
|
||||
CProxyDir2 &f = Dirs[subFile.AltDirIndex];
|
||||
f.PathPrefix = dir.PathPrefix + subFile.Name + L':';
|
||||
CalculateSizes(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(¤tItemIndex));
|
||||
}
|
||||
|
||||
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 / sizeof(wchar_t) - 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (p && propType == NPropDataType::kUtf8z)
|
||||
{
|
||||
tempAString = (const char *)p;
|
||||
ConvertUTF8ToUnicode(tempAString, tempUString);
|
||||
file.NameLen = tempUString.Len();
|
||||
file.Name = new wchar_t[file.NameLen + 1];
|
||||
file.NeedDeleteName = true;
|
||||
wmemcpy((wchar_t *)file.Name, tempUString.Ptr(), file.NameLen + 1);
|
||||
}
|
||||
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 = new wchar_t[file.NameLen + 1];
|
||||
file.NeedDeleteName = true;
|
||||
wmemcpy((wchar_t *)file.Name, s, file.NameLen + 1);
|
||||
}
|
||||
|
||||
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 = Dirs.Size();
|
||||
CProxyDir2 &dir = Dirs.AddNew();
|
||||
dir.ArcIndex = 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 < 0)
|
||||
dirIndex = k_Proxy2_AltRootDirIndex;
|
||||
else
|
||||
{
|
||||
int &folderIndex2 = Files[file.Parent].AltDirIndex;
|
||||
if (folderIndex2 < 0)
|
||||
{
|
||||
folderIndex2 = Dirs.Size();
|
||||
CProxyDir2 &dir = Dirs.AddNew();
|
||||
dir.ArcIndex = file.Parent;
|
||||
}
|
||||
dirIndex = folderIndex2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file.Parent < 0)
|
||||
dirIndex = k_Proxy2_RootDirIndex;
|
||||
else
|
||||
{
|
||||
dirIndex = Files[file.Parent].DirIndex;
|
||||
if (dirIndex < 0)
|
||||
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 < 0)
|
||||
continue;
|
||||
if (CompareFileNames(file.Name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// AgentProxy.h
|
||||
|
||||
#ifndef __AGENT_PROXY_H
|
||||
#define __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 *)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 *)Name; }
|
||||
|
||||
void Clear();
|
||||
bool IsLeaf() const { return ArcIndex >= 0; }
|
||||
};
|
||||
|
||||
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(int dirIndex, UStringVector &pathParts) const;
|
||||
// returns full path of Dirs[dirIndex], including back slash
|
||||
UString GetDirPath_as_Prefix(int 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 >= 0; }
|
||||
CProxyFile2():
|
||||
DirIndex(-1), AltDirIndex(-1), Parent(-1),
|
||||
Name(NULL), NameLen(0),
|
||||
NeedDeleteName(false),
|
||||
Ignore(false),
|
||||
IsAltStream(false)
|
||||
{}
|
||||
~CProxyFile2()
|
||||
{
|
||||
if (NeedDeleteName)
|
||||
delete [](wchar_t *)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(int 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 < 0)
|
||||
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,44 @@
|
||||
// Agent/ArchiveFolder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../Common/ArchiveExtractCallback.h"
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
/*
|
||||
STDMETHODIMP CAgentFolder::SetReplaceAltStreamCharsMode(Int32 replaceAltStreamCharsMode)
|
||||
{
|
||||
_replaceAltStreamCharsMode = replaceAltStreamCharsMode;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP 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,141 @@
|
||||
// Agent/ArchiveFolderOpen.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Windows/DLL.h"
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
void CArchiveFolderManager::LoadFormats()
|
||||
{
|
||||
LoadGlobalCodecs();
|
||||
}
|
||||
|
||||
int CArchiveFolderManager::FindFormat(const UString &type)
|
||||
{
|
||||
FOR_VECTOR (i, g_CodecsObj->Formats)
|
||||
if (type.IsEqualTo_NoCase(g_CodecsObj->Formats[i].Name))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
STDMETHODIMP 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;
|
||||
RINOK(agent->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback));
|
||||
return agent->BindToRootFolder(resultFolder);
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CAgent::FolderReOpen(
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
return ReOpenArchive(_archive, _archiveFilePath);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
STDMETHODIMP 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;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions)
|
||||
{
|
||||
LoadFormats();
|
||||
*extensions = 0;
|
||||
UString res;
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
FOR_VECTOR (i, g_CodecsObj->Libs)
|
||||
AddIconExt(g_CodecsObj->Libs[i], res);
|
||||
|
||||
#endif
|
||||
|
||||
AddIconExt(g_CodecsObj->InternalIcons, res);
|
||||
return StringToBstr(res, extensions);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex)
|
||||
{
|
||||
*iconPath = 0;
|
||||
*iconIndex = 0;
|
||||
|
||||
LoadFormats();
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
FOR_VECTOR (i, g_CodecsObj->Libs)
|
||||
{
|
||||
const CCodecLib &lib = g_CodecsObj->Libs[i];
|
||||
int ii;
|
||||
if (lib.FindIconIndex(ext, ii))
|
||||
{
|
||||
*iconIndex = ii;
|
||||
return StringToBstr(fs2us(lib.Path), iconPath);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int ii;
|
||||
if (g_CodecsObj->InternalIcons.FindIconIndex(ext, ii))
|
||||
{
|
||||
FString path;
|
||||
if (NWindows::NDLL::MyGetModuleFileName(path))
|
||||
{
|
||||
*iconIndex = ii;
|
||||
return StringToBstr(fs2us(path), iconPath);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
STDMETHODIMP 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);
|
||||
}
|
||||
STDMETHODIMP CArchiveFolderManager::CreateFolderFile(const wchar_t * type,
|
||||
const wchar_t * filePath, IProgress progress)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,373 @@
|
||||
// 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 DeleteEmptyFolderAndEmptySubFolders(const FString &path)
|
||||
{
|
||||
NFind::CFileInfo fileInfo;
|
||||
FString pathPrefix = path;
|
||||
pathPrefix.Add_PathSepar();
|
||||
{
|
||||
NFind::CEnumerator enumerator;
|
||||
enumerator.SetDirPrefix(pathPrefix);
|
||||
while (enumerator.Next(fileInfo))
|
||||
{
|
||||
if (fileInfo.IsDir())
|
||||
if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// we don't need clear readonly for folders
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
*/
|
||||
return RemoveDir(path);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CAgentFolder::CommonUpdateOperation(
|
||||
AGENT_OP operation,
|
||||
bool moveMode,
|
||||
const wchar_t *newItemName,
|
||||
const NUpdateArchive::CActionSet *actionSet,
|
||||
const UInt32 *indices, UInt32 numItems,
|
||||
IProgress *progress)
|
||||
{
|
||||
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 (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 (int 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();
|
||||
_agentSpec->Close();
|
||||
|
||||
// before 9.26: if there was error for MoveToOriginal archive was closed.
|
||||
// now: we reopen archive after close
|
||||
|
||||
// m_FolderItem = NULL;
|
||||
|
||||
HRESULT res = tempFile.MoveToOriginal(true);
|
||||
|
||||
// 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))
|
||||
DeleteEmptyFolderAndEmptySubFolders(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback;
|
||||
if (updateCallback100)
|
||||
updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback);
|
||||
RINOK(_agentSpec->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(_agentSpec->BindToRootFolder(&archiveFolder));
|
||||
|
||||
// CAgent::BindToRootFolder() changes _proxy and _proxy2
|
||||
_proxy = _agentSpec->_proxy;
|
||||
_proxy2 = _agentSpec->_proxy2;
|
||||
|
||||
if (_proxy)
|
||||
{
|
||||
FOR_VECTOR (i, pathParts)
|
||||
{
|
||||
int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]);
|
||||
if (next < 0)
|
||||
break;
|
||||
_proxyDirIndex = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (_proxy2)
|
||||
{
|
||||
if (pathParts.IsEmpty() && isAltStreamFolder)
|
||||
{
|
||||
_proxyDirIndex = k_Proxy2_AltRootDirIndex;
|
||||
}
|
||||
else FOR_VECTOR (i, pathParts)
|
||||
{
|
||||
bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder);
|
||||
int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly);
|
||||
if (index < 0)
|
||||
break;
|
||||
|
||||
const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]];
|
||||
|
||||
if (dirOnly)
|
||||
_proxyDirIndex = file.DirIndex;
|
||||
else
|
||||
{
|
||||
if (file.AltDirIndex >= 0)
|
||||
_proxyDirIndex = 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP 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
|
||||
}
|
||||
|
||||
STDMETHODIMP 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
|
||||
}
|
||||
|
||||
STDMETHODIMP 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
|
||||
}
|
||||
|
||||
STDMETHODIMP 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) >= 0)
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, progress);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP 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
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP 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,119 @@
|
||||
// IFolderArchive.h
|
||||
|
||||
#ifndef __IFOLDER_ARCHIVE_H
|
||||
#define __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"
|
||||
|
||||
#define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x)
|
||||
#define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
|
||||
|
||||
/* ---------- 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 INTERFACE_IArchiveFolder(x) \
|
||||
STDMETHOD(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) x; \
|
||||
|
||||
FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x0D)
|
||||
{
|
||||
INTERFACE_IArchiveFolder(PURE)
|
||||
};
|
||||
|
||||
|
||||
/* ---------- IInFolderArchive ----------
|
||||
IInFolderArchive is implemented by CAgent (Agent/Agent.h)
|
||||
IInFolderArchive Is used by FAR/Plugin
|
||||
*/
|
||||
|
||||
#define INTERFACE_IInFolderArchive(x) \
|
||||
STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \
|
||||
STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
|
||||
STDMETHOD(Close)() x; \
|
||||
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
|
||||
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
|
||||
STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) x; \
|
||||
STDMETHOD(Extract)(NExtract::NPathMode::EEnum pathMode, \
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \
|
||||
Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \
|
||||
|
||||
FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E)
|
||||
{
|
||||
INTERFACE_IInFolderArchive(PURE)
|
||||
};
|
||||
|
||||
#define INTERFACE_IFolderArchiveUpdateCallback(x) \
|
||||
STDMETHOD(CompressOperation)(const wchar_t *name) x; \
|
||||
STDMETHOD(DeleteOperation)(const wchar_t *name) x; \
|
||||
STDMETHOD(OperationResult)(Int32 opRes) x; \
|
||||
STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \
|
||||
STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \
|
||||
|
||||
FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)
|
||||
{
|
||||
INTERFACE_IFolderArchiveUpdateCallback(PURE)
|
||||
};
|
||||
|
||||
#define INTERFACE_IOutFolderArchive(x) \
|
||||
STDMETHOD(SetFolder)(IFolderFolder *folder) x; \
|
||||
STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t * const *names, UInt32 numNames) x; \
|
||||
STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \
|
||||
const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \
|
||||
STDMETHOD(DoOperation)( \
|
||||
FStringVector *requestedPaths, \
|
||||
FStringVector *processedPaths, \
|
||||
CCodecs *codecs, int index, \
|
||||
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
|
||||
IFolderArchiveUpdateCallback *updateCallback) x; \
|
||||
STDMETHOD(DoOperation2)( \
|
||||
FStringVector *requestedPaths, \
|
||||
FStringVector *processedPaths, \
|
||||
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
|
||||
IFolderArchiveUpdateCallback *updateCallback) x; \
|
||||
|
||||
FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0F)
|
||||
{
|
||||
INTERFACE_IOutFolderArchive(PURE)
|
||||
};
|
||||
|
||||
|
||||
#define INTERFACE_IFolderArchiveUpdateCallback2(x) \
|
||||
STDMETHOD(OpenFileError)(const wchar_t *path, HRESULT errorCode) x; \
|
||||
STDMETHOD(ReadingFileError)(const wchar_t *path, HRESULT errorCode) x; \
|
||||
STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 isEncrypted, const wchar_t *path) x; \
|
||||
STDMETHOD(ReportUpdateOperation)(UInt32 notifyOp, const wchar_t *path, Int32 isDir) x; \
|
||||
|
||||
FOLDER_ARCHIVE_INTERFACE(IFolderArchiveUpdateCallback2, 0x10)
|
||||
{
|
||||
INTERFACE_IFolderArchiveUpdateCallback2(PURE)
|
||||
};
|
||||
|
||||
|
||||
#define INTERFACE_IFolderScanProgress(x) \
|
||||
STDMETHOD(ScanError)(const wchar_t *path, HRESULT errorCode) x; \
|
||||
STDMETHOD(ScanProgress)(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 isDir) x; \
|
||||
|
||||
FOLDER_ARCHIVE_INTERFACE(IFolderScanProgress, 0x11)
|
||||
{
|
||||
INTERFACE_IFolderScanProgress(PURE)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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::ReportUpdateOpeartion(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 _NO_CRYPTO
|
||||
password
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifndef _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 __UPDATE_CALLBACK_AGENT_H
|
||||
#define __UPDATE_CALLBACK_AGENT_H
|
||||
|
||||
#include "../Common/UpdateCallback.h"
|
||||
|
||||
#include "IFolderArchive.h"
|
||||
|
||||
class CUpdateCallbackAgent: public IUpdateCallbackUI
|
||||
{
|
||||
INTERFACE_IUpdateCallbackUI(;)
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
|
||||
CMyComPtr<IFolderArchiveUpdateCallback> Callback;
|
||||
CMyComPtr<IFolderArchiveUpdateCallback2> Callback2;
|
||||
CMyComPtr<ICompressProgressInfo> _compressProgress;
|
||||
public:
|
||||
void SetCallback(IFolderArchiveUpdateCallback *callback);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,993 @@
|
||||
// Client7z.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include "../../../Common/Defs.h"
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/DLL.h"
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileFind.h"
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/NtCheck.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/PropVariantConv.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
#include "../../../../C/7zVersion.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
HINSTANCE g_hInstance = 0;
|
||||
#endif
|
||||
|
||||
// Tou can find the list of all GUIDs in Guid.txt file.
|
||||
// use another CLSIDs, if you want to support other formats (zip, rar, ...).
|
||||
// {23170F69-40C1-278A-1000-000110070000}
|
||||
|
||||
DEFINE_GUID(CLSID_CFormat7z,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
|
||||
DEFINE_GUID(CLSID_CFormatXz,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00);
|
||||
|
||||
#define CLSID_Format CLSID_CFormat7z
|
||||
// #define CLSID_Format CLSID_CFormatXz
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
#define kDllName "7z.dll"
|
||||
|
||||
static const char * const kCopyrightString =
|
||||
"\n"
|
||||
"7-Zip"
|
||||
" (" kDllName " client)"
|
||||
" " MY_VERSION
|
||||
" : " MY_COPYRIGHT_DATE
|
||||
"\n";
|
||||
|
||||
static const char * const kHelpString =
|
||||
"Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n"
|
||||
"Examples:\n"
|
||||
" 7zcl.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n"
|
||||
" 7zcl.exe l archive.7z : List contents of archive.7z\n"
|
||||
" 7zcl.exe x archive.7z : eXtract files from archive.7z\n";
|
||||
|
||||
|
||||
static void Convert_UString_to_AString(const UString &s, AString &temp)
|
||||
{
|
||||
int codePage = CP_OEMCP;
|
||||
/*
|
||||
int g_CodePage = -1;
|
||||
int codePage = g_CodePage;
|
||||
if (codePage == -1)
|
||||
codePage = CP_OEMCP;
|
||||
if (codePage == CP_UTF8)
|
||||
ConvertUnicodeToUTF8(s, temp);
|
||||
else
|
||||
*/
|
||||
UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
|
||||
}
|
||||
|
||||
static FString CmdStringToFString(const char *s)
|
||||
{
|
||||
return us2fs(GetUnicodeString(s));
|
||||
}
|
||||
|
||||
static void Print(const char *s)
|
||||
{
|
||||
fputs(s, stdout);
|
||||
}
|
||||
|
||||
static void Print(const AString &s)
|
||||
{
|
||||
Print(s.Ptr());
|
||||
}
|
||||
|
||||
static void Print(const UString &s)
|
||||
{
|
||||
AString as;
|
||||
Convert_UString_to_AString(s, as);
|
||||
Print(as);
|
||||
}
|
||||
|
||||
static void Print(const wchar_t *s)
|
||||
{
|
||||
Print(UString(s));
|
||||
}
|
||||
|
||||
static void PrintNewLine()
|
||||
{
|
||||
Print("\n");
|
||||
}
|
||||
|
||||
static void PrintStringLn(const char *s)
|
||||
{
|
||||
Print(s);
|
||||
PrintNewLine();
|
||||
}
|
||||
|
||||
static void PrintError(const char *message)
|
||||
{
|
||||
Print("Error: ");
|
||||
PrintNewLine();
|
||||
Print(message);
|
||||
PrintNewLine();
|
||||
}
|
||||
|
||||
static void PrintError(const char *message, const FString &name)
|
||||
{
|
||||
PrintError(message);
|
||||
Print(name);
|
||||
}
|
||||
|
||||
|
||||
static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, propID, &prop));
|
||||
if (prop.vt == VT_BOOL)
|
||||
result = VARIANT_BOOLToBool(prop.boolVal);
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
result = false;
|
||||
else
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
|
||||
{
|
||||
return IsArchiveItemProp(archive, index, kpidIsDir, result);
|
||||
}
|
||||
|
||||
|
||||
static const wchar_t * const kEmptyFileAlias = L"[Content]";
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Archive Open callback class
|
||||
|
||||
|
||||
class CArchiveOpenCallback:
|
||||
public IArchiveOpenCallback,
|
||||
public ICryptoGetTextPassword,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
|
||||
|
||||
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
|
||||
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
|
||||
CArchiveOpenCallback() : PasswordIsDefined(false) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
if (!PasswordIsDefined)
|
||||
{
|
||||
// You can ask real password here from user
|
||||
// Password = GetPassword(OutStream);
|
||||
// PasswordIsDefined = true;
|
||||
PrintError("Password is not defined");
|
||||
return E_ABORT;
|
||||
}
|
||||
return StringToBstr(Password, password);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char * const kIncorrectCommand = "incorrect command";
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Archive Extracting callback class
|
||||
|
||||
static const char * const kTestingString = "Testing ";
|
||||
static const char * const kExtractingString = "Extracting ";
|
||||
static const char * const kSkippingString = "Skipping ";
|
||||
|
||||
static const char * const kUnsupportedMethod = "Unsupported Method";
|
||||
static const char * const kCRCFailed = "CRC Failed";
|
||||
static const char * const kDataError = "Data Error";
|
||||
static const char * const kUnavailableData = "Unavailable data";
|
||||
static const char * const kUnexpectedEnd = "Unexpected end of data";
|
||||
static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
|
||||
static const char * const kIsNotArc = "Is not archive";
|
||||
static const char * const kHeadersError = "Headers Error";
|
||||
|
||||
|
||||
class CArchiveExtractCallback:
|
||||
public IArchiveExtractCallback,
|
||||
public ICryptoGetTextPassword,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
|
||||
|
||||
// IProgress
|
||||
STDMETHOD(SetTotal)(UInt64 size);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
|
||||
|
||||
// IArchiveExtractCallback
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
|
||||
STDMETHOD(PrepareOperation)(Int32 askExtractMode);
|
||||
STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
|
||||
|
||||
// ICryptoGetTextPassword
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
|
||||
|
||||
private:
|
||||
CMyComPtr<IInArchive> _archiveHandler;
|
||||
FString _directoryPath; // Output directory
|
||||
UString _filePath; // name inside arcvhive
|
||||
FString _diskFilePath; // full path to file on disk
|
||||
bool _extractMode;
|
||||
struct CProcessedFileInfo
|
||||
{
|
||||
FILETIME MTime;
|
||||
UInt32 Attrib;
|
||||
bool isDir;
|
||||
bool AttribDefined;
|
||||
bool MTimeDefined;
|
||||
} _processedFileInfo;
|
||||
|
||||
COutFileStream *_outFileStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _outFileStream;
|
||||
|
||||
public:
|
||||
void Init(IInArchive *archiveHandler, const FString &directoryPath);
|
||||
|
||||
UInt64 NumErrors;
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
|
||||
CArchiveExtractCallback() : PasswordIsDefined(false) {}
|
||||
};
|
||||
|
||||
void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath)
|
||||
{
|
||||
NumErrors = 0;
|
||||
_archiveHandler = archiveHandler;
|
||||
_directoryPath = directoryPath;
|
||||
NName::NormalizeDirPathPrefix(_directoryPath);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
|
||||
ISequentialOutStream **outStream, Int32 askExtractMode)
|
||||
{
|
||||
*outStream = 0;
|
||||
_outFileStream.Release();
|
||||
|
||||
{
|
||||
// Get Name
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
|
||||
|
||||
UString fullPath;
|
||||
if (prop.vt == VT_EMPTY)
|
||||
fullPath = kEmptyFileAlias;
|
||||
else
|
||||
{
|
||||
if (prop.vt != VT_BSTR)
|
||||
return E_FAIL;
|
||||
fullPath = prop.bstrVal;
|
||||
}
|
||||
_filePath = fullPath;
|
||||
}
|
||||
|
||||
if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
// Get Attrib
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
{
|
||||
_processedFileInfo.Attrib = 0;
|
||||
_processedFileInfo.AttribDefined = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_FAIL;
|
||||
_processedFileInfo.Attrib = prop.ulVal;
|
||||
_processedFileInfo.AttribDefined = true;
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir));
|
||||
|
||||
{
|
||||
// Get Modified Time
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
|
||||
_processedFileInfo.MTimeDefined = false;
|
||||
switch (prop.vt)
|
||||
{
|
||||
case VT_EMPTY:
|
||||
// _processedFileInfo.MTime = _utcMTimeDefault;
|
||||
break;
|
||||
case VT_FILETIME:
|
||||
_processedFileInfo.MTime = prop.filetime;
|
||||
_processedFileInfo.MTimeDefined = true;
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
// Get Size
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
|
||||
UInt64 newFileSize;
|
||||
/* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// Create folders for file
|
||||
int slashPos = _filePath.ReverseFind_PathSepar();
|
||||
if (slashPos >= 0)
|
||||
CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos)));
|
||||
}
|
||||
|
||||
FString fullProcessedPath = _directoryPath + us2fs(_filePath);
|
||||
_diskFilePath = fullProcessedPath;
|
||||
|
||||
if (_processedFileInfo.isDir)
|
||||
{
|
||||
CreateComplexDir(fullProcessedPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
NFind::CFileInfo fi;
|
||||
if (fi.Find(fullProcessedPath))
|
||||
{
|
||||
if (!DeleteFileAlways(fullProcessedPath))
|
||||
{
|
||||
PrintError("Can not delete output file", fullProcessedPath);
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
_outFileStreamSpec = new COutFileStream;
|
||||
CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
|
||||
if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))
|
||||
{
|
||||
PrintError("Can not open output file", fullProcessedPath);
|
||||
return E_ABORT;
|
||||
}
|
||||
_outFileStream = outStreamLoc;
|
||||
*outStream = outStreamLoc.Detach();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
||||
{
|
||||
_extractMode = false;
|
||||
switch (askExtractMode)
|
||||
{
|
||||
case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break;
|
||||
};
|
||||
switch (askExtractMode)
|
||||
{
|
||||
case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break;
|
||||
case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break;
|
||||
case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break;
|
||||
};
|
||||
Print(_filePath);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
|
||||
{
|
||||
switch (operationResult)
|
||||
{
|
||||
case NArchive::NExtract::NOperationResult::kOK:
|
||||
break;
|
||||
default:
|
||||
{
|
||||
NumErrors++;
|
||||
Print(" : ");
|
||||
const char *s = NULL;
|
||||
switch (operationResult)
|
||||
{
|
||||
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
|
||||
s = kUnsupportedMethod;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kCRCError:
|
||||
s = kCRCFailed;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kDataError:
|
||||
s = kDataError;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kUnavailable:
|
||||
s = kUnavailableData;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
|
||||
s = kUnexpectedEnd;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
|
||||
s = kDataAfterEnd;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kIsNotArc:
|
||||
s = kIsNotArc;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kHeadersError:
|
||||
s = kHeadersError;
|
||||
break;
|
||||
}
|
||||
if (s)
|
||||
{
|
||||
Print("Error : ");
|
||||
Print(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(operationResult, temp);
|
||||
Print("Error #");
|
||||
Print(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_outFileStream)
|
||||
{
|
||||
if (_processedFileInfo.MTimeDefined)
|
||||
_outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
|
||||
RINOK(_outFileStreamSpec->Close());
|
||||
}
|
||||
_outFileStream.Release();
|
||||
if (_extractMode && _processedFileInfo.AttribDefined)
|
||||
SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib);
|
||||
PrintNewLine();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
if (!PasswordIsDefined)
|
||||
{
|
||||
// You can ask real password here from user
|
||||
// Password = GetPassword(OutStream);
|
||||
// PasswordIsDefined = true;
|
||||
PrintError("Password is not defined");
|
||||
return E_ABORT;
|
||||
}
|
||||
return StringToBstr(Password, password);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Archive Creating callback class
|
||||
|
||||
struct CDirItem
|
||||
{
|
||||
UInt64 Size;
|
||||
FILETIME CTime;
|
||||
FILETIME ATime;
|
||||
FILETIME MTime;
|
||||
UString Name;
|
||||
FString FullPath;
|
||||
UInt32 Attrib;
|
||||
|
||||
bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
|
||||
};
|
||||
|
||||
class CArchiveUpdateCallback:
|
||||
public IArchiveUpdateCallback2,
|
||||
public ICryptoGetTextPassword2,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
|
||||
|
||||
// IProgress
|
||||
STDMETHOD(SetTotal)(UInt64 size);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
|
||||
|
||||
// IUpdateCallback2
|
||||
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
|
||||
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
|
||||
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
|
||||
STDMETHOD(SetOperationResult)(Int32 operationResult);
|
||||
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
|
||||
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
|
||||
|
||||
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
|
||||
|
||||
public:
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
UString VolName;
|
||||
UString VolExt;
|
||||
|
||||
FString DirPrefix;
|
||||
const CObjectVector<CDirItem> *DirItems;
|
||||
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
bool AskPassword;
|
||||
|
||||
bool m_NeedBeClosed;
|
||||
|
||||
FStringVector FailedFiles;
|
||||
CRecordVector<HRESULT> FailedCodes;
|
||||
|
||||
CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};
|
||||
|
||||
~CArchiveUpdateCallback() { Finilize(); }
|
||||
HRESULT Finilize();
|
||||
|
||||
void Init(const CObjectVector<CDirItem> *dirItems)
|
||||
{
|
||||
DirItems = dirItems;
|
||||
m_NeedBeClosed = false;
|
||||
FailedFiles.Clear();
|
||||
FailedCodes.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,
|
||||
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
|
||||
{
|
||||
if (newData)
|
||||
*newData = BoolToInt(true);
|
||||
if (newProperties)
|
||||
*newProperties = BoolToInt(true);
|
||||
if (indexInArchive)
|
||||
*indexInArchive = (UInt32)(Int32)-1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
if (propID == kpidIsAnti)
|
||||
{
|
||||
prop = false;
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
{
|
||||
const CDirItem &dirItem = (*DirItems)[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = dirItem.Name; break;
|
||||
case kpidIsDir: prop = dirItem.isDir(); break;
|
||||
case kpidSize: prop = dirItem.Size; break;
|
||||
case kpidAttrib: prop = dirItem.Attrib; break;
|
||||
case kpidCTime: prop = dirItem.CTime; break;
|
||||
case kpidATime: prop = dirItem.ATime; break;
|
||||
case kpidMTime: prop = dirItem.MTime; break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CArchiveUpdateCallback::Finilize()
|
||||
{
|
||||
if (m_NeedBeClosed)
|
||||
{
|
||||
PrintNewLine();
|
||||
m_NeedBeClosed = false;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void GetStream2(const wchar_t *name)
|
||||
{
|
||||
Print("Compressing ");
|
||||
if (name[0] == 0)
|
||||
name = kEmptyFileAlias;
|
||||
Print(name);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
|
||||
{
|
||||
RINOK(Finilize());
|
||||
|
||||
const CDirItem &dirItem = (*DirItems)[index];
|
||||
GetStream2(dirItem.Name);
|
||||
|
||||
if (dirItem.isDir())
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
FString path = DirPrefix + dirItem.FullPath;
|
||||
if (!inStreamSpec->Open(path))
|
||||
{
|
||||
DWORD sysError = ::GetLastError();
|
||||
FailedCodes.Add(sysError);
|
||||
FailedFiles.Add(path);
|
||||
// if (systemError == ERROR_SHARING_VIOLATION)
|
||||
{
|
||||
PrintNewLine();
|
||||
PrintError("WARNING: can't open file");
|
||||
// Print(NError::MyFormatMessageW(systemError));
|
||||
return S_FALSE;
|
||||
}
|
||||
// return sysError;
|
||||
}
|
||||
*inStream = inStreamLoc.Detach();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)
|
||||
{
|
||||
m_NeedBeClosed = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
|
||||
{
|
||||
if (VolumesSizes.Size() == 0)
|
||||
return S_FALSE;
|
||||
if (index >= (UInt32)VolumesSizes.Size())
|
||||
index = VolumesSizes.Size() - 1;
|
||||
*size = VolumesSizes[index];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
|
||||
{
|
||||
wchar_t temp[16];
|
||||
ConvertUInt32ToString(index + 1, temp);
|
||||
UString res = temp;
|
||||
while (res.Len() < 2)
|
||||
res.InsertAtFront(L'0');
|
||||
UString fileName = VolName;
|
||||
fileName += '.';
|
||||
fileName += res;
|
||||
fileName += VolExt;
|
||||
COutFileStream *streamSpec = new COutFileStream;
|
||||
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
|
||||
if (!streamSpec->Create(us2fs(fileName), false))
|
||||
return ::GetLastError();
|
||||
*volumeStream = streamLoc.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
|
||||
{
|
||||
if (!PasswordIsDefined)
|
||||
{
|
||||
if (AskPassword)
|
||||
{
|
||||
// You can ask real password here from user
|
||||
// Password = GetPassword(OutStream);
|
||||
// PasswordIsDefined = true;
|
||||
PrintError("Password is not defined");
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
*passwordIsDefined = BoolToInt(PasswordIsDefined);
|
||||
return StringToBstr(Password, password);
|
||||
}
|
||||
|
||||
|
||||
// Main function
|
||||
|
||||
#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
|
||||
|
||||
int MY_CDECL main(int numArgs, const char *args[])
|
||||
{
|
||||
NT_CHECK
|
||||
|
||||
PrintStringLn(kCopyrightString);
|
||||
|
||||
if (numArgs < 2)
|
||||
{
|
||||
PrintStringLn(kHelpString);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (numArgs < 3)
|
||||
{
|
||||
PrintError(kIncorrectCommand);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
NDLL::CLibrary lib;
|
||||
if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName)))
|
||||
{
|
||||
PrintError("Can not load 7-zip library");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject");
|
||||
if (!createObjectFunc)
|
||||
{
|
||||
PrintError("Can not get CreateObject");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char c;
|
||||
{
|
||||
AString command (args[1]);
|
||||
if (command.Len() != 1)
|
||||
{
|
||||
PrintError(kIncorrectCommand);
|
||||
return 1;
|
||||
}
|
||||
c = (char)MyCharLower_Ascii(command[0]);
|
||||
}
|
||||
|
||||
FString archiveName = CmdStringToFString(args[2]);
|
||||
|
||||
if (c == 'a')
|
||||
{
|
||||
// create archive command
|
||||
if (numArgs < 4)
|
||||
{
|
||||
PrintError(kIncorrectCommand);
|
||||
return 1;
|
||||
}
|
||||
CObjectVector<CDirItem> dirItems;
|
||||
{
|
||||
int i;
|
||||
for (i = 3; i < numArgs; i++)
|
||||
{
|
||||
CDirItem di;
|
||||
FString name = CmdStringToFString(args[i]);
|
||||
|
||||
NFind::CFileInfo fi;
|
||||
if (!fi.Find(name))
|
||||
{
|
||||
PrintError("Can't find file", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
di.Attrib = fi.Attrib;
|
||||
di.Size = fi.Size;
|
||||
di.CTime = fi.CTime;
|
||||
di.ATime = fi.ATime;
|
||||
di.MTime = fi.MTime;
|
||||
di.Name = fs2us(name);
|
||||
di.FullPath = name;
|
||||
dirItems.Add(di);
|
||||
}
|
||||
}
|
||||
|
||||
COutFileStream *outFileStreamSpec = new COutFileStream;
|
||||
CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
|
||||
if (!outFileStreamSpec->Create(archiveName, false))
|
||||
{
|
||||
PrintError("can't create archive file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMyComPtr<IOutArchive> outArchive;
|
||||
if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK)
|
||||
{
|
||||
PrintError("Can not get class object");
|
||||
return 1;
|
||||
}
|
||||
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
|
||||
updateCallbackSpec->Init(&dirItems);
|
||||
// updateCallbackSpec->PasswordIsDefined = true;
|
||||
// updateCallbackSpec->Password = L"1";
|
||||
|
||||
/*
|
||||
{
|
||||
const wchar_t *names[] =
|
||||
{
|
||||
L"s",
|
||||
L"x"
|
||||
};
|
||||
const unsigned kNumProps = ARRAY_SIZE(names);
|
||||
NCOM::CPropVariant values[kNumProps] =
|
||||
{
|
||||
false, // solid mode OFF
|
||||
(UInt32)9 // compression level = 9 - ultra
|
||||
};
|
||||
CMyComPtr<ISetProperties> setProperties;
|
||||
outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
|
||||
if (!setProperties)
|
||||
{
|
||||
PrintError("ISetProperties unsupported");
|
||||
return 1;
|
||||
}
|
||||
RINOK(setProperties->SetProperties(names, values, kNumProps));
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);
|
||||
|
||||
updateCallbackSpec->Finilize();
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
PrintError("Update Error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, updateCallbackSpec->FailedFiles)
|
||||
{
|
||||
PrintNewLine();
|
||||
PrintError("Error for file", updateCallbackSpec->FailedFiles[i]);
|
||||
}
|
||||
|
||||
if (updateCallbackSpec->FailedFiles.Size() != 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numArgs != 3)
|
||||
{
|
||||
PrintError(kIncorrectCommand);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool listCommand;
|
||||
|
||||
if (c == 'l')
|
||||
listCommand = true;
|
||||
else if (c == 'x')
|
||||
listCommand = false;
|
||||
else
|
||||
{
|
||||
PrintError(kIncorrectCommand);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMyComPtr<IInArchive> archive;
|
||||
if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK)
|
||||
{
|
||||
PrintError("Can not get class object");
|
||||
return 1;
|
||||
}
|
||||
|
||||
CInFileStream *fileSpec = new CInFileStream;
|
||||
CMyComPtr<IInStream> file = fileSpec;
|
||||
|
||||
if (!fileSpec->Open(archiveName))
|
||||
{
|
||||
PrintError("Can not open archive file", archiveName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
|
||||
openCallbackSpec->PasswordIsDefined = false;
|
||||
// openCallbackSpec->PasswordIsDefined = true;
|
||||
// openCallbackSpec->Password = L"1";
|
||||
|
||||
const UInt64 scanSize = 1 << 23;
|
||||
if (archive->Open(file, &scanSize, openCallback) != S_OK)
|
||||
{
|
||||
PrintError("Can not open file as archive", archiveName);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (listCommand)
|
||||
{
|
||||
// List command
|
||||
UInt32 numItems = 0;
|
||||
archive->GetNumberOfItems(&numItems);
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
{
|
||||
// Get uncompressed size of file
|
||||
NCOM::CPropVariant prop;
|
||||
archive->GetProperty(i, kpidSize, &prop);
|
||||
char s[32];
|
||||
ConvertPropVariantToShortString(prop, s);
|
||||
Print(s);
|
||||
Print(" ");
|
||||
}
|
||||
{
|
||||
// Get name of file
|
||||
NCOM::CPropVariant prop;
|
||||
archive->GetProperty(i, kpidPath, &prop);
|
||||
if (prop.vt == VT_BSTR)
|
||||
Print(prop.bstrVal);
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
Print("ERROR!");
|
||||
}
|
||||
PrintNewLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Extract command
|
||||
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
|
||||
extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path
|
||||
extractCallbackSpec->PasswordIsDefined = false;
|
||||
// extractCallbackSpec->PasswordIsDefined = true;
|
||||
// extractCallbackSpec->Password = "1";
|
||||
|
||||
/*
|
||||
const wchar_t *names[] =
|
||||
{
|
||||
L"mt",
|
||||
L"mtf"
|
||||
};
|
||||
const unsigned kNumProps = sizeof(names) / sizeof(names[0]);
|
||||
NCOM::CPropVariant values[kNumProps] =
|
||||
{
|
||||
(UInt32)1,
|
||||
false
|
||||
};
|
||||
CMyComPtr<ISetProperties> setProperties;
|
||||
archive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
|
||||
if (setProperties)
|
||||
setProperties->SetProperties(names, values, kNumProps);
|
||||
*/
|
||||
|
||||
HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
PrintError("Extract Error");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Client7z - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Client7z.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Client7z - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zcl.exe"
|
||||
|
||||
!ELSEIF "$(CFG)" == "Client7z - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zcl.exe" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Client7z - Win32 Release"
|
||||
# Name "Client7z - Win32 Debug"
|
||||
# Begin Group "Spec"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# ADD CPP /Yc"stdafx.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Windows"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\DLL.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\DLL.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileDir.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileDir.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileFind.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileFind.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileIO.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileIO.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileName.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileName.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariantConv.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariantConv.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyVector.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyVector.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringConvert.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "7zip Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FileStreams.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FileStreams.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Client7z.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Sort.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
PROG = 7zcl.exe
|
||||
MY_CONSOLE = 1
|
||||
|
||||
CURRENT_OBJS = \
|
||||
$O\Client7z.obj \
|
||||
|
||||
COMMON_OBJS = \
|
||||
$O\IntToString.obj \
|
||||
$O\NewHandler.obj \
|
||||
$O\MyString.obj \
|
||||
$O\StringConvert.obj \
|
||||
$O\StringToInt.obj \
|
||||
$O\MyVector.obj \
|
||||
$O\Wildcard.obj \
|
||||
|
||||
WIN_OBJS = \
|
||||
$O\DLL.obj \
|
||||
$O\FileDir.obj \
|
||||
$O\FileFind.obj \
|
||||
$O\FileIO.obj \
|
||||
$O\FileName.obj \
|
||||
$O\PropVariant.obj \
|
||||
$O\PropVariantConv.obj \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\FileStreams.obj \
|
||||
|
||||
!include "../../7zip.mak"
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "../../MyVersionInfo.rc"
|
||||
|
||||
MY_VERSION_INFO_APP("7-Zip client" , "7zcl")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
// ArchiveCommandLine.h
|
||||
|
||||
#ifndef __ARCHIVE_COMMAND_LINE_H
|
||||
#define __ARCHIVE_COMMAND_LINE_H
|
||||
|
||||
#include "../../../Common/CommandLineParser.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "EnumDirItems.h"
|
||||
|
||||
#include "Extract.h"
|
||||
#include "HashCalc.h"
|
||||
#include "Update.h"
|
||||
|
||||
typedef CMessagePathException CArcCmdLineException;
|
||||
|
||||
namespace NCommandType { enum EEnum
|
||||
{
|
||||
kAdd = 0,
|
||||
kUpdate,
|
||||
kDelete,
|
||||
kTest,
|
||||
kExtract,
|
||||
kExtractFull,
|
||||
kList,
|
||||
kBenchmark,
|
||||
kInfo,
|
||||
kHash,
|
||||
kRename
|
||||
};}
|
||||
|
||||
struct CArcCommand
|
||||
{
|
||||
NCommandType::EEnum CommandType;
|
||||
|
||||
bool IsFromExtractGroup() const;
|
||||
bool IsFromUpdateGroup() const;
|
||||
bool IsTestCommand() const { return CommandType == NCommandType::kTest; }
|
||||
NExtract::NPathMode::EEnum GetPathMode() const;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
k_OutStream_disabled = 0,
|
||||
k_OutStream_stdout = 1,
|
||||
k_OutStream_stderr = 2
|
||||
};
|
||||
|
||||
struct CArcCmdLineOptions
|
||||
{
|
||||
bool HelpMode;
|
||||
|
||||
// bool LargePages;
|
||||
bool CaseSensitiveChange;
|
||||
bool CaseSensitive;
|
||||
|
||||
bool IsInTerminal;
|
||||
bool IsStdOutTerminal;
|
||||
bool IsStdErrTerminal;
|
||||
bool StdInMode;
|
||||
bool StdOutMode;
|
||||
bool EnableHeaders;
|
||||
|
||||
bool YesToAll;
|
||||
bool ShowDialog;
|
||||
NWildcard::CCensor Censor;
|
||||
|
||||
CArcCommand Command;
|
||||
UString ArchiveName;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
bool PasswordEnabled;
|
||||
UString Password;
|
||||
#endif
|
||||
|
||||
bool TechMode;
|
||||
bool ShowTime;
|
||||
|
||||
UStringVector HashMethods;
|
||||
|
||||
bool AppendName;
|
||||
// UStringVector ArchivePathsSorted;
|
||||
// UStringVector ArchivePathsFullSorted;
|
||||
NWildcard::CCensor arcCensor;
|
||||
UString ArcName_for_StdInMode;
|
||||
|
||||
CObjectVector<CProperty> Properties;
|
||||
|
||||
CExtractOptionsBase ExtractOptions;
|
||||
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair AltStreams;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
CUpdateOptions UpdateOptions;
|
||||
CHashOptions HashOptions;
|
||||
UString ArcType;
|
||||
UStringVector ExcludedArcTypes;
|
||||
|
||||
unsigned Number_for_Out;
|
||||
unsigned Number_for_Errors;
|
||||
unsigned Number_for_Percents;
|
||||
unsigned LogLevel;
|
||||
|
||||
// bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; }
|
||||
|
||||
// Benchmark
|
||||
UInt32 NumIterations;
|
||||
|
||||
CArcCmdLineOptions():
|
||||
// LargePages(false),
|
||||
CaseSensitiveChange(false),
|
||||
CaseSensitive(false),
|
||||
|
||||
StdInMode(false),
|
||||
StdOutMode(false),
|
||||
|
||||
Number_for_Out(k_OutStream_stdout),
|
||||
Number_for_Errors(k_OutStream_stderr),
|
||||
Number_for_Percents(k_OutStream_stdout),
|
||||
|
||||
LogLevel(0)
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
class CArcCmdLineParser
|
||||
{
|
||||
NCommandLineParser::CParser parser;
|
||||
public:
|
||||
void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);
|
||||
void Parse2(CArcCmdLineOptions &options);
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,403 @@
|
||||
// ArchiveExtractCallback.h
|
||||
|
||||
#ifndef __ARCHIVE_EXTRACT_CALLBACK_H
|
||||
#define __ARCHIVE_EXTRACT_CALLBACK_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "ExtractMode.h"
|
||||
#include "IFileExtractCallback.h"
|
||||
#include "OpenArchive.h"
|
||||
|
||||
#include "HashCalc.h"
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
class COutStreamWithHash:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
bool _calculate;
|
||||
public:
|
||||
IHashCalc *_hash;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(bool calculate = true)
|
||||
{
|
||||
InitCRC();
|
||||
_size = 0;
|
||||
_calculate = calculate;
|
||||
}
|
||||
void EnableCalc(bool calculate) { _calculate = calculate; }
|
||||
void InitCRC() { _hash->InitForNewFile(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct CExtractNtOptions
|
||||
{
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair SymLinks;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair AltStreams;
|
||||
bool ReplaceColonForAltStream;
|
||||
bool WriteToAltStreamIfColon;
|
||||
|
||||
bool PreAllocateOutFile;
|
||||
|
||||
CExtractNtOptions():
|
||||
ReplaceColonForAltStream(false),
|
||||
WriteToAltStreamIfColon(false)
|
||||
{
|
||||
SymLinks.Val = true;
|
||||
HardLinks.Val = true;
|
||||
AltStreams.Val = true;
|
||||
|
||||
PreAllocateOutFile =
|
||||
#ifdef _WIN32
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
class CGetProp:
|
||||
public IGetProp,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
const CArc *Arc;
|
||||
UInt32 IndexInArc;
|
||||
// UString Name; // relative path
|
||||
|
||||
MY_UNKNOWN_IMP1(IGetProp)
|
||||
INTERFACE_IGetProp(;)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _SFX
|
||||
#ifndef UNDER_CE
|
||||
|
||||
#define SUPPORT_LINKS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
struct CHardLinkNode
|
||||
{
|
||||
UInt64 StreamId;
|
||||
UInt64 INode;
|
||||
|
||||
int Compare(const CHardLinkNode &a) const;
|
||||
};
|
||||
|
||||
class CHardLinks
|
||||
{
|
||||
public:
|
||||
CRecordVector<CHardLinkNode> IDs;
|
||||
CObjectVector<FString> Links;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
IDs.Clear();
|
||||
Links.Clear();
|
||||
}
|
||||
|
||||
void PrepareLinks()
|
||||
{
|
||||
while (Links.Size() < IDs.Size())
|
||||
Links.AddNew();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
|
||||
struct CIndexToPathPair
|
||||
{
|
||||
UInt32 Index;
|
||||
FString Path;
|
||||
|
||||
CIndexToPathPair(UInt32 index): Index(index) {}
|
||||
CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
|
||||
|
||||
int Compare(const CIndexToPathPair &pair) const
|
||||
{
|
||||
return MyCompare(Index, pair.Index);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct CDirPathTime
|
||||
{
|
||||
FILETIME CTime;
|
||||
FILETIME ATime;
|
||||
FILETIME MTime;
|
||||
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
|
||||
FString Path;
|
||||
|
||||
bool SetDirTime();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CArchiveExtractCallback:
|
||||
public IArchiveExtractCallback,
|
||||
public IArchiveExtractCallbackMessage,
|
||||
public ICryptoGetTextPassword,
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
const CArc *_arc;
|
||||
CExtractNtOptions _ntOptions;
|
||||
|
||||
const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
|
||||
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
|
||||
CMyComPtr<ICompressProgressInfo> _compressProgress;
|
||||
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
|
||||
CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;
|
||||
CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
|
||||
|
||||
FString _dirPathPrefix;
|
||||
FString _dirPathPrefix_Full;
|
||||
NExtract::NPathMode::EEnum _pathMode;
|
||||
NExtract::NOverwriteMode::EEnum _overwriteMode;
|
||||
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
|
||||
CGetProp *GetProp_Spec;
|
||||
CMyComPtr<IGetProp> GetProp;
|
||||
|
||||
#endif
|
||||
|
||||
CReadArcItem _item;
|
||||
FString _diskFilePath;
|
||||
UInt64 _position;
|
||||
bool _isSplit;
|
||||
|
||||
bool _extractMode;
|
||||
|
||||
bool WriteCTime;
|
||||
bool WriteATime;
|
||||
bool WriteMTime;
|
||||
|
||||
bool _encrypted;
|
||||
|
||||
struct CProcessedFileInfo
|
||||
{
|
||||
FILETIME CTime;
|
||||
FILETIME ATime;
|
||||
FILETIME MTime;
|
||||
UInt32 Attrib;
|
||||
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
bool AttribDefined;
|
||||
} _fi;
|
||||
|
||||
UInt32 _index;
|
||||
UInt64 _curSize;
|
||||
bool _curSizeDefined;
|
||||
bool _fileLengthWasSet;
|
||||
COutFileStream *_outFileStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _outFileStream;
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
COutStreamWithHash *_hashStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _hashStream;
|
||||
bool _hashStreamWasUsed;
|
||||
|
||||
#endif
|
||||
|
||||
bool _removePartsForAltStreams;
|
||||
UStringVector _removePathParts;
|
||||
|
||||
#ifndef _SFX
|
||||
bool _use_baseParentFolder_mode;
|
||||
UInt32 _baseParentFolder;
|
||||
#endif
|
||||
|
||||
bool _stdOutMode;
|
||||
bool _testMode;
|
||||
bool _multiArchives;
|
||||
|
||||
CMyComPtr<ICompressProgressInfo> _localProgress;
|
||||
UInt64 _packTotal;
|
||||
|
||||
UInt64 _progressTotal;
|
||||
bool _progressTotal_Defined;
|
||||
|
||||
CObjectVector<CDirPathTime> _extractedFolders;
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
|
||||
bool _saclEnabled;
|
||||
#endif
|
||||
|
||||
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
|
||||
HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
|
||||
HRESULT GetUnpackSize();
|
||||
|
||||
HRESULT SendMessageError(const char *message, const FString &path);
|
||||
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
|
||||
HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);
|
||||
|
||||
public:
|
||||
|
||||
CLocalProgress *LocalProgressSpec;
|
||||
|
||||
UInt64 NumFolders;
|
||||
UInt64 NumFiles;
|
||||
UInt64 NumAltStreams;
|
||||
UInt64 UnpackSize;
|
||||
UInt64 AltStreams_UnpackSize;
|
||||
|
||||
MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
|
||||
|
||||
INTERFACE_IArchiveExtractCallback(;)
|
||||
INTERFACE_IArchiveExtractCallbackMessage(;)
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
|
||||
CArchiveExtractCallback();
|
||||
|
||||
void InitForMulti(bool multiArchives,
|
||||
NExtract::NPathMode::EEnum pathMode,
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode,
|
||||
bool keepAndReplaceEmptyDirPrefixes)
|
||||
{
|
||||
_multiArchives = multiArchives;
|
||||
_pathMode = pathMode;
|
||||
_overwriteMode = overwriteMode;
|
||||
_keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
|
||||
NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
|
||||
}
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
void SetHashMethods(IHashCalc *hash)
|
||||
{
|
||||
if (!hash)
|
||||
return;
|
||||
_hashStreamSpec = new COutStreamWithHash;
|
||||
_hashStream = _hashStreamSpec;
|
||||
_hashStreamSpec->_hash = hash;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Init(
|
||||
const CExtractNtOptions &ntOptions,
|
||||
const NWildcard::CCensorNode *wildcardCensor,
|
||||
const CArc *arc,
|
||||
IFolderArchiveExtractCallback *extractCallback2,
|
||||
bool stdOutMode, bool testMode,
|
||||
const FString &directoryPath,
|
||||
const UStringVector &removePathParts, bool removePartsForAltStreams,
|
||||
UInt64 packSize);
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
private:
|
||||
CHardLinks _hardLinks;
|
||||
UString linkPath;
|
||||
|
||||
// FString _CopyFile_Path;
|
||||
// HRESULT MyCopyFile(ISequentialOutStream *outStream);
|
||||
|
||||
public:
|
||||
// call PrepareHardLinks() after Init()
|
||||
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
CObjectVector<CIndexToPathPair> _renamedFiles;
|
||||
#endif
|
||||
|
||||
// call it after Init()
|
||||
|
||||
#ifndef _SFX
|
||||
void SetBaseParentFolderIndex(UInt32 indexInArc)
|
||||
{
|
||||
_baseParentFolder = indexInArc;
|
||||
_use_baseParentFolder_mode = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT CloseArc();
|
||||
|
||||
private:
|
||||
void ClearExtractedDirsInfo()
|
||||
{
|
||||
_extractedFolders.Clear();
|
||||
}
|
||||
|
||||
HRESULT CloseFile();
|
||||
HRESULT SetDirsTimes();
|
||||
};
|
||||
|
||||
|
||||
struct CArchiveExtractCallback_Closer
|
||||
{
|
||||
CArchiveExtractCallback *_ref;
|
||||
|
||||
CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
|
||||
|
||||
HRESULT Close()
|
||||
{
|
||||
HRESULT res = S_OK;
|
||||
if (_ref)
|
||||
{
|
||||
res = _ref->CloseArc();
|
||||
_ref = NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
~CArchiveExtractCallback_Closer()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
// ArchiveName.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileName.h"
|
||||
|
||||
#include "ExtractingFilePath.h"
|
||||
#include "ArchiveName.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
static UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName)
|
||||
{
|
||||
FString resultName = fi.Name;
|
||||
if (!fi.IsDir() && !keepName)
|
||||
{
|
||||
int dotPos = resultName.ReverseFind_Dot();
|
||||
if (dotPos > 0)
|
||||
{
|
||||
FString archiveName2 = resultName.Left(dotPos);
|
||||
if (archiveName2.ReverseFind_Dot() < 0)
|
||||
resultName = archiveName2;
|
||||
}
|
||||
}
|
||||
return Get_Correct_FsFile_Name(fs2us(resultName));
|
||||
}
|
||||
|
||||
static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName)
|
||||
{
|
||||
FString resultName ("Archive");
|
||||
if (fromPrev)
|
||||
{
|
||||
FString dirPrefix;
|
||||
if (NDir::GetOnlyDirPrefix(path, dirPrefix))
|
||||
{
|
||||
if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))
|
||||
{
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))
|
||||
resultName = dirPrefix[dirPrefix.Len() - 3]; // only letter
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dirPrefix.DeleteBack();
|
||||
NFind::CFileInfo fi;
|
||||
if (fi.Find(dirPrefix))
|
||||
resultName = fi.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NFind::CFileInfo fi;
|
||||
if (fi.Find(path))
|
||||
{
|
||||
resultName = fi.Name;
|
||||
if (!fi.IsDir() && !keepName)
|
||||
{
|
||||
int dotPos = resultName.ReverseFind_Dot();
|
||||
if (dotPos > 0)
|
||||
{
|
||||
FString name2 = resultName.Left(dotPos);
|
||||
if (name2.ReverseFind_Dot() < 0)
|
||||
resultName = name2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultName;
|
||||
}
|
||||
|
||||
|
||||
UString CreateArchiveName(const UStringVector &paths, const NFind::CFileInfo *fi)
|
||||
{
|
||||
bool keepName = false;
|
||||
/*
|
||||
if (paths.Size() == 1)
|
||||
{
|
||||
const UString &name = paths[0];
|
||||
if (name.Len() > 4)
|
||||
if (CompareFileNames(name.RightPtr(4), L".tar") == 0)
|
||||
keepName = true;
|
||||
}
|
||||
*/
|
||||
|
||||
UString name;
|
||||
if (fi)
|
||||
name = CreateArchiveName(*fi, keepName);
|
||||
else
|
||||
{
|
||||
if (paths.IsEmpty())
|
||||
return L"archive";
|
||||
bool fromPrev = (paths.Size() > 1);
|
||||
name = Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(paths.Front()), fromPrev, keepName)));
|
||||
}
|
||||
|
||||
UStringVector names;
|
||||
|
||||
{
|
||||
FOR_VECTOR (i, paths)
|
||||
{
|
||||
NFind::CFileInfo fi2;
|
||||
const NFind::CFileInfo *fp;
|
||||
if (fi && paths.Size() == 1)
|
||||
fp = fi;
|
||||
else
|
||||
{
|
||||
if (!fi2.Find(us2fs(paths[i])))
|
||||
continue;
|
||||
fp = &fi2;
|
||||
}
|
||||
names.Add(fs2us(fp->Name));
|
||||
}
|
||||
}
|
||||
|
||||
UString postfix;
|
||||
UInt32 index = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// we don't want cases when we include archive to itself.
|
||||
// so we find first available name for archive
|
||||
const UString name2 = name + postfix;
|
||||
const UString name2_zip = name2 + L".zip";
|
||||
const UString name2_7z = name2 + L".7z";
|
||||
const UString name2_tar = name2 + L".tar";
|
||||
const UString name2_wim = name2 + L".wim";
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
for (i = 0; i < names.Size(); i++)
|
||||
{
|
||||
const UString &fname = names[i];
|
||||
if ( 0 == CompareFileNames(fname, name2_zip)
|
||||
|| 0 == CompareFileNames(fname, name2_7z)
|
||||
|| 0 == CompareFileNames(fname, name2_tar)
|
||||
|| 0 == CompareFileNames(fname, name2_wim))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == names.Size())
|
||||
break;
|
||||
index++;
|
||||
postfix = "_";
|
||||
postfix.Add_UInt32(index);
|
||||
}
|
||||
|
||||
name += postfix;
|
||||
return name;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// ArchiveName.h
|
||||
|
||||
#ifndef __ARCHIVE_NAME_H
|
||||
#define __ARCHIVE_NAME_H
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
UString CreateArchiveName(const UStringVector &paths, const NWindows::NFile::NFind::CFileInfo *fi = NULL);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
// ArchiveOpenCallback.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
return ReOpenCallback->SetTotal(files, bytes);
|
||||
if (!Callback)
|
||||
return S_OK;
|
||||
return Callback->Open_SetTotal(files, bytes);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
return ReOpenCallback->SetCompleted(files, bytes);
|
||||
if (!Callback)
|
||||
return S_OK;
|
||||
return Callback->Open_SetCompleted(files, bytes);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
if (_subArchiveMode)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidName: prop = _subArchiveName; break;
|
||||
// case kpidSize: prop = _subArchiveSize; break; // we don't use it now
|
||||
}
|
||||
else
|
||||
switch (propID)
|
||||
{
|
||||
case kpidName: prop = _fileInfo.Name; break;
|
||||
case kpidIsDir: prop = _fileInfo.IsDir(); break;
|
||||
case kpidSize: prop = _fileInfo.Size; break;
|
||||
case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break;
|
||||
case kpidCTime: prop = _fileInfo.CTime; break;
|
||||
case kpidATime: prop = _fileInfo.ATime; break;
|
||||
case kpidMTime: prop = _fileInfo.MTime; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
struct CInFileStreamVol: public CInFileStream
|
||||
{
|
||||
int FileNameIndex;
|
||||
COpenCallbackImp *OpenCallbackImp;
|
||||
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
|
||||
|
||||
~CInFileStreamVol()
|
||||
{
|
||||
if (OpenCallbackRef)
|
||||
OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// from ArchiveExtractCallback.cpp
|
||||
bool IsSafePath(const UString &path);
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*inStream = NULL;
|
||||
|
||||
if (_subArchiveMode)
|
||||
return S_FALSE;
|
||||
if (Callback)
|
||||
{
|
||||
RINOK(Callback->Open_CheckBreak());
|
||||
}
|
||||
|
||||
UString name2 = name;
|
||||
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
#ifdef _WIN32
|
||||
name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||
#endif
|
||||
|
||||
// if (!allowAbsVolPaths)
|
||||
if (!IsSafePath(name2))
|
||||
return S_FALSE;
|
||||
|
||||
// #ifdef _WIN32
|
||||
// we don't want to support wildcards in names here here
|
||||
if (name2.Find(L'?') >= 0 ||
|
||||
name2.Find(L'*') >= 0)
|
||||
return S_FALSE;
|
||||
// #endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
FString fullPath;
|
||||
if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))
|
||||
return S_FALSE;
|
||||
if (!_fileInfo.Find(fullPath))
|
||||
return S_FALSE;
|
||||
if (_fileInfo.IsDir())
|
||||
return S_FALSE;
|
||||
CInFileStreamVol *inFile = new CInFileStreamVol;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(fullPath))
|
||||
{
|
||||
DWORD lastError = ::GetLastError();
|
||||
if (lastError == 0)
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
}
|
||||
|
||||
FileSizes.Add(_fileInfo.Size);
|
||||
FileNames.Add(name2);
|
||||
inFile->FileNameIndex = FileNames_WasUsed.Add(true);
|
||||
inFile->OpenCallbackImp = this;
|
||||
inFile->OpenCallbackRef = this;
|
||||
// TotalSize += _fileInfo.Size;
|
||||
*inStream = inStreamTemp.Detach();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
{
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
if (getTextPassword)
|
||||
return getTextPassword->CryptoGetTextPassword(password);
|
||||
}
|
||||
if (!Callback)
|
||||
return E_NOTIMPL;
|
||||
PasswordWasAsked = true;
|
||||
return Callback->Open_CryptoGetTextPassword(password);
|
||||
COM_TRY_END
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,112 @@
|
||||
// ArchiveOpenCallback.h
|
||||
|
||||
#ifndef __ARCHIVE_OPEN_CALLBACK_H
|
||||
#define __ARCHIVE_OPEN_CALLBACK_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#include "../../IPassword.h"
|
||||
#endif
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#ifdef _NO_CRYPTO
|
||||
|
||||
#define INTERFACE_IOpenCallbackUI_Crypto(x)
|
||||
|
||||
#else
|
||||
|
||||
#define INTERFACE_IOpenCallbackUI_Crypto(x) \
|
||||
virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \
|
||||
/* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; */ \
|
||||
/* virtual bool Open_WasPasswordAsked() x; */ \
|
||||
/* virtual void Open_Clear_PasswordWasAsked_Flag() x; */ \
|
||||
|
||||
#endif
|
||||
|
||||
#define INTERFACE_IOpenCallbackUI(x) \
|
||||
virtual HRESULT Open_CheckBreak() x; \
|
||||
virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \
|
||||
virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \
|
||||
virtual HRESULT Open_Finished() x; \
|
||||
INTERFACE_IOpenCallbackUI_Crypto(x)
|
||||
|
||||
struct IOpenCallbackUI
|
||||
{
|
||||
INTERFACE_IOpenCallbackUI(=0)
|
||||
};
|
||||
|
||||
class COpenCallbackImp:
|
||||
public IArchiveOpenCallback,
|
||||
public IArchiveOpenVolumeCallback,
|
||||
public IArchiveOpenSetSubArchiveName,
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoGetTextPassword,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IArchiveOpenCallback(;)
|
||||
INTERFACE_IArchiveOpenVolumeCallback(;)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
#endif
|
||||
|
||||
STDMETHOD(SetSubArchiveName(const wchar_t *name))
|
||||
{
|
||||
_subArchiveMode = true;
|
||||
_subArchiveName = name;
|
||||
// TotalSize = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
FString _folderPrefix;
|
||||
NWindows::NFile::NFind::CFileInfo _fileInfo;
|
||||
bool _subArchiveMode;
|
||||
UString _subArchiveName;
|
||||
|
||||
public:
|
||||
UStringVector FileNames;
|
||||
CBoolVector FileNames_WasUsed;
|
||||
CRecordVector<UInt64> FileSizes;
|
||||
|
||||
bool PasswordWasAsked;
|
||||
|
||||
IOpenCallbackUI *Callback;
|
||||
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
|
||||
// UInt64 TotalSize;
|
||||
|
||||
COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}
|
||||
|
||||
void Init(const FString &folderPrefix, const FString &fileName)
|
||||
{
|
||||
_folderPrefix = folderPrefix;
|
||||
if (!_fileInfo.Find(_folderPrefix + fileName))
|
||||
throw 20121118;
|
||||
FileNames.Clear();
|
||||
FileNames_WasUsed.Clear();
|
||||
FileSizes.Clear();
|
||||
_subArchiveMode = false;
|
||||
// TotalSize = 0;
|
||||
PasswordWasAsked = false;
|
||||
}
|
||||
|
||||
bool SetSecondFileInfo(CFSTR newName)
|
||||
{
|
||||
return _fileInfo.Find(newName) && !_fileInfo.IsDir();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
// Bench.h
|
||||
|
||||
#ifndef __7ZIP_BENCH_H
|
||||
#define __7ZIP_BENCH_H
|
||||
|
||||
#include "../../../Windows/System.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../UI/Common/Property.h"
|
||||
|
||||
struct CBenchInfo
|
||||
{
|
||||
UInt64 GlobalTime;
|
||||
UInt64 GlobalFreq;
|
||||
UInt64 UserTime;
|
||||
UInt64 UserFreq;
|
||||
UInt64 UnpackSize;
|
||||
UInt64 PackSize;
|
||||
UInt64 NumIterations;
|
||||
|
||||
CBenchInfo(): NumIterations(0) {}
|
||||
UInt64 GetUsage() const;
|
||||
UInt64 GetRatingPerUsage(UInt64 rating) const;
|
||||
UInt64 GetSpeed(UInt64 numCommands) const;
|
||||
};
|
||||
|
||||
struct IBenchCallback
|
||||
{
|
||||
virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0;
|
||||
virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;
|
||||
virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;
|
||||
};
|
||||
|
||||
UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size);
|
||||
UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations);
|
||||
|
||||
const unsigned kBenchMinDicLogSize = 18;
|
||||
|
||||
UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary, bool totalBench = false);
|
||||
|
||||
struct IBenchPrintCallback
|
||||
{
|
||||
virtual void Print(const char *s) = 0;
|
||||
virtual void NewLine() = 0;
|
||||
virtual HRESULT CheckBreak() = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
struct IBenchFreqCallback
|
||||
{
|
||||
virtual void AddCpuFreq(UInt64 freq) = 0;
|
||||
};
|
||||
*/
|
||||
|
||||
HRESULT Bench(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IBenchPrintCallback *printCallback,
|
||||
IBenchCallback *benchCallback,
|
||||
// IBenchFreqCallback *freqCallback,
|
||||
const CObjectVector<CProperty> &props,
|
||||
UInt32 numIterations,
|
||||
bool multiDict
|
||||
);
|
||||
|
||||
AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti);
|
||||
|
||||
void GetSysInfo(AString &s1, AString &s2);
|
||||
void GetCpuName(AString &s);
|
||||
void GetCpuFeatures(AString &s);
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
void Add_LargePages_String(AString &s);
|
||||
#else
|
||||
// #define Add_LargePages_String
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,300 @@
|
||||
// CompressCall.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/Random.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/DLL.h"
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileMapping.h"
|
||||
#include "../../../Windows/MemoryLock.h"
|
||||
#include "../../../Windows/ProcessUtils.h"
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
|
||||
#include "../FileManager/RegistryUtils.h"
|
||||
|
||||
#include "CompressCall.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#define MY_TRY_BEGIN try {
|
||||
|
||||
#define MY_TRY_FINISH } \
|
||||
catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; }
|
||||
|
||||
#define MY_TRY_FINISH_VOID } \
|
||||
catch(...) { ErrorMessageHRESULT(E_FAIL); }
|
||||
|
||||
#define k7zGui "7zG.exe"
|
||||
|
||||
#define kShowDialogSwitch " -ad"
|
||||
#define kEmailSwitch " -seml."
|
||||
#define kIncludeSwitch " -i"
|
||||
#define kArchiveTypeSwitch " -t"
|
||||
#define kArcIncludeSwitches " -an -ai"
|
||||
#define kHashIncludeSwitches " -i"
|
||||
#define kStopSwitchParsing " --"
|
||||
|
||||
extern HWND g_HWND;
|
||||
|
||||
UString GetQuotedString(const UString &s)
|
||||
{
|
||||
UString s2 ('\"');
|
||||
s2 += s;
|
||||
s2 += '\"';
|
||||
return s2;
|
||||
}
|
||||
|
||||
static void ErrorMessage(LPCWSTR message)
|
||||
{
|
||||
MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL)
|
||||
{
|
||||
UString s2 = NError::MyFormatMessage(res);
|
||||
if (s)
|
||||
{
|
||||
s2.Add_LF();
|
||||
s2 += s;
|
||||
}
|
||||
ErrorMessage(s2);
|
||||
}
|
||||
|
||||
static HRESULT Call7zGui(const UString ¶ms,
|
||||
// LPCWSTR curDir,
|
||||
bool waitFinish,
|
||||
NSynchronization::CBaseEvent *event)
|
||||
{
|
||||
UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix());
|
||||
imageName += k7zGui;
|
||||
|
||||
CProcess process;
|
||||
WRes res = process.Create(imageName, params, NULL); // curDir);
|
||||
if (res != 0)
|
||||
{
|
||||
ErrorMessageHRESULT(res, imageName);
|
||||
return res;
|
||||
}
|
||||
if (waitFinish)
|
||||
process.Wait();
|
||||
else if (event != NULL)
|
||||
{
|
||||
HANDLE handles[] = { process, *event };
|
||||
::WaitForMultipleObjects(ARRAY_SIZE(handles), handles, FALSE, INFINITE);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void AddLagePagesSwitch(UString ¶ms)
|
||||
{
|
||||
if (ReadLockMemoryEnable())
|
||||
#ifndef UNDER_CE
|
||||
if (NSecurity::Get_LargePages_RiskLevel() == 0)
|
||||
#endif
|
||||
params += " -slp";
|
||||
}
|
||||
|
||||
class CRandNameGenerator
|
||||
{
|
||||
CRandom _random;
|
||||
public:
|
||||
CRandNameGenerator() { _random.Init(); }
|
||||
void GenerateName(UString &s, const char *prefix)
|
||||
{
|
||||
s += prefix;
|
||||
s.Add_UInt32((UInt32)(unsigned)_random.Generate());
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT CreateMap(const UStringVector &names,
|
||||
CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event,
|
||||
UString ¶ms)
|
||||
{
|
||||
size_t totalSize = 1;
|
||||
{
|
||||
FOR_VECTOR (i, names)
|
||||
totalSize += (names[i].Len() + 1);
|
||||
}
|
||||
totalSize *= sizeof(wchar_t);
|
||||
|
||||
CRandNameGenerator random;
|
||||
|
||||
UString mappingName;
|
||||
for (;;)
|
||||
{
|
||||
random.GenerateName(mappingName, "7zMap");
|
||||
|
||||
WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName));
|
||||
if (fileMapping.IsCreated() && res == 0)
|
||||
break;
|
||||
if (res != ERROR_ALREADY_EXISTS)
|
||||
return res;
|
||||
fileMapping.Close();
|
||||
}
|
||||
|
||||
UString eventName;
|
||||
for (;;)
|
||||
{
|
||||
random.GenerateName(eventName, "7zEvent");
|
||||
WRes res = event.CreateWithName(false, GetSystemString(eventName));
|
||||
if (event.IsCreated() && res == 0)
|
||||
break;
|
||||
if (res != ERROR_ALREADY_EXISTS)
|
||||
return res;
|
||||
event.Close();
|
||||
}
|
||||
|
||||
params += '#';
|
||||
params += mappingName;
|
||||
params += ':';
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(totalSize, temp);
|
||||
params += temp;
|
||||
|
||||
params += ':';
|
||||
params += eventName;
|
||||
|
||||
LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);
|
||||
if (!data)
|
||||
return E_FAIL;
|
||||
CFileUnmapper unmapper(data);
|
||||
{
|
||||
wchar_t *cur = (wchar_t *)data;
|
||||
*cur++ = 0; // it means wchar_t strings (UTF-16 in WIN32)
|
||||
FOR_VECTOR (i, names)
|
||||
{
|
||||
const UString &s = names[i];
|
||||
unsigned len = s.Len() + 1;
|
||||
wmemcpy(cur, (const wchar_t *)s, len);
|
||||
cur += len;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcName,
|
||||
const UString &arcType,
|
||||
bool addExtension,
|
||||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool waitFinish)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('a');
|
||||
|
||||
CFileMapping fileMapping;
|
||||
NSynchronization::CManualResetEvent event;
|
||||
params += kIncludeSwitch;
|
||||
RINOK(CreateMap(names, fileMapping, event, params));
|
||||
|
||||
if (!arcType.IsEmpty())
|
||||
{
|
||||
params += kArchiveTypeSwitch;
|
||||
params += arcType;
|
||||
}
|
||||
|
||||
if (email)
|
||||
params += kEmailSwitch;
|
||||
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
|
||||
AddLagePagesSwitch(params);
|
||||
|
||||
if (arcName.IsEmpty())
|
||||
params += " -an";
|
||||
|
||||
if (addExtension)
|
||||
params += " -saa";
|
||||
else
|
||||
params += " -sae";
|
||||
|
||||
params += kStopSwitchParsing;
|
||||
params.Add_Space();
|
||||
|
||||
if (!arcName.IsEmpty())
|
||||
{
|
||||
params += GetQuotedString(
|
||||
// #ifdef UNDER_CE
|
||||
arcPathPrefix +
|
||||
// #endif
|
||||
arcName);
|
||||
}
|
||||
|
||||
return Call7zGui(params,
|
||||
// (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix),
|
||||
waitFinish, &event);
|
||||
MY_TRY_FINISH
|
||||
}
|
||||
|
||||
static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, bool isHash)
|
||||
{
|
||||
AddLagePagesSwitch(params);
|
||||
params += (isHash ? kHashIncludeSwitches : kArcIncludeSwitches);
|
||||
CFileMapping fileMapping;
|
||||
NSynchronization::CManualResetEvent event;
|
||||
HRESULT result = CreateMap(arcPaths, fileMapping, event, params);
|
||||
if (result == S_OK)
|
||||
result = Call7zGui(params, false, &event);
|
||||
if (result != S_OK)
|
||||
ErrorMessageHRESULT(result);
|
||||
}
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('x');
|
||||
if (!outFolder.IsEmpty())
|
||||
{
|
||||
params += " -o";
|
||||
params += GetQuotedString(outFolder);
|
||||
}
|
||||
if (elimDup)
|
||||
params += " -spe";
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
ExtractGroupCommand(arcPaths, params, false);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
|
||||
void TestArchives(const UStringVector &arcPaths)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('t');
|
||||
ExtractGroupCommand(arcPaths, params, false);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
|
||||
void CalcChecksum(const UStringVector &paths, const UString &methodName)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('h');
|
||||
if (!methodName.IsEmpty())
|
||||
{
|
||||
params += " -scrc";
|
||||
params += methodName;
|
||||
}
|
||||
ExtractGroupCommand(paths, params, true);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
|
||||
void Benchmark(bool totalMode)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('b');
|
||||
if (totalMode)
|
||||
params += " -mm=*";
|
||||
AddLagePagesSwitch(params);
|
||||
HRESULT result = Call7zGui(params, false, NULL);
|
||||
if (result != S_OK)
|
||||
ErrorMessageHRESULT(result);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// CompressCall.h
|
||||
|
||||
#ifndef __COMPRESS_CALL_H
|
||||
#define __COMPRESS_CALL_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
UString GetQuotedString(const UString &s);
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcName,
|
||||
const UString &arcType,
|
||||
bool addExtension,
|
||||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool waitFinish);
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup);
|
||||
void TestArchives(const UStringVector &arcPaths);
|
||||
void CalcChecksum(const UStringVector &paths, const UString &methodName);
|
||||
void Benchmark(bool totalMode);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,276 @@
|
||||
// CompressCall2.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyException.h"
|
||||
|
||||
#include "../../UI/Common/EnumDirItems.h"
|
||||
|
||||
#include "../../UI/GUI/BenchmarkDialog.h"
|
||||
#include "../../UI/GUI/ExtractGUI.h"
|
||||
#include "../../UI/GUI/UpdateGUI.h"
|
||||
#include "../../UI/GUI/HashGUI.h"
|
||||
|
||||
#include "../../UI/GUI/ExtractRes.h"
|
||||
|
||||
#include "CompressCall.h"
|
||||
|
||||
extern HWND g_HWND;
|
||||
|
||||
#define MY_TRY_BEGIN HRESULT result; try {
|
||||
#define MY_TRY_FINISH } \
|
||||
catch(CSystemException &e) { result = e.ErrorCode; } \
|
||||
catch(UString &s) { ErrorMessage(s); result = E_FAIL; } \
|
||||
catch(...) { result = E_FAIL; } \
|
||||
if (result != S_OK && result != E_ABORT) \
|
||||
ErrorMessageHRESULT(result);
|
||||
|
||||
static void ThrowException_if_Error(HRESULT res)
|
||||
{
|
||||
if (res != S_OK)
|
||||
throw CSystemException(res);
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
#define CREATE_CODECS \
|
||||
CCodecs *codecs = new CCodecs; \
|
||||
CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \
|
||||
ThrowException_if_Error(codecs->Load());
|
||||
|
||||
#define LOAD_EXTERNAL_CODECS \
|
||||
CExternalCodecs __externalCodecs; \
|
||||
__externalCodecs.GetCodecs = codecs; \
|
||||
__externalCodecs.GetHashers = codecs; \
|
||||
ThrowException_if_Error(__externalCodecs.Load());
|
||||
|
||||
#else
|
||||
|
||||
#define CREATE_CODECS \
|
||||
CCodecs *codecs = new CCodecs; \
|
||||
CMyComPtr<IUnknown> compressCodecsInfo = codecs; \
|
||||
ThrowException_if_Error(codecs->Load());
|
||||
|
||||
#define LOAD_EXTERNAL_CODECS
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
UString GetQuotedString(const UString &s)
|
||||
{
|
||||
UString s2 ('\"');
|
||||
s2 += s;
|
||||
s2 += '\"';
|
||||
return s2;
|
||||
}
|
||||
|
||||
static void ErrorMessage(LPCWSTR message)
|
||||
{
|
||||
MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR);
|
||||
}
|
||||
|
||||
static void ErrorMessageHRESULT(HRESULT res)
|
||||
{
|
||||
ErrorMessage(HResultToMessage(res));
|
||||
}
|
||||
|
||||
static void ErrorLangMessage(UINT resourceID)
|
||||
{
|
||||
ErrorMessage(LangString(resourceID));
|
||||
}
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcName,
|
||||
const UString &arcType,
|
||||
bool addExtension,
|
||||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool /* waitFinish */)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
|
||||
CUpdateCallbackGUI callback;
|
||||
|
||||
callback.Init();
|
||||
|
||||
CUpdateOptions uo;
|
||||
uo.EMailMode = email;
|
||||
uo.SetActionCommand_Add();
|
||||
|
||||
uo.ArcNameMode = (addExtension ? k_ArcNameMode_Add : k_ArcNameMode_Exact);
|
||||
|
||||
CObjectVector<COpenType> formatIndices;
|
||||
if (!ParseOpenTypes(*codecs, arcType, formatIndices))
|
||||
{
|
||||
ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
|
||||
return E_FAIL;
|
||||
}
|
||||
const UString arcPath = arcPathPrefix + arcName;
|
||||
if (!uo.InitFormatIndex(codecs, formatIndices, arcPath) ||
|
||||
!uo.SetArcPath(codecs, arcPath))
|
||||
{
|
||||
ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
NWildcard::CCensor censor;
|
||||
FOR_VECTOR (i, names)
|
||||
{
|
||||
censor.AddPreItem(names[i]);
|
||||
}
|
||||
|
||||
bool messageWasDisplayed = false;
|
||||
|
||||
result = UpdateGUI(codecs,
|
||||
formatIndices, arcPath,
|
||||
censor, uo, showDialog, messageWasDisplayed, &callback, g_HWND);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT && messageWasDisplayed)
|
||||
return E_FAIL;
|
||||
throw CSystemException(result);
|
||||
}
|
||||
if (callback.FailedFiles.Size() > 0)
|
||||
{
|
||||
if (!messageWasDisplayed)
|
||||
throw CSystemException(E_FAIL);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
MY_TRY_FINISH
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
|
||||
bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
|
||||
CExtractOptions eo;
|
||||
eo.OutputDir = us2fs(outFolder);
|
||||
eo.TestMode = testMode;
|
||||
eo.ElimDup.Val = elimDup;
|
||||
eo.ElimDup.Def = elimDup;
|
||||
|
||||
CExtractCallbackImp *ecs = new CExtractCallbackImp;
|
||||
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
|
||||
|
||||
ecs->Init();
|
||||
|
||||
// eo.CalcCrc = options.CalcCrc;
|
||||
|
||||
UStringVector arcPathsSorted;
|
||||
UStringVector arcFullPathsSorted;
|
||||
{
|
||||
NWildcard::CCensor arcCensor;
|
||||
FOR_VECTOR (i, arcPaths)
|
||||
{
|
||||
arcCensor.AddPreItem(arcPaths[i]);
|
||||
}
|
||||
arcCensor.AddPathsToCensor(NWildcard::k_RelatPath);
|
||||
CDirItemsStat st;
|
||||
EnumerateDirItemsAndSort(arcCensor, NWildcard::k_RelatPath, UString(),
|
||||
arcPathsSorted, arcFullPathsSorted,
|
||||
st,
|
||||
NULL // &scan: change it!!!!
|
||||
);
|
||||
}
|
||||
|
||||
CObjectVector<COpenType> formatIndices;
|
||||
|
||||
NWildcard::CCensor censor;
|
||||
{
|
||||
censor.AddPreItem_Wildcard();
|
||||
}
|
||||
|
||||
censor.AddPathsToCensor(NWildcard::k_RelatPath);
|
||||
|
||||
bool messageWasDisplayed = false;
|
||||
|
||||
ecs->MultiArcMode = (arcPathsSorted.Size() > 1);
|
||||
|
||||
result = ExtractGUI(codecs,
|
||||
formatIndices, CIntVector(),
|
||||
arcPathsSorted, arcFullPathsSorted,
|
||||
censor.Pairs.Front().Head, eo, NULL, showDialog, messageWasDisplayed, ecs, g_HWND);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT && messageWasDisplayed)
|
||||
return E_FAIL;
|
||||
throw CSystemException(result);
|
||||
}
|
||||
return ecs->IsOK() ? S_OK : E_FAIL;
|
||||
|
||||
MY_TRY_FINISH
|
||||
return result;
|
||||
}
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup)
|
||||
{
|
||||
ExtractGroupCommand(arcPaths, showDialog, outFolder, false, elimDup);
|
||||
}
|
||||
|
||||
void TestArchives(const UStringVector &arcPaths)
|
||||
{
|
||||
ExtractGroupCommand(arcPaths, true, UString(), true);
|
||||
}
|
||||
|
||||
void CalcChecksum(const UStringVector &paths, const UString &methodName)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
LOAD_EXTERNAL_CODECS
|
||||
|
||||
NWildcard::CCensor censor;
|
||||
FOR_VECTOR (i, paths)
|
||||
{
|
||||
censor.AddPreItem(paths[i]);
|
||||
}
|
||||
|
||||
censor.AddPathsToCensor(NWildcard::k_RelatPath);
|
||||
bool messageWasDisplayed = false;
|
||||
|
||||
CHashOptions options;
|
||||
options.Methods.Add(methodName);
|
||||
|
||||
result = HashCalcGUI(EXTERNAL_CODECS_VARS_L censor, options, messageWasDisplayed);
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT && messageWasDisplayed)
|
||||
return; // E_FAIL;
|
||||
throw CSystemException(result);
|
||||
}
|
||||
|
||||
MY_TRY_FINISH
|
||||
return; // result;
|
||||
}
|
||||
|
||||
void Benchmark(bool totalMode)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
LOAD_EXTERNAL_CODECS
|
||||
|
||||
CObjectVector<CProperty> props;
|
||||
if (totalMode)
|
||||
{
|
||||
CProperty prop;
|
||||
prop.Name = "m";
|
||||
prop.Value = "*";
|
||||
props.Add(prop);
|
||||
}
|
||||
result = Benchmark(EXTERNAL_CODECS_VARS_L props, g_HWND);
|
||||
|
||||
MY_TRY_FINISH
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// DefaultName.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "DefaultName.h"
|
||||
|
||||
static UString GetDefaultName3(const UString &fileName,
|
||||
const UString &extension, const UString &addSubExtension)
|
||||
{
|
||||
const unsigned extLen = extension.Len();
|
||||
const unsigned fileNameLen = fileName.Len();
|
||||
|
||||
if (fileNameLen > extLen + 1)
|
||||
{
|
||||
const unsigned dotPos = fileNameLen - (extLen + 1);
|
||||
if (fileName[dotPos] == '.')
|
||||
if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1)))
|
||||
return fileName.Left(dotPos) + addSubExtension;
|
||||
}
|
||||
|
||||
int dotPos = fileName.ReverseFind_Dot();
|
||||
if (dotPos > 0)
|
||||
return fileName.Left(dotPos) + addSubExtension;
|
||||
|
||||
if (addSubExtension.IsEmpty())
|
||||
return fileName + L'~';
|
||||
else
|
||||
return fileName + addSubExtension;
|
||||
}
|
||||
|
||||
UString GetDefaultName2(const UString &fileName,
|
||||
const UString &extension, const UString &addSubExtension)
|
||||
{
|
||||
UString name = GetDefaultName3(fileName, extension, addSubExtension);
|
||||
name.TrimRight();
|
||||
return name;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// DefaultName.h
|
||||
|
||||
#ifndef __DEFAULT_NAME_H
|
||||
#define __DEFAULT_NAME_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
UString GetDefaultName2(const UString &fileName,
|
||||
const UString &extension, const UString &addSubExtension);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,190 @@
|
||||
// DirItem.h
|
||||
|
||||
#ifndef __DIR_ITEM_H
|
||||
#define __DIR_ITEM_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
#include "../../Common/UniqBlocks.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
struct CDirItemsStat
|
||||
{
|
||||
UInt64 NumDirs;
|
||||
UInt64 NumFiles;
|
||||
UInt64 NumAltStreams;
|
||||
UInt64 FilesSize;
|
||||
UInt64 AltStreamsSize;
|
||||
|
||||
UInt64 NumErrors;
|
||||
|
||||
// UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }
|
||||
UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; }
|
||||
UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }
|
||||
|
||||
bool IsEmpty() const { return
|
||||
0 == NumDirs
|
||||
&& 0 == NumFiles
|
||||
&& 0 == NumAltStreams
|
||||
&& 0 == FilesSize
|
||||
&& 0 == AltStreamsSize
|
||||
&& 0 == NumErrors; }
|
||||
|
||||
CDirItemsStat():
|
||||
NumDirs(0),
|
||||
NumFiles(0),
|
||||
NumAltStreams(0),
|
||||
FilesSize(0),
|
||||
AltStreamsSize(0),
|
||||
NumErrors(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct CDirItemsStat2: public CDirItemsStat
|
||||
{
|
||||
UInt64 Anti_NumDirs;
|
||||
UInt64 Anti_NumFiles;
|
||||
UInt64 Anti_NumAltStreams;
|
||||
|
||||
// UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); }
|
||||
UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); }
|
||||
|
||||
bool IsEmpty() const { return CDirItemsStat::IsEmpty()
|
||||
&& 0 == Anti_NumDirs
|
||||
&& 0 == Anti_NumFiles
|
||||
&& 0 == Anti_NumAltStreams; }
|
||||
|
||||
CDirItemsStat2():
|
||||
Anti_NumDirs(0),
|
||||
Anti_NumFiles(0),
|
||||
Anti_NumAltStreams(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define INTERFACE_IDirItemsCallback(x) \
|
||||
virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \
|
||||
virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \
|
||||
|
||||
struct IDirItemsCallback
|
||||
{
|
||||
INTERFACE_IDirItemsCallback(=0)
|
||||
};
|
||||
|
||||
struct CDirItem
|
||||
{
|
||||
UInt64 Size;
|
||||
FILETIME CTime;
|
||||
FILETIME ATime;
|
||||
FILETIME MTime;
|
||||
UString Name;
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
// UString ShortName;
|
||||
CByteBuffer ReparseData;
|
||||
CByteBuffer ReparseData2; // fixed (reduced) absolute links
|
||||
|
||||
bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }
|
||||
#endif
|
||||
|
||||
UInt32 Attrib;
|
||||
int PhyParent;
|
||||
int LogParent;
|
||||
int SecureIndex;
|
||||
|
||||
bool IsAltStream;
|
||||
|
||||
CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {}
|
||||
bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
|
||||
};
|
||||
|
||||
class CDirItems
|
||||
{
|
||||
UStringVector Prefixes;
|
||||
CIntVector PhyParents;
|
||||
CIntVector LogParents;
|
||||
|
||||
UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;
|
||||
|
||||
HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);
|
||||
|
||||
public:
|
||||
CObjectVector<CDirItem> Items;
|
||||
|
||||
bool SymLinks;
|
||||
|
||||
bool ScanAltStreams;
|
||||
|
||||
CDirItemsStat Stat;
|
||||
|
||||
#ifndef UNDER_CE
|
||||
HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,
|
||||
const FString &phyPrefix);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
CUniqBlocks SecureBlocks;
|
||||
CByteBuffer TempSecureBuf;
|
||||
bool _saclEnabled;
|
||||
bool ReadSecure;
|
||||
|
||||
HRESULT AddSecurityItem(const FString &path, int &secureIndex);
|
||||
|
||||
#endif
|
||||
|
||||
IDirItemsCallback *Callback;
|
||||
|
||||
CDirItems();
|
||||
|
||||
void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
|
||||
const NWindows::NFile::NFind::CFileInfo &fi);
|
||||
|
||||
HRESULT AddError(const FString &path, DWORD errorCode);
|
||||
HRESULT AddError(const FString &path);
|
||||
|
||||
HRESULT ScanProgress(const FString &path);
|
||||
|
||||
// unsigned GetNumFolders() const { return Prefixes.Size(); }
|
||||
FString GetPhyPath(unsigned index) const;
|
||||
UString GetLogPath(unsigned index) const;
|
||||
|
||||
unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);
|
||||
void DeleteLastPrefix();
|
||||
|
||||
HRESULT EnumerateItems2(
|
||||
const FString &phyPrefix,
|
||||
const UString &logPrefix,
|
||||
const FStringVector &filePaths,
|
||||
FStringVector *requestedPaths);
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
void FillFixedReparse();
|
||||
#endif
|
||||
|
||||
void ReserveDown();
|
||||
};
|
||||
|
||||
struct CArcItem
|
||||
{
|
||||
UInt64 Size;
|
||||
FILETIME MTime;
|
||||
UString Name;
|
||||
bool IsDir;
|
||||
bool IsAltStream;
|
||||
bool SizeDefined;
|
||||
bool MTimeDefined;
|
||||
bool Censored;
|
||||
UInt32 IndexInServer;
|
||||
int TimeType;
|
||||
|
||||
CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
// EnumDirItems.h
|
||||
|
||||
#ifndef __ENUM_DIR_ITEMS_H
|
||||
#define __ENUM_DIR_ITEMS_H
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
#include "DirItem.h"
|
||||
|
||||
void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
|
||||
const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems);
|
||||
|
||||
HRESULT EnumerateItems(
|
||||
const NWildcard::CCensor &censor,
|
||||
NWildcard::ECensorPathMode pathMode,
|
||||
const UString &addPathPrefix,
|
||||
CDirItems &dirItems);
|
||||
|
||||
|
||||
struct CMessagePathException: public UString
|
||||
{
|
||||
CMessagePathException(const char *a, const wchar_t *u = NULL);
|
||||
CMessagePathException(const wchar_t *a, const wchar_t *u = NULL);
|
||||
};
|
||||
|
||||
|
||||
HRESULT EnumerateDirItemsAndSort(
|
||||
NWildcard::CCensor &censor,
|
||||
NWildcard::ECensorPathMode pathMode,
|
||||
const UString &addPathPrefix,
|
||||
UStringVector &sortedPaths,
|
||||
UStringVector &sortedFullPaths,
|
||||
CDirItemsStat &st,
|
||||
IDirItemsCallback *callback);
|
||||
|
||||
#ifdef _WIN32
|
||||
void ConvertToLongNames(NWildcard::CCensor &censor);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
// ExitCode.h
|
||||
|
||||
#ifndef __EXIT_CODE_H
|
||||
#define __EXIT_CODE_H
|
||||
|
||||
namespace NExitCode {
|
||||
|
||||
enum EEnum {
|
||||
|
||||
kSuccess = 0, // Successful operation
|
||||
kWarning = 1, // Non fatal error(s) occurred
|
||||
kFatalError = 2, // A fatal error occurred
|
||||
// kCRCError = 3, // A CRC error occurred when unpacking
|
||||
// kLockedArchive = 4, // Attempt to modify an archive previously locked
|
||||
// kWriteError = 5, // Write to disk error
|
||||
// kOpenError = 6, // Open file error
|
||||
kUserError = 7, // Command line option error
|
||||
kMemoryError = 8, // Not enough memory for operation
|
||||
// kCreateFileError = 9, // Create file error
|
||||
|
||||
kUserBreak = 255 // User stopped the process
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,482 @@
|
||||
// Extract.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Sort.h"
|
||||
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/PropVariantConv.h"
|
||||
|
||||
#include "../Common/ExtractingFilePath.h"
|
||||
|
||||
#include "Extract.h"
|
||||
#include "SetProperties.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
static HRESULT DecompressArchive(
|
||||
CCodecs *codecs,
|
||||
const CArchiveLink &arcLink,
|
||||
UInt64 packSize,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
bool calcCrc,
|
||||
IExtractCallbackUI *callback,
|
||||
CArchiveExtractCallback *ecs,
|
||||
UString &errorMessage,
|
||||
UInt64 &stdInProcessed)
|
||||
{
|
||||
const CArc &arc = arcLink.Arcs.Back();
|
||||
stdInProcessed = 0;
|
||||
IInArchive *archive = arc.Archive;
|
||||
CRecordVector<UInt32> realIndices;
|
||||
|
||||
UStringVector removePathParts;
|
||||
|
||||
FString outDir = options.OutputDir;
|
||||
UString replaceName = arc.DefaultName;
|
||||
|
||||
if (arcLink.Arcs.Size() > 1)
|
||||
{
|
||||
// Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1".
|
||||
// So it extracts different archives to one folder.
|
||||
// We will use top level archive name
|
||||
const CArc &arc0 = arcLink.Arcs[0];
|
||||
if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe"))
|
||||
replaceName = arc0.DefaultName;
|
||||
}
|
||||
|
||||
outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName)));
|
||||
|
||||
bool elimIsPossible = false;
|
||||
UString elimPrefix; // only pure name without dir delimiter
|
||||
FString outDirReduced = outDir;
|
||||
|
||||
if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)
|
||||
{
|
||||
UString dirPrefix;
|
||||
SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);
|
||||
if (!elimPrefix.IsEmpty())
|
||||
{
|
||||
if (IsPathSepar(elimPrefix.Back()))
|
||||
elimPrefix.DeleteBack();
|
||||
if (!elimPrefix.IsEmpty())
|
||||
{
|
||||
outDirReduced = us2fs(dirPrefix);
|
||||
elimIsPossible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
|
||||
|
||||
if (!options.StdInMode)
|
||||
{
|
||||
UInt32 numItems;
|
||||
RINOK(archive->GetNumberOfItems(&numItems));
|
||||
|
||||
CReadArcItem item;
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (elimIsPossible || !allFilesAreAllowed)
|
||||
{
|
||||
RINOK(arc.GetItem(i, item));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
item.IsAltStream = false;
|
||||
if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream)
|
||||
{
|
||||
RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
if (!options.NtOptions.AltStreams.Val && item.IsAltStream)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (elimIsPossible)
|
||||
{
|
||||
const UString &s =
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
item.MainPath;
|
||||
#else
|
||||
item.Path;
|
||||
#endif
|
||||
if (!IsPath1PrefixedByPath2(s, elimPrefix))
|
||||
elimIsPossible = false;
|
||||
else
|
||||
{
|
||||
wchar_t c = s[elimPrefix.Len()];
|
||||
if (c == 0)
|
||||
{
|
||||
if (!item.MainIsDir)
|
||||
elimIsPossible = false;
|
||||
}
|
||||
else if (!IsPathSepar(c))
|
||||
elimIsPossible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allFilesAreAllowed)
|
||||
{
|
||||
if (!CensorNode_CheckPath(wildcardCensor, item))
|
||||
continue;
|
||||
}
|
||||
|
||||
realIndices.Add(i);
|
||||
}
|
||||
|
||||
if (realIndices.Size() == 0)
|
||||
{
|
||||
callback->ThereAreNoFiles();
|
||||
return callback->ExtractResult(S_OK);
|
||||
}
|
||||
}
|
||||
|
||||
if (elimIsPossible)
|
||||
{
|
||||
removePathParts.Add(elimPrefix);
|
||||
// outDir = outDirReduced;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// GetCorrectFullFsPath doesn't like "..".
|
||||
// outDir.TrimRight();
|
||||
// outDir = GetCorrectFullFsPath(outDir);
|
||||
#endif
|
||||
|
||||
if (outDir.IsEmpty())
|
||||
outDir = "." STRING_PATH_SEPARATOR;
|
||||
/*
|
||||
#ifdef _WIN32
|
||||
else if (NName::IsAltPathPrefix(outDir)) {}
|
||||
#endif
|
||||
*/
|
||||
else if (!CreateComplexDir(outDir))
|
||||
{
|
||||
HRESULT res = ::GetLastError();
|
||||
if (res == S_OK)
|
||||
res = E_FAIL;
|
||||
errorMessage = "Can not create output directory: ";
|
||||
errorMessage += fs2us(outDir);
|
||||
return res;
|
||||
}
|
||||
|
||||
ecs->Init(
|
||||
options.NtOptions,
|
||||
options.StdInMode ? &wildcardCensor : NULL,
|
||||
&arc,
|
||||
callback,
|
||||
options.StdOutMode, options.TestMode,
|
||||
outDir,
|
||||
removePathParts, false,
|
||||
packSize);
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
if (!options.StdInMode &&
|
||||
!options.TestMode &&
|
||||
options.NtOptions.HardLinks.Val)
|
||||
{
|
||||
RINOK(ecs->PrepareHardLinks(&realIndices));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT result;
|
||||
Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
|
||||
|
||||
CArchiveExtractCallback_Closer ecsCloser(ecs);
|
||||
|
||||
if (options.StdInMode)
|
||||
{
|
||||
result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
|
||||
NCOM::CPropVariant prop;
|
||||
if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
|
||||
ConvertPropVariantToUInt64(prop, stdInProcessed);
|
||||
}
|
||||
else
|
||||
result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
|
||||
|
||||
HRESULT res2 = ecsCloser.Close();
|
||||
if (result == S_OK)
|
||||
result = res2;
|
||||
|
||||
return callback->ExtractResult(result);
|
||||
}
|
||||
|
||||
/* v9.31: BUG was fixed:
|
||||
Sorted list for file paths was sorted with case insensitive compare function.
|
||||
But FindInSorted function did binary search via case sensitive compare function */
|
||||
|
||||
int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name)
|
||||
{
|
||||
unsigned left = 0, right = fileName.Size();
|
||||
while (left != right)
|
||||
{
|
||||
unsigned mid = (left + right) / 2;
|
||||
const UString &midValue = fileName[mid];
|
||||
int compare = CompareFileNames(name, midValue);
|
||||
if (compare == 0)
|
||||
return mid;
|
||||
if (compare < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
HRESULT Extract(
|
||||
CCodecs *codecs,
|
||||
const CObjectVector<COpenType> &types,
|
||||
const CIntVector &excludedFormats,
|
||||
UStringVector &arcPaths, UStringVector &arcPathsFull,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IExtractCallbackUI *extractCallback,
|
||||
#ifndef _SFX
|
||||
IHashCalc *hash,
|
||||
#endif
|
||||
UString &errorMessage,
|
||||
CDecompressStat &st)
|
||||
{
|
||||
st.Clear();
|
||||
UInt64 totalPackSize = 0;
|
||||
CRecordVector<UInt64> arcSizes;
|
||||
|
||||
unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < numArcs; i++)
|
||||
{
|
||||
NFind::CFileInfo fi;
|
||||
fi.Size = 0;
|
||||
if (!options.StdInMode)
|
||||
{
|
||||
const FString &arcPath = us2fs(arcPaths[i]);
|
||||
if (!fi.Find(arcPath))
|
||||
throw "there is no such archive";
|
||||
if (fi.IsDir())
|
||||
throw "can't decompress folder";
|
||||
}
|
||||
arcSizes.Add(fi.Size);
|
||||
totalPackSize += fi.Size;
|
||||
}
|
||||
|
||||
CBoolArr skipArcs(numArcs);
|
||||
for (i = 0; i < numArcs; i++)
|
||||
skipArcs[i] = false;
|
||||
|
||||
CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
|
||||
CMyComPtr<IArchiveExtractCallback> ec(ecs);
|
||||
bool multi = (numArcs > 1);
|
||||
ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode,
|
||||
false // keepEmptyDirParts
|
||||
);
|
||||
#ifndef _SFX
|
||||
ecs->SetHashMethods(hash);
|
||||
#endif
|
||||
|
||||
if (multi)
|
||||
{
|
||||
RINOK(extractCallback->SetTotal(totalPackSize));
|
||||
}
|
||||
|
||||
UInt64 totalPackProcessed = 0;
|
||||
bool thereAreNotOpenArcs = false;
|
||||
|
||||
for (i = 0; i < numArcs; i++)
|
||||
{
|
||||
if (skipArcs[i])
|
||||
continue;
|
||||
|
||||
const UString &arcPath = arcPaths[i];
|
||||
NFind::CFileInfo fi;
|
||||
if (options.StdInMode)
|
||||
{
|
||||
fi.Size = 0;
|
||||
fi.Attrib = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fi.Find(us2fs(arcPath)) || fi.IsDir())
|
||||
throw "there is no such archive";
|
||||
}
|
||||
|
||||
/*
|
||||
#ifndef _NO_CRYPTO
|
||||
openCallback->Open_Clear_PasswordWasAsked_Flag();
|
||||
#endif
|
||||
*/
|
||||
|
||||
RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode));
|
||||
CArchiveLink arcLink;
|
||||
|
||||
CObjectVector<COpenType> types2 = types;
|
||||
/*
|
||||
#ifndef _SFX
|
||||
if (types.IsEmpty())
|
||||
{
|
||||
int pos = arcPath.ReverseFind(L'.');
|
||||
if (pos >= 0)
|
||||
{
|
||||
UString s = arcPath.Ptr(pos + 1);
|
||||
int index = codecs->FindFormatForExtension(s);
|
||||
if (index >= 0 && s == L"001")
|
||||
{
|
||||
s = arcPath.Left(pos);
|
||||
pos = s.ReverseFind(L'.');
|
||||
if (pos >= 0)
|
||||
{
|
||||
int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));
|
||||
if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0
|
||||
{
|
||||
types2.Add(index2);
|
||||
types2.Add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
COpenOptions op;
|
||||
#ifndef _SFX
|
||||
op.props = &options.Properties;
|
||||
#endif
|
||||
op.codecs = codecs;
|
||||
op.types = &types2;
|
||||
op.excludedFormats = &excludedFormats;
|
||||
op.stdInMode = options.StdInMode;
|
||||
op.stream = NULL;
|
||||
op.filePath = arcPath;
|
||||
|
||||
HRESULT result = arcLink.Open_Strict(op, openCallback);
|
||||
|
||||
if (result == E_ABORT)
|
||||
return result;
|
||||
|
||||
// arcLink.Set_ErrorsText();
|
||||
RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result));
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
thereAreNotOpenArcs = true;
|
||||
if (!options.StdInMode)
|
||||
{
|
||||
NFind::CFileInfo fi2;
|
||||
if (fi2.Find(us2fs(arcPath)))
|
||||
if (!fi2.IsDir())
|
||||
totalPackProcessed += fi2.Size;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!options.StdInMode)
|
||||
{
|
||||
// numVolumes += arcLink.VolumePaths.Size();
|
||||
// arcLink.VolumesSize;
|
||||
|
||||
// totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);
|
||||
// numArcs = arcPaths.Size();
|
||||
if (arcLink.VolumePaths.Size() != 0)
|
||||
{
|
||||
Int64 correctionSize = arcLink.VolumesSize;
|
||||
FOR_VECTOR (v, arcLink.VolumePaths)
|
||||
{
|
||||
int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
|
||||
if (index >= 0)
|
||||
{
|
||||
if ((unsigned)index > i)
|
||||
{
|
||||
skipArcs[(unsigned)index] = true;
|
||||
correctionSize -= arcSizes[(unsigned)index];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (correctionSize != 0)
|
||||
{
|
||||
Int64 newPackSize = (Int64)totalPackSize + correctionSize;
|
||||
if (newPackSize < 0)
|
||||
newPackSize = 0;
|
||||
totalPackSize = newPackSize;
|
||||
RINOK(extractCallback->SetTotal(totalPackSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Now openCallback and extractCallback use same object. So we don't need to send password.
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
bool passwordIsDefined;
|
||||
UString password;
|
||||
RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password));
|
||||
if (passwordIsDefined)
|
||||
{
|
||||
RINOK(extractCallback->SetPassword(password));
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
CArc &arc = arcLink.Arcs.Back();
|
||||
arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
|
||||
arc.MTime = fi.MTime;
|
||||
|
||||
UInt64 packProcessed;
|
||||
bool calcCrc =
|
||||
#ifndef _SFX
|
||||
(hash != NULL);
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
|
||||
RINOK(DecompressArchive(
|
||||
codecs,
|
||||
arcLink,
|
||||
fi.Size + arcLink.VolumesSize,
|
||||
wildcardCensor,
|
||||
options,
|
||||
calcCrc,
|
||||
extractCallback, ecs, errorMessage, packProcessed));
|
||||
|
||||
if (!options.StdInMode)
|
||||
packProcessed = fi.Size + arcLink.VolumesSize;
|
||||
totalPackProcessed += packProcessed;
|
||||
ecs->LocalProgressSpec->InSize += packProcessed;
|
||||
ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;
|
||||
if (!errorMessage.IsEmpty())
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (multi || thereAreNotOpenArcs)
|
||||
{
|
||||
RINOK(extractCallback->SetTotal(totalPackSize));
|
||||
RINOK(extractCallback->SetCompleted(&totalPackProcessed));
|
||||
}
|
||||
|
||||
st.NumFolders = ecs->NumFolders;
|
||||
st.NumFiles = ecs->NumFiles;
|
||||
st.NumAltStreams = ecs->NumAltStreams;
|
||||
st.UnpackSize = ecs->UnpackSize;
|
||||
st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;
|
||||
st.NumArchives = arcPaths.Size();
|
||||
st.PackSize = ecs->LocalProgressSpec->InSize;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Extract.h
|
||||
|
||||
#ifndef __EXTRACT_H
|
||||
#define __EXTRACT_H
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "ArchiveExtractCallback.h"
|
||||
#include "ArchiveOpenCallback.h"
|
||||
#include "ExtractMode.h"
|
||||
#include "Property.h"
|
||||
|
||||
#include "../Common/LoadCodecs.h"
|
||||
|
||||
struct CExtractOptionsBase
|
||||
{
|
||||
CBoolPair ElimDup;
|
||||
|
||||
bool PathMode_Force;
|
||||
bool OverwriteMode_Force;
|
||||
NExtract::NPathMode::EEnum PathMode;
|
||||
NExtract::NOverwriteMode::EEnum OverwriteMode;
|
||||
|
||||
FString OutputDir;
|
||||
CExtractNtOptions NtOptions;
|
||||
|
||||
CExtractOptionsBase():
|
||||
PathMode_Force(false),
|
||||
OverwriteMode_Force(false),
|
||||
PathMode(NExtract::NPathMode::kFullPaths),
|
||||
OverwriteMode(NExtract::NOverwriteMode::kAsk)
|
||||
{}
|
||||
};
|
||||
|
||||
struct CExtractOptions: public CExtractOptionsBase
|
||||
{
|
||||
bool StdInMode;
|
||||
bool StdOutMode;
|
||||
bool YesToAll;
|
||||
bool TestMode;
|
||||
|
||||
// bool ShowDialog;
|
||||
// bool PasswordEnabled;
|
||||
// UString Password;
|
||||
#ifndef _SFX
|
||||
CObjectVector<CProperty> Properties;
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
CCodecs *Codecs;
|
||||
#endif
|
||||
|
||||
CExtractOptions():
|
||||
TestMode(false),
|
||||
StdInMode(false),
|
||||
StdOutMode(false),
|
||||
YesToAll(false)
|
||||
{}
|
||||
};
|
||||
|
||||
struct CDecompressStat
|
||||
{
|
||||
UInt64 NumArchives;
|
||||
UInt64 UnpackSize;
|
||||
UInt64 AltStreams_UnpackSize;
|
||||
UInt64 PackSize;
|
||||
UInt64 NumFolders;
|
||||
UInt64 NumFiles;
|
||||
UInt64 NumAltStreams;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0;
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT Extract(
|
||||
CCodecs *codecs,
|
||||
const CObjectVector<COpenType> &types,
|
||||
const CIntVector &excludedFormats,
|
||||
UStringVector &archivePaths, UStringVector &archivePathsFull,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IExtractCallbackUI *extractCallback,
|
||||
#ifndef _SFX
|
||||
IHashCalc *hash,
|
||||
#endif
|
||||
UString &errorMessage,
|
||||
CDecompressStat &st);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
// ExtractMode.h
|
||||
|
||||
#ifndef __EXTRACT_MODE_H
|
||||
#define __EXTRACT_MODE_H
|
||||
|
||||
namespace NExtract {
|
||||
|
||||
namespace NPathMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kFullPaths,
|
||||
kCurPaths,
|
||||
kNoPaths,
|
||||
kAbsPaths,
|
||||
kNoPathsAlt // alt streams must be extracted without name of base file
|
||||
};
|
||||
}
|
||||
|
||||
namespace NOverwriteMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kAsk,
|
||||
kOverwrite,
|
||||
kSkip,
|
||||
kRename,
|
||||
kRenameExisting
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,280 @@
|
||||
// ExtractingFilePath.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileName.h"
|
||||
|
||||
#include "ExtractingFilePath.h"
|
||||
|
||||
bool g_PathTrailReplaceMode =
|
||||
#ifdef _WIN32
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
static void ReplaceIncorrectChars(UString &s)
|
||||
{
|
||||
{
|
||||
for (unsigned i = 0; i < s.Len(); i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (
|
||||
#ifdef _WIN32
|
||||
c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'
|
||||
|| c == '/'
|
||||
// || c == 0x202E // RLO
|
||||
||
|
||||
#endif
|
||||
c == WCHAR_PATH_SEPARATOR)
|
||||
s.ReplaceOneCharAtPos(i, '_');
|
||||
}
|
||||
}
|
||||
|
||||
if (g_PathTrailReplaceMode)
|
||||
{
|
||||
/*
|
||||
// if (g_PathTrailReplaceMode == 1)
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
wchar_t c = s.Back();
|
||||
if (c == '.' || c == ' ')
|
||||
{
|
||||
// s += (wchar_t)(0x9c); // STRING TERMINATOR
|
||||
s += (wchar_t)'_';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
unsigned i;
|
||||
for (i = s.Len(); i != 0;)
|
||||
{
|
||||
wchar_t c = s[i - 1];
|
||||
if (c != '.' && c != ' ')
|
||||
break;
|
||||
i--;
|
||||
s.ReplaceOneCharAtPos(i, '_');
|
||||
// s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));
|
||||
}
|
||||
/*
|
||||
if (g_PathTrailReplaceMode > 1 && i != s.Len())
|
||||
{
|
||||
s.DeleteFrom(i);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream.
|
||||
But colon in postfix ":$DATA" is allowed.
|
||||
WIN32 functions don't allow empty alt stream name "name:" */
|
||||
|
||||
void Correct_AltStream_Name(UString &s)
|
||||
{
|
||||
unsigned len = s.Len();
|
||||
const unsigned kPostfixSize = 6;
|
||||
if (s.Len() >= kPostfixSize
|
||||
&& StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA"))
|
||||
len -= kPostfixSize;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c == ':' || c == '\\' || c == '/'
|
||||
|| c == 0x202E // RLO
|
||||
)
|
||||
s.ReplaceOneCharAtPos(i, '_');
|
||||
}
|
||||
if (s.IsEmpty())
|
||||
s = '_';
|
||||
}
|
||||
|
||||
static const unsigned g_ReservedWithNum_Index = 4;
|
||||
|
||||
static const char * const g_ReservedNames[] =
|
||||
{
|
||||
"CON", "PRN", "AUX", "NUL",
|
||||
"COM", "LPT"
|
||||
};
|
||||
|
||||
static bool IsSupportedName(const UString &name)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)
|
||||
{
|
||||
const char *reservedName = g_ReservedNames[i];
|
||||
unsigned len = MyStringLen(reservedName);
|
||||
if (name.Len() < len)
|
||||
continue;
|
||||
if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))
|
||||
continue;
|
||||
if (i >= g_ReservedWithNum_Index)
|
||||
{
|
||||
wchar_t c = name[len];
|
||||
if (c < L'0' || c > L'9')
|
||||
continue;
|
||||
len++;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = name[len++];
|
||||
if (c == 0 || c == '.')
|
||||
return false;
|
||||
if (c != ' ')
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CorrectUnsupportedName(UString &name)
|
||||
{
|
||||
if (!IsSupportedName(name))
|
||||
name.InsertAtFront(L'_');
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void Correct_PathPart(UString &s)
|
||||
{
|
||||
// "." and ".."
|
||||
if (s.IsEmpty())
|
||||
return;
|
||||
|
||||
if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))
|
||||
s.Empty();
|
||||
#ifdef _WIN32
|
||||
else
|
||||
ReplaceIncorrectChars(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
// static const char * const k_EmptyReplaceName = "[]";
|
||||
static const char k_EmptyReplaceName = '_';
|
||||
|
||||
UString Get_Correct_FsFile_Name(const UString &name)
|
||||
{
|
||||
UString res = name;
|
||||
Correct_PathPart(res);
|
||||
|
||||
#ifdef _WIN32
|
||||
CorrectUnsupportedName(res);
|
||||
#endif
|
||||
|
||||
if (res.IsEmpty())
|
||||
res = k_EmptyReplaceName;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
|
||||
{
|
||||
unsigned i = 0;
|
||||
|
||||
if (absIsAllowed)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
bool isDrive = false;
|
||||
#endif
|
||||
|
||||
if (parts[0].IsEmpty())
|
||||
{
|
||||
i = 1;
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (parts.Size() > 1 && parts[1].IsEmpty())
|
||||
{
|
||||
i = 2;
|
||||
if (parts.Size() > 2 && parts[2] == L"?")
|
||||
{
|
||||
i = 3;
|
||||
if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
|
||||
{
|
||||
isDrive = true;
|
||||
i = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))
|
||||
{
|
||||
isDrive = true;
|
||||
i = 1;
|
||||
}
|
||||
|
||||
if (isDrive)
|
||||
{
|
||||
// we convert "c:name" to "c:\name", if absIsAllowed path.
|
||||
UString &ds = parts[i - 1];
|
||||
if (ds.Len() > 2)
|
||||
{
|
||||
parts.Insert(i, ds.Ptr(2));
|
||||
ds.DeleteFrom(2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
keepAndReplaceEmptyPrefixes = false;
|
||||
|
||||
for (; i < parts.Size();)
|
||||
{
|
||||
UString &s = parts[i];
|
||||
|
||||
Correct_PathPart(s);
|
||||
|
||||
if (s.IsEmpty())
|
||||
{
|
||||
if (!keepAndReplaceEmptyPrefixes)
|
||||
if (isDir || i != parts.Size() - 1)
|
||||
{
|
||||
parts.Delete(i);
|
||||
continue;
|
||||
}
|
||||
s = k_EmptyReplaceName;
|
||||
}
|
||||
else
|
||||
{
|
||||
keepAndReplaceEmptyPrefixes = false;
|
||||
#ifdef _WIN32
|
||||
CorrectUnsupportedName(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!isDir)
|
||||
{
|
||||
if (parts.IsEmpty())
|
||||
parts.Add((UString)k_EmptyReplaceName);
|
||||
else
|
||||
{
|
||||
UString &s = parts.Back();
|
||||
if (s.IsEmpty())
|
||||
s = k_EmptyReplaceName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UString MakePathFromParts(const UStringVector &parts)
|
||||
{
|
||||
UString s;
|
||||
FOR_VECTOR (i, parts)
|
||||
{
|
||||
if (i != 0)
|
||||
s.Add_PathSepar();
|
||||
s += parts[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// ExtractingFilePath.h
|
||||
|
||||
#ifndef __EXTRACTING_FILE_PATH_H
|
||||
#define __EXTRACTING_FILE_PATH_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
void Correct_AltStream_Name(UString &s);
|
||||
#endif
|
||||
|
||||
// replaces unsuported characters, and replaces "." , ".." and "" to "[]"
|
||||
UString Get_Correct_FsFile_Name(const UString &name);
|
||||
|
||||
/*
|
||||
Correct_FsPath() corrects path parts to prepare it for File System operations.
|
||||
It also corrects empty path parts like "\\\\":
|
||||
- frontal empty path parts : it removes them or changes them to "_"
|
||||
- another empty path parts : it removes them
|
||||
if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker
|
||||
else
|
||||
{
|
||||
if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts
|
||||
if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_"
|
||||
}
|
||||
*/
|
||||
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir);
|
||||
|
||||
UString MakePathFromParts(const UStringVector &parts);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,347 @@
|
||||
// HashCalc.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "EnumDirItems.h"
|
||||
#include "HashCalc.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
class CHashMidBuf
|
||||
{
|
||||
void *_data;
|
||||
public:
|
||||
CHashMidBuf(): _data(0) {}
|
||||
operator void *() { return _data; }
|
||||
bool Alloc(size_t size)
|
||||
{
|
||||
if (_data != 0)
|
||||
return false;
|
||||
_data = ::MidAlloc(size);
|
||||
return _data != 0;
|
||||
}
|
||||
~CHashMidBuf() { ::MidFree(_data); }
|
||||
};
|
||||
|
||||
static const char * const k_DefaultHashMethod = "CRC32";
|
||||
|
||||
HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
|
||||
{
|
||||
UStringVector names = hashMethods;
|
||||
if (names.IsEmpty())
|
||||
names.Add(UString(k_DefaultHashMethod));
|
||||
|
||||
CRecordVector<CMethodId> ids;
|
||||
CObjectVector<COneMethodInfo> methods;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < names.Size(); i++)
|
||||
{
|
||||
COneMethodInfo m;
|
||||
RINOK(m.ParseMethodFromString(names[i]));
|
||||
|
||||
if (m.MethodName.IsEmpty())
|
||||
m.MethodName = k_DefaultHashMethod;
|
||||
|
||||
if (m.MethodName == "*")
|
||||
{
|
||||
CRecordVector<CMethodId> tempMethods;
|
||||
GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
|
||||
methods.Clear();
|
||||
ids.Clear();
|
||||
FOR_VECTOR (t, tempMethods)
|
||||
{
|
||||
unsigned index = ids.AddToUniqueSorted(tempMethods[t]);
|
||||
if (ids.Size() != methods.Size())
|
||||
methods.Insert(index, m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// m.MethodName.RemoveChar(L'-');
|
||||
CMethodId id;
|
||||
if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))
|
||||
return E_NOTIMPL;
|
||||
unsigned index = ids.AddToUniqueSorted(id);
|
||||
if (ids.Size() != methods.Size())
|
||||
methods.Insert(index, m);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ids.Size(); i++)
|
||||
{
|
||||
CMyComPtr<IHasher> hasher;
|
||||
AString name;
|
||||
RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher));
|
||||
if (!hasher)
|
||||
throw "Can't create hasher";
|
||||
const COneMethodInfo &m = methods[i];
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderProperties> scp;
|
||||
hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
|
||||
if (scp)
|
||||
RINOK(m.SetCoderProps(scp, NULL));
|
||||
}
|
||||
UInt32 digestSize = hasher->GetDigestSize();
|
||||
if (digestSize > k_HashCalc_DigestSize_Max)
|
||||
return E_NOTIMPL;
|
||||
CHasherState &h = Hashers.AddNew();
|
||||
h.Hasher = hasher;
|
||||
h.Name = name;
|
||||
h.DigestSize = digestSize;
|
||||
for (unsigned k = 0; k < k_HashCalc_NumGroups; k++)
|
||||
memset(h.Digests[k], 0, digestSize);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CHashBundle::InitForNewFile()
|
||||
{
|
||||
CurSize = 0;
|
||||
FOR_VECTOR (i, Hashers)
|
||||
{
|
||||
CHasherState &h = Hashers[i];
|
||||
h.Hasher->Init();
|
||||
memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize);
|
||||
}
|
||||
}
|
||||
|
||||
void CHashBundle::Update(const void *data, UInt32 size)
|
||||
{
|
||||
CurSize += size;
|
||||
FOR_VECTOR (i, Hashers)
|
||||
Hashers[i].Hasher->Update(data, size);
|
||||
}
|
||||
|
||||
void CHashBundle::SetSize(UInt64 size)
|
||||
{
|
||||
CurSize = size;
|
||||
}
|
||||
|
||||
static void AddDigests(Byte *dest, const Byte *src, UInt32 size)
|
||||
{
|
||||
unsigned next = 0;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
{
|
||||
next += (unsigned)dest[i] + (unsigned)src[i];
|
||||
dest[i] = (Byte)next;
|
||||
next >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
|
||||
{
|
||||
if (isDir)
|
||||
NumDirs++;
|
||||
else if (isAltStream)
|
||||
{
|
||||
NumAltStreams++;
|
||||
AltStreamsSize += CurSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumFiles++;
|
||||
FilesSize += CurSize;
|
||||
}
|
||||
|
||||
Byte pre[16];
|
||||
memset(pre, 0, sizeof(pre));
|
||||
if (isDir)
|
||||
pre[0] = 1;
|
||||
|
||||
FOR_VECTOR (i, Hashers)
|
||||
{
|
||||
CHasherState &h = Hashers[i];
|
||||
if (!isDir)
|
||||
{
|
||||
h.Hasher->Final(h.Digests[0]);
|
||||
if (!isAltStream)
|
||||
AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize);
|
||||
}
|
||||
|
||||
h.Hasher->Init();
|
||||
h.Hasher->Update(pre, sizeof(pre));
|
||||
h.Hasher->Update(h.Digests[0], h.DigestSize);
|
||||
|
||||
for (unsigned k = 0; k < path.Len(); k++)
|
||||
{
|
||||
wchar_t c = path[k];
|
||||
Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) };
|
||||
h.Hasher->Update(temp, 2);
|
||||
}
|
||||
|
||||
Byte tempDigest[k_HashCalc_DigestSize_Max];
|
||||
h.Hasher->Final(tempDigest);
|
||||
if (!isAltStream)
|
||||
AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize);
|
||||
AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT HashCalc(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const NWildcard::CCensor &censor,
|
||||
const CHashOptions &options,
|
||||
AString &errorInfo,
|
||||
IHashCallbackUI *callback)
|
||||
{
|
||||
CDirItems dirItems;
|
||||
dirItems.Callback = callback;
|
||||
|
||||
if (options.StdInMode)
|
||||
{
|
||||
CDirItem di;
|
||||
di.Size = (UInt64)(Int64)-1;
|
||||
di.Attrib = 0;
|
||||
di.MTime.dwLowDateTime = 0;
|
||||
di.MTime.dwHighDateTime = 0;
|
||||
di.CTime = di.ATime = di.MTime;
|
||||
dirItems.Items.Add(di);
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(callback->StartScanning());
|
||||
dirItems.ScanAltStreams = options.AltStreamsMode;
|
||||
|
||||
HRESULT res = EnumerateItems(censor,
|
||||
options.PathMode,
|
||||
UString(),
|
||||
dirItems);
|
||||
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (res != E_ABORT)
|
||||
errorInfo = "Scanning error";
|
||||
return res;
|
||||
}
|
||||
RINOK(callback->FinishScanning(dirItems.Stat));
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
CHashBundle hb;
|
||||
RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));
|
||||
// hb.Init();
|
||||
|
||||
hb.NumErrors = dirItems.Stat.NumErrors;
|
||||
|
||||
if (options.StdInMode)
|
||||
{
|
||||
RINOK(callback->SetNumFiles(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes()));
|
||||
}
|
||||
|
||||
const UInt32 kBufSize = 1 << 15;
|
||||
CHashMidBuf buf;
|
||||
if (!buf.Alloc(kBufSize))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
UInt64 completeValue = 0;
|
||||
|
||||
RINOK(callback->BeforeFirstFile(hb));
|
||||
|
||||
for (i = 0; i < dirItems.Items.Size(); i++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
UString path;
|
||||
bool isDir = false;
|
||||
bool isAltStream = false;
|
||||
if (options.StdInMode)
|
||||
{
|
||||
inStream = new CStdInFileStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
inStream = inStreamSpec;
|
||||
const CDirItem &dirItem = dirItems.Items[i];
|
||||
isDir = dirItem.IsDir();
|
||||
isAltStream = dirItem.IsAltStream;
|
||||
path = dirItems.GetLogPath(i);
|
||||
if (!isDir)
|
||||
{
|
||||
FString phyPath = dirItems.GetPhyPath(i);
|
||||
if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite))
|
||||
{
|
||||
HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());
|
||||
hb.NumErrors++;
|
||||
if (res != S_FALSE)
|
||||
return res;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
RINOK(callback->GetStream(path, isDir));
|
||||
UInt64 fileSize = 0;
|
||||
|
||||
hb.InitForNewFile();
|
||||
if (!isDir)
|
||||
{
|
||||
for (UInt32 step = 0;; step++)
|
||||
{
|
||||
if ((step & 0xFF) == 0)
|
||||
RINOK(callback->SetCompleted(&completeValue));
|
||||
UInt32 size;
|
||||
RINOK(inStream->Read(buf, kBufSize, &size));
|
||||
if (size == 0)
|
||||
break;
|
||||
hb.Update(buf, size);
|
||||
fileSize += size;
|
||||
completeValue += size;
|
||||
}
|
||||
}
|
||||
hb.Final(isDir, isAltStream, path);
|
||||
RINOK(callback->SetOperationResult(fileSize, hb, !isDir));
|
||||
RINOK(callback->SetCompleted(&completeValue));
|
||||
}
|
||||
return callback->AfterLastFile(hb);
|
||||
}
|
||||
|
||||
|
||||
static inline char GetHex(unsigned v)
|
||||
{
|
||||
return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
|
||||
}
|
||||
|
||||
void AddHashHexToString(char *dest, const Byte *data, UInt32 size)
|
||||
{
|
||||
dest[size * 2] = 0;
|
||||
|
||||
if (!data)
|
||||
{
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
{
|
||||
dest[0] = ' ';
|
||||
dest[1] = ' ';
|
||||
dest += 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int step = 2;
|
||||
if (size <= 8)
|
||||
{
|
||||
step = -2;
|
||||
dest += size * 2 - 2;
|
||||
}
|
||||
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
{
|
||||
unsigned b = data[i];
|
||||
dest[0] = GetHex((b >> 4) & 0xF);
|
||||
dest[1] = GetHex(b & 0xF);
|
||||
dest += step;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// HashCalc.h
|
||||
|
||||
#ifndef __HASH_CALC_H
|
||||
#define __HASH_CALC_H
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
#include "DirItem.h"
|
||||
|
||||
const unsigned k_HashCalc_DigestSize_Max = 64;
|
||||
|
||||
const unsigned k_HashCalc_NumGroups = 4;
|
||||
|
||||
enum
|
||||
{
|
||||
k_HashCalc_Index_Current,
|
||||
k_HashCalc_Index_DataSum,
|
||||
k_HashCalc_Index_NamesSum,
|
||||
k_HashCalc_Index_StreamsSum
|
||||
};
|
||||
|
||||
struct CHasherState
|
||||
{
|
||||
CMyComPtr<IHasher> Hasher;
|
||||
AString Name;
|
||||
UInt32 DigestSize;
|
||||
Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];
|
||||
};
|
||||
|
||||
struct IHashCalc
|
||||
{
|
||||
virtual void InitForNewFile() = 0;
|
||||
virtual void Update(const void *data, UInt32 size) = 0;
|
||||
virtual void SetSize(UInt64 size) = 0;
|
||||
virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;
|
||||
};
|
||||
|
||||
struct CHashBundle: public IHashCalc
|
||||
{
|
||||
CObjectVector<CHasherState> Hashers;
|
||||
|
||||
UInt64 NumDirs;
|
||||
UInt64 NumFiles;
|
||||
UInt64 NumAltStreams;
|
||||
UInt64 FilesSize;
|
||||
UInt64 AltStreamsSize;
|
||||
UInt64 NumErrors;
|
||||
|
||||
UInt64 CurSize;
|
||||
|
||||
UString MainName;
|
||||
UString FirstFileName;
|
||||
|
||||
HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
|
||||
|
||||
// void Init() {}
|
||||
CHashBundle()
|
||||
{
|
||||
NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
|
||||
}
|
||||
|
||||
void InitForNewFile();
|
||||
void Update(const void *data, UInt32 size);
|
||||
void SetSize(UInt64 size);
|
||||
void Final(bool isDir, bool isAltStream, const UString &path);
|
||||
};
|
||||
|
||||
#define INTERFACE_IHashCallbackUI(x) \
|
||||
INTERFACE_IDirItemsCallback(x) \
|
||||
virtual HRESULT StartScanning() x; \
|
||||
virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \
|
||||
virtual HRESULT SetNumFiles(UInt64 numFiles) x; \
|
||||
virtual HRESULT SetTotal(UInt64 size) x; \
|
||||
virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
|
||||
virtual HRESULT CheckBreak() x; \
|
||||
virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \
|
||||
virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \
|
||||
virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
|
||||
virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \
|
||||
virtual HRESULT AfterLastFile(CHashBundle &hb) x; \
|
||||
|
||||
struct IHashCallbackUI: public IDirItemsCallback
|
||||
{
|
||||
INTERFACE_IHashCallbackUI(=0)
|
||||
};
|
||||
|
||||
struct CHashOptions
|
||||
{
|
||||
UStringVector Methods;
|
||||
bool OpenShareForWrite;
|
||||
bool StdInMode;
|
||||
bool AltStreamsMode;
|
||||
NWildcard::ECensorPathMode PathMode;
|
||||
|
||||
CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {};
|
||||
};
|
||||
|
||||
HRESULT HashCalc(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const NWildcard::CCensor &censor,
|
||||
const CHashOptions &options,
|
||||
AString &errorInfo,
|
||||
IHashCallbackUI *callback);
|
||||
|
||||
void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
// IFileExtractCallback.h
|
||||
|
||||
#ifndef __I_FILE_EXTRACT_CALLBACK_H
|
||||
#define __I_FILE_EXTRACT_CALLBACK_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../IDecl.h"
|
||||
|
||||
#include "LoadCodecs.h"
|
||||
#include "OpenArchive.h"
|
||||
|
||||
namespace NOverwriteAnswer
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kYes,
|
||||
kYesToAll,
|
||||
kNo,
|
||||
kNoToAll,
|
||||
kAutoRename,
|
||||
kCancel
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* ---------- IFolderArchiveExtractCallback ----------
|
||||
is implemented by
|
||||
Console/ExtractCallbackConsole.h CExtractCallbackConsole
|
||||
FileManager/ExtractCallback.h CExtractCallbackImp
|
||||
FAR/ExtractEngine.cpp CExtractCallBackImp: (QueryInterface is not supported)
|
||||
|
||||
IID_IFolderArchiveExtractCallback is requested by:
|
||||
- Agent/ArchiveFolder.cpp
|
||||
CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback)
|
||||
is sent to IArchiveFolder::Extract()
|
||||
|
||||
- FileManager/PanelCopy.cpp
|
||||
CPanel::CopyTo(), if (options->testMode)
|
||||
is sent to IArchiveFolder::Extract()
|
||||
|
||||
IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp
|
||||
*/
|
||||
|
||||
#define INTERFACE_IFolderArchiveExtractCallback(x) \
|
||||
STDMETHOD(AskOverwrite)( \
|
||||
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \
|
||||
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \
|
||||
Int32 *answer) x; \
|
||||
STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) x; \
|
||||
STDMETHOD(MessageError)(const wchar_t *message) x; \
|
||||
STDMETHOD(SetOperationResult)(Int32 opRes, Int32 encrypted) x; \
|
||||
|
||||
DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)
|
||||
{
|
||||
INTERFACE_IFolderArchiveExtractCallback(PURE)
|
||||
};
|
||||
|
||||
#define INTERFACE_IFolderArchiveExtractCallback2(x) \
|
||||
STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 encrypted, const wchar_t *name) x; \
|
||||
|
||||
DECL_INTERFACE_SUB(IFolderArchiveExtractCallback2, IUnknown, 0x01, 0x08)
|
||||
{
|
||||
INTERFACE_IFolderArchiveExtractCallback2(PURE)
|
||||
};
|
||||
|
||||
/* ---------- IExtractCallbackUI ----------
|
||||
is implemented by
|
||||
Console/ExtractCallbackConsole.h CExtractCallbackConsole
|
||||
FileManager/ExtractCallback.h CExtractCallbackImp
|
||||
*/
|
||||
|
||||
#ifdef _NO_CRYPTO
|
||||
#define INTERFACE_IExtractCallbackUI_Crypto(x)
|
||||
#else
|
||||
#define INTERFACE_IExtractCallbackUI_Crypto(x) \
|
||||
virtual HRESULT SetPassword(const UString &password) x;
|
||||
#endif
|
||||
|
||||
#define INTERFACE_IExtractCallbackUI(x) \
|
||||
virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) x; \
|
||||
virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \
|
||||
virtual HRESULT ThereAreNoFiles() x; \
|
||||
virtual HRESULT ExtractResult(HRESULT result) x; \
|
||||
INTERFACE_IExtractCallbackUI_Crypto(x)
|
||||
|
||||
struct IExtractCallbackUI: IFolderArchiveExtractCallback
|
||||
{
|
||||
INTERFACE_IExtractCallbackUI(PURE)
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define INTERFACE_IGetProp(x) \
|
||||
STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \
|
||||
|
||||
DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)
|
||||
{
|
||||
INTERFACE_IGetProp(PURE)
|
||||
};
|
||||
|
||||
#define INTERFACE_IFolderExtractToStreamCallback(x) \
|
||||
STDMETHOD(UseExtractToStream)(Int32 *res) x; \
|
||||
STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \
|
||||
STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \
|
||||
STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \
|
||||
|
||||
DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
|
||||
{
|
||||
INTERFACE_IFolderExtractToStreamCallback(PURE)
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,424 @@
|
||||
// LoadCodecs.h
|
||||
|
||||
#ifndef __LOAD_CODECS_H
|
||||
#define __LOAD_CODECS_H
|
||||
|
||||
/*
|
||||
Client application uses LoadCodecs.* to load plugins to
|
||||
CCodecs object, that contains 3 lists of plugins:
|
||||
1) Formats - internal and external archive handlers
|
||||
2) Codecs - external codecs
|
||||
3) Hashers - external hashers
|
||||
|
||||
EXTERNAL_CODECS
|
||||
---------------
|
||||
|
||||
if EXTERNAL_CODECS is defined, then the code tries to load external
|
||||
plugins from DLL files (shared libraries).
|
||||
|
||||
There are two types of executables in 7-Zip:
|
||||
|
||||
1) Executable that uses external plugins must be compiled
|
||||
with EXTERNAL_CODECS defined:
|
||||
- 7z.exe, 7zG.exe, 7zFM.exe
|
||||
|
||||
Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h
|
||||
that code is used in plugin module (7z.dll).
|
||||
|
||||
2) Standalone modules are compiled without EXTERNAL_CODECS:
|
||||
- SFX modules: 7z.sfx, 7zCon.sfx
|
||||
- standalone versions of console 7-Zip: 7za.exe, 7zr.exe
|
||||
|
||||
if EXTERNAL_CODECS is defined, CCodecs class implements interfaces:
|
||||
- ICompressCodecsInfo : for Codecs
|
||||
- IHashers : for Hashers
|
||||
|
||||
The client application can send CCodecs object to each plugin module.
|
||||
And plugin module can use ICompressCodecsInfo or IHashers interface to access
|
||||
another plugins.
|
||||
|
||||
There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin
|
||||
1) for old versions:
|
||||
a) request ISetCompressCodecsInfo from created archive handler.
|
||||
b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo)
|
||||
2) for new versions:
|
||||
a) request "SetCodecs" function from DLL file
|
||||
b) call SetCodecs(compressCodecsInfo) function from DLL file
|
||||
*/
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#include "../../../Windows/DLL.h"
|
||||
#endif
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
struct CDllCodecInfo
|
||||
{
|
||||
unsigned LibIndex;
|
||||
UInt32 CodecIndex;
|
||||
bool EncoderIsAssigned;
|
||||
bool DecoderIsAssigned;
|
||||
CLSID Encoder;
|
||||
CLSID Decoder;
|
||||
};
|
||||
|
||||
struct CDllHasherInfo
|
||||
{
|
||||
unsigned LibIndex;
|
||||
UInt32 HasherIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct CArcExtInfo
|
||||
{
|
||||
UString Ext;
|
||||
UString AddExt;
|
||||
|
||||
CArcExtInfo() {}
|
||||
CArcExtInfo(const UString &ext): Ext(ext) {}
|
||||
CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
|
||||
};
|
||||
|
||||
|
||||
struct CArcInfoEx
|
||||
{
|
||||
UInt32 Flags;
|
||||
|
||||
Func_CreateInArchive CreateInArchive;
|
||||
Func_IsArc IsArcFunc;
|
||||
|
||||
UString Name;
|
||||
CObjectVector<CArcExtInfo> Exts;
|
||||
|
||||
#ifndef _SFX
|
||||
Func_CreateOutArchive CreateOutArchive;
|
||||
bool UpdateEnabled;
|
||||
bool NewInterface;
|
||||
// UInt32 Version;
|
||||
UInt32 SignatureOffset;
|
||||
CObjectVector<CByteBuffer> Signatures;
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
UStringVector AssociateExts;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
int LibIndex;
|
||||
UInt32 FormatIndex;
|
||||
CLSID ClassID;
|
||||
#endif
|
||||
|
||||
bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
|
||||
bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
|
||||
|
||||
bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
|
||||
bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
|
||||
bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }
|
||||
bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }
|
||||
|
||||
bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }
|
||||
bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }
|
||||
bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }
|
||||
bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
|
||||
bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
|
||||
|
||||
UString GetMainExt() const
|
||||
{
|
||||
if (Exts.IsEmpty())
|
||||
return UString();
|
||||
return Exts[0].Ext;
|
||||
}
|
||||
int FindExtension(const UString &ext) const;
|
||||
|
||||
/*
|
||||
UString GetAllExtensions() const
|
||||
{
|
||||
UString s;
|
||||
for (int i = 0; i < Exts.Size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
s += ' ';
|
||||
s += Exts[i].Ext;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
void AddExts(const UString &ext, const UString &addExt);
|
||||
|
||||
bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
|
||||
// bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
|
||||
|
||||
CArcInfoEx():
|
||||
Flags(0),
|
||||
CreateInArchive(NULL),
|
||||
IsArcFunc(NULL)
|
||||
#ifndef _SFX
|
||||
, CreateOutArchive(NULL)
|
||||
, UpdateEnabled(false)
|
||||
, NewInterface(false)
|
||||
// , Version(0)
|
||||
, SignatureOffset(0)
|
||||
#endif
|
||||
#ifdef EXTERNAL_CODECS
|
||||
, LibIndex(-1)
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
|
||||
struct CCodecIcons
|
||||
{
|
||||
struct CIconPair
|
||||
{
|
||||
UString Ext;
|
||||
int IconIndex;
|
||||
};
|
||||
CObjectVector<CIconPair> IconPairs;
|
||||
|
||||
void LoadIcons(HMODULE m);
|
||||
bool FindIconIndex(const UString &ext, int &iconIndex) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
struct CCodecLib
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
: public CCodecIcons
|
||||
#endif
|
||||
{
|
||||
NWindows::NDLL::CLibrary Lib;
|
||||
FString Path;
|
||||
|
||||
Func_CreateObject CreateObject;
|
||||
Func_GetMethodProperty GetMethodProperty;
|
||||
Func_CreateDecoder CreateDecoder;
|
||||
Func_CreateEncoder CreateEncoder;
|
||||
Func_SetCodecs SetCodecs;
|
||||
|
||||
CMyComPtr<IHashers> ComHashers;
|
||||
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }
|
||||
#endif
|
||||
|
||||
CCodecLib():
|
||||
CreateObject(NULL),
|
||||
GetMethodProperty(NULL),
|
||||
CreateDecoder(NULL),
|
||||
CreateEncoder(NULL),
|
||||
SetCodecs(NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class CCodecs:
|
||||
#ifdef EXTERNAL_CODECS
|
||||
public ICompressCodecsInfo,
|
||||
public IHashers,
|
||||
#else
|
||||
public IUnknown,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLASS_NO_COPY(CCodecs);
|
||||
public:
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
CObjectVector<CCodecLib> Libs;
|
||||
FString MainDll_ErrorPath;
|
||||
|
||||
void CloseLibs();
|
||||
|
||||
class CReleaser
|
||||
{
|
||||
CLASS_NO_COPY(CReleaser);
|
||||
|
||||
/* CCodecsReleaser object releases CCodecs links.
|
||||
1) CCodecs is COM object that is deleted when all links to that object will be released/
|
||||
2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.
|
||||
To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */
|
||||
|
||||
CCodecs *_codecs;
|
||||
|
||||
public:
|
||||
CReleaser(): _codecs(NULL) {}
|
||||
void Set(CCodecs *codecs) { _codecs = codecs; }
|
||||
~CReleaser() { if (_codecs) _codecs->CloseLibs(); }
|
||||
};
|
||||
|
||||
bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo
|
||||
|
||||
HRESULT LoadCodecs();
|
||||
HRESULT LoadFormats();
|
||||
HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);
|
||||
HRESULT LoadDllsFromFolder(const FString &folderPrefix);
|
||||
|
||||
HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const
|
||||
{
|
||||
return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
CCodecIcons InternalIcons;
|
||||
#endif
|
||||
|
||||
CObjectVector<CArcInfoEx> Formats;
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
CRecordVector<CDllCodecInfo> Codecs;
|
||||
CRecordVector<CDllHasherInfo> Hashers;
|
||||
#endif
|
||||
|
||||
bool CaseSensitiveChange;
|
||||
bool CaseSensitive;
|
||||
|
||||
CCodecs():
|
||||
#ifdef EXTERNAL_CODECS
|
||||
NeedSetLibCodecs(true),
|
||||
#endif
|
||||
CaseSensitiveChange(false),
|
||||
CaseSensitive(false)
|
||||
{}
|
||||
|
||||
~CCodecs()
|
||||
{
|
||||
// OutputDebugStringA("~CCodecs");
|
||||
}
|
||||
|
||||
const wchar_t *GetFormatNamePtr(int formatIndex) const
|
||||
{
|
||||
return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;
|
||||
}
|
||||
|
||||
HRESULT Load();
|
||||
|
||||
#ifndef _SFX
|
||||
int FindFormatForArchiveName(const UString &arcPath) const;
|
||||
int FindFormatForExtension(const UString &ext) const;
|
||||
int FindFormatForArchiveType(const UString &arcType) const;
|
||||
bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;
|
||||
#endif
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
|
||||
|
||||
STDMETHOD(GetNumMethods)(UInt32 *numMethods);
|
||||
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder);
|
||||
STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder);
|
||||
|
||||
STDMETHOD_(UInt32, GetNumHashers)();
|
||||
STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
|
||||
|
||||
#else
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
#endif // EXTERNAL_CODECS
|
||||
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
int GetCodec_LibIndex(UInt32 index) const;
|
||||
bool GetCodec_DecoderIsAssigned(UInt32 index) const;
|
||||
bool GetCodec_EncoderIsAssigned(UInt32 index) const;
|
||||
UInt32 GetCodec_NumStreams(UInt32 index);
|
||||
HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
|
||||
AString GetCodec_Name(UInt32 index);
|
||||
|
||||
int GetHasherLibIndex(UInt32 index);
|
||||
UInt64 GetHasherId(UInt32 index);
|
||||
AString GetHasherName(UInt32 index);
|
||||
UInt32 GetHasherDigestSize(UInt32 index);
|
||||
|
||||
#endif
|
||||
|
||||
HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const
|
||||
{
|
||||
const CArcInfoEx &ai = Formats[formatIndex];
|
||||
#ifdef EXTERNAL_CODECS
|
||||
if (ai.LibIndex < 0)
|
||||
#endif
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
archive = ai.CreateInArchive();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
#ifdef EXTERNAL_CODECS
|
||||
return CreateArchiveHandler(ai, false, (void **)&archive);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
|
||||
{
|
||||
const CArcInfoEx &ai = Formats[formatIndex];
|
||||
#ifdef EXTERNAL_CODECS
|
||||
if (ai.LibIndex < 0)
|
||||
#endif
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
archive = ai.CreateOutArchive();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
return CreateArchiveHandler(ai, true, (void **)&archive);
|
||||
#endif
|
||||
}
|
||||
|
||||
int FindOutFormatFromName(const UString &name) const
|
||||
{
|
||||
FOR_VECTOR (i, Formats)
|
||||
{
|
||||
const CArcInfoEx &arc = Formats[i];
|
||||
if (!arc.UpdateEnabled)
|
||||
continue;
|
||||
if (arc.Name.IsEqualTo_NoCase(name))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // _SFX
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#define CREATE_CODECS_OBJECT \
|
||||
CCodecs *codecs = new CCodecs; \
|
||||
CExternalCodecs __externalCodecs; \
|
||||
__externalCodecs.GetCodecs = codecs; \
|
||||
__externalCodecs.GetHashers = codecs; \
|
||||
CCodecs::CReleaser codecsReleaser; \
|
||||
codecsReleaser.Set(codecs);
|
||||
#else
|
||||
#define CREATE_CODECS_OBJECT \
|
||||
CCodecs *codecs = new CCodecs; \
|
||||
CMyComPtr<IUnknown> __codecsRef = codecs;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,436 @@
|
||||
// OpenArchive.h
|
||||
|
||||
#ifndef __OPEN_ARCHIVE_H
|
||||
#define __OPEN_ARCHIVE_H
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
#include "LoadCodecs.h"
|
||||
#include "Property.h"
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
#define SUPPORT_ALT_STREAMS
|
||||
|
||||
#endif
|
||||
|
||||
HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
|
||||
HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();
|
||||
HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
|
||||
HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
|
||||
HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
int FindAltStreamColon_in_Path(const wchar_t *path);
|
||||
#endif
|
||||
|
||||
/*
|
||||
struct COptionalOpenProperties
|
||||
{
|
||||
UString FormatName;
|
||||
CObjectVector<CProperty> Props;
|
||||
};
|
||||
*/
|
||||
|
||||
#ifdef _SFX
|
||||
#define OPEN_PROPS_DECL
|
||||
#else
|
||||
#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
|
||||
// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
|
||||
#endif
|
||||
|
||||
struct COpenSpecFlags
|
||||
{
|
||||
// bool CanReturnFull;
|
||||
bool CanReturnFrontal;
|
||||
bool CanReturnTail;
|
||||
bool CanReturnMid;
|
||||
|
||||
bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
|
||||
|
||||
COpenSpecFlags():
|
||||
// CanReturnFull(true),
|
||||
CanReturnFrontal(false),
|
||||
CanReturnTail(false),
|
||||
CanReturnMid(false)
|
||||
{}
|
||||
};
|
||||
|
||||
struct COpenType
|
||||
{
|
||||
int FormatIndex;
|
||||
|
||||
COpenSpecFlags SpecForcedType;
|
||||
COpenSpecFlags SpecMainType;
|
||||
COpenSpecFlags SpecWrongExt;
|
||||
COpenSpecFlags SpecUnknownExt;
|
||||
|
||||
bool Recursive;
|
||||
|
||||
bool CanReturnArc;
|
||||
bool CanReturnParser;
|
||||
bool EachPos;
|
||||
|
||||
// bool SkipSfxStub;
|
||||
// bool ExeAsUnknown;
|
||||
|
||||
bool ZerosTailIsAllowed;
|
||||
|
||||
bool MaxStartOffset_Defined;
|
||||
UInt64 MaxStartOffset;
|
||||
|
||||
const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
|
||||
{
|
||||
return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
|
||||
}
|
||||
|
||||
COpenType():
|
||||
FormatIndex(-1),
|
||||
Recursive(true),
|
||||
EachPos(false),
|
||||
CanReturnArc(true),
|
||||
CanReturnParser(false),
|
||||
// SkipSfxStub(true),
|
||||
// ExeAsUnknown(true),
|
||||
ZerosTailIsAllowed(false),
|
||||
MaxStartOffset_Defined(false),
|
||||
MaxStartOffset(0)
|
||||
{
|
||||
SpecForcedType.CanReturnFrontal = true;
|
||||
SpecForcedType.CanReturnTail = true;
|
||||
SpecForcedType.CanReturnMid = true;
|
||||
|
||||
SpecMainType.CanReturnFrontal = true;
|
||||
|
||||
SpecUnknownExt.CanReturnTail = true; // for sfx
|
||||
SpecUnknownExt.CanReturnMid = true;
|
||||
SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
|
||||
|
||||
// ZerosTailIsAllowed = true;
|
||||
}
|
||||
};
|
||||
|
||||
struct COpenOptions
|
||||
{
|
||||
CCodecs *codecs;
|
||||
COpenType openType;
|
||||
const CObjectVector<COpenType> *types;
|
||||
const CIntVector *excludedFormats;
|
||||
|
||||
IInStream *stream;
|
||||
ISequentialInStream *seqStream;
|
||||
IArchiveOpenCallback *callback;
|
||||
COpenCallbackImp *callbackSpec;
|
||||
OPEN_PROPS_DECL
|
||||
// bool openOnlySpecifiedByExtension,
|
||||
|
||||
bool stdInMode;
|
||||
UString filePath;
|
||||
|
||||
COpenOptions():
|
||||
codecs(NULL),
|
||||
types(NULL),
|
||||
excludedFormats(NULL),
|
||||
stream(NULL),
|
||||
seqStream(NULL),
|
||||
callback(NULL),
|
||||
callbackSpec(NULL),
|
||||
stdInMode(false)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
|
||||
|
||||
struct CArcErrorInfo
|
||||
{
|
||||
bool ThereIsTail;
|
||||
bool UnexpecedEnd;
|
||||
bool IgnoreTail; // all are zeros
|
||||
// bool NonZerosTail;
|
||||
bool ErrorFlags_Defined;
|
||||
UInt32 ErrorFlags;
|
||||
UInt32 WarningFlags;
|
||||
int ErrorFormatIndex; // - 1 means no Error.
|
||||
// if FormatIndex == ErrorFormatIndex, the archive is open with offset
|
||||
UInt64 TailSize;
|
||||
|
||||
/* if CArc is Open OK with some format:
|
||||
- ErrorFormatIndex shows error format index, if extension is incorrect
|
||||
- other variables show message and warnings of archive that is open */
|
||||
|
||||
UString ErrorMessage;
|
||||
UString WarningMessage;
|
||||
|
||||
// call IsArc_After_NonOpen only if Open returns S_FALSE
|
||||
bool IsArc_After_NonOpen() const
|
||||
{
|
||||
return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
|
||||
}
|
||||
|
||||
|
||||
CArcErrorInfo():
|
||||
ThereIsTail(false),
|
||||
UnexpecedEnd(false),
|
||||
IgnoreTail(false),
|
||||
// NonZerosTail(false),
|
||||
ErrorFlags_Defined(false),
|
||||
ErrorFlags(0),
|
||||
WarningFlags(0),
|
||||
ErrorFormatIndex(-1),
|
||||
TailSize(0)
|
||||
{}
|
||||
|
||||
void ClearErrors();
|
||||
|
||||
void ClearErrors_Full()
|
||||
{
|
||||
ErrorFormatIndex = -1;
|
||||
ClearErrors();
|
||||
}
|
||||
|
||||
bool IsThereErrorOrWarning() const
|
||||
{
|
||||
return ErrorFlags != 0
|
||||
|| WarningFlags != 0
|
||||
|| NeedTailWarning()
|
||||
|| UnexpecedEnd
|
||||
|| !ErrorMessage.IsEmpty()
|
||||
|| !WarningMessage.IsEmpty();
|
||||
}
|
||||
|
||||
bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
|
||||
bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
|
||||
|
||||
bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
|
||||
|
||||
UInt32 GetWarningFlags() const
|
||||
{
|
||||
UInt32 a = WarningFlags;
|
||||
if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
|
||||
a |= kpv_ErrorFlags_DataAfterEnd;
|
||||
return a;
|
||||
}
|
||||
|
||||
UInt32 GetErrorFlags() const
|
||||
{
|
||||
UInt32 a = ErrorFlags;
|
||||
if (UnexpecedEnd)
|
||||
a |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
struct CReadArcItem
|
||||
{
|
||||
UString Path; // Path from root (including alt stream name, if alt stream)
|
||||
UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
UString MainPath;
|
||||
/* MainPath = Path for non-AltStream,
|
||||
MainPath = Path of parent, if there is parent for AltStream. */
|
||||
UString AltStreamName;
|
||||
bool IsAltStream;
|
||||
bool WriteToAltStreamIfColon;
|
||||
#endif
|
||||
|
||||
bool IsDir;
|
||||
bool MainIsDir;
|
||||
UInt32 ParentIndex; // use it, if IsAltStream
|
||||
|
||||
#ifndef _SFX
|
||||
bool _use_baseParentFolder_mode;
|
||||
int _baseParentFolder;
|
||||
#endif
|
||||
|
||||
CReadArcItem()
|
||||
{
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
WriteToAltStreamIfColon = false;
|
||||
#endif
|
||||
|
||||
#ifndef _SFX
|
||||
_use_baseParentFolder_mode = false;
|
||||
_baseParentFolder = -1;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class CArc
|
||||
{
|
||||
HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
|
||||
HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
|
||||
HRESULT OpenStream2(const COpenOptions &options);
|
||||
|
||||
#ifndef _SFX
|
||||
// parts.Back() can contain alt stream name "nams:AltName"
|
||||
HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
CMyComPtr<IInArchive> Archive;
|
||||
CMyComPtr<IInStream> InStream;
|
||||
// we use InStream in 2 cases (ArcStreamOffset != 0):
|
||||
// 1) if we use additional cache stream
|
||||
// 2) we reopen sfx archive with CTailInStream
|
||||
|
||||
CMyComPtr<IArchiveGetRawProps> GetRawProps;
|
||||
CMyComPtr<IArchiveGetRootProps> GetRootProps;
|
||||
|
||||
CArcErrorInfo ErrorInfo; // for OK archives
|
||||
CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
|
||||
|
||||
UString Path;
|
||||
UString filePath;
|
||||
UString DefaultName;
|
||||
int FormatIndex; // - 1 means Parser.
|
||||
int SubfileIndex;
|
||||
FILETIME MTime;
|
||||
bool MTimeDefined;
|
||||
|
||||
Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
|
||||
UInt64 PhySize;
|
||||
// UInt64 OkPhySize;
|
||||
bool PhySizeDefined;
|
||||
// bool OkPhySize_Defined;
|
||||
UInt64 FileSize;
|
||||
UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
|
||||
// bool offsetDefined;
|
||||
|
||||
UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }
|
||||
|
||||
UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
|
||||
Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive
|
||||
|
||||
// AString ErrorFlagsText;
|
||||
|
||||
bool IsParseArc;
|
||||
|
||||
bool IsTree;
|
||||
bool IsReadOnly;
|
||||
|
||||
bool Ask_Deleted;
|
||||
bool Ask_AltStream;
|
||||
bool Ask_Aux;
|
||||
bool Ask_INode;
|
||||
|
||||
bool IgnoreSplit; // don't try split handler
|
||||
|
||||
// void Set_ErrorFlagsText();
|
||||
|
||||
CArc():
|
||||
MTimeDefined(false),
|
||||
IsTree(false),
|
||||
IsReadOnly(false),
|
||||
Ask_Deleted(false),
|
||||
Ask_AltStream(false),
|
||||
Ask_Aux(false),
|
||||
Ask_INode(false),
|
||||
IgnoreSplit(false)
|
||||
{}
|
||||
|
||||
HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
|
||||
|
||||
// ~CArc();
|
||||
|
||||
HRESULT Close()
|
||||
{
|
||||
InStream.Release();
|
||||
return Archive->Close();
|
||||
}
|
||||
|
||||
HRESULT GetItemPath(UInt32 index, UString &result) const;
|
||||
HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;
|
||||
|
||||
// GetItemPath2 adds [DELETED] dir prefix for deleted items.
|
||||
HRESULT GetItemPath2(UInt32 index, UString &result) const;
|
||||
|
||||
HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
|
||||
|
||||
HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
|
||||
HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
|
||||
HRESULT IsItemAnti(UInt32 index, bool &result) const
|
||||
{ return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
|
||||
|
||||
|
||||
HRESULT OpenStream(const COpenOptions &options);
|
||||
HRESULT OpenStreamOrFile(COpenOptions &options);
|
||||
|
||||
HRESULT ReOpen(const COpenOptions &options);
|
||||
|
||||
HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
|
||||
};
|
||||
|
||||
struct CArchiveLink
|
||||
{
|
||||
CObjectVector<CArc> Arcs;
|
||||
UStringVector VolumePaths;
|
||||
UInt64 VolumesSize;
|
||||
bool IsOpen;
|
||||
|
||||
bool PasswordWasAsked;
|
||||
// UString Password;
|
||||
|
||||
// int NonOpenErrorFormatIndex; // - 1 means no Error.
|
||||
UString NonOpen_ArcPath;
|
||||
|
||||
CArcErrorInfo NonOpen_ErrorInfo;
|
||||
|
||||
// UString ErrorsText;
|
||||
// void Set_ErrorsText();
|
||||
|
||||
CArchiveLink():
|
||||
VolumesSize(0),
|
||||
IsOpen(false),
|
||||
PasswordWasAsked(false)
|
||||
{}
|
||||
|
||||
void KeepModeForNextOpen();
|
||||
HRESULT Close();
|
||||
void Release();
|
||||
~CArchiveLink() { Release(); }
|
||||
|
||||
const CArc *GetArc() const { return &Arcs.Back(); }
|
||||
IInArchive *GetArchive() const { return Arcs.Back().Archive; }
|
||||
IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
|
||||
IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
|
||||
|
||||
HRESULT Open(COpenOptions &options);
|
||||
HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
|
||||
HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
|
||||
|
||||
HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
|
||||
{
|
||||
HRESULT result = Open3(options, callbackUI);
|
||||
if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
|
||||
result = S_FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT ReOpen(COpenOptions &options);
|
||||
};
|
||||
|
||||
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
|
||||
|
||||
|
||||
struct CDirPathSortPair
|
||||
{
|
||||
unsigned Len;
|
||||
unsigned Index;
|
||||
|
||||
void SetNumSlashes(const FChar *s);
|
||||
|
||||
int Compare(const CDirPathSortPair &a) const
|
||||
{
|
||||
// We need sorting order where parent items will be after child items
|
||||
if (Len < a.Len) return 1;
|
||||
if (Len > a.Len) return -1;
|
||||
if (Index < a.Index) return -1;
|
||||
if (Index > a.Index) return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,668 @@
|
||||
// PropIDUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/FileIO.h"
|
||||
#include "../../../Windows/PropVariantConv.h"
|
||||
|
||||
#include "../../PropID.h"
|
||||
|
||||
#include "PropIDUtils.h"
|
||||
|
||||
#define Get16(x) GetUi16(x)
|
||||
#define Get32(x) GetUi32(x)
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static const unsigned kNumWinAtrribFlags = 21;
|
||||
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
|
||||
|
||||
/*
|
||||
FILE_ATTRIBUTE_
|
||||
|
||||
0 READONLY
|
||||
1 HIDDEN
|
||||
2 SYSTEM
|
||||
3 (Volume label - obsolete)
|
||||
4 DIRECTORY
|
||||
5 ARCHIVE
|
||||
6 DEVICE
|
||||
7 NORMAL
|
||||
8 TEMPORARY
|
||||
9 SPARSE_FILE
|
||||
10 REPARSE_POINT
|
||||
11 COMPRESSED
|
||||
12 OFFLINE
|
||||
13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)
|
||||
14 ENCRYPTED
|
||||
15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)
|
||||
16 VIRTUAL (reserved)
|
||||
17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)
|
||||
18 RECALL_ON_OPEN or EA
|
||||
19 PINNED
|
||||
20 UNPINNED
|
||||
21 STRICTLY_SEQUENTIAL
|
||||
22 RECALL_ON_DATA_ACCESS
|
||||
*/
|
||||
|
||||
|
||||
static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
|
||||
#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
|
||||
|
||||
static void ConvertPosixAttribToString(char *s, UInt32 a) throw()
|
||||
{
|
||||
s[0] = kPosixTypes[(a >> 12) & 0xF];
|
||||
for (int i = 6; i >= 0; i -= 3)
|
||||
{
|
||||
s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
|
||||
s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
|
||||
s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
|
||||
}
|
||||
if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S');
|
||||
if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S');
|
||||
if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T');
|
||||
s[10] = 0;
|
||||
|
||||
a &= ~(UInt32)0xFFFF;
|
||||
if (a != 0)
|
||||
{
|
||||
s[10] = ' ';
|
||||
ConvertUInt32ToHex8Digits(a, s + 11);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConvertWinAttribToString(char *s, UInt32 wa) throw()
|
||||
{
|
||||
/*
|
||||
some programs store posix attributes in high 16 bits.
|
||||
p7zip - stores additional 0x8000 flag marker.
|
||||
macos - stores additional 0x4000 flag marker.
|
||||
info-zip - no additional marker.
|
||||
*/
|
||||
|
||||
bool isPosix = ((wa & 0xF0000000) != 0);
|
||||
|
||||
UInt32 posix = 0;
|
||||
if (isPosix)
|
||||
{
|
||||
posix = wa >> 16;
|
||||
wa &= (UInt32)0x3FFF;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
|
||||
{
|
||||
UInt32 flag = (1 << i);
|
||||
if ((wa & flag) != 0)
|
||||
{
|
||||
char c = g_WinAttribChars[i];
|
||||
if (c != '.')
|
||||
{
|
||||
wa &= ~flag;
|
||||
// if (i != 7) // we can disable N (NORMAL) printing
|
||||
*s++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wa != 0)
|
||||
{
|
||||
*s++ = ' ';
|
||||
ConvertUInt32ToHex8Digits(wa, s);
|
||||
s += strlen(s);
|
||||
}
|
||||
|
||||
*s = 0;
|
||||
|
||||
if (isPosix)
|
||||
{
|
||||
*s++ = ' ';
|
||||
ConvertPosixAttribToString(s, posix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()
|
||||
{
|
||||
*dest = 0;
|
||||
|
||||
if (prop.vt == VT_FILETIME)
|
||||
{
|
||||
const FILETIME &ft = prop.filetime;
|
||||
if ((ft.dwHighDateTime == 0 &&
|
||||
ft.dwLowDateTime == 0))
|
||||
return;
|
||||
ConvertUtcFileTimeToString(prop.filetime, dest, level);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidCRC:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
break;
|
||||
ConvertUInt32ToHex8Digits(prop.ulVal, dest);
|
||||
return;
|
||||
}
|
||||
case kpidAttrib:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
break;
|
||||
UInt32 a = prop.ulVal;
|
||||
|
||||
/*
|
||||
if ((a & 0x8000) && (a & 0x7FFF) == 0)
|
||||
ConvertPosixAttribToString(dest, a >> 16);
|
||||
else
|
||||
*/
|
||||
ConvertWinAttribToString(dest, a);
|
||||
return;
|
||||
}
|
||||
case kpidPosixAttrib:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
break;
|
||||
ConvertPosixAttribToString(dest, prop.ulVal);
|
||||
return;
|
||||
}
|
||||
case kpidINode:
|
||||
{
|
||||
if (prop.vt != VT_UI8)
|
||||
break;
|
||||
ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);
|
||||
dest += strlen(dest);
|
||||
*dest++ = '-';
|
||||
UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);
|
||||
ConvertUInt64ToString(low, dest);
|
||||
return;
|
||||
}
|
||||
case kpidVa:
|
||||
{
|
||||
UInt64 v = 0;
|
||||
if (prop.vt == VT_UI4)
|
||||
v = prop.ulVal;
|
||||
else if (prop.vt == VT_UI8)
|
||||
v = (UInt64)prop.uhVal.QuadPart;
|
||||
else
|
||||
break;
|
||||
dest[0] = '0';
|
||||
dest[1] = 'x';
|
||||
ConvertUInt64ToHex(v, dest + 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ConvertPropVariantToShortString(prop, dest);
|
||||
}
|
||||
|
||||
void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level)
|
||||
{
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
dest.SetFromBstr(prop.bstrVal);
|
||||
return;
|
||||
}
|
||||
char temp[64];
|
||||
ConvertPropertyToShortString2(temp, prop, propID, level);
|
||||
dest = temp;
|
||||
}
|
||||
|
||||
static inline unsigned GetHex(unsigned v)
|
||||
{
|
||||
return (v < 10) ? ('0' + v) : ('A' + (v - 10));
|
||||
}
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
static inline void AddHexToString(AString &res, unsigned v)
|
||||
{
|
||||
res += (char)GetHex(v >> 4);
|
||||
res += (char)GetHex(v & 0xF);
|
||||
}
|
||||
|
||||
/*
|
||||
static AString Data_To_Hex(const Byte *data, size_t size)
|
||||
{
|
||||
AString s;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
AddHexToString(s, data[i]);
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
static const char * const sidNames[] =
|
||||
{
|
||||
"0"
|
||||
, "Dialup"
|
||||
, "Network"
|
||||
, "Batch"
|
||||
, "Interactive"
|
||||
, "Logon" // S-1-5-5-X-Y
|
||||
, "Service"
|
||||
, "Anonymous"
|
||||
, "Proxy"
|
||||
, "EnterpriseDC"
|
||||
, "Self"
|
||||
, "AuthenticatedUsers"
|
||||
, "RestrictedCode"
|
||||
, "TerminalServer"
|
||||
, "RemoteInteractiveLogon"
|
||||
, "ThisOrganization"
|
||||
, "16"
|
||||
, "IUserIIS"
|
||||
, "LocalSystem"
|
||||
, "LocalService"
|
||||
, "NetworkService"
|
||||
, "Domains"
|
||||
};
|
||||
|
||||
struct CSecID2Name
|
||||
{
|
||||
UInt32 n;
|
||||
const char *sz;
|
||||
};
|
||||
|
||||
static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
|
||||
{
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
if (pairs[i].n == id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const CSecID2Name sid_32_Names[] =
|
||||
{
|
||||
{ 544, "Administrators" },
|
||||
{ 545, "Users" },
|
||||
{ 546, "Guests" },
|
||||
{ 547, "PowerUsers" },
|
||||
{ 548, "AccountOperators" },
|
||||
{ 549, "ServerOperators" },
|
||||
{ 550, "PrintOperators" },
|
||||
{ 551, "BackupOperators" },
|
||||
{ 552, "Replicators" },
|
||||
{ 553, "Backup Operators" },
|
||||
{ 554, "PreWindows2000CompatibleAccess" },
|
||||
{ 555, "RemoteDesktopUsers" },
|
||||
{ 556, "NetworkConfigurationOperators" },
|
||||
{ 557, "IncomingForestTrustBuilders" },
|
||||
{ 558, "PerformanceMonitorUsers" },
|
||||
{ 559, "PerformanceLogUsers" },
|
||||
{ 560, "WindowsAuthorizationAccessGroup" },
|
||||
{ 561, "TerminalServerLicenseServers" },
|
||||
{ 562, "DistributedCOMUsers" },
|
||||
{ 569, "CryptographicOperators" },
|
||||
{ 573, "EventLogReaders" },
|
||||
{ 574, "CertificateServiceDCOMAccess" }
|
||||
};
|
||||
|
||||
static const CSecID2Name sid_21_Names[] =
|
||||
{
|
||||
{ 500, "Administrator" },
|
||||
{ 501, "Guest" },
|
||||
{ 502, "KRBTGT" },
|
||||
{ 512, "DomainAdmins" },
|
||||
{ 513, "DomainUsers" },
|
||||
{ 515, "DomainComputers" },
|
||||
{ 516, "DomainControllers" },
|
||||
{ 517, "CertPublishers" },
|
||||
{ 518, "SchemaAdmins" },
|
||||
{ 519, "EnterpriseAdmins" },
|
||||
{ 520, "GroupPolicyCreatorOwners" },
|
||||
{ 553, "RASandIASServers" },
|
||||
{ 553, "RASandIASServers" },
|
||||
{ 571, "AllowedRODCPasswordReplicationGroup" },
|
||||
{ 572, "DeniedRODCPasswordReplicationGroup" }
|
||||
};
|
||||
|
||||
struct CServicesToName
|
||||
{
|
||||
UInt32 n[5];
|
||||
const char *sz;
|
||||
};
|
||||
|
||||
static const CServicesToName services_to_name[] =
|
||||
{
|
||||
{ { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }
|
||||
};
|
||||
|
||||
static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
|
||||
{
|
||||
sidSize = 0;
|
||||
if (lim < 8)
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
UInt32 rev = p[0];
|
||||
if (rev != 1)
|
||||
{
|
||||
s += "UNSUPPORTED";
|
||||
return;
|
||||
}
|
||||
UInt32 num = p[1];
|
||||
if (8 + num * 4 > lim)
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
sidSize = 8 + num * 4;
|
||||
UInt32 authority = GetBe32(p + 4);
|
||||
|
||||
if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
|
||||
{
|
||||
UInt32 v0 = Get32(p + 8);
|
||||
if (v0 < ARRAY_SIZE(sidNames))
|
||||
{
|
||||
s += sidNames[v0];
|
||||
return;
|
||||
}
|
||||
if (v0 == 32 && num == 2)
|
||||
{
|
||||
UInt32 v1 = Get32(p + 12);
|
||||
int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1);
|
||||
if (index >= 0)
|
||||
{
|
||||
s += sid_32_Names[(unsigned)index].sz;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (v0 == 21 && num == 5)
|
||||
{
|
||||
UInt32 v4 = Get32(p + 8 + 4 * 4);
|
||||
int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4);
|
||||
if (index >= 0)
|
||||
{
|
||||
s += sid_21_Names[(unsigned)index].sz;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (v0 == 80 && num == 6)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(services_to_name); i++)
|
||||
{
|
||||
const CServicesToName &sn = services_to_name[i];
|
||||
int j;
|
||||
for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);
|
||||
if (j == 5)
|
||||
{
|
||||
s += sn.sz;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += "S-1-";
|
||||
if (p[2] == 0 && p[3] == 0)
|
||||
s.Add_UInt32(authority);
|
||||
else
|
||||
{
|
||||
s += "0x";
|
||||
for (int i = 2; i < 8; i++)
|
||||
AddHexToString(s, p[i]);
|
||||
}
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
{
|
||||
s += '-';
|
||||
s.Add_UInt32(Get32(p + 8 + i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
|
||||
{
|
||||
if (pos > size)
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
UInt32 sidSize = 0;
|
||||
ParseSid(s, p + pos, size - pos, sidSize);
|
||||
}
|
||||
|
||||
static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
|
||||
{
|
||||
UInt32 control = Get16(p + 2);
|
||||
if ((flags & control) == 0)
|
||||
return;
|
||||
UInt32 pos = Get32(p + offset);
|
||||
s.Add_Space();
|
||||
s += strName;
|
||||
if (pos >= size)
|
||||
return;
|
||||
p += pos;
|
||||
size -= pos;
|
||||
if (size < 8)
|
||||
return;
|
||||
if (Get16(p) != 2) // revision
|
||||
return;
|
||||
UInt32 num = Get32(p + 4);
|
||||
s.Add_UInt32(num);
|
||||
|
||||
/*
|
||||
UInt32 aclSize = Get16(p + 2);
|
||||
if (num >= (1 << 16))
|
||||
return;
|
||||
if (aclSize > size)
|
||||
return;
|
||||
size = aclSize;
|
||||
size -= 8;
|
||||
p += 8;
|
||||
for (UInt32 i = 0 ; i < num; i++)
|
||||
{
|
||||
if (size <= 8)
|
||||
return;
|
||||
// Byte type = p[0];
|
||||
// Byte flags = p[1];
|
||||
// UInt32 aceSize = Get16(p + 2);
|
||||
// UInt32 mask = Get32(p + 4);
|
||||
p += 8;
|
||||
size -= 8;
|
||||
|
||||
UInt32 sidSize = 0;
|
||||
s.Add_Space();
|
||||
ParseSid(s, p, size, sidSize);
|
||||
if (sidSize == 0)
|
||||
return;
|
||||
p += sidSize;
|
||||
size -= sidSize;
|
||||
}
|
||||
|
||||
// the tail can contain zeros. So (size != 0) is not ERROR
|
||||
// if (size != 0) s += " ERROR";
|
||||
*/
|
||||
}
|
||||
|
||||
#define MY_SE_OWNER_DEFAULTED (0x0001)
|
||||
#define MY_SE_GROUP_DEFAULTED (0x0002)
|
||||
#define MY_SE_DACL_PRESENT (0x0004)
|
||||
#define MY_SE_DACL_DEFAULTED (0x0008)
|
||||
#define MY_SE_SACL_PRESENT (0x0010)
|
||||
#define MY_SE_SACL_DEFAULTED (0x0020)
|
||||
#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)
|
||||
#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)
|
||||
#define MY_SE_DACL_AUTO_INHERITED (0x0400)
|
||||
#define MY_SE_SACL_AUTO_INHERITED (0x0800)
|
||||
#define MY_SE_DACL_PROTECTED (0x1000)
|
||||
#define MY_SE_SACL_PROTECTED (0x2000)
|
||||
#define MY_SE_RM_CONTROL_VALID (0x4000)
|
||||
#define MY_SE_SELF_RELATIVE (0x8000)
|
||||
|
||||
void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
|
||||
{
|
||||
s.Empty();
|
||||
if (size < 20 || size > (1 << 18))
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
if (Get16(data) != 1) // revision
|
||||
{
|
||||
s += "UNSUPPORTED";
|
||||
return;
|
||||
}
|
||||
ParseOwner(s, data, size, Get32(data + 4));
|
||||
s.Add_Space();
|
||||
ParseOwner(s, data, size, Get32(data + 8));
|
||||
ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
|
||||
ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
|
||||
s.Add_Space();
|
||||
s.Add_UInt32(size);
|
||||
// s += '\n';
|
||||
// s += Data_To_Hex(data, size);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw()
|
||||
{
|
||||
if (pos >= size)
|
||||
return false;
|
||||
size -= pos;
|
||||
if (size < 8)
|
||||
return false;
|
||||
UInt32 rev = data[pos];
|
||||
if (rev != 1)
|
||||
return false;
|
||||
UInt32 num = data[pos + 1];
|
||||
return (8 + num * 4 <= size);
|
||||
}
|
||||
|
||||
static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw()
|
||||
{
|
||||
UInt32 control = Get16(p + 2);
|
||||
if ((flags & control) == 0)
|
||||
return true;
|
||||
UInt32 pos = Get32(p + offset);
|
||||
if (pos >= size)
|
||||
return false;
|
||||
p += pos;
|
||||
size -= pos;
|
||||
if (size < 8)
|
||||
return false;
|
||||
UInt32 aclSize = Get16(p + 2);
|
||||
return (aclSize <= size);
|
||||
}
|
||||
|
||||
bool CheckNtSecure(const Byte *data, UInt32 size) throw()
|
||||
{
|
||||
if (size < 20)
|
||||
return false;
|
||||
if (Get16(data) != 1) // revision
|
||||
return true; // windows function can handle such error, so we allow it
|
||||
if (size > (1 << 18))
|
||||
return false;
|
||||
if (!CheckSid(data, size, Get32(data + 4))) return false;
|
||||
if (!CheckSid(data, size, Get32(data + 8))) return false;
|
||||
if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;
|
||||
if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// IO_REPARSE_TAG_*
|
||||
|
||||
static const CSecID2Name k_ReparseTags[] =
|
||||
{
|
||||
{ 0xA0000003, "MOUNT_POINT" },
|
||||
{ 0xC0000004, "HSM" },
|
||||
{ 0x80000005, "DRIVE_EXTENDER" },
|
||||
{ 0x80000006, "HSM2" },
|
||||
{ 0x80000007, "SIS" },
|
||||
{ 0x80000008, "WIM" },
|
||||
{ 0x80000009, "CSV" },
|
||||
{ 0x8000000A, "DFS" },
|
||||
{ 0x8000000B, "FILTER_MANAGER" },
|
||||
{ 0xA000000C, "SYMLINK" },
|
||||
{ 0xA0000010, "IIS_CACHE" },
|
||||
{ 0x80000012, "DFSR" },
|
||||
{ 0x80000013, "DEDUP" },
|
||||
{ 0xC0000014, "APPXSTRM" },
|
||||
{ 0x80000014, "NFS" },
|
||||
{ 0x80000015, "FILE_PLACEHOLDER" },
|
||||
{ 0x80000016, "DFM" },
|
||||
{ 0x80000017, "WOF" }
|
||||
};
|
||||
|
||||
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
|
||||
{
|
||||
s.Empty();
|
||||
NFile::CReparseAttr attr;
|
||||
DWORD errorCode = 0;
|
||||
if (attr.Parse(data, size, errorCode))
|
||||
{
|
||||
if (!attr.IsSymLink())
|
||||
s += "Junction: ";
|
||||
s += attr.GetPath();
|
||||
if (!attr.IsOkNamePair())
|
||||
{
|
||||
s += " : ";
|
||||
s += attr.PrintName;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size < 8)
|
||||
return false;
|
||||
UInt32 tag = Get32(data);
|
||||
UInt32 len = Get16(data + 4);
|
||||
if (len + 8 > size)
|
||||
return false;
|
||||
if (Get16(data + 6) != 0) // padding
|
||||
return false;
|
||||
|
||||
/*
|
||||
#define _my_IO_REPARSE_TAG_DEDUP (0x80000013L)
|
||||
if (tag == _my_IO_REPARSE_TAG_DEDUP)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag);
|
||||
if (index >= 0)
|
||||
s += k_ReparseTags[(unsigned)index].sz;
|
||||
else
|
||||
{
|
||||
s += "REPARSE:";
|
||||
char hex[16];
|
||||
ConvertUInt32ToHex8Digits(tag, hex);
|
||||
s += hex;
|
||||
}
|
||||
}
|
||||
|
||||
s += ":";
|
||||
s.Add_UInt32(len);
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
s.Add_Space();
|
||||
|
||||
data += 8;
|
||||
|
||||
for (UInt32 i = 0; i < len; i++)
|
||||
{
|
||||
if (i >= 8)
|
||||
{
|
||||
s += "...";
|
||||
break;
|
||||
}
|
||||
unsigned b = data[i];
|
||||
s += (char)GetHex((b >> 4) & 0xF);
|
||||
s += (char)GetHex(b & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
// PropIDUtils.h
|
||||
|
||||
#ifndef __PROPID_UTILS_H
|
||||
#define __PROPID_UTILS_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
// provide at least 64 bytes for buffer including zero-end
|
||||
void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw();
|
||||
void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0);
|
||||
|
||||
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s);
|
||||
void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s);
|
||||
bool CheckNtSecure(const Byte *data, UInt32 size) throw();;
|
||||
|
||||
void ConvertWinAttribToString(char *s, UInt32 wa) throw();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
// Property.h
|
||||
|
||||
#ifndef __7Z_PROPERTY_H
|
||||
#define __7Z_PROPERTY_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
struct CProperty
|
||||
{
|
||||
UString Name;
|
||||
UString Value;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
// SetProperties.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "SetProperties.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
|
||||
{
|
||||
const wchar_t *end;
|
||||
UInt64 result = ConvertStringToUInt64(s, &end);
|
||||
if (*end != 0 || s.IsEmpty())
|
||||
prop = s;
|
||||
else if (result <= (UInt32)0xFFFFFFFF)
|
||||
prop = (UInt32)result;
|
||||
else
|
||||
prop = result;
|
||||
}
|
||||
|
||||
HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)
|
||||
{
|
||||
if (properties.IsEmpty())
|
||||
return S_OK;
|
||||
CMyComPtr<ISetProperties> setProperties;
|
||||
unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);
|
||||
if (!setProperties)
|
||||
return S_OK;
|
||||
|
||||
UStringVector realNames;
|
||||
CPropVariant *values = new CPropVariant[properties.Size()];
|
||||
try
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < properties.Size(); i++)
|
||||
{
|
||||
const CProperty &property = properties[i];
|
||||
NCOM::CPropVariant propVariant;
|
||||
UString name = property.Name;
|
||||
if (property.Value.IsEmpty())
|
||||
{
|
||||
if (!name.IsEmpty())
|
||||
{
|
||||
wchar_t c = name.Back();
|
||||
if (c == L'-')
|
||||
propVariant = false;
|
||||
else if (c == L'+')
|
||||
propVariant = true;
|
||||
if (propVariant.vt != VT_EMPTY)
|
||||
name.DeleteBack();
|
||||
}
|
||||
}
|
||||
else
|
||||
ParseNumberString(property.Value, propVariant);
|
||||
realNames.Add(name);
|
||||
values[i] = propVariant;
|
||||
}
|
||||
CRecordVector<const wchar_t *> names;
|
||||
for (i = 0; i < realNames.Size(); i++)
|
||||
names.Add((const wchar_t *)realNames[i]);
|
||||
|
||||
RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
delete []values;
|
||||
throw;
|
||||
}
|
||||
delete []values;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// SetProperties.h
|
||||
|
||||
#ifndef __SETPROPERTIES_H
|
||||
#define __SETPROPERTIES_H
|
||||
|
||||
#include "Property.h"
|
||||
|
||||
HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
// SortUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "SortUtils.h"
|
||||
|
||||
static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param)
|
||||
{
|
||||
const UStringVector &strings = *(const UStringVector *)param;
|
||||
return CompareFileNames(strings[*p1], strings[*p2]);
|
||||
}
|
||||
|
||||
void SortFileNames(const UStringVector &strings, CUIntVector &indices)
|
||||
{
|
||||
const unsigned numItems = strings.Size();
|
||||
indices.ClearAndSetSize(numItems);
|
||||
if (numItems == 0)
|
||||
return;
|
||||
unsigned *vals = &indices[0];
|
||||
for (unsigned i = 0; i < numItems; i++)
|
||||
vals[i] = i;
|
||||
indices.Sort(CompareStrings, (void *)&strings);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// SortUtils.h
|
||||
|
||||
#ifndef __SORT_UTLS_H
|
||||
#define __SORT_UTLS_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
void SortFileNames(const UStringVector &strings, CUIntVector &indices);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
// TempFiles.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
|
||||
#include "TempFiles.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
void CTempFiles::Clear()
|
||||
{
|
||||
while (!Paths.IsEmpty())
|
||||
{
|
||||
NDir::DeleteFileAlways(Paths.Back());
|
||||
Paths.DeleteBack();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// TempFiles.h
|
||||
|
||||
#ifndef __TEMP_FILES_H
|
||||
#define __TEMP_FILES_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
class CTempFiles
|
||||
{
|
||||
void Clear();
|
||||
public:
|
||||
FStringVector Paths;
|
||||
~CTempFiles() { Clear(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,200 @@
|
||||
// Update.h
|
||||
|
||||
#ifndef __COMMON_UPDATE_H
|
||||
#define __COMMON_UPDATE_H
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
#include "LoadCodecs.h"
|
||||
#include "OpenArchive.h"
|
||||
#include "Property.h"
|
||||
#include "UpdateAction.h"
|
||||
#include "UpdateCallback.h"
|
||||
|
||||
#include "DirItem.h"
|
||||
|
||||
enum EArcNameMode
|
||||
{
|
||||
k_ArcNameMode_Smart,
|
||||
k_ArcNameMode_Exact,
|
||||
k_ArcNameMode_Add,
|
||||
};
|
||||
|
||||
struct CArchivePath
|
||||
{
|
||||
UString OriginalPath;
|
||||
|
||||
UString Prefix; // path(folder) prefix including slash
|
||||
UString Name; // base name
|
||||
UString BaseExtension; // archive type extension or "exe" extension
|
||||
UString VolExtension; // archive type extension for volumes
|
||||
|
||||
bool Temp;
|
||||
FString TempPrefix; // path(folder) for temp location
|
||||
FString TempPostfix;
|
||||
|
||||
CArchivePath(): Temp(false) {};
|
||||
|
||||
void ParseFromPath(const UString &path, EArcNameMode mode);
|
||||
UString GetPathWithoutExt() const { return Prefix + Name; }
|
||||
UString GetFinalPath() const;
|
||||
UString GetFinalVolPath() const;
|
||||
FString GetTempPath() const;
|
||||
};
|
||||
|
||||
struct CUpdateArchiveCommand
|
||||
{
|
||||
UString UserArchivePath;
|
||||
CArchivePath ArchivePath;
|
||||
NUpdateArchive::CActionSet ActionSet;
|
||||
};
|
||||
|
||||
struct CCompressionMethodMode
|
||||
{
|
||||
bool Type_Defined;
|
||||
COpenType Type;
|
||||
CObjectVector<CProperty> Properties;
|
||||
|
||||
CCompressionMethodMode(): Type_Defined(false) {}
|
||||
};
|
||||
|
||||
namespace NRecursedType { enum EEnum
|
||||
{
|
||||
kRecursed,
|
||||
kWildcardOnlyRecursed,
|
||||
kNonRecursed
|
||||
};}
|
||||
|
||||
struct CRenamePair
|
||||
{
|
||||
UString OldName;
|
||||
UString NewName;
|
||||
bool WildcardParsing;
|
||||
NRecursedType::EEnum RecursedType;
|
||||
|
||||
CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {}
|
||||
|
||||
bool Prepare();
|
||||
bool GetNewPath(bool isFolder, const UString &src, UString &dest) const;
|
||||
};
|
||||
|
||||
struct CUpdateOptions
|
||||
{
|
||||
CCompressionMethodMode MethodMode;
|
||||
|
||||
CObjectVector<CUpdateArchiveCommand> Commands;
|
||||
bool UpdateArchiveItself;
|
||||
CArchivePath ArchivePath;
|
||||
EArcNameMode ArcNameMode;
|
||||
|
||||
bool SfxMode;
|
||||
FString SfxModule;
|
||||
|
||||
bool OpenShareForWrite;
|
||||
bool StopAfterOpenError;
|
||||
|
||||
bool StdInMode;
|
||||
UString StdInFileName;
|
||||
bool StdOutMode;
|
||||
|
||||
bool EMailMode;
|
||||
bool EMailRemoveAfter;
|
||||
UString EMailAddress;
|
||||
|
||||
FString WorkingDir;
|
||||
NWildcard::ECensorPathMode PathMode;
|
||||
UString AddPathPrefix;
|
||||
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair AltStreams;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
bool DeleteAfterCompressing;
|
||||
|
||||
bool SetArcMTime;
|
||||
|
||||
CObjectVector<CRenamePair> RenamePairs;
|
||||
|
||||
bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);
|
||||
bool SetArcPath(const CCodecs *codecs, const UString &arcPath);
|
||||
|
||||
CUpdateOptions():
|
||||
UpdateArchiveItself(true),
|
||||
SfxMode(false),
|
||||
StdInMode(false),
|
||||
StdOutMode(false),
|
||||
EMailMode(false),
|
||||
EMailRemoveAfter(false),
|
||||
OpenShareForWrite(false),
|
||||
StopAfterOpenError(false),
|
||||
ArcNameMode(k_ArcNameMode_Smart),
|
||||
PathMode(NWildcard::k_RelatPath),
|
||||
|
||||
DeleteAfterCompressing(false),
|
||||
SetArcMTime(false)
|
||||
|
||||
{};
|
||||
|
||||
void SetActionCommand_Add()
|
||||
{
|
||||
Commands.Clear();
|
||||
CUpdateArchiveCommand c;
|
||||
c.ActionSet = NUpdateArchive::k_ActionSet_Add;
|
||||
Commands.Add(c);
|
||||
}
|
||||
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
};
|
||||
|
||||
struct CUpdateErrorInfo
|
||||
{
|
||||
DWORD SystemError;
|
||||
AString Message;
|
||||
FStringVector FileNames;
|
||||
|
||||
bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); }
|
||||
HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); }
|
||||
void SetFromLastError(const char *message);
|
||||
HRESULT SetFromLastError(const char *message, const FString &fileName);
|
||||
|
||||
CUpdateErrorInfo(): SystemError(0) {};
|
||||
};
|
||||
|
||||
struct CFinishArchiveStat
|
||||
{
|
||||
UInt64 OutArcFileSize;
|
||||
|
||||
CFinishArchiveStat(): OutArcFileSize(0) {}
|
||||
};
|
||||
|
||||
#define INTERFACE_IUpdateCallbackUI2(x) \
|
||||
INTERFACE_IUpdateCallbackUI(x) \
|
||||
INTERFACE_IDirItemsCallback(x) \
|
||||
virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \
|
||||
virtual HRESULT StartScanning() x; \
|
||||
virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \
|
||||
virtual HRESULT StartOpenArchive(const wchar_t *name) x; \
|
||||
virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \
|
||||
virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x; \
|
||||
virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \
|
||||
virtual HRESULT FinishDeletingAfterArchiving() x; \
|
||||
|
||||
struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback
|
||||
{
|
||||
INTERFACE_IUpdateCallbackUI2(=0)
|
||||
};
|
||||
|
||||
HRESULT UpdateArchive(
|
||||
CCodecs *codecs,
|
||||
const CObjectVector<COpenType> &types,
|
||||
const UString &cmdArcPath2,
|
||||
NWildcard::CCensor &censor,
|
||||
CUpdateOptions &options,
|
||||
CUpdateErrorInfo &errorInfo,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IUpdateCallbackUI2 *callback,
|
||||
bool needSetPath);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
// UpdateAction.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "UpdateAction.h"
|
||||
|
||||
namespace NUpdateArchive {
|
||||
|
||||
const CActionSet k_ActionSet_Add =
|
||||
{{
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCompress
|
||||
}};
|
||||
|
||||
const CActionSet k_ActionSet_Update =
|
||||
{{
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress
|
||||
}};
|
||||
|
||||
const CActionSet k_ActionSet_Fresh =
|
||||
{{
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress
|
||||
}};
|
||||
|
||||
const CActionSet k_ActionSet_Sync =
|
||||
{{
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress,
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kCompress,
|
||||
}};
|
||||
|
||||
const CActionSet k_ActionSet_Delete =
|
||||
{{
|
||||
NPairAction::kCopy,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kIgnore,
|
||||
NPairAction::kIgnore
|
||||
}};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// UpdateAction.h
|
||||
|
||||
#ifndef __UPDATE_ACTION_H
|
||||
#define __UPDATE_ACTION_H
|
||||
|
||||
namespace NUpdateArchive {
|
||||
|
||||
namespace NPairState
|
||||
{
|
||||
const unsigned kNumValues = 7;
|
||||
enum EEnum
|
||||
{
|
||||
kNotMasked = 0,
|
||||
kOnlyInArchive,
|
||||
kOnlyOnDisk,
|
||||
kNewInArchive,
|
||||
kOldInArchive,
|
||||
kSameFiles,
|
||||
kUnknowNewerFiles
|
||||
};
|
||||
}
|
||||
|
||||
namespace NPairAction
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kIgnore = 0,
|
||||
kCopy,
|
||||
kCompress,
|
||||
kCompressAsAnti
|
||||
};
|
||||
}
|
||||
|
||||
struct CActionSet
|
||||
{
|
||||
NPairAction::EEnum StateActions[NPairState::kNumValues];
|
||||
|
||||
bool IsEqualTo(const CActionSet &a) const
|
||||
{
|
||||
for (unsigned i = 0; i < NPairState::kNumValues; i++)
|
||||
if (StateActions[i] != a.StateActions[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NeedScanning() const
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < NPairState::kNumValues; i++)
|
||||
if (StateActions[i] == NPairAction::kCompress)
|
||||
return true;
|
||||
for (i = 1; i < NPairState::kNumValues; i++)
|
||||
if (StateActions[i] != NPairAction::kIgnore)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
extern const CActionSet k_ActionSet_Add;
|
||||
extern const CActionSet k_ActionSet_Update;
|
||||
extern const CActionSet k_ActionSet_Fresh;
|
||||
extern const CActionSet k_ActionSet_Sync;
|
||||
extern const CActionSet k_ActionSet_Delete;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,771 @@
|
||||
// UpdateCallback.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
#endif
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
#include "UpdateCallback.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
#define _USE_SECURITY_CODE
|
||||
#include "../../../Windows/SecurityUtils.h"
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
static NSynchronization::CCriticalSection g_CriticalSection;
|
||||
#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
|
||||
#else
|
||||
#define MT_LOCK
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _USE_SECURITY_CODE
|
||||
bool InitLocalPrivileges();
|
||||
#endif
|
||||
|
||||
CArchiveUpdateCallback::CArchiveUpdateCallback():
|
||||
_hardIndex_From((UInt32)(Int32)-1),
|
||||
|
||||
Callback(NULL),
|
||||
|
||||
DirItems(NULL),
|
||||
ParentDirItem(NULL),
|
||||
|
||||
Arc(NULL),
|
||||
ArcItems(NULL),
|
||||
UpdatePairs(NULL),
|
||||
NewNames(NULL),
|
||||
CommentIndex(-1),
|
||||
Comment(NULL),
|
||||
|
||||
ShareForWrite(false),
|
||||
StopAfterOpenError(false),
|
||||
StdInMode(false),
|
||||
|
||||
KeepOriginalItemNames(false),
|
||||
StoreNtSecurity(false),
|
||||
StoreHardLinks(false),
|
||||
StoreSymLinks(false),
|
||||
|
||||
ProcessedItemsStatuses(NULL)
|
||||
{
|
||||
#ifdef _USE_SECURITY_CODE
|
||||
_saclEnabled = InitLocalPrivileges();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return Callback->SetTotal(size);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return Callback->SetCompleted(completeValue);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return Callback->SetRatioInfo(inSize, outSize);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static const CStatProp kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidCTime, VT_FILETIME},
|
||||
{ NULL, kpidATime, VT_FILETIME},
|
||||
{ NULL, kpidMTime, VT_FILETIME},
|
||||
{ NULL, kpidAttrib, VT_UI4},
|
||||
{ NULL, kpidIsAnti, VT_BOOL}
|
||||
};
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
|
||||
{
|
||||
return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator);
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
|
||||
Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
RINOK(Callback->CheckBreak());
|
||||
const CUpdatePair2 &up = (*UpdatePairs)[index];
|
||||
if (newData) *newData = BoolToInt(up.NewData);
|
||||
if (newProps) *newProps = BoolToInt(up.NewProps);
|
||||
if (indexInArchive)
|
||||
{
|
||||
*indexInArchive = (UInt32)(Int32)-1;
|
||||
if (up.ExistInArchive())
|
||||
*indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidIsDir: prop = true; break;
|
||||
case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break;
|
||||
case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
|
||||
case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
|
||||
case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
|
||||
{
|
||||
*parentType = NParentType::kDir;
|
||||
*parent = (UInt32)(Int32)-1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps)
|
||||
{
|
||||
*numProps = 0;
|
||||
if (StoreNtSecurity)
|
||||
*numProps = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
|
||||
{
|
||||
*name = NULL;
|
||||
*propID = kpidNtSecure;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID
|
||||
#ifdef _USE_SECURITY_CODE
|
||||
propID
|
||||
#endif
|
||||
, const void **data, UInt32 *dataSize, UInt32 *propType)
|
||||
{
|
||||
*data = 0;
|
||||
*dataSize = 0;
|
||||
*propType = 0;
|
||||
if (!StoreNtSecurity)
|
||||
return S_OK;
|
||||
#ifdef _USE_SECURITY_CODE
|
||||
if (propID == kpidNtSecure)
|
||||
{
|
||||
if (StdInMode)
|
||||
return S_OK;
|
||||
|
||||
if (ParentDirItem)
|
||||
{
|
||||
if (ParentDirItem->SecureIndex < 0)
|
||||
return S_OK;
|
||||
const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex];
|
||||
*data = buf;
|
||||
*dataSize = (UInt32)buf.Size();
|
||||
*propType = NPropDataType::kRaw;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (Arc && Arc->GetRootProps)
|
||||
return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
|
||||
}
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// #ifdef _USE_SECURITY_CODE
|
||||
// #endif
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
|
||||
{
|
||||
*data = 0;
|
||||
*dataSize = 0;
|
||||
*propType = 0;
|
||||
|
||||
if (propID == kpidNtSecure ||
|
||||
propID == kpidNtReparse)
|
||||
{
|
||||
if (StdInMode)
|
||||
return S_OK;
|
||||
|
||||
const CUpdatePair2 &up = (*UpdatePairs)[index];
|
||||
if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps)
|
||||
return Arc->GetRawProps->GetRawProp(
|
||||
ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,
|
||||
propID, data, dataSize, propType);
|
||||
{
|
||||
/*
|
||||
if (!up.NewData)
|
||||
return E_FAIL;
|
||||
*/
|
||||
if (up.IsAnti)
|
||||
return S_OK;
|
||||
|
||||
#ifndef UNDER_CE
|
||||
const CDirItem &di = DirItems->Items[up.DirIndex];
|
||||
#endif
|
||||
|
||||
#ifdef _USE_SECURITY_CODE
|
||||
if (propID == kpidNtSecure)
|
||||
{
|
||||
if (!StoreNtSecurity)
|
||||
return S_OK;
|
||||
if (di.SecureIndex < 0)
|
||||
return S_OK;
|
||||
const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex];
|
||||
*data = buf;
|
||||
*dataSize = (UInt32)buf.Size();
|
||||
*propType = NPropDataType::kRaw;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// propID == kpidNtReparse
|
||||
if (!StoreSymLinks)
|
||||
return S_OK;
|
||||
#ifndef UNDER_CE
|
||||
const CByteBuffer *buf = &di.ReparseData2;
|
||||
if (buf->Size() == 0)
|
||||
buf = &di.ReparseData;
|
||||
if (buf->Size() != 0)
|
||||
{
|
||||
*data = *buf;
|
||||
*dataSize = (UInt32)buf->Size();
|
||||
*propType = NPropDataType::kRaw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
static UString GetRelativePath(const UString &to, const UString &from)
|
||||
{
|
||||
UStringVector partsTo, partsFrom;
|
||||
SplitPathToParts(to, partsTo);
|
||||
SplitPathToParts(from, partsFrom);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
if (i + 1 >= partsFrom.Size() ||
|
||||
i + 1 >= partsTo.Size())
|
||||
break;
|
||||
if (CompareFileNames(partsFrom[i], partsTo[i]) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (NName::IsDrivePath(to) ||
|
||||
NName::IsDrivePath(from))
|
||||
return to;
|
||||
#endif
|
||||
}
|
||||
|
||||
UString s;
|
||||
unsigned k;
|
||||
|
||||
for (k = i + 1; k < partsFrom.Size(); k++)
|
||||
s += ".." STRING_PATH_SEPARATOR;
|
||||
|
||||
for (k = i; k < partsTo.Size(); k++)
|
||||
{
|
||||
if (k != i)
|
||||
s.Add_PathSepar();
|
||||
s += partsTo[k];
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const CUpdatePair2 &up = (*UpdatePairs)[index];
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
if (up.NewData)
|
||||
{
|
||||
/*
|
||||
if (propID == kpidIsHardLink)
|
||||
{
|
||||
prop = _isHardLink;
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
if (propID == kpidSymLink)
|
||||
{
|
||||
if (index == _hardIndex_From)
|
||||
{
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
if (up.DirIndex >= 0)
|
||||
{
|
||||
#ifndef UNDER_CE
|
||||
const CDirItem &di = DirItems->Items[up.DirIndex];
|
||||
// if (di.IsDir())
|
||||
{
|
||||
CReparseAttr attr;
|
||||
DWORD errorCode = 0;
|
||||
if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode))
|
||||
{
|
||||
UString simpleName = attr.GetPath();
|
||||
if (attr.IsRelative())
|
||||
prop = simpleName;
|
||||
else
|
||||
{
|
||||
const FString phyPath = DirItems->GetPhyPath(up.DirIndex);
|
||||
FString fullPath;
|
||||
if (NDir::MyGetFullPathName(phyPath, fullPath))
|
||||
{
|
||||
prop = GetRelativePath(simpleName, fs2us(fullPath));
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (propID == kpidHardLink)
|
||||
{
|
||||
if (index == _hardIndex_From)
|
||||
{
|
||||
const CKeyKeyValPair &pair = _map[_hardIndex_To];
|
||||
const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value];
|
||||
prop = DirItems->GetLogPath(up2.DirIndex);
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
if (up.DirIndex >= 0)
|
||||
{
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (up.IsAnti
|
||||
&& propID != kpidIsDir
|
||||
&& propID != kpidPath
|
||||
&& propID != kpidIsAltStream)
|
||||
{
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize: prop = (UInt64)0; break;
|
||||
case kpidIsAnti: prop = true; break;
|
||||
}
|
||||
}
|
||||
else if (propID == kpidPath && up.NewNameIndex >= 0)
|
||||
prop = (*NewNames)[up.NewNameIndex];
|
||||
else if (propID == kpidComment
|
||||
&& CommentIndex >= 0
|
||||
&& (unsigned)CommentIndex == index
|
||||
&& Comment)
|
||||
prop = *Comment;
|
||||
else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem)
|
||||
{
|
||||
// we can generate new ShortName here;
|
||||
}
|
||||
else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))
|
||||
&& up.ExistInArchive() && Archive)
|
||||
return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value);
|
||||
else if (up.ExistOnDisk())
|
||||
{
|
||||
const CDirItem &di = DirItems->Items[up.DirIndex];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
|
||||
case kpidIsDir: prop = di.IsDir(); break;
|
||||
case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
|
||||
case kpidAttrib: prop = di.Attrib; break;
|
||||
case kpidCTime: prop = di.CTime; break;
|
||||
case kpidATime: prop = di.ATime; break;
|
||||
case kpidMTime: prop = di.MTime; break;
|
||||
case kpidIsAltStream: prop = di.IsAltStream; break;
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
// case kpidShortName: prop = di.ShortName; break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
static NSynchronization::CCriticalSection CS;
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*inStream = NULL;
|
||||
const CUpdatePair2 &up = (*UpdatePairs)[index];
|
||||
if (!up.NewData)
|
||||
return E_FAIL;
|
||||
|
||||
RINOK(Callback->CheckBreak());
|
||||
// RINOK(Callback->Finalize());
|
||||
|
||||
bool isDir = IsDir(up);
|
||||
|
||||
if (up.IsAnti)
|
||||
{
|
||||
UString name;
|
||||
if (up.ArcIndex >= 0)
|
||||
name = (*ArcItems)[up.ArcIndex].Name;
|
||||
else if (up.DirIndex >= 0)
|
||||
name = DirItems->GetLogPath(up.DirIndex);
|
||||
RINOK(Callback->GetStream(name, isDir, true, mode));
|
||||
|
||||
/* 9.33: fixed. Handlers expect real stream object for files, even for anti-file.
|
||||
so we return empty stream */
|
||||
|
||||
if (!isDir)
|
||||
{
|
||||
CBufInStream *inStreamSpec = new CBufInStream();
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
|
||||
inStreamSpec->Init(NULL, 0);
|
||||
*inStream = inStreamLoc.Detach();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode));
|
||||
|
||||
if (isDir)
|
||||
return S_OK;
|
||||
|
||||
if (StdInMode)
|
||||
{
|
||||
if (mode != NUpdateNotifyOp::kAdd &&
|
||||
mode != NUpdateNotifyOp::kUpdate)
|
||||
return S_OK;
|
||||
|
||||
CStdInFileStream *inStreamSpec = new CStdInFileStream;
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
*inStream = inStreamLoc.Detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
|
||||
inStreamSpec->SupportHardLinks = StoreHardLinks;
|
||||
inStreamSpec->Callback = this;
|
||||
inStreamSpec->CallbackRef = index;
|
||||
|
||||
const FString path = DirItems->GetPhyPath(up.DirIndex);
|
||||
_openFiles_Indexes.Add(index);
|
||||
_openFiles_Paths.Add(path);
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (DirItems->Items[up.DirIndex].AreReparseData())
|
||||
{
|
||||
if (!inStreamSpec->File.OpenReparse(path))
|
||||
{
|
||||
return Callback->OpenFileError(path, ::GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!inStreamSpec->OpenShared(path, ShareForWrite))
|
||||
{
|
||||
DWORD error = ::GetLastError();
|
||||
HRESULT hres = Callback->OpenFileError(path, error);
|
||||
if (StopAfterOpenError)
|
||||
if (hres == S_OK || hres == S_FALSE)
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (StoreHardLinks)
|
||||
{
|
||||
CStreamFileProps props;
|
||||
if (inStreamSpec->GetProps2(&props) == S_OK)
|
||||
{
|
||||
if (props.NumLinks > 1)
|
||||
{
|
||||
CKeyKeyValPair pair;
|
||||
pair.Key1 = props.VolID;
|
||||
pair.Key2 = props.FileID_Low;
|
||||
pair.Value = index;
|
||||
unsigned numItems = _map.Size();
|
||||
unsigned pairIndex = _map.AddToUniqueSorted2(pair);
|
||||
if (numItems == _map.Size())
|
||||
{
|
||||
// const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex];
|
||||
_hardIndex_From = index;
|
||||
_hardIndex_To = pairIndex;
|
||||
// we could return NULL as stream, but it's better to return real stream
|
||||
// return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ProcessedItemsStatuses)
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
NSynchronization::CCriticalSectionLock lock(CS);
|
||||
#endif
|
||||
ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
|
||||
}
|
||||
*inStream = inStreamLoc.Detach();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return Callback->SetOperationResult(opRes);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return GetStream2(index, inStream,
|
||||
(*UpdatePairs)[index].ArcIndex < 0 ?
|
||||
NUpdateNotifyOp::kAdd :
|
||||
NUpdateNotifyOp::kUpdate);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
bool isDir = false;
|
||||
|
||||
if (indexType == NArchive::NEventIndexType::kOutArcIndex)
|
||||
{
|
||||
UString name;
|
||||
if (index != (UInt32)(Int32)-1)
|
||||
{
|
||||
const CUpdatePair2 &up = (*UpdatePairs)[index];
|
||||
if (up.ExistOnDisk())
|
||||
{
|
||||
name = DirItems->GetLogPath(up.DirIndex);
|
||||
isDir = DirItems->Items[up.DirIndex].IsDir();
|
||||
}
|
||||
}
|
||||
return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
|
||||
}
|
||||
|
||||
wchar_t temp[16];
|
||||
UString s2;
|
||||
const wchar_t *s = NULL;
|
||||
|
||||
if (indexType == NArchive::NEventIndexType::kInArcIndex)
|
||||
{
|
||||
if (index != (UInt32)(Int32)-1)
|
||||
{
|
||||
if (ArcItems)
|
||||
{
|
||||
const CArcItem &ai = (*ArcItems)[index];
|
||||
s = ai.Name;
|
||||
isDir = ai.IsDir;
|
||||
}
|
||||
else if (Arc)
|
||||
{
|
||||
RINOK(Arc->GetItemPath(index, s2));
|
||||
s = s2;
|
||||
RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (indexType == NArchive::NEventIndexType::kBlockIndex)
|
||||
{
|
||||
temp[0] = '#';
|
||||
ConvertUInt32ToString(index, temp + 1);
|
||||
s = temp;
|
||||
}
|
||||
|
||||
if (!s)
|
||||
s = L"";
|
||||
|
||||
return Callback->ReportUpdateOpeartion(op, s, isDir);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
bool isEncrypted = false;
|
||||
wchar_t temp[16];
|
||||
UString s2;
|
||||
const wchar_t *s = NULL;
|
||||
|
||||
if (indexType == NArchive::NEventIndexType::kOutArcIndex)
|
||||
{
|
||||
/*
|
||||
UString name;
|
||||
if (index != (UInt32)(Int32)-1)
|
||||
{
|
||||
const CUpdatePair2 &up = (*UpdatePairs)[index];
|
||||
if (up.ExistOnDisk())
|
||||
{
|
||||
s2 = DirItems->GetLogPath(up.DirIndex);
|
||||
s = s2;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (indexType == NArchive::NEventIndexType::kInArcIndex)
|
||||
{
|
||||
if (index != (UInt32)(Int32)-1)
|
||||
{
|
||||
if (ArcItems)
|
||||
s = (*ArcItems)[index].Name;
|
||||
else if (Arc)
|
||||
{
|
||||
RINOK(Arc->GetItemPath(index, s2));
|
||||
s = s2;
|
||||
}
|
||||
if (Archive)
|
||||
{
|
||||
RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (indexType == NArchive::NEventIndexType::kBlockIndex)
|
||||
{
|
||||
temp[0] = '#';
|
||||
ConvertUInt32ToString(index, temp + 1);
|
||||
s = temp;
|
||||
}
|
||||
|
||||
return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
|
||||
{
|
||||
if (VolumesSizes.Size() == 0)
|
||||
return S_FALSE;
|
||||
if (index >= (UInt32)VolumesSizes.Size())
|
||||
index = VolumesSizes.Size() - 1;
|
||||
*size = VolumesSizes[index];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(index + 1, temp);
|
||||
FString res (temp);
|
||||
while (res.Len() < 2)
|
||||
res.InsertAtFront(FTEXT('0'));
|
||||
FString fileName = VolName;
|
||||
fileName += '.';
|
||||
fileName += res;
|
||||
fileName += VolExt;
|
||||
COutFileStream *streamSpec = new COutFileStream;
|
||||
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
|
||||
if (!streamSpec->Create(fileName, false))
|
||||
return ::GetLastError();
|
||||
*volumeStream = streamLoc.Detach();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return Callback->CryptoGetTextPassword(password);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
|
||||
{
|
||||
if (error == ERROR_LOCK_VIOLATION)
|
||||
{
|
||||
MT_LOCK
|
||||
UInt32 index = (UInt32)val;
|
||||
FOR_VECTOR(i, _openFiles_Indexes)
|
||||
{
|
||||
if (_openFiles_Indexes[i] == index)
|
||||
{
|
||||
RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val)
|
||||
{
|
||||
MT_LOCK
|
||||
UInt32 index = (UInt32)val;
|
||||
FOR_VECTOR(i, _openFiles_Indexes)
|
||||
{
|
||||
if (_openFiles_Indexes[i] == index)
|
||||
{
|
||||
_openFiles_Indexes.Delete(i);
|
||||
_openFiles_Paths.Delete(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw 20141125;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// UpdateCallback.h
|
||||
|
||||
#ifndef __UPDATE_CALLBACK_H
|
||||
#define __UPDATE_CALLBACK_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
#include "../Common/UpdatePair.h"
|
||||
#include "../Common/UpdateProduce.h"
|
||||
|
||||
#include "OpenArchive.h"
|
||||
|
||||
struct CArcToDoStat
|
||||
{
|
||||
CDirItemsStat2 NewData;
|
||||
CDirItemsStat2 OldData;
|
||||
CDirItemsStat2 DeleteData;
|
||||
|
||||
UInt64 Get_NumDataItems_Total() const
|
||||
{
|
||||
return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2();
|
||||
}
|
||||
};
|
||||
|
||||
#define INTERFACE_IUpdateCallbackUI(x) \
|
||||
virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \
|
||||
virtual HRESULT SetTotal(UInt64 size) x; \
|
||||
virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
|
||||
virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \
|
||||
virtual HRESULT CheckBreak() x; \
|
||||
/* virtual HRESULT Finalize() x; */ \
|
||||
virtual HRESULT SetNumItems(const CArcToDoStat &stat) x; \
|
||||
virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \
|
||||
virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
|
||||
virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \
|
||||
virtual HRESULT SetOperationResult(Int32 opRes) x; \
|
||||
virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \
|
||||
virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \
|
||||
/* virtual HRESULT SetPassword(const UString &password) x; */ \
|
||||
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
|
||||
virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
|
||||
virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \
|
||||
/* virtual HRESULT CloseProgress() { return S_OK; } */
|
||||
|
||||
struct IUpdateCallbackUI
|
||||
{
|
||||
INTERFACE_IUpdateCallbackUI(=0)
|
||||
};
|
||||
|
||||
struct CKeyKeyValPair
|
||||
{
|
||||
UInt64 Key1;
|
||||
UInt64 Key2;
|
||||
unsigned Value;
|
||||
|
||||
int Compare(const CKeyKeyValPair &a) const
|
||||
{
|
||||
if (Key1 < a.Key1) return -1;
|
||||
if (Key1 > a.Key1) return 1;
|
||||
return MyCompare(Key2, a.Key2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CArchiveUpdateCallback:
|
||||
public IArchiveUpdateCallback2,
|
||||
public IArchiveUpdateCallbackFile,
|
||||
public IArchiveExtractCallbackMessage,
|
||||
public IArchiveGetRawProps,
|
||||
public IArchiveGetRootProps,
|
||||
public ICryptoGetTextPassword2,
|
||||
public ICryptoGetTextPassword,
|
||||
public ICompressProgressInfo,
|
||||
public IInFileStream_Callback,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
bool _saclEnabled;
|
||||
#endif
|
||||
CRecordVector<CKeyKeyValPair> _map;
|
||||
|
||||
UInt32 _hardIndex_From;
|
||||
UInt32 _hardIndex_To;
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps)
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword2)
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
|
||||
INTERFACE_IArchiveUpdateCallback2(;)
|
||||
INTERFACE_IArchiveUpdateCallbackFile(;)
|
||||
INTERFACE_IArchiveExtractCallbackMessage(;)
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
INTERFACE_IArchiveGetRootProps(;)
|
||||
|
||||
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
|
||||
CRecordVector<UInt32> _openFiles_Indexes;
|
||||
FStringVector _openFiles_Paths;
|
||||
|
||||
bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }
|
||||
virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error);
|
||||
virtual void InFileStream_On_Destroy(UINT_PTR val);
|
||||
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
FString VolName;
|
||||
FString VolExt;
|
||||
|
||||
IUpdateCallbackUI *Callback;
|
||||
|
||||
const CDirItems *DirItems;
|
||||
const CDirItem *ParentDirItem;
|
||||
|
||||
const CArc *Arc;
|
||||
CMyComPtr<IInArchive> Archive;
|
||||
const CObjectVector<CArcItem> *ArcItems;
|
||||
const CRecordVector<CUpdatePair2> *UpdatePairs;
|
||||
const UStringVector *NewNames;
|
||||
int CommentIndex;
|
||||
const UString *Comment;
|
||||
|
||||
bool ShareForWrite;
|
||||
bool StopAfterOpenError;
|
||||
bool StdInMode;
|
||||
|
||||
bool KeepOriginalItemNames;
|
||||
bool StoreNtSecurity;
|
||||
bool StoreHardLinks;
|
||||
bool StoreSymLinks;
|
||||
|
||||
Byte *ProcessedItemsStatuses;
|
||||
|
||||
|
||||
CArchiveUpdateCallback();
|
||||
|
||||
bool IsDir(const CUpdatePair2 &up) const
|
||||
{
|
||||
if (up.DirIndex >= 0)
|
||||
return DirItems->Items[up.DirIndex].IsDir();
|
||||
else if (up.ArcIndex >= 0)
|
||||
return (*ArcItems)[up.ArcIndex].IsDir;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,233 @@
|
||||
// UpdatePair.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "SortUtils.h"
|
||||
#include "UpdatePair.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
|
||||
{
|
||||
switch (fileTimeType)
|
||||
{
|
||||
case NFileTimeType::kWindows:
|
||||
return ::CompareFileTime(&time1, &time2);
|
||||
case NFileTimeType::kUnix:
|
||||
{
|
||||
UInt32 unixTime1, unixTime2;
|
||||
FileTimeToUnixTime(time1, unixTime1);
|
||||
FileTimeToUnixTime(time2, unixTime2);
|
||||
return MyCompare(unixTime1, unixTime2);
|
||||
}
|
||||
case NFileTimeType::kDOS:
|
||||
{
|
||||
UInt32 dosTime1, dosTime2;
|
||||
FileTimeToDosTime(time1, dosTime1);
|
||||
FileTimeToDosTime(time2, dosTime2);
|
||||
return MyCompare(dosTime1, dosTime2);
|
||||
}
|
||||
}
|
||||
throw 4191618;
|
||||
}
|
||||
|
||||
static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:";
|
||||
static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:";
|
||||
static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
|
||||
|
||||
static void ThrowError(const char *message, const UString &s1, const UString &s2)
|
||||
{
|
||||
UString m (message);
|
||||
m.Add_LF(); m += s1;
|
||||
m.Add_LF(); m += s2;
|
||||
throw m;
|
||||
}
|
||||
|
||||
static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
|
||||
{
|
||||
int res = CompareFileNames(ai1.Name, ai2.Name);
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (ai1.IsDir != ai2.IsDir)
|
||||
return ai1.IsDir ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)
|
||||
{
|
||||
unsigned i1 = *p1;
|
||||
unsigned i2 = *p2;
|
||||
const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
|
||||
int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);
|
||||
if (res != 0)
|
||||
return res;
|
||||
return MyCompare(i1, i2);
|
||||
}
|
||||
|
||||
void GetUpdatePairInfoList(
|
||||
const CDirItems &dirItems,
|
||||
const CObjectVector<CArcItem> &arcItems,
|
||||
NFileTimeType::EEnum fileTimeType,
|
||||
CRecordVector<CUpdatePair> &updatePairs)
|
||||
{
|
||||
CUIntVector dirIndices, arcIndices;
|
||||
|
||||
unsigned numDirItems = dirItems.Items.Size();
|
||||
unsigned numArcItems = arcItems.Size();
|
||||
|
||||
CIntArr duplicatedArcItem(numArcItems);
|
||||
{
|
||||
int *vals = &duplicatedArcItem[0];
|
||||
for (unsigned i = 0; i < numArcItems; i++)
|
||||
vals[i] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
arcIndices.ClearAndSetSize(numArcItems);
|
||||
if (numArcItems != 0)
|
||||
{
|
||||
unsigned *vals = &arcIndices[0];
|
||||
for (unsigned i = 0; i < numArcItems; i++)
|
||||
vals[i] = i;
|
||||
}
|
||||
arcIndices.Sort(CompareArcItems, (void *)&arcItems);
|
||||
for (unsigned i = 0; i + 1 < numArcItems; i++)
|
||||
if (CompareArcItemsBase(
|
||||
arcItems[arcIndices[i]],
|
||||
arcItems[arcIndices[i + 1]]) == 0)
|
||||
{
|
||||
duplicatedArcItem[i] = 1;
|
||||
duplicatedArcItem[i + 1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
UStringVector dirNames;
|
||||
{
|
||||
dirNames.ClearAndReserve(numDirItems);
|
||||
unsigned i;
|
||||
for (i = 0; i < numDirItems; i++)
|
||||
dirNames.AddInReserved(dirItems.GetLogPath(i));
|
||||
SortFileNames(dirNames, dirIndices);
|
||||
for (i = 0; i + 1 < numDirItems; i++)
|
||||
{
|
||||
const UString &s1 = dirNames[dirIndices[i]];
|
||||
const UString &s2 = dirNames[dirIndices[i + 1]];
|
||||
if (CompareFileNames(s1, s2) == 0)
|
||||
ThrowError(k_Duplicate_inDir_Message, s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned dirIndex = 0;
|
||||
unsigned arcIndex = 0;
|
||||
|
||||
int prevHostFile = -1;
|
||||
const UString *prevHostName = NULL;
|
||||
|
||||
while (dirIndex < numDirItems || arcIndex < numArcItems)
|
||||
{
|
||||
CUpdatePair pair;
|
||||
|
||||
int dirIndex2 = -1;
|
||||
int arcIndex2 = -1;
|
||||
const CDirItem *di = NULL;
|
||||
const CArcItem *ai = NULL;
|
||||
|
||||
int compareResult = -1;
|
||||
const UString *name = NULL;
|
||||
|
||||
if (dirIndex < numDirItems)
|
||||
{
|
||||
dirIndex2 = dirIndices[dirIndex];
|
||||
di = &dirItems.Items[dirIndex2];
|
||||
}
|
||||
|
||||
if (arcIndex < numArcItems)
|
||||
{
|
||||
arcIndex2 = arcIndices[arcIndex];
|
||||
ai = &arcItems[arcIndex2];
|
||||
compareResult = 1;
|
||||
if (dirIndex < numDirItems)
|
||||
{
|
||||
compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name);
|
||||
if (compareResult == 0)
|
||||
{
|
||||
if (di->IsDir() != ai->IsDir)
|
||||
compareResult = (ai->IsDir ? 1 : -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (compareResult < 0)
|
||||
{
|
||||
name = &dirNames[dirIndex2];
|
||||
pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
|
||||
pair.DirIndex = dirIndex2;
|
||||
dirIndex++;
|
||||
}
|
||||
else if (compareResult > 0)
|
||||
{
|
||||
name = &ai->Name;
|
||||
pair.State = ai->Censored ?
|
||||
NUpdateArchive::NPairState::kOnlyInArchive:
|
||||
NUpdateArchive::NPairState::kNotMasked;
|
||||
pair.ArcIndex = arcIndex2;
|
||||
arcIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int dupl = duplicatedArcItem[arcIndex];
|
||||
if (dupl != 0)
|
||||
ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name);
|
||||
|
||||
name = &dirNames[dirIndex2];
|
||||
if (!ai->Censored)
|
||||
ThrowError(k_NotCensoredCollision_Message, *name, ai->Name);
|
||||
|
||||
pair.DirIndex = dirIndex2;
|
||||
pair.ArcIndex = arcIndex2;
|
||||
|
||||
switch (ai->MTimeDefined ? MyCompareTime(
|
||||
ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType,
|
||||
di->MTime, ai->MTime): 0)
|
||||
{
|
||||
case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
|
||||
case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
|
||||
default:
|
||||
pair.State = (ai->SizeDefined && di->Size == ai->Size) ?
|
||||
NUpdateArchive::NPairState::kSameFiles :
|
||||
NUpdateArchive::NPairState::kUnknowNewerFiles;
|
||||
}
|
||||
|
||||
dirIndex++;
|
||||
arcIndex++;
|
||||
}
|
||||
|
||||
if ((di && di->IsAltStream) ||
|
||||
(ai && ai->IsAltStream))
|
||||
{
|
||||
if (prevHostName)
|
||||
{
|
||||
unsigned hostLen = prevHostName->Len();
|
||||
if (name->Len() > hostLen)
|
||||
if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0)
|
||||
pair.HostIndex = prevHostFile;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prevHostFile = updatePairs.Size();
|
||||
prevHostName = name;
|
||||
}
|
||||
|
||||
updatePairs.Add(pair);
|
||||
}
|
||||
|
||||
updatePairs.ReserveDown();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// UpdatePair.h
|
||||
|
||||
#ifndef __UPDATE_PAIR_H
|
||||
#define __UPDATE_PAIR_H
|
||||
|
||||
#include "DirItem.h"
|
||||
#include "UpdateAction.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
struct CUpdatePair
|
||||
{
|
||||
NUpdateArchive::NPairState::EEnum State;
|
||||
int ArcIndex;
|
||||
int DirIndex;
|
||||
int HostIndex; // >= 0 for alt streams only, contains index of host pair
|
||||
|
||||
CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {}
|
||||
};
|
||||
|
||||
void GetUpdatePairInfoList(
|
||||
const CDirItems &dirItems,
|
||||
const CObjectVector<CArcItem> &arcItems,
|
||||
NFileTimeType::EEnum fileTimeType,
|
||||
CRecordVector<CUpdatePair> &updatePairs);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
// UpdateProduce.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "UpdateProduce.h"
|
||||
|
||||
using namespace NUpdateArchive;
|
||||
|
||||
static const char * const kUpdateActionSetCollision = "Internal collision in update action set";
|
||||
|
||||
void UpdateProduce(
|
||||
const CRecordVector<CUpdatePair> &updatePairs,
|
||||
const CActionSet &actionSet,
|
||||
CRecordVector<CUpdatePair2> &operationChain,
|
||||
IUpdateProduceCallback *callback)
|
||||
{
|
||||
FOR_VECTOR (i, updatePairs)
|
||||
{
|
||||
const CUpdatePair &pair = updatePairs[i];
|
||||
|
||||
CUpdatePair2 up2;
|
||||
up2.DirIndex = pair.DirIndex;
|
||||
up2.ArcIndex = pair.ArcIndex;
|
||||
up2.NewData = up2.NewProps = true;
|
||||
up2.UseArcProps = false;
|
||||
|
||||
switch (actionSet.StateActions[(unsigned)pair.State])
|
||||
{
|
||||
case NPairAction::kIgnore:
|
||||
if (pair.ArcIndex >= 0 && callback)
|
||||
callback->ShowDeleteFile(pair.ArcIndex);
|
||||
continue;
|
||||
|
||||
case NPairAction::kCopy:
|
||||
if (pair.State == NPairState::kOnlyOnDisk)
|
||||
throw kUpdateActionSetCollision;
|
||||
if (pair.State == NPairState::kOnlyInArchive)
|
||||
{
|
||||
if (pair.HostIndex >= 0)
|
||||
{
|
||||
/*
|
||||
ignore alt stream if
|
||||
1) no such alt stream in Disk
|
||||
2) there is Host file in disk
|
||||
*/
|
||||
if (updatePairs[pair.HostIndex].DirIndex >= 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
up2.NewData = up2.NewProps = false;
|
||||
up2.UseArcProps = true;
|
||||
break;
|
||||
|
||||
case NPairAction::kCompress:
|
||||
if (pair.State == NPairState::kOnlyInArchive ||
|
||||
pair.State == NPairState::kNotMasked)
|
||||
throw kUpdateActionSetCollision;
|
||||
break;
|
||||
|
||||
case NPairAction::kCompressAsAnti:
|
||||
up2.IsAnti = true;
|
||||
up2.UseArcProps = (pair.ArcIndex >= 0);
|
||||
break;
|
||||
}
|
||||
|
||||
operationChain.Add(up2);
|
||||
}
|
||||
|
||||
operationChain.ReserveDown();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// UpdateProduce.h
|
||||
|
||||
#ifndef __UPDATE_PRODUCE_H
|
||||
#define __UPDATE_PRODUCE_H
|
||||
|
||||
#include "UpdatePair.h"
|
||||
|
||||
struct CUpdatePair2
|
||||
{
|
||||
bool NewData;
|
||||
bool NewProps;
|
||||
bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties.
|
||||
bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status
|
||||
|
||||
int DirIndex;
|
||||
int ArcIndex;
|
||||
int NewNameIndex;
|
||||
|
||||
bool IsMainRenameItem;
|
||||
|
||||
void SetAs_NoChangeArcItem(int arcIndex)
|
||||
{
|
||||
NewData = NewProps = false;
|
||||
UseArcProps = true;
|
||||
IsAnti = false;
|
||||
ArcIndex = arcIndex;
|
||||
}
|
||||
|
||||
bool ExistOnDisk() const { return DirIndex != -1; }
|
||||
bool ExistInArchive() const { return ArcIndex != -1; }
|
||||
|
||||
CUpdatePair2():
|
||||
NewData(false),
|
||||
NewProps(false),
|
||||
UseArcProps(false),
|
||||
IsAnti(false),
|
||||
DirIndex(-1),
|
||||
ArcIndex(-1),
|
||||
NewNameIndex(-1),
|
||||
IsMainRenameItem(false)
|
||||
{}
|
||||
};
|
||||
|
||||
struct IUpdateProduceCallback
|
||||
{
|
||||
virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;
|
||||
};
|
||||
|
||||
void UpdateProduce(
|
||||
const CRecordVector<CUpdatePair> &updatePairs,
|
||||
const NUpdateArchive::CActionSet &actionSet,
|
||||
CRecordVector<CUpdatePair2> &operationChain,
|
||||
IUpdateProduceCallback *callback);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
// WorkDir.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/StringConvert.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileName.h"
|
||||
|
||||
#include "WorkDir.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName)
|
||||
{
|
||||
NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (workDirInfo.ForRemovableOnly)
|
||||
{
|
||||
mode = NWorkDir::NMode::kCurrent;
|
||||
FString prefix = path.Left(3);
|
||||
if (prefix[1] == FTEXT(':') && prefix[2] == FTEXT('\\'))
|
||||
{
|
||||
UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP));
|
||||
if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)
|
||||
mode = workDirInfo.Mode;
|
||||
}
|
||||
/*
|
||||
CParsedPath parsedPath;
|
||||
parsedPath.ParsePath(archiveName);
|
||||
UINT driveType = GetDriveType(parsedPath.Prefix);
|
||||
if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))
|
||||
mode = NZipSettings::NWorkDir::NMode::kCurrent;
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
int pos = path.ReverseFind_PathSepar() + 1;
|
||||
fileName = path.Ptr(pos);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case NWorkDir::NMode::kCurrent:
|
||||
{
|
||||
return path.Left(pos);
|
||||
}
|
||||
case NWorkDir::NMode::kSpecified:
|
||||
{
|
||||
FString tempDir = workDirInfo.Path;
|
||||
NName::NormalizeDirPathPrefix(tempDir);
|
||||
return tempDir;
|
||||
}
|
||||
default:
|
||||
{
|
||||
FString tempDir;
|
||||
if (!MyGetTempPath(tempDir))
|
||||
throw 141717;
|
||||
return tempDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath)
|
||||
{
|
||||
NWorkDir::CInfo workDirInfo;
|
||||
workDirInfo.Load();
|
||||
FString namePart;
|
||||
FString workDir = GetWorkDir(workDirInfo, originalPath, namePart);
|
||||
CreateComplexDir(workDir);
|
||||
CTempFile tempFile;
|
||||
_outStreamSpec = new COutFileStream;
|
||||
OutStream = _outStreamSpec;
|
||||
if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return error ? error : E_FAIL;
|
||||
}
|
||||
_originalPath = originalPath;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal)
|
||||
{
|
||||
OutStream.Release();
|
||||
if (!_tempFile.MoveTo(_originalPath, deleteOriginal))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return error ? error : E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// WorkDir.h
|
||||
|
||||
#ifndef __WORK_DIR_H
|
||||
#define __WORK_DIR_H
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
#include "ZipRegistry.h"
|
||||
|
||||
FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName);
|
||||
|
||||
class CWorkDirTempFile
|
||||
{
|
||||
FString _originalPath;
|
||||
NWindows::NFile::NDir::CTempFile _tempFile;
|
||||
COutFileStream *_outStreamSpec;
|
||||
public:
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
|
||||
HRESULT CreateTempFile(const FString &originalPath);
|
||||
HRESULT MoveToOriginal(bool deleteOriginal);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,399 @@
|
||||
// ZipRegistry.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/Registry.h"
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
|
||||
#include "ZipRegistry.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NRegistry;
|
||||
|
||||
static NSynchronization::CCriticalSection g_CS;
|
||||
#define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS);
|
||||
|
||||
static LPCTSTR const kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR);
|
||||
|
||||
static CSysString GetKeyPath(LPCTSTR path) { return kCuPrefix + (CSysString)path; }
|
||||
|
||||
static LONG OpenMainKey(CKey &key, LPCTSTR keyName)
|
||||
{
|
||||
return key.Open(HKEY_CURRENT_USER, GetKeyPath(keyName), KEY_READ);
|
||||
}
|
||||
|
||||
static LONG CreateMainKey(CKey &key, LPCTSTR keyName)
|
||||
{
|
||||
return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName));
|
||||
}
|
||||
|
||||
static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b)
|
||||
{
|
||||
if (b.Def)
|
||||
key.SetValue(name, b.Val);
|
||||
}
|
||||
|
||||
static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b)
|
||||
{
|
||||
b.Val = false;
|
||||
b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b)
|
||||
{
|
||||
b.Val = true;
|
||||
b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
namespace NExtract
|
||||
{
|
||||
|
||||
static LPCTSTR const kKeyName = TEXT("Extraction");
|
||||
|
||||
static LPCTSTR const kExtractMode = TEXT("ExtractMode");
|
||||
static LPCTSTR const kOverwriteMode = TEXT("OverwriteMode");
|
||||
static LPCTSTR const kShowPassword = TEXT("ShowPassword");
|
||||
static LPCTSTR const kPathHistory = TEXT("PathHistory");
|
||||
static LPCTSTR const kSplitDest = TEXT("SplitDest");
|
||||
static LPCTSTR const kElimDup = TEXT("ElimDup");
|
||||
// static LPCTSTR const kAltStreams = TEXT("AltStreams");
|
||||
static LPCTSTR const kNtSecur = TEXT("Security");
|
||||
|
||||
void CInfo::Save() const
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
|
||||
if (PathMode_Force)
|
||||
key.SetValue(kExtractMode, (UInt32)PathMode);
|
||||
if (OverwriteMode_Force)
|
||||
key.SetValue(kOverwriteMode, (UInt32)OverwriteMode);
|
||||
|
||||
Key_Set_BoolPair(key, kSplitDest, SplitDest);
|
||||
Key_Set_BoolPair(key, kElimDup, ElimDup);
|
||||
// Key_Set_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Set_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Set_BoolPair(key, kShowPassword, ShowPassword);
|
||||
|
||||
key.RecurseDeleteKey(kPathHistory);
|
||||
key.SetValue_Strings(kPathHistory, Paths);
|
||||
}
|
||||
|
||||
void Save_ShowPassword(bool showPassword)
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
key.SetValue(kShowPassword, showPassword);
|
||||
}
|
||||
|
||||
void CInfo::Load()
|
||||
{
|
||||
PathMode = NPathMode::kCurPaths;
|
||||
PathMode_Force = false;
|
||||
OverwriteMode = NOverwriteMode::kAsk;
|
||||
OverwriteMode_Force = false;
|
||||
|
||||
SplitDest.Val = true;
|
||||
|
||||
Paths.Clear();
|
||||
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
key.GetValue_Strings(kPathHistory, Paths);
|
||||
UInt32 v;
|
||||
if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths)
|
||||
{
|
||||
PathMode = (NPathMode::EEnum)v;
|
||||
PathMode_Force = true;
|
||||
}
|
||||
if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting)
|
||||
{
|
||||
OverwriteMode = (NOverwriteMode::EEnum)v;
|
||||
OverwriteMode_Force = true;
|
||||
}
|
||||
|
||||
Key_Get_BoolPair_true(key, kSplitDest, SplitDest);
|
||||
|
||||
Key_Get_BoolPair(key, kElimDup, ElimDup);
|
||||
// Key_Get_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Get_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Get_BoolPair(key, kShowPassword, ShowPassword);
|
||||
}
|
||||
|
||||
bool Read_ShowPassword()
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
bool showPassword = false;
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return showPassword;
|
||||
key.GetValue_IfOk(kShowPassword, showPassword);
|
||||
return showPassword;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace NCompression
|
||||
{
|
||||
|
||||
static LPCTSTR const kKeyName = TEXT("Compression");
|
||||
|
||||
static LPCTSTR const kArcHistory = TEXT("ArcHistory");
|
||||
static LPCWSTR const kArchiver = L"Archiver";
|
||||
static LPCTSTR const kShowPassword = TEXT("ShowPassword");
|
||||
static LPCTSTR const kEncryptHeaders = TEXT("EncryptHeaders");
|
||||
|
||||
static LPCTSTR const kOptionsKeyName = TEXT("Options");
|
||||
|
||||
static LPCTSTR const kLevel = TEXT("Level");
|
||||
static LPCTSTR const kDictionary = TEXT("Dictionary");
|
||||
static LPCTSTR const kOrder = TEXT("Order");
|
||||
static LPCTSTR const kBlockSize = TEXT("BlockSize");
|
||||
static LPCTSTR const kNumThreads = TEXT("NumThreads");
|
||||
static LPCWSTR const kMethod = L"Method";
|
||||
static LPCWSTR const kOptions = L"Options";
|
||||
static LPCWSTR const kEncryptionMethod = L"EncryptionMethod";
|
||||
|
||||
static LPCTSTR const kNtSecur = TEXT("Security");
|
||||
static LPCTSTR const kAltStreams = TEXT("AltStreams");
|
||||
static LPCTSTR const kHardLinks = TEXT("HardLinks");
|
||||
static LPCTSTR const kSymLinks = TEXT("SymLinks");
|
||||
|
||||
static void SetRegString(CKey &key, LPCWSTR name, const UString &value)
|
||||
{
|
||||
if (value.IsEmpty())
|
||||
key.DeleteValue(name);
|
||||
else
|
||||
key.SetValue(name, value);
|
||||
}
|
||||
|
||||
static void SetRegUInt32(CKey &key, LPCTSTR name, UInt32 value)
|
||||
{
|
||||
if (value == (UInt32)(Int32)-1)
|
||||
key.DeleteValue(name);
|
||||
else
|
||||
key.SetValue(name, value);
|
||||
}
|
||||
|
||||
static void GetRegString(CKey &key, LPCWSTR name, UString &value)
|
||||
{
|
||||
if (key.QueryValue(name, value) != ERROR_SUCCESS)
|
||||
value.Empty();
|
||||
}
|
||||
|
||||
static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value)
|
||||
{
|
||||
if (key.QueryValue(name, value) != ERROR_SUCCESS)
|
||||
value = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
void CInfo::Save() const
|
||||
{
|
||||
CS_LOCK
|
||||
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
|
||||
Key_Set_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Set_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Set_BoolPair(key, kHardLinks, HardLinks);
|
||||
Key_Set_BoolPair(key, kSymLinks, SymLinks);
|
||||
|
||||
key.SetValue(kShowPassword, ShowPassword);
|
||||
key.SetValue(kLevel, (UInt32)Level);
|
||||
key.SetValue(kArchiver, ArcType);
|
||||
key.SetValue(kShowPassword, ShowPassword);
|
||||
key.SetValue(kEncryptHeaders, EncryptHeaders);
|
||||
key.RecurseDeleteKey(kArcHistory);
|
||||
key.SetValue_Strings(kArcHistory, ArcPaths);
|
||||
|
||||
key.RecurseDeleteKey(kOptionsKeyName);
|
||||
{
|
||||
CKey optionsKey;
|
||||
optionsKey.Create(key, kOptionsKeyName);
|
||||
FOR_VECTOR (i, Formats)
|
||||
{
|
||||
const CFormatOptions &fo = Formats[i];
|
||||
CKey fk;
|
||||
fk.Create(optionsKey, fo.FormatID);
|
||||
|
||||
SetRegUInt32(fk, kLevel, fo.Level);
|
||||
SetRegUInt32(fk, kDictionary, fo.Dictionary);
|
||||
SetRegUInt32(fk, kOrder, fo.Order);
|
||||
SetRegUInt32(fk, kBlockSize, fo.BlockLogSize);
|
||||
SetRegUInt32(fk, kNumThreads, fo.NumThreads);
|
||||
|
||||
SetRegString(fk, kMethod, fo.Method);
|
||||
SetRegString(fk, kOptions, fo.Options);
|
||||
SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInfo::Load()
|
||||
{
|
||||
ArcPaths.Clear();
|
||||
Formats.Clear();
|
||||
|
||||
Level = 5;
|
||||
ArcType = L"7z";
|
||||
ShowPassword = false;
|
||||
EncryptHeaders = false;
|
||||
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
Key_Get_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Get_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Get_BoolPair(key, kHardLinks, HardLinks);
|
||||
Key_Get_BoolPair(key, kSymLinks, SymLinks);
|
||||
|
||||
key.GetValue_Strings(kArcHistory, ArcPaths);
|
||||
|
||||
{
|
||||
CKey optionsKey;
|
||||
if (optionsKey.Open(key, kOptionsKeyName, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
CSysStringVector formatIDs;
|
||||
optionsKey.EnumKeys(formatIDs);
|
||||
FOR_VECTOR (i, formatIDs)
|
||||
{
|
||||
CKey fk;
|
||||
CFormatOptions fo;
|
||||
fo.FormatID = formatIDs[i];
|
||||
if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
GetRegString(fk, kOptions, fo.Options);
|
||||
GetRegString(fk, kMethod, fo.Method);
|
||||
GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
|
||||
|
||||
GetRegUInt32(fk, kLevel, fo.Level);
|
||||
GetRegUInt32(fk, kDictionary, fo.Dictionary);
|
||||
GetRegUInt32(fk, kOrder, fo.Order);
|
||||
GetRegUInt32(fk, kBlockSize, fo.BlockLogSize);
|
||||
GetRegUInt32(fk, kNumThreads, fo.NumThreads);
|
||||
|
||||
Formats.Add(fo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UString a;
|
||||
if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS)
|
||||
ArcType = a;
|
||||
key.GetValue_IfOk(kLevel, Level);
|
||||
key.GetValue_IfOk(kShowPassword, ShowPassword);
|
||||
key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static LPCTSTR const kOptionsInfoKeyName = TEXT("Options");
|
||||
|
||||
namespace NWorkDir
|
||||
{
|
||||
static LPCTSTR const kWorkDirType = TEXT("WorkDirType");
|
||||
static LPCWSTR const kWorkDirPath = L"WorkDirPath";
|
||||
static LPCTSTR const kTempRemovableOnly = TEXT("TempRemovableOnly");
|
||||
|
||||
|
||||
void CInfo::Save()const
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kOptionsInfoKeyName);
|
||||
key.SetValue(kWorkDirType, (UInt32)Mode);
|
||||
key.SetValue(kWorkDirPath, fs2us(Path));
|
||||
key.SetValue(kTempRemovableOnly, ForRemovableOnly);
|
||||
}
|
||||
|
||||
void CInfo::Load()
|
||||
{
|
||||
SetDefault();
|
||||
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
UInt32 dirType;
|
||||
if (key.QueryValue(kWorkDirType, dirType) != ERROR_SUCCESS)
|
||||
return;
|
||||
switch (dirType)
|
||||
{
|
||||
case NMode::kSystem:
|
||||
case NMode::kCurrent:
|
||||
case NMode::kSpecified:
|
||||
Mode = (NMode::EEnum)dirType;
|
||||
}
|
||||
UString pathU;
|
||||
if (key.QueryValue(kWorkDirPath, pathU) == ERROR_SUCCESS)
|
||||
Path = us2fs(pathU);
|
||||
else
|
||||
{
|
||||
Path.Empty();
|
||||
if (Mode == NMode::kSpecified)
|
||||
Mode = NMode::kSystem;
|
||||
}
|
||||
key.GetValue_IfOk(kTempRemovableOnly, ForRemovableOnly);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static LPCTSTR const kCascadedMenu = TEXT("CascadedMenu");
|
||||
static LPCTSTR const kContextMenu = TEXT("ContextMenu");
|
||||
static LPCTSTR const kMenuIcons = TEXT("MenuIcons");
|
||||
static LPCTSTR const kElimDup = TEXT("ElimDupExtract");
|
||||
|
||||
void CContextMenuInfo::Save() const
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kOptionsInfoKeyName);
|
||||
|
||||
Key_Set_BoolPair(key, kCascadedMenu, Cascaded);
|
||||
Key_Set_BoolPair(key, kMenuIcons, MenuIcons);
|
||||
Key_Set_BoolPair(key, kElimDup, ElimDup);
|
||||
|
||||
if (Flags_Def)
|
||||
key.SetValue(kContextMenu, Flags);
|
||||
}
|
||||
|
||||
void CContextMenuInfo::Load()
|
||||
{
|
||||
Cascaded.Val = true;
|
||||
Cascaded.Def = false;
|
||||
|
||||
MenuIcons.Val = false;
|
||||
MenuIcons.Def = false;
|
||||
|
||||
ElimDup.Val = true;
|
||||
ElimDup.Def = false;
|
||||
|
||||
Flags = (UInt32)(Int32)-1;
|
||||
Flags_Def = false;
|
||||
|
||||
CS_LOCK
|
||||
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
Key_Get_BoolPair_true(key, kCascadedMenu, Cascaded);
|
||||
Key_Get_BoolPair_true(key, kElimDup, ElimDup);
|
||||
Key_Get_BoolPair(key, kMenuIcons, MenuIcons);
|
||||
|
||||
Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// ZipRegistry.h
|
||||
|
||||
#ifndef __ZIP_REGISTRY_H
|
||||
#define __ZIP_REGISTRY_H
|
||||
|
||||
#include "../../../Common/MyTypes.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "ExtractMode.h"
|
||||
|
||||
namespace NExtract
|
||||
{
|
||||
struct CInfo
|
||||
{
|
||||
NPathMode::EEnum PathMode;
|
||||
NOverwriteMode::EEnum OverwriteMode;
|
||||
bool PathMode_Force;
|
||||
bool OverwriteMode_Force;
|
||||
|
||||
CBoolPair SplitDest;
|
||||
CBoolPair ElimDup;
|
||||
// CBoolPair AltStreams;
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair ShowPassword;
|
||||
|
||||
UStringVector Paths;
|
||||
|
||||
void Save() const;
|
||||
void Load();
|
||||
};
|
||||
|
||||
void Save_ShowPassword(bool showPassword);
|
||||
bool Read_ShowPassword();
|
||||
}
|
||||
|
||||
namespace NCompression
|
||||
{
|
||||
struct CFormatOptions
|
||||
{
|
||||
UInt32 Level;
|
||||
UInt32 Dictionary;
|
||||
UInt32 Order;
|
||||
UInt32 BlockLogSize;
|
||||
UInt32 NumThreads;
|
||||
|
||||
CSysString FormatID;
|
||||
UString Method;
|
||||
UString Options;
|
||||
UString EncryptionMethod;
|
||||
|
||||
void Reset_BlockLogSize()
|
||||
{
|
||||
BlockLogSize = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
void ResetForLevelChange()
|
||||
{
|
||||
BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;
|
||||
Method.Empty();
|
||||
// Options.Empty();
|
||||
// EncryptionMethod.Empty();
|
||||
}
|
||||
CFormatOptions() { ResetForLevelChange(); }
|
||||
};
|
||||
|
||||
struct CInfo
|
||||
{
|
||||
UInt32 Level;
|
||||
bool ShowPassword;
|
||||
bool EncryptHeaders;
|
||||
UString ArcType;
|
||||
UStringVector ArcPaths;
|
||||
|
||||
CObjectVector<CFormatOptions> Formats;
|
||||
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair AltStreams;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
void Save() const;
|
||||
void Load();
|
||||
};
|
||||
}
|
||||
|
||||
namespace NWorkDir
|
||||
{
|
||||
namespace NMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kSystem,
|
||||
kCurrent,
|
||||
kSpecified
|
||||
};
|
||||
}
|
||||
struct CInfo
|
||||
{
|
||||
NMode::EEnum Mode;
|
||||
FString Path;
|
||||
bool ForRemovableOnly;
|
||||
|
||||
void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }
|
||||
void SetDefault()
|
||||
{
|
||||
Mode = NMode::kSystem;
|
||||
Path.Empty();
|
||||
SetForRemovableOnlyDefault();
|
||||
}
|
||||
|
||||
void Save() const;
|
||||
void Load();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
struct CContextMenuInfo
|
||||
{
|
||||
CBoolPair Cascaded;
|
||||
CBoolPair MenuIcons;
|
||||
CBoolPair ElimDup;
|
||||
|
||||
bool Flags_Def;
|
||||
UInt32 Flags;
|
||||
|
||||
void Save() const;
|
||||
void Load();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
// BenchCon.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../Common/Bench.h"
|
||||
|
||||
#include "BenchCon.h"
|
||||
#include "ConsoleClose.h"
|
||||
|
||||
struct CPrintBenchCallback: public IBenchPrintCallback
|
||||
{
|
||||
FILE *_file;
|
||||
|
||||
void Print(const char *s);
|
||||
void NewLine();
|
||||
HRESULT CheckBreak();
|
||||
};
|
||||
|
||||
void CPrintBenchCallback::Print(const char *s)
|
||||
{
|
||||
fputs(s, _file);
|
||||
}
|
||||
|
||||
void CPrintBenchCallback::NewLine()
|
||||
{
|
||||
fputc('\n', _file);
|
||||
}
|
||||
|
||||
HRESULT CPrintBenchCallback::CheckBreak()
|
||||
{
|
||||
return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK;
|
||||
}
|
||||
|
||||
HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f)
|
||||
{
|
||||
CPrintBenchCallback callback;
|
||||
callback._file = f;
|
||||
return Bench(EXTERNAL_CODECS_LOC_VARS
|
||||
&callback, NULL, props, numIterations, true);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// BenchCon.h
|
||||
|
||||
#ifndef __BENCH_CON_H
|
||||
#define __BENCH_CON_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../UI/Common/Property.h"
|
||||
|
||||
HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,984 @@
|
||||
# Microsoft Developer Studio Project File - Name="Console" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Console - Win32 DebugU
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Console.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Console.mak" CFG="Console - Win32 DebugU"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Console - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Console - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Console - Win32 ReleaseU" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Console - Win32 DebugU" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Console - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAcs /Yu"StdAfx.h" /FD /GF /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7z.exe" /OPT:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept /ignore:4033
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Console___Win32_ReleaseU"
|
||||
# PROP BASE Intermediate_Dir "Console___Win32_ReleaseU"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ReleaseU"
|
||||
# PROP Intermediate_Dir "ReleaseU"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7z.exe"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7zn.exe" /OPT:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 DebugU"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Console___Win32_DebugU"
|
||||
# PROP BASE Intermediate_Dir "Console___Win32_DebugU"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugU"
|
||||
# PROP Intermediate_Dir "DebugU"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Console - Win32 Release"
|
||||
# Name "Console - Win32 Debug"
|
||||
# Name "Console - Win32 ReleaseU"
|
||||
# Name "Console - Win32 DebugU"
|
||||
# Begin Group "Spec"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# ADD CPP /Yc"StdAfx.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Console"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BenchCon.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BenchCon.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ConsoleClose.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ConsoleClose.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExtractCallbackConsole.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExtractCallbackConsole.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\HashCon.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\HashCon.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\List.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\List.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Main.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MainAr.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\OpenCallbackConsole.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\OpenCallbackConsole.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\PercentPrinter.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\PercentPrinter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UpdateCallbackConsole.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UpdateCallbackConsole.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UserInputUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UserInputUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Windows"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\DLL.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\DLL.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\ErrorMsg.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\ErrorMsg.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileDir.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileDir.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileFind.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileFind.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileIO.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileIO.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileLink.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileMapping.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileName.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileName.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileSystem.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileSystem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\MemoryLock.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\MemoryLock.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\NtCheck.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariantConv.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariantConv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Registry.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Registry.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Synchronization.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Thread.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\TimeUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\TimeUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\CommandLineParser.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\CommandLineParser.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Common.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\ComTry.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\CRC.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Defs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\ListFileUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\ListFileUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyBuffer2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyCom.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyTypes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyVector.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\MyVector.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StdInStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StdInStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StdOutStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StdOutStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringConvert.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringToInt.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringToInt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\UTFConvert.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\UTFConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "UI Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ArchiveCommandLine.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ArchiveCommandLine.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ArchiveExtractCallback.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ArchiveExtractCallback.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ArchiveOpenCallback.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ArchiveOpenCallback.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Bench.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Bench.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\DefaultName.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\DefaultName.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\DirItem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\EnumDirItems.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\EnumDirItems.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ExitCode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Extract.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Extract.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ExtractingFilePath.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ExtractingFilePath.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ExtractMode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\HashCalc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\HashCalc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\IFileExtractCallback.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\LoadCodecs.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\LoadCodecs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\OpenArchive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\OpenArchive.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Property.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\PropIDUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\PropIDUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\SetProperties.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\SetProperties.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\SortUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\SortUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\TempFiles.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\TempFiles.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Update.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\Update.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdateAction.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdateAction.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdateCallback.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdateCallback.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdatePair.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdatePair.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdateProduce.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\UpdateProduce.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ZipRegistry.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "7-zip Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\CreateCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\CreateCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FilePathAutoRename.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FilePathAutoRename.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FileStreams.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FileStreams.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FilterCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FilterCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\LimitedStreams.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\LimitedStreams.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MethodProps.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MethodProps.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\PropId.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\RegisterArc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamObjects.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamObjects.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\UniqBlocks.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\UniqBlocks.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Compress"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\CopyCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\CopyCoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "C"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\7zCrc.c
|
||||
|
||||
!IF "$(CFG)" == "Console - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 DebugU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\7zCrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\7zTypes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Alloc.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\CpuArch.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\CpuArch.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\DllSecur.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\DllSecur.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Sort.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Sort.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Threads.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Threads.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "ArchiveCommon"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Asm"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\Asm\x86\7zAsm.asm
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\Asm\x86\7zCrcOpt.asm
|
||||
|
||||
!IF "$(CFG)" == "Console - Win32 Release"
|
||||
|
||||
# Begin Custom Build
|
||||
OutDir=.\Release
|
||||
InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm
|
||||
InputName=7zCrcOpt
|
||||
|
||||
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath)
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 Debug"
|
||||
|
||||
# Begin Custom Build
|
||||
OutDir=.\Debug
|
||||
InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm
|
||||
InputName=7zCrcOpt
|
||||
|
||||
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath)
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU"
|
||||
|
||||
# Begin Custom Build
|
||||
OutDir=.\ReleaseU
|
||||
InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm
|
||||
InputName=7zCrcOpt
|
||||
|
||||
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath)
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 DebugU"
|
||||
|
||||
# Begin Custom Build
|
||||
OutDir=.\DebugU
|
||||
InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm
|
||||
InputName=7zCrcOpt
|
||||
|
||||
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath)
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Interface"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\IArchive.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\ICoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\IDecl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\IPassword.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\IProgress.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\IStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\PropID.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Console"=".\Console.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
MY_CONSOLE = 1
|
||||
|
||||
!IFNDEF UNDER_CE
|
||||
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
|
||||
!ENDIF
|
||||
|
||||
CONSOLE_OBJS = \
|
||||
$O\BenchCon.obj \
|
||||
$O\ConsoleClose.obj \
|
||||
$O\ExtractCallbackConsole.obj \
|
||||
$O\HashCon.obj \
|
||||
$O\List.obj \
|
||||
$O\Main.obj \
|
||||
$O\MainAr.obj \
|
||||
$O\OpenCallbackConsole.obj \
|
||||
$O\PercentPrinter.obj \
|
||||
$O\UpdateCallbackConsole.obj \
|
||||
$O\UserInputUtils.obj \
|
||||
|
||||
UI_COMMON_OBJS = \
|
||||
$O\ArchiveCommandLine.obj \
|
||||
$O\ArchiveExtractCallback.obj \
|
||||
$O\ArchiveOpenCallback.obj \
|
||||
$O\Bench.obj \
|
||||
$O\DefaultName.obj \
|
||||
$O\EnumDirItems.obj \
|
||||
$O\Extract.obj \
|
||||
$O\ExtractingFilePath.obj \
|
||||
$O\HashCalc.obj \
|
||||
$O\LoadCodecs.obj \
|
||||
$O\OpenArchive.obj \
|
||||
$O\PropIDUtils.obj \
|
||||
$O\SetProperties.obj \
|
||||
$O\SortUtils.obj \
|
||||
$O\TempFiles.obj \
|
||||
$O\Update.obj \
|
||||
$O\UpdateAction.obj \
|
||||
$O\UpdateCallback.obj \
|
||||
$O\UpdatePair.obj \
|
||||
$O\UpdateProduce.obj \
|
||||
|
||||
C_OBJS = $(C_OBJS) \
|
||||
$O\DllSecur.obj \
|
||||
@@ -0,0 +1,13 @@
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7z" type="win32"></assemblyIdentity>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false">
|
||||
</requestedExecutionLevel></requestedPrivileges></security></trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
|
||||
<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
</application></compatibility>
|
||||
</assembly>
|
||||
@@ -0,0 +1,69 @@
|
||||
// ConsoleClose.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
|
||||
#if !defined(UNDER_CE) && defined(_WIN32)
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#endif
|
||||
|
||||
namespace NConsoleClose {
|
||||
|
||||
unsigned g_BreakCounter = 0;
|
||||
static const unsigned kBreakAbortThreshold = 2;
|
||||
|
||||
#if !defined(UNDER_CE) && defined(_WIN32)
|
||||
static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
|
||||
{
|
||||
if (ctrlType == CTRL_LOGOFF_EVENT)
|
||||
{
|
||||
// printf("\nCTRL_LOGOFF_EVENT\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_BreakCounter++;
|
||||
if (g_BreakCounter < kBreakAbortThreshold)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
/*
|
||||
switch (ctrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
if (g_BreakCounter < kBreakAbortThreshold)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
void CheckCtrlBreak()
|
||||
{
|
||||
if (TestBreakSignal())
|
||||
throw CCtrlBreakException();
|
||||
}
|
||||
*/
|
||||
|
||||
CCtrlHandlerSetter::CCtrlHandlerSetter()
|
||||
{
|
||||
#if !defined(UNDER_CE) && defined(_WIN32)
|
||||
if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
|
||||
throw "SetConsoleCtrlHandler fails";
|
||||
#endif
|
||||
}
|
||||
|
||||
CCtrlHandlerSetter::~CCtrlHandlerSetter()
|
||||
{
|
||||
#if !defined(UNDER_CE) && defined(_WIN32)
|
||||
if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE))
|
||||
{
|
||||
// warning for throw in destructor.
|
||||
// throw "SetConsoleCtrlHandler fails";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// ConsoleClose.h
|
||||
|
||||
#ifndef __CONSOLE_CLOSE_H
|
||||
#define __CONSOLE_CLOSE_H
|
||||
|
||||
namespace NConsoleClose {
|
||||
|
||||
extern unsigned g_BreakCounter;
|
||||
|
||||
inline bool TestBreakSignal()
|
||||
{
|
||||
#ifdef UNDER_CE
|
||||
return false;
|
||||
#else
|
||||
return (g_BreakCounter != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
class CCtrlHandlerSetter
|
||||
{
|
||||
public:
|
||||
CCtrlHandlerSetter();
|
||||
virtual ~CCtrlHandlerSetter();
|
||||
};
|
||||
|
||||
class CCtrlBreakException
|
||||
{};
|
||||
|
||||
// void CheckCtrlBreak();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,825 @@
|
||||
// ExtractCallbackConsole.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileFind.h"
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
#include "../../../Windows/PropVariantConv.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
#endif
|
||||
|
||||
#include "../../Common/FilePathAutoRename.h"
|
||||
|
||||
#include "../Common/ExtractingFilePath.h"
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
#include "ExtractCallbackConsole.h"
|
||||
#include "UserInputUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
static HRESULT CheckBreak2()
|
||||
{
|
||||
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
|
||||
}
|
||||
|
||||
static const char * const kError = "ERROR: ";
|
||||
|
||||
|
||||
void CExtractScanConsole::StartScanning()
|
||||
{
|
||||
if (NeedPercents())
|
||||
_percent.Command = "Scan";
|
||||
}
|
||||
|
||||
HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Files = st.NumDirs + st.NumFiles;
|
||||
_percent.Completed = st.GetTotalBytes();
|
||||
_percent.FileName = fs2us(path);
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)
|
||||
{
|
||||
ClosePercentsAndFlush();
|
||||
|
||||
if (_se)
|
||||
{
|
||||
*_se << endl << kError << NError::MyFormatMessage(systemError) << endl;
|
||||
_se->NormalizePrint_UString(fs2us(path));
|
||||
*_se << endl << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
return HRESULT_FROM_WIN32(systemError);
|
||||
}
|
||||
|
||||
|
||||
void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)
|
||||
{
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(val, temp);
|
||||
s += temp;
|
||||
s.Add_Space();
|
||||
s += name;
|
||||
}
|
||||
|
||||
void PrintSize_bytes_Smart(AString &s, UInt64 val)
|
||||
{
|
||||
Print_UInt64_and_String(s, val, "bytes");
|
||||
|
||||
if (val == 0)
|
||||
return;
|
||||
|
||||
unsigned numBits = 10;
|
||||
char c = 'K';
|
||||
char temp[4] = { 'K', 'i', 'B', 0 };
|
||||
if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }
|
||||
else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }
|
||||
temp[0] = c;
|
||||
s += " (";
|
||||
Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
|
||||
s += ')';
|
||||
}
|
||||
|
||||
void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
|
||||
{
|
||||
if (val == (UInt64)(Int64)-1)
|
||||
return;
|
||||
s += ", ";
|
||||
PrintSize_bytes_Smart(s, val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
|
||||
{
|
||||
if (st.NumDirs != 0)
|
||||
{
|
||||
Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders");
|
||||
s += ", ";
|
||||
}
|
||||
Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");
|
||||
PrintSize_bytes_Smart_comma(s, st.FilesSize);
|
||||
if (st.NumAltStreams != 0)
|
||||
{
|
||||
s.Add_LF();
|
||||
Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
|
||||
PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)
|
||||
{
|
||||
Print_DirItemsStat(s, (CDirItemsStat &)st);
|
||||
bool needLF = true;
|
||||
if (st.Anti_NumDirs != 0)
|
||||
{
|
||||
if (needLF)
|
||||
s.Add_LF();
|
||||
needLF = false;
|
||||
Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders");
|
||||
}
|
||||
if (st.Anti_NumFiles != 0)
|
||||
{
|
||||
if (needLF)
|
||||
s.Add_LF();
|
||||
else
|
||||
s += ", ";
|
||||
needLF = false;
|
||||
Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files");
|
||||
}
|
||||
if (st.Anti_NumAltStreams != 0)
|
||||
{
|
||||
if (needLF)
|
||||
s.Add_LF();
|
||||
else
|
||||
s += ", ";
|
||||
needLF = false;
|
||||
Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CExtractScanConsole::PrintStat(const CDirItemsStat &st)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
AString s;
|
||||
Print_DirItemsStat(s, st);
|
||||
*_so << s << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
static NSynchronization::CCriticalSection g_CriticalSection;
|
||||
#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
|
||||
#else
|
||||
#define MT_LOCK
|
||||
#endif
|
||||
|
||||
|
||||
static const char * const kTestString = "T";
|
||||
static const char * const kExtractString = "-";
|
||||
static const char * const kSkipString = ".";
|
||||
|
||||
// static const char * const kCantAutoRename = "can not create file with auto name\n";
|
||||
// static const char * const kCantRenameFile = "can not rename existing file\n";
|
||||
// static const char * const kCantDeleteOutputFile = "can not delete output file ";
|
||||
|
||||
static const char * const kMemoryExceptionMessage = "Can't allocate required memory!";
|
||||
|
||||
static const char * const kExtracting = "Extracting archive: ";
|
||||
static const char * const kTesting = "Testing archive: ";
|
||||
|
||||
static const char * const kEverythingIsOk = "Everything is Ok";
|
||||
static const char * const kNoFiles = "No files to process";
|
||||
|
||||
static const char * const kUnsupportedMethod = "Unsupported Method";
|
||||
static const char * const kCrcFailed = "CRC Failed";
|
||||
static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
|
||||
static const char * const kDataError = "Data Error";
|
||||
static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
|
||||
static const char * const kUnavailableData = "Unavailable data";
|
||||
static const char * const kUnexpectedEnd = "Unexpected end of data";
|
||||
static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
|
||||
static const char * const kIsNotArc = "Is not archive";
|
||||
static const char * const kHeadersError = "Headers Error";
|
||||
static const char * const kWrongPassword = "Wrong password";
|
||||
|
||||
static const char * const k_ErrorFlagsMessages[] =
|
||||
{
|
||||
"Is not archive"
|
||||
, "Headers Error"
|
||||
, "Headers Error in encrypted archive. Wrong password?"
|
||||
, "Unavailable start of archive"
|
||||
, "Unconfirmed start of archive"
|
||||
, "Unexpected end of archive"
|
||||
, "There are data after the end of archive"
|
||||
, "Unsupported method"
|
||||
, "Unsupported feature"
|
||||
, "Data Error"
|
||||
, "CRC Error"
|
||||
};
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Total = size;
|
||||
_percent.Print();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
if (completeValue)
|
||||
_percent.Completed = *completeValue;
|
||||
_percent.Print();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
static const char * const kTab = " ";
|
||||
|
||||
static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
|
||||
{
|
||||
*_so << kTab << "Path: ";
|
||||
_so->NormalizePrint_wstr(path);
|
||||
*_so << endl;
|
||||
if (size && *size != (UInt64)(Int64)-1)
|
||||
{
|
||||
AString s;
|
||||
PrintSize_bytes_Smart(s, *size);
|
||||
*_so << kTab << "Size: " << s << endl;
|
||||
}
|
||||
if (ft)
|
||||
{
|
||||
char temp[64];
|
||||
if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC))
|
||||
*_so << kTab << "Modified: " << temp << endl;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
|
||||
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
|
||||
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
|
||||
Int32 *answer)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
RINOK(CheckBreak2());
|
||||
|
||||
ClosePercentsAndFlush();
|
||||
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl << "Would you like to replace the existing file:\n";
|
||||
PrintFileInfo(_so, existName, existTime, existSize);
|
||||
*_so << "with the file from archive:\n";
|
||||
PrintFileInfo(_so, newName, newTime, newSize);
|
||||
}
|
||||
|
||||
NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so);
|
||||
|
||||
switch (overwriteAnswer)
|
||||
{
|
||||
case NUserAnswerMode::kQuit: return E_ABORT;
|
||||
case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break;
|
||||
case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break;
|
||||
case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;
|
||||
case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break;
|
||||
case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
|
||||
case NUserAnswerMode::kEof: return E_ABORT;
|
||||
case NUserAnswerMode::kError: return E_FAIL;
|
||||
default: return E_FAIL;
|
||||
}
|
||||
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
_currentName = name;
|
||||
|
||||
const char *s;
|
||||
unsigned requiredLevel = 1;
|
||||
|
||||
switch (askExtractMode)
|
||||
{
|
||||
case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
|
||||
case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
|
||||
case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break;
|
||||
default: s = "???"; requiredLevel = 2;
|
||||
};
|
||||
|
||||
bool show2 = (LogLevel >= requiredLevel && _so);
|
||||
|
||||
if (show2)
|
||||
{
|
||||
ClosePercents_for_so();
|
||||
|
||||
_tempA = s;
|
||||
if (name)
|
||||
_tempA.Add_Space();
|
||||
*_so << _tempA;
|
||||
|
||||
_tempU.Empty();
|
||||
if (name)
|
||||
{
|
||||
_tempU = name;
|
||||
_so->Normalize_UString(_tempU);
|
||||
}
|
||||
_so->PrintUString(_tempU, _tempA);
|
||||
if (position)
|
||||
*_so << " <" << *position << ">";
|
||||
*_so << endl;
|
||||
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
if (PercentsNameLevel >= 1)
|
||||
{
|
||||
_percent.FileName.Empty();
|
||||
_percent.Command.Empty();
|
||||
if (PercentsNameLevel > 1 || !show2)
|
||||
{
|
||||
_percent.Command = s;
|
||||
if (name)
|
||||
_percent.FileName = name;
|
||||
}
|
||||
}
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
RINOK(CheckBreak2());
|
||||
|
||||
NumFileErrors_in_Current++;
|
||||
NumFileErrors++;
|
||||
|
||||
ClosePercentsAndFlush();
|
||||
if (_se)
|
||||
{
|
||||
*_se << kError << message << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
|
||||
{
|
||||
dest.Empty();
|
||||
const char *s = NULL;
|
||||
|
||||
switch (opRes)
|
||||
{
|
||||
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
|
||||
s = kUnsupportedMethod;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kCRCError:
|
||||
s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kDataError:
|
||||
s = (encrypted ? kDataErrorEncrypted : kDataError);
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kUnavailable:
|
||||
s = kUnavailableData;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
|
||||
s = kUnexpectedEnd;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
|
||||
s = kDataAfterEnd;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kIsNotArc:
|
||||
s = kIsNotArc;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kHeadersError:
|
||||
s = kHeadersError;
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kWrongPassword:
|
||||
s = kWrongPassword;
|
||||
break;
|
||||
}
|
||||
|
||||
dest += kError;
|
||||
if (s)
|
||||
dest += s;
|
||||
else
|
||||
{
|
||||
dest += "Error #";
|
||||
dest.Add_UInt32(opRes);
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
if (opRes == NArchive::NExtract::NOperationResult::kOK)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Command.Empty();
|
||||
_percent.FileName.Empty();
|
||||
_percent.Files++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumFileErrors_in_Current++;
|
||||
NumFileErrors++;
|
||||
|
||||
if (_se)
|
||||
{
|
||||
ClosePercentsAndFlush();
|
||||
|
||||
AString s;
|
||||
SetExtractErrorMessage(opRes, encrypted, s);
|
||||
|
||||
*_se << s;
|
||||
if (!_currentName.IsEmpty())
|
||||
{
|
||||
*_se << " : ";
|
||||
_se->NormalizePrint_UString(_currentName);
|
||||
}
|
||||
*_se << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
|
||||
{
|
||||
if (opRes != NArchive::NExtract::NOperationResult::kOK)
|
||||
{
|
||||
_currentName = name;
|
||||
return SetOperationResult(opRes, encrypted);
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
|
||||
HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
|
||||
{
|
||||
PasswordIsDefined = true;
|
||||
Password = password;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
MT_LOCK
|
||||
return Open_CryptoGetTextPassword(password);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
|
||||
{
|
||||
RINOK(CheckBreak2());
|
||||
|
||||
NumTryArcs++;
|
||||
ThereIsError_in_Current = false;
|
||||
ThereIsWarning_in_Current = false;
|
||||
NumFileErrors_in_Current = 0;
|
||||
|
||||
ClosePercents_for_so();
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl << (testMode ? kTesting : kExtracting);
|
||||
_so->NormalizePrint_wstr(name);
|
||||
*_so << endl;
|
||||
}
|
||||
|
||||
if (NeedPercents())
|
||||
_percent.Command = "Open";
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
|
||||
HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
|
||||
|
||||
static AString GetOpenArcErrorMessage(UInt32 errorFlags)
|
||||
{
|
||||
AString s;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)
|
||||
{
|
||||
UInt32 f = (1 << i);
|
||||
if ((errorFlags & f) == 0)
|
||||
continue;
|
||||
const char *m = k_ErrorFlagsMessages[i];
|
||||
if (!s.IsEmpty())
|
||||
s.Add_LF();
|
||||
s += m;
|
||||
errorFlags &= ~f;
|
||||
}
|
||||
|
||||
if (errorFlags != 0)
|
||||
{
|
||||
char sz[16];
|
||||
sz[0] = '0';
|
||||
sz[1] = 'x';
|
||||
ConvertUInt32ToHex(errorFlags, sz + 2);
|
||||
if (!s.IsEmpty())
|
||||
s.Add_LF();
|
||||
s += sz;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)
|
||||
{
|
||||
if (errorFlags == 0)
|
||||
return;
|
||||
so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;
|
||||
}
|
||||
|
||||
void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)
|
||||
{
|
||||
s.Add_LF();
|
||||
s += pre;
|
||||
s += " as [";
|
||||
s += arcType;
|
||||
s += "] archive";
|
||||
}
|
||||
|
||||
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)
|
||||
{
|
||||
const CArcErrorInfo &er = arc.ErrorInfo;
|
||||
|
||||
*_so << "WARNING:\n";
|
||||
_so->NormalizePrint_UString(arc.Path);
|
||||
UString s;
|
||||
if (arc.FormatIndex == er.ErrorFormatIndex)
|
||||
{
|
||||
s.Add_LF();
|
||||
s += "The archive is open with offset";
|
||||
}
|
||||
else
|
||||
{
|
||||
Add_Messsage_Pre_ArcType(s, "Can not open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex));
|
||||
Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex));
|
||||
}
|
||||
|
||||
*_so << s << endl << endl;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CExtractCallbackConsole::OpenResult(
|
||||
const CCodecs *codecs, const CArchiveLink &arcLink,
|
||||
const wchar_t *name, HRESULT result)
|
||||
{
|
||||
ClosePercents();
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Files = 0;
|
||||
_percent.Command.Empty();
|
||||
_percent.FileName.Empty();
|
||||
}
|
||||
|
||||
|
||||
ClosePercentsAndFlush();
|
||||
|
||||
FOR_VECTOR (level, arcLink.Arcs)
|
||||
{
|
||||
const CArc &arc = arcLink.Arcs[level];
|
||||
const CArcErrorInfo &er = arc.ErrorInfo;
|
||||
|
||||
UInt32 errorFlags = er.GetErrorFlags();
|
||||
|
||||
if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
|
||||
{
|
||||
if (_se)
|
||||
{
|
||||
*_se << endl;
|
||||
if (level != 0)
|
||||
{
|
||||
_se->NormalizePrint_UString(arc.Path);
|
||||
*_se << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorFlags != 0)
|
||||
{
|
||||
if (_se)
|
||||
PrintErrorFlags(*_se, "ERRORS:", errorFlags);
|
||||
NumOpenArcErrors++;
|
||||
ThereIsError_in_Current = true;
|
||||
}
|
||||
|
||||
if (!er.ErrorMessage.IsEmpty())
|
||||
{
|
||||
if (_se)
|
||||
*_se << "ERRORS:" << endl << er.ErrorMessage << endl;
|
||||
NumOpenArcErrors++;
|
||||
ThereIsError_in_Current = true;
|
||||
}
|
||||
|
||||
if (_se)
|
||||
{
|
||||
*_se << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 warningFlags = er.GetWarningFlags();
|
||||
|
||||
if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl;
|
||||
if (level != 0)
|
||||
{
|
||||
_so->NormalizePrint_UString(arc.Path);
|
||||
*_so << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (warningFlags != 0)
|
||||
{
|
||||
if (_so)
|
||||
PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
|
||||
NumOpenArcWarnings++;
|
||||
ThereIsWarning_in_Current = true;
|
||||
}
|
||||
|
||||
if (!er.WarningMessage.IsEmpty())
|
||||
{
|
||||
if (_so)
|
||||
*_so << "WARNINGS:" << endl << er.WarningMessage << endl;
|
||||
NumOpenArcWarnings++;
|
||||
ThereIsWarning_in_Current = true;
|
||||
}
|
||||
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (er.ErrorFormatIndex >= 0)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
Print_ErrorFormatIndex_Warning(_so, codecs, arc);
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
ThereIsWarning_in_Current = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
|
||||
*_so << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumCantOpenArcs++;
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
if (_se)
|
||||
{
|
||||
*_se << kError;
|
||||
_se->NormalizePrint_wstr(name);
|
||||
*_se << endl;
|
||||
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
|
||||
RINOK(res);
|
||||
if (result == S_FALSE)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result == E_OUTOFMEMORY)
|
||||
*_se << "Can't allocate required memory";
|
||||
else
|
||||
*_se << NError::MyFormatMessage(result);
|
||||
*_se << endl;
|
||||
}
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CExtractCallbackConsole::ThereAreNoFiles()
|
||||
{
|
||||
ClosePercents_for_so();
|
||||
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl << kNoFiles << endl;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.ClosePrint(true);
|
||||
_percent.Command.Empty();
|
||||
_percent.FileName.Empty();
|
||||
}
|
||||
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)
|
||||
{
|
||||
if (ThereIsWarning_in_Current)
|
||||
NumArcsWithWarnings++;
|
||||
else
|
||||
NumOkArcs++;
|
||||
if (_so)
|
||||
*_so << kEverythingIsOk << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumArcsWithError++;
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl;
|
||||
if (NumFileErrors_in_Current != 0)
|
||||
*_so << "Sub items Errors: " << NumFileErrors_in_Current << endl;
|
||||
}
|
||||
}
|
||||
if (_so && NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
NumArcsWithError++;
|
||||
if (result == E_ABORT || result == ERROR_DISK_FULL)
|
||||
return result;
|
||||
|
||||
if (_se)
|
||||
{
|
||||
*_se << endl << kError;
|
||||
if (result == E_OUTOFMEMORY)
|
||||
*_se << kMemoryExceptionMessage;
|
||||
else
|
||||
*_se << NError::MyFormatMessage(result);
|
||||
*_se << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// ExtractCallbackConsole.h
|
||||
|
||||
#ifndef __EXTRACT_CALLBACK_CONSOLE_H
|
||||
#define __EXTRACT_CALLBACK_CONSOLE_H
|
||||
|
||||
#include "../../../Common/StdOutStream.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "../Common/ArchiveExtractCallback.h"
|
||||
|
||||
#include "PercentPrinter.h"
|
||||
|
||||
#include "OpenCallbackConsole.h"
|
||||
|
||||
class CExtractScanConsole: public IDirItemsCallback
|
||||
{
|
||||
CStdOutStream *_so;
|
||||
CStdOutStream *_se;
|
||||
CPercentPrinter _percent;
|
||||
|
||||
bool NeedPercents() const { return _percent._so != NULL; }
|
||||
|
||||
void ClosePercentsAndFlush()
|
||||
{
|
||||
if (NeedPercents())
|
||||
_percent.ClosePrint(true);
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
}
|
||||
|
||||
public:
|
||||
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
|
||||
{
|
||||
_so = outStream;
|
||||
_se = errorStream;
|
||||
_percent._so = percentStream;
|
||||
}
|
||||
|
||||
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
|
||||
|
||||
void StartScanning();
|
||||
|
||||
INTERFACE_IDirItemsCallback(;)
|
||||
|
||||
void CloseScanning()
|
||||
{
|
||||
if (NeedPercents())
|
||||
_percent.ClosePrint(true);
|
||||
}
|
||||
|
||||
void PrintStat(const CDirItemsStat &st);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class CExtractCallbackConsole:
|
||||
public IExtractCallbackUI,
|
||||
// public IArchiveExtractCallbackMessage,
|
||||
public IFolderArchiveExtractCallback2,
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoGetTextPassword,
|
||||
#endif
|
||||
public COpenCallbackConsole,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
AString _tempA;
|
||||
UString _tempU;
|
||||
|
||||
UString _currentName;
|
||||
|
||||
void ClosePercents_for_so()
|
||||
{
|
||||
if (NeedPercents() && _so == _percent._so)
|
||||
_percent.ClosePrint(false);
|
||||
}
|
||||
|
||||
void ClosePercentsAndFlush()
|
||||
{
|
||||
if (NeedPercents())
|
||||
_percent.ClosePrint(true);
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
}
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
|
||||
// MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
|
||||
MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
STDMETHOD(SetTotal)(UInt64 total);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
|
||||
|
||||
INTERFACE_IFolderArchiveExtractCallback(;)
|
||||
|
||||
INTERFACE_IExtractCallbackUI(;)
|
||||
// INTERFACE_IArchiveExtractCallbackMessage(;)
|
||||
INTERFACE_IFolderArchiveExtractCallback2(;)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
|
||||
#endif
|
||||
|
||||
UInt64 NumTryArcs;
|
||||
|
||||
bool ThereIsError_in_Current;
|
||||
bool ThereIsWarning_in_Current;
|
||||
|
||||
UInt64 NumOkArcs;
|
||||
UInt64 NumCantOpenArcs;
|
||||
UInt64 NumArcsWithError;
|
||||
UInt64 NumArcsWithWarnings;
|
||||
|
||||
UInt64 NumOpenArcErrors;
|
||||
UInt64 NumOpenArcWarnings;
|
||||
|
||||
UInt64 NumFileErrors;
|
||||
UInt64 NumFileErrors_in_Current;
|
||||
|
||||
bool NeedFlush;
|
||||
unsigned PercentsNameLevel;
|
||||
unsigned LogLevel;
|
||||
|
||||
CExtractCallbackConsole():
|
||||
NeedFlush(false),
|
||||
PercentsNameLevel(1),
|
||||
LogLevel(0)
|
||||
{}
|
||||
|
||||
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
|
||||
|
||||
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
|
||||
{
|
||||
COpenCallbackConsole::Init(outStream, errorStream, percentStream);
|
||||
|
||||
NumTryArcs = 0;
|
||||
|
||||
ThereIsError_in_Current = false;
|
||||
ThereIsWarning_in_Current = false;
|
||||
|
||||
NumOkArcs = 0;
|
||||
NumCantOpenArcs = 0;
|
||||
NumArcsWithError = 0;
|
||||
NumArcsWithWarnings = 0;
|
||||
|
||||
NumOpenArcErrors = 0;
|
||||
NumOpenArcWarnings = 0;
|
||||
|
||||
NumFileErrors = 0;
|
||||
NumFileErrors_in_Current = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,367 @@
|
||||
// HashCon.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
#include "HashCon.h"
|
||||
|
||||
static const char * const kEmptyFileAlias = "[Content]";
|
||||
|
||||
static const char * const kScanningMessage = "Scanning";
|
||||
|
||||
static HRESULT CheckBreak2()
|
||||
{
|
||||
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::CheckBreak()
|
||||
{
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::StartScanning()
|
||||
{
|
||||
if (PrintHeaders && _so)
|
||||
*_so << kScanningMessage << endl;
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.ClearCurState();
|
||||
_percent.Command = "Scan";
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
|
||||
_percent.Completed = st.GetTotalBytes();
|
||||
_percent.FileName = fs2us(path);
|
||||
_percent.Print();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError)
|
||||
{
|
||||
return ScanError_Base(path, systemError);
|
||||
}
|
||||
|
||||
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
|
||||
|
||||
HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.ClosePrint(true);
|
||||
_percent.ClearCurState();
|
||||
}
|
||||
if (PrintHeaders && _so)
|
||||
{
|
||||
Print_DirItemsStat(_s, st);
|
||||
*_so << _s << endl << endl;
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */)
|
||||
{
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::SetTotal(UInt64 size)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Total = size;
|
||||
_percent.Print();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue)
|
||||
{
|
||||
if (completeValue && NeedPercents())
|
||||
{
|
||||
_percent.Completed = *completeValue;
|
||||
_percent.Print();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
static void AddMinuses(AString &s, unsigned num)
|
||||
{
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
s += '-';
|
||||
}
|
||||
|
||||
static void AddSpaces_if_Positive(AString &s, int num)
|
||||
{
|
||||
for (int i = 0; i < num; i++)
|
||||
s.Add_Space();
|
||||
}
|
||||
|
||||
static void SetSpacesAndNul(char *s, unsigned num)
|
||||
{
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
s[i] = ' ';
|
||||
s[num] = 0;
|
||||
}
|
||||
|
||||
static const unsigned kSizeField_Len = 13;
|
||||
static const unsigned kNameField_Len = 12;
|
||||
|
||||
static const unsigned kHashColumnWidth_Min = 4 * 2;
|
||||
|
||||
static unsigned GetColumnWidth(unsigned digestSize)
|
||||
{
|
||||
unsigned width = digestSize * 2;
|
||||
return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
|
||||
}
|
||||
|
||||
void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)
|
||||
{
|
||||
_s.Empty();
|
||||
|
||||
for (unsigned i = 0; i < hashers.Size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
_s.Add_Space();
|
||||
const CHasherState &h = hashers[i];
|
||||
AddMinuses(_s, GetColumnWidth(h.DigestSize));
|
||||
}
|
||||
|
||||
if (PrintSize)
|
||||
{
|
||||
_s.Add_Space();
|
||||
AddMinuses(_s, kSizeField_Len);
|
||||
}
|
||||
|
||||
if (PrintName)
|
||||
{
|
||||
AddSpacesBeforeName();
|
||||
AddMinuses(_s, kNameField_Len);
|
||||
}
|
||||
|
||||
*_so << _s << endl;
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)
|
||||
{
|
||||
if (PrintHeaders && _so)
|
||||
{
|
||||
_s.Empty();
|
||||
ClosePercents_for_so();
|
||||
|
||||
FOR_VECTOR (i, hb.Hashers)
|
||||
{
|
||||
if (i != 0)
|
||||
_s.Add_Space();
|
||||
const CHasherState &h = hb.Hashers[i];
|
||||
_s += h.Name;
|
||||
AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len());
|
||||
}
|
||||
|
||||
if (PrintSize)
|
||||
{
|
||||
_s.Add_Space();
|
||||
const AString s2 ("Size");
|
||||
AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());
|
||||
_s += s2;
|
||||
}
|
||||
|
||||
if (PrintName)
|
||||
{
|
||||
AddSpacesBeforeName();
|
||||
_s += "Name";
|
||||
}
|
||||
|
||||
*_so << _s << endl;
|
||||
PrintSeparatorLine(hb.Hashers);
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
|
||||
{
|
||||
return OpenFileError_Base(path, systemError);
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)
|
||||
{
|
||||
_fileName = name;
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
if (PrintNameInPercents)
|
||||
{
|
||||
_percent.FileName.Empty();
|
||||
if (name)
|
||||
_percent.FileName = name;
|
||||
}
|
||||
_percent.Print();
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
void CHashCallbackConsole::PrintResultLine(UInt64 fileSize,
|
||||
const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash)
|
||||
{
|
||||
ClosePercents_for_so();
|
||||
|
||||
_s.Empty();
|
||||
|
||||
FOR_VECTOR (i, hashers)
|
||||
{
|
||||
const CHasherState &h = hashers[i];
|
||||
char s[k_HashCalc_DigestSize_Max * 2 + 64];
|
||||
s[0] = 0;
|
||||
if (showHash)
|
||||
AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
|
||||
SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s));
|
||||
if (i != 0)
|
||||
_s.Add_Space();
|
||||
_s += s;
|
||||
}
|
||||
|
||||
if (PrintSize)
|
||||
{
|
||||
_s.Add_Space();
|
||||
|
||||
char s[kSizeField_Len + 32];
|
||||
char *p = s;
|
||||
|
||||
if (showHash)
|
||||
{
|
||||
p = s + kSizeField_Len;
|
||||
ConvertUInt64ToString(fileSize, p);
|
||||
int numSpaces = kSizeField_Len - (int)strlen(p);
|
||||
if (numSpaces > 0)
|
||||
{
|
||||
p -= (unsigned)numSpaces;
|
||||
for (unsigned i = 0; i < (unsigned)numSpaces; i++)
|
||||
p[i] = ' ';
|
||||
}
|
||||
}
|
||||
else
|
||||
SetSpacesAndNul(s, kSizeField_Len);
|
||||
|
||||
_s += p;
|
||||
}
|
||||
|
||||
if (PrintName)
|
||||
AddSpacesBeforeName();
|
||||
|
||||
*_so << _s;
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);
|
||||
if (PrintName)
|
||||
{
|
||||
if (_fileName.IsEmpty())
|
||||
*_so << kEmptyFileAlias;
|
||||
else
|
||||
_so->NormalizePrint_UString(_fileName);
|
||||
}
|
||||
*_so << endl;
|
||||
}
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Files++;
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
static const char * const k_DigestTitles[] =
|
||||
{
|
||||
" : "
|
||||
, " for data: "
|
||||
, " for data and names: "
|
||||
, " for streams and names: "
|
||||
};
|
||||
|
||||
static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex)
|
||||
{
|
||||
so << h.Name;
|
||||
|
||||
{
|
||||
AString temp;
|
||||
AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len());
|
||||
so << temp;
|
||||
}
|
||||
|
||||
so << k_DigestTitles[digestIndex];
|
||||
|
||||
char s[k_HashCalc_DigestSize_Max * 2 + 64];
|
||||
s[0] = 0;
|
||||
AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
|
||||
so << s << endl;
|
||||
}
|
||||
|
||||
void PrintHashStat(CStdOutStream &so, const CHashBundle &hb)
|
||||
{
|
||||
FOR_VECTOR (i, hb.Hashers)
|
||||
{
|
||||
const CHasherState &h = hb.Hashers[i];
|
||||
PrintSum(so, h, k_HashCalc_Index_DataSum);
|
||||
if (hb.NumFiles != 1 || hb.NumDirs != 0)
|
||||
PrintSum(so, h, k_HashCalc_Index_NamesSum);
|
||||
if (hb.NumAltStreams != 0)
|
||||
PrintSum(so, h, k_HashCalc_Index_StreamsSum);
|
||||
so << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value)
|
||||
{
|
||||
char s[32];
|
||||
s[0] = ':';
|
||||
s[1] = ' ';
|
||||
ConvertUInt64ToString(value, s + 2);
|
||||
*_so << name << s << endl;
|
||||
}
|
||||
|
||||
HRESULT CHashCallbackConsole::AfterLastFile(CHashBundle &hb)
|
||||
{
|
||||
ClosePercents2();
|
||||
|
||||
if (PrintHeaders && _so)
|
||||
{
|
||||
PrintSeparatorLine(hb.Hashers);
|
||||
|
||||
PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);
|
||||
|
||||
*_so << endl << endl;
|
||||
|
||||
if (hb.NumFiles != 1 || hb.NumDirs != 0)
|
||||
{
|
||||
if (hb.NumDirs != 0)
|
||||
PrintProperty("Folders", hb.NumDirs);
|
||||
PrintProperty("Files", hb.NumFiles);
|
||||
}
|
||||
|
||||
PrintProperty("Size", hb.FilesSize);
|
||||
|
||||
if (hb.NumAltStreams != 0)
|
||||
{
|
||||
PrintProperty("Alternate streams", hb.NumAltStreams);
|
||||
PrintProperty("Alternate streams size", hb.AltStreamsSize);
|
||||
}
|
||||
|
||||
*_so << endl;
|
||||
PrintHashStat(*_so, hb);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// HashCon.h
|
||||
|
||||
#ifndef __HASH_CON_H
|
||||
#define __HASH_CON_H
|
||||
|
||||
#include "../Common/HashCalc.h"
|
||||
|
||||
#include "UpdateCallbackConsole.h"
|
||||
|
||||
class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase
|
||||
{
|
||||
UString _fileName;
|
||||
AString _s;
|
||||
|
||||
void AddSpacesBeforeName()
|
||||
{
|
||||
_s.Add_Space();
|
||||
_s.Add_Space();
|
||||
}
|
||||
|
||||
void PrintSeparatorLine(const CObjectVector<CHasherState> &hashers);
|
||||
void PrintResultLine(UInt64 fileSize,
|
||||
const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash);
|
||||
void PrintProperty(const char *name, UInt64 value);
|
||||
|
||||
public:
|
||||
bool PrintNameInPercents;
|
||||
|
||||
bool PrintHeaders;
|
||||
|
||||
bool PrintSize;
|
||||
bool PrintName;
|
||||
|
||||
CHashCallbackConsole():
|
||||
PrintNameInPercents(true),
|
||||
PrintHeaders(false),
|
||||
PrintSize(true),
|
||||
PrintName(true)
|
||||
{}
|
||||
|
||||
~CHashCallbackConsole() { }
|
||||
|
||||
INTERFACE_IHashCallbackUI(;)
|
||||
};
|
||||
|
||||
void PrintHashStat(CStdOutStream &so, const CHashBundle &hb);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
// List.h
|
||||
|
||||
#ifndef __LIST_H
|
||||
#define __LIST_H
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../Common/LoadCodecs.h"
|
||||
|
||||
HRESULT ListArchives(CCodecs *codecs,
|
||||
const CObjectVector<COpenType> &types,
|
||||
const CIntVector &excludedFormats,
|
||||
bool stdInMode,
|
||||
UStringVector &archivePaths, UStringVector &archivePathsFull,
|
||||
bool processAltStreams, bool showAltStreams,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
bool enableHeaders, bool techMode,
|
||||
#ifndef _NO_CRYPTO
|
||||
bool &passwordEnabled, UString &password,
|
||||
#endif
|
||||
#ifndef _SFX
|
||||
const CObjectVector<CProperty> *props,
|
||||
#endif
|
||||
UInt64 &errors,
|
||||
UInt64 &numWarnings);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
// MainAr.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "../../../../C/DllSecur.h"
|
||||
#endif
|
||||
|
||||
#include "../../../Common/MyException.h"
|
||||
#include "../../../Common/StdOutStream.h"
|
||||
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
#include "../../../Windows/NtCheck.h"
|
||||
|
||||
#include "../Common/ArchiveCommandLine.h"
|
||||
#include "../Common/ExitCode.h"
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
CStdOutStream *g_StdStream = NULL;
|
||||
CStdOutStream *g_ErrStream = NULL;
|
||||
|
||||
extern int Main2(
|
||||
#ifndef _WIN32
|
||||
int numArgs, char *args[]
|
||||
#endif
|
||||
);
|
||||
|
||||
static const char * const kException_CmdLine_Error_Message = "Command Line Error:";
|
||||
static const char * const kExceptionErrorMessage = "ERROR:";
|
||||
static const char * const kUserBreakMessage = "Break signaled";
|
||||
static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";
|
||||
static const char * const kUnknownExceptionMessage = "Unknown Error";
|
||||
static const char * const kInternalExceptionMessage = "\n\nInternal Error #";
|
||||
|
||||
static void FlushStreams()
|
||||
{
|
||||
if (g_StdStream)
|
||||
g_StdStream->Flush();
|
||||
}
|
||||
|
||||
static void PrintError(const char *message)
|
||||
{
|
||||
FlushStreams();
|
||||
if (g_ErrStream)
|
||||
*g_ErrStream << "\n\n" << message << endl;
|
||||
}
|
||||
|
||||
#define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError;
|
||||
|
||||
int MY_CDECL main
|
||||
(
|
||||
#ifndef _WIN32
|
||||
int numArgs, char *args[]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
g_ErrStream = &g_StdErr;
|
||||
g_StdStream = &g_StdOut;
|
||||
|
||||
NT_CHECK
|
||||
|
||||
NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
|
||||
int res = 0;
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef _WIN32
|
||||
My_SetDefaultDllDirectories();
|
||||
#endif
|
||||
|
||||
res = Main2(
|
||||
#ifndef _WIN32
|
||||
numArgs, args
|
||||
#endif
|
||||
);
|
||||
}
|
||||
catch(const CNewException &)
|
||||
{
|
||||
PrintError(kMemoryExceptionMessage);
|
||||
return (NExitCode::kMemoryError);
|
||||
}
|
||||
catch(const NConsoleClose::CCtrlBreakException &)
|
||||
{
|
||||
PrintError(kUserBreakMessage);
|
||||
return (NExitCode::kUserBreak);
|
||||
}
|
||||
catch(const CMessagePathException &e)
|
||||
{
|
||||
PrintError(kException_CmdLine_Error_Message);
|
||||
if (g_ErrStream)
|
||||
*g_ErrStream << e << endl;
|
||||
return (NExitCode::kUserError);
|
||||
}
|
||||
catch(const CSystemException &systemError)
|
||||
{
|
||||
if (systemError.ErrorCode == E_OUTOFMEMORY)
|
||||
{
|
||||
PrintError(kMemoryExceptionMessage);
|
||||
return (NExitCode::kMemoryError);
|
||||
}
|
||||
if (systemError.ErrorCode == E_ABORT)
|
||||
{
|
||||
PrintError(kUserBreakMessage);
|
||||
return (NExitCode::kUserBreak);
|
||||
}
|
||||
if (g_ErrStream)
|
||||
{
|
||||
PrintError("System ERROR:");
|
||||
*g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl;
|
||||
}
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
catch(NExitCode::EEnum &exitCode)
|
||||
{
|
||||
FlushStreams();
|
||||
if (g_ErrStream)
|
||||
*g_ErrStream << kInternalExceptionMessage << exitCode << endl;
|
||||
return (exitCode);
|
||||
}
|
||||
catch(const UString &s)
|
||||
{
|
||||
if (g_ErrStream)
|
||||
{
|
||||
PrintError(kExceptionErrorMessage);
|
||||
*g_ErrStream << s << endl;
|
||||
}
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
catch(const AString &s)
|
||||
{
|
||||
if (g_ErrStream)
|
||||
{
|
||||
PrintError(kExceptionErrorMessage);
|
||||
*g_ErrStream << s << endl;
|
||||
}
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
catch(const char *s)
|
||||
{
|
||||
if (g_ErrStream)
|
||||
{
|
||||
PrintError(kExceptionErrorMessage);
|
||||
*g_ErrStream << s << endl;
|
||||
}
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
catch(const wchar_t *s)
|
||||
{
|
||||
if (g_ErrStream)
|
||||
{
|
||||
PrintError(kExceptionErrorMessage);
|
||||
*g_ErrStream << s << endl;
|
||||
}
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
catch(int t)
|
||||
{
|
||||
if (g_ErrStream)
|
||||
{
|
||||
FlushStreams();
|
||||
*g_ErrStream << kInternalExceptionMessage << t << endl;
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
PrintError(kUnknownExceptionMessage);
|
||||
return (NExitCode::kFatalError);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// OpenCallbackConsole.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OpenCallbackConsole.h"
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
#include "UserInputUtils.h"
|
||||
|
||||
static HRESULT CheckBreak2()
|
||||
{
|
||||
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
|
||||
}
|
||||
|
||||
HRESULT COpenCallbackConsole::Open_CheckBreak()
|
||||
{
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)
|
||||
{
|
||||
if (!MultiArcMode && NeedPercents())
|
||||
{
|
||||
if (files)
|
||||
{
|
||||
_totalFilesDefined = true;
|
||||
// _totalFiles = *files;
|
||||
_percent.Total = *files;
|
||||
}
|
||||
else
|
||||
_totalFilesDefined = false;
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
// _totalBytesDefined = true;
|
||||
_totalBytes = *bytes;
|
||||
if (!files)
|
||||
_percent.Total = *bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
// _totalBytesDefined = false;
|
||||
if (!files)
|
||||
_percent.Total = _totalBytes;
|
||||
}
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)
|
||||
{
|
||||
if (!MultiArcMode && NeedPercents())
|
||||
{
|
||||
if (files)
|
||||
{
|
||||
_percent.Files = *files;
|
||||
if (_totalFilesDefined)
|
||||
_percent.Completed = *files;
|
||||
}
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
if (!_totalFilesDefined)
|
||||
_percent.Completed = *bytes;
|
||||
}
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT COpenCallbackConsole::Open_Finished()
|
||||
{
|
||||
ClosePercents();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
|
||||
HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
*password = NULL;
|
||||
RINOK(CheckBreak2());
|
||||
|
||||
if (!PasswordIsDefined)
|
||||
{
|
||||
ClosePercents();
|
||||
RINOK(GetPassword_HRESULT(_so, Password));
|
||||
PasswordIsDefined = true;
|
||||
}
|
||||
return StringToBstr(Password, password);
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
|
||||
{
|
||||
passwordIsDefined = PasswordIsDefined;
|
||||
password = Password;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool COpenCallbackConsole::Open_WasPasswordAsked()
|
||||
{
|
||||
return PasswordWasAsked;
|
||||
}
|
||||
|
||||
void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag ()
|
||||
{
|
||||
PasswordWasAsked = false;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
// OpenCallbackConsole.h
|
||||
|
||||
#ifndef __OPEN_CALLBACK_CONSOLE_H
|
||||
#define __OPEN_CALLBACK_CONSOLE_H
|
||||
|
||||
#include "../../../Common/StdOutStream.h"
|
||||
|
||||
#include "../Common/ArchiveOpenCallback.h"
|
||||
|
||||
#include "PercentPrinter.h"
|
||||
|
||||
class COpenCallbackConsole: public IOpenCallbackUI
|
||||
{
|
||||
protected:
|
||||
CPercentPrinter _percent;
|
||||
|
||||
CStdOutStream *_so;
|
||||
CStdOutStream *_se;
|
||||
|
||||
bool _totalFilesDefined;
|
||||
// bool _totalBytesDefined;
|
||||
// UInt64 _totalFiles;
|
||||
UInt64 _totalBytes;
|
||||
|
||||
bool NeedPercents() const { return _percent._so != NULL; }
|
||||
|
||||
public:
|
||||
|
||||
bool MultiArcMode;
|
||||
|
||||
void ClosePercents()
|
||||
{
|
||||
if (NeedPercents())
|
||||
_percent.ClosePrint(true);
|
||||
}
|
||||
|
||||
COpenCallbackConsole():
|
||||
_totalFilesDefined(false),
|
||||
// _totalBytesDefined(false),
|
||||
_totalBytes(0),
|
||||
MultiArcMode(false)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
, PasswordIsDefined(false)
|
||||
// , PasswordWasAsked(false)
|
||||
#endif
|
||||
|
||||
{}
|
||||
|
||||
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
|
||||
{
|
||||
_so = outStream;
|
||||
_se = errorStream;
|
||||
_percent._so = percentStream;
|
||||
}
|
||||
|
||||
INTERFACE_IOpenCallbackUI(;)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
bool PasswordIsDefined;
|
||||
// bool PasswordWasAsked;
|
||||
UString Password;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,183 @@
|
||||
// PercentPrinter.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#include "PercentPrinter.h"
|
||||
|
||||
static const unsigned kPercentsSize = 4;
|
||||
|
||||
CPercentPrinter::~CPercentPrinter()
|
||||
{
|
||||
ClosePrint(false);
|
||||
}
|
||||
|
||||
void CPercentPrinterState::ClearCurState()
|
||||
{
|
||||
Completed = 0;
|
||||
Total = ((UInt64)(Int64)-1);
|
||||
Files = 0;
|
||||
Command.Empty();
|
||||
FileName.Empty();
|
||||
}
|
||||
|
||||
void CPercentPrinter::ClosePrint(bool needFlush)
|
||||
{
|
||||
unsigned num = _printedString.Len();
|
||||
if (num != 0)
|
||||
{
|
||||
|
||||
unsigned i;
|
||||
|
||||
/* '\r' in old MAC OS means "new line".
|
||||
So we can't use '\r' in some systems */
|
||||
|
||||
#ifdef _WIN32
|
||||
char *start = _temp.GetBuf(num + 2);
|
||||
char *p = start;
|
||||
*p++ = '\r';
|
||||
for (i = 0; i < num; i++) *p++ = ' ';
|
||||
*p++ = '\r';
|
||||
#else
|
||||
char *start = _temp.GetBuf(num * 3);
|
||||
char *p = start;
|
||||
for (i = 0; i < num; i++) *p++ = '\b';
|
||||
for (i = 0; i < num; i++) *p++ = ' ';
|
||||
for (i = 0; i < num; i++) *p++ = '\b';
|
||||
#endif
|
||||
|
||||
*p = 0;
|
||||
_temp.ReleaseBuf_SetLen((unsigned)(p - start));
|
||||
*_so << _temp;
|
||||
}
|
||||
if (needFlush)
|
||||
_so->Flush();
|
||||
_printedString.Empty();
|
||||
}
|
||||
|
||||
void CPercentPrinter::GetPercents()
|
||||
{
|
||||
char s[32];
|
||||
unsigned size;
|
||||
{
|
||||
char c = '%';
|
||||
UInt64 val = 0;
|
||||
if (Total == (UInt64)(Int64)-1)
|
||||
{
|
||||
val = Completed >> 20;
|
||||
c = 'M';
|
||||
}
|
||||
else if (Total != 0)
|
||||
val = Completed * 100 / Total;
|
||||
ConvertUInt64ToString(val, s);
|
||||
size = (unsigned)strlen(s);
|
||||
s[size++] = c;
|
||||
s[size] = 0;
|
||||
}
|
||||
|
||||
while (size < kPercentsSize)
|
||||
{
|
||||
_s += ' ';
|
||||
size++;
|
||||
}
|
||||
|
||||
_s += s;
|
||||
}
|
||||
|
||||
void CPercentPrinter::Print()
|
||||
{
|
||||
DWORD tick = 0;
|
||||
if (_tickStep != 0)
|
||||
tick = GetTickCount();
|
||||
|
||||
bool onlyPercentsChanged = false;
|
||||
|
||||
if (!_printedString.IsEmpty())
|
||||
{
|
||||
if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)
|
||||
return;
|
||||
|
||||
CPercentPrinterState &st = *this;
|
||||
if (_printedState.Command == st.Command
|
||||
&& _printedState.FileName == st.FileName
|
||||
&& _printedState.Files == st.Files)
|
||||
{
|
||||
if (_printedState.Total == st.Total
|
||||
&& _printedState.Completed == st.Completed)
|
||||
return;
|
||||
onlyPercentsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
_s.Empty();
|
||||
|
||||
GetPercents();
|
||||
|
||||
if (onlyPercentsChanged && _s == _printedPercents)
|
||||
return;
|
||||
|
||||
_printedPercents = _s;
|
||||
|
||||
if (Files != 0)
|
||||
{
|
||||
char s[32];
|
||||
ConvertUInt64ToString(Files, s);
|
||||
// unsigned size = (unsigned)strlen(s);
|
||||
// for (; size < 3; size++) _s += ' ';
|
||||
_s += ' ';
|
||||
_s += s;
|
||||
// _s += "f";
|
||||
}
|
||||
|
||||
|
||||
if (!Command.IsEmpty())
|
||||
{
|
||||
_s += ' ';
|
||||
_s += Command;
|
||||
}
|
||||
|
||||
if (!FileName.IsEmpty() && _s.Len() < MaxLen)
|
||||
{
|
||||
_s += ' ';
|
||||
|
||||
_tempU = FileName;
|
||||
_so->Normalize_UString(_tempU);
|
||||
StdOut_Convert_UString_to_AString(_tempU, _temp);
|
||||
if (_s.Len() + _temp.Len() > MaxLen)
|
||||
{
|
||||
unsigned len = FileName.Len();
|
||||
for (; len != 0;)
|
||||
{
|
||||
unsigned delta = len / 8;
|
||||
if (delta == 0)
|
||||
delta = 1;
|
||||
len -= delta;
|
||||
_tempU = FileName;
|
||||
_tempU.Delete(len / 2, _tempU.Len() - len);
|
||||
_tempU.Insert(len / 2, L" . ");
|
||||
_so->Normalize_UString(_tempU);
|
||||
StdOut_Convert_UString_to_AString(_tempU, _temp);
|
||||
if (_s.Len() + _temp.Len() <= MaxLen)
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
_temp.Empty();
|
||||
}
|
||||
_s += _temp;
|
||||
}
|
||||
|
||||
if (_printedString != _s)
|
||||
{
|
||||
ClosePrint(false);
|
||||
*_so << _s;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
_printedString = _s;
|
||||
}
|
||||
|
||||
_printedState = *this;
|
||||
|
||||
if (_tickStep != 0)
|
||||
_prevTick = tick;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// PercentPrinter.h
|
||||
|
||||
#ifndef __PERCENT_PRINTER_H
|
||||
#define __PERCENT_PRINTER_H
|
||||
|
||||
#include "../../../Common/StdOutStream.h"
|
||||
|
||||
struct CPercentPrinterState
|
||||
{
|
||||
UInt64 Completed;
|
||||
UInt64 Total;
|
||||
|
||||
UInt64 Files;
|
||||
|
||||
AString Command;
|
||||
UString FileName;
|
||||
|
||||
void ClearCurState();
|
||||
|
||||
CPercentPrinterState():
|
||||
Completed(0),
|
||||
Total((UInt64)(Int64)-1),
|
||||
Files(0)
|
||||
{}
|
||||
};
|
||||
|
||||
class CPercentPrinter: public CPercentPrinterState
|
||||
{
|
||||
UInt32 _tickStep;
|
||||
DWORD _prevTick;
|
||||
|
||||
AString _s;
|
||||
|
||||
AString _printedString;
|
||||
AString _temp;
|
||||
UString _tempU;
|
||||
|
||||
CPercentPrinterState _printedState;
|
||||
AString _printedPercents;
|
||||
|
||||
void GetPercents();
|
||||
|
||||
public:
|
||||
CStdOutStream *_so;
|
||||
|
||||
bool NeedFlush;
|
||||
unsigned MaxLen;
|
||||
|
||||
CPercentPrinter(UInt32 tickStep = 200):
|
||||
_tickStep(tickStep),
|
||||
_prevTick(0),
|
||||
NeedFlush(true),
|
||||
MaxLen(80 - 1)
|
||||
{}
|
||||
|
||||
~CPercentPrinter();
|
||||
|
||||
void ClosePrint(bool needFlush);
|
||||
void Print();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,702 @@
|
||||
// UpdateCallbackConsole.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
#endif
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
#include "UserInputUtils.h"
|
||||
#include "UpdateCallbackConsole.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
static NSynchronization::CCriticalSection g_CriticalSection;
|
||||
#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
|
||||
#else
|
||||
#define MT_LOCK
|
||||
#endif
|
||||
|
||||
static const wchar_t * const kEmptyFileAlias = L"[Content]";
|
||||
|
||||
static const char * const kOpenArchiveMessage = "Open archive: ";
|
||||
static const char * const kCreatingArchiveMessage = "Creating archive: ";
|
||||
static const char * const kUpdatingArchiveMessage = "Updating archive: ";
|
||||
static const char * const kScanningMessage = "Scanning the drive:";
|
||||
|
||||
static const char * const kError = "ERROR: ";
|
||||
static const char * const kWarning = "WARNING: ";
|
||||
|
||||
static HRESULT CheckBreak2()
|
||||
{
|
||||
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
|
||||
}
|
||||
|
||||
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
|
||||
HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
|
||||
|
||||
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
|
||||
|
||||
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
|
||||
|
||||
HRESULT CUpdateCallbackConsole::OpenResult(
|
||||
const CCodecs *codecs, const CArchiveLink &arcLink,
|
||||
const wchar_t *name, HRESULT result)
|
||||
{
|
||||
ClosePercents2();
|
||||
|
||||
FOR_VECTOR (level, arcLink.Arcs)
|
||||
{
|
||||
const CArc &arc = arcLink.Arcs[level];
|
||||
const CArcErrorInfo &er = arc.ErrorInfo;
|
||||
|
||||
UInt32 errorFlags = er.GetErrorFlags();
|
||||
|
||||
if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
|
||||
{
|
||||
if (_se)
|
||||
{
|
||||
*_se << endl;
|
||||
if (level != 0)
|
||||
*_se << arc.Path << endl;
|
||||
}
|
||||
|
||||
if (errorFlags != 0)
|
||||
{
|
||||
if (_se)
|
||||
PrintErrorFlags(*_se, "ERRORS:", errorFlags);
|
||||
}
|
||||
|
||||
if (!er.ErrorMessage.IsEmpty())
|
||||
{
|
||||
if (_se)
|
||||
*_se << "ERRORS:" << endl << er.ErrorMessage << endl;
|
||||
}
|
||||
|
||||
if (_se)
|
||||
{
|
||||
*_se << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 warningFlags = er.GetWarningFlags();
|
||||
|
||||
if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl;
|
||||
if (level != 0)
|
||||
*_so << arc.Path << endl;
|
||||
}
|
||||
|
||||
if (warningFlags != 0)
|
||||
{
|
||||
if (_so)
|
||||
PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
|
||||
}
|
||||
|
||||
if (!er.WarningMessage.IsEmpty())
|
||||
{
|
||||
if (_so)
|
||||
*_so << "WARNINGS:" << endl << er.WarningMessage << endl;
|
||||
}
|
||||
|
||||
if (_so)
|
||||
{
|
||||
*_so << endl;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (er.ErrorFormatIndex >= 0)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
Print_ErrorFormatIndex_Warning(_so, codecs, arc);
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
|
||||
*_so << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
if (_se)
|
||||
{
|
||||
*_se << kError;
|
||||
_se->NormalizePrint_wstr(name);
|
||||
*_se << endl;
|
||||
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
|
||||
RINOK(res);
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::StartScanning()
|
||||
{
|
||||
if (_so)
|
||||
*_so << kScanningMessage << endl;
|
||||
_percent.Command = "Scan ";
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
|
||||
_percent.Completed = st.GetTotalBytes();
|
||||
_percent.FileName = fs2us(path);
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return CheckBreak();
|
||||
}
|
||||
|
||||
void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
|
||||
{
|
||||
ClosePercents2();
|
||||
|
||||
if (_se)
|
||||
{
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
|
||||
*_se << endl << (isWarning ? kWarning : kError)
|
||||
<< NError::MyFormatMessage(systemError)
|
||||
<< endl;
|
||||
_se->NormalizePrint_UString(fs2us(path));
|
||||
*_se << endl << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
ScanErrors.AddError(path, systemError);
|
||||
CommonError(path, systemError, true);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)
|
||||
{
|
||||
MT_LOCK
|
||||
FailedFiles.AddError(path, systemError);
|
||||
/*
|
||||
if (systemError == ERROR_SHARING_VIOLATION)
|
||||
{
|
||||
*/
|
||||
CommonError(path, systemError, true);
|
||||
return S_FALSE;
|
||||
/*
|
||||
}
|
||||
return systemError;
|
||||
*/
|
||||
}
|
||||
|
||||
HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)
|
||||
{
|
||||
MT_LOCK
|
||||
CommonError(path, systemError, false);
|
||||
return HRESULT_FROM_WIN32(systemError);
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
|
||||
{
|
||||
return ScanError_Base(path, systemError);
|
||||
}
|
||||
|
||||
|
||||
static void PrintPropPair(AString &s, const char *name, UInt64 val)
|
||||
{
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(val, temp);
|
||||
s += name;
|
||||
s += ": ";
|
||||
s += temp;
|
||||
}
|
||||
|
||||
void PrintSize_bytes_Smart(AString &s, UInt64 val);
|
||||
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
|
||||
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
|
||||
|
||||
HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.ClosePrint(true);
|
||||
_percent.ClearCurState();
|
||||
}
|
||||
|
||||
if (_so)
|
||||
{
|
||||
AString s;
|
||||
Print_DirItemsStat(s, st);
|
||||
*_so << s << endl << endl;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const char * const k_StdOut_ArcName = "StdOut";
|
||||
|
||||
HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
*_so << kOpenArchiveMessage;
|
||||
if (name)
|
||||
*_so << name;
|
||||
else
|
||||
*_so << k_StdOut_ArcName;
|
||||
*_so << endl;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
*_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
|
||||
if (name)
|
||||
_so->NormalizePrint_wstr(name);
|
||||
else
|
||||
*_so << k_StdOut_ArcName;
|
||||
*_so << endl << endl;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
|
||||
{
|
||||
ClosePercents2();
|
||||
|
||||
if (_so)
|
||||
{
|
||||
AString s;
|
||||
// Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
|
||||
PrintPropPair(s, "Files read from disk", _percent.Files);
|
||||
s.Add_LF();
|
||||
s += "Archive size: ";
|
||||
PrintSize_bytes_Smart(s, st.OutArcFileSize);
|
||||
s.Add_LF();
|
||||
*_so << endl;
|
||||
*_so << s;
|
||||
// *_so << endl;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
*_so << "Write SFX: ";
|
||||
*_so << name;
|
||||
AString s (" : ");
|
||||
PrintSize_bytes_Smart(s, size);
|
||||
*_so << s << endl;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
|
||||
{
|
||||
if (LogLevel > 0 && _so)
|
||||
{
|
||||
ClosePercents_for_so();
|
||||
|
||||
if (!DeleteMessageWasShown)
|
||||
{
|
||||
if (_so)
|
||||
*_so << endl << ": Removing files after including to archive" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
_tempA = "Removing";
|
||||
_tempA.Add_Space();
|
||||
*_so << _tempA;
|
||||
_tempU = fs2us(path);
|
||||
_so->Normalize_UString(_tempU);
|
||||
_so->PrintUString(_tempU, _tempA);
|
||||
*_so << endl;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!DeleteMessageWasShown)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.ClearCurState();
|
||||
}
|
||||
DeleteMessageWasShown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_percent.Files++;
|
||||
}
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
// if (!FullLog)
|
||||
{
|
||||
_percent.Command = "Removing";
|
||||
_percent.FileName = fs2us(path);
|
||||
}
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
|
||||
{
|
||||
ClosePercents2();
|
||||
if (_so && DeleteMessageWasShown)
|
||||
*_so << endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::CheckBreak()
|
||||
{
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CUpdateCallbackConsole::Finalize()
|
||||
{
|
||||
// MT_LOCK
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
|
||||
{
|
||||
AString s;
|
||||
Print_DirItemsStat2(s, stat);
|
||||
*_so << name << ": " << s << endl;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
|
||||
{
|
||||
if (_so)
|
||||
{
|
||||
ClosePercents_for_so();
|
||||
if (!stat.DeleteData.IsEmpty())
|
||||
{
|
||||
*_so << endl;
|
||||
PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
|
||||
}
|
||||
if (!stat.OldData.IsEmpty())
|
||||
PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
|
||||
// if (!stat.NewData.IsEmpty())
|
||||
{
|
||||
PrintToDoStat(_so, stat.NewData, "Add new data to archive");
|
||||
}
|
||||
*_so << endl;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
|
||||
{
|
||||
MT_LOCK
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Total = size;
|
||||
_percent.Print();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
|
||||
{
|
||||
MT_LOCK
|
||||
if (completeValue)
|
||||
{
|
||||
if (NeedPercents())
|
||||
{
|
||||
_percent.Completed = *completeValue;
|
||||
_percent.Print();
|
||||
}
|
||||
}
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
|
||||
{
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
|
||||
{
|
||||
MT_LOCK
|
||||
|
||||
bool show2 = (showInLog && _so);
|
||||
|
||||
if (show2)
|
||||
{
|
||||
ClosePercents_for_so();
|
||||
|
||||
_tempA = command;
|
||||
if (name)
|
||||
_tempA.Add_Space();
|
||||
*_so << _tempA;
|
||||
|
||||
_tempU.Empty();
|
||||
if (name)
|
||||
{
|
||||
_tempU = name;
|
||||
_so->Normalize_UString(_tempU);
|
||||
}
|
||||
_so->PrintUString(_tempU, _tempA);
|
||||
*_so << endl;
|
||||
if (NeedFlush)
|
||||
_so->Flush();
|
||||
}
|
||||
|
||||
if (NeedPercents())
|
||||
{
|
||||
if (PercentsNameLevel >= 1)
|
||||
{
|
||||
_percent.FileName.Empty();
|
||||
_percent.Command.Empty();
|
||||
if (PercentsNameLevel > 1 || !show2)
|
||||
{
|
||||
_percent.Command = command;
|
||||
if (name)
|
||||
_percent.FileName = name;
|
||||
}
|
||||
}
|
||||
_percent.Print();
|
||||
}
|
||||
|
||||
return CheckBreak2();
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
|
||||
{
|
||||
if (StdOutMode)
|
||||
return S_OK;
|
||||
|
||||
if (!name || name[0] == 0)
|
||||
name = kEmptyFileAlias;
|
||||
|
||||
unsigned requiredLevel = 1;
|
||||
|
||||
const char *s;
|
||||
if (mode == NUpdateNotifyOp::kAdd ||
|
||||
mode == NUpdateNotifyOp::kUpdate)
|
||||
{
|
||||
if (isAnti)
|
||||
s = "Anti";
|
||||
else if (mode == NUpdateNotifyOp::kAdd)
|
||||
s = "+";
|
||||
else
|
||||
s = "U";
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredLevel = 3;
|
||||
if (mode == NUpdateNotifyOp::kAnalyze)
|
||||
s = "A";
|
||||
else
|
||||
s = "Reading";
|
||||
}
|
||||
|
||||
return PrintProgress(name, s, LogLevel >= requiredLevel);
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
|
||||
{
|
||||
return OpenFileError_Base(path, systemError);
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
|
||||
{
|
||||
return ReadingFileError_Base(path, systemError);
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
|
||||
{
|
||||
MT_LOCK
|
||||
_percent.Files++;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
|
||||
|
||||
HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
|
||||
{
|
||||
// if (StdOutMode) return S_OK;
|
||||
|
||||
if (opRes != NArchive::NExtract::NOperationResult::kOK)
|
||||
{
|
||||
ClosePercents2();
|
||||
|
||||
if (_se)
|
||||
{
|
||||
if (_so)
|
||||
_so->Flush();
|
||||
|
||||
AString s;
|
||||
SetExtractErrorMessage(opRes, isEncrypted, s);
|
||||
*_se << s << " : " << endl;
|
||||
_se->NormalizePrint_wstr(name);
|
||||
*_se << endl << endl;
|
||||
_se->Flush();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
|
||||
{
|
||||
// if (StdOutMode) return S_OK;
|
||||
|
||||
char temp[16];
|
||||
const char *s;
|
||||
|
||||
unsigned requiredLevel = 1;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case NUpdateNotifyOp::kAdd: s = "+"; break;
|
||||
case NUpdateNotifyOp::kUpdate: s = "U"; break;
|
||||
case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
|
||||
case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
|
||||
case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
|
||||
case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
|
||||
case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
|
||||
case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
|
||||
default:
|
||||
{
|
||||
temp[0] = 'o';
|
||||
temp[1] = 'p';
|
||||
ConvertUInt64ToString(op, temp + 2);
|
||||
s = temp;
|
||||
}
|
||||
}
|
||||
|
||||
return PrintProgress(name, s, LogLevel >= requiredLevel);
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CUpdateCallbackConsole::SetPassword(const UString &
|
||||
#ifndef _NO_CRYPTO
|
||||
password
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifndef _NO_CRYPTO
|
||||
PasswordIsDefined = true;
|
||||
Password = password;
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
*password = NULL;
|
||||
|
||||
#ifdef _NO_CRYPTO
|
||||
|
||||
*passwordIsDefined = false;
|
||||
return S_OK;
|
||||
|
||||
#else
|
||||
|
||||
if (!PasswordIsDefined)
|
||||
{
|
||||
if (AskPassword)
|
||||
{
|
||||
RINOK(GetPassword_HRESULT(_so, Password));
|
||||
PasswordIsDefined = true;
|
||||
}
|
||||
}
|
||||
*passwordIsDefined = BoolToInt(PasswordIsDefined);
|
||||
return StringToBstr(Password, password);
|
||||
|
||||
#endif
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
*password = NULL;
|
||||
|
||||
#ifdef _NO_CRYPTO
|
||||
|
||||
return E_NOTIMPL;
|
||||
|
||||
#else
|
||||
|
||||
if (!PasswordIsDefined)
|
||||
{
|
||||
{
|
||||
RINOK(GetPassword_HRESULT(_so, Password))
|
||||
PasswordIsDefined = true;
|
||||
}
|
||||
}
|
||||
return StringToBstr(Password, password);
|
||||
|
||||
#endif
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
|
||||
{
|
||||
if (StdOutMode)
|
||||
return S_OK;
|
||||
|
||||
if (LogLevel > 7)
|
||||
{
|
||||
if (!name || name[0] == 0)
|
||||
name = kEmptyFileAlias;
|
||||
return PrintProgress(name, "D", true);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// UpdateCallbackConsole.h
|
||||
|
||||
#ifndef __UPDATE_CALLBACK_CONSOLE_H
|
||||
#define __UPDATE_CALLBACK_CONSOLE_H
|
||||
|
||||
#include "../../../Common/StdOutStream.h"
|
||||
|
||||
#include "../Common/Update.h"
|
||||
|
||||
#include "PercentPrinter.h"
|
||||
|
||||
struct CErrorPathCodes
|
||||
{
|
||||
FStringVector Paths;
|
||||
CRecordVector<DWORD> Codes;
|
||||
|
||||
void AddError(const FString &path, DWORD systemError)
|
||||
{
|
||||
Paths.Add(path);
|
||||
Codes.Add(systemError);
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
Paths.Clear();
|
||||
Codes.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
class CCallbackConsoleBase
|
||||
{
|
||||
protected:
|
||||
CPercentPrinter _percent;
|
||||
|
||||
CStdOutStream *_so;
|
||||
CStdOutStream *_se;
|
||||
|
||||
void CommonError(const FString &path, DWORD systemError, bool isWarning);
|
||||
|
||||
HRESULT ScanError_Base(const FString &path, DWORD systemError);
|
||||
HRESULT OpenFileError_Base(const FString &name, DWORD systemError);
|
||||
HRESULT ReadingFileError_Base(const FString &name, DWORD systemError);
|
||||
|
||||
public:
|
||||
bool NeedPercents() const { return _percent._so != NULL; };
|
||||
|
||||
bool StdOutMode;
|
||||
|
||||
bool NeedFlush;
|
||||
unsigned PercentsNameLevel;
|
||||
unsigned LogLevel;
|
||||
|
||||
AString _tempA;
|
||||
UString _tempU;
|
||||
|
||||
CCallbackConsoleBase():
|
||||
StdOutMode(false),
|
||||
NeedFlush(false),
|
||||
PercentsNameLevel(1),
|
||||
LogLevel(0)
|
||||
{}
|
||||
|
||||
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
|
||||
|
||||
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
|
||||
{
|
||||
FailedFiles.Clear();
|
||||
|
||||
_so = outStream;
|
||||
_se = errorStream;
|
||||
_percent._so = percentStream;
|
||||
}
|
||||
|
||||
void ClosePercents2()
|
||||
{
|
||||
if (NeedPercents())
|
||||
_percent.ClosePrint(true);
|
||||
}
|
||||
|
||||
void ClosePercents_for_so()
|
||||
{
|
||||
if (NeedPercents() && _so == _percent._so)
|
||||
_percent.ClosePrint(false);
|
||||
}
|
||||
|
||||
|
||||
CErrorPathCodes FailedFiles;
|
||||
CErrorPathCodes ScanErrors;
|
||||
|
||||
HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog);
|
||||
|
||||
};
|
||||
|
||||
class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase
|
||||
{
|
||||
// void PrintPropPair(const char *name, const wchar_t *val);
|
||||
|
||||
public:
|
||||
#ifndef _NO_CRYPTO
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
bool AskPassword;
|
||||
#endif
|
||||
|
||||
bool DeleteMessageWasShown;
|
||||
|
||||
CUpdateCallbackConsole()
|
||||
: DeleteMessageWasShown(false)
|
||||
#ifndef _NO_CRYPTO
|
||||
, PasswordIsDefined(false)
|
||||
, AskPassword(false)
|
||||
#endif
|
||||
{}
|
||||
|
||||
/*
|
||||
void Init(CStdOutStream *outStream)
|
||||
{
|
||||
CCallbackConsoleBase::Init(outStream);
|
||||
}
|
||||
*/
|
||||
// ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); }
|
||||
INTERFACE_IUpdateCallbackUI2(;)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
// UserInputUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/StdInStream.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "UserInputUtils.h"
|
||||
|
||||
static const char kYes = 'y';
|
||||
static const char kNo = 'n';
|
||||
static const char kYesAll = 'a';
|
||||
static const char kNoAll = 's';
|
||||
static const char kAutoRenameAll = 'u';
|
||||
static const char kQuit = 'q';
|
||||
|
||||
static const char * const kFirstQuestionMessage = "? ";
|
||||
static const char * const kHelpQuestionMessage =
|
||||
"(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";
|
||||
|
||||
// return true if pressed Quite;
|
||||
|
||||
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
|
||||
{
|
||||
if (outStream)
|
||||
*outStream << kFirstQuestionMessage;
|
||||
for (;;)
|
||||
{
|
||||
if (outStream)
|
||||
{
|
||||
*outStream << kHelpQuestionMessage;
|
||||
outStream->Flush();
|
||||
}
|
||||
AString scannedString;
|
||||
if (!g_StdIn.ScanAStringUntilNewLine(scannedString))
|
||||
return NUserAnswerMode::kError;
|
||||
if (g_StdIn.Error())
|
||||
return NUserAnswerMode::kError;
|
||||
scannedString.Trim();
|
||||
if (scannedString.IsEmpty() && g_StdIn.Eof())
|
||||
return NUserAnswerMode::kEof;
|
||||
|
||||
if (scannedString.Len() == 1)
|
||||
switch (::MyCharLower_Ascii(scannedString[0]))
|
||||
{
|
||||
case kYes: return NUserAnswerMode::kYes;
|
||||
case kNo: return NUserAnswerMode::kNo;
|
||||
case kYesAll: return NUserAnswerMode::kYesAll;
|
||||
case kNoAll: return NUserAnswerMode::kNoAll;
|
||||
case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll;
|
||||
case kQuit: return NUserAnswerMode::kQuit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef UNDER_CE
|
||||
#define MY_DISABLE_ECHO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static bool GetPassword(CStdOutStream *outStream, UString &psw)
|
||||
{
|
||||
if (outStream)
|
||||
{
|
||||
*outStream << "\nEnter password"
|
||||
#ifdef MY_DISABLE_ECHO
|
||||
" (will not be echoed)"
|
||||
#endif
|
||||
":";
|
||||
outStream->Flush();
|
||||
}
|
||||
|
||||
#ifdef MY_DISABLE_ECHO
|
||||
|
||||
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
|
||||
bool wasChanged = false;
|
||||
DWORD mode = 0;
|
||||
if (console != INVALID_HANDLE_VALUE && console != 0)
|
||||
if (GetConsoleMode(console, &mode))
|
||||
wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0);
|
||||
bool res = g_StdIn.ScanUStringUntilNewLine(psw);
|
||||
if (wasChanged)
|
||||
SetConsoleMode(console, mode);
|
||||
|
||||
#else
|
||||
|
||||
bool res = g_StdIn.ScanUStringUntilNewLine(psw);
|
||||
|
||||
#endif
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
*outStream << endl;
|
||||
outStream->Flush();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw)
|
||||
{
|
||||
if (!GetPassword(outStream, psw))
|
||||
return E_INVALIDARG;
|
||||
if (g_StdIn.Error())
|
||||
return E_FAIL;
|
||||
if (g_StdIn.Eof() && psw.IsEmpty())
|
||||
return E_ABORT;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// UserInputUtils.h
|
||||
|
||||
#ifndef __USER_INPUT_UTILS_H
|
||||
#define __USER_INPUT_UTILS_H
|
||||
|
||||
#include "../../../Common/StdOutStream.h"
|
||||
|
||||
namespace NUserAnswerMode {
|
||||
|
||||
enum EEnum
|
||||
{
|
||||
kYes,
|
||||
kNo,
|
||||
kYesAll,
|
||||
kNoAll,
|
||||
kAutoRenameAll,
|
||||
kQuit,
|
||||
kEof,
|
||||
kError
|
||||
};
|
||||
}
|
||||
|
||||
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
|
||||
// bool GetPassword(CStdOutStream *outStream, UString &psw);
|
||||
HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user