OSDN Git Service

Fixed some warning on msvc.
[tpi/lychee.git] / src / plugin / 7zArc / 7zArc.cpp
1 /*******************************************************************************\r
2   TPI - flexible but useless plug-in framework.\r
3   Copyright (C) 2002-2009 Silky\r
4 \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
8   any later version.\r
9 \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
13   for more details.\r
14 \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
18 \r
19   $Id$\r
20 *******************************************************************************/\r
21 \r
22 //******************************************************************************\r
23 //    Includes\r
24 //******************************************************************************\r
25 \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
31 #include "7zArc.h"\r
32 \r
33 //******************************************************************************\r
34 //    Global varients\r
35 //******************************************************************************\r
36 \r
37 wxDynamicLibrary g_hLib;\r
38 void * g_fpProc;\r
39 TPI_PROC g_prProc;\r
40 wxULongLong g_llEngineId;\r
41 \r
42 //******************************************************************************\r
43 //    Inside Functions\r
44 //******************************************************************************\r
45 \r
46 int GetFileInformation2(void * _hArchive, TPI_FILEINFO * _fiInfo, unsigned int nIndex)\r
47 {\r
48         IInArchive * hArc = (IInArchive *) _hArchive;\r
49 \r
50         NWindows::NCOM::CPropVariant prop;\r
51         hArc->GetProperty(nIndex, kpidAttrib, & prop);\r
52         _fiInfo->dwAttribute    = prop.vt == VT_EMPTY ? 0 : prop.uintVal;\r
53         hArc->GetProperty(nIndex, kpidEncrypted, & prop);\r
54         if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))\r
55         {\r
56                 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
57         }\r
58         hArc->GetProperty(nIndex, kpidIsDir, & prop);\r
59         if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))\r
60         {\r
61                 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_DIRECTORY;\r
62         }\r
63         hArc->GetProperty(nIndex, kpidCRC, & prop);\r
64         _fiInfo->dwCRC32        = prop.ulVal;\r
65         hArc->GetProperty(nIndex, kpidPackSize, & prop);\r
66         _fiInfo->llPackedSize   = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
67         hArc->GetProperty(nIndex, kpidSize, & prop);\r
68         _fiInfo->llUnpackedSize = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
69         unsigned int t;\r
70         hArc->GetProperty(nIndex, kpidMTime, & prop);\r
71         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
72         _fiInfo->tmModified.Set((time_t) t);\r
73         hArc->GetProperty(nIndex, kpidCTime, & prop);\r
74         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
75         _fiInfo->tmCreate.Set((time_t) t);\r
76         hArc->GetProperty(nIndex, kpidATime, & prop);\r
77         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
78         _fiInfo->tmAccess.Set((time_t) t);\r
79 //      _fiInfo->uOSType        = hdInfo.HostOS;\r
80         hArc->GetProperty(nIndex, kpidPath, & prop);\r
81         if (prop.vt == VT_BSTR)\r
82         {\r
83                 _fiInfo->szStoredName = WC2String(prop.bstrVal);\r
84         }\r
85         else\r
86         {\r
87                 hArc->GetProperty(nIndex, kpidExtension, & prop);\r
88                 _fiInfo->szStoredName = wxT("data.") + WC2String(prop.bstrVal);\r
89         }\r
90         hArc->GetProperty(nIndex, kpidMethod, & prop);\r
91         if (prop.vt == VT_BSTR)\r
92         {\r
93                 _fiInfo->szMethod = WC2String(prop.bstrVal);\r
94         }\r
95         hArc->GetProperty(nIndex, kpidCommented, & prop);\r
96         if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))\r
97         {\r
98                 hArc->GetProperty(nIndex, kpidComment, & prop);\r
99                 _fiInfo->szComment  = WC2String(prop.bstrVal);\r
100         }\r
101         _fiInfo->llFileId       = nIndex;\r
102         _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName, wxPATH_DOS);\r
103         return TPI_ERROR_SUCCESS;\r
104 }\r
105 \r
106 int __stdcall GetFormatInformation2(TPI_FORMATINFO * _fiInfo, unsigned int & nIndex)\r
107 {\r
108         _fiInfo->szEngineName = g_hLib.CanonicalizeName(wxT("7z"));\r
109         _fiInfo->szTPIName    = wxT("7zArc");\r
110         _fiInfo->llSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;\r
111         _fiInfo->llTypeId     = nIndex;\r
112         _fiInfo->fArchive     = true;\r
113         switch (nIndex++)\r
114         {\r
115         case 0:\r
116                 _fiInfo->szTypeName   = wxT("7-zip");\r
117                 _fiInfo->szSuffix     = wxT("zip");\r
118                 _fiInfo->llSupportedCommand |= TPI_COMMAND_CREATE | TPI_COMMAND_ADD;\r
119                 _fiInfo->fSFX         = true;\r
120                 _fiInfo->fEncryptPassword = true;\r
121                 _fiInfo->sCompressLevelMin = 0;\r
122                 _fiInfo->sCompressLevelMax = 9;\r
123                 break;\r
124 #ifdef __LINUX__\r
125         case 1: _fiInfo->szTypeName = wxT("Arj");   _fiInfo->szSuffix = wxT("arj"); _fiInfo->fEncryptPassword = true; break;\r
126         case 2: _fiInfo->szTypeName = wxT("Lzh");   _fiInfo->szSuffix = wxT("lzh;lha;lzs"); break;\r
127 #endif\r
128         case 3:\r
129                 _fiInfo->szTypeName   = wxT("7z");\r
130                 _fiInfo->szSuffix     = wxT("7z");\r
131                 _fiInfo->llSupportedCommand |= TPI_COMMAND_CREATE | TPI_COMMAND_ADD;\r
132                 _fiInfo->fSFX         = true;\r
133                 _fiInfo->fSolid       = true;\r
134                 _fiInfo->fEncryptPassword = true;\r
135                 _fiInfo->fEncryptHeader=true;\r
136                 _fiInfo->fMultiVolume = true;\r
137                 _fiInfo->sCompressLevelMin = 0;\r
138                 _fiInfo->sCompressLevelMax = 9;\r
139                 break;\r
140 #ifdef __LINUX__\r
141         case 4: _fiInfo->szTypeName = wxT("Cab");   _fiInfo->szSuffix = wxT("cab"); _fiInfo->fMultiVolume = true; break;\r
142 #endif\r
143         case 5: _fiInfo->szTypeName = wxT("NSIS");  _fiInfo->szSuffix = wxT("exe"); break;\r
144         case 6: _fiInfo->szTypeName = wxT("MSLZ");  _fiInfo->szSuffix = wxT("xx_"); _fiInfo->fArchive = false; break;\r
145         case 7: _fiInfo->szTypeName = wxT("Flv");   _fiInfo->szSuffix = wxT("flv"); break;\r
146         case 8: _fiInfo->szTypeName = wxT("Swf");   _fiInfo->szSuffix = wxT("swf"); break;\r
147         case 9: _fiInfo->szTypeName = wxT("Swfc");  _fiInfo->szSuffix = wxT("swfc");break;\r
148         case 10:_fiInfo->szTypeName = wxT("Udf");   _fiInfo->szSuffix = wxT("udf"); break;\r
149         case 11:_fiInfo->szTypeName = wxT("HFS");   _fiInfo->szSuffix = wxT("hfs"); break;\r
150         case 12:_fiInfo->szTypeName = wxT("DMG");   _fiInfo->szSuffix = wxT("dmg"); break;\r
151         case 13:_fiInfo->szTypeName = wxT("ISO");   _fiInfo->szSuffix = wxT("iso"); break;\r
152         case 14:_fiInfo->szTypeName = wxT("Chm");   _fiInfo->szSuffix = wxT("chm"); break;\r
153 #ifdef __LINUX__\r
154         case 15:_fiInfo->szTypeName = wxT("RPM");   _fiInfo->szSuffix = wxT("rpm"); _fiInfo->fArchive = false; break;\r
155         case 16:_fiInfo->szTypeName = wxT("Deb");   _fiInfo->szSuffix = wxT("deb"); break;\r
156         case 17:_fiInfo->szTypeName = wxT("Cpio");  _fiInfo->szSuffix = wxT("cpio");break;\r
157         case 18:\r
158                 _fiInfo->szTypeName   = wxT("TAR");\r
159                 _fiInfo->szSuffix     = wxT("tar");\r
160                 _fiInfo->llSupportedCommand |= TPI_COMMAND_CREATE | TPI_COMMAND_ADD;\r
161                 break;\r
162 #endif\r
163         default:\r
164                 return nIndex > 18 ? TPI_ERROR_S_ENDOFDATA : GetFormatInformation2(_fiInfo, nIndex);\r
165         }\r
166         return TPI_ERROR_SUCCESS;\r
167 }\r
168 \r
169 //******************************************************************************\r
170 //    Callback Wrapper\r
171 //******************************************************************************\r
172 \r
173 // CArchiveOpenCallback\r
174 class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp\r
175 {\r
176 public:\r
177         MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
178         STDMETHOD(SetTotal)(const wxULongLong_t *, const wxULongLong_t *);\r
179         STDMETHOD(SetCompleted)(const wxULongLong_t *, const wxULongLong_t *);\r
180         STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
181         int nErrorCode;\r
182 \r
183 private:\r
184         TPI_PROCESSINFO piInfo;\r
185 };\r
186 \r
187 STDMETHODIMP CArchiveOpenCallback::SetTotal(const wxULongLong_t *, const wxULongLong_t *)\r
188 {\r
189         return S_OK;\r
190 }\r
191 \r
192 STDMETHODIMP CArchiveOpenCallback::SetCompleted(const wxULongLong_t *, const wxULongLong_t *)\r
193 {\r
194         return S_OK;\r
195 }\r
196 \r
197 STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR * szPassword)\r
198 {\r
199         this->piInfo.uMessage           = TPI_MESSAGE_ASK;\r
200         this->piInfo.uStatus            = TPI_PARAM_PASSWORD;\r
201         return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;\r
202 }\r
203 \r
204 // CArchiveExtractCallback\r
205 class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp\r
206 {\r
207 public:\r
208         MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
209         STDMETHOD(SetTotal)(wxULongLong_t size);\r
210         STDMETHOD(SetCompleted)(const wxULongLong_t *completeValue);\r
211         STDMETHOD(GetStream)(unsigned int nIndex, ISequentialOutStream ** outStream, int nExtractMode);\r
212         STDMETHOD(PrepareOperation)(int nExtractMode);\r
213         STDMETHOD(SetOperationResult)(int nErrorCode);\r
214         STDMETHOD(CryptoGetTextPassword)(BSTR * szPassword);\r
215 \r
216         int nErrorCode;\r
217         CMyComPtr<IInArchive> hArc;\r
218         TPI_SWITCHES * swInfo;\r
219 \r
220 private:\r
221         int nMode;\r
222         bool fTriedPassword;\r
223         TPI_PROCESSINFO piInfo;\r
224         wxULongLong llCurrentPos;\r
225         COutFileStream * _outFileStreamSpec;\r
226         CMyComPtr<ISequentialOutStream> _outFileStream;\r
227 };\r
228 \r
229 STDMETHODIMP CArchiveExtractCallback::SetTotal(wxULongLong_t)\r
230 {\r
231         return S_OK;\r
232 }\r
233 \r
234 STDMETHODIMP CArchiveExtractCallback::SetCompleted(const wxULongLong_t * llProcessed)\r
235 {\r
236         this->piInfo.uStatus                = TPI_STATUS_INPROCESS;\r
237         this->piInfo.llProcessedSize    = * llProcessed - this->llCurrentPos;\r
238         if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)\r
239         {\r
240                 return S_OK;\r
241         }\r
242         else\r
243         {\r
244                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
245                 return E_ABORT;\r
246         }\r
247 }\r
248 \r
249 STDMETHODIMP CArchiveExtractCallback::GetStream(unsigned int nIndex, ISequentialOutStream ** outStream, int nExtractMode)\r
250 {\r
251         * outStream = 0;\r
252         _outFileStream.Release();\r
253 \r
254         // 現在位置を記録。\r
255         this->llCurrentPos += this->piInfo.fiInfo.llUnpackedSize;\r
256 \r
257         // ファイルの基本情報を取得。\r
258         this->piInfo.uMessage               = TPI_MESSAGE_STATUS;\r
259         this->piInfo.uStatus                = TPI_STATUS_BEGINPROCESS;\r
260         GetFileInformation2(this->hArc, & this->piInfo.fiInfo, nIndex);\r
261         this->piInfo.fnDestination          = wxFileName(swInfo->fnDestinationDirectory.GetFullPath() + wxFileName::GetPathSeparator() + (swInfo->fStoreDirectoryPathes ? this->piInfo.fiInfo.fnFileName.GetPath() : (wxString) wxEmptyString), this->piInfo.fiInfo.fnFileName.GetFullName());\r
262 \r
263         // コールバック関数に送信。\r
264         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
265         {\r
266                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
267                 return E_ABORT;\r
268         }\r
269 \r
270         if (nExtractMode != NArchive::NExtract::NAskMode::kExtract)\r
271         {\r
272                 return S_OK;\r
273         }\r
274 \r
275         // ディレクトリかどうかを判定し、必要なディレクトリを作成。\r
276         if (! ::wxFileName::Mkdir(this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? this->piInfo.fnDestination.GetFullPath() : this->piInfo.fnDestination.GetPath(), 0777, wxPATH_MKDIR_FULL))\r
277         {\r
278                 this->nErrorCode = TPI_ERROR_IO_DIR_OPEN;\r
279                 return E_ABORT;\r
280         }\r
281         if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
282         {\r
283                 return S_OK;\r
284         }\r
285 \r
286         if (::wxFileExists(this->piInfo.fnDestination.GetFullPath()))\r
287         {\r
288                 // 既にファイルが存在する場合。\r
289                 if (! ::wxRemoveFile(this->piInfo.fnDestination.GetFullPath()))\r
290                 {\r
291                         this->nErrorCode = TPI_ERROR_IO_FILE_DELETE;\r
292                         return E_ABORT;\r
293                 }\r
294         }\r
295 \r
296         _outFileStreamSpec = new COutFileStream;\r
297         CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\r
298         if (! _outFileStreamSpec->Open(this->piInfo.fnDestination.GetFullPath(), CREATE_ALWAYS))\r
299         {\r
300                 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;\r
301                 return E_ABORT;\r
302         }\r
303 \r
304         _outFileStream = outStreamLoc;\r
305         * outStream = outStreamLoc.Detach();\r
306         return S_OK;\r
307 }\r
308 \r
309 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(int nExtractMode)\r
310 {\r
311         this->nMode = nExtractMode;\r
312         return S_OK;\r
313 }\r
314 \r
315 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(int nResult)\r
316 {\r
317         switch (nResult)\r
318         {\r
319         case NArchive::NExtract::NOperationResult::kOK:                this->nErrorCode = TPI_ERROR_SUCCESS;         break;\r
320         case NArchive::NExtract::NOperationResult::kUnSupportedMethod: this->nErrorCode = TPI_ERROR_ARC_UNSUPPORTED; break;\r
321         case NArchive::NExtract::NOperationResult::kDataError:         this->nErrorCode = TPI_ERROR_ARC_BROKEN_MISC; break;\r
322         case NArchive::NExtract::NOperationResult::kCRCError:          this->nErrorCode = TPI_ERROR_ARC_BROKEN_SUM;  break;\r
323         default:                                                       this->nErrorCode = TPI_ERROR_UNDEFINED;       break;\r
324         }\r
325 \r
326         // 更新時刻を記録。\r
327         if (_outFileStream != NULL)\r
328         {\r
329                 FILETIME ft;\r
330                 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmModified.GetTicks(), ft);\r
331                 _outFileStreamSpec->SetMTime(& ft);\r
332                 _outFileStreamSpec->Close();\r
333         }\r
334         _outFileStream.Release();\r
335 \r
336         // 属性を記録。\r
337         if (this->nMode == NArchive::NExtract::NAskMode::kExtract)\r
338         {\r
339 //              NWindows::NFile::NDirectory::MySetFileAttributes(this->piInfo.fiInfo.fnFileName.GetFullPath(), this->piInfo.fiInfo.dwAttribute);\r
340         }\r
341 \r
342         return S_OK;\r
343 }\r
344 \r
345 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR * szPassword)\r
346 {\r
347         if (this->fTriedPassword || this->swInfo->szPassword.IsEmpty())\r
348         {\r
349                 this->piInfo.uMessage           = TPI_MESSAGE_ASK;\r
350                 this->piInfo.uStatus            = TPI_PARAM_PASSWORD;\r
351                 return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;\r
352         }\r
353         else\r
354         {\r
355                 // 既定のパスワードがある場合はまずそれを試す。\r
356                 this->fTriedPassword = true;\r
357                 return ::StringToBstr(this->swInfo->szPassword, szPassword);\r
358         }\r
359 }\r
360 \r
361 // CArchiveUpdateCallback\r
362 class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp\r
363 {\r
364 public:\r
365         MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)\r
366         STDMETHOD(SetTotal)(wxULongLong_t size);\r
367         STDMETHOD(SetCompleted)(const wxULongLong_t * completeValue);\r
368         STDMETHOD(EnumProperties)(IEnumSTATPROPSTG ** enumerator);\r
369         STDMETHOD(GetUpdateItemInfo)(unsigned int nIndex, int * newData, int * newProperties, unsigned int * indexInArchive);\r
370         STDMETHOD(GetProperty)(unsigned int nIndex, PROPID propID, PROPVARIANT * value);\r
371         STDMETHOD(GetStream)(unsigned int index, ISequentialInStream ** inStream);\r
372         STDMETHOD(SetOperationResult)(int operationResult);\r
373         STDMETHOD(GetVolumeSize)(unsigned int nIndex, wxULongLong_t * size);\r
374         STDMETHOD(GetVolumeStream)(unsigned int nIndex, ISequentialOutStream ** volumeStream);\r
375         STDMETHOD(CryptoGetTextPassword2)(int * nPasswordIsDefined, BSTR * szPassword);\r
376         CArchiveUpdateCallback(): fiItems(0) {};\r
377 \r
378         CRecordVector<wxULongLong_t> VolumesSizes;\r
379         wxString szVolumeName;\r
380         wxString szVolumeExtension;\r
381         const CObjectVector<NWindows::NFile::NFind::CFileInfoW> * fiItems;\r
382         int nErrorCode;\r
383         TPI_SWITCHES * swInfo;\r
384 \r
385 private:\r
386         wxULongLong llCurrentPos;\r
387         TPI_PROCESSINFO piInfo;\r
388 };\r
389 \r
390 STDMETHODIMP CArchiveUpdateCallback::SetTotal(wxULongLong_t)\r
391 {\r
392         return S_OK;\r
393 }\r
394 \r
395 STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const wxULongLong_t * llProcessed)\r
396 {\r
397         this->piInfo.uStatus            = TPI_STATUS_INPROCESS;\r
398         this->piInfo.llProcessedSize    = * llProcessed - this->llCurrentPos;\r
399         if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)\r
400         {\r
401                 return S_OK;\r
402         }\r
403         else\r
404         {\r
405                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
406                 return E_ABORT;\r
407         }\r
408 }\r
409 \r
410 STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)\r
411 {\r
412         return E_NOTIMPL;\r
413 }\r
414 \r
415 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(unsigned int /* index */, int *newData, int *newProperties, unsigned int *indexInArchive)\r
416 {\r
417         if (newData != NULL)\r
418         {\r
419                 * newData = BoolToInt(true);\r
420         }\r
421         if (newProperties != NULL)\r
422         {\r
423                 * newProperties = BoolToInt(true);\r
424         }\r
425         if (indexInArchive != NULL)\r
426         {\r
427                 *indexInArchive = (unsigned int)-1;\r
428         }\r
429         return S_OK;\r
430 }\r
431 \r
432 STDMETHODIMP CArchiveUpdateCallback::GetProperty(unsigned int nIndex, PROPID propID, PROPVARIANT * value)\r
433 {\r
434         NWindows::NCOM::CPropVariant prop;\r
435         if (propID == kpidIsAnti)\r
436         {\r
437                 prop = false;\r
438                 prop.Detach(value);\r
439                 return S_OK;\r
440         }\r
441 \r
442         const NWindows::NFile::NFind::CFileInfoW fiItem = (* this->fiItems)[nIndex];\r
443         switch (propID)\r
444         {\r
445                 case kpidPath:  prop = fiItem.Name;  break;\r
446                 case kpidIsDir: prop = (unsigned int) fiItem.Attrib & TPI_ATTRIBUTE_DIRECTORY ? true : false; break;\r
447                 case kpidSize:  prop = fiItem.Size;  break;\r
448                 case kpidAttrib:prop = (unsigned int) fiItem.Attrib;break;\r
449                 case kpidCTime: prop = fiItem.CTime; break;\r
450                 case kpidATime: prop = fiItem.ATime; break;\r
451                 case kpidMTime: prop = fiItem.MTime; break;\r
452         }\r
453         prop.Detach(value);\r
454         return S_OK;\r
455 }\r
456 \r
457 STDMETHODIMP CArchiveUpdateCallback::GetStream(unsigned int nIndex, ISequentialInStream ** inStream)\r
458 {\r
459         // 現在位置を記録。\r
460         this->llCurrentPos += this->piInfo.fiInfo.llUnpackedSize;\r
461 \r
462         // ファイルの基本情報を取得。\r
463         NWindows::NCOM::CPropVariant prop;\r
464         this->GetProperty(nIndex, kpidAttrib, & prop);\r
465         this->piInfo.fiInfo.dwAttribute    = prop.uintVal;\r
466         this->GetProperty(nIndex, kpidSize, & prop);\r
467         this->piInfo.fiInfo.llUnpackedSize = prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
468         unsigned int t;\r
469         this->GetProperty(nIndex, kpidMTime, & prop);\r
470         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
471         this->piInfo.fiInfo.tmModified.Set((time_t) t);\r
472         this->GetProperty(nIndex, kpidCTime, & prop);\r
473         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
474         this->piInfo.fiInfo.tmCreate.Set((time_t) t);\r
475         this->GetProperty(nIndex, kpidATime, & prop);\r
476         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
477         this->piInfo.fiInfo.tmAccess.Set((time_t) t);\r
478         this->GetProperty(nIndex, kpidPath, & prop);\r
479         this->piInfo.fiInfo.szStoredName = WC2String(prop.bstrVal);\r
480         this->piInfo.fiInfo.llFileId       = nIndex;\r
481         this->piInfo.fiInfo.fnFileName     = wxFileName(this->piInfo.fiInfo.szStoredName);\r
482         this->piInfo.fiInfo.fnFileName.Normalize(wxPATH_NORM_ALL, this->swInfo->fnDestinationDirectory.GetFullPath());\r
483         this->piInfo.uMessage               = TPI_MESSAGE_STATUS;\r
484         this->piInfo.uStatus                = TPI_STATUS_BEGINPROCESS;\r
485         this->piInfo.fnDestination          = wxFileName(this->piInfo.fiInfo.szStoredName);\r
486 \r
487         // コールバック関数に送信。\r
488         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
489         {\r
490                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
491                 return E_ABORT;\r
492         }\r
493 \r
494         if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
495         {\r
496                 return S_OK;\r
497         }\r
498 \r
499         CInFileStream * inStreamSpec = new CInFileStream;\r
500         CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
501         if (! inStreamSpec->Open(this->piInfo.fiInfo.fnFileName.GetFullPath().c_str()))\r
502         {\r
503                 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;\r
504                 return S_FALSE;\r
505         }\r
506 \r
507         * inStream = inStreamLoc.Detach();\r
508         return S_OK;\r
509 }\r
510 \r
511 STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(int nResult)\r
512 {\r
513         switch (nResult)\r
514         {\r
515         case NArchive::NUpdate::NOperationResult::kOK:                 this->nErrorCode = TPI_ERROR_SUCCESS;         break;\r
516         case NArchive::NUpdate::NOperationResult::kError:\r
517         default:                                                       this->nErrorCode = TPI_ERROR_UNDEFINED;       break;\r
518         }\r
519         return S_OK;\r
520 }\r
521 \r
522 STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(unsigned int index, wxULongLong_t *size)\r
523 {\r
524         if (VolumesSizes.Size() == 0)\r
525         {\r
526                 return S_FALSE;\r
527         }\r
528         if (index >= (unsigned int)VolumesSizes.Size())\r
529         {\r
530                 index = VolumesSizes.Size() - 1;\r
531         }\r
532 \r
533         * size = VolumesSizes[index];\r
534         return S_OK;\r
535 }\r
536 \r
537 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(unsigned int nIndex, ISequentialOutStream ** volumeStream)\r
538 {\r
539         COutFileStream * streamSpec = new COutFileStream;\r
540         CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);\r
541         if (! streamSpec->Create(szVolumeName + wxString::Format(wxT(".%03d"), nIndex + 1) + szVolumeExtension, false))\r
542         {\r
543                 return TPI_ERROR_IO_ARC_OPEN;\r
544         }\r
545         * volumeStream = streamLoc.Detach();\r
546         return S_OK;\r
547 }\r
548 \r
549 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(int * nPasswordIsDefined, BSTR * szPassword)\r
550 {\r
551         * nPasswordIsDefined = ! this->swInfo->szPassword.IsEmpty();\r
552         return ::StringToBstr(this->swInfo->szPassword.c_str(), szPassword);\r
553 }\r
554 \r
555 //******************************************************************************\r
556 //    Functions\r
557 //******************************************************************************\r
558 \r
559 #ifdef __cplusplus\r
560 extern "C"\r
561 {\r
562 #endif\r
563 \r
564 int __stdcall GetPluginInformation\r
565 (\r
566         unsigned int _uInfoId,\r
567         wxULongLong,\r
568         void * _pPtr\r
569 )\r
570 {\r
571         if (_pPtr == NULL)\r
572         {\r
573                 return TPI_ERROR_D_PARAMETER;\r
574         }\r
575         switch (_uInfoId)\r
576         {\r
577         case TPI_INFO_VERSION_MAJOR:\r
578         case TPI_INFO_VERSION_MINOR:\r
579                 * (int *) _pPtr = 0;\r
580                 break;\r
581         case TPI_INFO_VERSION_API:\r
582                 * (int *) _pPtr = 2;\r
583                 break;\r
584         default:\r
585                 return TPI_ERROR_D_UNSUPPORTED;\r
586         }\r
587         return TPI_ERROR_SUCCESS;\r
588 }\r
589 \r
590 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
591 {\r
592         static unsigned int s_uTypeId;\r
593         if (_bFirst)\r
594         {\r
595                 s_uTypeId = 0;\r
596         }\r
597         return GetFormatInformation2(_fiInfo, s_uTypeId);\r
598 }\r
599 \r
600 int __stdcall LoadPlugin\r
601 (\r
602         const wxString & _szArcName,\r
603         wxULongLong _llTypeId\r
604 )\r
605 {\r
606         g_hLib.Load(g_hLib.CanonicalizeName(wxT("7z")));\r
607         if (! g_hLib.IsLoaded())\r
608         {\r
609                 g_hLib.Unload();\r
610                 return TPI_ERROR_U_LOAD_LIBRARY;\r
611         }\r
612 \r
613         if (! g_hLib.HasSymbol(wxT("CreateObject")))\r
614         {\r
615                 return TPI_ERROR_U_USE_LIBRARY;\r
616         }\r
617         g_fpProc = g_hLib.GetSymbol(wxT("CreateObject"));\r
618         if (! g_fpProc)\r
619         {\r
620                 return TPI_ERROR_U_USE_LIBRARY;\r
621         }\r
622 \r
623         if (! ::wxFileExists(_szArcName))\r
624         {\r
625                 g_llEngineId = _llTypeId;\r
626         }\r
627 \r
628         return TPI_ERROR_SUCCESS;\r
629 }\r
630 \r
631 int __stdcall FreePlugin\r
632 (\r
633         void * // _pReserved\r
634 )\r
635 {\r
636         g_hLib.Unload();\r
637         return TPI_ERROR_SUCCESS;\r
638 }\r
639 \r
640 int __stdcall CheckArchive\r
641 (\r
642         const wxString & _szArcName,\r
643         wxULongLong * _llFileCount\r
644 )\r
645 {\r
646         void * _hArchive;\r
647         int nErrorCode = OpenArchive(_szArcName, & _hArchive);\r
648         if (nErrorCode != TPI_ERROR_SUCCESS)\r
649         {\r
650                 return nErrorCode;\r
651         }\r
652 \r
653         if (_llFileCount != NULL)\r
654         {\r
655                 unsigned int nFileCount = 0;\r
656                 ((IInArchive *) _hArchive)->GetNumberOfItems(& nFileCount);\r
657                 * _llFileCount = nFileCount;\r
658         }\r
659 \r
660         return CloseArchive(_hArchive);\r
661 }\r
662 \r
663 int __stdcall OpenArchive\r
664 (\r
665         const wxString & _szArcName,\r
666         void * * _hArchive\r
667 )\r
668 {\r
669         // 書庫形式を認識。\r
670         IInArchive * hArc;\r
671         for (unsigned int i = 0; i < sizeof(guidList) / sizeof(GUID); i++)\r
672         {\r
673                 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void * *)) g_fpProc)(& guidList[i], & IID_IInArchive, (void **) & hArc) != S_OK)\r
674                 {\r
675                         continue;\r
676                 }\r
677 \r
678                 // 書庫を開く。\r
679                 CInFileStream * fileSpec = new CInFileStream;\r
680                 CMyComPtr<IInStream> file = fileSpec;\r
681                 if (! fileSpec->Open(_szArcName.c_str()))\r
682                 {\r
683                         return TPI_ERROR_IO_ARC_OPEN;\r
684                 }\r
685 \r
686                 // 書庫として開く。\r
687                 CArchiveOpenCallback * openCallbackSpec = new CArchiveOpenCallback;\r
688                 CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);\r
689                 if (hArc->Open(file, 0, openCallback) == S_OK)\r
690                 {\r
691                         g_llEngineId = i;\r
692                         * _hArchive = hArc;\r
693                         return TPI_ERROR_SUCCESS;\r
694                 }\r
695         }\r
696         return TPI_ERROR_IO_ARC_OPEN;\r
697 }\r
698 \r
699 int __stdcall CloseArchive\r
700 (\r
701         void * _hArchive\r
702 )\r
703 {\r
704     IInArchive * hArc = (IInArchive *) _hArchive;\r
705         hArc->Close();\r
706         hArc->Release();\r
707         return TPI_ERROR_SUCCESS;\r
708 }\r
709 \r
710 int __stdcall GetFileInformation\r
711 (\r
712         void * _hArchive,\r
713         TPI_FILEINFO * _fiInfo,\r
714         bool _bFirst\r
715 )\r
716 {\r
717         static unsigned int s_uFileId, s_uFileCount;\r
718         if (_bFirst)\r
719         {\r
720                 s_uFileId = 0;\r
721                 ((IInArchive *) _hArchive)->GetNumberOfItems(& s_uFileCount);\r
722         }\r
723 \r
724         if (s_uFileId >= s_uFileCount)\r
725         {\r
726                 return TPI_ERROR_S_ENDOFDATA;\r
727         }\r
728 \r
729         return GetFileInformation2(_hArchive, _fiInfo, s_uFileId++);\r
730 }\r
731 \r
732 int __stdcall GetArchiveInformation\r
733 (\r
734         void * _hArchive,\r
735         TPI_ARCHIVEINFO * _aiInfo\r
736 )\r
737 {\r
738     IInArchive * hArc = (IInArchive *) _hArchive;\r
739         NWindows::NCOM::CPropVariant prop;\r
740         hArc->GetArchiveProperty(kpidSolid, & prop);\r
741         _aiInfo->fSolid         = VARIANT_BOOLToBool(prop.boolVal);\r
742         hArc->GetArchiveProperty(kpidComment, & prop);\r
743         if (prop.vt == VT_BSTR)\r
744         {\r
745                 _aiInfo->szComment  = WC2String(prop.bstrVal);\r
746         }\r
747         unsigned int u = g_llEngineId.ToULong();\r
748         GetFormatInformation2(& _aiInfo->fiInfo, u);\r
749         return TPI_ERROR_SUCCESS;\r
750 }\r
751 \r
752 int __stdcall Command\r
753 (\r
754         unsigned int _uCommand,\r
755         TPI_SWITCHES * _swInfo,\r
756         const wxString & _szArcName,\r
757         const wxArrayString & _szFiles\r
758 )\r
759 {\r
760         // コマンドを実行。\r
761         int nErrorCode;\r
762         switch (_uCommand)\r
763         {\r
764         case TPI_COMMAND_EXTRACT:\r
765         case TPI_COMMAND_TEST:\r
766         {\r
767                 // 開きなおす。\r
768                 IInArchive * hArc;\r
769                 nErrorCode = OpenArchive(_szArcName, (void **) & hArc);\r
770                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
771                 {\r
772                         return nErrorCode;\r
773                 }\r
774 \r
775                 // ファイル名からインデックスを取得。\r
776                 TPI_FILEINFO fiInfo;\r
777                 CRecordVector<unsigned int> nIndexes;\r
778                 if (GetFileInformation(hArc, & fiInfo, true) == TPI_ERROR_SUCCESS)\r
779                 {\r
780                         do\r
781                         {\r
782                                 if (_szFiles.Index(fiInfo.szStoredName) != wxNOT_FOUND)\r
783                                 {\r
784                                         nIndexes.Add(fiInfo.llFileId.ToULong());\r
785                                 }\r
786                         }\r
787                         while (GetFileInformation(hArc, & fiInfo, false) == TPI_ERROR_SUCCESS);\r
788                 }\r
789 \r
790                 CArchiveExtractCallback * extractCallbackSpec = new CArchiveExtractCallback;\r
791                 CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);\r
792                 extractCallbackSpec->hArc = hArc;\r
793                 extractCallbackSpec->swInfo = _swInfo;\r
794                 hArc->Extract(& nIndexes.Front(), nIndexes.Size(), _uCommand == TPI_COMMAND_TEST, extractCallback);\r
795                 nErrorCode = extractCallbackSpec->nErrorCode;\r
796                 CloseArchive(hArc);\r
797                 break;\r
798         }\r
799         case TPI_COMMAND_CREATE:\r
800 //      case TPI_COMMAND_ADD:\r
801         {\r
802                 CObjectVector<NWindows::NFile::NFind::CFileInfoW> fiItems;\r
803                 for (unsigned int i = 0; i < _szFiles.GetCount(); i++)\r
804                 {\r
805                         NWindows::NFile::NFind::CFileInfoW fi;\r
806                         wxFileName fn(_szFiles[i]);\r
807                         fn.Normalize(wxPATH_NORM_ALL, _swInfo->fnDestinationDirectory.GetFullPath());\r
808                         if (! fi.Find(fn.GetFullPath().c_str()))\r
809                         {\r
810                                 return TPI_ERROR_IO_FILE_ACCESS;\r
811                         }\r
812                         fiItems.Add(fi);\r
813                 }\r
814 \r
815                 COutFileStream * outFileStreamSpec = new COutFileStream;\r
816                 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;\r
817                 if (! outFileStreamSpec->Create(_szArcName.c_str(), false))\r
818                 {\r
819                         return TPI_ERROR_IO_ARC_OPEN;\r
820                 }\r
821 \r
822                 IOutArchive * hArc;\r
823                 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void **)) g_fpProc)(& guidList[g_llEngineId.ToULong()], & IID_IOutArchive, (void **) & hArc) != S_OK)\r
824                 {\r
825                         return TPI_ERROR_ARC_UNSUPPORTED;\r
826                 }\r
827 \r
828                 CArchiveUpdateCallback * updateCallbackSpec = new CArchiveUpdateCallback;\r
829                 CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);\r
830                 updateCallbackSpec->fiItems = & fiItems;\r
831                 updateCallbackSpec->swInfo = _swInfo;\r
832                 hArc->UpdateItems(outFileStream, fiItems.Size(), updateCallback);\r
833                 nErrorCode = updateCallbackSpec->nErrorCode;\r
834                 break;\r
835         }\r
836         default:\r
837                 nErrorCode = TPI_ERROR_D_UNSUPPORTED;\r
838         }\r
839         return nErrorCode;\r
840 }\r
841 \r
842 int __stdcall SetCallbackProc\r
843 (\r
844         TPI_PROC _prArcProc\r
845 )\r
846 {\r
847         // ポインタを保存。\r
848         if (_prArcProc == NULL)\r
849         {\r
850                 return TPI_ERROR_D_PARAMETER;\r
851         }\r
852         g_prProc = * _prArcProc;\r
853 \r
854         return TPI_ERROR_SUCCESS;\r
855 }\r
856 \r
857 #ifdef __cplusplus\r
858 }\r
859 #endif\r