1 // ExtractCallback.cpp
\r
5 #include "Windows/Error.h"
\r
6 #include "Windows/FileDir.h"
\r
7 #include "Windows/FileFind.h"
\r
9 #include "../../Common/FilePathAutoRename.h"
\r
11 #include "../GUI/ExtractRes.h"
\r
13 #include "ExtractCallback.h"
\r
14 #include "FormatUtils.h"
\r
15 #include "OverwriteDialog.h"
\r
17 #include "PasswordDialog.h"
\r
20 using namespace NWindows;
\r
21 using namespace NFile;
\r
22 using namespace NFind;
\r
24 CExtractCallbackImp::~CExtractCallbackImp() {}
\r
26 void CExtractCallbackImp::Init()
\r
28 NumArchiveErrors = 0;
\r
29 ThereAreMessageErrors = false;
\r
31 NumFolders = NumFiles = 0;
\r
32 NeedAddFile = false;
\r
36 void CExtractCallbackImp::AddErrorMessage(LPCWSTR message)
\r
38 ThereAreMessageErrors = true;
\r
39 ProgressDialog->Sync.AddErrorMessage(message);
\r
42 STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64
\r
49 ProgressDialog->Sync.SetNumFilesTotal(numFiles);
\r
54 STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total)
\r
56 ProgressDialog->Sync.SetProgress(total, 0);
\r
60 STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value)
\r
62 RINOK(ProgressDialog->Sync.ProcessStopAndPause());
\r
64 ProgressDialog->Sync.SetPos(*value);
\r
68 HRESULT CExtractCallbackImp::Open_CheckBreak()
\r
70 return ProgressDialog->Sync.ProcessStopAndPause();
\r
73 HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
\r
75 // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles);
\r
79 HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
\r
81 RINOK(ProgressDialog->Sync.ProcessStopAndPause());
\r
82 // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesCur(*numFiles);
\r
88 HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
\r
90 return CryptoGetTextPassword(password);
\r
93 HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(UString &password)
\r
95 if (PasswordIsDefined)
\r
96 password = Password;
\r
100 bool CExtractCallbackImp::Open_WasPasswordAsked()
\r
102 return PasswordWasAsked;
\r
105 void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag()
\r
107 PasswordWasAsked = false;
\r
114 STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
\r
116 ProgressDialog->Sync.SetRatioInfo(inSize, outSize);
\r
122 STDMETHODIMP CExtractCallbackImp::SetTotalFiles(UInt64 total)
\r
124 ProgressDialog->Sync.SetNumFilesTotal(total);
\r
128 STDMETHODIMP CExtractCallbackImp::SetCompletedFiles(const UInt64 *value)
\r
131 ProgressDialog->Sync.SetNumFilesCur(*value);
\r
136 STDMETHODIMP CExtractCallbackImp::AskOverwrite(
\r
137 const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
\r
138 const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
\r
141 COverwriteDialog dialog;
\r
143 dialog.OldFileInfo.SetTime(existTime);
\r
144 dialog.OldFileInfo.SetSize(existSize);
\r
145 dialog.OldFileInfo.Name = existName;
\r
147 dialog.NewFileInfo.SetTime(newTime);
\r
148 dialog.NewFileInfo.SetSize(newSize);
\r
149 dialog.NewFileInfo.Name = newName;
\r
151 ProgressDialog->WaitCreating();
\r
152 INT_PTR writeAnswer = dialog.Create(*ProgressDialog);
\r
154 switch(writeAnswer)
\r
156 case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT;
\r
157 case IDYES: *answer = NOverwriteAnswer::kYes; break;
\r
158 case IDNO: *answer = NOverwriteAnswer::kNo; break;
\r
159 case IDC_BUTTON_OVERWRITE_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break;
\r
160 case IDC_BUTTON_OVERWRITE_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break;
\r
161 case IDC_BUTTON_OVERWRITE_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break;
\r
162 default: return E_FAIL;
\r
168 STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */)
\r
170 _isFolder = isFolder;
\r
171 return SetCurrentFilePath2(name);
\r
174 STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message)
\r
176 AddErrorMessage(message);
\r
180 STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *message)
\r
182 AddErrorMessage(message);
\r
186 STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 operationResult, bool encrypted)
\r
188 switch(operationResult)
\r
190 case NArchive::NExtract::NOperationResult::kOK:
\r
196 switch(operationResult)
\r
198 case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
\r
199 messageID = IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;
\r
200 langID = 0x02000A91;
\r
202 case NArchive::NExtract::NOperationResult::kDataError:
\r
203 messageID = encrypted ?
\r
204 IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:
\r
205 IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR;
\r
206 langID = encrypted ? 0x02000A94 : 0x02000A92;
\r
208 case NArchive::NExtract::NOperationResult::kCRCError:
\r
209 messageID = encrypted ?
\r
210 IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED:
\r
211 IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC;
\r
212 langID = encrypted ? 0x02000A95 : 0x02000A93;
\r
217 if (_needWriteArchivePath)
\r
219 if (!_currentArchivePath.IsEmpty())
\r
220 AddErrorMessage(_currentArchivePath);
\r
221 _needWriteArchivePath = false;
\r
224 MyFormatNew(messageID,
\r
228 _currentFilePath));
\r
236 ProgressDialog->Sync.SetNumFilesCur(NumFiles);
\r
241 ////////////////////////////////////////
\r
242 // IExtractCallbackUI
\r
244 HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name)
\r
247 ProgressDialog->Sync.SetTitleFileName(name);
\r
249 _currentArchivePath = name;
\r
253 HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path)
\r
255 _currentFilePath = path;
\r
257 ProgressDialog->Sync.SetCurrentFileName(path);
\r
262 HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)
\r
267 NeedAddFile = true;
\r
268 ProgressDialog->Sync.SetNumFilesCur(NumFiles);
\r
270 return SetCurrentFilePath2(path);
\r
273 HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted)
\r
275 if (result != S_OK)
\r
278 if (result == S_FALSE)
\r
280 message = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE,
\r
282 (encrypted ? 0x0200060A : 0x02000609),
\r
291 if (result == E_OUTOFMEMORY)
\r
294 LangString(IDS_MEM_ERROR, 0x0200060B);
\r
296 MyLoadStringW(IDS_MEM_ERROR);
\r
299 NError::MyFormatMessage(result, message2);
\r
300 message += message2;
\r
302 MessageError(message);
\r
303 NumArchiveErrors++;
\r
305 _currentArchivePath = name;
\r
306 _needWriteArchivePath = true;
\r
310 HRESULT CExtractCallbackImp::ThereAreNoFiles()
\r
315 HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
\r
317 if (result == S_OK)
\r
319 NumArchiveErrors++;
\r
320 if (result == E_ABORT || result == ERROR_DISK_FULL)
\r
322 MessageError(_currentFilePath);
\r
323 MessageError(NError::MyFormatMessageW(result));
\r
329 HRESULT CExtractCallbackImp::SetPassword(const UString &password)
\r
331 PasswordIsDefined = true;
\r
332 Password = password;
\r
336 STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
\r
338 PasswordWasAsked = true;
\r
339 if (!PasswordIsDefined)
\r
341 CPasswordDialog dialog;
\r
342 ProgressDialog->WaitCreating();
\r
343 if (dialog.Create(*ProgressDialog) == IDCANCEL)
\r
345 Password = dialog.Password;
\r
346 PasswordIsDefined = true;
\r
348 return StringToBstr(Password, password);
\r
353 // IExtractCallBack3
\r
354 STDMETHODIMP CExtractCallbackImp::AskWrite(
\r
355 const wchar_t *srcPath, Int32 srcIsFolder,
\r
356 const FILETIME *srcTime, const UInt64 *srcSize,
\r
357 const wchar_t *destPath,
\r
358 BSTR *destPathResult,
\r
359 Int32 *writeAnswer)
\r
361 UString destPathResultTemp = destPath;
\r
363 // RINOK(StringToBstr(destPath, destPathResult));
\r
365 *destPathResult = 0;
\r
366 *writeAnswer = BoolToInt(false);
\r
368 UString destPathSpec = destPath;
\r
369 UString destPathSys = destPathSpec;
\r
370 bool srcIsFolderSpec = IntToBool(srcIsFolder);
\r
371 CFileInfoW destFileInfo;
\r
372 if (destFileInfo.Find(destPathSys))
\r
374 if (srcIsFolderSpec)
\r
376 if (!destFileInfo.IsDir())
\r
378 UString message = UString(L"can not replace file \'")
\r
380 UString(L"\' with folder with same name");
\r
381 RINOK(MessageError(message));
\r
384 *writeAnswer = BoolToInt(false);
\r
387 if (destFileInfo.IsDir())
\r
389 UString message = UString(L"can not replace folder \'")
\r
391 UString(L"\' with file with same name");
\r
392 RINOK(MessageError(message));
\r
396 switch(OverwriteMode)
\r
398 case NExtract::NOverwriteMode::kSkipExisting:
\r
400 case NExtract::NOverwriteMode::kAskBefore:
\r
402 Int32 overwiteResult;
\r
403 RINOK(AskOverwrite(
\r
405 &destFileInfo.MTime, &destFileInfo.Size,
\r
409 switch(overwiteResult)
\r
411 case NOverwriteAnswer::kCancel:
\r
413 case NOverwriteAnswer::kNo:
\r
415 case NOverwriteAnswer::kNoToAll:
\r
416 OverwriteMode = NExtract::NOverwriteMode::kSkipExisting;
\r
418 case NOverwriteAnswer::kYesToAll:
\r
419 OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
\r
421 case NOverwriteAnswer::kYes:
\r
423 case NOverwriteAnswer::kAutoRename:
\r
424 OverwriteMode = NExtract::NOverwriteMode::kAutoRename;
\r
431 if (OverwriteMode == NExtract::NOverwriteMode::kAutoRename)
\r
433 if (!AutoRenamePath(destPathSys))
\r
435 UString message = UString(L"can not create name of file ")
\r
437 RINOK(MessageError(message));
\r
440 destPathResultTemp = destPathSys;
\r
443 if (!NFile::NDirectory::DeleteFileAlways(destPathSys))
\r
445 UString message = UString(L"can not delete output file ")
\r
447 RINOK(MessageError(message));
\r
451 *writeAnswer = BoolToInt(true);
\r
452 return StringToBstr(destPathResultTemp, destPathResult);
\r