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 LPCWSTR kCantFindArchive = L"Can not find archive file";
22 static LPCWSTR kCantOpenArchive = L"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
Process2CThreadExtracting37 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
ProcessCThreadExtracting82 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
MyThreadFunctionCThreadExtracting94 static THREAD_FUNC_DECL MyThreadFunction(void *param)
95 {
96 ((CThreadExtracting *)param)->Process();
97 return 0;
98 }
99 };
100
ExtractArchive(CCodecs * codecs,const FString & fileName,const FString & destFolder,bool showProgress,bool & isCorrupt,UString & errorMessage)101 HRESULT 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