1// ExtractGUI.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6#include "../../../Common/StringConvert.h"
7
8#include "../../../Windows/FileDir.h"
9#include "../../../Windows/FileFind.h"
10#include "../../../Windows/FileName.h"
11#include "../../../Windows/Thread.h"
12
13#include "../FileManager/ExtractCallback.h"
14#include "../FileManager/FormatUtils.h"
15#include "../FileManager/LangUtils.h"
16#include "../FileManager/resourceGui.h"
17#include "../FileManager/OverwriteDialogRes.h"
18
19#include "../Common/ArchiveExtractCallback.h"
20#include "../Common/PropIDUtils.h"
21
22#include "../Explorer/MyMessages.h"
23
24#include "resource2.h"
25#include "ExtractRes.h"
26
27#include "ExtractDialog.h"
28#include "ExtractGUI.h"
29#include "HashGUI.h"
30
31#include "../FileManager/PropertyNameRes.h"
32
33using namespace NWindows;
34using namespace NFile;
35using namespace NDir;
36
37static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";
38
39#ifndef _SFX
40
41static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)
42{
43  AddLangString(s, resourceID);
44  if (addColon)
45    s += L':';
46  s.Add_Space();
47  char sz[32];
48  ConvertUInt64ToString(value, sz);
49  s.AddAscii(sz);
50  s.Add_LF();
51}
52
53static void AddSizePair(UString &s, UINT resourceID, UInt64 value)
54{
55  wchar_t sz[32];
56  AddLangString(s, resourceID);
57  s += L": ";
58  ConvertUInt64ToString(value, sz);
59  s += MyFormatNew(IDS_FILE_SIZE, sz);
60  // s += sz;
61  if (value >= (1 << 20))
62  {
63    ConvertUInt64ToString(value >> 20, sz);
64    s += L" (";
65    s += sz;
66    s += L" MB)";
67  }
68  s.Add_LF();
69}
70
71#endif
72
73class CThreadExtracting: public CProgressThreadVirt
74{
75  HRESULT ProcessVirt();
76public:
77  CCodecs *codecs;
78  CExtractCallbackImp *ExtractCallbackSpec;
79  const CObjectVector<COpenType> *FormatIndices;
80  const CIntVector *ExcludedFormatIndices;
81
82  UStringVector *ArchivePaths;
83  UStringVector *ArchivePathsFull;
84  const NWildcard::CCensorNode *WildcardCensor;
85  const CExtractOptions *Options;
86  #ifndef _SFX
87  CHashBundle *HashBundle;
88  #endif
89  CMyComPtr<IExtractCallbackUI> ExtractCallback;
90  UString Title;
91};
92
93HRESULT CThreadExtracting::ProcessVirt()
94{
95  CDecompressStat Stat;
96  #ifndef _SFX
97  if (HashBundle)
98    HashBundle->Init();
99  #endif
100
101  HRESULT res = Extract(codecs,
102      *FormatIndices, *ExcludedFormatIndices,
103      *ArchivePaths, *ArchivePathsFull,
104      *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback,
105      #ifndef _SFX
106        HashBundle,
107      #endif
108      FinalMessage.ErrorMessage.Message, Stat);
109  #ifndef _SFX
110  if (res == S_OK && Options->TestMode && ExtractCallbackSpec->IsOK())
111  {
112    UString s;
113
114    AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);
115    AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);
116
117    if (!HashBundle)
118    {
119      if (Stat.NumFolders != 0)
120        AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders);
121      AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles);
122      AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);
123      if (Stat.NumAltStreams != 0)
124      {
125        s.Add_LF();
126        AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);
127        AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);
128      }
129    }
130
131    if (HashBundle)
132    {
133      s.Add_LF();
134      AddHashBundleRes(s, *HashBundle, UString());
135    }
136
137    s.Add_LF();
138    AddLangString(s, IDS_MESSAGE_NO_ERRORS);
139
140    FinalMessage.OkMessage.Title = Title;
141    FinalMessage.OkMessage.Message = s;
142  }
143  #endif
144  return res;
145}
146
147HRESULT ExtractGUI(
148    CCodecs *codecs,
149    const CObjectVector<COpenType> &formatIndices,
150    const CIntVector &excludedFormatIndices,
151    UStringVector &archivePaths,
152    UStringVector &archivePathsFull,
153    const NWildcard::CCensorNode &wildcardCensor,
154    CExtractOptions &options,
155    #ifndef _SFX
156    CHashBundle *hb,
157    #endif
158    bool showDialog,
159    bool &messageWasDisplayed,
160    CExtractCallbackImp *extractCallback,
161    HWND hwndParent)
162{
163  messageWasDisplayed = false;
164
165  CThreadExtracting extracter;
166  extracter.codecs = codecs;
167  extracter.FormatIndices = &formatIndices;
168  extracter.ExcludedFormatIndices = &excludedFormatIndices;
169
170  if (!options.TestMode)
171  {
172    FString outputDir = options.OutputDir;
173    #ifndef UNDER_CE
174    if (outputDir.IsEmpty())
175      GetCurrentDir(outputDir);
176    #endif
177    if (showDialog)
178    {
179      CExtractDialog dialog;
180      FString outputDirFull;
181      if (!MyGetFullPathName(outputDir, outputDirFull))
182      {
183        ShowErrorMessage(kIncorrectOutDir);
184        messageWasDisplayed = true;
185        return E_FAIL;
186      }
187      NName::NormalizeDirPathPrefix(outputDirFull);
188
189      dialog.DirPath = fs2us(outputDirFull);
190
191      dialog.OverwriteMode = options.OverwriteMode;
192      dialog.OverwriteMode_Force = options.OverwriteMode_Force;
193      dialog.PathMode = options.PathMode;
194      dialog.PathMode_Force = options.PathMode_Force;
195      dialog.ElimDup = options.ElimDup;
196
197      if (archivePathsFull.Size() == 1)
198        dialog.ArcPath = archivePathsFull[0];
199
200      #ifndef _SFX
201      // dialog.AltStreams = options.NtOptions.AltStreams;
202      dialog.NtSecurity = options.NtOptions.NtSecurity;
203      if (extractCallback->PasswordIsDefined)
204        dialog.Password = extractCallback->Password;
205      #endif
206
207      if (dialog.Create(hwndParent) != IDOK)
208        return E_ABORT;
209
210      outputDir = us2fs(dialog.DirPath);
211
212      options.OverwriteMode = dialog.OverwriteMode;
213      options.PathMode = dialog.PathMode;
214      options.ElimDup = dialog.ElimDup;
215
216      #ifndef _SFX
217      // options.NtOptions.AltStreams = dialog.AltStreams;
218      options.NtOptions.NtSecurity = dialog.NtSecurity;
219      extractCallback->Password = dialog.Password;
220      extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty();
221      #endif
222    }
223    if (!MyGetFullPathName(outputDir, options.OutputDir))
224    {
225      ShowErrorMessage(kIncorrectOutDir);
226      messageWasDisplayed = true;
227      return E_FAIL;
228    }
229    NName::NormalizeDirPathPrefix(options.OutputDir);
230
231    /*
232    if (!CreateComplexDirectory(options.OutputDir))
233    {
234      UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));
235      UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,
236      #ifdef LANG
237      0x02000603,
238      #endif
239      options.OutputDir);
240      s2.Add_LF();
241      s2 += s;
242      MyMessageBox(s2);
243      return E_FAIL;
244    }
245    */
246  }
247
248  UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING);
249
250  extracter.Title = title;
251  extracter.ExtractCallbackSpec = extractCallback;
252  extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;
253  extracter.ExtractCallback = extractCallback;
254  extracter.ExtractCallbackSpec->Init();
255
256  extracter.ProgressDialog.CompressingMode = false;
257
258  extracter.ArchivePaths = &archivePaths;
259  extracter.ArchivePathsFull = &archivePathsFull;
260  extracter.WildcardCensor = &wildcardCensor;
261  extracter.Options = &options;
262  #ifndef _SFX
263  extracter.HashBundle = hb;
264  #endif
265
266  extracter.ProgressDialog.IconID = IDI_ICON;
267
268  RINOK(extracter.Create(title, hwndParent));
269  messageWasDisplayed = extracter.ThreadFinishedOK &
270      extracter.ProgressDialog.MessagesDisplayed;
271  return extracter.Result;
272}
273