• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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