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 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, L"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 100HRESULT 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