xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/PanelCopy.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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