ExtractCallbackSfx.cpp (6346B)
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 LPCSTR const kCantDeleteFile = "Can not delete output file"; 19 static LPCSTR const kCantOpenFile = "Can not open output file"; 20 static LPCSTR const kUnsupportedMethod = "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 HRESULT CExtractCallbackImp::Open_Finished() 62 { 63 return S_OK; 64 } 65 66 STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size) 67 { 68 #ifndef _NO_PROGRESS 69 ProgressDialog.Sync.SetProgress(size, 0); 70 #endif 71 return S_OK; 72 } 73 74 STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue) 75 { 76 #ifndef _NO_PROGRESS 77 RINOK(ProgressDialog.Sync.ProcessStopAndPause()); 78 if (completeValue != NULL) 79 ProgressDialog.Sync.SetPos(*completeValue); 80 #endif 81 return S_OK; 82 } 83 84 void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts) 85 { 86 FString fullPath = _directoryPath; 87 FOR_VECTOR (i, dirPathParts) 88 { 89 fullPath += us2fs(dirPathParts[i]); 90 CreateDir(fullPath); 91 fullPath.Add_PathSepar(); 92 } 93 } 94 95 STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, 96 ISequentialOutStream **outStream, Int32 askExtractMode) 97 { 98 #ifndef _NO_PROGRESS 99 if (ProgressDialog.Sync.GetStopped()) 100 return E_ABORT; 101 #endif 102 _outFileStream.Release(); 103 104 UString fullPath; 105 { 106 NCOM::CPropVariant prop; 107 RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); 108 if (prop.vt == VT_EMPTY) 109 fullPath = _itemDefaultName; 110 else 111 { 112 if (prop.vt != VT_BSTR) 113 return E_FAIL; 114 fullPath.SetFromBstr(prop.bstrVal); 115 } 116 _filePath = fullPath; 117 } 118 119 if (askExtractMode == NArchive::NExtract::NAskMode::kExtract) 120 { 121 NCOM::CPropVariant prop; 122 RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); 123 if (prop.vt == VT_EMPTY) 124 _processedFileInfo.Attributes = _defaultAttributes; 125 else 126 { 127 if (prop.vt != VT_UI4) 128 return E_FAIL; 129 _processedFileInfo.Attributes = prop.ulVal; 130 } 131 132 RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop)); 133 _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal); 134 135 bool isAnti = false; 136 { 137 NCOM::CPropVariant propTemp; 138 RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp)); 139 if (propTemp.vt == VT_BOOL) 140 isAnti = VARIANT_BOOLToBool(propTemp.boolVal); 141 } 142 143 RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); 144 switch (prop.vt) 145 { 146 case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break; 147 case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break; 148 default: return E_FAIL; 149 } 150 151 UStringVector pathParts; 152 SplitPathToParts(fullPath, pathParts); 153 if (pathParts.IsEmpty()) 154 return E_FAIL; 155 156 UString processedPath = fullPath; 157 158 if (!_processedFileInfo.IsDir) 159 pathParts.DeleteBack(); 160 if (!pathParts.IsEmpty()) 161 { 162 if (!isAnti) 163 CreateComplexDirectory(pathParts); 164 } 165 166 FString fullProcessedPath = _directoryPath + us2fs(processedPath); 167 168 if (_processedFileInfo.IsDir) 169 { 170 _diskFilePath = fullProcessedPath; 171 172 if (isAnti) 173 RemoveDir(_diskFilePath); 174 else 175 SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime); 176 return S_OK; 177 } 178 179 NFind::CFileInfo fileInfo; 180 if (fileInfo.Find(fullProcessedPath)) 181 { 182 if (!DeleteFileAlways(fullProcessedPath)) 183 { 184 _message = kCantDeleteFile; 185 return E_FAIL; 186 } 187 } 188 189 if (!isAnti) 190 { 191 _outFileStreamSpec = new COutFileStream; 192 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); 193 if (!_outFileStreamSpec->Create(fullProcessedPath, true)) 194 { 195 _message = kCantOpenFile; 196 return E_FAIL; 197 } 198 _outFileStream = outStreamLoc; 199 *outStream = outStreamLoc.Detach(); 200 } 201 _diskFilePath = fullProcessedPath; 202 } 203 else 204 { 205 *outStream = NULL; 206 } 207 return S_OK; 208 } 209 210 STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode) 211 { 212 _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract); 213 return S_OK; 214 } 215 216 STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult) 217 { 218 switch (resultEOperationResult) 219 { 220 case NArchive::NExtract::NOperationResult::kOK: 221 break; 222 223 default: 224 { 225 _outFileStream.Release(); 226 switch (resultEOperationResult) 227 { 228 case NArchive::NExtract::NOperationResult::kUnsupportedMethod: 229 _message = kUnsupportedMethod; 230 break; 231 default: 232 _isCorrupt = true; 233 } 234 return E_FAIL; 235 } 236 } 237 if (_outFileStream != NULL) 238 { 239 _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); 240 RINOK(_outFileStreamSpec->Close()); 241 } 242 _outFileStream.Release(); 243 if (_extractMode) 244 SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes); 245 return S_OK; 246 }