1 // ArchiveOpenCallback.cpp 2 3 #include "StdAfx.h" 4 5 #include "../../../Common/ComTry.h" 6 7 #include "../../../Windows/FileName.h" 8 #include "../../../Windows/PropVariant.h" 9 10 #include "../../Common/FileStreams.h" 11 12 #include "ArchiveOpenCallback.h" 13 14 using namespace NWindows; 15 16 STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) 17 { 18 COM_TRY_BEGIN 19 if (ReOpenCallback) 20 return ReOpenCallback->SetTotal(files, bytes); 21 if (!Callback) 22 return S_OK; 23 return Callback->Open_SetTotal(files, bytes); 24 COM_TRY_END 25 } 26 27 STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) 28 { 29 COM_TRY_BEGIN 30 if (ReOpenCallback) 31 return ReOpenCallback->SetCompleted(files, bytes); 32 if (!Callback) 33 return S_OK; 34 return Callback->Open_SetCompleted(files, bytes); 35 COM_TRY_END 36 } 37 38 STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) 39 { 40 COM_TRY_BEGIN 41 NCOM::CPropVariant prop; 42 if (_subArchiveMode) 43 switch (propID) 44 { 45 case kpidName: prop = _subArchiveName; break; 46 // case kpidSize: prop = _subArchiveSize; break; // we don't use it now 47 } 48 else 49 switch (propID) 50 { 51 case kpidName: prop = _fileInfo.Name; break; 52 case kpidIsDir: prop = _fileInfo.IsDir(); break; 53 case kpidSize: prop = _fileInfo.Size; break; 54 case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; 55 case kpidCTime: prop = _fileInfo.CTime; break; 56 case kpidATime: prop = _fileInfo.ATime; break; 57 case kpidMTime: prop = _fileInfo.MTime; break; 58 } 59 prop.Detach(value); 60 return S_OK; 61 COM_TRY_END 62 } 63 64 struct CInFileStreamVol: public CInFileStream 65 { 66 int FileNameIndex; 67 COpenCallbackImp *OpenCallbackImp; 68 CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; 69 70 ~CInFileStreamVol() 71 { 72 if (OpenCallbackRef) 73 OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false; 74 } 75 }; 76 77 78 // from ArchiveExtractCallback.cpp 79 bool IsSafePath(const UString &path); 80 81 STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) 82 { 83 COM_TRY_BEGIN 84 *inStream = NULL; 85 86 if (_subArchiveMode) 87 return S_FALSE; 88 if (Callback) 89 { 90 RINOK(Callback->Open_CheckBreak()); 91 } 92 93 UString name2 = name; 94 95 96 #ifndef _SFX 97 98 #ifdef _WIN32 99 name2.Replace(L'/', WCHAR_PATH_SEPARATOR); 100 #endif 101 102 // if (!allowAbsVolPaths) 103 if (!IsSafePath(name2)) 104 return S_FALSE; 105 106 #endif 107 108 109 FString fullPath; 110 if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath)) 111 return S_FALSE; 112 if (!_fileInfo.Find(fullPath)) 113 return S_FALSE; 114 if (_fileInfo.IsDir()) 115 return S_FALSE; 116 CInFileStreamVol *inFile = new CInFileStreamVol; 117 CMyComPtr<IInStream> inStreamTemp = inFile; 118 if (!inFile->Open(fullPath)) 119 { 120 DWORD lastError = ::GetLastError(); 121 if (lastError == 0) 122 return E_FAIL; 123 return HRESULT_FROM_WIN32(lastError); 124 } 125 126 FileSizes.Add(_fileInfo.Size); 127 FileNames.Add(name2); 128 inFile->FileNameIndex = FileNames_WasUsed.Add(true); 129 inFile->OpenCallbackImp = this; 130 inFile->OpenCallbackRef = this; 131 // TotalSize += _fileInfo.Size; 132 *inStream = inStreamTemp.Detach(); 133 return S_OK; 134 COM_TRY_END 135 } 136 137 #ifndef _NO_CRYPTO 138 STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) 139 { 140 COM_TRY_BEGIN 141 if (ReOpenCallback) 142 { 143 CMyComPtr<ICryptoGetTextPassword> getTextPassword; 144 ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); 145 if (getTextPassword) 146 return getTextPassword->CryptoGetTextPassword(password); 147 } 148 if (!Callback) 149 return E_NOTIMPL; 150 PasswordWasAsked = true; 151 return Callback->Open_CryptoGetTextPassword(password); 152 COM_TRY_END 153 } 154 #endif 155