OSDN Git Service

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