268 lines
6.4 KiB
C++
268 lines
6.4 KiB
C++
|
// UpdateCallback.cpp
|
||
|
|
||
|
#include "StdAfx.h"
|
||
|
|
||
|
#include "UpdateCallback.h"
|
||
|
|
||
|
#include "Common/StringConvert.h"
|
||
|
#include "Common/IntToString.h"
|
||
|
#include "Common/Defs.h"
|
||
|
#include "Common/ComTry.h"
|
||
|
|
||
|
#include "Windows/PropVariant.h"
|
||
|
|
||
|
#include "../../Common/FileStreams.h"
|
||
|
|
||
|
using namespace NWindows;
|
||
|
|
||
|
CArchiveUpdateCallback::CArchiveUpdateCallback():
|
||
|
Callback(0),
|
||
|
ShareForWrite(false),
|
||
|
StdInMode(false),
|
||
|
DirItems(0),
|
||
|
ArchiveItems(0),
|
||
|
UpdatePairs(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
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
STATPROPSTG kProperties[] =
|
||
|
{
|
||
|
{ NULL, kpidPath, VT_BSTR},
|
||
|
{ NULL, kpidIsFolder, VT_BOOL},
|
||
|
{ NULL, kpidSize, VT_UI8},
|
||
|
{ NULL, kpidLastAccessTime, VT_FILETIME},
|
||
|
{ NULL, kpidCreationTime, VT_FILETIME},
|
||
|
{ NULL, kpidLastWriteTime, VT_FILETIME},
|
||
|
{ NULL, kpidAttributes, VT_UI4},
|
||
|
{ NULL, kpidIsAnti, VT_BOOL}
|
||
|
};
|
||
|
*/
|
||
|
|
||
|
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
/*
|
||
|
return CStatPropEnumerator::CreateEnumerator(kProperties,
|
||
|
sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
|
||
|
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
|
||
|
{
|
||
|
COM_TRY_BEGIN
|
||
|
RINOK(Callback->CheckBreak());
|
||
|
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
|
||
|
if(newData != NULL)
|
||
|
*newData = BoolToInt(updatePair.NewData);
|
||
|
if(newProperties != NULL)
|
||
|
*newProperties = BoolToInt(updatePair.NewProperties);
|
||
|
if(indexInArchive != NULL)
|
||
|
{
|
||
|
if (updatePair.ExistInArchive)
|
||
|
{
|
||
|
if (ArchiveItems == 0)
|
||
|
*indexInArchive = updatePair.ArchiveItemIndex;
|
||
|
else
|
||
|
*indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
|
||
|
}
|
||
|
else
|
||
|
*indexInArchive = UInt32(-1);
|
||
|
}
|
||
|
return S_OK;
|
||
|
COM_TRY_END
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||
|
{
|
||
|
COM_TRY_BEGIN
|
||
|
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
|
||
|
NWindows::NCOM::CPropVariant propVariant;
|
||
|
|
||
|
if (propID == kpidIsAnti)
|
||
|
{
|
||
|
propVariant = updatePair.IsAnti;
|
||
|
propVariant.Detach(value);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
if (updatePair.IsAnti)
|
||
|
{
|
||
|
switch(propID)
|
||
|
{
|
||
|
case kpidIsFolder:
|
||
|
case kpidPath:
|
||
|
break;
|
||
|
case kpidSize:
|
||
|
propVariant = (UInt64)0;
|
||
|
propVariant.Detach(value);
|
||
|
return S_OK;
|
||
|
default:
|
||
|
propVariant.Detach(value);
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(updatePair.ExistOnDisk)
|
||
|
{
|
||
|
const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
|
||
|
switch(propID)
|
||
|
{
|
||
|
case kpidPath:
|
||
|
propVariant = dirItem.Name;
|
||
|
break;
|
||
|
case kpidIsFolder:
|
||
|
propVariant = dirItem.IsDirectory();
|
||
|
break;
|
||
|
case kpidSize:
|
||
|
propVariant = dirItem.Size;
|
||
|
break;
|
||
|
case kpidAttributes:
|
||
|
propVariant = dirItem.Attributes;
|
||
|
break;
|
||
|
case kpidLastAccessTime:
|
||
|
propVariant = dirItem.LastAccessTime;
|
||
|
break;
|
||
|
case kpidCreationTime:
|
||
|
propVariant = dirItem.CreationTime;
|
||
|
break;
|
||
|
case kpidLastWriteTime:
|
||
|
propVariant = dirItem.LastWriteTime;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (propID == kpidPath)
|
||
|
{
|
||
|
if (updatePair.NewNameIsDefined)
|
||
|
{
|
||
|
propVariant = updatePair.NewName;
|
||
|
propVariant.Detach(value);
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
if (updatePair.ExistInArchive && Archive)
|
||
|
{
|
||
|
UInt32 indexInArchive;
|
||
|
if (ArchiveItems == 0)
|
||
|
indexInArchive = updatePair.ArchiveItemIndex;
|
||
|
else
|
||
|
indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
|
||
|
return Archive->GetProperty(indexInArchive, propID, value);
|
||
|
}
|
||
|
}
|
||
|
propVariant.Detach(value);
|
||
|
return S_OK;
|
||
|
COM_TRY_END
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
|
||
|
{
|
||
|
COM_TRY_BEGIN
|
||
|
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
|
||
|
if(!updatePair.NewData)
|
||
|
return E_FAIL;
|
||
|
|
||
|
RINOK(Callback->CheckBreak());
|
||
|
RINOK(Callback->Finilize());
|
||
|
|
||
|
if(updatePair.IsAnti)
|
||
|
{
|
||
|
return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true);
|
||
|
}
|
||
|
const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
|
||
|
RINOK(Callback->GetStream(dirItem.Name, false));
|
||
|
|
||
|
if(dirItem.IsDirectory())
|
||
|
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);
|
||
|
UString path = DirPrefix + dirItem.FullPath;
|
||
|
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[32];
|
||
|
ConvertUInt64ToString(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
|
||
|
}
|