You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
6.2 KiB
247 lines
6.2 KiB
4 months ago
|
// ExtractCallbackSfx.h
|
||
|
|
||
|
#include "StdAfx.h"
|
||
|
|
||
|
#include "../../../Common/Wildcard.h"
|
||
|
|
||
|
#include "../../../Windows/FileDir.h"
|
||
|
#include "../../../Windows/FileFind.h"
|
||
|
#include "../../../Windows/FileName.h"
|
||
|
#include "../../../Windows/PropVariant.h"
|
||
|
|
||
|
#include "ExtractCallbackSfx.h"
|
||
|
|
||
|
using namespace NWindows;
|
||
|
using namespace NFile;
|
||
|
using namespace NDir;
|
||
|
|
||
|
static LPCSTR const kCantDeleteFile = "Can not delete output file";
|
||
|
static LPCSTR const kCantOpenFile = "Can not open output file";
|
||
|
static LPCSTR const kUnsupportedMethod = "Unsupported Method";
|
||
|
|
||
|
void CExtractCallbackImp::Init(IInArchive *archiveHandler,
|
||
|
const FString &directoryPath,
|
||
|
const UString &itemDefaultName,
|
||
|
const FILETIME &defaultMTime,
|
||
|
UInt32 defaultAttributes)
|
||
|
{
|
||
|
_message.Empty();
|
||
|
_isCorrupt = false;
|
||
|
_itemDefaultName = itemDefaultName;
|
||
|
_defaultMTime = defaultMTime;
|
||
|
_defaultAttributes = defaultAttributes;
|
||
|
_archiveHandler = archiveHandler;
|
||
|
_directoryPath = directoryPath;
|
||
|
NName::NormalizeDirPathPrefix(_directoryPath);
|
||
|
}
|
||
|
|
||
|
HRESULT CExtractCallbackImp::Open_CheckBreak()
|
||
|
{
|
||
|
#ifndef _NO_PROGRESS
|
||
|
return ProgressDialog.Sync.ProcessStopAndPause();
|
||
|
#else
|
||
|
return S_OK;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
|
||
|
{
|
||
|
#ifndef _NO_PROGRESS
|
||
|
return ProgressDialog.Sync.ProcessStopAndPause();
|
||
|
#else
|
||
|
return S_OK;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
HRESULT CExtractCallbackImp::Open_Finished()
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)
|
||
|
{
|
||
|
#ifndef _NO_PROGRESS
|
||
|
ProgressDialog.Sync.SetProgress(size, 0);
|
||
|
#endif
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
|
||
|
{
|
||
|
#ifndef _NO_PROGRESS
|
||
|
RINOK(ProgressDialog.Sync.ProcessStopAndPause());
|
||
|
if (completeValue != NULL)
|
||
|
ProgressDialog.Sync.SetPos(*completeValue);
|
||
|
#endif
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
|
||
|
{
|
||
|
FString fullPath = _directoryPath;
|
||
|
FOR_VECTOR (i, dirPathParts)
|
||
|
{
|
||
|
fullPath += us2fs(dirPathParts[i]);
|
||
|
CreateDir(fullPath);
|
||
|
fullPath.Add_PathSepar();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
|
||
|
ISequentialOutStream **outStream, Int32 askExtractMode)
|
||
|
{
|
||
|
#ifndef _NO_PROGRESS
|
||
|
if (ProgressDialog.Sync.GetStopped())
|
||
|
return E_ABORT;
|
||
|
#endif
|
||
|
_outFileStream.Release();
|
||
|
|
||
|
UString fullPath;
|
||
|
{
|
||
|
NCOM::CPropVariant prop;
|
||
|
RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
|
||
|
if (prop.vt == VT_EMPTY)
|
||
|
fullPath = _itemDefaultName;
|
||
|
else
|
||
|
{
|
||
|
if (prop.vt != VT_BSTR)
|
||
|
return E_FAIL;
|
||
|
fullPath.SetFromBstr(prop.bstrVal);
|
||
|
}
|
||
|
_filePath = fullPath;
|
||
|
}
|
||
|
|
||
|
if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)
|
||
|
{
|
||
|
NCOM::CPropVariant prop;
|
||
|
RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
|
||
|
if (prop.vt == VT_EMPTY)
|
||
|
_processedFileInfo.Attributes = _defaultAttributes;
|
||
|
else
|
||
|
{
|
||
|
if (prop.vt != VT_UI4)
|
||
|
return E_FAIL;
|
||
|
_processedFileInfo.Attributes = prop.ulVal;
|
||
|
}
|
||
|
|
||
|
RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop));
|
||
|
_processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);
|
||
|
|
||
|
bool isAnti = false;
|
||
|
{
|
||
|
NCOM::CPropVariant propTemp;
|
||
|
RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp));
|
||
|
if (propTemp.vt == VT_BOOL)
|
||
|
isAnti = VARIANT_BOOLToBool(propTemp.boolVal);
|
||
|
}
|
||
|
|
||
|
RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
|
||
|
switch (prop.vt)
|
||
|
{
|
||
|
case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;
|
||
|
case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;
|
||
|
default: return E_FAIL;
|
||
|
}
|
||
|
|
||
|
UStringVector pathParts;
|
||
|
SplitPathToParts(fullPath, pathParts);
|
||
|
if (pathParts.IsEmpty())
|
||
|
return E_FAIL;
|
||
|
|
||
|
UString processedPath = fullPath;
|
||
|
|
||
|
if (!_processedFileInfo.IsDir)
|
||
|
pathParts.DeleteBack();
|
||
|
if (!pathParts.IsEmpty())
|
||
|
{
|
||
|
if (!isAnti)
|
||
|
CreateComplexDirectory(pathParts);
|
||
|
}
|
||
|
|
||
|
FString fullProcessedPath = _directoryPath + us2fs(processedPath);
|
||
|
|
||
|
if (_processedFileInfo.IsDir)
|
||
|
{
|
||
|
_diskFilePath = fullProcessedPath;
|
||
|
|
||
|
if (isAnti)
|
||
|
RemoveDir(_diskFilePath);
|
||
|
else
|
||
|
SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
NFind::CFileInfo fileInfo;
|
||
|
if (fileInfo.Find(fullProcessedPath))
|
||
|
{
|
||
|
if (!DeleteFileAlways(fullProcessedPath))
|
||
|
{
|
||
|
_message = kCantDeleteFile;
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!isAnti)
|
||
|
{
|
||
|
_outFileStreamSpec = new COutFileStream;
|
||
|
CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
|
||
|
if (!_outFileStreamSpec->Create(fullProcessedPath, true))
|
||
|
{
|
||
|
_message = kCantOpenFile;
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
_outFileStream = outStreamLoc;
|
||
|
*outStream = outStreamLoc.Detach();
|
||
|
}
|
||
|
_diskFilePath = fullProcessedPath;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*outStream = NULL;
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)
|
||
|
{
|
||
|
_extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)
|
||
|
{
|
||
|
switch (resultEOperationResult)
|
||
|
{
|
||
|
case NArchive::NExtract::NOperationResult::kOK:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
_outFileStream.Release();
|
||
|
switch (resultEOperationResult)
|
||
|
{
|
||
|
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
|
||
|
_message = kUnsupportedMethod;
|
||
|
break;
|
||
|
default:
|
||
|
_isCorrupt = true;
|
||
|
}
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
if (_outFileStream != NULL)
|
||
|
{
|
||
|
_outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
|
||
|
RINOK(_outFileStreamSpec->Close());
|
||
|
}
|
||
|
_outFileStream.Release();
|
||
|
if (_extractMode)
|
||
|
SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);
|
||
|
return S_OK;
|
||
|
}
|