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