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 17 using namespace NWindows; 18 using namespace NFile; 19 using namespace NDir; 20 21 static LPCSTR const kCantFindArchive = "Can not find archive file"; 22 static LPCSTR const kCantOpenArchive = "Can not open the file as archive"; 23 24 struct 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, 68 #ifdef LANG 69 0x02000603, 70 #endif 71 fs2us(dirPath)); 72 Result = E_FAIL; 73 return; 74 } 75 76 ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0); 77 78 Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback); 79 } 80 81 void Process() 82 { 83 try 84 { 85 #ifndef _NO_PROGRESS 86 CProgressCloser closer(ExtractCallbackSpec->ProgressDialog); 87 #endif 88 Process2(); 89 } 90 catch(...) { Result = E_FAIL; } 91 } 92 93 static THREAD_FUNC_DECL MyThreadFunction(void *param) 94 { 95 ((CThreadExtracting *)param)->Process(); 96 return 0; 97 } 98 }; 99 100 HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, 101 bool showProgress, bool &isCorrupt, UString &errorMessage) 102 { 103 isCorrupt = false; 104 CThreadExtracting t; 105 106 t.Codecs = codecs; 107 t.FileName = fileName; 108 t.DestFolder = destFolder; 109 110 t.ExtractCallbackSpec = new CExtractCallbackImp; 111 t.ExtractCallback = t.ExtractCallbackSpec; 112 113 #ifndef _NO_PROGRESS 114 115 if (showProgress) 116 { 117 t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON; 118 NWindows::CThread thread; 119 RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t)); 120 121 UString title; 122 LangString(IDS_PROGRESS_EXTRACTING, title); 123 t.ExtractCallbackSpec->StartProgressDialog(title, thread); 124 } 125 else 126 127 #endif 128 { 129 t.Process2(); 130 } 131 132 errorMessage = t.ErrorMessage; 133 if (errorMessage.IsEmpty()) 134 errorMessage = t.ExtractCallbackSpec->_message; 135 isCorrupt = t.ExtractCallbackSpec->_isCorrupt; 136 return t.Result; 137 } 138