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 {
79 CMyComPtr<IFolderSetZoneIdMode> setZoneMode;
80 FolderOperations.QueryInterface(IID_IFolderSetZoneIdMode, &setZoneMode);
81 if (setZoneMode)
82 {
83 RINOK(setZoneMode->SetZoneIdMode(options->ZoneIdMode))
84 }
85 }
86 {
87 CMyComPtr<IFolderSetZoneIdFile> setZoneFile;
88 FolderOperations.QueryInterface(IID_IFolderSetZoneIdFile, &setZoneFile);
89 if (setZoneFile)
90 {
91 RINOK(setZoneFile->SetZoneIdFile(options->ZoneBuf, (UInt32)options->ZoneBuf.Size()))
92 }
93 }
94 }
95
96 if (CopyFrom_Paths)
97 {
98 result2 = NFsFolder::CopyFileSystemItems(
99 *CopyFrom_Paths,
100 us2fs(options->folder),
101 options->moveMode,
102 (IFolderOperationsExtractCallback *)ExtractCallbackSpec);
103 }
104 else if (options->testMode)
105 {
106 CMyComPtr<IArchiveFolder> archiveFolder;
107 FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder);
108 if (!archiveFolder)
109 return E_NOTIMPL;
110 CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
111 RINOK(ExtractCallback.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2))
112 NExtract::NPathMode::EEnum pathMode =
113 NExtract::NPathMode::kCurPaths;
114 // NExtract::NPathMode::kFullPathnames;
115 result2 = archiveFolder->Extract(Indices.ConstData(), Indices.Size(),
116 BoolToInt(options->includeAltStreams),
117 BoolToInt(options->replaceAltStreamChars),
118 pathMode, NExtract::NOverwriteMode::kAsk,
119 options->folder, BoolToInt(true), extractCallback2);
120 }
121 else
122 result2 = FolderOperations->CopyTo(
123 BoolToInt(options->moveMode),
124 Indices.ConstData(), Indices.Size(),
125 BoolToInt(options->includeAltStreams),
126 BoolToInt(options->replaceAltStreamChars),
127 options->folder, ExtractCallback);
128
129 if (result2 == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors)
130 {
131 if (!options->hashMethods.IsEmpty())
132 NeedShowRes = true;
133 else if (options->testMode)
134 {
135 CProgressMessageBoxPair &pair = GetMessagePair(false); // GetMessagePair(ExtractCallbackSpec->Hash.NumErrors != 0);
136 AddHashBundleRes(pair.Message, Hash);
137 }
138 }
139
140 return result2;
141 }
142
143
144 /*
145 #ifdef Z7_EXTERNAL_CODECS
146
147 static void ThrowException_if_Error(HRESULT res)
148 {
149 if (res != S_OK)
150 throw CSystemException(res);
151 }
152
153 #endif
154 */
155
Get_ZoneId_Stream_from_ParentFolders(CByteBuffer & buf)156 void CPanel::Get_ZoneId_Stream_from_ParentFolders(CByteBuffer &buf)
157 {
158 // we suppose that ZoneId of top parent has priority over ZoneId from childs.
159 FOR_VECTOR (i, _parentFolders)
160 {
161 // _parentFolders[0] = is top level archive
162 // _parentFolders[1 ... ].isVirtual == true is possible
163 // if extracted size meets size conditions derived from g_RAM_Size.
164 const CFolderLink &fl = _parentFolders[i];
165 if (fl.IsVirtual)
166 {
167 if (fl.ZoneBuf.Size() != 0)
168 {
169 buf = fl.ZoneBuf;
170 return;
171 }
172 }
173 else if (!fl.FilePath.IsEmpty())
174 {
175 ReadZoneFile_Of_BaseFile(fl.FilePath, buf);
176 if (buf.Size() != 0)
177 return;
178 }
179 }
180 }
181
CopyTo(CCopyToOptions & options,const CRecordVector<UInt32> & indices,UStringVector * messages,bool & usePassword,UString & password,const UStringVector * filePaths)182 HRESULT CPanel::CopyTo(CCopyToOptions &options,
183 const CRecordVector<UInt32> &indices,
184 UStringVector *messages,
185 bool &usePassword, UString &password,
186 const UStringVector *filePaths)
187 {
188 if (options.NeedRegistryZone && !options.testMode)
189 {
190 CContextMenuInfo ci;
191 ci.Load();
192 if (ci.WriteZone != (UInt32)(Int32)-1)
193 options.ZoneIdMode = (NExtract::NZoneIdMode::EEnum)(int)(Int32)ci.WriteZone;
194 }
195
196 if (options.ZoneBuf.Size() == 0
197 && options.ZoneIdMode != NExtract::NZoneIdMode::kNone)
198 Get_ZoneId_Stream_from_ParentFolders(options.ZoneBuf);
199
200 if (IsHashFolder())
201 {
202 if (!options.testMode)
203 return E_NOTIMPL;
204 }
205
206 if (!filePaths)
207 if (!_folderOperations)
208 {
209 const UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
210 if (options.showErrorMessages)
211 MessageBox_Error(errorMessage);
212 else if (messages)
213 messages->Add(errorMessage);
214 return E_FAIL;
215 }
216
217 HRESULT res = S_OK;
218
219 {
220 /*
221 #ifdef Z7_EXTERNAL_CODECS
222 CExternalCodecs g_ExternalCodecs;
223 #endif
224 */
225 /* extracter.Hash uses g_ExternalCodecs
226 extracter must be declared after g_ExternalCodecs for correct destructor order !!! */
227
228 CPanelCopyThread extracter;
229
230 extracter.ExtractCallbackSpec = new CExtractCallbackImp;
231 extracter.ExtractCallback = extracter.ExtractCallbackSpec;
232 extracter.ExtractCallbackSpec->Src_Is_IO_FS_Folder =
233 IsFSFolder() || IsAltStreamsFolder();
234 // options.src_Is_IO_FS_Folder;
235 extracter.options = &options;
236 extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
237 extracter.CompressingMode = false;
238
239 extracter.ExtractCallbackSpec->StreamMode = options.streamMode;
240
241
242 if (indices.Size() == 1)
243 {
244 extracter.Hash.FirstFileName = GetItemRelPath(indices[0]);
245 extracter.Hash.MainName = extracter.Hash.FirstFileName;
246 }
247
248 if (options.VirtFileSystemSpec)
249 {
250 extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystemSpec;
251 extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec;
252 }
253 extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams;
254
255 if (!options.hashMethods.IsEmpty())
256 {
257 /* this code is used when we call CRC calculation for files in side archive
258 But new code uses global codecs so we don't need to call LoadGlobalCodecs again */
259
260 /*
261 #ifdef Z7_EXTERNAL_CODECS
262 ThrowException_if_Error(LoadGlobalCodecs());
263 #endif
264 */
265
266 extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods);
267 extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash);
268 }
269 else if (options.testMode)
270 {
271 extracter.ExtractCallbackSpec->SetHashCalc(&extracter.Hash);
272 }
273
274 // extracter.Hash.Init();
275
276 UString title;
277 {
278 UInt32 titleID = IDS_COPYING;
279 if (options.moveMode)
280 titleID = IDS_MOVING;
281 else if (!options.hashMethods.IsEmpty() && options.streamMode)
282 {
283 titleID = IDS_CHECKSUM_CALCULATING;
284 if (options.hashMethods.Size() == 1)
285 {
286 const UString &s = options.hashMethods[0];
287 if (s != L"*")
288 title = s;
289 }
290 }
291 else if (options.testMode)
292 titleID = IDS_PROGRESS_TESTING;
293
294 if (title.IsEmpty())
295 title = LangString(titleID);
296 }
297
298 const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
299
300 extracter.MainWindow = GetParent();
301 extracter.MainTitle = progressWindowTitle;
302 extracter.MainAddTitle = title + L' ';
303
304 extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk;
305 extracter.ExtractCallbackSpec->Init();
306
307 extracter.CopyFrom_Paths = filePaths;
308 if (!filePaths)
309 {
310 extracter.Indices = indices;
311 extracter.FolderOperations = _folderOperations;
312 }
313
314 extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;
315 extracter.ExtractCallbackSpec->Password = password;
316
317 RINOK(extracter.Create(title, GetParent()))
318
319
320 if (messages)
321 *messages = extracter.Sync.Messages;
322
323 // res = extracter.Result2;
324 res = extracter.Result;
325
326 if (res == S_OK && extracter.ExtractCallbackSpec->IsOK())
327 {
328 usePassword = extracter.ExtractCallbackSpec->PasswordIsDefined;
329 password = extracter.ExtractCallbackSpec->Password;
330 }
331
332 extracter.ShowFinalResults(_window);
333
334 }
335
336 RefreshTitleAlways();
337 return res;
338 }
339
340
341 struct CThreadUpdate
342 {
343 CMyComPtr<IFolderOperations> FolderOperations;
344 UString FolderPrefix;
345 UStringVector FileNames;
346 CRecordVector<const wchar_t *> FileNamePointers;
347 CProgressDialog ProgressDialog;
348 CMyComPtr<IFolderArchiveUpdateCallback> UpdateCallback;
349 CUpdateCallback100Imp *UpdateCallbackSpec;
350 HRESULT Result;
351 bool MoveMode;
352
ProcessCThreadUpdate353 void Process()
354 {
355 try
356 {
357 CProgressCloser closer(ProgressDialog);
358 Result = FolderOperations->CopyFrom(
359 MoveMode,
360 FolderPrefix,
361 FileNamePointers.ConstData(),
362 FileNamePointers.Size(),
363 UpdateCallback);
364 }
365 catch(...) { Result = E_FAIL; }
366 }
MyThreadFunctionCThreadUpdate367 static THREAD_FUNC_DECL MyThreadFunction(void *param)
368 {
369 ((CThreadUpdate *)param)->Process();
370 return 0;
371 }
372 };
373
374
CopyFrom(bool moveMode,const UString & folderPrefix,const UStringVector & filePaths,bool showErrorMessages,UStringVector * messages)375 HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
376 bool showErrorMessages, UStringVector *messages)
377 {
378 if (IsHashFolder())
379 {
380 if (moveMode)
381 return E_NOTIMPL;
382 }
383 // CDisableNotify disableNotify(*this);
384
385 HRESULT res;
386 if (!_folderOperations)
387 res = E_NOINTERFACE;
388 else
389 {
390 CThreadUpdate updater;
391 updater.MoveMode = moveMode;
392 updater.UpdateCallbackSpec = new CUpdateCallback100Imp;
393 updater.UpdateCallback = updater.UpdateCallbackSpec;
394 updater.UpdateCallbackSpec->Init();
395
396 updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;
397
398 const UString title = LangString(IDS_COPYING);
399 const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
400
401 updater.ProgressDialog.MainWindow = GetParent();
402 updater.ProgressDialog.MainTitle = progressWindowTitle;
403 updater.ProgressDialog.MainAddTitle = title + L' ';
404
405 {
406 if (!_parentFolders.IsEmpty())
407 {
408 const CFolderLink &fl = _parentFolders.Back();
409 updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
410 updater.UpdateCallbackSpec->Password = fl.Password;
411 }
412 }
413
414 updater.FolderOperations = _folderOperations;
415 updater.FolderPrefix = folderPrefix;
416 updater.FileNames.ClearAndReserve(filePaths.Size());
417 unsigned i;
418 for (i = 0; i < filePaths.Size(); i++)
419 updater.FileNames.AddInReserved(filePaths[i]);
420 updater.FileNamePointers.ClearAndReserve(updater.FileNames.Size());
421 for (i = 0; i < updater.FileNames.Size(); i++)
422 updater.FileNamePointers.AddInReserved(updater.FileNames[i]);
423
424 {
425 NWindows::CThread thread;
426 const WRes wres = thread.Create(CThreadUpdate::MyThreadFunction, &updater);
427 if (wres != 0)
428 return HRESULT_FROM_WIN32(wres);
429 updater.ProgressDialog.Create(title, thread, GetParent());
430 }
431
432 if (messages)
433 *messages = updater.ProgressDialog.Sync.Messages;
434
435 res = updater.Result;
436 }
437
438 if (res == E_NOINTERFACE)
439 {
440 const UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
441 if (showErrorMessages)
442 MessageBox_Error(errorMessage);
443 else if (messages)
444 messages->Add(errorMessage);
445 return E_ABORT;
446 }
447
448 RefreshTitleAlways();
449 return res;
450 }
451
CopyFromNoAsk(bool moveMode,const UStringVector & filePaths)452 void CPanel::CopyFromNoAsk(bool moveMode, const UStringVector &filePaths)
453 {
454 CDisableTimerProcessing disableTimerProcessing(*this);
455
456 CSelectedState srcSelState;
457 SaveSelectedState(srcSelState);
458
459 CDisableNotify disableNotify(*this);
460
461 const HRESULT result = CopyFrom(moveMode, L"", filePaths, true, NULL);
462
463 if (result != S_OK)
464 {
465 disableNotify.Restore();
466 // For Password:
467 SetFocusToList();
468 if (result != E_ABORT)
469 MessageBox_Error_HRESULT(result);
470 return;
471 }
472
473 RefreshListCtrl(srcSelState);
474
475 disableNotify.Restore();
476 SetFocusToList();
477 }
478