// 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 LPCWSTR kCantDeleteFile = L"Can not delete output file"; | |
static LPCWSTR kCantOpenFile = L"Can not open output file"; | |
static LPCWSTR kUnsupportedMethod = L"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 | |
} | |
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 += FCHAR_PATH_SEPARATOR; | |
} | |
} | |
STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, | |
ISequentialOutStream **outStream, Int32 askExtractMode) | |
{ | |
#ifndef _NO_PROGRESS | |
if (ProgressDialog.Sync.GetStopped()) | |
return E_ABORT; | |
#endif | |
_outFileStream.Release(); | |
NCOM::CPropVariant propVariantName; | |
RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName)); | |
UString fullPath; | |
if (propVariantName.vt == VT_EMPTY) | |
fullPath = _itemDefaultName; | |
else | |
{ | |
if (propVariantName.vt != VT_BSTR) | |
return E_FAIL; | |
fullPath = propVariantName.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; | |
} |