#include "StdAfx.h"
#include "Common/ComTry.h"
#include "Common/Defs.h"
#include "Common/IntToString.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
#include "UpdateCallback.h"
using
namespace
NWindows;
CArchiveUpdateCallback::CArchiveUpdateCallback():
Callback(0),
ShareForWrite(
false
),
StdInMode(
false
),
DirItems(0),
ArcItems(0),
UpdatePairs(0),
NewNames(0)
{}
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
{
COM_TRY_BEGIN
return
Callback->SetTotal(size);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(
const
UInt64 *completeValue)
{
COM_TRY_BEGIN
return
Callback->SetCompleted(completeValue);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(
const
UInt64 *inSize,
const
UInt64 *outSize)
{
COM_TRY_BEGIN
return
Callback->SetRatioInfo(inSize, outSize);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)
{
COM_TRY_BEGIN
RINOK(Callback->CheckBreak());
const
CUpdatePair2 &up = (*UpdatePairs)[index];
if
(newData != NULL) *newData = BoolToInt(up.NewData);
if
(newProps != NULL) *newProps = BoolToInt(up.NewProps);
if
(indexInArchive != NULL)
{
*indexInArchive = (UInt32)-1;
if
(up.ExistInArchive())
*indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;
}
return
S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
const
CUpdatePair2 &up = (*UpdatePairs)[index];
NWindows::NCOM::CPropVariant prop;
if
(propID == kpidIsAnti)
{
prop = up.IsAnti;
prop.Detach(value);
return
S_OK;
}
if
(up.IsAnti)
{
switch
(propID)
{
case
kpidIsDir:
case
kpidPath:
break
;
case
kpidSize:
prop = (UInt64)0;
prop.Detach(value);
return
S_OK;
default
:
prop.Detach(value);
return
S_OK;
}
}
if
(up.ExistOnDisk())
{
const
CDirItem &di = DirItems->Items[up.DirIndex];
switch
(propID)
{
case
kpidPath: prop = DirItems->GetLogPath(up.DirIndex);
break
;
case
kpidIsDir: prop = di.IsDir();
break
;
case
kpidSize: prop = di.Size;
break
;
case
kpidAttrib: prop = di.Attrib;
break
;
case
kpidCTime: prop = di.CTime;
break
;
case
kpidATime: prop = di.ATime;
break
;
case
kpidMTime: prop = di.MTime;
break
;
}
}
else
{
if
(propID == kpidPath)
{
if
(up.NewNameIndex >= 0)
{
prop = (*NewNames)[up.NewNameIndex];
prop.Detach(value);
return
S_OK;
}
}
if
(up.ExistInArchive() && Archive)
{
UInt32 indexInArchive;
if
(ArcItems == 0)
indexInArchive = up.ArcIndex;
else
indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer;
return
Archive->GetProperty(indexInArchive, propID, value);
}
}
prop.Detach(value);
return
S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
{
COM_TRY_BEGIN
const
CUpdatePair2 &up = (*UpdatePairs)[index];
if
(!up.NewData)
return
E_FAIL;
RINOK(Callback->CheckBreak());
RINOK(Callback->Finilize());
if
(up.IsAnti)
{
return
Callback->GetStream((*ArcItems)[up.ArcIndex].Name,
true
);
}
const
CDirItem &di = DirItems->Items[up.DirIndex];
RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex),
false
));
if
(di.IsDir())
return
S_OK;
if
(StdInMode)
{
CStdInFileStream *inStreamSpec =
new
CStdInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
*inStream = inStreamLoc.Detach();
}
else
{
CInFileStream *inStreamSpec =
new
CInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
const
UString path = DirItems->GetPhyPath(up.DirIndex);
if
(!inStreamSpec->OpenShared(path, ShareForWrite))
{
return
Callback->OpenFileError(path, ::GetLastError());
}
*inStream = inStreamLoc.Detach();
}
return
S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
{
COM_TRY_BEGIN
return
Callback->SetOperationResult(operationResult);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
{
if
(VolumesSizes.Size() == 0)
return
S_FALSE;
if
(index >= (UInt32)VolumesSizes.Size())
index = VolumesSizes.Size() - 1;
*size = VolumesSizes[index];
return
S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
{
COM_TRY_BEGIN
wchar_t
temp[16];
ConvertUInt32ToString(index + 1, temp);
UString res = temp;
while
(res.Length() < 2)
res = UString(L
'0'
) + res;
UString fileName = VolName;
fileName += L
'.'
;
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec =
new
COutFileStream;
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
if
(!streamSpec->Create(fileName,
false
))
return
::GetLastError();
*volumeStream = streamLoc.Detach();
return
S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
COM_TRY_BEGIN
return
Callback->CryptoGetTextPassword2(passwordIsDefined, password);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)
{
COM_TRY_BEGIN
return
Callback->CryptoGetTextPassword(password);
COM_TRY_END
}