1 // ArchiveOpenCallback.cpp 2 3 #include "StdAfx.h" 4 5 #include "Common/StringConvert.h" 6 #include "Common/ComTry.h" 7 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 } 47 else 48 switch(propID) 49 { 50 case kpidName: prop = _fileInfo.Name; break; 51 case kpidIsDir: prop = _fileInfo.IsDir(); break; 52 case kpidSize: prop = _fileInfo.Size; break; 53 case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; 54 case kpidCTime: prop = _fileInfo.CTime; break; 55 case kpidATime: prop = _fileInfo.ATime; break; 56 case kpidMTime: prop = _fileInfo.MTime; break; 57 } 58 prop.Detach(value); 59 return S_OK; 60 COM_TRY_END 61 } 62 63 int COpenCallbackImp::FindName(const UString &name) 64 { 65 for (int i = 0; i < FileNames.Size(); i++) 66 if (name.CompareNoCase(FileNames[i]) == 0) 67 return i; 68 return -1; 69 } 70 71 struct CInFileStreamVol: public CInFileStream 72 { 73 UString Name; 74 COpenCallbackImp *OpenCallbackImp; 75 CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; 76 ~CInFileStreamVol() 77 { 78 if (OpenCallbackRef) 79 { 80 int index = OpenCallbackImp->FindName(Name); 81 if (index >= 0) 82 OpenCallbackImp->FileNames.Delete(index); 83 } 84 } 85 }; 86 87 STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) 88 { 89 COM_TRY_BEGIN 90 if (_subArchiveMode) 91 return S_FALSE; 92 if (Callback) 93 { 94 RINOK(Callback->Open_CheckBreak()); 95 } 96 *inStream = NULL; 97 UString fullPath = _folderPrefix + name; 98 if (!_fileInfo.Find(fullPath)) 99 return S_FALSE; 100 if (_fileInfo.IsDir()) 101 return S_FALSE; 102 CInFileStreamVol *inFile = new CInFileStreamVol; 103 CMyComPtr<IInStream> inStreamTemp = inFile; 104 if (!inFile->Open(fullPath)) 105 return ::GetLastError(); 106 *inStream = inStreamTemp.Detach(); 107 inFile->Name = name; 108 inFile->OpenCallbackImp = this; 109 inFile->OpenCallbackRef = this; 110 FileNames.Add(name); 111 TotalSize += _fileInfo.Size; 112 return S_OK; 113 COM_TRY_END 114 } 115 116 #ifndef _NO_CRYPTO 117 STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) 118 { 119 COM_TRY_BEGIN 120 if (ReOpenCallback) 121 { 122 CMyComPtr<ICryptoGetTextPassword> getTextPassword; 123 ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); 124 if (getTextPassword) 125 return getTextPassword->CryptoGetTextPassword(password); 126 } 127 if (!Callback) 128 return E_NOTIMPL; 129 return Callback->Open_CryptoGetTextPassword(password); 130 COM_TRY_END 131 } 132 #endif 133 134