mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 06:07:05 -06:00
23.01
This commit is contained in:
@@ -6,14 +6,54 @@
|
||||
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/System.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
|
||||
// #define DEBUG_VOLUMES
|
||||
|
||||
#ifdef DEBUG_VOLUMES
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG_VOLUMES
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
|
||||
HRESULT COpenCallbackImp::Init2(const FString &folderPrefix, const FString &fileName)
|
||||
{
|
||||
Volumes.Init();
|
||||
FileNames.Clear();
|
||||
FileNames_WasUsed.Clear();
|
||||
FileSizes.Clear();
|
||||
_subArchiveMode = false;
|
||||
// TotalSize = 0;
|
||||
PasswordWasAsked = false;
|
||||
_folderPrefix = folderPrefix;
|
||||
if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName))
|
||||
{
|
||||
// throw 20121118;
|
||||
return GetLastError_noZero_HRESULT();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetSubArchiveName(const wchar_t *name))
|
||||
{
|
||||
_subArchiveMode = true;
|
||||
_subArchiveName = name;
|
||||
// TotalSize = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
@@ -24,7 +64,7 @@ STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
@@ -36,7 +76,7 @@ STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *b
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
Z7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
@@ -63,24 +103,180 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
struct CInFileStreamVol: public CInFileStream
|
||||
{
|
||||
unsigned FileNameIndex;
|
||||
|
||||
// ---------- CInFileStreamVol ----------
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CInFileStreamVol
|
||||
, IInStream
|
||||
, IStreamGetSize
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(ISequentialInStream)
|
||||
public:
|
||||
unsigned FileIndex;
|
||||
COpenCallbackImp *OpenCallbackImp;
|
||||
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
|
||||
|
||||
|
||||
HRESULT EnsureOpen()
|
||||
{
|
||||
return OpenCallbackImp->Volumes.EnsureOpen(FileIndex);
|
||||
}
|
||||
|
||||
~CInFileStreamVol()
|
||||
{
|
||||
if (OpenCallbackRef)
|
||||
OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
|
||||
OpenCallbackImp->AtCloseFile(FileIndex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void CMultiStreams::InsertToList(unsigned index)
|
||||
{
|
||||
{
|
||||
CSubStream &s = Streams[index];
|
||||
s.Next = Head;
|
||||
s.Prev = -1;
|
||||
}
|
||||
if (Head != -1)
|
||||
Streams[(unsigned)Head].Prev = (int)index;
|
||||
else
|
||||
{
|
||||
// if (Tail != -1) throw 1;
|
||||
Tail = (int)index;
|
||||
}
|
||||
Head = (int)index;
|
||||
NumListItems++;
|
||||
}
|
||||
|
||||
// s must bee in List
|
||||
void CMultiStreams::RemoveFromList(CSubStream &s)
|
||||
{
|
||||
if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev;
|
||||
if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next;
|
||||
s.Next = -1; // optional
|
||||
s.Prev = -1; // optional
|
||||
NumListItems--;
|
||||
}
|
||||
|
||||
void CMultiStreams::CloseFile(unsigned index)
|
||||
{
|
||||
CSubStream &s = Streams[index];
|
||||
if (s.Stream)
|
||||
{
|
||||
s.Stream.Release();
|
||||
RemoveFromList(s);
|
||||
// s.InFile->Close();
|
||||
// s.IsOpen = false;
|
||||
#ifdef DEBUG_VOLUMES
|
||||
static int numClosing = 0;
|
||||
numClosing++;
|
||||
printf("\nCloseFile %u, total_closes = %u, num_open_files = %u\n", index, numClosing, NumListItems);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CMultiStreams::Init()
|
||||
{
|
||||
Head = -1;
|
||||
Tail = -1;
|
||||
NumListItems = 0;
|
||||
Streams.Clear();
|
||||
}
|
||||
|
||||
CMultiStreams::CMultiStreams():
|
||||
Head(-1),
|
||||
Tail(-1),
|
||||
NumListItems(0)
|
||||
{
|
||||
NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks();
|
||||
PRF(printf("\nNumOpenFiles_Limit = %u\n", NumOpenFiles_AllowedMax));
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiStreams::PrepareToOpenNew()
|
||||
{
|
||||
if (NumListItems < NumOpenFiles_AllowedMax)
|
||||
return S_OK;
|
||||
if (Tail == -1)
|
||||
return E_FAIL;
|
||||
CMultiStreams::CSubStream &tailStream = Streams[(unsigned)Tail];
|
||||
RINOK(InStream_GetPos(tailStream.Stream, tailStream.LocalPos))
|
||||
CloseFile((unsigned)Tail);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiStreams::EnsureOpen(unsigned index)
|
||||
{
|
||||
CMultiStreams::CSubStream &s = Streams[index];
|
||||
if (s.Stream)
|
||||
{
|
||||
if ((int)index != Head)
|
||||
{
|
||||
RemoveFromList(s);
|
||||
InsertToList(index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(PrepareToOpenNew())
|
||||
{
|
||||
CInFileStream *inFile = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(s.Path))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
s.FileSpec = inFile;
|
||||
s.Stream = s.FileSpec;
|
||||
InsertToList(index);
|
||||
}
|
||||
// s.IsOpen = true;
|
||||
if (s.LocalPos != 0)
|
||||
{
|
||||
RINOK(s.Stream->Seek((Int64)s.LocalPos, STREAM_SEEK_SET, &s.LocalPos))
|
||||
}
|
||||
#ifdef DEBUG_VOLUMES
|
||||
static int numOpens = 0;
|
||||
numOpens++;
|
||||
printf("\n-- %u, ReOpen, total_reopens = %u, num_open_files = %u\n", index, numOpens, NumListItems);
|
||||
#endif
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CInFileStreamVol::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
RINOK(EnsureOpen())
|
||||
CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
|
||||
PRF(printf("\n== %u, Read =%u \n", FileIndex, size));
|
||||
return s.Stream->Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CInFileStreamVol::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
// if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION;
|
||||
RINOK(EnsureOpen())
|
||||
CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
|
||||
PRF(printf("\n-- %u, Seek seekOrigin=%u Seek =%u\n", FileIndex, seekOrigin, (unsigned)offset));
|
||||
return s.Stream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CInFileStreamVol::GetSize(UInt64 *size))
|
||||
{
|
||||
RINOK(EnsureOpen())
|
||||
CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
|
||||
return s.FileSpec->GetSize(size);
|
||||
}
|
||||
|
||||
|
||||
// from ArchiveExtractCallback.cpp
|
||||
bool IsSafePath(const UString &path);
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
|
||||
Z7_COM7F_IMF(COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*inStream = NULL;
|
||||
@@ -89,13 +285,13 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
|
||||
return S_FALSE;
|
||||
if (Callback)
|
||||
{
|
||||
RINOK(Callback->Open_CheckBreak());
|
||||
RINOK(Callback->Open_CheckBreak())
|
||||
}
|
||||
|
||||
UString name2 = name;
|
||||
|
||||
|
||||
#ifndef _SFX
|
||||
#ifndef Z7_SFX
|
||||
|
||||
#ifdef _WIN32
|
||||
name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||
@@ -112,7 +308,7 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
|
||||
if (name2.Find(L'*') >= 0)
|
||||
return S_FALSE;
|
||||
{
|
||||
int startPos = 0;
|
||||
unsigned startPos = 0;
|
||||
if (name2.IsPrefixedBy_Ascii_NoCase("\\\\?\\"))
|
||||
startPos = 3;
|
||||
if (name2.Find(L'?', startPos) >= 0)
|
||||
@@ -130,16 +326,32 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
|
||||
return S_FALSE;
|
||||
if (_fileInfo.IsDir())
|
||||
return S_FALSE;
|
||||
CInFileStreamVol *inFile = new CInFileStreamVol;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(fullPath))
|
||||
|
||||
CMultiStreams::CSubStream s;
|
||||
|
||||
{
|
||||
return GetLastError_noZero_HRESULT();
|
||||
CInFileStream *inFile = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(fullPath))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
RINOK(Volumes.PrepareToOpenNew())
|
||||
s.FileSpec = inFile;
|
||||
s.Stream = s.FileSpec;
|
||||
s.Path = fullPath;
|
||||
// s.Size = _fileInfo.Size;
|
||||
// s.IsOpen = true;
|
||||
}
|
||||
|
||||
const unsigned fileIndex = Volumes.Streams.Add(s);
|
||||
Volumes.InsertToList(fileIndex);
|
||||
|
||||
FileSizes.Add(_fileInfo.Size);
|
||||
FileNames.Add(name2);
|
||||
inFile->FileNameIndex = FileNames_WasUsed.Add(true);
|
||||
FileNames_WasUsed.Add(true);
|
||||
|
||||
CInFileStreamVol *inFile = new CInFileStreamVol;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
inFile->FileIndex = fileIndex;
|
||||
inFile->OpenCallbackImp = this;
|
||||
inFile->OpenCallbackRef = this;
|
||||
// TotalSize += _fileInfo.Size;
|
||||
@@ -148,14 +360,16 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
Z7_COM7F_IMF(COpenCallbackImp::CryptoGetTextPassword(BSTR *password))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
{
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICryptoGetTextPassword,
|
||||
getTextPassword, ReOpenCallback)
|
||||
if (getTextPassword)
|
||||
return getTextPassword->CryptoGetTextPassword(password);
|
||||
}
|
||||
@@ -166,3 +380,14 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
|
||||
COM_TRY_END
|
||||
}
|
||||
#endif
|
||||
|
||||
// IProgress
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 /* total */))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user