OSDN Git Service

SetCallbackProcをLoadLibraryに統合。
[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         TPI_PROC _prProc,\r
191         wxULongLong_t\r
192 )\r
193 {\r
194         ::RemoveCwdFromSearchPath();\r
195         g_hLib.Load(g_hLib.CanonicalizeName(wxT("unrar")));\r
196         if (! g_hLib.IsLoaded())\r
197         {\r
198                 g_hLib.Unload();\r
199                 return TPI_ERROR_U_LOAD_LIBRARY;\r
200         }\r
201 \r
202         // コールバック関数を設定。\r
203         if (_prProc != NULL)\r
204         {\r
205                 g_prProc = * _prProc;\r
206         }\r
207         return TPI_ERROR_SUCCESS;\r
208 }\r
209 \r
210 int __stdcall FreePlugin\r
211 (\r
212         void * // _pReserved\r
213 )\r
214 {\r
215         g_hLib.Unload();\r
216         return TPI_ERROR_SUCCESS;\r
217 }\r
218 \r
219 int __stdcall OpenArchive\r
220 (\r
221         const wxString & _szArcName,\r
222         void * * _hArchive,\r
223         wxULongLong_t *\r
224 )\r
225 {\r
226         if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))\r
227         {\r
228                 return TPI_ERROR_U_USE_LIBRARY;\r
229         }\r
230         void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));\r
231         if (! p)\r
232         {\r
233                 return TPI_ERROR_U_USE_LIBRARY;\r
234         }\r
235 \r
236         memset(& g_oaInfo, 0, sizeof(g_oaInfo));\r
237         g_oaInfo.ArcName    = NULL;\r
238 //      g_oaInfo.ArcNameW   = _szArcName.wchar_str();\r
239         g_oaInfo.ArcNameW   = (wchar_t *) malloc((_szArcName.Len() + 1) * sizeof(wchar_t));\r
240         wcscpy(g_oaInfo.ArcNameW, _szArcName.wchar_str());\r
241         g_oaInfo.OpenMode   = RAR_OM_LIST;\r
242         g_oaInfo.CmtBuf     = g_szComment;\r
243         g_oaInfo.CmtBufSize = sizeof(g_szComment) - 1;\r
244         g_oaInfo.Callback   = CallbackProc;\r
245         * _hArchive = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& g_oaInfo);\r
246         free(g_oaInfo.ArcNameW);\r
247         return * _hArchive == NULL ? TPI_ERROR_UNDEFINED : ErrorCodeConvert(g_oaInfo.OpenResult);\r
248 }\r
249 \r
250 int __stdcall CloseArchive\r
251 (\r
252         void * _hArchive\r
253 )\r
254 {\r
255         if (! g_hLib.HasSymbol(wxT("RARCloseArchive")))\r
256         {\r
257                 return TPI_ERROR_U_USE_LIBRARY;\r
258         }\r
259         void * p = g_hLib.GetSymbol(wxT("RARCloseArchive"));\r
260         return (! p || _hArchive == NULL) ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((int (__stdcall *)(void *)) p)(_hArchive));\r
261 }\r
262 \r
263 int __stdcall GetFileInformation\r
264 (\r
265         void * _hArchive,\r
266         TPI_FILEINFO * _fiInfo,\r
267         bool _bFirst\r
268 )\r
269 {\r
270         static wxULongLong_t s_nFileId;\r
271         static void * pR, * pP;\r
272         int nErrorCode;\r
273 \r
274         if (_bFirst)\r
275         {\r
276                 s_nFileId = 0;\r
277                 pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL;\r
278                 pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
279                 if (! pR || ! pP)\r
280                 {\r
281                         return TPI_ERROR_U_USE_LIBRARY;\r
282                 }\r
283         }\r
284 \r
285         RARHeaderDataEx hdInfo;\r
286         char szComment[64001];\r
287         hdInfo.CmtBuf     = szComment;\r
288         hdInfo.CmtBufSize = sizeof(szComment) - 1;\r
289         nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(_hArchive, & hdInfo));\r
290         if (nErrorCode == TPI_ERROR_SUCCESS)\r
291         {\r
292                 if (hdInfo.HostOS == 3)\r
293                 {\r
294                         _fiInfo->wPermission = hdInfo.FileAttr;\r
295                 }\r
296                 else\r
297                 {\r
298                         _fiInfo->dwAttribute = hdInfo.FileAttr;\r
299                 }\r
300                 if (hdInfo.Flags & 0x04)\r
301                 {\r
302                         _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
303                 }\r
304                 _fiInfo->dwCRC32        = hdInfo.FileCRC;\r
305                 _fiInfo->nPackedSize    = hdInfo.PackSizeHigh;\r
306                 _fiInfo->nPackedSize    = _fiInfo->nPackedSize << 32;\r
307                 _fiInfo->nPackedSize   += hdInfo.PackSize;\r
308                 _fiInfo->nUnpackedSize  = hdInfo.UnpSizeHigh;\r
309                 _fiInfo->nUnpackedSize  = _fiInfo->nUnpackedSize << 32;\r
310                 _fiInfo->nUnpackedSize += hdInfo.UnpSize;\r
311                 _fiInfo->tmModify.SetFromDOS(hdInfo.FileTime);\r
312                 _fiInfo->eOSType        = hdInfo.HostOS;\r
313                 _fiInfo->szStoredName   = WC2String(hdInfo.FileNameW);\r
314                 _fiInfo->szMethod.Printf(wxT("%x"), hdInfo.Method);\r
315                 _fiInfo->szComment      = UTF82String(hdInfo.CmtBuf);\r
316                 _fiInfo->nFileId        = s_nFileId++;\r
317                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName);\r
318 \r
319                 // 次のファイルへ。\r
320                 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(_hArchive, RAR_SKIP, NULL, NULL));\r
321         }\r
322 \r
323         return nErrorCode;\r
324 }\r
325 \r
326 int __stdcall GetArchiveInformation\r
327 (\r
328         void *,\r
329         TPI_ARCHIVEINFO * _aiInfo\r
330 )\r
331 {\r
332         _aiInfo->fSolid         = (g_oaInfo.Flags & 0x0008) == 1;\r
333         _aiInfo->fEncryptHeader = (g_oaInfo.Flags & 0x0080) == 1;\r
334         _aiInfo->szComment      = UTF82String(g_szComment);\r
335         GetFormatInformation(& _aiInfo->fiInfo, true);\r
336         return TPI_ERROR_SUCCESS;\r
337 }\r
338 \r
339 int __stdcall Command\r
340 (\r
341         wxULongLong_t _eCommand,\r
342         TPI_SWITCHES * _swInfo,\r
343         const wxString & _szArcName,\r
344         const wxArrayString & _szFiles\r
345 )\r
346 {\r
347         if (_eCommand != TPI_COMMAND_EXTRACT && _eCommand != TPI_COMMAND_TEST)\r
348         {\r
349                 return TPI_ERROR_U_USE_LIBRARY;\r
350         }\r
351 \r
352         // 開きなおす。\r
353         if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))\r
354         {\r
355                 return TPI_ERROR_U_USE_LIBRARY;\r
356         }\r
357         void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));\r
358         if (! p)\r
359         {\r
360                 return TPI_ERROR_U_USE_LIBRARY;\r
361         }\r
362         RAROpenArchiveDataEx oaInfo;\r
363         memset(& oaInfo, 0, sizeof(oaInfo));\r
364         oaInfo.ArcName    = NULL;\r
365 //      oaInfo.ArcNameW   = _szArcName.wchar_str();\r
366         oaInfo.ArcNameW   = (wchar_t *) malloc((_szArcName.Len() + 1) * sizeof(wchar_t));\r
367         wcscpy(oaInfo.ArcNameW, _szArcName.wchar_str());\r
368         oaInfo.OpenMode   = RAR_OM_EXTRACT;\r
369         oaInfo.CmtBufSize = 0;\r
370         oaInfo.Callback   = CallbackProc;\r
371         void * hArc = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& oaInfo);\r
372         free(oaInfo.ArcNameW);\r
373         if (hArc == NULL)\r
374         {\r
375                 return TPI_ERROR_UNDEFINED;\r
376         }\r
377         int nErrorCode = ErrorCodeConvert(oaInfo.OpenResult);\r
378         if (nErrorCode != TPI_ERROR_SUCCESS)\r
379         {\r
380                 return nErrorCode;\r
381         }\r
382 \r
383         void\r
384                 * pS = g_hLib.HasSymbol(wxT("RARSetPassword"))  ? g_hLib.GetSymbol(wxT("RARSetPassword"))  : NULL,\r
385                 * pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL,\r
386                 * pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
387         if (! pR || ! pP)\r
388         {\r
389                 CloseArchive(hArc);\r
390                 return TPI_ERROR_U_USE_LIBRARY;\r
391         }\r
392         if (pS)\r
393         {\r
394                 ((void (__stdcall *)(void *, char *)) pS)(hArc, _swInfo->szPassword.char_str());\r
395         }\r
396 \r
397         RARHeaderDataEx hdInfo;\r
398         g_hdInfo = & hdInfo;\r
399         while (nErrorCode == TPI_ERROR_SUCCESS && ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(hArc, & hdInfo)) == TPI_ERROR_SUCCESS)\r
400         {\r
401                 TPI_PROCESSINFO piInfo;\r
402                 piInfo.fiInfo.fnFileName     = wxFileName(WC2String(hdInfo.FileNameW));\r
403                 piInfo.fnDestination         = wxFileName(_swInfo->fnDestinationDirectory.GetPathWithSep() + (_swInfo->fStoreDirectoryPathes ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetFullName()));\r
404                 bool bSkip = _szFiles.GetCount() != 0 && _szFiles.Index(piInfo.fiInfo.fnFileName.GetFullPath()) == wxNOT_FOUND;\r
405                 if (! bSkip && _eCommand == TPI_COMMAND_EXTRACT)\r
406                 {\r
407                         // 処理するかどうか確認。\r
408                         piInfo.eMessage = TPI_MESSAGE_ASK;\r
409                         piInfo.eStatus  = TPI_PARAM_DEST;\r
410                         piInfo.fiInfo.nUnpackedSize  = hdInfo.UnpSizeHigh;\r
411                         piInfo.fiInfo.nUnpackedSize  = piInfo.fiInfo.nUnpackedSize << 32;\r
412                         piInfo.fiInfo.nUnpackedSize += hdInfo.UnpSize;\r
413                         piInfo.fiInfo.tmModify.SetFromDOS(hdInfo.FileTime);\r
414                         if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
415                         {\r
416                                 nErrorCode = TPI_ERROR_D_SKIPPED;\r
417                                 break;\r
418                         }\r
419                         bSkip = ! piInfo.fnDestination.IsOk();\r
420                 }\r
421 \r
422                 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(hArc, bSkip ? RAR_SKIP : _eCommand == TPI_COMMAND_EXTRACT ? RAR_EXTRACT : RAR_TEST, NULL, piInfo.fnDestination.GetFullPath().wchar_str()));\r
423         }\r
424         CloseArchive(hArc);\r
425         return nErrorCode;\r
426 }\r
427 \r
428 #ifdef __cplusplus\r
429 }\r
430 #endif\r