Files
nsis-plugin-ns7zip/versions/26.00/CPP/7zip/UI/FileManager/ExtractCallback.h
T
Simone d074cc7c07 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
2026-04-29 14:07:51 +02:00

348 lines
8.7 KiB
C++

// ExtractCallback.h
#ifndef ZIP7_INC_EXTRACT_CALLBACK_H
#define ZIP7_INC_EXTRACT_CALLBACK_H
#include "../../../../C/Alloc.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/StringConvert.h"
#ifndef Z7_SFX
#include "../Agent/IFolderArchive.h"
#endif
#include "../Common/ArchiveExtractCallback.h"
#include "../Common/ArchiveOpenCallback.h"
#ifndef Z7_NO_CRYPTO
#include "../../IPassword.h"
#endif
#ifndef Z7_SFX
#include "IFolder.h"
#endif
#include "ProgressDialog2.h"
#ifndef Z7_SFX
class CGrowBuf
{
Byte *_items;
size_t _size;
Z7_CLASS_NO_COPY(CGrowBuf)
public:
void Free()
{
MyFree(_items);
_items = NULL;
_size = 0;
}
// newSize >= keepSize
bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
{
void *buf = NULL;
if (newSize)
{
buf = MyAlloc(newSize);
if (!buf)
return false;
}
if (keepSize)
memcpy(buf, _items, keepSize);
MyFree(_items);
_items = (Byte *)buf;
_size = newSize;
return true;
}
CGrowBuf(): _items(NULL), _size(0) {}
~CGrowBuf() { MyFree(_items); }
operator Byte *() { return _items; }
operator const Byte *() const { return _items; }
size_t Size() const { return _size; }
};
struct CVirtFile
{
CGrowBuf Data;
UInt64 ExpectedSize; // size from props request. 0 if unknown
size_t WrittenSize; // size of written data in (Data) buffer
// use (WrittenSize) only if (CVirtFileSystem::_newVirtFileStream_IsReadyToWrite == false)
UString BaseName; // original name of file inside archive,
// It's not path. So any path separators
// should be treated as part of name (or as incorrect chars)
UString AltStreamName;
bool CTime_Defined;
bool ATime_Defined;
bool MTime_Defined;
bool Attrib_Defined;
// bool IsDir;
bool IsAltStream;
bool ColonWasUsed;
DWORD Attrib;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
CVirtFile():
CTime_Defined(false),
ATime_Defined(false),
MTime_Defined(false),
Attrib_Defined(false),
// IsDir(false),
IsAltStream(false),
ColonWasUsed(false)
{}
};
/*
We use CVirtFileSystem only for single file extraction:
It supports the following cases and names:
- "fileName" : single file
- "fileName" item (main base file) and additional "fileName:altStream" items
- "altStream" : single item without "fileName:" prefix.
If file is flushed to disk, it uses Get_Correct_FsFile_Name(name).
*/
Z7_CLASS_IMP_NOQIB_1(
CVirtFileSystem,
ISequentialOutStream
)
unsigned _numFlushed;
public:
bool IsAltStreamFile; // in:
// = true, if extracting file is alt stream without "fileName:" prefix.
// = false, if extracting file is normal file, but additional
// alt streams "fileName:altStream" items are possible.
private:
bool _newVirtFileStream_IsReadyToWrite; // it can non real file (if can't open alt stream)
bool _needWriteToRealFile; // we need real writing to open file.
bool _wasSwitchedToFsMode;
bool _altStream_NeedRestore_Attrib_bool;
DWORD _altStream_NeedRestore_AttribVal;
CMyComPtr2<ISequentialOutStream, COutFileStream> _outFileStream;
public:
CObjectVector<CVirtFile> Files;
size_t MaxTotalAllocSize; // remain size, including Files.Back()
FString DirPrefix; // files will be flushed to this FS directory.
UString FileName; // name of file that will be extracted.
// it can be name of alt stream without "fileName:" prefix, if (IsAltStreamFile == trye).
// we use that name to detect altStream part in "FileName:altStream".
CByteBuffer ZoneBuf;
int Index_of_MainExtractedFile_in_Files; // out: index in Files. == -1, if expected file was not extracted
int Index_of_ZoneBuf_AltStream_in_Files; // out: index in Files. == -1, if no zonbuf alt stream
CVirtFileSystem()
{
_numFlushed = 0;
IsAltStreamFile = false;
_newVirtFileStream_IsReadyToWrite = false;
_needWriteToRealFile = false;
_wasSwitchedToFsMode = false;
_altStream_NeedRestore_Attrib_bool = false;
MaxTotalAllocSize = (size_t)0 - 1;
Index_of_MainExtractedFile_in_Files = -1;
Index_of_ZoneBuf_AltStream_in_Files = -1;
}
bool WasStreamFlushedToFS() const { return _wasSwitchedToFsMode; }
HRESULT CloseMemFile()
{
if (_wasSwitchedToFsMode)
return FlushToDisk(true); // closeLast
CVirtFile &file = Files.Back();
if (file.Data.Size() != file.WrittenSize)
file.Data.ReAlloc_KeepData(file.WrittenSize, file.WrittenSize);
return S_OK;
}
HRESULT FlushToDisk(bool closeLast);
};
#endif
class CExtractCallbackImp Z7_final:
public IFolderArchiveExtractCallback,
/* IExtractCallbackUI:
before v23.00 : it included IFolderArchiveExtractCallback
since v23.00 : it doesn't include IFolderArchiveExtractCallback
*/
public IExtractCallbackUI, // NON-COM interface since 23.00
public IOpenCallbackUI, // NON-COM interface
public IFolderArchiveExtractCallback2,
#ifndef Z7_SFX
public IFolderOperationsExtractCallback,
public IFolderExtractToStreamCallback,
public ICompressProgressInfo,
public IArchiveRequestMemoryUseCallback,
#endif
#ifndef Z7_NO_CRYPTO
public ICryptoGetTextPassword,
#endif
public CMyUnknownImp
{
Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback)
Z7_COM_QI_ENTRY(IFolderArchiveExtractCallback2)
#ifndef Z7_SFX
Z7_COM_QI_ENTRY(IFolderOperationsExtractCallback)
Z7_COM_QI_ENTRY(IFolderExtractToStreamCallback)
Z7_COM_QI_ENTRY(ICompressProgressInfo)
Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)
#endif
#ifndef Z7_NO_CRYPTO
Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
#endif
Z7_COM_QI_END
Z7_COM_ADDREF_RELEASE
Z7_IFACE_IMP(IExtractCallbackUI)
Z7_IFACE_IMP(IOpenCallbackUI)
Z7_IFACE_COM7_IMP(IProgress)
Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback)
Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback2)
#ifndef Z7_SFX
Z7_IFACE_COM7_IMP(IFolderOperationsExtractCallback)
Z7_IFACE_COM7_IMP(IFolderExtractToStreamCallback)
Z7_IFACE_COM7_IMP(ICompressProgressInfo)
Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
#endif
#ifndef Z7_NO_CRYPTO
Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
#endif
bool _needWriteArchivePath;
bool _isFolder;
bool _totalFiles_Defined;
bool _totalBytes_Defined;
public:
bool MultiArcMode;
bool ProcessAltStreams;
bool StreamMode; // set to true, if you want the callee to call GetStream7()
bool ThereAreMessageErrors;
bool Src_Is_IO_FS_Folder;
#ifndef Z7_NO_CRYPTO
bool PasswordIsDefined;
bool PasswordWasAsked;
#endif
private:
#ifndef Z7_SFX
bool _needUpdateStat;
bool _newVirtFileWasAdded;
bool _isAltStream;
// bool _extractMode;
// bool _testMode;
bool _hashStream_WasUsed;
bool _curSize_Defined;
bool NeedAddFile;
bool _remember;
bool _skipArc;
#endif
public:
bool YesToAll;
bool TestMode;
UInt32 NumArchiveErrors;
NExtract::NOverwriteMode::EEnum OverwriteMode;
private:
UString _currentArchivePath;
UString _currentFilePath;
UString _filePath; // virtual path than will be sent via IFolderExtractToStreamCallback
#ifndef Z7_SFX
UInt64 _curSize;
CMyComPtr2<ISequentialOutStream, COutStreamWithHash> _hashStream;
IHashCalc *_hashCalc; // it's for stat in Test operation
#endif
public:
CProgressDialog *ProgressDialog;
#ifndef Z7_SFX
CVirtFileSystem *VirtFileSystemSpec;
CMyComPtr<ISequentialOutStream> VirtFileSystem;
UInt64 NumFolders;
UInt64 NumFiles;
#endif
#ifndef Z7_NO_CRYPTO
UString Password;
#endif
UString _lang_Extracting;
UString _lang_Testing;
UString _lang_Skipping;
UString _lang_Reading;
UString _lang_Empty;
CExtractCallbackImp():
_totalFiles_Defined(false)
, _totalBytes_Defined(false)
, MultiArcMode(false)
, ProcessAltStreams(true)
, StreamMode(false)
, ThereAreMessageErrors(false)
, Src_Is_IO_FS_Folder(false)
#ifndef Z7_NO_CRYPTO
, PasswordIsDefined(false)
, PasswordWasAsked(false)
#endif
#ifndef Z7_SFX
, _remember(false)
, _skipArc(false)
#endif
, YesToAll(false)
, TestMode(false)
, OverwriteMode(NExtract::NOverwriteMode::kAsk)
#ifndef Z7_SFX
, _hashCalc(NULL)
#endif
{}
~CExtractCallbackImp();
void Init();
HRESULT SetCurrentFilePath2(const wchar_t *filePath);
void AddError_Message(LPCWSTR message);
void AddError_Message_ShowArcPath(LPCWSTR message);
HRESULT MessageError(const char *message, const FString &path);
void Add_ArchiveName_Error();
#ifndef Z7_SFX
void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
void SetHashMethods(IHashCalc *hash)
{
if (!hash)
return;
_hashStream.Create_if_Empty();
_hashStream->_hash = hash;
}
#endif
bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
};
#endif