aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/UI/Common/ArchiveOpenCallback.h
blob: 4e44c9dde21c4e043484cebde1204af990f5c51b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// ArchiveOpenCallback.h

#ifndef ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H
#define ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H

#include "../../../Common/MyCom.h"

#include "../../../Windows/FileFind.h"

#include "../../Common/FileStreams.h"

#ifndef Z7_NO_CRYPTO
#include "../../IPassword.h"
#endif
#include "../../Archive/IArchive.h"

Z7_PURE_INTERFACES_BEGIN

#ifdef Z7_NO_CRYPTO

#define Z7_IFACEM_IOpenCallbackUI_Crypto(x)

#else

#define Z7_IFACEM_IOpenCallbackUI_Crypto(x) \
  virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x \
  /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x */ \
  /* virtual bool Open_WasPasswordAsked() x */ \
  /* virtual void Open_Clear_PasswordWasAsked_Flag() x */  \
  
#endif

#define Z7_IFACEN_IOpenCallbackUI(x) \
  virtual HRESULT Open_CheckBreak() x \
  virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x \
  virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x \
  virtual HRESULT Open_Finished() x \
  Z7_IFACEM_IOpenCallbackUI_Crypto(x)

Z7_IFACE_DECL_PURE(IOpenCallbackUI)

Z7_PURE_INTERFACES_END


class CMultiStreams Z7_final
{
public:
  struct CSubStream
  {
    CMyComPtr<IInStream> Stream;
    CInFileStream *FileSpec;
    FString Path;
    // UInt64 Size;
    UInt64 LocalPos;
    int Next; // next older
    int Prev; // prev newer
    // bool IsOpen;

    CSubStream():
        FileSpec(NULL),
        // Size(0),
        LocalPos(0),
        Next(-1),
        Prev(-1)
        // IsOpen(false)
        {}
  };

  CObjectVector<CSubStream> Streams;
private:
  // we must use critical section here, if we want to access from different volumnes simultaneously
  int Head; // newest
  int Tail; // oldest
  unsigned NumListItems;
  unsigned NumOpenFiles_AllowedMax;
public:

  CMultiStreams();
  void Init();
  HRESULT PrepareToOpenNew();
  void InsertToList(unsigned index);
  void RemoveFromList(CSubStream &s);
  void CloseFile(unsigned index);
  HRESULT EnsureOpen(unsigned index);
};


/*
  We need COpenCallbackImp class for multivolume processing.
  Also we use it as proxy from COM interfaces (IArchiveOpenCallback) to internal (IOpenCallbackUI) interfaces.
  If archive is multivolume:
    COpenCallbackImp object will exist after Open stage.
    COpenCallbackImp object will be deleted when last reference
      from each volume object (CInFileStreamVol) will be closed (when archive will be closed).
*/

class COpenCallbackImp Z7_final:
  public IArchiveOpenCallback,
  public IArchiveOpenVolumeCallback,
  public IArchiveOpenSetSubArchiveName,
 #ifndef Z7_NO_CRYPTO
  public ICryptoGetTextPassword,
 #endif
  public IProgress, // IProgress is used for 7zFM
  public CMyUnknownImp
{
  Z7_COM_QI_BEGIN2(IArchiveOpenCallback)
  Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback)
  Z7_COM_QI_ENTRY(IArchiveOpenSetSubArchiveName)
 #ifndef Z7_NO_CRYPTO
  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
 #endif
  // Z7_COM_QI_ENTRY(IProgress) // the code doesn't require it
  Z7_COM_QI_END
  Z7_COM_ADDREF_RELEASE
  
  Z7_IFACE_COM7_IMP(IArchiveOpenCallback)
  Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback)
  Z7_IFACE_COM7_IMP(IProgress)
public:
  Z7_IFACE_COM7_IMP(IArchiveOpenSetSubArchiveName)
private:
 #ifndef Z7_NO_CRYPTO
  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
 #endif

  bool _subArchiveMode;

public:
  bool PasswordWasAsked;
  UStringVector FileNames;
  CBoolVector FileNames_WasUsed;
  CRecordVector<UInt64> FileSizes;

  void AtCloseFile(unsigned fileIndex)
  {
    FileNames_WasUsed[fileIndex] = false;
    Volumes.CloseFile(fileIndex);
  }

  /* we have two ways to Callback from this object
      1) IArchiveOpenCallback * ReOpenCallback - for ReOpen function, when IOpenCallbackUI is not available
      2) IOpenCallbackUI *Callback - for usual callback
     we can't transfer IOpenCallbackUI pointer via internal interface,
     so we use ReOpenCallback to callback without IOpenCallbackUI.
  */

  /* we use Callback/ReOpenCallback only at Open stage.
     So the CMyComPtr reference counter is not required,
     and we don't want additional reference to unused object,
     if COpenCallbackImp is not closed
  */
  IArchiveOpenCallback *ReOpenCallback;
  // CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
  IOpenCallbackUI *Callback;
  // CMyComPtr<IUnknown> Callback_Ref;

private:
  FString _folderPrefix;
  UString _subArchiveName;
  NWindows::NFile::NFind::CFileInfo _fileInfo;

public:
  CMultiStreams Volumes;
  
  // UInt64 TotalSize;

  COpenCallbackImp():
      _subArchiveMode(false),
      ReOpenCallback(NULL),
      Callback(NULL)  {}
  
  HRESULT Init2(const FString &folderPrefix, const FString &fileName);

  bool SetSecondFileInfo(CFSTR newName)
  {
    return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir();
  }
};

#endif