OSDN Git Service

a1dd8bf53c57fb0a924666bec120c0a49cd4b48c
[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 == nullptr)\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->tmModify       = 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 != nullptr && 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 == nullptr || 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 == nullptr)\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 == nullptr)\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         case TPI_INFO_HANDLE_ON_COMMAND:\r
237                 * (int *) _pPtr = 1;\r
238                 break;\r
239         default:\r
240                 return TPI_ERROR_D_UNSUPPORTED;\r
241         }\r
242         return TPI_ERROR_SUCCESS;\r
243 }\r
244 \r
245 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
246 {\r
247         if (! _bFirst)\r
248         {\r
249                 return TPI_ERROR_S_ENDOFDATA;\r
250         }\r
251 \r
252         _fiInfo->szTypeName   = wxT("EGG/ALZ");\r
253         _fiInfo->szSuffix     = wxT("egg;alz");\r
254         _fiInfo->szEngineName = wxT("UnEGG32.dll");\r
255         _fiInfo->szTPIName    = wxT("eggArc");\r
256         _fiInfo->nTypeId      = 0;\r
257         _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;\r
258         _fiInfo->fArchive     = true;\r
259         _fiInfo->fComment     = true;\r
260         _fiInfo->fSFX         = true;\r
261         _fiInfo->fSolid       = true;\r
262         _fiInfo->fEncryptPassword = true;\r
263         _fiInfo->fMultiVolume = true;\r
264 \r
265         return TPI_ERROR_SUCCESS;\r
266 }\r
267 \r
268 int __stdcall LoadPlugin\r
269 (\r
270         const wxString &,\r
271         TPI_PROC _prProc,\r
272         wxULongLong_t\r
273 )\r
274 {\r
275         ::RemoveCwdFromSearchPath();\r
276         g_hLib = ::LoadLibrary(L"UnEGG32.dll");\r
277         if (g_hLib == nullptr)\r
278         {\r
279                 ::FreeLibrary(g_hLib);\r
280                 return TPI_ERROR_U_LOAD_LIBRARY;\r
281         }\r
282 \r
283         // コールバック関数を設定。\r
284         if (_prProc != nullptr)\r
285         {\r
286                 g_prProc = * _prProc;\r
287         }\r
288         return TPI_ERROR_SUCCESS;\r
289 }\r
290 \r
291 int __stdcall FreePlugin\r
292 (\r
293         void * // _pReserved\r
294 )\r
295 {\r
296         ::FreeLibrary(g_hLib);\r
297         return TPI_ERROR_SUCCESS;\r
298 }\r
299 \r
300 int __stdcall OpenArchive\r
301 (\r
302         const wxString & _szArcName,\r
303         void * * _hArchive,\r
304         wxULongLong_t * _nFileCount\r
305 )\r
306 {\r
307         FARPROC fpProc = ::GetAPIAddress("IsValidArchive");\r
308         if (fpProc == nullptr)\r
309         {\r
310                 return TPI_ERROR_U_USE_LIBRARY;\r
311         }\r
312 \r
313         egg_type eType;\r
314         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(const wchar_t *, egg_type *)) fpProc)(_szArcName.wchar_str(), & eType));\r
315         if (nErrorCode != TPI_ERROR_SUCCESS)\r
316         {\r
317                 return nErrorCode;\r
318         }\r
319 \r
320         fpProc = ::GetAPIAddress("CreateEgg");\r
321         if (fpProc == nullptr)\r
322         {\r
323                 return TPI_ERROR_U_USE_LIBRARY;\r
324         }\r
325         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void **, eggevent::Proc, void *)) fpProc)(_hArchive, CallbackProc, _hArchive));\r
326         if (nErrorCode != TPI_ERROR_SUCCESS)\r
327         {\r
328                 return nErrorCode;\r
329         }\r
330         if (_hArchive == nullptr)\r
331         {\r
332                 return TPI_ERROR_UNDEFINED;\r
333         }\r
334 \r
335         fpProc = ::GetAPIAddress("OpenArchive");\r
336         if (fpProc == nullptr)\r
337         {\r
338                 return TPI_ERROR_U_USE_LIBRARY;\r
339         }\r
340         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, wchar_t *)) fpProc)(* _hArchive, _szArcName.wchar_str()));\r
341         if (nErrorCode != TPI_ERROR_SUCCESS)\r
342         {\r
343                 return nErrorCode;\r
344         }\r
345 \r
346         if (_nFileCount != nullptr)\r
347         {\r
348                 fpProc = ::GetAPIAddress("GetFileCount");\r
349                 if (fpProc == nullptr)\r
350                 {\r
351                         CloseArchive(* _hArchive);\r
352                         return TPI_ERROR_U_USE_LIBRARY;\r
353                 }\r
354                 size_t n;\r
355                 nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t *)) fpProc)(* _hArchive, & n));\r
356                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
357                 {\r
358                         CloseArchive(* _hArchive);\r
359                         return nErrorCode;\r
360                 }\r
361                 * _nFileCount = n;\r
362         }\r
363 \r
364         return TPI_ERROR_SUCCESS;\r
365 }\r
366 \r
367 int __stdcall CloseArchive\r
368 (\r
369         void * _hArchive\r
370 )\r
371 {\r
372         FARPROC fpProc = ::GetAPIAddress("CloseArchive");\r
373         if (fpProc == nullptr || _hArchive == nullptr)\r
374         {\r
375                 return TPI_ERROR_U_USE_LIBRARY;\r
376         }\r
377         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(_hArchive));\r
378         if (nErrorCode != TPI_ERROR_SUCCESS)\r
379         {\r
380                 return nErrorCode;\r
381         }\r
382 \r
383         fpProc = ::GetAPIAddress("DestroyEgg");\r
384         return fpProc == nullptr ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void **)) fpProc)(& _hArchive));\r
385 }\r
386 \r
387 int __stdcall GetFileInformation\r
388 (\r
389         void * _hArchive,\r
390         TPI_FILEINFO * _fiInfo,\r
391         bool _bFirst\r
392 )\r
393 {\r
394         static wxULongLong_t s_nFileId;\r
395         static size_t s_nFileCount;\r
396         if (_bFirst)\r
397         {\r
398                 s_nFileId = 0;\r
399                 FARPROC fpProc = ::GetAPIAddress("GetFileCount");\r
400                 if (fpProc == nullptr)\r
401                 {\r
402                         return TPI_ERROR_U_USE_LIBRARY;\r
403                 }\r
404                 int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t *)) fpProc)(_hArchive, & s_nFileCount));\r
405                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
406                 {\r
407                         return nErrorCode;\r
408                 }\r
409         }\r
410         return s_nFileId >= s_nFileCount ? TPI_ERROR_S_ENDOFDATA : GetFileInformation2(_hArchive, _fiInfo, s_nFileId++);\r
411 }\r
412 \r
413 int __stdcall GetArchiveInformation\r
414 (\r
415         void *,\r
416         TPI_ARCHIVEINFO * _aiInfo\r
417 )\r
418 {\r
419         GetFormatInformation(& _aiInfo->fiInfo, true);\r
420         return TPI_ERROR_SUCCESS;\r
421 }\r
422 \r
423 int __stdcall Command\r
424 (\r
425         wxULongLong_t _eCommand,\r
426         TPI_SWITCHES * _swInfo,\r
427         void * _hArchive,\r
428         const wxArrayString & _szFiles\r
429 )\r
430 {\r
431         if (_eCommand != TPI_COMMAND_EXTRACT && _eCommand != TPI_COMMAND_TEST)\r
432         {\r
433                 return TPI_ERROR_U_USE_LIBRARY;\r
434         }\r
435 \r
436         // グローバル変数にポインタを保存。\r
437         g_swInfo = _swInfo;\r
438         g_asFiles = & _szFiles;\r
439 \r
440         FARPROC fpProc = _eCommand == TPI_COMMAND_EXTRACT ? ::GetAPIAddress("Extract") : ::GetAPIAddress("Test");\r
441         return fpProc == nullptr ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(_hArchive));\r
442 }\r
443 \r
444 #ifdef __cplusplus\r
445 }\r
446 #endif\r