OSDN Git Service

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