OSDN Git Service

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