OSDN Git Service

ec9a2cb143dfbcfd62008178cc44c995c53f82f5
[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 #ifdef __LINUX__\r
34 #define LIB_NAME wxT("7z.so")\r
35 #else\r
36 #define LIB_NAME g_hLib.CanonicalizeName(wxT("7z"))\r
37 #endif\r
38 \r
39 //******************************************************************************\r
40 //    Global varients\r
41 //******************************************************************************\r
42 \r
43 wxDynamicLibrary g_hLib;\r
44 void * g_fpProc;\r
45 TPI_PROC g_prProc;\r
46 wxULongLong_t g_nEngineId;\r
47 \r
48 #ifdef __LINUX__\r
49 extern int global_use_utf16_conversion;\r
50 #endif\r
51 \r
52 //******************************************************************************\r
53 //    Inside Functions\r
54 //******************************************************************************\r
55 \r
56 int GetFileInformation2(void * _hArchive, TPI_FILEINFO * _fiInfo, wxULongLong_t nIndex)\r
57 {\r
58         IInArchive * hArc = (IInArchive *) _hArchive;\r
59         NWindows::NCOM::CPropVariant prop;\r
60         hArc->GetProperty(nIndex, kpidAttrib, & prop);\r
61         _fiInfo->dwAttribute    = prop.vt == VT_EMPTY ? 0 : prop.uintVal;\r
62         hArc->GetProperty(nIndex, kpidEncrypted, & prop);\r
63         if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))\r
64         {\r
65                 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
66         }\r
67         hArc->GetProperty(nIndex, kpidIsDir, & prop);\r
68         if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))\r
69         {\r
70                 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_DIRECTORY;\r
71         }\r
72         hArc->GetProperty(nIndex, kpidCRC, & prop);\r
73         _fiInfo->dwCRC32        = prop.ulVal;\r
74         hArc->GetProperty(nIndex, kpidPackSize, & prop);\r
75         _fiInfo->nPackedSize    = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
76         hArc->GetProperty(nIndex, kpidSize, & prop);\r
77         _fiInfo->nUnpackedSize  = prop.vt == VT_EMPTY ? 0 : prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
78         unsigned int t;\r
79         hArc->GetProperty(nIndex, kpidMTime, & prop);\r
80         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
81         _fiInfo->tmModified.Set((time_t) t);\r
82         hArc->GetProperty(nIndex, kpidCTime, & prop);\r
83         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
84         _fiInfo->tmCreate.Set((time_t) t);\r
85         hArc->GetProperty(nIndex, kpidATime, & prop);\r
86         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
87         _fiInfo->tmAccess.Set((time_t) t);\r
88         hArc->GetProperty(nIndex, kpidPath, & prop);\r
89         if (prop.vt == VT_BSTR)\r
90         {\r
91                 _fiInfo->szStoredName = WC2String(prop.bstrVal);\r
92                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName, wxPATH_DOS);\r
93         }\r
94         else\r
95         {\r
96                 hArc->GetProperty(nIndex, kpidExtension, & prop);\r
97                 _fiInfo->szStoredName = wxT("data") + (prop.vt == VT_BSTR ? wxT(".") + WC2String(prop.bstrVal) : (wxString) wxEmptyString);\r
98                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName, wxPATH_DOS);\r
99         }\r
100         hArc->GetProperty(nIndex, kpidMethod, & prop);\r
101         if (prop.vt == VT_BSTR)\r
102         {\r
103                 _fiInfo->szMethod = WC2String(prop.bstrVal);\r
104         }\r
105         hArc->GetProperty(nIndex, kpidCommented, & prop);\r
106         if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))\r
107         {\r
108                 hArc->GetProperty(nIndex, kpidComment, & prop);\r
109                 _fiInfo->szComment  = WC2String(prop.bstrVal);\r
110         }\r
111         _fiInfo->nFileId        = nIndex;\r
112         return TPI_ERROR_SUCCESS;\r
113 }\r
114 \r
115 int __stdcall GetFormatInformation2(TPI_FORMATINFO * _fiInfo, wxULongLong_t & nIndex)\r
116 {\r
117         // Initialization.\r
118         _fiInfo->fArchive           = true;\r
119         _fiInfo->fComment           = false;\r
120         _fiInfo->fEncryptKeyFile    = false;\r
121         _fiInfo->fEncryptPassword   = false;\r
122         _fiInfo->fEncryptHeader     = false;\r
123         _fiInfo->fCompressHeader    = false;\r
124         _fiInfo->fMMOptimize        = false;\r
125         _fiInfo->fMultiVolume       = false;\r
126         _fiInfo->fSFX               = false;\r
127         _fiInfo->fSolid             = false;\r
128         _fiInfo->nCompressLevelMin  = 0;\r
129         _fiInfo->nCompressLevelMax  = 0;\r
130         _fiInfo->nRecoveryRecordMin = 0;\r
131         _fiInfo->nRecoveryRecordMax = 0;\r
132         _fiInfo->szTypeName.Empty();\r
133         _fiInfo->szSuffix.Empty();\r
134         _fiInfo->szEngineName       = LIB_NAME;\r
135         _fiInfo->szTPIName          = wxT("7zArc");\r
136         _fiInfo->eSupportedCommand  = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;\r
137         _fiInfo->nTypeId            = nIndex;\r
138         _fiInfo->pCustomInfo        = NULL;\r
139         wxULongLong_t nBase = nIndex++;\r
140         if (nBase >= sizeof(guidList) / sizeof(GUID))\r
141         {\r
142                 return TPI_ERROR_S_ENDOFDATA;\r
143         }\r
144         else if (guidList[nBase] == CLSID_CFormatZip)\r
145         {\r
146                 _fiInfo->szTypeName          = wxT("7-zip");\r
147                 _fiInfo->szSuffix            = wxT("zip");\r
148                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;\r
149                 _fiInfo->fSFX                = true;\r
150                 _fiInfo->fMultiVolume        = true;\r
151                 _fiInfo->fEncryptPassword    = true;\r
152                 _fiInfo->nCompressLevelMin   = 0;\r
153                 _fiInfo->nCompressLevelMax   = 9;\r
154         }\r
155         else if (guidList[nBase] == CLSID_CFormatBZip2)\r
156         {\r
157                 _fiInfo->szTypeName          = wxT("BZip2");\r
158                 _fiInfo->szSuffix            = wxT("bz2");\r
159                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;\r
160                 _fiInfo->fArchive            = false;\r
161                 _fiInfo->nCompressLevelMin   = 1;\r
162                 _fiInfo->nCompressLevelMax   = 9;\r
163         }\r
164 //      else if (guidList[nBase] == CLSID_CFormatRar)  { _fiInfo->szTypeName = wxT("Rar");     _fiInfo->szSuffix = wxT("rar"); }\r
165 #ifdef __LINUX__\r
166         else if (guidList[nBase] == CLSID_CFormatArj)  { _fiInfo->szTypeName = wxT("Arj");     _fiInfo->szSuffix = wxT("arj"); _fiInfo->fEncryptPassword = true; _fiInfo->fSFX = true; }\r
167 #endif\r
168         else if (guidList[nBase] == CLSID_CFormatZ)    { _fiInfo->szTypeName = wxT("Z");       _fiInfo->szSuffix = wxT("Z"); _fiInfo->fArchive = false; }\r
169 #ifdef __LINUX__\r
170         else if (guidList[nBase] == CLSID_CFormatLzh)  { _fiInfo->szTypeName = wxT("Lzh");     _fiInfo->szSuffix = wxT("lzh;lha;lzs"); _fiInfo->fSFX = true; }\r
171 #endif\r
172         else if (guidList[nBase] == CLSID_CFormat7z)\r
173         {\r
174                 _fiInfo->szTypeName          = wxT("7z");\r
175                 _fiInfo->szSuffix            = wxT("7z");\r
176                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;\r
177                 _fiInfo->fSFX                = true;\r
178                 _fiInfo->fMultiVolume        = true;\r
179                 _fiInfo->fSolid              = true;\r
180                 _fiInfo->fEncryptPassword    = true;\r
181                 _fiInfo->fEncryptHeader      = true;\r
182                 _fiInfo->fCompressHeader     = true;\r
183                 _fiInfo->nCompressLevelMin   = 0;\r
184                 _fiInfo->nCompressLevelMax   = 9;\r
185         }\r
186 #ifdef __LINUX__\r
187         else if (guidList[nBase] == CLSID_CFormatCab)  { _fiInfo->szTypeName = wxT("Cab");     _fiInfo->szSuffix = wxT("cab"); _fiInfo->fMultiVolume = true; _fiInfo->fSFX = true; }\r
188 #endif\r
189         else if (guidList[nBase] == CLSID_CFormatNsis) { _fiInfo->szTypeName = wxT("NSIS");    _fiInfo->szSuffix = wxT("exe"); _fiInfo->fSFX = true; }\r
190         else if (guidList[nBase] == CLSID_CFormatLzma) { _fiInfo->szTypeName = wxT("LZMA");    _fiInfo->szSuffix = wxT("lzma"); _fiInfo->fArchive = false; }\r
191         else if (guidList[nBase] == CLSID_CFormatLzma86){_fiInfo->szTypeName = wxT("LZMA86");  _fiInfo->szSuffix = wxT("lzma"); _fiInfo->fArchive = false; }\r
192         else if (guidList[nBase] == CLSID_CFormatXz)\r
193         {\r
194                 _fiInfo->szTypeName          = wxT("XZ");\r
195                 _fiInfo->szSuffix            = wxT("xz");\r
196                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;\r
197                 _fiInfo->fArchive            = false;\r
198                 _fiInfo->nCompressLevelMin   = 0;\r
199                 _fiInfo->nCompressLevelMax   = 9;\r
200         }\r
201         else if (guidList[nBase] == CLSID_CFormatApm)  { _fiInfo->szTypeName = wxT("Apm");     _fiInfo->szSuffix = wxT("apm"); }\r
202         else if (guidList[nBase] == CLSID_CFormatMslz) { _fiInfo->szTypeName = wxT("MSLZ");    _fiInfo->szSuffix = wxT("xx_"); _fiInfo->fArchive = false; }\r
203         else if (guidList[nBase] == CLSID_CFormatFlv)  { _fiInfo->szTypeName = wxT("Flv");     _fiInfo->szSuffix = wxT("flv"); }\r
204 //      else if (guidList[nBase] == CLSID_CFormatSwf)  { _fiInfo->szTypeName = wxT("Swf");     _fiInfo->szSuffix = wxT("swf"); }\r
205         else if (guidList[nBase] == CLSID_CFormatSwfc) { _fiInfo->szTypeName = wxT("Swfc");    _fiInfo->szSuffix = wxT("swf"); }\r
206         else if (guidList[nBase] == CLSID_CFormatNtfs) { _fiInfo->szTypeName = wxT("NTFS");    _fiInfo->szSuffix = wxT("ntfs");}\r
207         else if (guidList[nBase] == CLSID_CFormatFat)  { _fiInfo->szTypeName = wxT("FAT");     _fiInfo->szSuffix = wxT("fat"); }\r
208         else if (guidList[nBase] == CLSID_CFormatMbr)  { _fiInfo->szTypeName = wxT("Mbr");     _fiInfo->szSuffix = wxT("mbr"); }\r
209         else if (guidList[nBase] == CLSID_CFormatVhd)  { _fiInfo->szTypeName = wxT("Vhd");     _fiInfo->szSuffix = wxT("vhd"); }\r
210 //      else if (guidList[nBase] == CLSID_CFormatPe)   { _fiInfo->szTypeName = wxT("PE");      _fiInfo->szSuffix = wxT("exe"); _fiInfo->fArchive = false; }\r
211 //      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)\r
220         {\r
221                 _fiInfo->szTypeName          = wxT("WIM");\r
222                 _fiInfo->szSuffix            = wxT("wim");\r
223                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;\r
224         }\r
225         else if (guidList[nBase] == CLSID_CFormatIso)  { _fiInfo->szTypeName = wxT("ISO");     _fiInfo->szSuffix = wxT("iso"); }\r
226         else if (guidList[nBase] == CLSID_CFormatBkf)  { _fiInfo->szTypeName = wxT("Bkf");     _fiInfo->szSuffix = wxT("bkf"); }\r
227         else if (guidList[nBase] == CLSID_CFormatChm)  { _fiInfo->szTypeName = wxT("Chm");     _fiInfo->szSuffix = wxT("chm"); }\r
228         else if (guidList[nBase] == CLSID_CFormatSplit){ _fiInfo->szTypeName = wxT("Split"); }\r
229 #ifdef __LINUX__\r
230         else if (guidList[nBase] == CLSID_CFormatRpm)  { _fiInfo->szTypeName = wxT("RPM");     _fiInfo->szSuffix = wxT("rpm"); _fiInfo->fArchive = false; }\r
231         else if (guidList[nBase] == CLSID_CFormatDeb)  { _fiInfo->szTypeName = wxT("Deb");     _fiInfo->szSuffix = wxT("deb"); }\r
232         else if (guidList[nBase] == CLSID_CFormatCpio) { _fiInfo->szTypeName = wxT("Cpio");    _fiInfo->szSuffix = wxT("cpio");}\r
233         else if (guidList[nBase] == CLSID_CFormatTar)\r
234         {\r
235                 _fiInfo->szTypeName          = wxT("TAR");\r
236                 _fiInfo->szSuffix            = wxT("tar");\r
237                 _fiInfo->fSFX                = true;\r
238                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;// | TPI_COMMAND_ADD;\r
239         }\r
240 #endif\r
241         else if (guidList[nBase] == CLSID_CFormatGZip)\r
242         {\r
243                 _fiInfo->szTypeName          = wxT("GZip");\r
244                 _fiInfo->szSuffix            = wxT("gz");\r
245                 _fiInfo->eSupportedCommand  |= TPI_COMMAND_CREATE;\r
246                 _fiInfo->fArchive            = false;\r
247                 _fiInfo->nCompressLevelMin   = 1;\r
248                 _fiInfo->nCompressLevelMax   = 9;\r
249         }\r
250         else\r
251         {\r
252                 return GetFormatInformation2(_fiInfo, nIndex);\r
253         }\r
254         return TPI_ERROR_SUCCESS;\r
255 }\r
256 \r
257 //******************************************************************************\r
258 //    Callback Wrapper\r
259 //******************************************************************************\r
260 \r
261 // CArchiveOpenCallback\r
262 class CArchiveOpenCallback: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, public ICryptoGetTextPassword, public CMyUnknownImp\r
263 {\r
264 public:\r
265         MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
266         INTERFACE_IArchiveOpenCallback(;)\r
267         INTERFACE_IArchiveOpenVolumeCallback(;)\r
268         STDMETHOD(SetSubArchiveName)(const wchar_t * szName);\r
269         STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
270         int nErrorCode;\r
271         wxString szSubArchiveName;\r
272         NWindows::NFile::NFind::CFileInfoW fiInfo;\r
273 \r
274 private:\r
275         TPI_PROCESSINFO piInfo;\r
276 };\r
277 \r
278 STDMETHODIMP CArchiveOpenCallback::SetTotal(const wxULongLong_t *, const wxULongLong_t *)\r
279 {\r
280         return S_OK;\r
281 }\r
282 \r
283 STDMETHODIMP CArchiveOpenCallback::SetCompleted(const wxULongLong_t *, const wxULongLong_t *)\r
284 {\r
285         return S_OK;\r
286 }\r
287 \r
288 STDMETHODIMP CArchiveOpenCallback::GetProperty(PROPID propID, PROPVARIANT * value)\r
289 {\r
290         NWindows::NCOM::CPropVariant prop;\r
291         if (! this->szSubArchiveName.IsEmpty())\r
292         {\r
293                 switch (propID)\r
294                 {\r
295                         case kpidName: prop = (wxChar *) this->szSubArchiveName.wchar_str(); break;\r
296                 }\r
297         }\r
298         else\r
299         {\r
300                 switch (propID)\r
301                 {\r
302                         case kpidName:  prop = this->fiInfo.Name; break;\r
303                         case kpidIsDir: prop = this->fiInfo.IsDir(); break;\r
304                         case kpidSize:  prop = this->fiInfo.Size; break;\r
305                         case kpidAttrib:prop = (unsigned int) this->fiInfo.Attrib; break;\r
306                         case kpidCTime: prop = this->fiInfo.CTime; break;\r
307                         case kpidATime: prop = this->fiInfo.ATime; break;\r
308                         case kpidMTime: prop = this->fiInfo.MTime; break;\r
309                 }\r
310         }\r
311         prop.Detach(value);\r
312         return S_OK;\r
313 }\r
314 \r
315 STDMETHODIMP CArchiveOpenCallback::GetStream(const wchar_t * szName, IInStream ** inStream)\r
316 {\r
317         if (! this->szSubArchiveName.IsEmpty())\r
318         {\r
319                 return S_FALSE;\r
320         }\r
321         * inStream = NULL;\r
322         wxString szFileName = this->piInfo.fiInfo.fnFileName.GetPathWithSep() + szName;\r
323         if (! this->fiInfo.Find(szFileName.c_str()) || fiInfo.IsDir())\r
324         {\r
325                 this->nErrorCode = TPI_ERROR_IO_ARC_OPEN;\r
326                 return S_FALSE;\r
327         }\r
328 \r
329         CInFileStream * inFile = new CInFileStream;\r
330         CMyComPtr<IInStream> inStreamTemp = inFile;\r
331         if (! inFile->Open(szFileName.c_str()))\r
332         {\r
333                 this->nErrorCode = TPI_ERROR_IO_ARC_OPEN;\r
334                 return S_FALSE;\r
335         }\r
336         * inStream = inStreamTemp.Detach();\r
337         return S_OK;\r
338 }\r
339 \r
340 STDMETHODIMP CArchiveOpenCallback::SetSubArchiveName(const wchar_t * szName)\r
341 {\r
342         this->szSubArchiveName = WC2String(szName);\r
343         return S_OK;\r
344 }\r
345 \r
346 STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR * szPassword)\r
347 {\r
348         this->piInfo.eMessage           = TPI_MESSAGE_ASK;\r
349         this->piInfo.eStatus            = TPI_PARAM_PASSWORD;\r
350         return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;\r
351 }\r
352 \r
353 // CArchiveExtractCallback\r
354 class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp\r
355 {\r
356 public:\r
357         MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
358         INTERFACE_IArchiveExtractCallback(;)\r
359         STDMETHOD(CryptoGetTextPassword)(BSTR * szPassword);\r
360         CArchiveExtractCallback(CMyComPtr<IInArchive>, TPI_SWITCHES *);\r
361 \r
362         int nErrorCode;\r
363         TPI_SWITCHES * swInfo;\r
364 \r
365 private:\r
366         int nMode;\r
367         bool fTriedPassword;\r
368         TPI_PROCESSINFO piInfo;\r
369         wxULongLong_t nCurrentPos;\r
370         COutFileStream * _outFileStreamSpec;\r
371         CMyComPtr<ISequentialOutStream> _outFileStream;\r
372         CMyComPtr<IInArchive> hArc;\r
373 };\r
374 \r
375 CArchiveExtractCallback::CArchiveExtractCallback(CMyComPtr<IInArchive> hArc, TPI_SWITCHES * swInfo)\r
376 {\r
377         this->hArc = hArc;\r
378         this->swInfo = swInfo;\r
379         this->fTriedPassword = false;\r
380 }\r
381 \r
382 STDMETHODIMP CArchiveExtractCallback::SetTotal(wxULongLong_t)\r
383 {\r
384         return S_OK;\r
385 }\r
386 \r
387 STDMETHODIMP CArchiveExtractCallback::SetCompleted(const wxULongLong_t * nProcessed)\r
388 {\r
389         this->piInfo.eStatus                = TPI_STATUS_INPROCESS;\r
390         this->piInfo.nProcessedSize     = * nProcessed - this->nCurrentPos;\r
391         if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)\r
392         {\r
393                 return S_OK;\r
394         }\r
395         else\r
396         {\r
397                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
398                 return E_ABORT;\r
399         }\r
400 }\r
401 \r
402 STDMETHODIMP CArchiveExtractCallback::GetStream(unsigned int nIndex, ISequentialOutStream ** outStream, int nExtractMode)\r
403 {\r
404         * outStream = 0;\r
405         _outFileStream.Release();\r
406 \r
407         // 前のファイルの処理の終了を通知。\r
408         this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;\r
409         this->piInfo.eMessage               = TPI_MESSAGE_STATUS;\r
410         if (this->nCurrentPos != 0)\r
411         {\r
412                 this->piInfo.eStatus            = TPI_STATUS_ENDPROCESS;\r
413                 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
414                 {\r
415                         this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
416                         return E_ABORT;\r
417                 }\r
418         }\r
419 \r
420         // ファイルの基本情報を取得。\r
421         this->piInfo.eStatus                = TPI_STATUS_BEGINPROCESS;\r
422         GetFileInformation2(this->hArc, & this->piInfo.fiInfo, nIndex);\r
423         this->piInfo.fnDestination          = wxFileName(swInfo->fnDestinationDirectory.GetFullPath() + wxFileName::GetPathSeparator() + (swInfo->fStoreDirectoryPathes ? this->piInfo.fiInfo.fnFileName.GetPath() : (wxString) wxEmptyString), this->piInfo.fiInfo.fnFileName.GetFullName());\r
424         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
425         {\r
426                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
427                 return E_ABORT;\r
428         }\r
429 \r
430         if (nExtractMode != NArchive::NExtract::NAskMode::kExtract)\r
431         {\r
432                 return S_OK;\r
433         }\r
434 \r
435         // ディレクトリかどうかを判定し、必要なディレクトリを作成。\r
436         if (! ::wxFileName::Mkdir(this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? this->piInfo.fnDestination.GetFullPath() : this->piInfo.fnDestination.GetPath(), 0777, wxPATH_MKDIR_FULL))\r
437         {\r
438                 this->nErrorCode = TPI_ERROR_IO_DIR_OPEN;\r
439                 return E_ABORT;\r
440         }\r
441         if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
442         {\r
443                 return S_OK;\r
444         }\r
445 \r
446         if (::wxFileExists(this->piInfo.fnDestination.GetFullPath()))\r
447         {\r
448                 // 既にファイルが存在する場合。\r
449                 if (! ::wxRemoveFile(this->piInfo.fnDestination.GetFullPath()))\r
450                 {\r
451                         this->nErrorCode = TPI_ERROR_IO_FILE_DELETE;\r
452                         return E_ABORT;\r
453                 }\r
454         }\r
455 \r
456         _outFileStreamSpec = new COutFileStream;\r
457         CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\r
458         if (! _outFileStreamSpec->Open(this->piInfo.fnDestination.GetFullPath(), CREATE_ALWAYS))\r
459         {\r
460                 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;\r
461                 return E_ABORT;\r
462         }\r
463 \r
464         _outFileStream = outStreamLoc;\r
465         * outStream = outStreamLoc.Detach();\r
466         return S_OK;\r
467 }\r
468 \r
469 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(int nExtractMode)\r
470 {\r
471         this->nMode = nExtractMode;\r
472         return S_OK;\r
473 }\r
474 \r
475 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(int nResult)\r
476 {\r
477         switch (nResult)\r
478         {\r
479         case NArchive::NExtract::NOperationResult::kOK:                this->nErrorCode = TPI_ERROR_SUCCESS;         break;\r
480         case NArchive::NExtract::NOperationResult::kUnSupportedMethod: this->nErrorCode = TPI_ERROR_ARC_UNSUPPORTED; break;\r
481         case NArchive::NExtract::NOperationResult::kDataError:         this->nErrorCode = TPI_ERROR_ARC_BROKEN_MISC; break;\r
482         case NArchive::NExtract::NOperationResult::kCRCError:          this->nErrorCode = TPI_ERROR_ARC_BROKEN_SUM;  break;\r
483         default:                                                       this->nErrorCode = TPI_ERROR_UNDEFINED;       break;\r
484         }\r
485 \r
486         // 更新時刻を記録。\r
487         if (_outFileStream != NULL)\r
488         {\r
489                 FILETIME ft;\r
490                 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmModified.GetTicks(), ft);\r
491                 _outFileStreamSpec->SetMTime(& ft);\r
492                 _outFileStreamSpec->Close();\r
493         }\r
494         _outFileStream.Release();\r
495 \r
496         // 属性を記録。\r
497         if (this->nMode == NArchive::NExtract::NAskMode::kExtract)\r
498         {\r
499 //              NWindows::NFile::NDirectory::MySetFileAttributes(this->piInfo.fiInfo.fnFileName.GetFullPath(), this->piInfo.fiInfo.dwAttribute);\r
500         }\r
501 \r
502         return S_OK;\r
503 }\r
504 \r
505 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR * szPassword)\r
506 {\r
507         if (this->fTriedPassword || this->swInfo->szPassword.IsEmpty())\r
508         {\r
509                 this->piInfo.eMessage           = TPI_MESSAGE_ASK;\r
510                 this->piInfo.eStatus            = TPI_PARAM_PASSWORD;\r
511                 // 次のファイル名が取得できないので、とりあえず空にしておく。\r
512                 this->piInfo.fiInfo.fnFileName.Clear();\r
513                 return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;\r
514         }\r
515         else\r
516         {\r
517                 // 既定のパスワードがある場合はまずそれを試す。\r
518                 this->fTriedPassword = true;\r
519                 return ::StringToBstr(this->swInfo->szPassword, szPassword);\r
520         }\r
521 }\r
522 \r
523 // CArchiveUpdateCallback\r
524 class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp\r
525 {\r
526 public:\r
527         MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)\r
528         INTERFACE_IArchiveUpdateCallback2(;)\r
529         STDMETHOD(CryptoGetTextPassword2)(int * nPasswordIsDefined, BSTR * szPassword);\r
530         CArchiveUpdateCallback(TPI_SWITCHES *, CObjectVector<NWindows::NFile::NFind::CFileInfoW> *);\r
531 \r
532         const CObjectVector<NWindows::NFile::NFind::CFileInfoW> * fiItems;\r
533         int nErrorCode;\r
534 \r
535 private:\r
536         wxULongLong_t nCurrentPos;\r
537         TPI_PROCESSINFO piInfo;\r
538         TPI_SWITCHES * swInfo;\r
539 };\r
540 \r
541 CArchiveUpdateCallback::CArchiveUpdateCallback(TPI_SWITCHES * swInfo, CObjectVector<NWindows::NFile::NFind::CFileInfoW> * fiItems)\r
542 {\r
543         this->swInfo = swInfo;\r
544         this->fiItems = fiItems;\r
545 }\r
546 \r
547 STDMETHODIMP CArchiveUpdateCallback::SetTotal(wxULongLong_t)\r
548 {\r
549         return S_OK;\r
550 }\r
551 \r
552 STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const wxULongLong_t * nProcessed)\r
553 {\r
554         this->piInfo.eStatus            = TPI_STATUS_INPROCESS;\r
555         this->piInfo.nProcessedSize     = * nProcessed - this->nCurrentPos;\r
556         if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)\r
557         {\r
558                 return S_OK;\r
559         }\r
560         else\r
561         {\r
562                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
563                 return E_ABORT;\r
564         }\r
565 }\r
566 \r
567 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(unsigned int /* index */, int *newData, int *newProperties, unsigned int *indexInArchive)\r
568 {\r
569         if (newData != NULL)\r
570         {\r
571                 * newData = 1;\r
572         }\r
573         if (newProperties != NULL)\r
574         {\r
575                 * newProperties = 1;\r
576         }\r
577         if (indexInArchive != NULL)\r
578         {\r
579                 * indexInArchive = (unsigned) -1;\r
580         }\r
581         return S_OK;\r
582 }\r
583 \r
584 STDMETHODIMP CArchiveUpdateCallback::GetProperty(unsigned int nIndex, PROPID propID, PROPVARIANT * value)\r
585 {\r
586         NWindows::NCOM::CPropVariant prop;\r
587         if (propID == kpidIsAnti)\r
588         {\r
589                 prop = false;\r
590                 prop.Detach(value);\r
591                 return S_OK;\r
592         }\r
593 \r
594         const NWindows::NFile::NFind::CFileInfoW fiItem = (* this->fiItems)[nIndex];\r
595         switch (propID)\r
596         {\r
597                 case kpidPath:  prop = fiItem.Name;  break;\r
598                 case kpidIsDir: prop = (unsigned int) fiItem.Attrib & TPI_ATTRIBUTE_DIRECTORY ? true : false; break;\r
599                 case kpidSize:  prop = fiItem.Size;  break;\r
600                 case kpidAttrib:prop = (unsigned int) fiItem.Attrib;break;\r
601                 case kpidCTime: prop = fiItem.CTime; break;\r
602                 case kpidATime: prop = fiItem.ATime; break;\r
603                 case kpidMTime: prop = fiItem.MTime; break;\r
604         }\r
605         prop.Detach(value);\r
606         return S_OK;\r
607 }\r
608 \r
609 STDMETHODIMP CArchiveUpdateCallback::GetStream(unsigned int nIndex, ISequentialInStream ** inStream)\r
610 {\r
611         // 前のファイルの処理の終了を通知。\r
612         this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;\r
613         this->piInfo.eMessage               = TPI_MESSAGE_STATUS;\r
614         if (this->nCurrentPos != 0)\r
615         {\r
616                 this->piInfo.eStatus            = TPI_STATUS_ENDPROCESS;\r
617                 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
618                 {\r
619                         this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
620                         return E_ABORT;\r
621                 }\r
622         }\r
623 \r
624         // ファイルの基本情報を取得。\r
625         NWindows::NCOM::CPropVariant prop;\r
626         this->GetProperty(nIndex, kpidAttrib, & prop);\r
627         this->piInfo.fiInfo.dwAttribute     = prop.uintVal;\r
628         this->GetProperty(nIndex, kpidSize, & prop);\r
629         this->piInfo.fiInfo.nUnpackedSize   = prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
630         unsigned int t;\r
631         this->GetProperty(nIndex, kpidMTime, & prop);\r
632         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
633         this->piInfo.fiInfo.tmModified.Set((time_t) t);\r
634         this->GetProperty(nIndex, kpidCTime, & prop);\r
635         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
636         this->piInfo.fiInfo.tmCreate.Set((time_t) t);\r
637         this->GetProperty(nIndex, kpidATime, & prop);\r
638         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
639         this->piInfo.fiInfo.tmAccess.Set((time_t) t);\r
640         this->GetProperty(nIndex, kpidPath, & prop);\r
641         this->piInfo.fiInfo.szStoredName = WC2String(prop.bstrVal);\r
642         this->piInfo.fiInfo.nFileId         = nIndex;\r
643         this->piInfo.fiInfo.fnFileName      = wxFileName(this->piInfo.fiInfo.szStoredName);\r
644         this->piInfo.fiInfo.fnFileName.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, this->swInfo->fnDestinationDirectory.GetFullPath());\r
645         this->piInfo.eStatus                = TPI_STATUS_BEGINPROCESS;\r
646         this->piInfo.fnDestination          = wxFileName(this->piInfo.fiInfo.szStoredName);\r
647 \r
648         // コールバック関数に送信。\r
649         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
650         {\r
651                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
652                 return E_ABORT;\r
653         }\r
654 \r
655         if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
656         {\r
657                 return S_OK;\r
658         }\r
659 \r
660         CInFileStream * inStreamSpec = new CInFileStream;\r
661         CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
662         if (! inStreamSpec->Open(this->piInfo.fiInfo.fnFileName.GetFullPath().c_str()))\r
663         {\r
664                 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;\r
665                 return S_FALSE;\r
666         }\r
667 \r
668         * inStream = inStreamLoc.Detach();\r
669         return S_OK;\r
670 }\r
671 \r
672 STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(int nResult)\r
673 {\r
674         switch (nResult)\r
675         {\r
676         case NArchive::NUpdate::NOperationResult::kOK:                 this->nErrorCode = TPI_ERROR_SUCCESS;         break;\r
677         case NArchive::NUpdate::NOperationResult::kError:\r
678         default:                                                       this->nErrorCode = TPI_ERROR_UNDEFINED;       break;\r
679         }\r
680         return S_OK;\r
681 }\r
682 \r
683 STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(unsigned int, wxULongLong_t * nSplitSize)\r
684 {\r
685         * nSplitSize = this->swInfo->nSplitSize;\r
686         return S_OK;\r
687 }\r
688 \r
689 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(unsigned int nIndex, ISequentialOutStream ** volumeStream)\r
690 {\r
691         COutFileStream * streamSpec = new COutFileStream;\r
692         CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);\r
693         if (! streamSpec->Create(this->piInfo.fiInfo.fnFileName.GetFullPath() + wxString::Format(wxT(".%03d"), nIndex + 1), false))\r
694         {\r
695                 return TPI_ERROR_IO_ARC_OPEN;\r
696         }\r
697         * volumeStream = streamLoc.Detach();\r
698         return S_OK;\r
699 }\r
700 \r
701 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(int * nPasswordIsDefined, BSTR * szPassword)\r
702 {\r
703         * nPasswordIsDefined = ! this->swInfo->szPassword.IsEmpty();\r
704         return ::StringToBstr(this->swInfo->szPassword.c_str(), szPassword);\r
705 }\r
706 \r
707 //******************************************************************************\r
708 //    Functions\r
709 //******************************************************************************\r
710 \r
711 #ifdef __cplusplus\r
712 extern "C"\r
713 {\r
714 #endif\r
715 \r
716 int __stdcall GetPluginInformation\r
717 (\r
718         unsigned int _uInfoId,\r
719         wxULongLong_t,\r
720         void * _pPtr\r
721 )\r
722 {\r
723         if (_pPtr == NULL)\r
724         {\r
725                 return TPI_ERROR_D_PARAMETER;\r
726         }\r
727         switch (_uInfoId)\r
728         {\r
729         case TPI_INFO_VERSION_MAJOR:\r
730         case TPI_INFO_VERSION_MINOR:\r
731                 * (int *) _pPtr = 0;\r
732                 break;\r
733         case TPI_INFO_VERSION_API:\r
734                 * (int *) _pPtr = 2;\r
735                 break;\r
736         default:\r
737                 return TPI_ERROR_D_UNSUPPORTED;\r
738         }\r
739         return TPI_ERROR_SUCCESS;\r
740 }\r
741 \r
742 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
743 {\r
744         static wxULongLong_t s_nTypeId;\r
745         if (_bFirst)\r
746         {\r
747                 s_nTypeId = 0;\r
748         }\r
749         return GetFormatInformation2(_fiInfo, s_nTypeId);\r
750 }\r
751 \r
752 int __stdcall LoadPlugin\r
753 (\r
754         const wxString & _szArcName,\r
755         wxULongLong_t _nTypeId\r
756 )\r
757 {\r
758         ::RemoveCwdFromSearchPath();\r
759 #ifdef __LINUX__\r
760         global_use_utf16_conversion = 1;\r
761 #endif\r
762         g_hLib.Load(LIB_NAME);\r
763         if (! g_hLib.IsLoaded())\r
764         {\r
765                 g_hLib.Unload();\r
766                 return TPI_ERROR_U_LOAD_LIBRARY;\r
767         }\r
768 \r
769         if (! g_hLib.HasSymbol(wxT("CreateObject")))\r
770         {\r
771                 return TPI_ERROR_U_USE_LIBRARY;\r
772         }\r
773         g_fpProc = g_hLib.GetSymbol(wxT("CreateObject"));\r
774         if (! g_fpProc)\r
775         {\r
776                 return TPI_ERROR_U_USE_LIBRARY;\r
777         }\r
778 \r
779         if (! ::wxFileExists(_szArcName))\r
780         {\r
781                 g_nEngineId = _nTypeId;\r
782         }\r
783 \r
784         return TPI_ERROR_SUCCESS;\r
785 }\r
786 \r
787 int __stdcall FreePlugin\r
788 (\r
789         void * // _pReserved\r
790 )\r
791 {\r
792         g_hLib.Unload();\r
793         return TPI_ERROR_SUCCESS;\r
794 }\r
795 \r
796 int __stdcall CheckArchive\r
797 (\r
798         const wxString &,\r
799         wxULongLong_t *\r
800 )\r
801 {\r
802         return TPI_ERROR_SUCCESS;\r
803 }\r
804 \r
805 int __stdcall OpenArchive\r
806 (\r
807         const wxString & _szArcName,\r
808         void * * _hArchive\r
809 )\r
810 {\r
811         // ***.tar.xxxは不便なので弾く。\r
812         wxString s = _szArcName.BeforeLast(wxT('.'));\r
813         if (s.Find(wxT('.')) != wxNOT_FOUND && s.AfterLast(wxT('.')) == wxT("tar"))\r
814         {\r
815                 return TPI_ERROR_IO_ARC_OPEN;\r
816         }\r
817 \r
818         // 書庫形式を認識。\r
819         IInArchive * hArc;\r
820         for (wxULongLong_t i = 0; i < sizeof(guidList) / sizeof(GUID); )\r
821         {\r
822                 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void * *)) g_fpProc)(& guidList[i], & IID_IInArchive, (void **) & hArc) != S_OK)\r
823                 {\r
824                         i++;\r
825                         continue;\r
826                 }\r
827 \r
828                 // 書庫を開く。\r
829                 CInFileStream * fileSpec = new CInFileStream;\r
830                 CMyComPtr<IInStream> file = fileSpec;\r
831                 if (! fileSpec->Open(_szArcName.c_str()))\r
832                 {\r
833                         return TPI_ERROR_IO_ARC_OPEN;\r
834                 }\r
835 \r
836                 // 形式の情報を取得。\r
837                 g_nEngineId = i;\r
838                 TPI_FORMATINFO fiInfo;\r
839                 GetFormatInformation2(& fiInfo, i);\r
840 \r
841                 // 書庫として開く。\r
842                 CArchiveOpenCallback * openCallbackSpec = new CArchiveOpenCallback;\r
843                 CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);\r
844                 wxULongLong_t nMax = 0;\r
845                 if (fiInfo.fSFX)\r
846                 {\r
847                         fileSpec->GetSize(& nMax);\r
848                 }\r
849                 if (hArc->Open(file, & nMax, openCallback) == S_OK)\r
850                 {\r
851                         * _hArchive = hArc;\r
852                         return TPI_ERROR_SUCCESS;\r
853                 }\r
854         }\r
855         return TPI_ERROR_IO_ARC_OPEN;\r
856 }\r
857 \r
858 int __stdcall CloseArchive\r
859 (\r
860         void * _hArchive\r
861 )\r
862 {\r
863     IInArchive * hArc = (IInArchive *) _hArchive;\r
864         hArc->Close();\r
865         hArc->Release();\r
866         return TPI_ERROR_SUCCESS;\r
867 }\r
868 \r
869 int __stdcall GetFileInformation\r
870 (\r
871         void * _hArchive,\r
872         TPI_FILEINFO * _fiInfo,\r
873         bool _bFirst\r
874 )\r
875 {\r
876         static unsigned int s_uFileId, s_uFileCount;\r
877         if (_bFirst)\r
878         {\r
879                 s_uFileId = 0;\r
880                 ((IInArchive *) _hArchive)->GetNumberOfItems(& s_uFileCount);\r
881         }\r
882 \r
883         if (s_uFileId >= s_uFileCount)\r
884         {\r
885                 return TPI_ERROR_S_ENDOFDATA;\r
886         }\r
887 \r
888         return GetFileInformation2(_hArchive, _fiInfo, s_uFileId++);\r
889 }\r
890 \r
891 int __stdcall GetArchiveInformation\r
892 (\r
893         void * _hArchive,\r
894         TPI_ARCHIVEINFO * _aiInfo\r
895 )\r
896 {\r
897     IInArchive * hArc = (IInArchive *) _hArchive;\r
898         NWindows::NCOM::CPropVariant prop;\r
899         hArc->GetArchiveProperty(kpidSolid, & prop);\r
900         _aiInfo->fSolid         = VARIANT_BOOLToBool(prop.boolVal);\r
901         hArc->GetArchiveProperty(kpidComment, & prop);\r
902         if (prop.vt == VT_BSTR)\r
903         {\r
904                 _aiInfo->szComment  = WC2String(prop.bstrVal);\r
905         }\r
906         wxULongLong_t n = g_nEngineId;\r
907         GetFormatInformation2(& _aiInfo->fiInfo, n);\r
908         return TPI_ERROR_SUCCESS;\r
909 }\r
910 \r
911 int __stdcall Command\r
912 (\r
913         wxULongLong_t _eCommand,\r
914         TPI_SWITCHES * _swInfo,\r
915         const wxString & _szArcName,\r
916         const wxArrayString & _szFiles\r
917 )\r
918 {\r
919         // コマンドを実行。\r
920         int nErrorCode;\r
921         switch (_eCommand)\r
922         {\r
923         case TPI_COMMAND_EXTRACT:\r
924         case TPI_COMMAND_TEST:\r
925         {\r
926                 // 開きなおす。\r
927                 IInArchive * hArc;\r
928                 nErrorCode = OpenArchive(_szArcName, (void **) & hArc);\r
929                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
930                 {\r
931                         return nErrorCode;\r
932                 }\r
933 \r
934                 // ファイル名からインデックスを取得。\r
935                 TPI_FILEINFO fiInfo;\r
936                 CRecordVector<unsigned int> nIndexes;\r
937                 if (GetFileInformation(hArc, & fiInfo, true) == TPI_ERROR_SUCCESS)\r
938                 {\r
939                         do\r
940                         {\r
941                                 if (_szFiles.Index(fiInfo.szStoredName) != wxNOT_FOUND)\r
942                                 {\r
943                                         nIndexes.Add(fiInfo.nFileId);\r
944                                 }\r
945                         }\r
946                         while (GetFileInformation(hArc, & fiInfo, false) == TPI_ERROR_SUCCESS);\r
947                 }\r
948 \r
949                 CArchiveExtractCallback * extractCallbackSpec = new CArchiveExtractCallback(hArc,_swInfo);\r
950                 CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);\r
951                 hArc->Extract(& nIndexes.Front(), nIndexes.Size(), _eCommand == TPI_COMMAND_TEST, extractCallback);\r
952                 nErrorCode = extractCallbackSpec->nErrorCode;\r
953                 CloseArchive(hArc);\r
954                 break;\r
955         }\r
956         case TPI_COMMAND_CREATE:\r
957 //      case TPI_COMMAND_ADD:\r
958         {\r
959                 // 入力リストを作成。\r
960                 CObjectVector<NWindows::NFile::NFind::CFileInfoW> fiItems;\r
961                 for (unsigned int i = 0; i < _szFiles.GetCount(); i++)\r
962                 {\r
963                         NWindows::NFile::NFind::CFileInfoW fi;\r
964                         wxFileName fn(_szFiles[i]);\r
965                         fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, _swInfo->fnDestinationDirectory.GetFullPath());\r
966                         if (! fi.Find(fn.GetFullPath().c_str()))\r
967                         {\r
968                                 return TPI_ERROR_IO_FILE_ACCESS;\r
969                         }\r
970                         fiItems.Add(fi);\r
971                 }\r
972 \r
973                 // 書庫を作成。\r
974                 COutFileStream * outFileStreamSpec = new COutFileStream;\r
975                 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;\r
976                 if (! outFileStreamSpec->Create(_szArcName.c_str(), false))\r
977                 {\r
978                         return TPI_ERROR_IO_ARC_OPEN;\r
979                 }\r
980 \r
981                 // エンジンを読み込み。\r
982                 IOutArchive * hArc;\r
983                 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void **)) g_fpProc)(& guidList[g_nEngineId], & IID_IOutArchive, (void **) & hArc) != S_OK)\r
984                 {\r
985                         return TPI_ERROR_ARC_UNSUPPORTED;\r
986                 }\r
987 \r
988                 // 形式情報を取得。\r
989                 TPI_FORMATINFO fiInfo;\r
990                 wxULongLong_t nIndex = g_nEngineId;\r
991                 GetFormatInformation2(& fiInfo, nIndex);\r
992 \r
993                 // パラメータを設定。\r
994                 ISetProperties * setProp;\r
995                 if (hArc->QueryInterface(IID_ISetProperties, (void **) & setProp) == S_OK)\r
996                 {\r
997                         CRecordVector<const wchar_t *> szProps;\r
998                         NWindows::NCOM::CPropVariant propValues[15];\r
999                         wxString szProp;\r
1000                         // 圧縮レベル。\r
1001                         if (fiInfo.nCompressLevelMin != fiInfo.nCompressLevelMax)\r
1002                         {\r
1003                                 szProp = wxString::Format(wxT("x%d"), _swInfo->nCompressLevel);\r
1004                                 szProps.Add(szProp.c_str());\r
1005                         }\r
1006                         // Solid圧縮。\r
1007                         if (fiInfo.fSolid)\r
1008                         {\r
1009                                 propValues[szProps.Size()] = _swInfo->fSolid;\r
1010                                 szProps.Add(wxT("s"));\r
1011                         }\r
1012                         // ヘッダ圧縮。\r
1013                         if (fiInfo.fCompressHeader)\r
1014                         {\r
1015                                 propValues[szProps.Size()] = _swInfo->fCompressHeader;\r
1016                                 szProps.Add(wxT("hc"));\r
1017                         }\r
1018                         // ヘッダ暗号化。\r
1019                         if (fiInfo.fEncryptHeader)\r
1020                         {\r
1021                                 propValues[szProps.Size()] = _swInfo->fEncryptHeader;\r
1022                                 szProps.Add(wxT("he"));\r
1023                         }\r
1024 \r
1025 //                      szProp = wxString::Format(wxT("m"));\r
1026 //                      propValues[szProps.Size()] = L"Deflate";\r
1027 //                      szProps.Add(szProp.c_str());\r
1028 \r
1029 //                      szProp = wxString::Format(wxT("fb%d"), );\r
1030 //                      szProps.Add(szProp.c_str());\r
1031 \r
1032                         setProp->SetProperties(& szProps.Front(), propValues, szProps.Size());\r
1033                 }\r
1034 \r
1035                 // 更新処理を実行。\r
1036                 CArchiveUpdateCallback * updateCallbackSpec = new CArchiveUpdateCallback(_swInfo, & fiItems);\r
1037                 CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);\r
1038                 hArc->UpdateItems(outFileStream, fiItems.Size(), updateCallback);\r
1039                 nErrorCode = updateCallbackSpec->nErrorCode;\r
1040                 break;\r
1041         }\r
1042         default:\r
1043                 nErrorCode = TPI_ERROR_D_UNSUPPORTED;\r
1044         }\r
1045         return nErrorCode;\r
1046 }\r
1047 \r
1048 int __stdcall SetCallbackProc\r
1049 (\r
1050         TPI_PROC _prArcProc\r
1051 )\r
1052 {\r
1053         // ポインタを保存。\r
1054         if (_prArcProc == NULL)\r
1055         {\r
1056                 return TPI_ERROR_D_PARAMETER;\r
1057         }\r
1058         g_prProc = * _prArcProc;\r
1059 \r
1060         return TPI_ERROR_SUCCESS;\r
1061 }\r
1062 \r
1063 #ifdef __cplusplus\r
1064 }\r
1065 #endif\r