OSDN Git Service

ca305da532d8a48284d9a426eb77c33cbf0543fe
[tpi/lychee.git] / src / plugin / eggArc / eggArc.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 #include "../../common/header/plugin.h"\r
27 #include "../../common/header/plugin-extra.h"\r
28 #include "../../common/library/library.h"\r
29 #include <windows.h>\r
30 #include "eggArc.h"\r
31 \r
32 //******************************************************************************\r
33 //    Global varients\r
34 //******************************************************************************\r
35 \r
36 HMODULE g_hLib;\r
37 TPI_PROC g_prProc;\r
38 TPI_SWITCHES * g_swInfo;\r
39 const wxArrayString * g_asFiles;\r
40 \r
41 //******************************************************************************\r
42 //    Inside Functions\r
43 //******************************************************************************\r
44 \r
45 #define GetAPIAddress(name) GetProcAddress(g_hLib, "EGG_" name)\r
46 \r
47 int ErrorCodeConvert(int nErrorCode)\r
48 {\r
49         switch (nErrorCode)\r
50         {\r
51         case EGG_ERROR_FAIL:        return TPI_ERROR_UNDEFINED;\r
52         case EGG_ERROR_SUCCESS:     return TPI_ERROR_SUCCESS;\r
53         case EGG_ERROR_SKIP:        return TPI_ERROR_D_SKIPPED;\r
54         case EGG_ERROR_CANCEL:      return TPI_ERROR_D_SKIPPED;\r
55         case EGG_ERROR_IO:          return TPI_ERROR_IO_MISC;\r
56         case EGG_ERROR_TYPEMISMATCH:return TPI_ERROR_ARC_UNSUPPORTED;\r
57         case EGG_ERROR_FILE:        return TPI_ERROR_IO_MISC;\r
58         case EGG_ERROR_FORMAT:      return TPI_ERROR_IO_ARC_MISC;\r
59         case EGG_ERROR_ALGORITHM:   return TPI_ERROR_UNDEFINED;\r
60         default:                    return TPI_ERROR_UNDEFINED;\r
61         }\r
62 }\r
63 \r
64 int __stdcall GetFileInformation2\r
65 (\r
66         void * _hArchive,\r
67         TPI_FILEINFO * _fiInfo,\r
68         wxULongLong_t _nIndex\r
69 )\r
70 {\r
71         static FARPROC fpProc = ::GetAPIAddress("GetFileHeader");\r
72         if (fpProc == NULL)\r
73         {\r
74                 return TPI_ERROR_U_USE_LIBRARY;\r
75         }\r
76 \r
77         EGGFileHeader fhInfo;\r
78         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t, EGGFileHeader *)) fpProc)(_hArchive, _nIndex, & fhInfo));\r
79         if (nErrorCode == TPI_ERROR_SUCCESS)\r
80         {\r
81                 _fiInfo->dwAttribute    = fhInfo.attribute;\r
82                 if (fhInfo.encrypted)\r
83                 {\r
84                         _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
85                 }\r
86                 _fiInfo->dwCRC32        = fhInfo.crc;\r
87                 _fiInfo->nPackedSize    = fhInfo.packedSize;\r
88                 _fiInfo->nUnpackedSize  = fhInfo.unpackedSize;\r
89                 _fiInfo->tmModified     = fhInfo.lastModified;\r
90                 _fiInfo->szComment      = WC2String(fhInfo.comment);\r
91                 _fiInfo->szStoredName   = WC2String(fhInfo.fileName);\r
92                 _fiInfo->szMethod       = fhInfo.method == 2 ? wxT("ALZ") : fhInfo.method == 0 ? wxT("EGG") : wxT("unknown");\r
93                 _fiInfo->nFileId        = _nIndex;\r
94                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName);\r
95         }\r
96 \r
97         return nErrorCode;\r
98 }\r
99 \r
100 //******************************************************************************\r
101 //    Callback Wrapper\r
102 //******************************************************************************\r
103 \r
104 UINT __cdecl CallbackProc(void * user, UINT code, void* param)\r
105 {\r
106         // 構造体を初期化。\r
107         static TPI_PROCESSINFO piInfo;\r
108         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
109 \r
110         switch (code)\r
111         {\r
112         case eggevent::Start::CODE:\r
113                 piInfo.eStatus = TPI_STATUS_OPENARCHIVE;\r
114                 break;\r
115         case eggevent::Extract::CODE:\r
116         {\r
117                 // 対象ファイルか確認。\r
118                 eggevent::Extract * p = (eggevent::Extract *) param;\r
119                 GetFileInformation2(* (void **) user, & piInfo.fiInfo, p->index);\r
120                 if (g_asFiles->Count() != 0 && g_asFiles->Index(piInfo.fiInfo.szStoredName) == wxNOT_FOUND)\r
121                 {\r
122                         return EGG_ERROR_SKIP;\r
123                 }\r
124 \r
125                 // 処理するかどうか確認。\r
126                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
127                 piInfo.eStatus  = TPI_PARAM_DEST;\r
128                 piInfo.fnDestination = wxFileName(g_swInfo->fnDestinationDirectory.GetPathWithSep() + (g_swInfo->fStoreDirectoryPathes ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetFullName()));\r
129                 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
130                 {\r
131                         return EGG_ERROR_CANCEL;\r
132                 }\r
133                 if (! piInfo.fnDestination.IsOk())\r
134                 {\r
135                         return EGG_ERROR_SKIP;\r
136                 }\r
137 \r
138                 // 展開する。\r
139                 wcsncpy(p->fileName, piInfo.fnDestination.GetFullPath().wchar_str(), MAX_PATH - 1);\r
140                 return EGG_ERROR_SUCCESS;\r
141         }\r
142         case eggevent::Test::CODE:\r
143         {\r
144                 // 対象ファイルか確認。\r
145                 eggevent::Test * p = (eggevent::Test *) param;\r
146                 GetFileInformation2(* (void **) user, & piInfo.fiInfo, p->index);\r
147                 if (g_asFiles->Count() != 0 && g_asFiles->Index(piInfo.fiInfo.szStoredName) == wxNOT_FOUND)\r
148                 {\r
149                         p->skipThisFile = true;\r
150                         return EGG_ERROR_SKIP;\r
151                 }\r
152                 return EGG_ERROR_SUCCESS;\r
153         }\r
154         case eggevent::ActivityStart::CODE:\r
155                 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;\r
156                 GetFileInformation2(* (void **) user, & piInfo.fiInfo, ((eggevent::ActivityStart *) param)->index);\r
157                 break;\r
158         case eggevent::Progress::CODE:\r
159                 piInfo.eStatus = TPI_STATUS_INPROCESS;\r
160                 piInfo.nProcessedSize = ((eggevent::Progress *) param)->current * (piInfo.fiInfo.nUnpackedSize / 10000);\r
161                 break;\r
162         case eggevent::ActivityFinish::CODE:\r
163                 piInfo.eStatus = TPI_STATUS_ENDPROCESS;\r
164                 break;\r
165         case eggevent::Finish::CODE:\r
166                 piInfo.eStatus = TPI_STATUS_CLOSEARCHIVE;\r
167                 break;\r
168         case eggevent::QueryPassword::CODE:\r
169         {\r
170                 // パスワード問い合わせ。\r
171                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
172                 piInfo.eStatus  = TPI_PARAM_PASSWORD;\r
173 \r
174                 // コールバック関数に送信。\r
175                 eggevent::QueryPassword * p = (eggevent::QueryPassword *) param;\r
176                 // 初回は既定のパスワードを試す。\r
177                 if (p->queryCount == 1)\r
178                 {\r
179                         wcsncpy(p->password, g_swInfo->szPassword.wchar_str(), 1024 - 1);\r
180                         return EGG_ERROR_SUCCESS;\r
181                 }\r
182 \r
183                 // 2回目以降はコールバック関数に送信する。\r
184                 if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
185                 {\r
186                         return EGG_ERROR_CANCEL;\r
187                 }\r
188 \r
189                 // 既定のパスワードも変更しておく。\r
190                 g_swInfo->szPassword = piInfo.szParam;\r
191                 wcsncpy(p->password, piInfo.szParam.wchar_str(), 1024 - 1);\r
192                 return EGG_ERROR_SUCCESS;\r
193         }\r
194         default:\r
195                 return EGG_ERROR_SUCCESS;\r
196         }\r
197 \r
198         // コールバック関数に送信。\r
199         if (g_prProc == NULL)\r
200         {\r
201                 return EGG_ERROR_SUCCESS;\r
202         }\r
203 \r
204         return g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CANCEL ? EGG_ERROR_SUCCESS : EGG_ERROR_CANCEL;\r
205 }\r
206 \r
207 //******************************************************************************\r
208 //    Functions\r
209 //******************************************************************************\r
210 \r
211 #ifdef __cplusplus\r
212 extern "C"\r
213 {\r
214 #endif\r
215 \r
216 int __stdcall GetPluginInformation\r
217 (\r
218         unsigned int _uInfoId,\r
219         wxULongLong_t,\r
220         void * _pPtr\r
221 )\r
222 {\r
223         if (_pPtr == NULL)\r
224         {\r
225                 return TPI_ERROR_D_PARAMETER;\r
226         }\r
227         switch (_uInfoId)\r
228         {\r
229         case TPI_INFO_VERSION_MAJOR:\r
230         case TPI_INFO_VERSION_MINOR:\r
231                 * (int *) _pPtr = 0;\r
232                 break;\r
233         case TPI_INFO_VERSION_API:\r
234                 * (int *) _pPtr = 2;\r
235                 break;\r
236         default:\r
237                 return TPI_ERROR_D_UNSUPPORTED;\r
238         }\r
239         return TPI_ERROR_SUCCESS;\r
240 }\r
241 \r
242 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
243 {\r
244         if (! _bFirst)\r
245         {\r
246                 return TPI_ERROR_S_ENDOFDATA;\r
247         }\r
248 \r
249         _fiInfo->szTypeName   = wxT("EGG/ALZ");\r
250         _fiInfo->szSuffix     = wxT("egg;alz");\r
251         _fiInfo->szEngineName = wxT("UnEGG32.dll");\r
252         _fiInfo->szTPIName    = wxT("eggArc");\r
253         _fiInfo->nTypeId      = 0;\r
254         _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;\r
255         _fiInfo->fArchive     = true;\r
256         _fiInfo->fComment     = true;\r
257         _fiInfo->fSFX         = true;\r
258         _fiInfo->fSolid       = true;\r
259         _fiInfo->fEncryptPassword = true;\r
260         _fiInfo->fMultiVolume = true;\r
261 \r
262         return TPI_ERROR_SUCCESS;\r
263 }\r
264 \r
265 int __stdcall LoadPlugin\r
266 (\r
267         const wxString &,\r
268         wxULongLong_t\r
269 )\r
270 {\r
271         ::RemoveCwdFromSearchPath();\r
272         g_hLib = ::LoadLibrary(L"UnEGG32.dll");\r
273         if (g_hLib == NULL)\r
274         {\r
275                 ::FreeLibrary(g_hLib);\r
276                 return TPI_ERROR_U_LOAD_LIBRARY;\r
277         }\r
278 \r
279         return TPI_ERROR_SUCCESS;\r
280 }\r
281 \r
282 int __stdcall FreePlugin\r
283 (\r
284         void * // _pReserved\r
285 )\r
286 {\r
287         ::FreeLibrary(g_hLib);\r
288         return TPI_ERROR_SUCCESS;\r
289 }\r
290 \r
291 int __stdcall OpenArchive\r
292 (\r
293         const wxString & _szArcName,\r
294         void * * _hArchive,\r
295         wxULongLong_t * _nFileCount\r
296 )\r
297 {\r
298         FARPROC fpProc = ::GetAPIAddress("IsValidArchive");\r
299         if (fpProc == NULL)\r
300         {\r
301                 return TPI_ERROR_U_USE_LIBRARY;\r
302         }\r
303 \r
304         egg_type eType;\r
305         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(const wchar_t *, egg_type *)) fpProc)(_szArcName.wchar_str(), & eType));\r
306         if (nErrorCode != TPI_ERROR_SUCCESS)\r
307         {\r
308                 return nErrorCode;\r
309         }\r
310 \r
311         fpProc = ::GetAPIAddress("CreateEgg");\r
312         if (fpProc == NULL)\r
313         {\r
314                 return TPI_ERROR_U_USE_LIBRARY;\r
315         }\r
316         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void **, eggevent::Proc, void *)) fpProc)(_hArchive, CallbackProc, _hArchive));\r
317         if (nErrorCode != TPI_ERROR_SUCCESS)\r
318         {\r
319                 return nErrorCode;\r
320         }\r
321         if (_hArchive == NULL)\r
322         {\r
323                 return TPI_ERROR_UNDEFINED;\r
324         }\r
325 \r
326         fpProc = ::GetAPIAddress("OpenArchive");\r
327         if (fpProc == NULL)\r
328         {\r
329                 return TPI_ERROR_U_USE_LIBRARY;\r
330         }\r
331         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, wchar_t *)) fpProc)(* _hArchive, _szArcName.wchar_str()));\r
332         if (nErrorCode != TPI_ERROR_SUCCESS)\r
333         {\r
334                 return nErrorCode;\r
335         }\r
336 \r
337         if (_nFileCount != NULL)\r
338         {\r
339                 fpProc = ::GetAPIAddress("GetFileCount");\r
340                 if (fpProc == NULL)\r
341                 {\r
342                         return TPI_ERROR_U_USE_LIBRARY;\r
343                 }\r
344                 unsigned int n;\r
345                 nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t *)) fpProc)(* _hArchive, & n));\r
346                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
347                 {\r
348                         return nErrorCode;\r
349                 }\r
350                 * _nFileCount = n;\r
351         }\r
352 \r
353         return TPI_ERROR_SUCCESS;\r
354 }\r
355 \r
356 int __stdcall CloseArchive\r
357 (\r
358         void * _hArchive\r
359 )\r
360 {\r
361         FARPROC fpProc = ::GetAPIAddress("CloseArchive");\r
362         if (fpProc == NULL || _hArchive == NULL)\r
363         {\r
364                 return TPI_ERROR_U_USE_LIBRARY;\r
365         }\r
366         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(_hArchive));\r
367         if (nErrorCode != TPI_ERROR_SUCCESS)\r
368         {\r
369                 return nErrorCode;\r
370         }\r
371 \r
372         fpProc = ::GetAPIAddress("DestroyEgg");\r
373         return fpProc == NULL ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void **)) fpProc)(& _hArchive));\r
374 }\r
375 \r
376 int __stdcall GetFileInformation\r
377 (\r
378         void * _hArchive,\r
379         TPI_FILEINFO * _fiInfo,\r
380         bool _bFirst\r
381 )\r
382 {\r
383         static wxULongLong_t s_nFileId;\r
384         static size_t s_nFileCount;\r
385         if (_bFirst)\r
386         {\r
387                 s_nFileId = 0;\r
388                 FARPROC fpProc = ::GetAPIAddress("GetFileCount");\r
389                 if (fpProc == NULL)\r
390                 {\r
391                         return TPI_ERROR_U_USE_LIBRARY;\r
392                 }\r
393                 int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t *)) fpProc)(_hArchive, & s_nFileCount));\r
394                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
395                 {\r
396                         return nErrorCode;\r
397                 }\r
398         }\r
399         return s_nFileId >= s_nFileCount ? TPI_ERROR_S_ENDOFDATA : GetFileInformation2(_hArchive, _fiInfo, s_nFileId++);\r
400 }\r
401 \r
402 int __stdcall GetArchiveInformation\r
403 (\r
404         void *,\r
405         TPI_ARCHIVEINFO * _aiInfo\r
406 )\r
407 {\r
408         GetFormatInformation(& _aiInfo->fiInfo, true);\r
409         return TPI_ERROR_SUCCESS;\r
410 }\r
411 \r
412 int __stdcall Command\r
413 (\r
414         wxULongLong_t _eCommand,\r
415         TPI_SWITCHES * _swInfo,\r
416         const wxString & _szArcName,\r
417         const wxArrayString & _szFiles\r
418 )\r
419 {\r
420         if (_eCommand != TPI_COMMAND_EXTRACT && _eCommand != TPI_COMMAND_TEST)\r
421         {\r
422                 return TPI_ERROR_U_USE_LIBRARY;\r
423         }\r
424 \r
425         // 開きなおす。\r
426         void * hArc;\r
427         int nErrorCode = OpenArchive(_szArcName, & hArc);\r
428         if (nErrorCode != TPI_ERROR_SUCCESS)\r
429         {\r
430                 return nErrorCode;\r
431         }\r
432 \r
433         // グローバル変数にポインタを保存。\r
434         g_swInfo = _swInfo;\r
435         g_asFiles = & _szFiles;\r
436 \r
437         FARPROC fpProc = _eCommand == TPI_COMMAND_EXTRACT ? ::GetAPIAddress("Extract") : ::GetAPIAddress("Test");\r
438         if (fpProc == NULL)\r
439         {\r
440                 return TPI_ERROR_U_USE_LIBRARY;\r
441         }\r
442         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(hArc));\r
443         if (nErrorCode != TPI_ERROR_SUCCESS)\r
444         {\r
445                 return nErrorCode;\r
446         }\r
447 \r
448         return CloseArchive(hArc);\r
449 }\r
450 \r
451 int __stdcall SetCallbackProc\r
452 (\r
453         TPI_PROC _prArcProc\r
454 )\r
455 {\r
456         // ポインタを保存。\r
457         if (_prArcProc == NULL)\r
458         {\r
459                 return TPI_ERROR_D_PARAMETER;\r
460         }\r
461         g_prProc = * _prArcProc;\r
462 \r
463         return TPI_ERROR_SUCCESS;\r
464 }\r
465 \r
466 #ifdef __cplusplus\r
467 }\r
468 #endif\r