// ArchiveOpenCallback.h #ifndef ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H #define ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H #include "../../../Common/MyCom.h" #include "../../../Windows/FileFind.h" #include "../../Common/FileStreams.h" #ifndef Z7_NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" Z7_PURE_INTERFACES_BEGIN #ifdef Z7_NO_CRYPTO #define Z7_IFACEM_IOpenCallbackUI_Crypto(x) #else #define Z7_IFACEM_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 Z7_IFACEN_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 \ Z7_IFACEM_IOpenCallbackUI_Crypto(x) Z7_IFACE_DECL_PURE(IOpenCallbackUI) Z7_PURE_INTERFACES_END class CMultiStreams Z7_final { public: struct CSubStream { CMyComPtr Stream; CInFileStream *FileSpec; FString Path; // UInt64 Size; UInt64 LocalPos; int Next; // next older int Prev; // prev newer // bool IsOpen; CSubStream(): FileSpec(NULL), // Size(0), LocalPos(0), Next(-1), Prev(-1) // IsOpen(false) {} }; CObjectVector Streams; private: // we must use critical section here, if we want to access from different volumnes simultaneously int Head; // newest int Tail; // oldest unsigned NumListItems; unsigned NumOpenFiles_AllowedMax; public: CMultiStreams(); void Init(); HRESULT PrepareToOpenNew(); void InsertToList(unsigned index); void RemoveFromList(CSubStream &s); void CloseFile(unsigned index); HRESULT EnsureOpen(unsigned index); }; /* We need COpenCallbackImp class for multivolume processing. Also we use it as proxy from COM interfaces (IArchiveOpenCallback) to internal (IOpenCallbackUI) interfaces. If archive is multivolume: COpenCallbackImp object will exist after Open stage. COpenCallbackImp object will be deleted when last reference from each volume object (CInFileStreamVol) will be closed (when archive will be closed). */ class COpenCallbackImp Z7_final: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef Z7_NO_CRYPTO public ICryptoGetTextPassword, #endif public IProgress, // IProgress is used for 7zFM public CMyUnknownImp { Z7_COM_QI_BEGIN2(IArchiveOpenCallback) Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback) Z7_COM_QI_ENTRY(IArchiveOpenSetSubArchiveName) #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY(ICryptoGetTextPassword) #endif // Z7_COM_QI_ENTRY(IProgress) // the code doesn't require it Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IArchiveOpenCallback) Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback) Z7_IFACE_COM7_IMP(IProgress) public: Z7_IFACE_COM7_IMP(IArchiveOpenSetSubArchiveName) private: #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) #endif bool _subArchiveMode; public: bool PasswordWasAsked; UStringVector FileNames; CBoolVector FileNames_WasUsed; CRecordVector FileSizes; void AtCloseFile(unsigned fileIndex) { FileNames_WasUsed[fileIndex] = false; Volumes.CloseFile(fileIndex); } /* we have two ways to Callback from this object 1) IArchiveOpenCallback * ReOpenCallback - for ReOpen function, when IOpenCallbackUI is not available 2) IOpenCallbackUI *Callback - for usual callback we can't transfer IOpenCallbackUI pointer via internal interface, so we use ReOpenCallback to callback without IOpenCallbackUI. */ /* we use Callback/ReOpenCallback only at Open stage. So the CMyComPtr reference counter is not required, and we don't want additional reference to unused object, if COpenCallbackImp is not closed */ IArchiveOpenCallback *ReOpenCallback; // CMyComPtr ReOpenCallback; IOpenCallbackUI *Callback; // CMyComPtr Callback_Ref; private: FString _folderPrefix; UString _subArchiveName; NWindows::NFile::NFind::CFileInfo _fileInfo; public: CMultiStreams Volumes; // UInt64 TotalSize; COpenCallbackImp(): _subArchiveMode(false), ReOpenCallback(NULL), Callback(NULL) {} HRESULT Init2(const FString &folderPrefix, const FString &fileName); bool SetSecondFileInfo(CFSTR newName) { return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir(); } }; #endif