Home | History | Annotate | Download | only in SFXSetup
      1 // ExtractCallbackSfx.h
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../Common/Wildcard.h"
      6 
      7 #include "../../../Windows/FileDir.h"
      8 #include "../../../Windows/FileFind.h"
      9 #include "../../../Windows/FileName.h"
     10 #include "../../../Windows/PropVariant.h"
     11 
     12 #include "ExtractCallbackSfx.h"
     13 
     14 using namespace NWindows;
     15 using namespace NFile;
     16 using namespace NDir;
     17 
     18 static LPCWSTR kCantDeleteFile = L"Can not delete output file";
     19 static LPCWSTR kCantOpenFile = L"Can not open output file";
     20 static LPCWSTR kUnsupportedMethod = L"Unsupported Method";
     21 
     22 void CExtractCallbackImp::Init(IInArchive *archiveHandler,
     23     const FString &directoryPath,
     24     const UString &itemDefaultName,
     25     const FILETIME &defaultMTime,
     26     UInt32 defaultAttributes)
     27 {
     28   _message.Empty();
     29   _isCorrupt = false;
     30   _itemDefaultName = itemDefaultName;
     31   _defaultMTime = defaultMTime;
     32   _defaultAttributes = defaultAttributes;
     33   _archiveHandler = archiveHandler;
     34   _directoryPath = directoryPath;
     35   NName::NormalizeDirPathPrefix(_directoryPath);
     36 }
     37 
     38 HRESULT CExtractCallbackImp::Open_CheckBreak()
     39 {
     40   #ifndef _NO_PROGRESS
     41   return ProgressDialog.Sync.ProcessStopAndPause();
     42   #else
     43   return S_OK;
     44   #endif
     45 }
     46 
     47 HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
     48 {
     49   return S_OK;
     50 }
     51 
     52 HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
     53 {
     54   #ifndef _NO_PROGRESS
     55   return ProgressDialog.Sync.ProcessStopAndPause();
     56   #else
     57   return S_OK;
     58   #endif
     59 }
     60 
     61 STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)
     62 {
     63   #ifndef _NO_PROGRESS
     64   ProgressDialog.Sync.SetProgress(size, 0);
     65   #endif
     66   return S_OK;
     67 }
     68 
     69 STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
     70 {
     71   #ifndef _NO_PROGRESS
     72   RINOK(ProgressDialog.Sync.ProcessStopAndPause());
     73   if (completeValue != NULL)
     74     ProgressDialog.Sync.SetPos(*completeValue);
     75   #endif
     76   return S_OK;
     77 }
     78 
     79 void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
     80 {
     81   FString fullPath = _directoryPath;
     82   FOR_VECTOR (i, dirPathParts)
     83   {
     84     fullPath += us2fs(dirPathParts[i]);
     85     CreateDir(fullPath);
     86     fullPath += FCHAR_PATH_SEPARATOR;
     87   }
     88 }
     89 
     90 STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
     91     ISequentialOutStream **outStream, Int32 askExtractMode)
     92 {
     93   #ifndef _NO_PROGRESS
     94   if (ProgressDialog.Sync.GetStopped())
     95     return E_ABORT;
     96   #endif
     97   _outFileStream.Release();
     98   NCOM::CPropVariant propVariantName;
     99   RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName));
    100   UString fullPath;
    101   if (propVariantName.vt == VT_EMPTY)
    102     fullPath = _itemDefaultName;
    103   else
    104   {
    105     if (propVariantName.vt != VT_BSTR)
    106       return E_FAIL;
    107     fullPath = propVariantName.bstrVal;
    108   }
    109   _filePath = fullPath;
    110 
    111   if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)
    112   {
    113     NCOM::CPropVariant prop;
    114     RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
    115     if (prop.vt == VT_EMPTY)
    116       _processedFileInfo.Attributes = _defaultAttributes;
    117     else
    118     {
    119       if (prop.vt != VT_UI4)
    120         return E_FAIL;
    121       _processedFileInfo.Attributes = prop.ulVal;
    122     }
    123 
    124     RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop));
    125     _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);
    126 
    127     bool isAnti = false;
    128     {
    129       NCOM::CPropVariant propTemp;
    130       RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp));
    131       if (propTemp.vt == VT_BOOL)
    132         isAnti = VARIANT_BOOLToBool(propTemp.boolVal);
    133     }
    134 
    135     RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
    136     switch(prop.vt)
    137     {
    138       case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;
    139       case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;
    140       default: return E_FAIL;
    141     }
    142 
    143     UStringVector pathParts;
    144     SplitPathToParts(fullPath, pathParts);
    145     if (pathParts.IsEmpty())
    146       return E_FAIL;
    147 
    148     UString processedPath = fullPath;
    149 
    150     if (!_processedFileInfo.IsDir)
    151       pathParts.DeleteBack();
    152     if (!pathParts.IsEmpty())
    153     {
    154       if (!isAnti)
    155         CreateComplexDirectory(pathParts);
    156     }
    157 
    158     FString fullProcessedPath = _directoryPath + us2fs(processedPath);
    159 
    160     if (_processedFileInfo.IsDir)
    161     {
    162       _diskFilePath = fullProcessedPath;
    163 
    164       if (isAnti)
    165         RemoveDir(_diskFilePath);
    166       else
    167         SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
    168       return S_OK;
    169     }
    170 
    171     NFind::CFileInfo fileInfo;
    172     if (fileInfo.Find(fullProcessedPath))
    173     {
    174       if (!DeleteFileAlways(fullProcessedPath))
    175       {
    176         _message = kCantDeleteFile;
    177         return E_FAIL;
    178       }
    179     }
    180 
    181     if (!isAnti)
    182     {
    183       _outFileStreamSpec = new COutFileStream;
    184       CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
    185       if (!_outFileStreamSpec->Create(fullProcessedPath, true))
    186       {
    187         _message = kCantOpenFile;
    188         return E_FAIL;
    189       }
    190       _outFileStream = outStreamLoc;
    191       *outStream = outStreamLoc.Detach();
    192     }
    193     _diskFilePath = fullProcessedPath;
    194   }
    195   else
    196   {
    197     *outStream = NULL;
    198   }
    199   return S_OK;
    200 }
    201 
    202 STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)
    203 {
    204   _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);
    205   return S_OK;
    206 }
    207 
    208 STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)
    209 {
    210   switch(resultEOperationResult)
    211   {
    212     case NArchive::NExtract::NOperationResult::kOK:
    213       break;
    214 
    215     default:
    216     {
    217       _outFileStream.Release();
    218       switch(resultEOperationResult)
    219       {
    220         case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
    221           _message = kUnsupportedMethod;
    222           break;
    223         default:
    224           _isCorrupt = true;
    225       }
    226       return E_FAIL;
    227     }
    228   }
    229   if (_outFileStream != NULL)
    230   {
    231     _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
    232     RINOK(_outFileStreamSpec->Close());
    233   }
    234   _outFileStream.Release();
    235   if (_extractMode)
    236     SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);
    237   return S_OK;
    238 }
    239