OSDN Git Service

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