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