mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
436 lines
11 KiB
C++
Executable File
436 lines
11 KiB
C++
Executable File
/// PanelCopy.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "../Common/ZipRegistry.h"
|
|
|
|
#include "../GUI/HashGUI.h"
|
|
|
|
#include "FSFolder.h"
|
|
#include "ExtractCallback.h"
|
|
#include "LangUtils.h"
|
|
#include "Panel.h"
|
|
#include "UpdateCallback100.h"
|
|
|
|
#include "resource.h"
|
|
|
|
|
|
class CPanelCopyThread: public CProgressThreadVirt
|
|
{
|
|
bool ResultsWereShown;
|
|
bool NeedShowRes;
|
|
|
|
HRESULT ProcessVirt() Z7_override;
|
|
virtual void ProcessWasFinished_GuiVirt() Z7_override;
|
|
public:
|
|
const CCopyToOptions *options;
|
|
const UStringVector *CopyFrom_Paths;
|
|
CMyComPtr<IFolderOperations> FolderOperations;
|
|
CRecordVector<UInt32> Indices;
|
|
CExtractCallbackImp *ExtractCallbackSpec;
|
|
CMyComPtr<IFolderOperationsExtractCallback> ExtractCallback;
|
|
|
|
CHashBundle Hash;
|
|
// UString FirstFilePath;
|
|
|
|
// HRESULT Result2;
|
|
|
|
void ShowFinalResults(HWND hwnd);
|
|
|
|
CPanelCopyThread():
|
|
ResultsWereShown(false),
|
|
NeedShowRes(false),
|
|
CopyFrom_Paths(NULL)
|
|
// , Result2(E_FAIL)
|
|
{}
|
|
};
|
|
|
|
void CPanelCopyThread::ShowFinalResults(HWND hwnd)
|
|
{
|
|
if (NeedShowRes)
|
|
if (!ResultsWereShown)
|
|
{
|
|
ResultsWereShown = true;
|
|
ShowHashResults(Hash, hwnd);
|
|
}
|
|
}
|
|
|
|
void CPanelCopyThread::ProcessWasFinished_GuiVirt()
|
|
{
|
|
ShowFinalResults(*this);
|
|
}
|
|
|
|
HRESULT CPanelCopyThread::ProcessVirt()
|
|
{
|
|
/*
|
|
CMyComPtr<IFolderSetReplaceAltStreamCharsMode> iReplace;
|
|
FolderOperations.QueryInterface(IID_IFolderSetReplaceAltStreamCharsMode, &iReplace);
|
|
if (iReplace)
|
|
{
|
|
RINOK(iReplace->SetReplaceAltStreamCharsMode(ReplaceAltStreamChars ? 1 : 0));
|
|
}
|
|
*/
|
|
|
|
HRESULT result2;
|
|
|
|
if (FolderOperations)
|
|
{
|
|
CMyComPtr<IFolderSetZoneIdMode> setZoneMode;
|
|
FolderOperations.QueryInterface(IID_IFolderSetZoneIdMode, &setZoneMode);
|
|
if (setZoneMode)
|
|
{
|
|
RINOK(setZoneMode->SetZoneIdMode(options->ZoneIdMode))
|
|
}
|
|
}
|
|
|
|
if (CopyFrom_Paths)
|
|
{
|
|
result2 = NFsFolder::CopyFileSystemItems(
|
|
*CopyFrom_Paths,
|
|
us2fs(options->folder),
|
|
options->moveMode,
|
|
(IFolderOperationsExtractCallback *)ExtractCallbackSpec);
|
|
}
|
|
else if (options->testMode)
|
|
{
|
|
CMyComPtr<IArchiveFolder> archiveFolder;
|
|
FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder);
|
|
if (!archiveFolder)
|
|
return E_NOTIMPL;
|
|
CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
|
|
RINOK(ExtractCallback.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2))
|
|
NExtract::NPathMode::EEnum pathMode =
|
|
NExtract::NPathMode::kCurPaths;
|
|
// NExtract::NPathMode::kFullPathnames;
|
|
result2 = archiveFolder->Extract(&Indices.Front(), Indices.Size(),
|
|
BoolToInt(options->includeAltStreams),
|
|
BoolToInt(options->replaceAltStreamChars),
|
|
pathMode, NExtract::NOverwriteMode::kAsk,
|
|
options->folder, BoolToInt(true), extractCallback2);
|
|
}
|
|
else
|
|
result2 = FolderOperations->CopyTo(
|
|
BoolToInt(options->moveMode),
|
|
&Indices.Front(), Indices.Size(),
|
|
BoolToInt(options->includeAltStreams),
|
|
BoolToInt(options->replaceAltStreamChars),
|
|
options->folder, ExtractCallback);
|
|
|
|
if (result2 == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors)
|
|
{
|
|
if (!options->hashMethods.IsEmpty())
|
|
NeedShowRes = true;
|
|
else if (options->testMode)
|
|
{
|
|
CProgressMessageBoxPair &pair = GetMessagePair(false); // GetMessagePair(ExtractCallbackSpec->Hash.NumErrors != 0);
|
|
AddHashBundleRes(pair.Message, Hash);
|
|
}
|
|
}
|
|
|
|
return result2;
|
|
}
|
|
|
|
|
|
/*
|
|
#ifdef Z7_EXTERNAL_CODECS
|
|
|
|
static void ThrowException_if_Error(HRESULT res)
|
|
{
|
|
if (res != S_OK)
|
|
throw CSystemException(res);
|
|
}
|
|
|
|
#endif
|
|
*/
|
|
|
|
HRESULT CPanel::CopyTo(CCopyToOptions &options,
|
|
const CRecordVector<UInt32> &indices,
|
|
UStringVector *messages,
|
|
bool &usePassword, UString &password,
|
|
const UStringVector *filePaths)
|
|
{
|
|
if (options.NeedRegistryZone && !options.testMode)
|
|
{
|
|
CContextMenuInfo ci;
|
|
ci.Load();
|
|
if (ci.WriteZone != (UInt32)(Int32)-1)
|
|
options.ZoneIdMode = (NExtract::NZoneIdMode::EEnum)(int)(Int32)ci.WriteZone;
|
|
}
|
|
|
|
if (IsHashFolder())
|
|
{
|
|
if (!options.testMode)
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
if (!filePaths)
|
|
if (!_folderOperations)
|
|
{
|
|
const UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
|
|
if (options.showErrorMessages)
|
|
MessageBox_Error(errorMessage);
|
|
else if (messages)
|
|
messages->Add(errorMessage);
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT res = S_OK;
|
|
|
|
{
|
|
/*
|
|
#ifdef Z7_EXTERNAL_CODECS
|
|
CExternalCodecs g_ExternalCodecs;
|
|
#endif
|
|
*/
|
|
/* extracter.Hash uses g_ExternalCodecs
|
|
extracter must be declared after g_ExternalCodecs for correct destructor order !!! */
|
|
|
|
CPanelCopyThread extracter;
|
|
|
|
extracter.ExtractCallbackSpec = new CExtractCallbackImp;
|
|
extracter.ExtractCallback = extracter.ExtractCallbackSpec;
|
|
|
|
extracter.options = &options;
|
|
extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
|
|
extracter.CompressingMode = false;
|
|
|
|
extracter.ExtractCallbackSpec->StreamMode = options.streamMode;
|
|
|
|
|
|
if (indices.Size() == 1)
|
|
{
|
|
extracter.Hash.FirstFileName = GetItemRelPath(indices[0]);
|
|
extracter.Hash.MainName = extracter.Hash.FirstFileName;
|
|
}
|
|
|
|
if (options.VirtFileSystem)
|
|
{
|
|
extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystem;
|
|
extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec;
|
|
}
|
|
extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams;
|
|
|
|
if (!options.hashMethods.IsEmpty())
|
|
{
|
|
/* this code is used when we call CRC calculation for files in side archive
|
|
But new code uses global codecs so we don't need to call LoadGlobalCodecs again */
|
|
|
|
/*
|
|
#ifdef Z7_EXTERNAL_CODECS
|
|
ThrowException_if_Error(LoadGlobalCodecs());
|
|
#endif
|
|
*/
|
|
|
|
extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods);
|
|
extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash);
|
|
}
|
|
else if (options.testMode)
|
|
{
|
|
extracter.ExtractCallbackSpec->SetHashCalc(&extracter.Hash);
|
|
}
|
|
|
|
// extracter.Hash.Init();
|
|
|
|
UString title;
|
|
{
|
|
UInt32 titleID = IDS_COPYING;
|
|
if (options.moveMode)
|
|
titleID = IDS_MOVING;
|
|
else if (!options.hashMethods.IsEmpty() && options.streamMode)
|
|
{
|
|
titleID = IDS_CHECKSUM_CALCULATING;
|
|
if (options.hashMethods.Size() == 1)
|
|
{
|
|
const UString &s = options.hashMethods[0];
|
|
if (s != L"*")
|
|
title = s;
|
|
}
|
|
}
|
|
else if (options.testMode)
|
|
titleID = IDS_PROGRESS_TESTING;
|
|
|
|
if (title.IsEmpty())
|
|
title = LangString(titleID);
|
|
}
|
|
|
|
const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
|
|
|
|
extracter.MainWindow = GetParent();
|
|
extracter.MainTitle = progressWindowTitle;
|
|
extracter.MainAddTitle = title + L' ';
|
|
|
|
extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk;
|
|
extracter.ExtractCallbackSpec->Init();
|
|
|
|
extracter.CopyFrom_Paths = filePaths;
|
|
if (!filePaths)
|
|
{
|
|
extracter.Indices = indices;
|
|
extracter.FolderOperations = _folderOperations;
|
|
}
|
|
|
|
extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;
|
|
extracter.ExtractCallbackSpec->Password = password;
|
|
|
|
RINOK(extracter.Create(title, GetParent()))
|
|
|
|
|
|
if (messages)
|
|
*messages = extracter.Sync.Messages;
|
|
|
|
// res = extracter.Result2;
|
|
res = extracter.Result;
|
|
|
|
if (res == S_OK && extracter.ExtractCallbackSpec->IsOK())
|
|
{
|
|
usePassword = extracter.ExtractCallbackSpec->PasswordIsDefined;
|
|
password = extracter.ExtractCallbackSpec->Password;
|
|
}
|
|
|
|
extracter.ShowFinalResults(_window);
|
|
|
|
}
|
|
|
|
RefreshTitleAlways();
|
|
return res;
|
|
}
|
|
|
|
|
|
struct CThreadUpdate
|
|
{
|
|
CMyComPtr<IFolderOperations> FolderOperations;
|
|
UString FolderPrefix;
|
|
UStringVector FileNames;
|
|
CRecordVector<const wchar_t *> FileNamePointers;
|
|
CProgressDialog ProgressDialog;
|
|
CMyComPtr<IFolderArchiveUpdateCallback> UpdateCallback;
|
|
CUpdateCallback100Imp *UpdateCallbackSpec;
|
|
HRESULT Result;
|
|
bool MoveMode;
|
|
|
|
void Process()
|
|
{
|
|
try
|
|
{
|
|
CProgressCloser closer(ProgressDialog);
|
|
Result = FolderOperations->CopyFrom(
|
|
MoveMode,
|
|
FolderPrefix,
|
|
&FileNamePointers.Front(),
|
|
FileNamePointers.Size(),
|
|
UpdateCallback);
|
|
}
|
|
catch(...) { Result = E_FAIL; }
|
|
}
|
|
static THREAD_FUNC_DECL MyThreadFunction(void *param)
|
|
{
|
|
((CThreadUpdate *)param)->Process();
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
|
|
HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
|
|
bool showErrorMessages, UStringVector *messages)
|
|
{
|
|
if (IsHashFolder())
|
|
{
|
|
if (moveMode)
|
|
return E_NOTIMPL;
|
|
}
|
|
// CDisableNotify disableNotify(*this);
|
|
|
|
HRESULT res;
|
|
if (!_folderOperations)
|
|
res = E_NOINTERFACE;
|
|
else
|
|
{
|
|
CThreadUpdate updater;
|
|
updater.MoveMode = moveMode;
|
|
updater.UpdateCallbackSpec = new CUpdateCallback100Imp;
|
|
updater.UpdateCallback = updater.UpdateCallbackSpec;
|
|
updater.UpdateCallbackSpec->Init();
|
|
|
|
updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;
|
|
|
|
const UString title = LangString(IDS_COPYING);
|
|
const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
|
|
|
|
updater.ProgressDialog.MainWindow = GetParent();
|
|
updater.ProgressDialog.MainTitle = progressWindowTitle;
|
|
updater.ProgressDialog.MainAddTitle = title + L' ';
|
|
|
|
{
|
|
if (!_parentFolders.IsEmpty())
|
|
{
|
|
const CFolderLink &fl = _parentFolders.Back();
|
|
updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
|
|
updater.UpdateCallbackSpec->Password = fl.Password;
|
|
}
|
|
}
|
|
|
|
updater.FolderOperations = _folderOperations;
|
|
updater.FolderPrefix = folderPrefix;
|
|
updater.FileNames.ClearAndReserve(filePaths.Size());
|
|
unsigned i;
|
|
for (i = 0; i < filePaths.Size(); i++)
|
|
updater.FileNames.AddInReserved(filePaths[i]);
|
|
updater.FileNamePointers.ClearAndReserve(updater.FileNames.Size());
|
|
for (i = 0; i < updater.FileNames.Size(); i++)
|
|
updater.FileNamePointers.AddInReserved(updater.FileNames[i]);
|
|
|
|
{
|
|
NWindows::CThread thread;
|
|
const WRes wres = thread.Create(CThreadUpdate::MyThreadFunction, &updater);
|
|
if (wres != 0)
|
|
return HRESULT_FROM_WIN32(wres);
|
|
updater.ProgressDialog.Create(title, thread, GetParent());
|
|
}
|
|
|
|
if (messages)
|
|
*messages = updater.ProgressDialog.Sync.Messages;
|
|
|
|
res = updater.Result;
|
|
}
|
|
|
|
if (res == E_NOINTERFACE)
|
|
{
|
|
const UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
|
|
if (showErrorMessages)
|
|
MessageBox_Error(errorMessage);
|
|
else if (messages)
|
|
messages->Add(errorMessage);
|
|
return E_ABORT;
|
|
}
|
|
|
|
RefreshTitleAlways();
|
|
return res;
|
|
}
|
|
|
|
void CPanel::CopyFromNoAsk(bool moveMode, const UStringVector &filePaths)
|
|
{
|
|
CDisableTimerProcessing disableTimerProcessing(*this);
|
|
|
|
CSelectedState srcSelState;
|
|
SaveSelectedState(srcSelState);
|
|
|
|
CDisableNotify disableNotify(*this);
|
|
|
|
const HRESULT result = CopyFrom(moveMode, L"", filePaths, true, NULL);
|
|
|
|
if (result != S_OK)
|
|
{
|
|
disableNotify.Restore();
|
|
// For Password:
|
|
SetFocusToList();
|
|
if (result != E_ABORT)
|
|
MessageBox_Error_HRESULT(result);
|
|
return;
|
|
}
|
|
|
|
RefreshListCtrl(srcSelState);
|
|
|
|
disableNotify.Restore();
|
|
SetFocusToList();
|
|
}
|