• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Init(IInArchive * archiveHandler,const FString & directoryPath,const UString & itemDefaultName,const FILETIME & defaultMTime,UInt32 defaultAttributes)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 
Open_CheckBreak()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 
Open_SetTotal(const UInt64 *,const UInt64 *)47 HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
48 {
49   return S_OK;
50 }
51 
Open_SetCompleted(const UInt64 *,const UInt64 *)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 
SetTotal(UInt64 size)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 
SetCompleted(const UInt64 * completeValue)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 
CreateComplexDirectory(const UStringVector & dirPathParts)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 
GetStream(UInt32 index,ISequentialOutStream ** outStream,Int32 askExtractMode)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 
PrepareOperation(Int32 askExtractMode)202 STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)
203 {
204   _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);
205   return S_OK;
206 }
207 
SetOperationResult(Int32 resultEOperationResult)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