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