OSDN Git Service

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