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 = &excl;
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