1// ExtractEngine.cpp 2 3#include "StdAfx.h" 4 5#include "../../../Windows/FileDir.h" 6#include "../../../Windows/FileName.h" 7#include "../../../Windows/Thread.h" 8 9#include "../../UI/Common/OpenArchive.h" 10 11#include "../../UI/FileManager/FormatUtils.h" 12#include "../../UI/FileManager/LangUtils.h" 13 14#include "ExtractCallbackSfx.h" 15#include "ExtractEngine.h" 16 17using namespace NWindows; 18using namespace NFile; 19using namespace NDir; 20 21static LPCSTR const kCantFindArchive = "Cannot find archive file"; 22static LPCSTR const kCantOpenArchive = "Cannot open the file as archive"; 23 24struct CThreadExtracting 25{ 26 CCodecs *Codecs; 27 FString FileName; 28 FString DestFolder; 29 30 CExtractCallbackImp *ExtractCallbackSpec; 31 CMyComPtr<IArchiveExtractCallback> ExtractCallback; 32 33 CArchiveLink ArchiveLink; 34 HRESULT Result; 35 UString ErrorMessage; 36 37 void Process2() 38 { 39 NFind::CFileInfo fi; 40 if (!fi.Find(FileName)) 41 { 42 ErrorMessage = kCantFindArchive; 43 Result = E_FAIL; 44 return; 45 } 46 47 CObjectVector<COpenType> incl; 48 CIntVector excl; 49 COpenOptions options; 50 options.codecs = Codecs; 51 options.types = &incl; 52 options.excludedFormats = ! 53 options.filePath = fs2us(FileName); 54 55 Result = ArchiveLink.Open2(options, ExtractCallbackSpec); 56 if (Result != S_OK) 57 { 58 ErrorMessage = kCantOpenArchive; 59 return; 60 } 61 62 FString dirPath = DestFolder; 63 NName::NormalizeDirPathPrefix(dirPath); 64 65 if (!CreateComplexDir(dirPath)) 66 { 67 ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, fs2us(dirPath)); 68 Result = E_FAIL; 69 return; 70 } 71 72 ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0); 73 74 Result = ArchiveLink.GetArchive()->Extract(NULL, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback); 75 } 76 77 void Process() 78 { 79 try 80 { 81 #ifndef _NO_PROGRESS 82 CProgressCloser closer(ExtractCallbackSpec->ProgressDialog); 83 #endif 84 Process2(); 85 } 86 catch(...) { Result = E_FAIL; } 87 } 88 89 static THREAD_FUNC_DECL MyThreadFunction(void *param) 90 { 91 ((CThreadExtracting *)param)->Process(); 92 return 0; 93 } 94}; 95 96HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, 97 bool showProgress, bool &isCorrupt, UString &errorMessage) 98{ 99 isCorrupt = false; 100 CThreadExtracting t; 101 102 t.Codecs = codecs; 103 t.FileName = fileName; 104 t.DestFolder = destFolder; 105 106 t.ExtractCallbackSpec = new CExtractCallbackImp; 107 t.ExtractCallback = t.ExtractCallbackSpec; 108 109 #ifndef _NO_PROGRESS 110 111 if (showProgress) 112 { 113 t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON; 114 NWindows::CThread thread; 115 const WRes wres = thread.Create(CThreadExtracting::MyThreadFunction, &t); 116 if (wres != 0) 117 return HRESULT_FROM_WIN32(wres); 118 119 UString title; 120 LangString(IDS_PROGRESS_EXTRACTING, title); 121 t.ExtractCallbackSpec->StartProgressDialog(title, thread); 122 } 123 else 124 125 #endif 126 { 127 t.Process2(); 128 } 129 130 errorMessage = t.ErrorMessage; 131 if (errorMessage.IsEmpty()) 132 errorMessage = t.ExtractCallbackSpec->_message; 133 isCorrupt = t.ExtractCallbackSpec->_isCorrupt; 134 return t.Result; 135} 136