1// ArchiveOpenCallback.cpp
2
3#include "StdAfx.h"
4
5#include "Common/StringConvert.h"
6#include "Common/ComTry.h"
7
8#include "Windows/PropVariant.h"
9
10#include "../../Common/FileStreams.h"
11
12#include "ArchiveOpenCallback.h"
13
14using namespace NWindows;
15
16STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
17{
18  COM_TRY_BEGIN
19  if (ReOpenCallback)
20    return ReOpenCallback->SetTotal(files, bytes);
21  if (!Callback)
22    return S_OK;
23  return Callback->Open_SetTotal(files, bytes);
24  COM_TRY_END
25}
26
27STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
28{
29  COM_TRY_BEGIN
30  if (ReOpenCallback)
31    return ReOpenCallback->SetCompleted(files, bytes);
32  if (!Callback)
33    return S_OK;
34  return Callback->Open_SetCompleted(files, bytes);
35  COM_TRY_END
36}
37
38STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
39{
40  COM_TRY_BEGIN
41  NCOM::CPropVariant prop;
42  if (_subArchiveMode)
43    switch(propID)
44    {
45      case kpidName: prop = _subArchiveName; break;
46    }
47  else
48    switch(propID)
49    {
50      case kpidName:  prop = _fileInfo.Name; break;
51      case kpidIsDir:  prop = _fileInfo.IsDir(); break;
52      case kpidSize:  prop = _fileInfo.Size; break;
53      case kpidAttrib:  prop = (UInt32)_fileInfo.Attrib; break;
54      case kpidCTime:  prop = _fileInfo.CTime; break;
55      case kpidATime:  prop = _fileInfo.ATime; break;
56      case kpidMTime:  prop = _fileInfo.MTime; break;
57    }
58  prop.Detach(value);
59  return S_OK;
60  COM_TRY_END
61}
62
63int COpenCallbackImp::FindName(const UString &name)
64{
65  for (int i = 0; i < FileNames.Size(); i++)
66    if (name.CompareNoCase(FileNames[i]) == 0)
67      return i;
68  return -1;
69}
70
71struct CInFileStreamVol: public CInFileStream
72{
73  UString Name;
74  COpenCallbackImp *OpenCallbackImp;
75  CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
76  ~CInFileStreamVol()
77  {
78    if (OpenCallbackRef)
79    {
80      int index = OpenCallbackImp->FindName(Name);
81      if (index >= 0)
82        OpenCallbackImp->FileNames.Delete(index);
83    }
84  }
85};
86
87STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
88{
89  COM_TRY_BEGIN
90  if (_subArchiveMode)
91    return S_FALSE;
92  if (Callback)
93  {
94    RINOK(Callback->Open_CheckBreak());
95  }
96  *inStream = NULL;
97  UString fullPath = _folderPrefix + name;
98  if (!_fileInfo.Find(fullPath))
99    return S_FALSE;
100  if (_fileInfo.IsDir())
101    return S_FALSE;
102  CInFileStreamVol *inFile = new CInFileStreamVol;
103  CMyComPtr<IInStream> inStreamTemp = inFile;
104  if (!inFile->Open(fullPath))
105    return ::GetLastError();
106  *inStream = inStreamTemp.Detach();
107  inFile->Name = name;
108  inFile->OpenCallbackImp = this;
109  inFile->OpenCallbackRef = this;
110  FileNames.Add(name);
111  TotalSize += _fileInfo.Size;
112  return S_OK;
113  COM_TRY_END
114}
115
116#ifndef _NO_CRYPTO
117STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
118{
119  COM_TRY_BEGIN
120  if (ReOpenCallback)
121  {
122    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
123    ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
124    if (getTextPassword)
125      return getTextPassword->CryptoGetTextPassword(password);
126  }
127  if (!Callback)
128    return E_NOTIMPL;
129  return Callback->Open_CryptoGetTextPassword(password);
130  COM_TRY_END
131}
132#endif
133
134