1 /// PanelCopy.cpp
2
3 #include "StdAfx.h"
4
5 #include "../Common/ZipRegistry.h"
6
7 #include "../GUI/HashGUI.h"
8
9 #include "FSFolder.h"
10 #include "ExtractCallback.h"
11 #include "LangUtils.h"
12 #include "Panel.h"
13 #include "UpdateCallback100.h"
14
15 #include "resource.h"
16
17
18 class CPanelCopyThread: public CProgressThreadVirt
19 {
20 bool ResultsWereShown;
21 bool NeedShowRes;
22
23 HRESULT ProcessVirt() Z7_override;
24 virtual void ProcessWasFinished_GuiVirt() Z7_override;
25 public:
26 const CCopyToOptions *options;
27 const UStringVector *CopyFrom_Paths;
28 CMyComPtr<IFolderOperations> FolderOperations;
29 CRecordVector<UInt32> Indices;
30 CExtractCallbackImp *ExtractCallbackSpec;
31 CMyComPtr<IFolderOperationsExtractCallback> ExtractCallback;
32
33 CHashBundle Hash;
34 // UString FirstFilePath;
35
36 // HRESULT Result2;
37
38 void ShowFinalResults(HWND hwnd);
39
CPanelCopyThread()40 CPanelCopyThread():
41 ResultsWereShown(false),
42 NeedShowRes(false),
43 CopyFrom_Paths(NULL)
44 // , Result2(E_FAIL)
45 {}
46 };
47
ShowFinalResults(HWND hwnd)48 void CPanelCopyThread::ShowFinalResults(HWND hwnd)
49 {
50 if (NeedShowRes)
51 if (!ResultsWereShown)
52 {
53 ResultsWereShown = true;
54 ShowHashResults(Hash, hwnd);
55 }
56 }
57
ProcessWasFinished_GuiVirt()58 void CPanelCopyThread::ProcessWasFinished_GuiVirt()
59 {
60 ShowFinalResults(*this);
61 }
62
ProcessVirt()63 HRESULT CPanelCopyThread::ProcessVirt()
64 {
65 /*
66 CMyComPtr<IFolderSetReplaceAltStreamCharsMode> iReplace;
67 FolderOperations.QueryInterface(IID_IFolderSetReplaceAltStreamCharsMode, &iReplace);
68 if (iReplace)
69 {
70 RINOK(iReplace->SetReplaceAltStreamCharsMode(ReplaceAltStreamChars ? 1 : 0));
71 }
72 */
73
74 HRESULT result2;
75
76 if (FolderOperations)
77 {
78 CMyComPtr<IFolderSetZoneIdMode> setZoneMode;
79 FolderOperations.QueryInterface(IID_IFolderSetZoneIdMode, &setZoneMode);
80 if (setZoneMode)
81 {
82 RINOK(setZoneMode->SetZoneIdMode(options->ZoneIdMode))
83 }
84 }
85
86 if (CopyFrom_Paths)
87 {
88 result2 = NFsFolder::CopyFileSystemItems(
89 *CopyFrom_Paths,
90 us2fs(options->folder),
91 options->moveMode,
92 (IFolderOperationsExtractCallback *)ExtractCallbackSpec);
93 }
94 else if (options->testMode)
95 {
96 CMyComPtr<IArchiveFolder> archiveFolder;
97 FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder);
98 if (!archiveFolder)
99 return E_NOTIMPL;
100 CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
101 RINOK(ExtractCallback.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2))
102 NExtract::NPathMode::EEnum pathMode =
103 NExtract::NPathMode::kCurPaths;
104 // NExtract::NPathMode::kFullPathnames;
105 result2 = archiveFolder->Extract(Indices.ConstData(), Indices.Size(),
106 BoolToInt(options->includeAltStreams),
107 BoolToInt(options->replaceAltStreamChars),
108 pathMode, NExtract::NOverwriteMode::kAsk,
109 options->folder, BoolToInt(true), extractCallback2);
110 }
111 else
112 result2 = FolderOperations->CopyTo(
113 BoolToInt(options->moveMode),
114 Indices.ConstData(), Indices.Size(),
115 BoolToInt(options->includeAltStreams),
116 BoolToInt(options->replaceAltStreamChars),
117 options->folder, ExtractCallback);
118
119 if (result2 == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors)
120 {
121 if (!options->hashMethods.IsEmpty())
122 NeedShowRes = true;
123 else if (options->testMode)
124 {
125 CProgressMessageBoxPair &pair = GetMessagePair(false); // GetMessagePair(ExtractCallbackSpec->Hash.NumErrors != 0);
126 AddHashBundleRes(pair.Message, Hash);
127 }
128 }
129
130 return result2;
131 }
132
133
134 /*
135 #ifdef Z7_EXTERNAL_CODECS
136
137 static void ThrowException_if_Error(HRESULT res)
138 {
139 if (res != S_OK)
140 throw CSystemException(res);
141 }
142
143 #endif
144 */
145
CopyTo(CCopyToOptions & options,const CRecordVector<UInt32> & indices,UStringVector * messages,bool & usePassword,UString & password,const UStringVector * filePaths)146 HRESULT CPanel::CopyTo(CCopyToOptions &options,
147 const CRecordVector<UInt32> &indices,
148 UStringVector *messages,
149 bool &usePassword, UString &password,
150 const UStringVector *filePaths)
151 {
152 if (options.NeedRegistryZone && !options.testMode)
153 {
154 CContextMenuInfo ci;
155 ci.Load();
156 if (ci.WriteZone != (UInt32)(Int32)-1)
157 options.ZoneIdMode = (NExtract::NZoneIdMode::EEnum)(int)(Int32)ci.WriteZone;
158 }
159
160 if (IsHashFolder())
161 {
162 if (!options.testMode)
163 return E_NOTIMPL;
164 }
165
166 if (!filePaths)
167 if (!_folderOperations)
168 {
169 const UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
170 if (options.showErrorMessages)
171 MessageBox_Error(errorMessage);
172 else if (messages)
173 messages->Add(errorMessage);
174 return E_FAIL;
175 }
176
177 HRESULT res = S_OK;
178
179 {
180 /*
181 #ifdef Z7_EXTERNAL_CODECS
182 CExternalCodecs g_ExternalCodecs;
183 #endif
184 */
185 /* extracter.Hash uses g_ExternalCodecs
186 extracter must be declared after g_ExternalCodecs for correct destructor order !!! */
187
188 CPanelCopyThread extracter;
189
190 extracter.ExtractCallbackSpec = new CExtractCallbackImp;
191 extracter.ExtractCallback = extracter.ExtractCallbackSpec;
192
193 extracter.options = &options;
194 extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
195 extracter.CompressingMode = false;
196
197 extracter.ExtractCallbackSpec->StreamMode = options.streamMode;
198
199
200 if (indices.Size() == 1)
201 {
202 extracter.Hash.FirstFileName = GetItemRelPath(indices[0]);
203 extracter.Hash.MainName = extracter.Hash.FirstFileName;
204 }
205
206 if (options.VirtFileSystem)
207 {
208 extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystem;
209 extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec;
210 }
211 extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams;
212
213 if (!options.hashMethods.IsEmpty())
214 {
215 /* this code is used when we call CRC calculation for files in side archive
216 But new code uses global codecs so we don't need to call LoadGlobalCodecs again */
217
218 /*
219 #ifdef Z7_EXTERNAL_CODECS
220 ThrowException_if_Error(LoadGlobalCodecs());
221 #endif
222 */
223
224 extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods);
225 extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash);
226 }
227 else if (options.testMode)
228 {
229 extracter.ExtractCallbackSpec->SetHashCalc(&extracter.Hash);
230 }
231
232 // extracter.Hash.Init();
233
234 UString title;
235 {
236 UInt32 titleID = IDS_COPYING;
237 if (options.moveMode)
238 titleID = IDS_MOVING;
239 else if (!options.hashMethods.IsEmpty() && options.streamMode)
240 {
241 titleID = IDS_CHECKSUM_CALCULATING;
242 if (options.hashMethods.Size() == 1)
243 {
244 const UString &s = options.hashMethods[0];
245 if (s != L"*")
246 title = s;
247 }
248 }
249 else if (options.testMode)
250 titleID = IDS_PROGRESS_TESTING;
251
252 if (title.IsEmpty())
253 title = LangString(titleID);
254 }
255
256 const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
257
258 extracter.MainWindow = GetParent();
259 extracter.MainTitle = progressWindowTitle;
260 extracter.MainAddTitle = title + L' ';
261
262 extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk;
263 extracter.ExtractCallbackSpec->Init();
264
265 extracter.CopyFrom_Paths = filePaths;
266 if (!filePaths)
267 {
268 extracter.Indices = indices;
269 extracter.FolderOperations = _folderOperations;
270 }
271
272 extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;
273 extracter.ExtractCallbackSpec->Password = password;
274
275 RINOK(extracter.Create(title, GetParent()))
276
277
278 if (messages)
279 *messages = extracter.Sync.Messages;
280
281 // res = extracter.Result2;
282 res = extracter.Result;
283
284 if (res == S_OK && extracter.ExtractCallbackSpec->IsOK())
285 {
286 usePassword = extracter.ExtractCallbackSpec->PasswordIsDefined;
287 password = extracter.ExtractCallbackSpec->Password;
288 }
289
290 extracter.ShowFinalResults(_window);
291
292 }
293
294 RefreshTitleAlways();
295 return res;
296 }
297
298
299 struct CThreadUpdate
300 {
301 CMyComPtr<IFolderOperations> FolderOperations;
302 UString FolderPrefix;
303 UStringVector FileNames;
304 CRecordVector<const wchar_t *> FileNamePointers;
305 CProgressDialog ProgressDialog;
306 CMyComPtr<IFolderArchiveUpdateCallback> UpdateCallback;
307 CUpdateCallback100Imp *UpdateCallbackSpec;
308 HRESULT Result;
309 bool MoveMode;
310
ProcessCThreadUpdate311 void Process()
312 {
313 try
314 {
315 CProgressCloser closer(ProgressDialog);
316 Result = FolderOperations->CopyFrom(
317 MoveMode,
318 FolderPrefix,
319 FileNamePointers.ConstData(),
320 FileNamePointers.Size(),
321 UpdateCallback);
322 }
323 catch(...) { Result = E_FAIL; }
324 }
MyThreadFunctionCThreadUpdate325 static THREAD_FUNC_DECL MyThreadFunction(void *param)
326 {
327 ((CThreadUpdate *)param)->Process();
328 return 0;
329 }
330 };
331
332
CopyFrom(bool moveMode,const UString & folderPrefix,const UStringVector & filePaths,bool showErrorMessages,UStringVector * messages)333 HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
334 bool showErrorMessages, UStringVector *messages)
335 {
336 if (IsHashFolder())
337 {
338 if (moveMode)
339 return E_NOTIMPL;
340 }
341 // CDisableNotify disableNotify(*this);
342
343 HRESULT res;
344 if (!_folderOperations)
345 res = E_NOINTERFACE;
346 else
347 {
348 CThreadUpdate updater;
349 updater.MoveMode = moveMode;
350 updater.UpdateCallbackSpec = new CUpdateCallback100Imp;
351 updater.UpdateCallback = updater.UpdateCallbackSpec;
352 updater.UpdateCallbackSpec->Init();
353
354 updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;
355
356 const UString title = LangString(IDS_COPYING);
357 const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
358
359 updater.ProgressDialog.MainWindow = GetParent();
360 updater.ProgressDialog.MainTitle = progressWindowTitle;
361 updater.ProgressDialog.MainAddTitle = title + L' ';
362
363 {
364 if (!_parentFolders.IsEmpty())
365 {
366 const CFolderLink &fl = _parentFolders.Back();
367 updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
368 updater.UpdateCallbackSpec->Password = fl.Password;
369 }
370 }
371
372 updater.FolderOperations = _folderOperations;
373 updater.FolderPrefix = folderPrefix;
374 updater.FileNames.ClearAndReserve(filePaths.Size());
375 unsigned i;
376 for (i = 0; i < filePaths.Size(); i++)
377 updater.FileNames.AddInReserved(filePaths[i]);
378 updater.FileNamePointers.ClearAndReserve(updater.FileNames.Size());
379 for (i = 0; i < updater.FileNames.Size(); i++)
380 updater.FileNamePointers.AddInReserved(updater.FileNames[i]);
381
382 {
383 NWindows::CThread thread;
384 const WRes wres = thread.Create(CThreadUpdate::MyThreadFunction, &updater);
385 if (wres != 0)
386 return HRESULT_FROM_WIN32(wres);
387 updater.ProgressDialog.Create(title, thread, GetParent());
388 }
389
390 if (messages)
391 *messages = updater.ProgressDialog.Sync.Messages;
392
393 res = updater.Result;
394 }
395
396 if (res == E_NOINTERFACE)
397 {
398 const UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
399 if (showErrorMessages)
400 MessageBox_Error(errorMessage);
401 else if (messages)
402 messages->Add(errorMessage);
403 return E_ABORT;
404 }
405
406 RefreshTitleAlways();
407 return res;
408 }
409
CopyFromNoAsk(bool moveMode,const UStringVector & filePaths)410 void CPanel::CopyFromNoAsk(bool moveMode, const UStringVector &filePaths)
411 {
412 CDisableTimerProcessing disableTimerProcessing(*this);
413
414 CSelectedState srcSelState;
415 SaveSelectedState(srcSelState);
416
417 CDisableNotify disableNotify(*this);
418
419 const HRESULT result = CopyFrom(moveMode, L"", filePaths, true, NULL);
420
421 if (result != S_OK)
422 {
423 disableNotify.Restore();
424 // For Password:
425 SetFocusToList();
426 if (result != E_ABORT)
427 MessageBox_Error_HRESULT(result);
428 return;
429 }
430
431 RefreshListCtrl(srcSelState);
432
433 disableNotify.Restore();
434 SetFocusToList();
435 }
436