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