OSDN Git Service

コメントのバッファを確保し忘れていたのを修正。wxULongLong_tの作成方法を簡略化。
[tpi/lychee.git] / src / plugin / rarArc / rarArc.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 "rarArc.h"\r
32 \r
33 //******************************************************************************\r
34 //    Global varients\r
35 //******************************************************************************\r
36 \r
37 wxDynamicLibrary g_hLib;\r
38 TPI_PROC g_prProc;\r
39 char g_szComment[64001];\r
40 RAROpenArchiveDataEx g_oaInfo;\r
41 RARHeaderDataEx * g_hdInfo;\r
42 \r
43 //******************************************************************************\r
44 //    Callback Wrapper\r
45 //******************************************************************************\r
46 \r
47 int __stdcall CallbackProc(unsigned int msg, long, long P1, long P2)\r
48 {\r
49         // 構造体を初期化。\r
50         static TPI_PROCESSINFO piInfo;\r
51 \r
52         switch (msg)\r
53         {\r
54         case UCM_CHANGEVOLUME:\r
55                 switch (P2)\r
56                 {\r
57                 case RAR_VOL_ASK:\r
58                         // 分割書庫の次の部分を要求。\r
59                         piInfo.eMessage = TPI_MESSAGE_ASK;\r
60                         piInfo.eStatus  = TPI_PARAM_NEXTVOLUME;\r
61                         piInfo.szParam.Empty();\r
62                         break;\r
63                 case RAR_VOL_NOTIFY:\r
64                         // 分割部分の読み込みを開始。\r
65                         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
66                         piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
67                         piInfo.fiInfo.fnFileName = wxFileName(UTF82String((char *) P1));\r
68                         break;\r
69                 default:\r
70                         return 1;\r
71                 }\r
72                 break;\r
73         case UCM_PROCESSDATA:\r
74                 piInfo.eMessage = TPI_MESSAGE_STATUS;\r
75                 piInfo.eStatus  = TPI_STATUS_INPROCESS;\r
76                 piInfo.nProcessedSize += P2;\r
77                 break;\r
78         case UCM_NEEDPASSWORD:\r
79                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
80                 piInfo.eStatus  = TPI_PARAM_PASSWORD;\r
81                 piInfo.szParam.Empty();\r
82                 break;\r
83         default:\r
84                 return 1;\r
85         }\r
86 \r
87         // コールバック関数に送信。\r
88         if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, & piInfo) == TPI_CALLBACK_CONTINUE)\r
89         {\r
90                 if (msg != UCM_PROCESSDATA && P2 != RAR_VOL_NOTIFY)\r
91                 {\r
92                         strncpy((char *) P1, piInfo.szParam.char_str(), (msg == UCM_CHANGEVOLUME ? 1024 : P2) - 1);\r
93                 }\r
94                 return 1;\r
95         }\r
96         else\r
97         {\r
98                 return -1;\r
99         }\r
100 }\r
101 \r
102 //******************************************************************************\r
103 //    Inside Functions\r
104 //******************************************************************************\r
105 \r
106 int ErrorCodeConvert(int nErrorCode)\r
107 {\r
108         switch (nErrorCode)\r
109         {\r
110         case 0:                     return TPI_ERROR_SUCCESS;\r
111         case 1:                     return TPI_ERROR_SUCCESS;\r
112         case ERAR_END_ARCHIVE:      return TPI_ERROR_S_ENDOFDATA;\r
113         case ERAR_NO_MEMORY:        return TPI_ERROR_D_OUTOFMEMORY;\r
114         case ERAR_BAD_DATA:         return TPI_ERROR_ARC_BROKEN_MISC;\r
115         case ERAR_BAD_ARCHIVE:      return TPI_ERROR_ARC_UNSUPPORTED;\r
116         case ERAR_UNKNOWN_FORMAT:   return TPI_ERROR_ARC_ENCRYPTED;\r
117         case ERAR_EOPEN:            return TPI_ERROR_IO_ARC_OPEN;\r
118         case ERAR_ECREATE:          return TPI_ERROR_IO_FILE_OPEN;\r
119         case ERAR_ECLOSE:           return TPI_ERROR_IO_CLOSE;\r
120         case ERAR_EREAD:            return TPI_ERROR_IO_ARC_READ;\r
121         case ERAR_EWRITE:           return TPI_ERROR_IO_FILE_WRITE;\r
122         case ERAR_SMALL_BUF:        return TPI_ERROR_UNDEFINED;\r
123         case ERAR_UNKNOWN:          return TPI_ERROR_UNDEFINED;\r
124         case ERAR_MISSING_PASSWORD: return TPI_ERROR_ARC_ENCRYPTED;\r
125         default:                    return TPI_ERROR_UNDEFINED;\r
126         }\r
127 }\r
128 \r
129 //******************************************************************************\r
130 //    Functions\r
131 //******************************************************************************\r
132 \r
133 #ifdef __cplusplus\r
134 extern "C"\r
135 {\r
136 #endif\r
137 \r
138 int __stdcall GetPluginInformation\r
139 (\r
140         unsigned int _uInfoId,\r
141         wxULongLong_t,\r
142         void * _pPtr\r
143 )\r
144 {\r
145         if (_pPtr == NULL)\r
146         {\r
147                 return TPI_ERROR_D_PARAMETER;\r
148         }\r
149         switch (_uInfoId)\r
150         {\r
151         case TPI_INFO_VERSION_MAJOR:\r
152         case TPI_INFO_VERSION_MINOR:\r
153                 * (int *) _pPtr = 0;\r
154                 break;\r
155         case TPI_INFO_VERSION_API:\r
156                 * (int *) _pPtr = 2;\r
157                 break;\r
158         default:\r
159                 return TPI_ERROR_D_UNSUPPORTED;\r
160         }\r
161         return TPI_ERROR_SUCCESS;\r
162 }\r
163 \r
164 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
165 {\r
166         if (! _bFirst)\r
167         {\r
168                 return TPI_ERROR_S_ENDOFDATA;\r
169         }\r
170 \r
171         _fiInfo->szTypeName   = wxT("RAR");\r
172         _fiInfo->szSuffix     = wxT("rar");\r
173         _fiInfo->szEngineName = g_hLib.CanonicalizeName(wxT("unrar"));\r
174         _fiInfo->szTPIName    = wxT("rarArc");\r
175         _fiInfo->nTypeId      = 0;\r
176         _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;\r
177         _fiInfo->fArchive     = true;\r
178         _fiInfo->fComment     = true;\r
179         _fiInfo->fSFX         = true;\r
180         _fiInfo->fSolid       = true;\r
181         _fiInfo->fEncryptPassword = true;\r
182         _fiInfo->fMultiVolume = true;\r
183 \r
184         return TPI_ERROR_SUCCESS;\r
185 }\r
186 \r
187 int __stdcall LoadPlugin\r
188 (\r
189         const wxString &,\r
190         wxULongLong_t\r
191 )\r
192 {\r
193         g_hLib.Load(g_hLib.CanonicalizeName(wxT("unrar")));\r
194         if (! g_hLib.IsLoaded())\r
195         {\r
196                 g_hLib.Unload();\r
197                 return TPI_ERROR_U_LOAD_LIBRARY;\r
198         }\r
199 \r
200         return TPI_ERROR_SUCCESS;\r
201 }\r
202 \r
203 int __stdcall FreePlugin\r
204 (\r
205         void * // _pReserved\r
206 )\r
207 {\r
208         g_hLib.Unload();\r
209         return TPI_ERROR_SUCCESS;\r
210 }\r
211 \r
212 int __stdcall CheckArchive\r
213 (\r
214         const wxString & _szArcName,\r
215         wxULongLong_t * _llFileCount\r
216 )\r
217 {\r
218         void * _hArchive;\r
219         int nErrorCode = OpenArchive(_szArcName, & _hArchive);\r
220         if (nErrorCode != TPI_ERROR_SUCCESS)\r
221         {\r
222                 return nErrorCode;\r
223         }\r
224 \r
225         if (_llFileCount != NULL)\r
226         {\r
227                 * _llFileCount = 1;\r
228         }\r
229 \r
230         return CloseArchive(_hArchive);\r
231 }\r
232 \r
233 int __stdcall OpenArchive\r
234 (\r
235         const wxString & _szArcName,\r
236         void * * _hArchive\r
237 )\r
238 {\r
239         if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))\r
240         {\r
241                 return TPI_ERROR_U_USE_LIBRARY;\r
242         }\r
243         void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));\r
244         if (! p)\r
245         {\r
246                 return TPI_ERROR_U_USE_LIBRARY;\r
247         }\r
248 \r
249         memset(& g_oaInfo, 0, sizeof(g_oaInfo));\r
250         g_oaInfo.ArcName    = NULL;\r
251         g_oaInfo.ArcNameW   = (wchar_t *) malloc((_szArcName.Len() + 1) * sizeof(wchar_t));\r
252         wcscpy(g_oaInfo.ArcNameW, _szArcName.wchar_str());\r
253         g_oaInfo.OpenMode   = RAR_OM_EXTRACT;\r
254         g_oaInfo.CmtBuf     = g_szComment;\r
255         g_oaInfo.CmtBufSize = sizeof(g_szComment) - 1;\r
256         * _hArchive = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& g_oaInfo);\r
257         free(g_oaInfo.ArcNameW);\r
258         if (* _hArchive == NULL)\r
259         {\r
260                 return TPI_ERROR_UNDEFINED;\r
261         }\r
262         int nErrorCode = ErrorCodeConvert(g_oaInfo.OpenResult);\r
263         if (nErrorCode != TPI_ERROR_SUCCESS)\r
264         {\r
265                 return nErrorCode;\r
266         }\r
267 \r
268         // コールバック関数を設定。\r
269         if (! g_hLib.HasSymbol(wxT("RARSetCallback")))\r
270         {\r
271                 return TPI_ERROR_U_USE_LIBRARY;\r
272         }\r
273         p = g_hLib.GetSymbol(wxT("RARSetCallback"));\r
274         if (! p)\r
275         {\r
276                 return TPI_ERROR_U_USE_LIBRARY;\r
277         }\r
278         ((void (__stdcall *)(void *, void *, long)) p)(* _hArchive, (void *) CallbackProc, (long) & g_hdInfo);\r
279 \r
280         return TPI_ERROR_SUCCESS;\r
281 }\r
282 \r
283 int __stdcall CloseArchive\r
284 (\r
285         void * _hArchive\r
286 )\r
287 {\r
288         if (! g_hLib.HasSymbol(wxT("RARCloseArchive")))\r
289         {\r
290                 return TPI_ERROR_U_USE_LIBRARY;\r
291         }\r
292         void * p = g_hLib.GetSymbol(wxT("RARCloseArchive"));\r
293         return (! p || _hArchive == NULL) ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((int (__stdcall *)(void *)) p)(_hArchive));\r
294 }\r
295 \r
296 int __stdcall GetFileInformation\r
297 (\r
298         void * _hArchive,\r
299         TPI_FILEINFO * _fiInfo,\r
300         bool _bFirst\r
301 )\r
302 {\r
303         static wxULongLong_t s_nFileId;\r
304         static void * pR, * pP;\r
305         int nErrorCode;\r
306 \r
307         if (_bFirst)\r
308         {\r
309                 s_nFileId = 0;\r
310                 pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL;\r
311                 pP = g_hLib.HasSymbol(wxT("RARProcessFileW"))  ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
312                 if (! pR || ! pP)\r
313                 {\r
314                         return TPI_ERROR_U_USE_LIBRARY;\r
315                 }\r
316         }\r
317 \r
318         RARHeaderDataEx hdInfo;\r
319         char szComment[64001];\r
320         hdInfo.CmtBuf     = szComment;\r
321         hdInfo.CmtBufSize = sizeof(szComment) - 1;\r
322         nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(_hArchive, & hdInfo));\r
323         if (nErrorCode == TPI_ERROR_SUCCESS)\r
324         {\r
325                 _fiInfo->dwAttribute    = hdInfo.FileAttr;\r
326                 if (hdInfo.Flags & 0x04)\r
327                 {\r
328                         _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
329                 }\r
330                 _fiInfo->dwCRC32        = hdInfo.FileCRC;\r
331                 _fiInfo->nPackedSize    = hdInfo.PackSizeHigh;\r
332                 _fiInfo->nPackedSize    = _fiInfo->nPackedSize << 32;\r
333                 _fiInfo->nPackedSize   += hdInfo.PackSize;\r
334                 _fiInfo->nUnpackedSize  = hdInfo.UnpSizeHigh;\r
335                 _fiInfo->nUnpackedSize  = _fiInfo->nUnpackedSize << 32;\r
336                 _fiInfo->nUnpackedSize += hdInfo.UnpSize;\r
337                 _fiInfo->tmModified.SetFromDOS(hdInfo.FileTime);\r
338                 _fiInfo->eOSType        = hdInfo.HostOS;\r
339                 _fiInfo->szStoredName   = WC2String(hdInfo.FileNameW);\r
340                 _fiInfo->szMethod.Printf(wxT("%x"), hdInfo.Method);\r
341                 _fiInfo->szComment      = UTF82String(hdInfo.CmtBuf);\r
342                 _fiInfo->nFileId        = s_nFileId++;\r
343                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName);\r
344 \r
345                 // 次のファイルへ。\r
346                 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(_hArchive, RAR_SKIP, NULL, NULL));\r
347         }\r
348 \r
349         return nErrorCode;\r
350 }\r
351 \r
352 int __stdcall GetArchiveInformation\r
353 (\r
354         void *,\r
355         TPI_ARCHIVEINFO * _aiInfo\r
356 )\r
357 {\r
358         _aiInfo->fSolid         = (g_oaInfo.Flags & 0x0008) == 1;\r
359         _aiInfo->fEncryptHeader = (g_oaInfo.Flags & 0x0080) == 1;\r
360         _aiInfo->szComment      = UTF82String(g_szComment);\r
361         GetFormatInformation(& _aiInfo->fiInfo, true);\r
362         return TPI_ERROR_SUCCESS;\r
363 }\r
364 \r
365 int __stdcall Command\r
366 (\r
367         wxULongLong_t _eCommand,\r
368         TPI_SWITCHES * _swInfo,\r
369         const wxString & _szArcName,\r
370         const wxArrayString & _szFiles\r
371 )\r
372 {\r
373         if (_eCommand != TPI_COMMAND_EXTRACT && _eCommand != TPI_COMMAND_TEST)\r
374         {\r
375                 return TPI_ERROR_U_USE_LIBRARY;\r
376         }\r
377 \r
378         // 開きなおす。\r
379         void * hArc;\r
380         int nErrorCode = OpenArchive(_szArcName, & hArc);\r
381         if (nErrorCode != TPI_ERROR_SUCCESS)\r
382         {\r
383                 return nErrorCode;\r
384         }\r
385 \r
386         void\r
387                 * pS = g_hLib.HasSymbol(wxT("RARSetPassword"))  ? g_hLib.GetSymbol(wxT("RARSetPassword"))  : NULL,\r
388                 * pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL,\r
389                 * pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
390         if (! pR || ! pP)\r
391         {\r
392                 return TPI_ERROR_U_USE_LIBRARY;\r
393         }\r
394         if (pS)\r
395         {\r
396                 ((void (__stdcall *)(void *, char *)) pS)(hArc, _swInfo->szPassword.char_str());\r
397         }\r
398 \r
399         RARHeaderDataEx hdInfo;\r
400         g_hdInfo = & hdInfo;\r
401         while (nErrorCode == TPI_ERROR_SUCCESS && ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(hArc, & hdInfo)) == TPI_ERROR_SUCCESS)\r
402         {\r
403                 nErrorCode =\r
404                         ErrorCodeConvert(\r
405                                 ((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(\r
406                                         hArc,\r
407                                         (_szFiles.GetCount() != 0 && _szFiles.Index(wxString(hdInfo.FileNameW)) == wxNOT_FOUND) ? RAR_SKIP : _eCommand == TPI_COMMAND_EXTRACT ? RAR_EXTRACT : RAR_TEST,\r
408                                         _swInfo->fStoreDirectoryPathes ? _swInfo->fnDestinationDirectory.GetFullPath().wchar_str() : NULL,\r
409                                         _swInfo->fStoreDirectoryPathes ? NULL : (_swInfo->fnDestinationDirectory.GetPathWithSep() + wxFileName(hdInfo.FileNameW).GetFullName()).wchar_str()\r
410                                 )\r
411                         );\r
412         }\r
413         CloseArchive(hArc);\r
414         return nErrorCode;\r
415 }\r
416 \r
417 int __stdcall SetCallbackProc\r
418 (\r
419         TPI_PROC _prArcProc\r
420 )\r
421 {\r
422         // ポインタを保存。\r
423         if (_prArcProc == NULL)\r
424         {\r
425                 return TPI_ERROR_D_PARAMETER;\r
426         }\r
427         g_prProc = * _prArcProc;\r
428 \r
429         return TPI_ERROR_SUCCESS;\r
430 }\r
431 \r
432 #ifdef __cplusplus\r
433 }\r
434 #endif\r