OSDN Git Service

170b644206a9e2f01770abba3394ff986d695227
[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(prop.vt == VT_BSTR ? WC2String(prop.bstrVal) : (wxString) wxEmptyString);\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();\r
452                 if (this->piInfo.fiInfo.fnFileName.HasExt())\r
453                 {\r
454                         this->piInfo.fiInfo.szStoredName += wxT('.') + this->piInfo.fiInfo.fnFileName.GetExt();\r
455                 }\r
456                 this->piInfo.fiInfo.fnFileName = wxFileName(this->piInfo.fiInfo.szStoredName);\r
457         }\r
458 \r
459         this->piInfo.fnDestination          = wxFileName(swInfo->fnDestinationDirectory.GetFullPath() + wxFileName::GetPathSeparator() + (swInfo->fStoreDirectoryPathes ? this->piInfo.fiInfo.fnFileName.GetPath() : (wxString) wxEmptyString), this->piInfo.fiInfo.fnFileName.GetFullName());\r
460         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
461         {\r
462                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
463                 return E_ABORT;\r
464         }\r
465         if (! piInfo.fnDestination.IsOk())\r
466         {\r
467                 return S_OK;\r
468         }\r
469 \r
470         // ファイルの基本情報を取得。\r
471         this->piInfo.eMessage   = TPI_MESSAGE_STATUS;\r
472         this->piInfo.eStatus    = TPI_STATUS_BEGINPROCESS;\r
473         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
474         {\r
475                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
476                 return E_ABORT;\r
477         }\r
478 \r
479         if (nExtractMode != NArchive::NExtract::NAskMode::kExtract)\r
480         {\r
481                 return S_OK;\r
482         }\r
483 \r
484         // ディレクトリかどうかを判定し、必要なディレクトリを作成。\r
485         if (! ::wxFileName::Mkdir(this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? this->piInfo.fnDestination.GetFullPath() : this->piInfo.fnDestination.GetPath(), 0777, wxPATH_MKDIR_FULL))\r
486         {\r
487                 this->nErrorCode = TPI_ERROR_IO_DIR_OPEN;\r
488                 return E_ABORT;\r
489         }\r
490         if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
491         {\r
492                 return S_OK;\r
493         }\r
494 \r
495         // ファイルを作成。\r
496         _outFileStreamSpec = new COutFileStream;\r
497         CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\r
498         if (! _outFileStreamSpec->Open(this->piInfo.fnDestination.GetFullPath(), CREATE_NEW))\r
499         {\r
500                 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;\r
501                 return E_ABORT;\r
502         }\r
503 \r
504         _outFileStream = outStreamLoc;\r
505         * outStream = outStreamLoc.Detach();\r
506         return S_OK;\r
507 }\r
508 \r
509 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(int nExtractMode)\r
510 {\r
511         this->nMode = nExtractMode;\r
512         return S_OK;\r
513 }\r
514 \r
515 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(int nResult)\r
516 {\r
517         switch (nResult)\r
518         {\r
519         case NArchive::NExtract::NOperationResult::kOK:                this->nErrorCode = TPI_ERROR_SUCCESS;         break;\r
520         case NArchive::NExtract::NOperationResult::kUnSupportedMethod: this->nErrorCode = TPI_ERROR_ARC_UNSUPPORTED; break;\r
521         case NArchive::NExtract::NOperationResult::kDataError:         this->nErrorCode = TPI_ERROR_ARC_BROKEN_MISC; break;\r
522         case NArchive::NExtract::NOperationResult::kCRCError:          this->nErrorCode = TPI_ERROR_ARC_BROKEN_SUM;  break;\r
523         default:                                                       this->nErrorCode = TPI_ERROR_UNDEFINED;       break;\r
524         }\r
525 \r
526         // 時刻を記録。\r
527         if (_outFileStream != NULL)\r
528         {\r
529                 FILETIME ftAccess, ftCreate, ftModified;\r
530                 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmAccess.GetTicks(),   ftAccess);\r
531                 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmCreate.GetTicks(),   ftCreate);\r
532                 NWindows::NTime::UnixTimeToFileTime(this->piInfo.fiInfo.tmModified.GetTicks(), ftModified);\r
533                 _outFileStreamSpec->SetTime(& ftCreate, & ftAccess, & ftModified);\r
534                 _outFileStreamSpec->Close();\r
535         }\r
536         _outFileStream.Release();\r
537 \r
538         // 属性を記録。\r
539         if (this->nMode == NArchive::NExtract::NAskMode::kExtract)\r
540         {\r
541                 chmod(this->piInfo.fnDestination.GetFullPath().ToUTF8(), this->piInfo.fiInfo.wPermission);\r
542 #ifdef __WINDOWS__\r
543                 NWindows::NFile::NDirectory::MySetFileAttributes(this->piInfo.fnDestination.GetFullPath(), this->piInfo.fiInfo.dwAttribute);\r
544 #endif\r
545         }\r
546 \r
547         return S_OK;\r
548 }\r
549 \r
550 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR * szPassword)\r
551 {\r
552         if (this->fTriedPassword || this->swInfo->szPassword.IsEmpty())\r
553         {\r
554                 this->piInfo.eMessage           = TPI_MESSAGE_ASK;\r
555                 this->piInfo.eStatus            = TPI_PARAM_PASSWORD;\r
556                 // 次のファイル名が取得できないので、とりあえず空にしておく。\r
557                 this->piInfo.fiInfo.fnFileName.Clear();\r
558                 return (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE) ? ::StringToBstr(this->piInfo.szParam.c_str(), szPassword) : E_ABORT;\r
559         }\r
560         else\r
561         {\r
562                 // 既定のパスワードがある場合はまずそれを試す。\r
563                 this->fTriedPassword = true;\r
564                 return ::StringToBstr(this->swInfo->szPassword, szPassword);\r
565         }\r
566 }\r
567 \r
568 // CArchiveUpdateCallback\r
569 class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp\r
570 {\r
571 public:\r
572         MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)\r
573         INTERFACE_IArchiveUpdateCallback2(;)\r
574         STDMETHOD(CryptoGetTextPassword2)(int * nPasswordIsDefined, BSTR * szPassword);\r
575         CArchiveUpdateCallback(TPI_SWITCHES *, CObjectVector<NWindows::NFile::NFind::CFileInfoW> *);\r
576 \r
577         const CObjectVector<NWindows::NFile::NFind::CFileInfoW> * fiItems;\r
578         int nErrorCode;\r
579 \r
580 private:\r
581         wxULongLong_t nCurrentPos;\r
582         TPI_PROCESSINFO piInfo;\r
583         TPI_SWITCHES * swInfo;\r
584 };\r
585 \r
586 CArchiveUpdateCallback::CArchiveUpdateCallback(TPI_SWITCHES * swInfo, CObjectVector<NWindows::NFile::NFind::CFileInfoW> * fiItems)\r
587 {\r
588         this->swInfo = swInfo;\r
589         this->fiItems = fiItems;\r
590 }\r
591 \r
592 STDMETHODIMP CArchiveUpdateCallback::SetTotal(wxULongLong_t)\r
593 {\r
594         return S_OK;\r
595 }\r
596 \r
597 STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const wxULongLong_t * nProcessed)\r
598 {\r
599         this->piInfo.eStatus            = TPI_STATUS_INPROCESS;\r
600         this->piInfo.nProcessedSize     = * nProcessed - this->nCurrentPos;\r
601         if (g_prProc == NULL || this->piInfo.fiInfo.szStoredName.IsEmpty() || g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) == TPI_CALLBACK_CONTINUE)\r
602         {\r
603                 return S_OK;\r
604         }\r
605         else\r
606         {\r
607                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
608                 return E_ABORT;\r
609         }\r
610 }\r
611 \r
612 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(unsigned int /* index */, int *newData, int *newProperties, unsigned int *indexInArchive)\r
613 {\r
614         if (newData != NULL)\r
615         {\r
616                 * newData = 1;\r
617         }\r
618         if (newProperties != NULL)\r
619         {\r
620                 * newProperties = 1;\r
621         }\r
622         if (indexInArchive != NULL)\r
623         {\r
624                 * indexInArchive = (unsigned) -1;\r
625         }\r
626         return S_OK;\r
627 }\r
628 \r
629 STDMETHODIMP CArchiveUpdateCallback::GetProperty(unsigned int nIndex, PROPID propID, PROPVARIANT * value)\r
630 {\r
631         NWindows::NCOM::CPropVariant prop;\r
632         if (propID == kpidIsAnti)\r
633         {\r
634                 prop = false;\r
635                 prop.Detach(value);\r
636                 return S_OK;\r
637         }\r
638 \r
639         const NWindows::NFile::NFind::CFileInfoW fiItem = (* this->fiItems)[nIndex];\r
640         switch (propID)\r
641         {\r
642                 case kpidPath:  prop = fiItem.Name;  break;\r
643                 case kpidIsDir: prop = (unsigned int) fiItem.Attrib & TPI_ATTRIBUTE_DIRECTORY ? true : false; break;\r
644                 case kpidSize:  prop = fiItem.Size;  break;\r
645                 case kpidAttrib:prop = (unsigned int) fiItem.Attrib;break;\r
646                 case kpidCTime: prop = fiItem.CTime; break;\r
647                 case kpidATime: prop = fiItem.ATime; break;\r
648                 case kpidMTime: prop = fiItem.MTime; break;\r
649         }\r
650         prop.Detach(value);\r
651         return S_OK;\r
652 }\r
653 \r
654 STDMETHODIMP CArchiveUpdateCallback::GetStream(unsigned int nIndex, ISequentialInStream ** inStream)\r
655 {\r
656         // 前のファイルの処理の終了を通知。\r
657         this->nCurrentPos += this->piInfo.fiInfo.nUnpackedSize;\r
658         this->piInfo.eMessage               = TPI_MESSAGE_STATUS;\r
659         if (this->nCurrentPos != 0)\r
660         {\r
661                 this->piInfo.eStatus            = TPI_STATUS_ENDPROCESS;\r
662                 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
663                 {\r
664                         this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
665                         return E_ABORT;\r
666                 }\r
667         }\r
668 \r
669         // ファイルの基本情報を取得。\r
670         NWindows::NCOM::CPropVariant prop;\r
671         this->GetProperty(nIndex, kpidAttrib, & prop);\r
672         this->piInfo.fiInfo.dwAttribute     = prop.uintVal;\r
673         this->GetProperty(nIndex, kpidSize, & prop);\r
674         this->piInfo.fiInfo.nUnpackedSize   = prop.vt == VT_UI8 ? prop.uhVal.QuadPart : prop.ulVal;\r
675         unsigned int t;\r
676         this->GetProperty(nIndex, kpidMTime, & prop);\r
677         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
678         this->piInfo.fiInfo.tmModified.Set((time_t) t);\r
679         this->GetProperty(nIndex, kpidCTime, & prop);\r
680         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
681         this->piInfo.fiInfo.tmCreate.Set((time_t) t);\r
682         this->GetProperty(nIndex, kpidATime, & prop);\r
683         NWindows::NTime::FileTimeToUnixTime(prop.filetime, t);\r
684         this->piInfo.fiInfo.tmAccess.Set((time_t) t);\r
685         this->GetProperty(nIndex, kpidPath, & prop);\r
686         this->piInfo.fiInfo.szStoredName = WC2String(prop.bstrVal);\r
687         this->piInfo.fiInfo.nFileId         = nIndex;\r
688         this->piInfo.fiInfo.fnFileName      = wxFileName(this->piInfo.fiInfo.szStoredName);\r
689         this->piInfo.fiInfo.fnFileName.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, this->swInfo->fnDestinationDirectory.GetFullPath());\r
690         this->piInfo.eStatus                = TPI_STATUS_BEGINPROCESS;\r
691         this->piInfo.fnDestination          = wxFileName(this->piInfo.fiInfo.szStoredName);\r
692 \r
693         // コールバック関数に送信。\r
694         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & this->piInfo) != TPI_CALLBACK_CONTINUE)\r
695         {\r
696                 this->nErrorCode = TPI_ERROR_D_SKIPPED;\r
697                 return E_ABORT;\r
698         }\r
699 \r
700         if (this->piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
701         {\r
702                 return S_OK;\r
703         }\r
704 \r
705         CInFileStream * inStreamSpec = new CInFileStream;\r
706         CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
707         if (! inStreamSpec->Open(this->piInfo.fiInfo.fnFileName.GetFullPath().c_str()))\r
708         {\r
709                 this->nErrorCode = TPI_ERROR_IO_FILE_OPEN;\r
710                 return S_FALSE;\r
711         }\r
712 \r
713         * inStream = inStreamLoc.Detach();\r
714         return S_OK;\r
715 }\r
716 \r
717 STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(int nResult)\r
718 {\r
719         switch (nResult)\r
720         {\r
721         case NArchive::NUpdate::NOperationResult::kOK:                 this->nErrorCode = TPI_ERROR_SUCCESS;         break;\r
722         case NArchive::NUpdate::NOperationResult::kError:\r
723         default:                                                       this->nErrorCode = TPI_ERROR_UNDEFINED;       break;\r
724         }\r
725         return S_OK;\r
726 }\r
727 \r
728 STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(unsigned int, wxULongLong_t * nSplitSize)\r
729 {\r
730         * nSplitSize = this->swInfo->nSplitSize;\r
731         return S_OK;\r
732 }\r
733 \r
734 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(unsigned int nIndex, ISequentialOutStream ** volumeStream)\r
735 {\r
736         COutFileStream * streamSpec = new COutFileStream;\r
737         CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);\r
738         if (! streamSpec->Create(this->piInfo.fiInfo.fnFileName.GetFullPath() + wxString::Format(wxT(".%03d"), nIndex + 1), false))\r
739         {\r
740                 return TPI_ERROR_IO_ARC_OPEN;\r
741         }\r
742         * volumeStream = streamLoc.Detach();\r
743         return S_OK;\r
744 }\r
745 \r
746 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(int * nPasswordIsDefined, BSTR * szPassword)\r
747 {\r
748         * nPasswordIsDefined = ! this->swInfo->szPassword.IsEmpty();\r
749         return ::StringToBstr(this->swInfo->szPassword.c_str(), szPassword);\r
750 }\r
751 \r
752 //******************************************************************************\r
753 //    Functions\r
754 //******************************************************************************\r
755 \r
756 #ifdef __cplusplus\r
757 extern "C"\r
758 {\r
759 #endif\r
760 \r
761 int __stdcall GetPluginInformation\r
762 (\r
763         unsigned int _uInfoId,\r
764         wxULongLong_t,\r
765         void * _pPtr\r
766 )\r
767 {\r
768         if (_pPtr == NULL)\r
769         {\r
770                 return TPI_ERROR_D_PARAMETER;\r
771         }\r
772         switch (_uInfoId)\r
773         {\r
774         case TPI_INFO_VERSION_MAJOR:\r
775         case TPI_INFO_VERSION_MINOR:\r
776                 * (int *) _pPtr = 0;\r
777                 break;\r
778         case TPI_INFO_VERSION_API:\r
779                 * (int *) _pPtr = 2;\r
780                 break;\r
781         default:\r
782                 return TPI_ERROR_D_UNSUPPORTED;\r
783         }\r
784         return TPI_ERROR_SUCCESS;\r
785 }\r
786 \r
787 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
788 {\r
789         static wxULongLong_t s_nTypeId;\r
790         if (_bFirst)\r
791         {\r
792                 s_nTypeId = 0;\r
793         }\r
794         return GetFormatInformation2(_fiInfo, s_nTypeId);\r
795 }\r
796 \r
797 int __stdcall LoadPlugin\r
798 (\r
799         const wxString & _szArcName,\r
800         wxULongLong_t _nTypeId\r
801 )\r
802 {\r
803         ::RemoveCwdFromSearchPath();\r
804 #ifdef __LINUX__\r
805         global_use_utf16_conversion = 1;\r
806 #endif\r
807         g_hLib.Load(LIB_NAME);\r
808         if (! g_hLib.IsLoaded())\r
809         {\r
810                 g_hLib.Unload();\r
811                 return TPI_ERROR_U_LOAD_LIBRARY;\r
812         }\r
813 \r
814         if (! g_hLib.HasSymbol(wxT("CreateObject")))\r
815         {\r
816                 return TPI_ERROR_U_USE_LIBRARY;\r
817         }\r
818         g_fpProc = g_hLib.GetSymbol(wxT("CreateObject"));\r
819         if (! g_fpProc)\r
820         {\r
821                 return TPI_ERROR_U_USE_LIBRARY;\r
822         }\r
823 \r
824         if (! ::wxFileExists(_szArcName))\r
825         {\r
826                 g_nEngineId = _nTypeId;\r
827         }\r
828 \r
829         return TPI_ERROR_SUCCESS;\r
830 }\r
831 \r
832 int __stdcall FreePlugin\r
833 (\r
834         void * // _pReserved\r
835 )\r
836 {\r
837         g_hLib.Unload();\r
838         return TPI_ERROR_SUCCESS;\r
839 }\r
840 \r
841 int __stdcall OpenArchive\r
842 (\r
843         const wxString & _szArcName,\r
844         void * * _hArchive,\r
845         wxULongLong_t * _nFileCount\r
846 )\r
847 {\r
848         // ***.tar.xxxは不便なので弾く。\r
849         wxString s = _szArcName.BeforeLast(wxT('.'));\r
850         if (s.Find(wxT('.')) != wxNOT_FOUND && s.AfterLast(wxT('.')) == wxT("tar"))\r
851         {\r
852                 return TPI_ERROR_IO_ARC_OPEN;\r
853         }\r
854 \r
855         // 書庫形式を認識。\r
856         IInArchive * hArc;\r
857         for (wxULongLong_t i = 0; i < sizeof(guidList) / sizeof(GUID); )\r
858         {\r
859                 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void * *)) g_fpProc)(& guidList[i], & IID_IInArchive, (void **) & hArc) != S_OK)\r
860                 {\r
861                         i++;\r
862                         continue;\r
863                 }\r
864 \r
865                 // 書庫を開く。\r
866                 CInFileStream * fileSpec = new CInFileStream;\r
867                 CMyComPtr<IInStream> file = fileSpec;\r
868                 if (! fileSpec->Open(_szArcName.c_str()))\r
869                 {\r
870                         return TPI_ERROR_IO_ARC_OPEN;\r
871                 }\r
872 \r
873                 // 形式の情報を取得。\r
874                 g_nEngineId = i;\r
875                 TPI_FORMATINFO fiInfo;\r
876                 GetFormatInformation2(& fiInfo, i);\r
877 \r
878                 // 書庫として開く。\r
879                 CArchiveOpenCallback * openCallbackSpec = new CArchiveOpenCallback;\r
880                 CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);\r
881                 // SFXを完全に検出するには全体をロードする必要がある。\r
882                 wxULongLong_t nMax = fiInfo.fSFX ? 262114 : 1024;\r
883 /*\r
884                 if (fiInfo.fSFX)\r
885                 {\r
886                         fileSpec->GetSize(& nMax);\r
887                 }\r
888 */\r
889                 if (hArc->Open(file, & nMax, openCallback) == S_OK)\r
890                 {\r
891                         if (_nFileCount != NULL)\r
892                         {\r
893                                 unsigned int n;\r
894                                 hArc->GetNumberOfItems(& n);\r
895                                 * _nFileCount = n;\r
896                         }\r
897                         * _hArchive = hArc;\r
898                         return TPI_ERROR_SUCCESS;\r
899                 }\r
900         }\r
901         return TPI_ERROR_IO_ARC_OPEN;\r
902 }\r
903 \r
904 int __stdcall CloseArchive\r
905 (\r
906         void * _hArchive\r
907 )\r
908 {\r
909     IInArchive * hArc = (IInArchive *) _hArchive;\r
910         hArc->Close();\r
911         hArc->Release();\r
912         return TPI_ERROR_SUCCESS;\r
913 }\r
914 \r
915 int __stdcall GetFileInformation\r
916 (\r
917         void * _hArchive,\r
918         TPI_FILEINFO * _fiInfo,\r
919         bool _bFirst\r
920 )\r
921 {\r
922         static unsigned int s_uFileId, s_uFileCount;\r
923         if (_bFirst)\r
924         {\r
925                 s_uFileId = 0;\r
926                 ((IInArchive *) _hArchive)->GetNumberOfItems(& s_uFileCount);\r
927         }\r
928 \r
929         if (s_uFileId >= s_uFileCount)\r
930         {\r
931                 return TPI_ERROR_S_ENDOFDATA;\r
932         }\r
933 \r
934         return GetFileInformation2(_hArchive, _fiInfo, s_uFileId++);\r
935 }\r
936 \r
937 int __stdcall GetArchiveInformation\r
938 (\r
939         void * _hArchive,\r
940         TPI_ARCHIVEINFO * _aiInfo\r
941 )\r
942 {\r
943     IInArchive * hArc = (IInArchive *) _hArchive;\r
944         NWindows::NCOM::CPropVariant prop;\r
945         hArc->GetArchiveProperty(kpidSolid, & prop);\r
946         _aiInfo->fSolid         = VARIANT_BOOLToBool(prop.boolVal);\r
947         hArc->GetArchiveProperty(kpidComment, & prop);\r
948         if (prop.vt == VT_BSTR)\r
949         {\r
950                 _aiInfo->szComment  = WC2String(prop.bstrVal);\r
951         }\r
952         wxULongLong_t n = g_nEngineId;\r
953         GetFormatInformation2(& _aiInfo->fiInfo, n);\r
954         return TPI_ERROR_SUCCESS;\r
955 }\r
956 \r
957 int __stdcall Command\r
958 (\r
959         wxULongLong_t _eCommand,\r
960         TPI_SWITCHES * _swInfo,\r
961         const wxString & _szArcName,\r
962         const wxArrayString & _szFiles\r
963 )\r
964 {\r
965         // コマンドを実行。\r
966         int nErrorCode;\r
967         switch (_eCommand)\r
968         {\r
969         case TPI_COMMAND_EXTRACT:\r
970         case TPI_COMMAND_TEST:\r
971         {\r
972                 // 開きなおす。\r
973                 IInArchive * hArc;\r
974                 nErrorCode = OpenArchive(_szArcName, (void **) & hArc);\r
975                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
976                 {\r
977                         return nErrorCode;\r
978                 }\r
979 \r
980                 // ファイル名からインデックスを取得。\r
981                 TPI_FILEINFO fiInfo;\r
982                 CRecordVector<unsigned int> nIndexes;\r
983                 wxFileName fnArchive = wxFileName(_szArcName);\r
984                 if (GetFileInformation(hArc, & fiInfo, true) == TPI_ERROR_SUCCESS)\r
985                 {\r
986                         do\r
987                         {\r
988                                 if (fiInfo.szStoredName.IsEmpty())\r
989                                 {\r
990                                         fiInfo.szStoredName = fnArchive.GetName();\r
991                                         if (fiInfo.fnFileName.HasExt())\r
992                                         {\r
993                                                 fiInfo.szStoredName += wxT('.') + fiInfo.fnFileName.GetExt();\r
994                                         }\r
995                                 }\r
996                                 if (_szFiles.Index(fiInfo.szStoredName) != wxNOT_FOUND)\r
997                                 {\r
998                                         nIndexes.Add(fiInfo.nFileId);\r
999                                 }\r
1000                         }\r
1001                         while (GetFileInformation(hArc, & fiInfo) == TPI_ERROR_SUCCESS);\r
1002                 }\r
1003 \r
1004                 CArchiveExtractCallback * extractCallbackSpec = new CArchiveExtractCallback(hArc,_swInfo);\r
1005                 extractCallbackSpec->fnArchive = fnArchive;\r
1006                 CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);\r
1007                 hArc->Extract(& nIndexes.Front(), nIndexes.Size(), _eCommand == TPI_COMMAND_TEST, extractCallback);\r
1008                 nErrorCode = extractCallbackSpec->nErrorCode;\r
1009                 CloseArchive(hArc);\r
1010                 break;\r
1011         }\r
1012         case TPI_COMMAND_CREATE:\r
1013 //      case TPI_COMMAND_ADD:\r
1014         {\r
1015                 // 入力リストを作成。\r
1016                 CObjectVector<NWindows::NFile::NFind::CFileInfoW> fiItems;\r
1017                 for (unsigned int i = 0; i < _szFiles.GetCount(); i++)\r
1018                 {\r
1019                         NWindows::NFile::NFind::CFileInfoW fi;\r
1020                         wxFileName fn(_szFiles[i]);\r
1021                         fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG, _swInfo->fnDestinationDirectory.GetFullPath());\r
1022                         if (! fi.Find(fn.GetFullPath().c_str()))\r
1023                         {\r
1024                                 return TPI_ERROR_IO_FILE_ACCESS;\r
1025                         }\r
1026                         fiItems.Add(fi);\r
1027                 }\r
1028 \r
1029                 // 書庫を作成。\r
1030                 COutFileStream * outFileStreamSpec = new COutFileStream;\r
1031                 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;\r
1032                 if (! outFileStreamSpec->Create(_szArcName.c_str(), false))\r
1033                 {\r
1034                         return TPI_ERROR_IO_ARC_OPEN;\r
1035                 }\r
1036 \r
1037                 // エンジンを読み込み。\r
1038                 IOutArchive * hArc;\r
1039                 if (((unsigned int (__stdcall *)(const GUID *, const GUID *, void **)) g_fpProc)(& guidList[g_nEngineId], & IID_IOutArchive, (void **) & hArc) != S_OK)\r
1040                 {\r
1041                         return TPI_ERROR_ARC_UNSUPPORTED;\r
1042                 }\r
1043 \r
1044                 // 形式情報を取得。\r
1045                 TPI_FORMATINFO fiInfo;\r
1046                 wxULongLong_t nIndex = g_nEngineId;\r
1047                 GetFormatInformation2(& fiInfo, nIndex);\r
1048 \r
1049                 // パラメータを設定。\r
1050                 ISetProperties * setProp;\r
1051                 if (hArc->QueryInterface(IID_ISetProperties, (void **) & setProp) == S_OK)\r
1052                 {\r
1053                         CRecordVector<const wchar_t *> szProps;\r
1054                         NWindows::NCOM::CPropVariant propValues[15];\r
1055                         wxString szProp;\r
1056                         // 圧縮レベル。\r
1057                         if (fiInfo.nCompressLevelMin != fiInfo.nCompressLevelMax)\r
1058                         {\r
1059                                 szProp = wxString::Format(wxT("x%d"), _swInfo->nCompressLevel);\r
1060                                 szProps.Add(szProp.c_str());\r
1061                         }\r
1062                         // Solid圧縮。\r
1063                         if (fiInfo.fSolid)\r
1064                         {\r
1065                                 propValues[szProps.Size()] = _swInfo->fSolid;\r
1066                                 szProps.Add(wxT("s"));\r
1067                         }\r
1068                         // ヘッダ圧縮。\r
1069                         if (fiInfo.fCompressHeader)\r
1070                         {\r
1071                                 propValues[szProps.Size()] = _swInfo->fCompressHeader;\r
1072                                 szProps.Add(wxT("hc"));\r
1073                         }\r
1074                         // ヘッダ暗号化。\r
1075                         if (fiInfo.fEncryptHeader)\r
1076                         {\r
1077                                 propValues[szProps.Size()] = _swInfo->fEncryptHeader;\r
1078                                 szProps.Add(wxT("he"));\r
1079                         }\r
1080 \r
1081 //                      szProp = wxString::Format(wxT("m"));\r
1082 //                      propValues[szProps.Size()] = L"Deflate";\r
1083 //                      szProps.Add(szProp.c_str());\r
1084 \r
1085 //                      szProp = wxString::Format(wxT("fb%d"), );\r
1086 //                      szProps.Add(szProp.c_str());\r
1087 \r
1088                         setProp->SetProperties(& szProps.Front(), propValues, szProps.Size());\r
1089                 }\r
1090 \r
1091                 // 更新処理を実行。\r
1092                 CArchiveUpdateCallback * updateCallbackSpec = new CArchiveUpdateCallback(_swInfo, & fiItems);\r
1093                 CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);\r
1094                 hArc->UpdateItems(outFileStream, fiItems.Size(), updateCallback);\r
1095                 nErrorCode = updateCallbackSpec->nErrorCode;\r
1096                 break;\r
1097         }\r
1098         default:\r
1099                 nErrorCode = TPI_ERROR_D_UNSUPPORTED;\r
1100         }\r
1101         return nErrorCode;\r
1102 }\r
1103 \r
1104 int __stdcall SetCallbackProc\r
1105 (\r
1106         TPI_PROC _prArcProc\r
1107 )\r
1108 {\r
1109         // ポインタを保存。\r
1110         if (_prArcProc == NULL)\r
1111         {\r
1112                 return TPI_ERROR_D_PARAMETER;\r
1113         }\r
1114         g_prProc = * _prArcProc;\r
1115 \r
1116         return TPI_ERROR_SUCCESS;\r
1117 }\r
1118 \r
1119 #ifdef __cplusplus\r
1120 }\r
1121 #endif\r