1370b324cSopenharmony_ci// Client7z.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include <stdio.h>
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../../Common/MyWindows.h"
8370b324cSopenharmony_ci#include "../../../Common/MyInitGuid.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "../../../Common/Defs.h"
11370b324cSopenharmony_ci#include "../../../Common/IntToString.h"
12370b324cSopenharmony_ci#include "../../../Common/StringConvert.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#include "../../../Windows/DLL.h"
15370b324cSopenharmony_ci#include "../../../Windows/FileDir.h"
16370b324cSopenharmony_ci#include "../../../Windows/FileFind.h"
17370b324cSopenharmony_ci#include "../../../Windows/FileName.h"
18370b324cSopenharmony_ci#include "../../../Windows/NtCheck.h"
19370b324cSopenharmony_ci#include "../../../Windows/PropVariant.h"
20370b324cSopenharmony_ci#include "../../../Windows/PropVariantConv.h"
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci#include "../../Common/FileStreams.h"
23370b324cSopenharmony_ci
24370b324cSopenharmony_ci#include "../../Archive/IArchive.h"
25370b324cSopenharmony_ci
26370b324cSopenharmony_ci#include "../../IPassword.h"
27370b324cSopenharmony_ci#include "../../../../C/7zVersion.h"
28370b324cSopenharmony_ci
29370b324cSopenharmony_ci#ifdef _WIN32
30370b324cSopenharmony_ciextern
31370b324cSopenharmony_ciHINSTANCE g_hInstance;
32370b324cSopenharmony_ciHINSTANCE g_hInstance = NULL;
33370b324cSopenharmony_ci#endif
34370b324cSopenharmony_ci
35370b324cSopenharmony_ci// You can find full list of all GUIDs supported by 7-Zip in Guid.txt file.
36370b324cSopenharmony_ci// 7z format GUID: {23170F69-40C1-278A-1000-000110070000}
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci#define DEFINE_GUID_ARC(name, id) Z7_DEFINE_GUID(name, \
39370b324cSopenharmony_ci  0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, id, 0x00, 0x00);
40370b324cSopenharmony_ci
41370b324cSopenharmony_cienum
42370b324cSopenharmony_ci{
43370b324cSopenharmony_ci  kId_Zip = 1,
44370b324cSopenharmony_ci  kId_BZip2 = 2,
45370b324cSopenharmony_ci  kId_7z = 7,
46370b324cSopenharmony_ci  kId_Xz = 0xC,
47370b324cSopenharmony_ci  kId_Tar = 0xEE,
48370b324cSopenharmony_ci  kId_GZip = 0xEF
49370b324cSopenharmony_ci};
50370b324cSopenharmony_ci
51370b324cSopenharmony_ci// use another id, if you want to support other formats (zip, Xz, ...).
52370b324cSopenharmony_ci// DEFINE_GUID_ARC (CLSID_Format, kId_Zip)
53370b324cSopenharmony_ci// DEFINE_GUID_ARC (CLSID_Format, kId_BZip2)
54370b324cSopenharmony_ci// DEFINE_GUID_ARC (CLSID_Format, kId_Xz)
55370b324cSopenharmony_ci// DEFINE_GUID_ARC (CLSID_Format, kId_Tar)
56370b324cSopenharmony_ci// DEFINE_GUID_ARC (CLSID_Format, kId_GZip)
57370b324cSopenharmony_ciDEFINE_GUID_ARC (CLSID_Format, kId_7z)
58370b324cSopenharmony_ci
59370b324cSopenharmony_ciusing namespace NWindows;
60370b324cSopenharmony_ciusing namespace NFile;
61370b324cSopenharmony_ciusing namespace NDir;
62370b324cSopenharmony_ci
63370b324cSopenharmony_ci#ifdef _WIN32
64370b324cSopenharmony_ci#define kDllName "7z.dll"
65370b324cSopenharmony_ci#else
66370b324cSopenharmony_ci#define kDllName "7z.so"
67370b324cSopenharmony_ci#endif
68370b324cSopenharmony_ci
69370b324cSopenharmony_cistatic const char * const kCopyrightString =
70370b324cSopenharmony_ci  "\n"
71370b324cSopenharmony_ci  "7-Zip"
72370b324cSopenharmony_ci  " (" kDllName " client)"
73370b324cSopenharmony_ci  " " MY_VERSION
74370b324cSopenharmony_ci  " : " MY_COPYRIGHT_DATE
75370b324cSopenharmony_ci  "\n";
76370b324cSopenharmony_ci
77370b324cSopenharmony_cistatic const char * const kHelpString =
78370b324cSopenharmony_ci"Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n"
79370b324cSopenharmony_ci"Examples:\n"
80370b324cSopenharmony_ci"  7zcl.exe a archive.7z f1.txt f2.txt  : compress two files to archive.7z\n"
81370b324cSopenharmony_ci"  7zcl.exe l archive.7z   : List contents of archive.7z\n"
82370b324cSopenharmony_ci"  7zcl.exe x archive.7z   : eXtract files from archive.7z\n";
83370b324cSopenharmony_ci
84370b324cSopenharmony_ci
85370b324cSopenharmony_cistatic void Convert_UString_to_AString(const UString &s, AString &temp)
86370b324cSopenharmony_ci{
87370b324cSopenharmony_ci  int codePage = CP_OEMCP;
88370b324cSopenharmony_ci  /*
89370b324cSopenharmony_ci  int g_CodePage = -1;
90370b324cSopenharmony_ci  int codePage = g_CodePage;
91370b324cSopenharmony_ci  if (codePage == -1)
92370b324cSopenharmony_ci    codePage = CP_OEMCP;
93370b324cSopenharmony_ci  if (codePage == CP_UTF8)
94370b324cSopenharmony_ci    ConvertUnicodeToUTF8(s, temp);
95370b324cSopenharmony_ci  else
96370b324cSopenharmony_ci  */
97370b324cSopenharmony_ci    UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
98370b324cSopenharmony_ci}
99370b324cSopenharmony_ci
100370b324cSopenharmony_cistatic FString CmdStringToFString(const char *s)
101370b324cSopenharmony_ci{
102370b324cSopenharmony_ci  return us2fs(GetUnicodeString(s));
103370b324cSopenharmony_ci}
104370b324cSopenharmony_ci
105370b324cSopenharmony_cistatic void Print(const char *s)
106370b324cSopenharmony_ci{
107370b324cSopenharmony_ci  fputs(s, stdout);
108370b324cSopenharmony_ci}
109370b324cSopenharmony_ci
110370b324cSopenharmony_cistatic void Print(const AString &s)
111370b324cSopenharmony_ci{
112370b324cSopenharmony_ci  Print(s.Ptr());
113370b324cSopenharmony_ci}
114370b324cSopenharmony_ci
115370b324cSopenharmony_cistatic void Print(const UString &s)
116370b324cSopenharmony_ci{
117370b324cSopenharmony_ci  AString as;
118370b324cSopenharmony_ci  Convert_UString_to_AString(s, as);
119370b324cSopenharmony_ci  Print(as);
120370b324cSopenharmony_ci}
121370b324cSopenharmony_ci
122370b324cSopenharmony_cistatic void Print(const wchar_t *s)
123370b324cSopenharmony_ci{
124370b324cSopenharmony_ci  Print(UString(s));
125370b324cSopenharmony_ci}
126370b324cSopenharmony_ci
127370b324cSopenharmony_cistatic void PrintNewLine()
128370b324cSopenharmony_ci{
129370b324cSopenharmony_ci  Print("\n");
130370b324cSopenharmony_ci}
131370b324cSopenharmony_ci
132370b324cSopenharmony_cistatic void PrintStringLn(const char *s)
133370b324cSopenharmony_ci{
134370b324cSopenharmony_ci  Print(s);
135370b324cSopenharmony_ci  PrintNewLine();
136370b324cSopenharmony_ci}
137370b324cSopenharmony_ci
138370b324cSopenharmony_cistatic void PrintError(const char *message)
139370b324cSopenharmony_ci{
140370b324cSopenharmony_ci  Print("Error: ");
141370b324cSopenharmony_ci  PrintNewLine();
142370b324cSopenharmony_ci  Print(message);
143370b324cSopenharmony_ci  PrintNewLine();
144370b324cSopenharmony_ci}
145370b324cSopenharmony_ci
146370b324cSopenharmony_cistatic void PrintError(const char *message, const FString &name)
147370b324cSopenharmony_ci{
148370b324cSopenharmony_ci  PrintError(message);
149370b324cSopenharmony_ci  Print(name);
150370b324cSopenharmony_ci}
151370b324cSopenharmony_ci
152370b324cSopenharmony_ci
153370b324cSopenharmony_cistatic HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
154370b324cSopenharmony_ci{
155370b324cSopenharmony_ci  NCOM::CPropVariant prop;
156370b324cSopenharmony_ci  RINOK(archive->GetProperty(index, propID, &prop))
157370b324cSopenharmony_ci  if (prop.vt == VT_BOOL)
158370b324cSopenharmony_ci    result = VARIANT_BOOLToBool(prop.boolVal);
159370b324cSopenharmony_ci  else if (prop.vt == VT_EMPTY)
160370b324cSopenharmony_ci    result = false;
161370b324cSopenharmony_ci  else
162370b324cSopenharmony_ci    return E_FAIL;
163370b324cSopenharmony_ci  return S_OK;
164370b324cSopenharmony_ci}
165370b324cSopenharmony_ci
166370b324cSopenharmony_cistatic HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
167370b324cSopenharmony_ci{
168370b324cSopenharmony_ci  return IsArchiveItemProp(archive, index, kpidIsDir, result);
169370b324cSopenharmony_ci}
170370b324cSopenharmony_ci
171370b324cSopenharmony_ci
172370b324cSopenharmony_cistatic const wchar_t * const kEmptyFileAlias = L"[Content]";
173370b324cSopenharmony_ci
174370b324cSopenharmony_ci
175370b324cSopenharmony_ci//////////////////////////////////////////////////////////////
176370b324cSopenharmony_ci// Archive Open callback class
177370b324cSopenharmony_ci
178370b324cSopenharmony_ci
179370b324cSopenharmony_ciclass CArchiveOpenCallback Z7_final:
180370b324cSopenharmony_ci  public IArchiveOpenCallback,
181370b324cSopenharmony_ci  public ICryptoGetTextPassword,
182370b324cSopenharmony_ci  public CMyUnknownImp
183370b324cSopenharmony_ci{
184370b324cSopenharmony_ci  Z7_IFACES_IMP_UNK_2(IArchiveOpenCallback, ICryptoGetTextPassword)
185370b324cSopenharmony_cipublic:
186370b324cSopenharmony_ci
187370b324cSopenharmony_ci  bool PasswordIsDefined;
188370b324cSopenharmony_ci  UString Password;
189370b324cSopenharmony_ci
190370b324cSopenharmony_ci  CArchiveOpenCallback() : PasswordIsDefined(false) {}
191370b324cSopenharmony_ci};
192370b324cSopenharmony_ci
193370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */))
194370b324cSopenharmony_ci{
195370b324cSopenharmony_ci  return S_OK;
196370b324cSopenharmony_ci}
197370b324cSopenharmony_ci
198370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */))
199370b324cSopenharmony_ci{
200370b324cSopenharmony_ci  return S_OK;
201370b324cSopenharmony_ci}
202370b324cSopenharmony_ci
203370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password))
204370b324cSopenharmony_ci{
205370b324cSopenharmony_ci  if (!PasswordIsDefined)
206370b324cSopenharmony_ci  {
207370b324cSopenharmony_ci    // You can ask real password here from user
208370b324cSopenharmony_ci    // Password = GetPassword(OutStream);
209370b324cSopenharmony_ci    // PasswordIsDefined = true;
210370b324cSopenharmony_ci    PrintError("Password is not defined");
211370b324cSopenharmony_ci    return E_ABORT;
212370b324cSopenharmony_ci  }
213370b324cSopenharmony_ci  return StringToBstr(Password, password);
214370b324cSopenharmony_ci}
215370b324cSopenharmony_ci
216370b324cSopenharmony_ci
217370b324cSopenharmony_ci
218370b324cSopenharmony_cistatic const char * const kIncorrectCommand = "incorrect command";
219370b324cSopenharmony_ci
220370b324cSopenharmony_ci//////////////////////////////////////////////////////////////
221370b324cSopenharmony_ci// Archive Extracting callback class
222370b324cSopenharmony_ci
223370b324cSopenharmony_cistatic const char * const kTestingString    =  "Testing     ";
224370b324cSopenharmony_cistatic const char * const kExtractingString =  "Extracting  ";
225370b324cSopenharmony_cistatic const char * const kSkippingString   =  "Skipping    ";
226370b324cSopenharmony_cistatic const char * const kReadingString    =  "Reading     ";
227370b324cSopenharmony_ci
228370b324cSopenharmony_cistatic const char * const kUnsupportedMethod = "Unsupported Method";
229370b324cSopenharmony_cistatic const char * const kCRCFailed = "CRC Failed";
230370b324cSopenharmony_cistatic const char * const kDataError = "Data Error";
231370b324cSopenharmony_cistatic const char * const kUnavailableData = "Unavailable data";
232370b324cSopenharmony_cistatic const char * const kUnexpectedEnd = "Unexpected end of data";
233370b324cSopenharmony_cistatic const char * const kDataAfterEnd = "There are some data after the end of the payload data";
234370b324cSopenharmony_cistatic const char * const kIsNotArc = "Is not archive";
235370b324cSopenharmony_cistatic const char * const kHeadersError = "Headers Error";
236370b324cSopenharmony_ci
237370b324cSopenharmony_ci
238370b324cSopenharmony_cistruct CArcTime
239370b324cSopenharmony_ci{
240370b324cSopenharmony_ci  FILETIME FT;
241370b324cSopenharmony_ci  UInt16 Prec;
242370b324cSopenharmony_ci  Byte Ns100;
243370b324cSopenharmony_ci  bool Def;
244370b324cSopenharmony_ci
245370b324cSopenharmony_ci  CArcTime()
246370b324cSopenharmony_ci  {
247370b324cSopenharmony_ci    Clear();
248370b324cSopenharmony_ci  }
249370b324cSopenharmony_ci
250370b324cSopenharmony_ci  void Clear()
251370b324cSopenharmony_ci  {
252370b324cSopenharmony_ci    FT.dwHighDateTime = FT.dwLowDateTime = 0;
253370b324cSopenharmony_ci    Prec = 0;
254370b324cSopenharmony_ci    Ns100 = 0;
255370b324cSopenharmony_ci    Def = false;
256370b324cSopenharmony_ci  }
257370b324cSopenharmony_ci
258370b324cSopenharmony_ci  bool IsZero() const
259370b324cSopenharmony_ci  {
260370b324cSopenharmony_ci    return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0;
261370b324cSopenharmony_ci  }
262370b324cSopenharmony_ci
263370b324cSopenharmony_ci  int GetNumDigits() const
264370b324cSopenharmony_ci  {
265370b324cSopenharmony_ci    if (Prec == k_PropVar_TimePrec_Unix ||
266370b324cSopenharmony_ci        Prec == k_PropVar_TimePrec_DOS)
267370b324cSopenharmony_ci      return 0;
268370b324cSopenharmony_ci    if (Prec == k_PropVar_TimePrec_HighPrec)
269370b324cSopenharmony_ci      return 9;
270370b324cSopenharmony_ci    if (Prec == k_PropVar_TimePrec_0)
271370b324cSopenharmony_ci      return 7;
272370b324cSopenharmony_ci    int digits = (int)Prec - (int)k_PropVar_TimePrec_Base;
273370b324cSopenharmony_ci    if (digits < 0)
274370b324cSopenharmony_ci      digits = 0;
275370b324cSopenharmony_ci    return digits;
276370b324cSopenharmony_ci  }
277370b324cSopenharmony_ci
278370b324cSopenharmony_ci  void Write_To_FiTime(CFiTime &dest) const
279370b324cSopenharmony_ci  {
280370b324cSopenharmony_ci   #ifdef _WIN32
281370b324cSopenharmony_ci    dest = FT;
282370b324cSopenharmony_ci   #else
283370b324cSopenharmony_ci    if (FILETIME_To_timespec(FT, dest))
284370b324cSopenharmony_ci    if ((Prec == k_PropVar_TimePrec_Base + 8 ||
285370b324cSopenharmony_ci         Prec == k_PropVar_TimePrec_Base + 9)
286370b324cSopenharmony_ci        && Ns100 != 0)
287370b324cSopenharmony_ci    {
288370b324cSopenharmony_ci      dest.tv_nsec += Ns100;
289370b324cSopenharmony_ci    }
290370b324cSopenharmony_ci   #endif
291370b324cSopenharmony_ci  }
292370b324cSopenharmony_ci
293370b324cSopenharmony_ci  void Set_From_Prop(const PROPVARIANT &prop)
294370b324cSopenharmony_ci  {
295370b324cSopenharmony_ci    FT = prop.filetime;
296370b324cSopenharmony_ci    unsigned prec = 0;
297370b324cSopenharmony_ci    unsigned ns100 = 0;
298370b324cSopenharmony_ci    const unsigned prec_Temp = prop.wReserved1;
299370b324cSopenharmony_ci    if (prec_Temp != 0
300370b324cSopenharmony_ci        && prec_Temp <= k_PropVar_TimePrec_1ns
301370b324cSopenharmony_ci        && prop.wReserved3 == 0)
302370b324cSopenharmony_ci    {
303370b324cSopenharmony_ci      const unsigned ns100_Temp = prop.wReserved2;
304370b324cSopenharmony_ci      if (ns100_Temp < 100)
305370b324cSopenharmony_ci      {
306370b324cSopenharmony_ci        ns100 = ns100_Temp;
307370b324cSopenharmony_ci        prec = prec_Temp;
308370b324cSopenharmony_ci      }
309370b324cSopenharmony_ci    }
310370b324cSopenharmony_ci    Prec = (UInt16)prec;
311370b324cSopenharmony_ci    Ns100 = (Byte)ns100;
312370b324cSopenharmony_ci    Def = true;
313370b324cSopenharmony_ci  }
314370b324cSopenharmony_ci};
315370b324cSopenharmony_ci
316370b324cSopenharmony_ci
317370b324cSopenharmony_ci
318370b324cSopenharmony_ciclass CArchiveExtractCallback Z7_final:
319370b324cSopenharmony_ci  public IArchiveExtractCallback,
320370b324cSopenharmony_ci  public ICryptoGetTextPassword,
321370b324cSopenharmony_ci  public CMyUnknownImp
322370b324cSopenharmony_ci{
323370b324cSopenharmony_ci  Z7_IFACES_IMP_UNK_2(IArchiveExtractCallback, ICryptoGetTextPassword)
324370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(IProgress)
325370b324cSopenharmony_ci
326370b324cSopenharmony_ci  CMyComPtr<IInArchive> _archiveHandler;
327370b324cSopenharmony_ci  FString _directoryPath;  // Output directory
328370b324cSopenharmony_ci  UString _filePath;       // name inside arcvhive
329370b324cSopenharmony_ci  FString _diskFilePath;   // full path to file on disk
330370b324cSopenharmony_ci  bool _extractMode;
331370b324cSopenharmony_ci  struct CProcessedFileInfo
332370b324cSopenharmony_ci  {
333370b324cSopenharmony_ci    CArcTime MTime;
334370b324cSopenharmony_ci    UInt32 Attrib;
335370b324cSopenharmony_ci    bool isDir;
336370b324cSopenharmony_ci    bool Attrib_Defined;
337370b324cSopenharmony_ci  } _processedFileInfo;
338370b324cSopenharmony_ci
339370b324cSopenharmony_ci  COutFileStream *_outFileStreamSpec;
340370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> _outFileStream;
341370b324cSopenharmony_ci
342370b324cSopenharmony_cipublic:
343370b324cSopenharmony_ci  void Init(IInArchive *archiveHandler, const FString &directoryPath);
344370b324cSopenharmony_ci
345370b324cSopenharmony_ci  UInt64 NumErrors;
346370b324cSopenharmony_ci  bool PasswordIsDefined;
347370b324cSopenharmony_ci  UString Password;
348370b324cSopenharmony_ci
349370b324cSopenharmony_ci  CArchiveExtractCallback() : PasswordIsDefined(false) {}
350370b324cSopenharmony_ci};
351370b324cSopenharmony_ci
352370b324cSopenharmony_civoid CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath)
353370b324cSopenharmony_ci{
354370b324cSopenharmony_ci  NumErrors = 0;
355370b324cSopenharmony_ci  _archiveHandler = archiveHandler;
356370b324cSopenharmony_ci  _directoryPath = directoryPath;
357370b324cSopenharmony_ci  NName::NormalizeDirPathPrefix(_directoryPath);
358370b324cSopenharmony_ci}
359370b324cSopenharmony_ci
360370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 /* size */))
361370b324cSopenharmony_ci{
362370b324cSopenharmony_ci  return S_OK;
363370b324cSopenharmony_ci}
364370b324cSopenharmony_ci
365370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */))
366370b324cSopenharmony_ci{
367370b324cSopenharmony_ci  return S_OK;
368370b324cSopenharmony_ci}
369370b324cSopenharmony_ci
370370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index,
371370b324cSopenharmony_ci    ISequentialOutStream **outStream, Int32 askExtractMode))
372370b324cSopenharmony_ci{
373370b324cSopenharmony_ci  *outStream = NULL;
374370b324cSopenharmony_ci  _outFileStream.Release();
375370b324cSopenharmony_ci
376370b324cSopenharmony_ci  {
377370b324cSopenharmony_ci    // Get Name
378370b324cSopenharmony_ci    NCOM::CPropVariant prop;
379370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop))
380370b324cSopenharmony_ci
381370b324cSopenharmony_ci    UString fullPath;
382370b324cSopenharmony_ci    if (prop.vt == VT_EMPTY)
383370b324cSopenharmony_ci      fullPath = kEmptyFileAlias;
384370b324cSopenharmony_ci    else
385370b324cSopenharmony_ci    {
386370b324cSopenharmony_ci      if (prop.vt != VT_BSTR)
387370b324cSopenharmony_ci        return E_FAIL;
388370b324cSopenharmony_ci      fullPath = prop.bstrVal;
389370b324cSopenharmony_ci    }
390370b324cSopenharmony_ci    _filePath = fullPath;
391370b324cSopenharmony_ci  }
392370b324cSopenharmony_ci
393370b324cSopenharmony_ci  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)
394370b324cSopenharmony_ci    return S_OK;
395370b324cSopenharmony_ci
396370b324cSopenharmony_ci  {
397370b324cSopenharmony_ci    // Get Attrib
398370b324cSopenharmony_ci    NCOM::CPropVariant prop;
399370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop))
400370b324cSopenharmony_ci    if (prop.vt == VT_EMPTY)
401370b324cSopenharmony_ci    {
402370b324cSopenharmony_ci      _processedFileInfo.Attrib = 0;
403370b324cSopenharmony_ci      _processedFileInfo.Attrib_Defined = false;
404370b324cSopenharmony_ci    }
405370b324cSopenharmony_ci    else
406370b324cSopenharmony_ci    {
407370b324cSopenharmony_ci      if (prop.vt != VT_UI4)
408370b324cSopenharmony_ci        return E_FAIL;
409370b324cSopenharmony_ci      _processedFileInfo.Attrib = prop.ulVal;
410370b324cSopenharmony_ci      _processedFileInfo.Attrib_Defined = true;
411370b324cSopenharmony_ci    }
412370b324cSopenharmony_ci  }
413370b324cSopenharmony_ci
414370b324cSopenharmony_ci  RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir))
415370b324cSopenharmony_ci
416370b324cSopenharmony_ci  {
417370b324cSopenharmony_ci    _processedFileInfo.MTime.Clear();
418370b324cSopenharmony_ci    // Get Modified Time
419370b324cSopenharmony_ci    NCOM::CPropVariant prop;
420370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop))
421370b324cSopenharmony_ci    switch (prop.vt)
422370b324cSopenharmony_ci    {
423370b324cSopenharmony_ci      case VT_EMPTY:
424370b324cSopenharmony_ci        // _processedFileInfo.MTime = _utcMTimeDefault;
425370b324cSopenharmony_ci        break;
426370b324cSopenharmony_ci      case VT_FILETIME:
427370b324cSopenharmony_ci        _processedFileInfo.MTime.Set_From_Prop(prop);
428370b324cSopenharmony_ci        break;
429370b324cSopenharmony_ci      default:
430370b324cSopenharmony_ci        return E_FAIL;
431370b324cSopenharmony_ci    }
432370b324cSopenharmony_ci
433370b324cSopenharmony_ci  }
434370b324cSopenharmony_ci  {
435370b324cSopenharmony_ci    // Get Size
436370b324cSopenharmony_ci    NCOM::CPropVariant prop;
437370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop))
438370b324cSopenharmony_ci    UInt64 newFileSize;
439370b324cSopenharmony_ci    /* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize);
440370b324cSopenharmony_ci  }
441370b324cSopenharmony_ci
442370b324cSopenharmony_ci
443370b324cSopenharmony_ci  {
444370b324cSopenharmony_ci    // Create folders for file
445370b324cSopenharmony_ci    int slashPos = _filePath.ReverseFind_PathSepar();
446370b324cSopenharmony_ci    if (slashPos >= 0)
447370b324cSopenharmony_ci      CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos)));
448370b324cSopenharmony_ci  }
449370b324cSopenharmony_ci
450370b324cSopenharmony_ci  FString fullProcessedPath = _directoryPath + us2fs(_filePath);
451370b324cSopenharmony_ci  _diskFilePath = fullProcessedPath;
452370b324cSopenharmony_ci
453370b324cSopenharmony_ci  if (_processedFileInfo.isDir)
454370b324cSopenharmony_ci  {
455370b324cSopenharmony_ci    CreateComplexDir(fullProcessedPath);
456370b324cSopenharmony_ci  }
457370b324cSopenharmony_ci  else
458370b324cSopenharmony_ci  {
459370b324cSopenharmony_ci    NFind::CFileInfo fi;
460370b324cSopenharmony_ci    if (fi.Find(fullProcessedPath))
461370b324cSopenharmony_ci    {
462370b324cSopenharmony_ci      if (!DeleteFileAlways(fullProcessedPath))
463370b324cSopenharmony_ci      {
464370b324cSopenharmony_ci        PrintError("Cannot delete output file", fullProcessedPath);
465370b324cSopenharmony_ci        return E_ABORT;
466370b324cSopenharmony_ci      }
467370b324cSopenharmony_ci    }
468370b324cSopenharmony_ci
469370b324cSopenharmony_ci    _outFileStreamSpec = new COutFileStream;
470370b324cSopenharmony_ci    CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
471370b324cSopenharmony_ci    if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))
472370b324cSopenharmony_ci    {
473370b324cSopenharmony_ci      PrintError("Cannot open output file", fullProcessedPath);
474370b324cSopenharmony_ci      return E_ABORT;
475370b324cSopenharmony_ci    }
476370b324cSopenharmony_ci    _outFileStream = outStreamLoc;
477370b324cSopenharmony_ci    *outStream = outStreamLoc.Detach();
478370b324cSopenharmony_ci  }
479370b324cSopenharmony_ci  return S_OK;
480370b324cSopenharmony_ci}
481370b324cSopenharmony_ci
482370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode))
483370b324cSopenharmony_ci{
484370b324cSopenharmony_ci  _extractMode = false;
485370b324cSopenharmony_ci  switch (askExtractMode)
486370b324cSopenharmony_ci  {
487370b324cSopenharmony_ci    case NArchive::NExtract::NAskMode::kExtract:  _extractMode = true; break;
488370b324cSopenharmony_ci  }
489370b324cSopenharmony_ci  switch (askExtractMode)
490370b324cSopenharmony_ci  {
491370b324cSopenharmony_ci    case NArchive::NExtract::NAskMode::kExtract:  Print(kExtractingString); break;
492370b324cSopenharmony_ci    case NArchive::NExtract::NAskMode::kTest:  Print(kTestingString); break;
493370b324cSopenharmony_ci    case NArchive::NExtract::NAskMode::kSkip:  Print(kSkippingString); break;
494370b324cSopenharmony_ci    case NArchive::NExtract::NAskMode::kReadExternal: Print(kReadingString); break;
495370b324cSopenharmony_ci    default:
496370b324cSopenharmony_ci      Print("??? "); break;
497370b324cSopenharmony_ci  }
498370b324cSopenharmony_ci  Print(_filePath);
499370b324cSopenharmony_ci  return S_OK;
500370b324cSopenharmony_ci}
501370b324cSopenharmony_ci
502370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 operationResult))
503370b324cSopenharmony_ci{
504370b324cSopenharmony_ci  switch (operationResult)
505370b324cSopenharmony_ci  {
506370b324cSopenharmony_ci    case NArchive::NExtract::NOperationResult::kOK:
507370b324cSopenharmony_ci      break;
508370b324cSopenharmony_ci    default:
509370b324cSopenharmony_ci    {
510370b324cSopenharmony_ci      NumErrors++;
511370b324cSopenharmony_ci      Print("  :  ");
512370b324cSopenharmony_ci      const char *s = NULL;
513370b324cSopenharmony_ci      switch (operationResult)
514370b324cSopenharmony_ci      {
515370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
516370b324cSopenharmony_ci          s = kUnsupportedMethod;
517370b324cSopenharmony_ci          break;
518370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kCRCError:
519370b324cSopenharmony_ci          s = kCRCFailed;
520370b324cSopenharmony_ci          break;
521370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kDataError:
522370b324cSopenharmony_ci          s = kDataError;
523370b324cSopenharmony_ci          break;
524370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kUnavailable:
525370b324cSopenharmony_ci          s = kUnavailableData;
526370b324cSopenharmony_ci          break;
527370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
528370b324cSopenharmony_ci          s = kUnexpectedEnd;
529370b324cSopenharmony_ci          break;
530370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kDataAfterEnd:
531370b324cSopenharmony_ci          s = kDataAfterEnd;
532370b324cSopenharmony_ci          break;
533370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kIsNotArc:
534370b324cSopenharmony_ci          s = kIsNotArc;
535370b324cSopenharmony_ci          break;
536370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kHeadersError:
537370b324cSopenharmony_ci          s = kHeadersError;
538370b324cSopenharmony_ci          break;
539370b324cSopenharmony_ci      }
540370b324cSopenharmony_ci      if (s)
541370b324cSopenharmony_ci      {
542370b324cSopenharmony_ci        Print("Error : ");
543370b324cSopenharmony_ci        Print(s);
544370b324cSopenharmony_ci      }
545370b324cSopenharmony_ci      else
546370b324cSopenharmony_ci      {
547370b324cSopenharmony_ci        char temp[16];
548370b324cSopenharmony_ci        ConvertUInt32ToString((UInt32)operationResult, temp);
549370b324cSopenharmony_ci        Print("Error #");
550370b324cSopenharmony_ci        Print(temp);
551370b324cSopenharmony_ci      }
552370b324cSopenharmony_ci    }
553370b324cSopenharmony_ci  }
554370b324cSopenharmony_ci
555370b324cSopenharmony_ci  if (_outFileStream)
556370b324cSopenharmony_ci  {
557370b324cSopenharmony_ci    if (_processedFileInfo.MTime.Def)
558370b324cSopenharmony_ci    {
559370b324cSopenharmony_ci      CFiTime ft;
560370b324cSopenharmony_ci      _processedFileInfo.MTime.Write_To_FiTime(ft);
561370b324cSopenharmony_ci      _outFileStreamSpec->SetMTime(&ft);
562370b324cSopenharmony_ci    }
563370b324cSopenharmony_ci    RINOK(_outFileStreamSpec->Close())
564370b324cSopenharmony_ci  }
565370b324cSopenharmony_ci  _outFileStream.Release();
566370b324cSopenharmony_ci  if (_extractMode && _processedFileInfo.Attrib_Defined)
567370b324cSopenharmony_ci    SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib);
568370b324cSopenharmony_ci  PrintNewLine();
569370b324cSopenharmony_ci  return S_OK;
570370b324cSopenharmony_ci}
571370b324cSopenharmony_ci
572370b324cSopenharmony_ci
573370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password))
574370b324cSopenharmony_ci{
575370b324cSopenharmony_ci  if (!PasswordIsDefined)
576370b324cSopenharmony_ci  {
577370b324cSopenharmony_ci    // You can ask real password here from user
578370b324cSopenharmony_ci    // Password = GetPassword(OutStream);
579370b324cSopenharmony_ci    // PasswordIsDefined = true;
580370b324cSopenharmony_ci    PrintError("Password is not defined");
581370b324cSopenharmony_ci    return E_ABORT;
582370b324cSopenharmony_ci  }
583370b324cSopenharmony_ci  return StringToBstr(Password, password);
584370b324cSopenharmony_ci}
585370b324cSopenharmony_ci
586370b324cSopenharmony_ci
587370b324cSopenharmony_ci
588370b324cSopenharmony_ci//////////////////////////////////////////////////////////////
589370b324cSopenharmony_ci// Archive Creating callback class
590370b324cSopenharmony_ci
591370b324cSopenharmony_cistruct CDirItem: public NWindows::NFile::NFind::CFileInfoBase
592370b324cSopenharmony_ci{
593370b324cSopenharmony_ci  UString Path_For_Handler;
594370b324cSopenharmony_ci  FString FullPath; // for filesystem
595370b324cSopenharmony_ci
596370b324cSopenharmony_ci  CDirItem(const NWindows::NFile::NFind::CFileInfo &fi):
597370b324cSopenharmony_ci      CFileInfoBase(fi)
598370b324cSopenharmony_ci    {}
599370b324cSopenharmony_ci};
600370b324cSopenharmony_ci
601370b324cSopenharmony_ciclass CArchiveUpdateCallback Z7_final:
602370b324cSopenharmony_ci  public IArchiveUpdateCallback2,
603370b324cSopenharmony_ci  public ICryptoGetTextPassword2,
604370b324cSopenharmony_ci  public CMyUnknownImp
605370b324cSopenharmony_ci{
606370b324cSopenharmony_ci  Z7_IFACES_IMP_UNK_2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
607370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(IProgress)
608370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(IArchiveUpdateCallback)
609370b324cSopenharmony_ci
610370b324cSopenharmony_cipublic:
611370b324cSopenharmony_ci  CRecordVector<UInt64> VolumesSizes;
612370b324cSopenharmony_ci  UString VolName;
613370b324cSopenharmony_ci  UString VolExt;
614370b324cSopenharmony_ci
615370b324cSopenharmony_ci  FString DirPrefix;
616370b324cSopenharmony_ci  const CObjectVector<CDirItem> *DirItems;
617370b324cSopenharmony_ci
618370b324cSopenharmony_ci  bool PasswordIsDefined;
619370b324cSopenharmony_ci  UString Password;
620370b324cSopenharmony_ci  bool AskPassword;
621370b324cSopenharmony_ci
622370b324cSopenharmony_ci  bool m_NeedBeClosed;
623370b324cSopenharmony_ci
624370b324cSopenharmony_ci  FStringVector FailedFiles;
625370b324cSopenharmony_ci  CRecordVector<HRESULT> FailedCodes;
626370b324cSopenharmony_ci
627370b324cSopenharmony_ci  CArchiveUpdateCallback():
628370b324cSopenharmony_ci      DirItems(NULL),
629370b324cSopenharmony_ci      PasswordIsDefined(false),
630370b324cSopenharmony_ci      AskPassword(false)
631370b324cSopenharmony_ci      {}
632370b324cSopenharmony_ci
633370b324cSopenharmony_ci  ~CArchiveUpdateCallback() { Finilize(); }
634370b324cSopenharmony_ci  HRESULT Finilize();
635370b324cSopenharmony_ci
636370b324cSopenharmony_ci  void Init(const CObjectVector<CDirItem> *dirItems)
637370b324cSopenharmony_ci  {
638370b324cSopenharmony_ci    DirItems = dirItems;
639370b324cSopenharmony_ci    m_NeedBeClosed = false;
640370b324cSopenharmony_ci    FailedFiles.Clear();
641370b324cSopenharmony_ci    FailedCodes.Clear();
642370b324cSopenharmony_ci  }
643370b324cSopenharmony_ci};
644370b324cSopenharmony_ci
645370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::SetTotal(UInt64 /* size */))
646370b324cSopenharmony_ci{
647370b324cSopenharmony_ci  return S_OK;
648370b324cSopenharmony_ci}
649370b324cSopenharmony_ci
650370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */))
651370b324cSopenharmony_ci{
652370b324cSopenharmony_ci  return S_OK;
653370b324cSopenharmony_ci}
654370b324cSopenharmony_ci
655370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,
656370b324cSopenharmony_ci      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive))
657370b324cSopenharmony_ci{
658370b324cSopenharmony_ci  if (newData)
659370b324cSopenharmony_ci    *newData = BoolToInt(true);
660370b324cSopenharmony_ci  if (newProperties)
661370b324cSopenharmony_ci    *newProperties = BoolToInt(true);
662370b324cSopenharmony_ci  if (indexInArchive)
663370b324cSopenharmony_ci    *indexInArchive = (UInt32)(Int32)-1;
664370b324cSopenharmony_ci  return S_OK;
665370b324cSopenharmony_ci}
666370b324cSopenharmony_ci
667370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
668370b324cSopenharmony_ci{
669370b324cSopenharmony_ci  NCOM::CPropVariant prop;
670370b324cSopenharmony_ci
671370b324cSopenharmony_ci  if (propID == kpidIsAnti)
672370b324cSopenharmony_ci  {
673370b324cSopenharmony_ci    prop = false;
674370b324cSopenharmony_ci    prop.Detach(value);
675370b324cSopenharmony_ci    return S_OK;
676370b324cSopenharmony_ci  }
677370b324cSopenharmony_ci
678370b324cSopenharmony_ci  {
679370b324cSopenharmony_ci    const CDirItem &di = (*DirItems)[index];
680370b324cSopenharmony_ci    switch (propID)
681370b324cSopenharmony_ci    {
682370b324cSopenharmony_ci      case kpidPath:  prop = di.Path_For_Handler; break;
683370b324cSopenharmony_ci      case kpidIsDir:  prop = di.IsDir(); break;
684370b324cSopenharmony_ci      case kpidSize:  prop = di.Size; break;
685370b324cSopenharmony_ci      case kpidCTime:  PropVariant_SetFrom_FiTime(prop, di.CTime); break;
686370b324cSopenharmony_ci      case kpidATime:  PropVariant_SetFrom_FiTime(prop, di.ATime); break;
687370b324cSopenharmony_ci      case kpidMTime:  PropVariant_SetFrom_FiTime(prop, di.MTime); break;
688370b324cSopenharmony_ci      case kpidAttrib:  prop = (UInt32)di.GetWinAttrib(); break;
689370b324cSopenharmony_ci      case kpidPosixAttrib: prop = (UInt32)di.GetPosixAttrib(); break;
690370b324cSopenharmony_ci    }
691370b324cSopenharmony_ci  }
692370b324cSopenharmony_ci  prop.Detach(value);
693370b324cSopenharmony_ci  return S_OK;
694370b324cSopenharmony_ci}
695370b324cSopenharmony_ci
696370b324cSopenharmony_ciHRESULT CArchiveUpdateCallback::Finilize()
697370b324cSopenharmony_ci{
698370b324cSopenharmony_ci  if (m_NeedBeClosed)
699370b324cSopenharmony_ci  {
700370b324cSopenharmony_ci    PrintNewLine();
701370b324cSopenharmony_ci    m_NeedBeClosed = false;
702370b324cSopenharmony_ci  }
703370b324cSopenharmony_ci  return S_OK;
704370b324cSopenharmony_ci}
705370b324cSopenharmony_ci
706370b324cSopenharmony_cistatic void GetStream2(const wchar_t *name)
707370b324cSopenharmony_ci{
708370b324cSopenharmony_ci  Print("Compressing  ");
709370b324cSopenharmony_ci  if (name[0] == 0)
710370b324cSopenharmony_ci    name = kEmptyFileAlias;
711370b324cSopenharmony_ci  Print(name);
712370b324cSopenharmony_ci}
713370b324cSopenharmony_ci
714370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream))
715370b324cSopenharmony_ci{
716370b324cSopenharmony_ci  RINOK(Finilize())
717370b324cSopenharmony_ci
718370b324cSopenharmony_ci  const CDirItem &dirItem = (*DirItems)[index];
719370b324cSopenharmony_ci  GetStream2(dirItem.Path_For_Handler);
720370b324cSopenharmony_ci
721370b324cSopenharmony_ci  if (dirItem.IsDir())
722370b324cSopenharmony_ci    return S_OK;
723370b324cSopenharmony_ci
724370b324cSopenharmony_ci  {
725370b324cSopenharmony_ci    CInFileStream *inStreamSpec = new CInFileStream;
726370b324cSopenharmony_ci    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
727370b324cSopenharmony_ci    FString path = DirPrefix + dirItem.FullPath;
728370b324cSopenharmony_ci    if (!inStreamSpec->Open(path))
729370b324cSopenharmony_ci    {
730370b324cSopenharmony_ci      const DWORD sysError = ::GetLastError();
731370b324cSopenharmony_ci      FailedCodes.Add(HRESULT_FROM_WIN32(sysError));
732370b324cSopenharmony_ci      FailedFiles.Add(path);
733370b324cSopenharmony_ci      // if (systemError == ERROR_SHARING_VIOLATION)
734370b324cSopenharmony_ci      {
735370b324cSopenharmony_ci        PrintNewLine();
736370b324cSopenharmony_ci        PrintError("WARNING: can't open file");
737370b324cSopenharmony_ci        // Print(NError::MyFormatMessageW(systemError));
738370b324cSopenharmony_ci        return S_FALSE;
739370b324cSopenharmony_ci      }
740370b324cSopenharmony_ci      // return sysError;
741370b324cSopenharmony_ci    }
742370b324cSopenharmony_ci    *inStream = inStreamLoc.Detach();
743370b324cSopenharmony_ci  }
744370b324cSopenharmony_ci  return S_OK;
745370b324cSopenharmony_ci}
746370b324cSopenharmony_ci
747370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */))
748370b324cSopenharmony_ci{
749370b324cSopenharmony_ci  m_NeedBeClosed = true;
750370b324cSopenharmony_ci  return S_OK;
751370b324cSopenharmony_ci}
752370b324cSopenharmony_ci
753370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size))
754370b324cSopenharmony_ci{
755370b324cSopenharmony_ci  if (VolumesSizes.Size() == 0)
756370b324cSopenharmony_ci    return S_FALSE;
757370b324cSopenharmony_ci  if (index >= (UInt32)VolumesSizes.Size())
758370b324cSopenharmony_ci    index = VolumesSizes.Size() - 1;
759370b324cSopenharmony_ci  *size = VolumesSizes[index];
760370b324cSopenharmony_ci  return S_OK;
761370b324cSopenharmony_ci}
762370b324cSopenharmony_ci
763370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream))
764370b324cSopenharmony_ci{
765370b324cSopenharmony_ci  wchar_t temp[16];
766370b324cSopenharmony_ci  ConvertUInt32ToString(index + 1, temp);
767370b324cSopenharmony_ci  UString res = temp;
768370b324cSopenharmony_ci  while (res.Len() < 2)
769370b324cSopenharmony_ci    res.InsertAtFront(L'0');
770370b324cSopenharmony_ci  UString fileName = VolName;
771370b324cSopenharmony_ci  fileName.Add_Dot();
772370b324cSopenharmony_ci  fileName += res;
773370b324cSopenharmony_ci  fileName += VolExt;
774370b324cSopenharmony_ci  COutFileStream *streamSpec = new COutFileStream;
775370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
776370b324cSopenharmony_ci  if (!streamSpec->Create(us2fs(fileName), false))
777370b324cSopenharmony_ci    return GetLastError_noZero_HRESULT();
778370b324cSopenharmony_ci  *volumeStream = streamLoc.Detach();
779370b324cSopenharmony_ci  return S_OK;
780370b324cSopenharmony_ci}
781370b324cSopenharmony_ci
782370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password))
783370b324cSopenharmony_ci{
784370b324cSopenharmony_ci  if (!PasswordIsDefined)
785370b324cSopenharmony_ci  {
786370b324cSopenharmony_ci    if (AskPassword)
787370b324cSopenharmony_ci    {
788370b324cSopenharmony_ci      // You can ask real password here from user
789370b324cSopenharmony_ci      // Password = GetPassword(OutStream);
790370b324cSopenharmony_ci      // PasswordIsDefined = true;
791370b324cSopenharmony_ci      PrintError("Password is not defined");
792370b324cSopenharmony_ci      return E_ABORT;
793370b324cSopenharmony_ci    }
794370b324cSopenharmony_ci  }
795370b324cSopenharmony_ci  *passwordIsDefined = BoolToInt(PasswordIsDefined);
796370b324cSopenharmony_ci  return StringToBstr(Password, password);
797370b324cSopenharmony_ci}
798370b324cSopenharmony_ci
799370b324cSopenharmony_ci
800370b324cSopenharmony_ci// Main function
801370b324cSopenharmony_ci
802370b324cSopenharmony_ci#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
803370b324cSopenharmony_ci#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
804370b324cSopenharmony_ci#endif
805370b324cSopenharmony_ci
806370b324cSopenharmony_ciint Z7_CDECL main(int numArgs, const char *args[])
807370b324cSopenharmony_ci{
808370b324cSopenharmony_ci  NT_CHECK
809370b324cSopenharmony_ci
810370b324cSopenharmony_ci  #ifdef ENV_HAVE_LOCALE
811370b324cSopenharmony_ci  MY_SetLocale();
812370b324cSopenharmony_ci  #endif
813370b324cSopenharmony_ci
814370b324cSopenharmony_ci  PrintStringLn(kCopyrightString);
815370b324cSopenharmony_ci
816370b324cSopenharmony_ci  if (numArgs < 2)
817370b324cSopenharmony_ci  {
818370b324cSopenharmony_ci    PrintStringLn(kHelpString);
819370b324cSopenharmony_ci    return 0;
820370b324cSopenharmony_ci  }
821370b324cSopenharmony_ci
822370b324cSopenharmony_ci  FString dllPrefix;
823370b324cSopenharmony_ci
824370b324cSopenharmony_ci  #ifdef _WIN32
825370b324cSopenharmony_ci  dllPrefix = NDLL::GetModuleDirPrefix();
826370b324cSopenharmony_ci  #else
827370b324cSopenharmony_ci  {
828370b324cSopenharmony_ci    AString s (args[0]);
829370b324cSopenharmony_ci    int sep = s.ReverseFind_PathSepar();
830370b324cSopenharmony_ci    s.DeleteFrom(sep + 1);
831370b324cSopenharmony_ci    dllPrefix = s;
832370b324cSopenharmony_ci  }
833370b324cSopenharmony_ci  #endif
834370b324cSopenharmony_ci
835370b324cSopenharmony_ci  NDLL::CLibrary lib;
836370b324cSopenharmony_ci  if (!lib.Load(dllPrefix + FTEXT(kDllName)))
837370b324cSopenharmony_ci  {
838370b324cSopenharmony_ci    PrintError("Cannot load 7-zip library");
839370b324cSopenharmony_ci    return 1;
840370b324cSopenharmony_ci  }
841370b324cSopenharmony_ci
842370b324cSopenharmony_ci  Func_CreateObject
843370b324cSopenharmony_ci     f_CreateObject = Z7_GET_PROC_ADDRESS(
844370b324cSopenharmony_ci  Func_CreateObject, lib.Get_HMODULE(),
845370b324cSopenharmony_ci      "CreateObject");
846370b324cSopenharmony_ci  if (!f_CreateObject)
847370b324cSopenharmony_ci  {
848370b324cSopenharmony_ci    PrintError("Cannot get CreateObject");
849370b324cSopenharmony_ci    return 1;
850370b324cSopenharmony_ci  }
851370b324cSopenharmony_ci
852370b324cSopenharmony_ci  char c = 0;
853370b324cSopenharmony_ci  UString password;
854370b324cSopenharmony_ci  bool passwordIsDefined = false;
855370b324cSopenharmony_ci  CObjectVector<FString> params;
856370b324cSopenharmony_ci
857370b324cSopenharmony_ci  for (int curCmd = 1; curCmd < numArgs; curCmd++)
858370b324cSopenharmony_ci  {
859370b324cSopenharmony_ci    AString a(args[curCmd]);
860370b324cSopenharmony_ci
861370b324cSopenharmony_ci    if (!a.IsEmpty())
862370b324cSopenharmony_ci    {
863370b324cSopenharmony_ci      if (a[0] == '-')
864370b324cSopenharmony_ci      {
865370b324cSopenharmony_ci        if (!passwordIsDefined && a[1] == 'p')
866370b324cSopenharmony_ci        {
867370b324cSopenharmony_ci          password = GetUnicodeString(a.Ptr(2));
868370b324cSopenharmony_ci          passwordIsDefined = true;
869370b324cSopenharmony_ci          continue;
870370b324cSopenharmony_ci        }
871370b324cSopenharmony_ci      }
872370b324cSopenharmony_ci      else
873370b324cSopenharmony_ci      {
874370b324cSopenharmony_ci        if (c)
875370b324cSopenharmony_ci        {
876370b324cSopenharmony_ci          params.Add(CmdStringToFString(a));
877370b324cSopenharmony_ci          continue;
878370b324cSopenharmony_ci        }
879370b324cSopenharmony_ci        if (a.Len() == 1)
880370b324cSopenharmony_ci        {
881370b324cSopenharmony_ci          c = (char)MyCharLower_Ascii(a[0]);
882370b324cSopenharmony_ci          continue;
883370b324cSopenharmony_ci        }
884370b324cSopenharmony_ci      }
885370b324cSopenharmony_ci    }
886370b324cSopenharmony_ci    {
887370b324cSopenharmony_ci      PrintError(kIncorrectCommand);
888370b324cSopenharmony_ci      return 1;
889370b324cSopenharmony_ci    }
890370b324cSopenharmony_ci  }
891370b324cSopenharmony_ci
892370b324cSopenharmony_ci  if (!c || params.Size() < 1)
893370b324cSopenharmony_ci  {
894370b324cSopenharmony_ci    PrintError(kIncorrectCommand);
895370b324cSopenharmony_ci    return 1;
896370b324cSopenharmony_ci  }
897370b324cSopenharmony_ci
898370b324cSopenharmony_ci  const FString &archiveName = params[0];
899370b324cSopenharmony_ci
900370b324cSopenharmony_ci  if (c == 'a')
901370b324cSopenharmony_ci  {
902370b324cSopenharmony_ci    // create archive command
903370b324cSopenharmony_ci    if (params.Size() < 2)
904370b324cSopenharmony_ci    {
905370b324cSopenharmony_ci      PrintError(kIncorrectCommand);
906370b324cSopenharmony_ci      return 1;
907370b324cSopenharmony_ci    }
908370b324cSopenharmony_ci    CObjectVector<CDirItem> dirItems;
909370b324cSopenharmony_ci    {
910370b324cSopenharmony_ci      unsigned i;
911370b324cSopenharmony_ci      for (i = 1; i < params.Size(); i++)
912370b324cSopenharmony_ci      {
913370b324cSopenharmony_ci        const FString &name = params[i];
914370b324cSopenharmony_ci
915370b324cSopenharmony_ci        NFind::CFileInfo fi;
916370b324cSopenharmony_ci        if (!fi.Find(name))
917370b324cSopenharmony_ci        {
918370b324cSopenharmony_ci          PrintError("Can't find file", name);
919370b324cSopenharmony_ci          return 1;
920370b324cSopenharmony_ci        }
921370b324cSopenharmony_ci
922370b324cSopenharmony_ci        CDirItem di(fi);
923370b324cSopenharmony_ci
924370b324cSopenharmony_ci        di.Path_For_Handler = fs2us(name);
925370b324cSopenharmony_ci        di.FullPath = name;
926370b324cSopenharmony_ci        dirItems.Add(di);
927370b324cSopenharmony_ci      }
928370b324cSopenharmony_ci    }
929370b324cSopenharmony_ci
930370b324cSopenharmony_ci    COutFileStream *outFileStreamSpec = new COutFileStream;
931370b324cSopenharmony_ci    CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
932370b324cSopenharmony_ci    if (!outFileStreamSpec->Create(archiveName, false))
933370b324cSopenharmony_ci    {
934370b324cSopenharmony_ci      PrintError("can't create archive file");
935370b324cSopenharmony_ci      return 1;
936370b324cSopenharmony_ci    }
937370b324cSopenharmony_ci
938370b324cSopenharmony_ci    CMyComPtr<IOutArchive> outArchive;
939370b324cSopenharmony_ci    if (f_CreateObject(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK)
940370b324cSopenharmony_ci    {
941370b324cSopenharmony_ci      PrintError("Cannot get class object");
942370b324cSopenharmony_ci      return 1;
943370b324cSopenharmony_ci    }
944370b324cSopenharmony_ci
945370b324cSopenharmony_ci    CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
946370b324cSopenharmony_ci    CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
947370b324cSopenharmony_ci    updateCallbackSpec->Init(&dirItems);
948370b324cSopenharmony_ci    updateCallbackSpec->PasswordIsDefined = passwordIsDefined;
949370b324cSopenharmony_ci    updateCallbackSpec->Password = password;
950370b324cSopenharmony_ci
951370b324cSopenharmony_ci    /*
952370b324cSopenharmony_ci    {
953370b324cSopenharmony_ci      const wchar_t *names[] =
954370b324cSopenharmony_ci      {
955370b324cSopenharmony_ci        L"m",
956370b324cSopenharmony_ci        L"s",
957370b324cSopenharmony_ci        L"x"
958370b324cSopenharmony_ci      };
959370b324cSopenharmony_ci      const unsigned kNumProps = Z7_ARRAY_SIZE(names);
960370b324cSopenharmony_ci      NCOM::CPropVariant values[kNumProps] =
961370b324cSopenharmony_ci      {
962370b324cSopenharmony_ci        L"lzma",
963370b324cSopenharmony_ci        false,    // solid mode OFF
964370b324cSopenharmony_ci        (UInt32)9 // compression level = 9 - ultra
965370b324cSopenharmony_ci      };
966370b324cSopenharmony_ci      CMyComPtr<ISetProperties> setProperties;
967370b324cSopenharmony_ci      outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
968370b324cSopenharmony_ci      if (!setProperties)
969370b324cSopenharmony_ci      {
970370b324cSopenharmony_ci        PrintError("ISetProperties unsupported");
971370b324cSopenharmony_ci        return 1;
972370b324cSopenharmony_ci      }
973370b324cSopenharmony_ci      if (setProperties->SetProperties(names, values, kNumProps) != S_OK)
974370b324cSopenharmony_ci      {
975370b324cSopenharmony_ci        PrintError("SetProperties() error");
976370b324cSopenharmony_ci        return 1;
977370b324cSopenharmony_ci      }
978370b324cSopenharmony_ci    }
979370b324cSopenharmony_ci    */
980370b324cSopenharmony_ci
981370b324cSopenharmony_ci    HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);
982370b324cSopenharmony_ci
983370b324cSopenharmony_ci    updateCallbackSpec->Finilize();
984370b324cSopenharmony_ci
985370b324cSopenharmony_ci    if (result != S_OK)
986370b324cSopenharmony_ci    {
987370b324cSopenharmony_ci      PrintError("Update Error");
988370b324cSopenharmony_ci      return 1;
989370b324cSopenharmony_ci    }
990370b324cSopenharmony_ci
991370b324cSopenharmony_ci    FOR_VECTOR (i, updateCallbackSpec->FailedFiles)
992370b324cSopenharmony_ci    {
993370b324cSopenharmony_ci      PrintNewLine();
994370b324cSopenharmony_ci      PrintError("Error for file", updateCallbackSpec->FailedFiles[i]);
995370b324cSopenharmony_ci    }
996370b324cSopenharmony_ci
997370b324cSopenharmony_ci    if (updateCallbackSpec->FailedFiles.Size() != 0)
998370b324cSopenharmony_ci      return 1;
999370b324cSopenharmony_ci  }
1000370b324cSopenharmony_ci  else
1001370b324cSopenharmony_ci  {
1002370b324cSopenharmony_ci    if (params.Size() != 1)
1003370b324cSopenharmony_ci    {
1004370b324cSopenharmony_ci      PrintError(kIncorrectCommand);
1005370b324cSopenharmony_ci      return 1;
1006370b324cSopenharmony_ci    }
1007370b324cSopenharmony_ci
1008370b324cSopenharmony_ci    bool listCommand;
1009370b324cSopenharmony_ci
1010370b324cSopenharmony_ci    if (c == 'l')
1011370b324cSopenharmony_ci      listCommand = true;
1012370b324cSopenharmony_ci    else if (c == 'x')
1013370b324cSopenharmony_ci      listCommand = false;
1014370b324cSopenharmony_ci    else
1015370b324cSopenharmony_ci    {
1016370b324cSopenharmony_ci      PrintError(kIncorrectCommand);
1017370b324cSopenharmony_ci      return 1;
1018370b324cSopenharmony_ci    }
1019370b324cSopenharmony_ci
1020370b324cSopenharmony_ci    CMyComPtr<IInArchive> archive;
1021370b324cSopenharmony_ci    if (f_CreateObject(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK)
1022370b324cSopenharmony_ci    {
1023370b324cSopenharmony_ci      PrintError("Cannot get class object");
1024370b324cSopenharmony_ci      return 1;
1025370b324cSopenharmony_ci    }
1026370b324cSopenharmony_ci
1027370b324cSopenharmony_ci    CInFileStream *fileSpec = new CInFileStream;
1028370b324cSopenharmony_ci    CMyComPtr<IInStream> file = fileSpec;
1029370b324cSopenharmony_ci
1030370b324cSopenharmony_ci    if (!fileSpec->Open(archiveName))
1031370b324cSopenharmony_ci    {
1032370b324cSopenharmony_ci      PrintError("Cannot open archive file", archiveName);
1033370b324cSopenharmony_ci      return 1;
1034370b324cSopenharmony_ci    }
1035370b324cSopenharmony_ci
1036370b324cSopenharmony_ci    {
1037370b324cSopenharmony_ci      CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;
1038370b324cSopenharmony_ci      CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
1039370b324cSopenharmony_ci      openCallbackSpec->PasswordIsDefined = passwordIsDefined;
1040370b324cSopenharmony_ci      openCallbackSpec->Password = password;
1041370b324cSopenharmony_ci
1042370b324cSopenharmony_ci      const UInt64 scanSize = 1 << 23;
1043370b324cSopenharmony_ci      if (archive->Open(file, &scanSize, openCallback) != S_OK)
1044370b324cSopenharmony_ci      {
1045370b324cSopenharmony_ci        PrintError("Cannot open file as archive", archiveName);
1046370b324cSopenharmony_ci        return 1;
1047370b324cSopenharmony_ci      }
1048370b324cSopenharmony_ci    }
1049370b324cSopenharmony_ci
1050370b324cSopenharmony_ci    if (listCommand)
1051370b324cSopenharmony_ci    {
1052370b324cSopenharmony_ci      // List command
1053370b324cSopenharmony_ci      UInt32 numItems = 0;
1054370b324cSopenharmony_ci      archive->GetNumberOfItems(&numItems);
1055370b324cSopenharmony_ci      for (UInt32 i = 0; i < numItems; i++)
1056370b324cSopenharmony_ci      {
1057370b324cSopenharmony_ci        {
1058370b324cSopenharmony_ci          // Get uncompressed size of file
1059370b324cSopenharmony_ci          NCOM::CPropVariant prop;
1060370b324cSopenharmony_ci          archive->GetProperty(i, kpidSize, &prop);
1061370b324cSopenharmony_ci          char s[32];
1062370b324cSopenharmony_ci          ConvertPropVariantToShortString(prop, s);
1063370b324cSopenharmony_ci          Print(s);
1064370b324cSopenharmony_ci          Print("  ");
1065370b324cSopenharmony_ci        }
1066370b324cSopenharmony_ci        {
1067370b324cSopenharmony_ci          // Get name of file
1068370b324cSopenharmony_ci          NCOM::CPropVariant prop;
1069370b324cSopenharmony_ci          archive->GetProperty(i, kpidPath, &prop);
1070370b324cSopenharmony_ci          if (prop.vt == VT_BSTR)
1071370b324cSopenharmony_ci            Print(prop.bstrVal);
1072370b324cSopenharmony_ci          else if (prop.vt != VT_EMPTY)
1073370b324cSopenharmony_ci            Print("ERROR!");
1074370b324cSopenharmony_ci        }
1075370b324cSopenharmony_ci        PrintNewLine();
1076370b324cSopenharmony_ci      }
1077370b324cSopenharmony_ci    }
1078370b324cSopenharmony_ci    else
1079370b324cSopenharmony_ci    {
1080370b324cSopenharmony_ci      // Extract command
1081370b324cSopenharmony_ci      CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
1082370b324cSopenharmony_ci      CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
1083370b324cSopenharmony_ci      extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path
1084370b324cSopenharmony_ci      extractCallbackSpec->PasswordIsDefined = passwordIsDefined;
1085370b324cSopenharmony_ci      extractCallbackSpec->Password = password;
1086370b324cSopenharmony_ci
1087370b324cSopenharmony_ci      /*
1088370b324cSopenharmony_ci      const wchar_t *names[] =
1089370b324cSopenharmony_ci      {
1090370b324cSopenharmony_ci        L"mt",
1091370b324cSopenharmony_ci        L"mtf"
1092370b324cSopenharmony_ci      };
1093370b324cSopenharmony_ci      const unsigned kNumProps = sizeof(names) / sizeof(names[0]);
1094370b324cSopenharmony_ci      NCOM::CPropVariant values[kNumProps] =
1095370b324cSopenharmony_ci      {
1096370b324cSopenharmony_ci        (UInt32)1,
1097370b324cSopenharmony_ci        false
1098370b324cSopenharmony_ci      };
1099370b324cSopenharmony_ci      CMyComPtr<ISetProperties> setProperties;
1100370b324cSopenharmony_ci      archive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
1101370b324cSopenharmony_ci      if (setProperties)
1102370b324cSopenharmony_ci      {
1103370b324cSopenharmony_ci        if (setProperties->SetProperties(names, values, kNumProps) != S_OK)
1104370b324cSopenharmony_ci        {
1105370b324cSopenharmony_ci          PrintError("SetProperties() error");
1106370b324cSopenharmony_ci          return 1;
1107370b324cSopenharmony_ci        }
1108370b324cSopenharmony_ci      }
1109370b324cSopenharmony_ci      */
1110370b324cSopenharmony_ci
1111370b324cSopenharmony_ci      HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);
1112370b324cSopenharmony_ci
1113370b324cSopenharmony_ci      if (result != S_OK)
1114370b324cSopenharmony_ci      {
1115370b324cSopenharmony_ci        PrintError("Extract Error");
1116370b324cSopenharmony_ci        return 1;
1117370b324cSopenharmony_ci      }
1118370b324cSopenharmony_ci    }
1119370b324cSopenharmony_ci  }
1120370b324cSopenharmony_ci
1121370b324cSopenharmony_ci  return 0;
1122370b324cSopenharmony_ci}
1123