1 /*******************************************************************************
\r
2 TPI - flexible but useless plug-in framework.
\r
3 Copyright (C) 2002-2009 Silky
\r
5 This library is free software; you can redistribute it and/or modify it under
\r
6 the terms of the GNU Lesser General Public License as published by the Free
\r
7 Software Foundation; either version 2.1 of the License, or (at your option)
\r
10 This library is distributed in the hope that it will be useful, but WITHOUT
\r
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
\r
15 You should have received a copy of the GNU Lesser General Public License along
\r
16 with this library; if not, write to the Free Software Foundation, Inc.,
\r
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\r
20 *******************************************************************************/
\r
22 //******************************************************************************
\r
24 //******************************************************************************
\r
26 #define wxUSE_DYNLIB_CLASS 1
\r
27 #include "../../common/header/plugin.h"
\r
28 #include "../../common/header/plugin-extra.h"
\r
29 #include "../../common/library/library.h"
\r
30 #include <wx/dynlib.h>
\r
34 #define LIB_NAME wxT("7z.so")
\r
36 #define LIB_NAME g_hLib.CanonicalizeName(wxT("7z"))
\r
39 //******************************************************************************
\r
41 //******************************************************************************
\r
43 wxDynamicLibrary g_hLib;
\r
46 wxULongLong_t g_nEngineId;
\r
48 //******************************************************************************
\r
50 //******************************************************************************
\r
52 int GetFileInformation2(void * _hArchive, TPI_FILEINFO * _fiInfo, wxULongLong_t nIndex)
\r
54 IInArchive * hArc = (IInArchive *) _hArchive;
\r
55 NWindows::NCOM::CPropVariant prop;
\r
56 hArc->GetProperty(nIndex, kpidAttrib, & prop);
\r
57 _fiInfo->dwAttribute = prop.vt == VT_EMPTY ? 0 : prop.uintVal;
\r
58 hArc->GetProperty(nIndex, kpidEncrypted, & prop);
\r
59 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
\r
61 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;
\r
63 hArc->GetProperty(nIndex, kpidIsDir, & prop);
\r
64 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
\r
66 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_DIRECTORY;
\r
68 hArc->GetProperty(nIndex, kpidCRC, & prop);
\r
69 _fiInfo->dwCRC32 = prop.ulVal;
\r
70 hArc->GetProperty(nIndex, kpidPackSize, & prop);
\r
71 _fiInfo->nPackedSize = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;
\r
72 hArc->GetProperty(nIndex, kpidSize, & prop);
\r
73 _fiInfo->nUnpackedSize = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;
\r
75 hArc->GetProperty(nIndex, kpidMTime, & prop);
\r
76 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
77 _fiInfo->tmModified.Set((time_t) t);
\r
78 hArc->GetProperty(nIndex, kpidCTime, & prop);
\r
79 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
80 _fiInfo->tmCreate.Set((time_t) t);
\r
81 hArc->GetProperty(nIndex, kpidATime, & prop);
\r
82 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
83 _fiInfo->tmAccess.Set((time_t) t);
\r
84 hArc->GetProperty(nIndex, kpidPath, & prop);
\r
85 if (prop.vt == VT_BSTR)
\r
87 _fiInfo->szStoredName = WC2String(prop.bstrVal);
\r
88 _fiInfo->fnFileName = wxFileName(_fiInfo->szStoredName, wxPATH_DOS);
\r
92 hArc->GetProperty(nIndex, kpidExtension, & prop);
\r
93 _fiInfo->szStoredName = wxT("data") + (prop.vt == VT_BSTR ? wxT(".") + WC2String(prop.bstrVal) : (wxString) wxEmptyString);
\r
94 _fiInfo->fnFileName = wxFileName(_fiInfo->szStoredName, wxPATH_DOS);
\r
96 hArc->GetProperty(nIndex, kpidMethod, & prop);
\r
97 if (prop.vt == VT_BSTR)
\r
99 _fiInfo->szMethod = WC2String(prop.bstrVal);
\r
101 hArc->GetProperty(nIndex, kpidCommented, & prop);
\r
102 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
\r
104 hArc->GetProperty(nIndex, kpidComment, & prop);
\r
105 _fiInfo->szComment = WC2String(prop.bstrVal);
\r
107 _fiInfo->nFileId = nIndex;
\r
108 return TPI_ERROR_SUCCESS;
\r
111 int __stdcall GetFormatInformation2(TPI_FORMATINFO * _fiInfo, wxULongLong_t & nIndex)
\r
114 _fiInfo->fArchive = true;
\r
115 _fiInfo->fComment = false;
\r
116 _fiInfo->fEncryptKeyFile = false;
\r
117 _fiInfo->fEncryptPassword = false;
\r
118 _fiInfo->fEncryptHeader = false;
\r
119 _fiInfo->fCompressHeader = false;
\r
120 _fiInfo->fMMOptimize = false;
\r
121 _fiInfo->fMultiVolume = false;
\r
122 _fiInfo->fSFX = false;
\r
123 _fiInfo->fSolid = false;
\r
124 _fiInfo->nCompressLevelMin = 0;
\r
125 _fiInfo->nCompressLevelMax = 0;
\r
126 _fiInfo->nRecoveryRecordMin = 0;
\r
127 _fiInfo->nRecoveryRecordMax = 0;
\r
128 _fiInfo->szTypeName.Empty();
\r
129 _fiInfo->szSuffix.Empty();
\r
130 _fiInfo->szEngineName = LIB_NAME;
\r
131 _fiInfo->szTPIName = wxT("7zArc");
\r
132 _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;
\r
133 _fiInfo->nTypeId = nIndex;
\r
134 _fiInfo->pCustomInfo = NULL;
\r
135 wxULongLong_t nBase = nIndex++;
\r
136 if (nBase >= sizeof(guidList) / sizeof(GUID))
\r
138 return TPI_ERROR_S_ENDOFDATA;
\r
140 else if (guidList[nBase] == CLSID_CFormatZip)
\r
142 _fiInfo->szTypeName = wxT("7-zip");
\r
143 _fiInfo->szSuffix = wxT("zip");
\r
144 _fiInfo->eSupportedCommand |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;
\r
145 _fiInfo->fSFX = true;
\r
146 _fiInfo->fMultiVolume = true;
\r
147 _fiInfo->fEncryptPassword = true;
\r
148 _fiInfo->nCompressLevelMin = 0;
\r
149 _fiInfo->nCompressLevelMax = 9;
\r
151 else if (guidList[nBase] == CLSID_CFormatBZip2)
\r
153 _fiInfo->szTypeName = wxT("BZip2");
\r
154 _fiInfo->szSuffix = wxT("bz2");
\r
155 _fiInfo->eSupportedCommand |= TPI_COMMAND_CREATE;
\r
156 _fiInfo->fArchive = false;
\r
157 _fiInfo->nCompressLevelMin = 1;
\r
158 _fiInfo->nCompressLevelMax = 9;
\r
161 else if (guidList[nBase] == CLSID_CFormatRar) { _fiInfo->szTypeName = wxT("Rar"); _fiInfo->szSuffix = wxT("rar"); }
\r
164 else if (guidList[nBase] == CLSID_CFormatArj) { _fiInfo->szTypeName = wxT("Arj"); _fiInfo->szSuffix = wxT("arj"); _fiInfo->fEncryptPassword = true; _fiInfo->fSFX = true; }
\r
166 else if (guidList[nBase] == CLSID_CFormatZ) { _fiInfo->szTypeName = wxT("Z"); _fiInfo->szSuffix = wxT("Z"); _fiInfo->fArchive = false; }
\r
168 else if (guidList[nBase] == CLSID_CFormatLzh) { _fiInfo->szTypeName = wxT("Lzh"); _fiInfo->szSuffix = wxT("lzh;lha;lzs"); _fiInfo->fSFX = true; }
\r
170 else if (guidList[nBase] == CLSID_CFormat7z)
\r
172 _fiInfo->szTypeName = wxT("7z");
\r
173 _fiInfo->szSuffix = wxT("7z");
\r
174 _fiInfo->eSupportedCommand |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;
\r
175 _fiInfo->fSFX = true;
\r
176 _fiInfo->fMultiVolume = true;
\r
177 _fiInfo->fSolid = true;
\r
178 _fiInfo->fEncryptPassword = true;
\r
179 _fiInfo->fEncryptHeader = true;
\r
180 _fiInfo->fCompressHeader = true;
\r
181 _fiInfo->nCompressLevelMin = 0;
\r
182 _fiInfo->nCompressLevelMax = 9;
\r
185 else if (guidList[nBase] == CLSID_CFormatCab) { _fiInfo->szTypeName = wxT("Cab"); _fiInfo->szSuffix = wxT("cab"); _fiInfo->fMultiVolume = true; _fiInfo->fSFX = true; }
\r
187 else if (guidList[nBase] == CLSID_CFormatNsis) { _fiInfo->szTypeName = wxT("NSIS"); _fiInfo->szSuffix = wxT("exe"); _fiInfo->fSFX = true; }
\r
188 else if (guidList[nBase] == CLSID_CFormatLzma) { _fiInfo->szTypeName = wxT("LZMA"); _fiInfo->szSuffix = wxT("lzma"); _fiInfo->fArchive = false; }
\r
189 else if (guidList[nBase] == CLSID_CFormatLzma86){_fiInfo->szTypeName = wxT("LZMA86"); _fiInfo->szSuffix = wxT("lzma"); _fiInfo->fArchive = false; }
\r
190 else if (guidList[nBase] == CLSID_CFormatXz)
\r
192 _fiInfo->szTypeName = wxT("XZ");
\r
193 _fiInfo->szSuffix = wxT("xz");
\r
194 _fiInfo->eSupportedCommand |= TPI_COMMAND_CREATE;
\r
195 _fiInfo->fArchive = false;
\r
196 _fiInfo->nCompressLevelMin = 0;
\r
197 _fiInfo->nCompressLevelMax = 9;
\r
199 else if (guidList[nBase] == CLSID_CFormatApm) { _fiInfo->szTypeName = wxT("Apm"); _fiInfo->szSuffix = wxT("apm"); }
\r
200 else if (guidList[nBase] == CLSID_CFormatMslz) { _fiInfo->szTypeName = wxT("MSLZ"); _fiInfo->szSuffix = wxT("xx_"); _fiInfo->fArchive = false; }
\r
201 else if (guidList[nBase] == CLSID_CFormatFlv) { _fiInfo->szTypeName = wxT("Flv"); _fiInfo->szSuffix = wxT("flv"); }
\r
202 else if (guidList[nBase] == CLSID_CFormatSwf) { _fiInfo->szTypeName = wxT("Swf"); _fiInfo->szSuffix = wxT("swf"); }
\r
203 else if (guidList[nBase] == CLSID_CFormatSwfc) { _fiInfo->szTypeName = wxT("Swfc"); _fiInfo->szSuffix = wxT("swfc");}
\r
204 else if (guidList[nBase] == CLSID_CFormatNtfs) { _fiInfo->szTypeName = wxT("NTFS"); _fiInfo->szSuffix = wxT("ntfs");}
\r
205 else if (guidList[nBase] == CLSID_CFormatFat) { _fiInfo->szTypeName = wxT("FAT"); _fiInfo->szSuffix = wxT("fat"); }
\r
206 else if (guidList[nBase] == CLSID_CFormatMbr) { _fiInfo->szTypeName = wxT("Mbr"); _fiInfo->szSuffix = wxT("mbr"); }
\r
207 else if (guidList[nBase] == CLSID_CFormatVhd) { _fiInfo->szTypeName = wxT("Vhd"); _fiInfo->szSuffix = wxT("vhd"); }
\r
209 else if (guidList[nBase] == CLSID_CFormatPe) { _fiInfo->szTypeName = wxT("PE"); _fiInfo->szSuffix = wxT("exe"); _fiInfo->fArchive = false; }
\r
210 else if (guidList[nBase] == CLSID_CFormatElf) { _fiInfo->szTypeName = wxT("ELF"); _fiInfo->fArchive = false; }
\r
212 else if (guidList[nBase] == CLSID_CFormatMachO){ _fiInfo->szTypeName = wxT("Mach-O"); }
\r
213 else if (guidList[nBase] == CLSID_CFormatUdf) { _fiInfo->szTypeName = wxT("Udf"); _fiInfo->szSuffix = wxT("udf"); }
\r
214 else if (guidList[nBase] == CLSID_CFormatXar) { _fiInfo->szTypeName = wxT("Xar"); _fiInfo->szSuffix = wxT("xar"); }
\r
215 else if (guidList[nBase] == CLSID_CFormatMub) { _fiInfo->szTypeName = wxT("Mub"); _fiInfo->szSuffix = wxT("mub"); }
\r
216 else if (guidList[nBase] == CLSID_CFormatHfs) { _fiInfo->szTypeName = wxT("HFS"); _fiInfo->szSuffix = wxT("hfs"); }
\r
217 else if (guidList[nBase] == CLSID_CFormatDmg) { _fiInfo->szTypeName = wxT("DMG"); _fiInfo->szSuffix = wxT("dmg"); }
\r
218 else if (guidList[nBase] == CLSID_CFormatCom) { _fiInfo->szTypeName = wxT("Compound");_fiInfo->szSuffix = wxT("msi"); _fiInfo->fSFX = true; }
\r
219 else if (guidList[nBase] == CLSID_CFormatWim) { _fiInfo->szTypeName = wxT("Wim"); _fiInfo->szSuffix = wxT("wim"); }
\r
220 else if (guidList[nBase] == CLSID_CFormatIso) { _fiInfo->szTypeName = wxT("ISO"); _fiInfo->szSuffix = wxT("iso"); }
\r
221 else if (guidList[nBase] == CLSID_CFormatBkf) { _fiInfo->szTypeName = wxT("Bkf"); _fiInfo->szSuffix = wxT("bkf"); }
\r
222 else if (guidList[nBase] == CLSID_CFormatChm) { _fiInfo->szTypeName = wxT("Chm"); _fiInfo->szSuffix = wxT("chm"); }
\r
223 else if (guidList[nBase] == CLSID_CFormatSplit){ _fiInfo->szTypeName = wxT("Split"); }
\r
225 else if (guidList[nBase] == CLSID_CFormatRpm) { _fiInfo->szTypeName = wxT("RPM"); _fiInfo->szSuffix = wxT("rpm"); _fiInfo->fArchive = false; }
\r
226 else if (guidList[nBase] == CLSID_CFormatDeb) { _fiInfo->szTypeName = wxT("Deb"); _fiInfo->szSuffix = wxT("deb"); }
\r
227 else if (guidList[nBase] == CLSID_CFormatCpio) { _fiInfo->szTypeName = wxT("Cpio"); _fiInfo->szSuffix = wxT("cpio");}
\r
228 else if (guidList[nBase] == CLSID_CFormatTar)
\r
230 _fiInfo->szTypeName = wxT("TAR");
\r
231 _fiInfo->szSuffix = wxT("tar");
\r
232 _fiInfo->fSFX = true;
\r
233 _fiInfo->eSupportedCommand |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;
\r
236 else if (guidList[nBase] == CLSID_CFormatGZip)
\r
238 _fiInfo->szTypeName = wxT("GZip");
\r
239 _fiInfo->szSuffix = wxT("gz");
\r
240 _fiInfo->eSupportedCommand |= TPI_COMMAND_CREATE;
\r
241 _fiInfo->fArchive = false;
\r
242 _fiInfo->nCompressLevelMin = 1;
\r
243 _fiInfo->nCompressLevelMax = 9;
\r
247 return GetFormatInformation2(_fiInfo, nIndex);
\r
249 return TPI_ERROR_SUCCESS;
\r
252 //******************************************************************************
\r
253 // Callback Wrapper
\r
254 //******************************************************************************
\r
256 // CArchiveOpenCallback
\r
257 class CArchiveOpenCallback: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, public ICryptoGetTextPassword, public CMyUnknownImp
\r
260 MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
\r
261 INTERFACE_IArchiveOpenCallback(;)
\r
262 INTERFACE_IArchiveOpenVolumeCallback(;)
\r
263 STDMETHOD(SetSubArchiveName)(const wchar_t * szName);
\r
264 STDMETHOD(CryptoGetTextPassword)(BSTR *password);
\r
266 wxString szSubArchiveName;
\r
267 NWindows::NFile::NFind::CFileInfoW fiInfo;
\r
270 TPI_PROCESSINFO piInfo;
\r
273 STDMETHODIMP CArchiveOpenCallback::SetTotal(const wxULongLong_t *, const wxULongLong_t *)
\r
278 STDMETHODIMP CArchiveOpenCallback::SetCompleted(const wxULongLong_t *, const wxULongLong_t *)
\r
283 STDMETHODIMP CArchiveOpenCallback::GetProperty(PROPID propID, PROPVARIANT * value)
\r
285 NWindows::NCOM::CPropVariant prop;
\r
286 if (! this->szSubArchiveName.IsEmpty())
\r
290 case kpidName: prop = (wxChar *) this->szSubArchiveName.wchar_str(); break;
\r
297 case kpidName: prop = this->fiInfo.Name; break;
\r
298 case kpidIsDir: prop = this->fiInfo.IsDir(); break;
\r
299 case kpidSize: prop = this->fiInfo.Size; break;
\r
300 case kpidAttrib:prop = (unsigned int) this->fiInfo.Attrib; break;
\r
301 case kpidCTime: prop = this->fiInfo.CTime; break;
\r
302 case kpidATime: prop = this->fiInfo.ATime; break;
\r
303 case kpidMTime: prop = this->fiInfo.MTime; break;
\r
306 prop.Detach(value);
\r
310 STDMETHODIMP CArchiveOpenCallback::GetStream(const wchar_t * szName, IInStream ** inStream)
\r
312 if (! this->szSubArchiveName.IsEmpty())
\r
317 wxString szFileName = this->piInfo.fiInfo.fnFileName.GetPathWithSep() + szName;
\r
318 if (! this->fiInfo.Find(szFileName.c_str()) || fiInfo.IsDir())
\r
320 this->nErrorCode = TPI_ERROR_IO_ARC_OPEN;
\r
324 CInFileStream * inFile = new CInFileStream;
\r
325 CMyComPtr<IInStream> inStreamTemp = inFile;
\r
326 if (! inFile->Open(szFileName.c_str()))
\r
328 this->nErrorCode = TPI_ERROR_IO_ARC_OPEN;
\r
331 * inStream = inStreamTemp.Detach();
\r
335 STDMETHODIMP CArchiveOpenCallback::SetSubArchiveName(const wchar_t * szName)
\r
337 this->szSubArchiveName = WC2String(szName);
\r
341 STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR * szPassword)
\r
343 this->piInfo.eMessage = TPI_MESSAGE_ASK;
\r
344 this->piInfo.eStatus = TPI_PARAM_PASSWORD;
\r
345 return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;
\r
348 // CArchiveExtractCallback
\r
349 class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp
\r
352 MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
\r
353 INTERFACE_IArchiveExtractCallback(;)
\r
354 STDMETHOD(CryptoGetTextPassword)(BSTR * szPassword);
\r
357 CMyComPtr<IInArchive> hArc;
\r
358 TPI_SWITCHES * swInfo;
\r
362 bool fTriedPassword;
\r
363 TPI_PROCESSINFO piInfo;
\r
364 wxULongLong_t nCurrentPos;
\r
365 COutFileStream * _outFileStreamSpec;
\r
366 CMyComPtr<ISequentialOutStream> _outFileStream;
\r
369 STDMETHODIMP CArchiveExtractCallback::SetTotal(wxULongLong_t)
\r
374 STDMETHODIMP CArchiveExtractCallback::SetCompleted(const wxULongLong_t * nProcessed)
\r
376 this->piInfo.eStatus = TPI_STATUS_INPROCESS;
\r
377 this->piInfo.nProcessedSize = * nProcessed - this->nCurrentPos;
\r
378 if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)
\r
384 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
389 STDMETHODIMP CArchiveExtractCallback::GetStream(unsigned int nIndex, ISequentialOutStream ** outStream, int nExtractMode)
\r
392 _outFileStream.Release();
\r
394 // 前のファイルの処理の終了を通知。
\r
395 this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;
\r
396 this->piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
397 if (this->nCurrentPos != 0)
\r
399 this->piInfo.eStatus = TPI_STATUS_ENDPROCESS;
\r
400 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
402 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
408 this->piInfo.eStatus = TPI_STATUS_BEGINPROCESS;
\r
409 GetFileInformation2(this->hArc, & this->piInfo.fiInfo, nIndex);
\r
410 this->piInfo.fnDestination = wxFileName(swInfo->fnDestinationDirectory.GetFullPath() + wxFileName::GetPathSeparator() + (swInfo->fStoreDirectoryPathes ? this->piInfo.fiInfo.fnFileName.GetPath() : (wxString) wxEmptyString), this->piInfo.fiInfo.fnFileName.GetFullName());
\r
411 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
413 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
417 if (nExtractMode != NArchive::NExtract::NAskMode::kExtract)
\r
422 // ディレクトリかどうかを判定し、必要なディレクトリを作成。
\r
423 if (! ::wxFileName::Mkdir(this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? this->piInfo.fnDestination.GetFullPath() : this->piInfo.fnDestination.GetPath(), 0777, wxPATH_MKDIR_FULL))
\r
425 this->nErrorCode = TPI_ERROR_IO_DIR_OPEN;
\r
428 if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
433 if (::wxFileExists(this->piInfo.fnDestination.GetFullPath()))
\r
436 if (! ::wxRemoveFile(this->piInfo.fnDestination.GetFullPath()))
\r
438 this->nErrorCode = TPI_ERROR_IO_FILE_DELETE;
\r
443 _outFileStreamSpec = new COutFileStream;
\r
444 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
\r
445 if (! _outFileStreamSpec->Open(this->piInfo.fnDestination.GetFullPath(), CREATE_ALWAYS))
\r
447 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;
\r
451 _outFileStream = outStreamLoc;
\r
452 * outStream = outStreamLoc.Detach();
\r
456 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(int nExtractMode)
\r
458 this->nMode = nExtractMode;
\r
462 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(int nResult)
\r
466 case NArchive::NExtract::NOperationResult::kOK: this->nErrorCode = TPI_ERROR_SUCCESS; break;
\r
467 case NArchive::NExtract::NOperationResult::kUnSupportedMethod: this->nErrorCode = TPI_ERROR_ARC_UNSUPPORTED; break;
\r
468 case NArchive::NExtract::NOperationResult::kDataError: this->nErrorCode = TPI_ERROR_ARC_BROKEN_MISC; break;
\r
469 case NArchive::NExtract::NOperationResult::kCRCError: this->nErrorCode = TPI_ERROR_ARC_BROKEN_SUM; break;
\r
470 default: this->nErrorCode = TPI_ERROR_UNDEFINED; break;
\r
474 if (_outFileStream != NULL)
\r
477 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmModified.GetTicks(), ft);
\r
478 _outFileStreamSpec->SetMTime(& ft);
\r
479 _outFileStreamSpec->Close();
\r
481 _outFileStream.Release();
\r
484 if (this->nMode == NArchive::NExtract::NAskMode::kExtract)
\r
486 // NWindows::NFile::NDirectory::MySetFileAttributes(this->piInfo.fiInfo.fnFileName.GetFullPath(), this->piInfo.fiInfo.dwAttribute);
\r
492 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR * szPassword)
\r
494 if (this->fTriedPassword || this->swInfo->szPassword.IsEmpty())
\r
496 this->piInfo.eMessage = TPI_MESSAGE_ASK;
\r
497 this->piInfo.eStatus = TPI_PARAM_PASSWORD;
\r
498 return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;
\r
502 // 既定のパスワードがある場合はまずそれを試す。
\r
503 this->fTriedPassword = true;
\r
504 return ::StringToBstr(this->swInfo->szPassword, szPassword);
\r
508 // CArchiveUpdateCallback
\r
509 class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp
\r
512 MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
\r
513 INTERFACE_IArchiveUpdateCallback2(;)
\r
514 STDMETHOD(CryptoGetTextPassword2)(int * nPasswordIsDefined, BSTR * szPassword);
\r
515 CArchiveUpdateCallback(): fiItems(0) {};
\r
517 const CObjectVector<NWindows::NFile::NFind::CFileInfoW> * fiItems;
\r
519 TPI_SWITCHES * swInfo;
\r
522 wxULongLong_t nCurrentPos;
\r
523 TPI_PROCESSINFO piInfo;
\r
526 STDMETHODIMP CArchiveUpdateCallback::SetTotal(wxULongLong_t)
\r
531 STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const wxULongLong_t * nProcessed)
\r
533 this->piInfo.eStatus = TPI_STATUS_INPROCESS;
\r
534 this->piInfo.nProcessedSize = * nProcessed - this->nCurrentPos;
\r
535 if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)
\r
541 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
546 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(unsigned int /* index */, int *newData, int *newProperties, unsigned int *indexInArchive)
\r
548 if (newData != NULL)
\r
552 if (newProperties != NULL)
\r
554 * newProperties = 1;
\r
556 if (indexInArchive != NULL)
\r
558 * indexInArchive = (unsigned) -1;
\r
563 STDMETHODIMP CArchiveUpdateCallback::GetProperty(unsigned int nIndex, PROPID propID, PROPVARIANT * value)
\r
565 NWindows::NCOM::CPropVariant prop;
\r
566 if (propID == kpidIsAnti)
\r
569 prop.Detach(value);
\r
573 const NWindows::NFile::NFind::CFileInfoW fiItem = (* this->fiItems)[nIndex];
\r
576 case kpidPath: prop = fiItem.Name; break;
\r
577 case kpidIsDir: prop = (unsigned int) fiItem.Attrib & TPI_ATTRIBUTE_DIRECTORY ? true : false; break;
\r
578 case kpidSize: prop = fiItem.Size; break;
\r
579 case kpidAttrib:prop = (unsigned int) fiItem.Attrib;break;
\r
580 case kpidCTime: prop = fiItem.CTime; break;
\r
581 case kpidATime: prop = fiItem.ATime; break;
\r
582 case kpidMTime: prop = fiItem.MTime; break;
\r
584 prop.Detach(value);
\r
588 STDMETHODIMP CArchiveUpdateCallback::GetStream(unsigned int nIndex, ISequentialInStream ** inStream)
\r
590 // 前のファイルの処理の終了を通知。
\r
591 this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;
\r
592 this->piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
593 if (this->nCurrentPos != 0)
\r
595 this->piInfo.eStatus = TPI_STATUS_ENDPROCESS;
\r
596 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
598 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
604 NWindows::NCOM::CPropVariant prop;
\r
605 this->GetProperty(nIndex, kpidAttrib, & prop);
\r
606 this->piInfo.fiInfo.dwAttribute = prop.uintVal;
\r
607 this->GetProperty(nIndex, kpidSize, & prop);
\r
608 this->piInfo.fiInfo.nUnpackedSize = prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;
\r
610 this->GetProperty(nIndex, kpidMTime, & prop);
\r
611 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
612 this->piInfo.fiInfo.tmModified.Set((time_t) t);
\r
613 this->GetProperty(nIndex, kpidCTime, & prop);
\r
614 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
615 this->piInfo.fiInfo.tmCreate.Set((time_t) t);
\r
616 this->GetProperty(nIndex, kpidATime, & prop);
\r
617 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
618 this->piInfo.fiInfo.tmAccess.Set((time_t) t);
\r
619 this->GetProperty(nIndex, kpidPath, & prop);
\r
620 this->piInfo.fiInfo.szStoredName = WC2String(prop.bstrVal);
\r
621 this->piInfo.fiInfo.nFileId = nIndex;
\r
622 this->piInfo.fiInfo.fnFileName = wxFileName(this->piInfo.fiInfo.szStoredName);
\r
623 this->piInfo.fiInfo.fnFileName.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, this->swInfo->fnDestinationDirectory.GetFullPath());
\r
624 this->piInfo.eStatus = TPI_STATUS_BEGINPROCESS;
\r
625 this->piInfo.fnDestination = wxFileName(this->piInfo.fiInfo.szStoredName);
\r
628 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
630 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
634 if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
639 CInFileStream * inStreamSpec = new CInFileStream;
\r
640 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
\r
641 if (! inStreamSpec->Open(this->piInfo.fiInfo.fnFileName.GetFullPath().c_str()))
\r
643 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;
\r
647 * inStream = inStreamLoc.Detach();
\r
651 STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(int nResult)
\r
655 case NArchive::NUpdate::NOperationResult::kOK: this->nErrorCode = TPI_ERROR_SUCCESS; break;
\r
656 case NArchive::NUpdate::NOperationResult::kError:
\r
657 default: this->nErrorCode = TPI_ERROR_UNDEFINED; break;
\r
662 STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(unsigned int, wxULongLong_t * nSplitSize)
\r
664 * nSplitSize = this->swInfo->nSplitSize;
\r
668 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(unsigned int nIndex, ISequentialOutStream ** volumeStream)
\r
670 COutFileStream * streamSpec = new COutFileStream;
\r
671 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
\r
672 if (! streamSpec->Create(this->piInfo.fiInfo.fnFileName.GetFullPath() + wxString::Format(wxT(".%03d"), nIndex + 1), false))
\r
674 return TPI_ERROR_IO_ARC_OPEN;
\r
676 * volumeStream = streamLoc.Detach();
\r
680 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(int * nPasswordIsDefined, BSTR * szPassword)
\r
682 * nPasswordIsDefined = ! this->swInfo->szPassword.IsEmpty();
\r
683 return ::StringToBstr(this->swInfo->szPassword.c_str(), szPassword);
\r
686 //******************************************************************************
\r
688 //******************************************************************************
\r
695 int __stdcall GetPluginInformation
\r
697 unsigned int _uInfoId,
\r
704 return TPI_ERROR_D_PARAMETER;
\r
708 case TPI_INFO_VERSION_MAJOR:
\r
709 case TPI_INFO_VERSION_MINOR:
\r
710 * (int *) _pPtr = 0;
\r
712 case TPI_INFO_VERSION_API:
\r
713 * (int *) _pPtr = 2;
\r
716 return TPI_ERROR_D_UNSUPPORTED;
\r
718 return TPI_ERROR_SUCCESS;
\r
721 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)
\r
723 static wxULongLong_t s_nTypeId;
\r
728 return GetFormatInformation2(_fiInfo, s_nTypeId);
\r
731 int __stdcall LoadPlugin
\r
733 const wxString & _szArcName,
\r
734 wxULongLong_t _nTypeId
\r
737 ::RemoveCwdFromSearchPath();
\r
738 g_hLib.Load(LIB_NAME);
\r
739 if (! g_hLib.IsLoaded())
\r
742 return TPI_ERROR_U_LOAD_LIBRARY;
\r
745 if (! g_hLib.HasSymbol(wxT("CreateObject")))
\r
747 return TPI_ERROR_U_USE_LIBRARY;
\r
749 g_fpProc = g_hLib.GetSymbol(wxT("CreateObject"));
\r
752 return TPI_ERROR_U_USE_LIBRARY;
\r
755 if (! ::wxFileExists(_szArcName))
\r
757 g_nEngineId = _nTypeId;
\r
760 return TPI_ERROR_SUCCESS;
\r
763 int __stdcall FreePlugin
\r
765 void * // _pReserved
\r
769 return TPI_ERROR_SUCCESS;
\r
772 int __stdcall CheckArchive
\r
774 const wxString & _szArcName,
\r
775 wxULongLong_t * _llFileCount
\r
779 int nErrorCode = OpenArchive(_szArcName, & _hArchive);
\r
780 if (nErrorCode != TPI_ERROR_SUCCESS)
\r
785 if (_llFileCount != NULL)
\r
787 unsigned int nFileCount = 0;
\r
788 ((IInArchive *) _hArchive)->GetNumberOfItems(& nFileCount);
\r
789 * _llFileCount = nFileCount;
\r
792 return CloseArchive(_hArchive);
\r
795 int __stdcall OpenArchive
\r
797 const wxString & _szArcName,
\r
801 // ***.tar.xxxは不便なので弾く。
\r
802 wxString s = _szArcName.BeforeLast(wxT('.'));
\r
803 if (s.Find(wxT('.')) != wxNOT_FOUND && s.AfterLast(wxT('.')) == wxT("tar"))
\r
805 return TPI_ERROR_IO_ARC_OPEN;
\r
810 for (wxULongLong_t i = 0; i < sizeof(guidList) / sizeof(GUID); )
\r
812 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void * *)) g_fpProc)(& guidList[i], & IID_IInArchive, (void **) & hArc) != S_OK)
\r
819 CInFileStream * fileSpec = new CInFileStream;
\r
820 CMyComPtr<IInStream> file = fileSpec;
\r
821 if (! fileSpec->Open(_szArcName.c_str()))
\r
823 return TPI_ERROR_IO_ARC_OPEN;
\r
828 TPI_FORMATINFO fiInfo;
\r
829 GetFormatInformation2(& fiInfo, i);
\r
832 CArchiveOpenCallback * openCallbackSpec = new CArchiveOpenCallback;
\r
833 CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
\r
834 wxULongLong_t nMax = 0;
\r
837 fileSpec->GetSize(& nMax);
\r
839 if (hArc->Open(file, & nMax, openCallback) == S_OK)
\r
841 * _hArchive = hArc;
\r
842 return TPI_ERROR_SUCCESS;
\r
845 return TPI_ERROR_IO_ARC_OPEN;
\r
848 int __stdcall CloseArchive
\r
853 IInArchive * hArc = (IInArchive *) _hArchive;
\r
856 return TPI_ERROR_SUCCESS;
\r
859 int __stdcall GetFileInformation
\r
862 TPI_FILEINFO * _fiInfo,
\r
866 static unsigned int s_uFileId, s_uFileCount;
\r
870 ((IInArchive *) _hArchive)->GetNumberOfItems(& s_uFileCount);
\r
873 if (s_uFileId >= s_uFileCount)
\r
875 return TPI_ERROR_S_ENDOFDATA;
\r
878 return GetFileInformation2(_hArchive, _fiInfo, s_uFileId++);
\r
881 int __stdcall GetArchiveInformation
\r
884 TPI_ARCHIVEINFO * _aiInfo
\r
887 IInArchive * hArc = (IInArchive *) _hArchive;
\r
888 NWindows::NCOM::CPropVariant prop;
\r
889 hArc->GetArchiveProperty(kpidSolid, & prop);
\r
890 _aiInfo->fSolid = VARIANT_BOOLToBool(prop.boolVal);
\r
891 hArc->GetArchiveProperty(kpidComment, & prop);
\r
892 if (prop.vt == VT_BSTR)
\r
894 _aiInfo->szComment = WC2String(prop.bstrVal);
\r
896 wxULongLong_t n = g_nEngineId;
\r
897 GetFormatInformation2(& _aiInfo->fiInfo, n);
\r
898 return TPI_ERROR_SUCCESS;
\r
901 int __stdcall Command
\r
903 wxULongLong_t _eCommand,
\r
904 TPI_SWITCHES * _swInfo,
\r
905 const wxString & _szArcName,
\r
906 const wxArrayString & _szFiles
\r
913 case TPI_COMMAND_EXTRACT:
\r
914 case TPI_COMMAND_TEST:
\r
918 nErrorCode = OpenArchive(_szArcName, (void **) & hArc);
\r
919 if (nErrorCode != TPI_ERROR_SUCCESS)
\r
924 // ファイル名からインデックスを取得。
\r
925 TPI_FILEINFO fiInfo;
\r
926 CRecordVector<unsigned int> nIndexes;
\r
927 if (GetFileInformation(hArc, & fiInfo, true) == TPI_ERROR_SUCCESS)
\r
931 if (_szFiles.Index(fiInfo.szStoredName) != wxNOT_FOUND)
\r
933 nIndexes.Add(fiInfo.nFileId);
\r
936 while (GetFileInformation(hArc, & fiInfo, false) == TPI_ERROR_SUCCESS);
\r
939 CArchiveExtractCallback * extractCallbackSpec = new CArchiveExtractCallback;
\r
940 CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
\r
941 extractCallbackSpec->hArc = hArc;
\r
942 extractCallbackSpec->swInfo = _swInfo;
\r
943 hArc->Extract(& nIndexes.Front(), nIndexes.Size(), _eCommand == TPI_COMMAND_TEST, extractCallback);
\r
944 nErrorCode = extractCallbackSpec->nErrorCode;
\r
945 CloseArchive(hArc);
\r
948 case TPI_COMMAND_CREATE:
\r
949 // case TPI_COMMAND_ADD:
\r
952 CObjectVector<NWindows::NFile::NFind::CFileInfoW> fiItems;
\r
953 for (unsigned int i = 0; i < _szFiles.GetCount(); i++)
\r
955 NWindows::NFile::NFind::CFileInfoW fi;
\r
956 wxFileName fn(_szFiles[i]);
\r
957 fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, _swInfo->fnDestinationDirectory.GetFullPath());
\r
958 if (! fi.Find(fn.GetFullPath().c_str()))
\r
960 return TPI_ERROR_IO_FILE_ACCESS;
\r
966 COutFileStream * outFileStreamSpec = new COutFileStream;
\r
967 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
\r
968 if (! outFileStreamSpec->Create(_szArcName.c_str(), false))
\r
970 return TPI_ERROR_IO_ARC_OPEN;
\r
974 IOutArchive * hArc;
\r
975 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void **)) g_fpProc)(& guidList[g_nEngineId], & IID_IOutArchive, (void **) & hArc) != S_OK)
\r
977 return TPI_ERROR_ARC_UNSUPPORTED;
\r
981 TPI_FORMATINFO fiInfo;
\r
982 wxULongLong_t nIndex = g_nEngineId;
\r
983 GetFormatInformation2(& fiInfo, nIndex);
\r
986 ISetProperties * setProp;
\r
987 if (hArc->QueryInterface(IID_ISetProperties, (void **) & setProp) == S_OK)
\r
989 CRecordVector<const wchar_t *> szProps;
\r
990 NWindows::NCOM::CPropVariant propValues[15];
\r
993 if (fiInfo.nCompressLevelMin != fiInfo.nCompressLevelMax)
\r
995 szProp = wxString::Format(wxT("x%d"), _swInfo->nCompressLevel);
\r
996 szProps.Add(szProp.c_str());
\r
1001 propValues[szProps.Size()] = _swInfo->fSolid;
\r
1002 szProps.Add(wxT("s"));
\r
1005 if (fiInfo.fCompressHeader)
\r
1007 propValues[szProps.Size()] = _swInfo->fCompressHeader;
\r
1008 szProps.Add(wxT("hc"));
\r
1011 if (fiInfo.fEncryptHeader)
\r
1013 propValues[szProps.Size()] = _swInfo->fEncryptHeader;
\r
1014 szProps.Add(wxT("he"));
\r
1017 // szProp = wxString::Format(wxT("m"));
\r
1018 // propValues[szProps.Size()] = L"Deflate";
\r
1019 // szProps.Add(szProp.c_str());
\r
1021 // szProp = wxString::Format(wxT("fb%d"), );
\r
1022 // szProps.Add(szProp.c_str());
\r
1024 setProp->SetProperties(& szProps.Front(), propValues, szProps.Size());
\r
1028 CArchiveUpdateCallback * updateCallbackSpec = new CArchiveUpdateCallback;
\r
1029 CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
\r
1030 updateCallbackSpec->fiItems = & fiItems;
\r
1031 updateCallbackSpec->swInfo = _swInfo;
\r
1032 hArc->UpdateItems(outFileStream, fiItems.Size(), updateCallback);
\r
1033 nErrorCode = updateCallbackSpec->nErrorCode;
\r
1037 nErrorCode = TPI_ERROR_D_UNSUPPORTED;
\r
1039 return nErrorCode;
\r
1042 int __stdcall SetCallbackProc
\r
1044 TPI_PROC _prArcProc
\r
1048 if (_prArcProc == NULL)
\r
1050 return TPI_ERROR_D_PARAMETER;
\r
1052 g_prProc = * _prArcProc;
\r
1054 return TPI_ERROR_SUCCESS;
\r
1057 #ifdef __cplusplus
\r