1 // ExtractCallback.h 2 3 #ifndef __EXTRACT_CALLBACK_H 4 #define __EXTRACT_CALLBACK_H 5 6 #include "../../../../C/Alloc.h" 7 8 #include "../../../Common/MyCom.h" 9 #include "../../../Common/StringConvert.h" 10 11 #ifndef _SFX 12 #include "../Agent/IFolderArchive.h" 13 #endif 14 15 #include "../Common/ArchiveExtractCallback.h" 16 #include "../Common/ArchiveOpenCallback.h" 17 18 #ifndef _NO_CRYPTO 19 #include "../../IPassword.h" 20 #endif 21 22 #ifndef _SFX 23 #include "IFolder.h" 24 #endif 25 26 #include "ProgressDialog2.h" 27 28 #ifdef LANG 29 #include "LangUtils.h" 30 #endif 31 32 #ifndef _SFX 33 34 class CGrowBuf 35 { 36 Byte *_items; 37 size_t _size; 38 39 CGrowBuf(const CGrowBuf &buffer); 40 void operator=(const CGrowBuf &buffer); 41 42 public: 43 bool ReAlloc_KeepData(size_t newSize, size_t keepSize) 44 { 45 void *buf = MyAlloc(newSize); 46 if (!buf) 47 return false; 48 memcpy(buf, _items, keepSize); 49 MyFree(_items); 50 _items = (Byte *)buf; 51 _size = newSize; 52 return true; 53 } 54 55 CGrowBuf(): _items(0), _size(0) {} 56 ~CGrowBuf() { MyFree(_items); } 57 58 operator Byte *() { return _items; }; 59 operator const Byte *() const { return _items; }; 60 size_t Size() const { return _size; } 61 }; 62 63 struct CVirtFile 64 { 65 CGrowBuf Data; 66 67 UInt64 Size; // real size 68 UInt64 ExpectedSize; // the size from props request. 0 if unknown 69 70 UString Name; 71 72 bool CTimeDefined; 73 bool ATimeDefined; 74 bool MTimeDefined; 75 bool AttribDefined; 76 77 bool IsDir; 78 bool IsAltStream; 79 80 DWORD Attrib; 81 82 FILETIME CTime; 83 FILETIME ATime; 84 FILETIME MTime; 85 86 CVirtFile(): 87 CTimeDefined(false), 88 ATimeDefined(false), 89 MTimeDefined(false), 90 AttribDefined(false), 91 IsDir(false), 92 IsAltStream(false) {} 93 }; 94 95 class CVirtFileSystem: 96 public ISequentialOutStream, 97 public CMyUnknownImp 98 { 99 UInt64 _totalAllocSize; 100 101 size_t _pos; 102 unsigned _numFlushed; 103 bool _fileIsOpen; 104 bool _fileMode; 105 COutFileStream *_outFileStreamSpec; 106 CMyComPtr<ISequentialOutStream> _outFileStream; 107 public: 108 CObjectVector<CVirtFile> Files; 109 UInt64 MaxTotalAllocSize; 110 FString DirPrefix; 111 112 CVirtFile &AddNewFile() 113 { 114 if (!Files.IsEmpty()) 115 { 116 MaxTotalAllocSize -= Files.Back().Data.Size(); 117 } 118 return Files.AddNew(); 119 } 120 HRESULT CloseMemFile() 121 { 122 if (_fileMode) 123 { 124 return FlushToDisk(true); 125 } 126 CVirtFile &file = Files.Back(); 127 if (file.Data.Size() != file.Size) 128 { 129 file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size); 130 } 131 return S_OK; 132 } 133 134 bool IsStreamInMem() const 135 { 136 if (_fileMode) 137 return false; 138 if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir) 139 return false; 140 return true; 141 } 142 size_t GetMemStreamWrittenSize() const { return _pos; } 143 144 CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {} 145 146 void Init() 147 { 148 _totalAllocSize = 0; 149 _fileMode = false; 150 _pos = 0; 151 _numFlushed = 0; 152 _fileIsOpen = false; 153 } 154 155 HRESULT CloseFile(const FString &path); 156 HRESULT FlushToDisk(bool closeLast); 157 size_t GetPos() const { return _pos; } 158 159 MY_UNKNOWN_IMP 160 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); 161 }; 162 163 #endif 164 165 class CExtractCallbackImp: 166 public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback 167 public IOpenCallbackUI, 168 #ifndef _SFX 169 public IFolderOperationsExtractCallback, 170 public IFolderExtractToStreamCallback, 171 public ICompressProgressInfo, 172 #endif 173 #ifndef _NO_CRYPTO 174 public ICryptoGetTextPassword, 175 #endif 176 public CMyUnknownImp 177 { 178 HRESULT MessageError(const char *message, const FString &path); 179 public: 180 MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) 181 #ifndef _SFX 182 MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback) 183 MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback) 184 MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo) 185 #endif 186 #ifndef _NO_CRYPTO 187 MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) 188 #endif 189 MY_QUERYINTERFACE_END 190 MY_ADDREF_RELEASE 191 192 INTERFACE_IProgress(;) 193 INTERFACE_IOpenCallbackUI(;) 194 195 // IFolderArchiveExtractCallback 196 // STDMETHOD(SetTotalFiles)(UInt64 total); 197 // STDMETHOD(SetCompletedFiles)(const UInt64 *value); 198 STDMETHOD(AskOverwrite)( 199 const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, 200 const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, 201 Int32 *answer); 202 STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); 203 204 STDMETHOD(MessageError)(const wchar_t *message); 205 STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); 206 207 // IExtractCallbackUI 208 209 HRESULT BeforeOpen(const wchar_t *name); 210 HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); 211 HRESULT SetError(int level, const wchar_t *name, 212 UInt32 errorFlags, const wchar_t *errors, 213 UInt32 warningFlags, const wchar_t *warnings); 214 HRESULT ThereAreNoFiles(); 215 HRESULT ExtractResult(HRESULT result); 216 HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType); 217 218 #ifndef _NO_CRYPTO 219 HRESULT SetPassword(const UString &password); 220 #endif 221 222 #ifndef _SFX 223 // IFolderOperationsExtractCallback 224 STDMETHOD(AskWrite)( 225 const wchar_t *srcPath, 226 Int32 srcIsFolder, 227 const FILETIME *srcTime, 228 const UInt64 *srcSize, 229 const wchar_t *destPathRequest, 230 BSTR *destPathResult, 231 Int32 *writeAnswer); 232 STDMETHOD(ShowMessage)(const wchar_t *message); 233 STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath); 234 STDMETHOD(SetNumFiles)(UInt64 numFiles); 235 INTERFACE_IFolderExtractToStreamCallback(;) 236 STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); 237 #endif 238 239 // ICryptoGetTextPassword 240 #ifndef _NO_CRYPTO 241 STDMETHOD(CryptoGetTextPassword)(BSTR *password); 242 #endif 243 244 private: 245 UString _currentArchivePath; 246 bool _needWriteArchivePath; 247 248 UString _currentFilePath; 249 bool _isFolder; 250 251 bool _isAltStream; 252 UInt64 _curSize; 253 bool _curSizeDefined; 254 UString _filePath; 255 // bool _extractMode; 256 // bool _testMode; 257 bool _newVirtFileWasAdded; 258 bool _needUpdateStat; 259 260 261 HRESULT SetCurrentFilePath2(const wchar_t *filePath); 262 void AddError_Message(LPCWSTR message); 263 264 #ifndef _SFX 265 bool _hashStreamWasUsed; 266 COutStreamWithHash *_hashStreamSpec; 267 CMyComPtr<ISequentialOutStream> _hashStream; 268 IHashCalc *_hashCalc; // it's for stat in Test operation 269 #endif 270 271 public: 272 273 #ifndef _SFX 274 CVirtFileSystem *VirtFileSystemSpec; 275 CMyComPtr<ISequentialOutStream> VirtFileSystem; 276 #endif 277 278 bool ProcessAltStreams; 279 280 bool StreamMode; 281 282 CProgressDialog *ProgressDialog; 283 #ifndef _SFX 284 UInt64 NumFolders; 285 UInt64 NumFiles; 286 bool NeedAddFile; 287 #endif 288 UInt32 NumArchiveErrors; 289 bool ThereAreMessageErrors; 290 NExtract::NOverwriteMode::EEnum OverwriteMode; 291 292 #ifndef _NO_CRYPTO 293 bool PasswordIsDefined; 294 bool PasswordWasAsked; 295 UString Password; 296 #endif 297 298 CExtractCallbackImp(): 299 #ifndef _NO_CRYPTO 300 PasswordIsDefined(false), 301 PasswordWasAsked(false), 302 #endif 303 OverwriteMode(NExtract::NOverwriteMode::kAsk), 304 StreamMode(false), 305 ProcessAltStreams(true) 306 #ifndef _SFX 307 , _hashCalc(NULL) 308 #endif 309 {} 310 311 ~CExtractCallbackImp(); 312 void Init(); 313 314 #ifndef _SFX 315 void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; } 316 317 void SetHashMethods(IHashCalc *hash) 318 { 319 if (!hash) 320 return; 321 _hashStreamSpec = new COutStreamWithHash; 322 _hashStream = _hashStreamSpec; 323 _hashStreamSpec->_hash = hash; 324 } 325 #endif 326 327 bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; } 328 }; 329 330 #endif 331