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 #define MYUSE_LIBPATH 1
\r
28 #include "../../common/header/plugin.h"
\r
29 #include "../../common/header/plugin-extra.h"
\r
30 #include "../../common/library/library.h"
\r
31 #include "../../common/library/xmldoc.h"
\r
32 #include <wx/dynlib.h>
\r
36 #define LIB_NAME wxT("7z.so")
\r
37 #define CFileInfo CFileInfoW
\r
39 #define LIB_NAME g_LibInfo.hLib.CanonicalizeName(wxT("7z"))
\r
42 //******************************************************************************
\r
44 //******************************************************************************
\r
48 wxDynamicLibrary hLib;
\r
57 extern int global_use_utf16_conversion;
\r
60 //******************************************************************************
\r
62 //******************************************************************************
\r
64 int GetFileInformation2(void * _hArchive, TPI_FILEINFO * _fiInfo, wxULongLong_t nIndex)
\r
66 IInArchive * hArc = (IInArchive *) _hArchive;
\r
67 NWindows::NCOM::CPropVariant prop;
\r
68 hArc->GetProperty(nIndex, kpidAttrib, & prop);
\r
69 _fiInfo->dwAttribute = prop.vt == VT_EMPTY ? 0 : prop.uintVal;
\r
70 hArc->GetProperty(nIndex, kpidEncrypted, & prop);
\r
71 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
\r
73 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;
\r
75 hArc->GetProperty(nIndex, kpidIsDir, & prop);
\r
76 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
\r
78 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_DIRECTORY;
\r
80 hArc->GetProperty(nIndex, kpidPosixAttrib, & prop);
\r
81 _fiInfo->wPermission = prop.vt == VT_EMPTY ? 0664 : prop.uintVal;
\r
82 hArc->GetProperty(nIndex, kpidEncrypted, & prop);
\r
83 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
\r
85 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;
\r
87 hArc->GetProperty(nIndex, kpidCRC, & prop);
\r
88 _fiInfo->dwCRC32 = prop.ulVal;
\r
89 hArc->GetProperty(nIndex, kpidPackSize, & prop);
\r
90 _fiInfo->nPackedSize = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;
\r
91 hArc->GetProperty(nIndex, kpidSize, & prop);
\r
92 _fiInfo->nUnpackedSize = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;
\r
94 hArc->GetProperty(nIndex, kpidMTime, & prop);
\r
95 if (prop.vt == VT_FILETIME)
\r
97 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
98 _fiInfo->tmModify.Set((time_t) t);
\r
102 _fiInfo->tmModify.SetToCurrent();
\r
104 hArc->GetProperty(nIndex, kpidCTime, & prop);
\r
105 if (prop.vt == VT_FILETIME)
\r
107 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
108 _fiInfo->tmCreate.Set((time_t) t);
\r
112 _fiInfo->tmCreate.SetToCurrent();
\r
114 hArc->GetProperty(nIndex, kpidATime, & prop);
\r
115 if (prop.vt == VT_FILETIME)
\r
117 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
118 _fiInfo->tmAccess.Set((time_t) t);
\r
122 _fiInfo->tmAccess.SetToCurrent();
\r
124 hArc->GetProperty(nIndex, kpidPath, & prop);
\r
125 if (prop.vt == VT_BSTR)
\r
127 _fiInfo->szStoredName = WC2String(prop.bstrVal);
\r
128 _fiInfo->fnFileName = wxFileName(_fiInfo->szStoredName, wxPATH_DOS);
\r
132 hArc->GetProperty(nIndex, kpidExtension, & prop);
\r
133 _fiInfo->szStoredName.Empty();
\r
134 _fiInfo->fnFileName.SetExt(prop.vt == VT_BSTR ? WC2String(prop.bstrVal) : (wxString) wxEmptyString);
\r
136 hArc->GetProperty(nIndex, kpidMethod, & prop); _fiInfo->szMethod = prop.vt == VT_BSTR ? WC2String(prop.bstrVal) : (wxString) wxEmptyString;
\r
137 hArc->GetProperty(nIndex, kpidComment, & prop); _fiInfo->szComment = prop.vt == VT_BSTR ? WC2String(prop.bstrVal) : (wxString) wxEmptyString;
\r
138 hArc->GetProperty(nIndex, kpidUser, & prop); _fiInfo->szUser = prop.vt == VT_BSTR ? WC2String(prop.bstrVal) : (wxString) wxEmptyString;
\r
139 hArc->GetProperty(nIndex, kpidComment, & prop); _fiInfo->szGroup = prop.vt == VT_BSTR ? WC2String(prop.bstrVal) : (wxString) wxEmptyString;
\r
140 _fiInfo->nFileId = nIndex;
\r
141 return TPI_ERROR_SUCCESS;
\r
144 //******************************************************************************
\r
145 // Callback Wrapper
\r
146 //******************************************************************************
\r
148 // CArchiveOpenCallback
\r
149 class CArchiveOpenCallback: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, public ICryptoGetTextPassword, public CMyUnknownImp
\r
152 MY_UNKNOWN_IMP3(ICryptoGetTextPassword, IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName)
\r
153 INTERFACE_IArchiveOpenCallback(;)
\r
154 INTERFACE_IArchiveOpenVolumeCallback(;)
\r
155 STDMETHOD(SetSubArchiveName)(const wchar_t * szName);
\r
156 STDMETHOD(CryptoGetTextPassword)(BSTR *password);
\r
158 wxString szSubArchiveName;
\r
159 NWindows::NFile::NFind::CFileInfo fiInfo;
\r
162 TPI_PROCESSINFO piInfo;
\r
165 STDMETHODIMP CArchiveOpenCallback::SetTotal(const wxULongLong_t *, const wxULongLong_t *)
\r
170 STDMETHODIMP CArchiveOpenCallback::SetCompleted(const wxULongLong_t *, const wxULongLong_t *)
\r
175 STDMETHODIMP CArchiveOpenCallback::GetProperty(PROPID propID, PROPVARIANT * value)
\r
177 NWindows::NCOM::CPropVariant prop;
\r
178 if (! this->szSubArchiveName.IsEmpty())
\r
182 case kpidName: prop = (wxChar *) this->szSubArchiveName.wchar_str(); break;
\r
189 case kpidName: prop = this->fiInfo.Name; break;
\r
190 case kpidIsDir: prop = this->fiInfo.IsDir(); break;
\r
191 case kpidSize: prop = this->fiInfo.Size; break;
\r
192 case kpidAttrib:prop = (unsigned int) this->fiInfo.Attrib; break;
\r
193 case kpidCTime: prop = this->fiInfo.CTime; break;
\r
194 case kpidATime: prop = this->fiInfo.ATime; break;
\r
195 case kpidMTime: prop = this->fiInfo.MTime; break;
\r
198 prop.Detach(value);
\r
202 STDMETHODIMP CArchiveOpenCallback::GetStream(const wchar_t * szName, IInStream ** inStream)
\r
204 if (! this->szSubArchiveName.IsEmpty())
\r
208 * inStream = nullptr;
\r
209 wxString szFileName = this->piInfo.fiInfo.fnFileName.GetPathWithSep() + szName;
\r
210 if (! this->fiInfo.Find(szFileName.c_str()) || fiInfo.IsDir())
\r
212 this->nErrorCode = TPI_ERROR_IO_ARC_OPEN;
\r
216 auto inFile = new CInFileStream;
\r
217 CMyComPtr<IInStream> inStreamTemp = inFile;
\r
218 if (! inFile->Open(szFileName.c_str()))
\r
220 this->nErrorCode = TPI_ERROR_IO_ARC_OPEN;
\r
223 * inStream = inStreamTemp.Detach();
\r
227 STDMETHODIMP CArchiveOpenCallback::SetSubArchiveName(const wchar_t * szName)
\r
229 this->szSubArchiveName = WC2String(szName);
\r
233 STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR * sz)
\r
235 this->piInfo.eMessage = TPI_MESSAGE_ASK;
\r
236 this->piInfo.eStatus = TPI_PARAM_PASSWORD;
\r
238 (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), sz) :
\r
242 // CArchiveExtractCallback
\r
243 class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp
\r
246 MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
\r
247 INTERFACE_IArchiveExtractCallback(;)
\r
248 STDMETHOD(CryptoGetTextPassword)(BSTR * szPassword);
\r
249 CArchiveExtractCallback(CMyComPtr<IInArchive>, TPI_SWITCHES *);
\r
252 TPI_SWITCHES * swInfo;
\r
253 wxFileName fnArchive;
\r
257 bool fTriedPassword;
\r
258 TPI_PROCESSINFO piInfo;
\r
259 wxULongLong_t nCurrentPos;
\r
260 COutFileStream * _outFileStreamSpec;
\r
261 CMyComPtr<ISequentialOutStream> _outFileStream;
\r
262 CMyComPtr<IInArchive> hArc;
\r
265 CArchiveExtractCallback::CArchiveExtractCallback(CMyComPtr<IInArchive> hArc, TPI_SWITCHES * swInfo)
\r
268 this->swInfo = swInfo;
\r
269 this->nCurrentPos = 0;
\r
270 this->fTriedPassword = false;
\r
273 STDMETHODIMP CArchiveExtractCallback::SetTotal(wxULongLong_t)
\r
278 STDMETHODIMP CArchiveExtractCallback::SetCompleted(const wxULongLong_t * nProcessed)
\r
280 this->piInfo.eStatus = TPI_STATUS_INPROCESS;
\r
281 this->piInfo.nProcessedSize = * nProcessed - this->nCurrentPos;
\r
282 if (g_prProc == nullptr || this->piInfo.fiInfo.szStoredName.IsEmpty() || ! this->piInfo.fnDestination.IsOk() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)
\r
288 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
293 STDMETHODIMP CArchiveExtractCallback::GetStream(unsigned int nIndex, ISequentialOutStream ** outStream, int nExtractMode)
\r
296 _outFileStream.Release();
\r
298 // 前のファイルの処理の終了を通知。
\r
299 this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;
\r
300 if (this->nCurrentPos != 0)
\r
302 this->piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
303 this->piInfo.eStatus = TPI_STATUS_ENDPROCESS;
\r
304 if (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
306 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
312 this->piInfo.eMessage = TPI_MESSAGE_ASK;
\r
313 this->piInfo.eStatus = TPI_PARAM_DEST;
\r
314 GetFileInformation2(this->hArc, & this->piInfo.fiInfo, nIndex);
\r
315 if (this->piInfo.fiInfo.szStoredName.IsEmpty())
\r
317 this->piInfo.fiInfo.szStoredName = this->fnArchive.GetName();
\r
318 if (this->piInfo.fiInfo.fnFileName.HasExt())
\r
320 this->piInfo.fiInfo.szStoredName += wxT('.') + this->piInfo.fiInfo.fnFileName.GetExt();
\r
322 this->piInfo.fiInfo.fnFileName = wxFileName(this->piInfo.fiInfo.szStoredName);
\r
325 this->piInfo.fnDestination = wxFileName(swInfo->fnDestinationDirectory.GetFullPath() + wxFileName::GetPathSeparator() + (swInfo->fStoreDirectoryPathes ? this->piInfo.fiInfo.fnFileName.GetPath() : (wxString) wxEmptyString), this->piInfo.fiInfo.fnFileName.GetFullName());
\r
326 if (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
328 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
331 if (! piInfo.fnDestination.IsOk())
\r
337 this->piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
338 this->piInfo.eStatus = TPI_STATUS_BEGINPROCESS;
\r
339 if (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
341 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
345 if (nExtractMode != NArchive::NExtract::NAskMode::kExtract)
\r
350 // ディレクトリかどうかを判定し、必要なディレクトリを作成。
\r
351 if (! ::wxFileName::Mkdir(this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? this->piInfo.fnDestination.GetFullPath() : this->piInfo.fnDestination.GetPath(), 0777, wxPATH_MKDIR_FULL))
\r
353 this->nErrorCode = TPI_ERROR_IO_DIR_OPEN;
\r
356 if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
362 _outFileStreamSpec = new COutFileStream;
\r
363 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
\r
364 if (! _outFileStreamSpec->Open(this->piInfo.fnDestination.GetFullPath(), CREATE_NEW))
\r
366 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;
\r
370 _outFileStream = outStreamLoc;
\r
371 * outStream = outStreamLoc.Detach();
\r
375 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(int nExtractMode)
\r
377 this->nMode = nExtractMode;
\r
381 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(int nResult)
\r
385 case NArchive::NExtract::NOperationResult::kOK: this->nErrorCode = TPI_ERROR_SUCCESS; break;
\r
386 case NArchive::NExtract::NOperationResult::kUnSupportedMethod: this->nErrorCode = TPI_ERROR_ARC_UNSUPPORTED; break;
\r
387 case NArchive::NExtract::NOperationResult::kDataError: this->nErrorCode = TPI_ERROR_ARC_BROKEN_MISC; break;
\r
388 case NArchive::NExtract::NOperationResult::kCRCError: this->nErrorCode = TPI_ERROR_ARC_BROKEN_SUM; break;
\r
389 default: this->nErrorCode = TPI_ERROR_UNDEFINED; break;
\r
393 if (_outFileStream != nullptr)
\r
395 FILETIME ftAccess, ftCreate, ftModify;
\r
396 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmAccess.GetTicks(), ftAccess);
\r
397 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmCreate.GetTicks(), ftCreate);
\r
398 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmModify.GetTicks(), ftModify);
\r
399 _outFileStreamSpec->SetTime(& ftCreate, & ftAccess, & ftModify);
\r
400 _outFileStreamSpec->Close();
\r
402 _outFileStream.Release();
\r
405 if (this->nMode == NArchive::NExtract::NAskMode::kExtract)
\r
407 chmod(this->piInfo.fnDestination.GetFullPath().ToUTF8(), this->piInfo.fiInfo.wPermission);
\r
409 NWindows::NFile::NDirectory::MySetFileAttributes(this->piInfo.fnDestination.GetFullPath(), this->piInfo.fiInfo.dwAttribute);
\r
416 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR * szPassword)
\r
418 if (this->fTriedPassword || this->swInfo->szPassword.IsEmpty())
\r
420 this->piInfo.eMessage = TPI_MESSAGE_ASK;
\r
421 this->piInfo.eStatus = TPI_PARAM_PASSWORD;
\r
422 // 次のファイル名が取得できないので、とりあえず空にしておく。
\r
423 this->piInfo.fiInfo.fnFileName.Clear();
\r
424 return (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;
\r
428 // 既定のパスワードがある場合はまずそれを試す。
\r
429 this->fTriedPassword = true;
\r
430 return ::StringToBstr(this->swInfo->szPassword, szPassword);
\r
434 // CArchiveUpdateCallback
\r
435 class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp
\r
438 MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
\r
439 INTERFACE_IArchiveUpdateCallback2(;)
\r
440 STDMETHOD(CryptoGetTextPassword2)(int * nPasswordIsDefined, BSTR * szPassword);
\r
441 CArchiveUpdateCallback(TPI_SWITCHES *, CObjectVector<NWindows::NFile::NFind::CFileInfo> *);
\r
443 const CObjectVector<NWindows::NFile::NFind::CFileInfo> * fiItems;
\r
447 wxULongLong_t nCurrentPos;
\r
448 TPI_PROCESSINFO piInfo;
\r
449 TPI_SWITCHES * swInfo;
\r
452 CArchiveUpdateCallback::CArchiveUpdateCallback(TPI_SWITCHES * swInfo, CObjectVector<NWindows::NFile::NFind::CFileInfo> * fiItems)
\r
454 this->swInfo = swInfo;
\r
455 this->fiItems = fiItems;
\r
458 STDMETHODIMP CArchiveUpdateCallback::SetTotal(wxULongLong_t)
\r
463 STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const wxULongLong_t * nProcessed)
\r
465 this->piInfo.eStatus = TPI_STATUS_INPROCESS;
\r
466 this->piInfo.nProcessedSize = * nProcessed - this->nCurrentPos;
\r
467 if (g_prProc == nullptr || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)
\r
473 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
478 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(unsigned int /* index */, int *newData, int *newProperties, unsigned int *indexInArchive)
\r
480 if (newData != nullptr)
\r
484 if (newProperties != nullptr)
\r
486 * newProperties = 1;
\r
488 if (indexInArchive != nullptr)
\r
490 * indexInArchive = (unsigned) -1;
\r
495 STDMETHODIMP CArchiveUpdateCallback::GetProperty(unsigned int nIndex, PROPID propID, PROPVARIANT * value)
\r
497 NWindows::NCOM::CPropVariant prop;
\r
498 if (propID == kpidIsAnti)
\r
501 prop.Detach(value);
\r
505 const NWindows::NFile::NFind::CFileInfo fiItem = (* this->fiItems)[nIndex];
\r
508 case kpidPath: prop = fiItem.Name; break;
\r
509 case kpidIsDir: prop = (unsigned int) fiItem.Attrib & TPI_ATTRIBUTE_DIRECTORY ? true : false; break;
\r
510 case kpidSize: prop = fiItem.Size; break;
\r
511 case kpidAttrib:prop = (unsigned int) fiItem.Attrib;break;
\r
512 case kpidCTime: prop = fiItem.CTime; break;
\r
513 case kpidATime: prop = fiItem.ATime; break;
\r
514 case kpidMTime: prop = fiItem.MTime; break;
\r
516 prop.Detach(value);
\r
520 STDMETHODIMP CArchiveUpdateCallback::GetStream(unsigned int nIndex, ISequentialInStream ** inStream)
\r
522 // 前のファイルの処理の終了を通知。
\r
523 this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;
\r
524 this->piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
525 if (this->nCurrentPos > 0)
\r
527 this->piInfo.eStatus = TPI_STATUS_ENDPROCESS;
\r
528 if (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
530 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
536 NWindows::NCOM::CPropVariant prop;
\r
537 this->GetProperty(nIndex, kpidAttrib, & prop);
\r
538 this->piInfo.fiInfo.dwAttribute = prop.uintVal;
\r
539 this->GetProperty(nIndex, kpidSize, & prop);
\r
540 this->piInfo.fiInfo.nUnpackedSize = prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;
\r
542 this->GetProperty(nIndex, kpidMTime, & prop); NWindows::NTime::FileTimeToUnixTime(prop.filetime, t); this->piInfo.fiInfo.tmModify.Set((time_t) t);
\r
543 this->GetProperty(nIndex, kpidCTime, & prop); NWindows::NTime::FileTimeToUnixTime(prop.filetime, t); this->piInfo.fiInfo.tmCreate.Set((time_t) t);
\r
544 this->GetProperty(nIndex, kpidATime, & prop); NWindows::NTime::FileTimeToUnixTime(prop.filetime, t); this->piInfo.fiInfo.tmAccess.Set((time_t) t);
\r
545 this->GetProperty(nIndex, kpidPath, & prop);
\r
546 this->piInfo.fiInfo.szStoredName = WC2String(prop.bstrVal);
\r
547 this->piInfo.fiInfo.nFileId = nIndex;
\r
548 this->piInfo.fiInfo.fnFileName = wxFileName(this->piInfo.fiInfo.szStoredName);
\r
549 this->piInfo.fiInfo.fnFileName.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, this->swInfo->fnDestinationDirectory.GetFullPath());
\r
550 this->piInfo.eStatus = TPI_STATUS_BEGINPROCESS;
\r
551 this->piInfo.fnDestination = wxFileName(this->piInfo.fiInfo.szStoredName);
\r
554 if (g_prProc != nullptr && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)
\r
556 this->nErrorCode = TPI_ERROR_D_SKIPPED;
\r
560 if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
565 auto inStreamSpec = new CInFileStream;
\r
566 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
\r
567 if (! inStreamSpec->Open(this->piInfo.fiInfo.fnFileName.GetFullPath().c_str()))
\r
569 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;
\r
573 * inStream = inStreamLoc.Detach();
\r
577 STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(int nResult)
\r
581 case NArchive::NUpdate::NOperationResult::kOK: this->nErrorCode = TPI_ERROR_SUCCESS; break;
\r
582 case NArchive::NUpdate::NOperationResult::kError:
\r
583 default: this->nErrorCode = TPI_ERROR_UNDEFINED; break;
\r
588 STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(unsigned int, wxULongLong_t * nSplitSize)
\r
590 * nSplitSize = this->swInfo->nSplitSize;
\r
594 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(unsigned int nIndex, ISequentialOutStream ** volumeStream)
\r
596 auto streamSpec = new COutFileStream;
\r
597 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
\r
598 if (! streamSpec->Create(this->piInfo.fiInfo.fnFileName.GetFullPath() + wxString::Format(wxT(".%03d"), nIndex + 1), false))
\r
600 return TPI_ERROR_IO_ARC_OPEN;
\r
602 * volumeStream = streamLoc.Detach();
\r
606 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(int * nPasswordIsDefined, BSTR * szPassword)
\r
608 * nPasswordIsDefined = ! this->swInfo->szPassword.IsEmpty();
\r
609 return ::StringToBstr(this->swInfo->szPassword.c_str(), szPassword);
\r
612 //******************************************************************************
\r
614 //******************************************************************************
\r
621 int __stdcall GetPluginInformation
\r
623 unsigned int _uInfoId,
\r
628 if (_pPtr == nullptr)
\r
630 return TPI_ERROR_D_PARAMETER;
\r
634 case TPI_INFO_VERSION_MAJOR:
\r
635 case TPI_INFO_VERSION_MINOR:
\r
636 * (int *) _pPtr = 0;
\r
638 case TPI_INFO_VERSION_API:
\r
639 * (int *) _pPtr = 2;
\r
641 case TPI_INFO_HANDLE_ON_COMMAND:
\r
642 * (int *) _pPtr = 1;
\r
645 return TPI_ERROR_D_UNSUPPORTED;
\r
647 return TPI_ERROR_SUCCESS;
\r
650 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)
\r
652 static wxULongLong_t s_nFileId;
\r
653 static wxXmlDocument xmlDoc(myMakeXMLName(wxT("7zArc")));
\r
654 static wxXmlNode * xmlLibrary;
\r
659 xmlLibrary = myGetFirstLib(& xmlDoc);
\r
663 xmlLibrary = myGetNextLib(xmlLibrary);
\r
665 if (xmlLibrary == nullptr)
\r
668 return TPI_ERROR_S_ENDOFDATA;
\r
670 MakeFormatInfo(xmlLibrary, wxT("7zArc"), _fiInfo, s_nFileId++);
\r
671 return TPI_ERROR_SUCCESS;
\r
674 int __stdcall LoadPlugin
\r
676 const wxString & _szArcName,
\r
678 wxULongLong_t _nTypeId
\r
681 ::RemoveCwdFromSearchPath();
\r
683 global_use_utf16_conversion = 1;
\r
685 g_LibInfo.hLib.Load(LIB_NAME, wxDL_QUIET);
\r
686 if (! g_LibInfo.hLib.IsLoaded())
\r
688 return TPI_ERROR_U_LOAD_LIBRARY;
\r
691 if (! g_LibInfo.hLib.HasSymbol(wxT("CreateObject")))
\r
693 return TPI_ERROR_U_USE_LIBRARY;
\r
695 g_LibInfo.fpProc = g_LibInfo.hLib.GetSymbol(wxT("CreateObject"));
\r
696 if (! g_LibInfo.fpProc)
\r
698 return TPI_ERROR_U_USE_LIBRARY;
\r
701 // 対象が存在しないならば指示されたライブラリをロード。
\r
703 if (_szArcName.IsEmpty())
\r
705 return TPI_ERROR_SUCCESS;
\r
707 if (! ::wxFileExists(_szArcName))
\r
710 wxXmlDocument xmlDoc(myMakeXMLName(wxT("7zArc")));
\r
711 wxXmlNode * xmlLibrary = myGetFirstLib(& xmlDoc, _nTypeId);
\r
712 if (xmlLibrary == nullptr)
\r
715 return TPI_ERROR_UNDEFINED;
\r
717 g_LibInfo.node = * xmlLibrary;
\r
718 g_LibInfo.nLibIndex = _nTypeId;
\r
722 if (_prProc != nullptr)
\r
724 g_prProc = * _prProc;
\r
726 return TPI_ERROR_SUCCESS;
\r
729 int __stdcall FreePlugin
\r
731 void * // _pReserved
\r
734 g_LibInfo.hLib.Unload();
\r
735 return TPI_ERROR_SUCCESS;
\r
738 int __stdcall OpenArchive
\r
740 const wxString & _szArcName,
\r
741 void * * _hArchive,
\r
742 wxULongLong_t * _nFileCount
\r
745 // *.tar.xxx, *.tgz, *.tbz2, *.txzは不便なので弾く。
\r
747 wxString s = _szArcName.BeforeLast(wxT('.')), t = _szArcName.AfterLast(wxT('.'));
\r
748 if ((s.Find(wxT('.')) != wxNOT_FOUND && s.AfterLast(wxT('.')) == wxT("tar")) || t == wxT("tgz") || t == wxT("tbz2") || t == wxT("txz"))
\r
750 return TPI_ERROR_IO_ARC_OPEN;
\r
756 wxXmlDocument xmlDoc(myMakeXMLName(wxT("7zArc")));
\r
757 wxXmlNode * xmlLibrary = myGetFirstLib(& xmlDoc);
\r
760 // 無限ループに陥らないよう上限を設定。
\r
761 for (g_LibInfo.nLibIndex = 0; g_LibInfo.nLibIndex < 300 && xmlLibrary != nullptr; g_LibInfo.nLibIndex++)
\r
764 const GUID guid = {0x23170F69, 0x40C1, 0x278A, {0x10, 0x00, 0x00, 0x01, 0x10, (unsigned char) myGetAttributeInt(xmlLibrary, wxT("name"), 0, 16), 0x00, 0x00}};
\r
765 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void * *)) g_LibInfo.fpProc)(& guid, & IID_IInArchive, (void **) & hArc) != S_OK)
\r
767 xmlLibrary = myGetNextLib(xmlLibrary);
\r
770 g_LibInfo.node = * xmlLibrary;
\r
773 auto fileSpec = new CInFileStream;
\r
774 CMyComPtr<IInStream> file = fileSpec;
\r
775 if (! fileSpec->Open(_szArcName.c_str()))
\r
777 return TPI_ERROR_IO_ARC_OPEN;
\r
781 TPI_FORMATINFO fiInfo;
\r
782 MakeFormatInfo(xmlLibrary, wxT("7zArc"), & fiInfo, g_LibInfo.nLibIndex);
\r
785 auto openCallbackSpec = new CArchiveOpenCallback;
\r
786 CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
\r
787 // SFXを完全に検出するには全体をロードする必要がある。
\r
788 wxULongLong_t nMax = fiInfo.fSFX ? 262114 : 1024;
\r
792 fileSpec->GetSize(& nMax);
\r
795 if (hArc->Open(file, & nMax, openCallback) == S_OK)
\r
797 if (_nFileCount != nullptr)
\r
800 hArc->GetNumberOfItems(& n);
\r
803 * _hArchive = hArc;
\r
804 return TPI_ERROR_SUCCESS;
\r
806 xmlLibrary = myGetNextLib(xmlLibrary);
\r
809 return TPI_ERROR_IO_ARC_OPEN;
\r
812 int __stdcall CloseArchive
\r
817 IInArchive * hArc = (IInArchive *) _hArchive;
\r
820 return TPI_ERROR_SUCCESS;
\r
823 int __stdcall GetFileInformation
\r
826 TPI_FILEINFO * _fiInfo,
\r
830 static unsigned int s_uFileId, s_uFileCount;
\r
834 ((IInArchive *) _hArchive)->GetNumberOfItems(& s_uFileCount);
\r
837 if (s_uFileId >= s_uFileCount)
\r
839 return TPI_ERROR_S_ENDOFDATA;
\r
842 return GetFileInformation2(_hArchive, _fiInfo, s_uFileId++);
\r
845 int __stdcall GetArchiveInformation
\r
848 TPI_ARCHIVEINFO * _aiInfo
\r
851 IInArchive * hArc = (IInArchive *) _hArchive;
\r
852 NWindows::NCOM::CPropVariant prop;
\r
853 hArc->GetArchiveProperty(kpidSolid, & prop);
\r
854 _aiInfo->fSolid = VARIANT_BOOLToBool(prop.boolVal);
\r
855 hArc->GetArchiveProperty(kpidComment, & prop);
\r
856 if (prop.vt == VT_BSTR)
\r
858 _aiInfo->szComment = WC2String(prop.bstrVal);
\r
863 hArc->GetArchiveProperty(kpidMTime, & prop);
\r
864 if (prop.vt == VT_FILETIME)
\r
866 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
867 _aiInfo->tmModify.Set((time_t) t);
\r
869 hArc->GetArchiveProperty(kpidCTime, & prop);
\r
870 if (prop.vt == VT_FILETIME)
\r
872 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
873 _aiInfo->tmCreate.Set((time_t) t);
\r
875 hArc->GetArchiveProperty(kpidATime, & prop);
\r
876 if (prop.vt == VT_FILETIME)
\r
878 NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);
\r
879 _aiInfo->tmAccess.Set((time_t) t);
\r
882 MakeFormatInfo(& g_LibInfo.node, wxT("7zArc"), & _aiInfo->fiInfo, g_LibInfo.nLibIndex);
\r
883 return TPI_ERROR_SUCCESS;
\r
886 int __stdcall Command
\r
888 wxULongLong_t _eCommand,
\r
889 TPI_SWITCHES * _swInfo,
\r
891 const wxArrayString & _szFiles
\r
898 case TPI_COMMAND_EXTRACT:
\r
899 case TPI_COMMAND_TEST:
\r
901 // ファイル名からインデックスを取得。
\r
902 TPI_FILEINFO fiInfo;
\r
903 CRecordVector<unsigned int> nIndexes;
\r
904 wxFileName fnArchive = wxFileName(_swInfo->szArcName);
\r
905 if (GetFileInformation(_hArchive, & fiInfo, true) == TPI_ERROR_SUCCESS)
\r
909 if (fiInfo.szStoredName.IsEmpty())
\r
911 fiInfo.szStoredName = fnArchive.GetName();
\r
912 if (fiInfo.fnFileName.HasExt())
\r
914 fiInfo.szStoredName += wxT('.') + fiInfo.fnFileName.GetExt();
\r
917 if (_szFiles.Index(fiInfo.szStoredName) != wxNOT_FOUND)
\r
919 nIndexes.Add(fiInfo.nFileId);
\r
922 while (GetFileInformation(_hArchive, & fiInfo) == TPI_ERROR_SUCCESS);
\r
925 auto extractCallbackSpec = new CArchiveExtractCallback((IInArchive *) _hArchive, _swInfo);
\r
926 extractCallbackSpec->fnArchive = fnArchive;
\r
927 CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
\r
928 ((IInArchive *) _hArchive)->Extract(& nIndexes.Front(), nIndexes.Size(), _eCommand == TPI_COMMAND_TEST, extractCallback);
\r
929 nErrorCode = extractCallbackSpec->nErrorCode;
\r
932 case TPI_COMMAND_CREATE:
\r
933 case TPI_COMMAND_ADD:
\r
936 CObjectVector<NWindows::NFile::NFind::CFileInfo> fiItems;
\r
937 for (unsigned int i = 0; i < _szFiles.GetCount(); i++)
\r
939 NWindows::NFile::NFind::CFileInfo fi;
\r
940 wxFileName fn(_szFiles[i]);
\r
941 fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, _swInfo->fnDestinationDirectory.GetFullPath());
\r
942 if (! fi.Find(fn.GetFullPath().c_str()))
\r
944 return TPI_ERROR_IO_FILE_ACCESS;
\r
949 auto outFileStreamSpec = new COutFileStream;
\r
950 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
\r
951 IOutArchive * hArc;
\r
952 if (_eCommand == TPI_COMMAND_CREATE)
\r
955 if (! outFileStreamSpec->Create(_swInfo->szArcName.c_str(), false))
\r
957 return TPI_ERROR_IO_ARC_OPEN;
\r
961 const GUID guid = {0x23170F69, 0x40C1, 0x278A, {0x10, 0x00, 0x00, 0x01, 0x10, (unsigned char) myGetAttributeInt(& g_LibInfo.node, wxT("name"), 0, 16), 0x00, 0x00}};
\r
962 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void **)) g_LibInfo.fpProc)(& guid, & IID_IOutArchive, (void **) & hArc) != S_OK)
\r
964 return TPI_ERROR_ARC_UNSUPPORTED;
\r
970 if (! outFileStreamSpec->Open(_swInfo->szArcName.c_str(), OPEN_EXISTING))
\r
972 return TPI_ERROR_IO_ARC_OPEN;
\r
975 // IOutArchiveインタフェースを取得。
\r
976 if (((IInArchive *) _hArchive)->QueryInterface(IID_IOutArchive, (void **) & hArc) != S_OK)
\r
978 return TPI_ERROR_ARC_UNSUPPORTED;
\r
983 TPI_FORMATINFO fiInfo;
\r
984 MakeFormatInfo(& g_LibInfo.node, wxT("7zArc"), & fiInfo, g_LibInfo.nLibIndex);
\r
987 ISetProperties * setProp;
\r
988 if (hArc->QueryInterface(IID_ISetProperties, (void **) & setProp) == S_OK)
\r
990 CRecordVector<const wchar_t *> szProps;
\r
991 NWindows::NCOM::CPropVariant propValues[15];
\r
994 if (fiInfo.nCompressLevelMin != fiInfo.nCompressLevelMax)
\r
996 szProp = wxString::Format(wxT("x%d"), _swInfo->nCompressLevel);
\r
997 szProps.Add(szProp.c_str());
\r
1000 if (fiInfo.fSolid)
\r
1002 propValues[szProps.Size()] = _swInfo->fSolid;
\r
1003 szProps.Add(wxT("s"));
\r
1006 if (fiInfo.fCompressHeader)
\r
1008 propValues[szProps.Size()] = _swInfo->fCompressHeader;
\r
1009 szProps.Add(wxT("hc"));
\r
1012 if (fiInfo.fEncryptHeader)
\r
1014 propValues[szProps.Size()] = _swInfo->fEncryptHeader;
\r
1015 szProps.Add(wxT("he"));
\r
1018 // szProp = wxString::Format(wxT("m"));
\r
1019 // propValues[szProps.Size()] = L"Deflate";
\r
1020 // szProps.Add(szProp.c_str());
\r
1022 // szProp = wxString::Format(wxT("fb%d"), );
\r
1023 // szProps.Add(szProp.c_str());
\r
1025 setProp->SetProperties(& szProps.Front(), propValues, szProps.Size());
\r
1029 auto updateCallbackSpec = new CArchiveUpdateCallback(_swInfo, & fiItems);
\r
1030 CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
\r
1031 hArc->UpdateItems(outFileStream, fiItems.Size(), updateCallback);
\r
1032 nErrorCode = updateCallbackSpec->nErrorCode;
\r
1036 nErrorCode = TPI_ERROR_D_UNSUPPORTED;
\r
1038 return nErrorCode;
\r
1041 #ifdef __cplusplus
\r