OSDN Git Service

e0b59644096b8091dc4f4f971a44df4a30c93d3c
[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.fnFileName.GetFullPath()) == 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::ActivityStart::CODE:\r
143                 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;\r
144                 GetFileInformation2(* (void **) user, & piInfo.fiInfo, ((eggevent::ActivityStart *) param)->index);\r
145                 break;\r
146         case eggevent::Progress::CODE:\r
147                 piInfo.eStatus = TPI_STATUS_INPROCESS;\r
148                 piInfo.nProcessedSize = ((eggevent::Progress *) param)->current * (piInfo.fiInfo.nUnpackedSize / 10000);\r
149                 break;\r
150         case eggevent::ActivityFinish::CODE:\r
151                 piInfo.eStatus = TPI_STATUS_ENDPROCESS;\r
152                 break;\r
153         case eggevent::Finish::CODE:\r
154                 piInfo.eStatus = TPI_STATUS_CLOSEARCHIVE;\r
155                 break;\r
156         case eggevent::QueryPassword::CODE:\r
157         {\r
158                 // パスワード問い合わせ。\r
159                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
160                 piInfo.eStatus  = TPI_PARAM_PASSWORD;\r
161 \r
162                 // コールバック関数に送信。\r
163                 eggevent::QueryPassword * p = (eggevent::QueryPassword *) param;\r
164                 // 初回は既定のパスワードを試す。\r
165                 if (p->queryCount == 1)\r
166                 {\r
167                         wcsncpy(p->password, g_swInfo->szPassword.wchar_str(), 1024 - 1);\r
168                         return EGG_ERROR_SUCCESS;\r
169                 }\r
170 \r
171                 // 2回目以降はコールバック関数に送信する。\r
172                 if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
173                 {\r
174                         return EGG_ERROR_CANCEL;\r
175                 }\r
176 \r
177                 // 既定のパスワードも変更しておく。\r
178                 g_swInfo->szPassword = piInfo.szParam;\r
179                 wcsncpy(p->password, piInfo.szParam.wchar_str(), 1024 - 1);\r
180                 return EGG_ERROR_SUCCESS;\r
181         }\r
182         default:\r
183                 return EGG_ERROR_SUCCESS;\r
184         }\r
185 \r
186         // コールバック関数に送信。\r
187         if (g_prProc == NULL)\r
188         {\r
189                 return EGG_ERROR_SUCCESS;\r
190         }\r
191 \r
192         return g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CANCEL ? EGG_ERROR_SUCCESS : EGG_ERROR_CANCEL;\r
193 }\r
194 \r
195 //******************************************************************************\r
196 //    Functions\r
197 //******************************************************************************\r
198 \r
199 #ifdef __cplusplus\r
200 extern "C"\r
201 {\r
202 #endif\r
203 \r
204 int __stdcall GetPluginInformation\r
205 (\r
206         unsigned int _uInfoId,\r
207         wxULongLong_t,\r
208         void * _pPtr\r
209 )\r
210 {\r
211         if (_pPtr == NULL)\r
212         {\r
213                 return TPI_ERROR_D_PARAMETER;\r
214         }\r
215         switch (_uInfoId)\r
216         {\r
217         case TPI_INFO_VERSION_MAJOR:\r
218         case TPI_INFO_VERSION_MINOR:\r
219                 * (int *) _pPtr = 0;\r
220                 break;\r
221         case TPI_INFO_VERSION_API:\r
222                 * (int *) _pPtr = 2;\r
223                 break;\r
224         default:\r
225                 return TPI_ERROR_D_UNSUPPORTED;\r
226         }\r
227         return TPI_ERROR_SUCCESS;\r
228 }\r
229 \r
230 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
231 {\r
232         if (! _bFirst)\r
233         {\r
234                 return TPI_ERROR_S_ENDOFDATA;\r
235         }\r
236 \r
237         _fiInfo->szTypeName   = wxT("EGG/ALZ");\r
238         _fiInfo->szSuffix     = wxT("egg;alz");\r
239         _fiInfo->szEngineName = wxT("UnEGG32.dll");\r
240         _fiInfo->szTPIName    = wxT("eggArc");\r
241         _fiInfo->nTypeId      = 0;\r
242         _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT;\r
243         _fiInfo->fArchive     = true;\r
244         _fiInfo->fComment     = true;\r
245         _fiInfo->fSFX         = true;\r
246         _fiInfo->fSolid       = true;\r
247         _fiInfo->fEncryptPassword = true;\r
248         _fiInfo->fMultiVolume = true;\r
249 \r
250         return TPI_ERROR_SUCCESS;\r
251 }\r
252 \r
253 int __stdcall LoadPlugin\r
254 (\r
255         const wxString &,\r
256         wxULongLong_t\r
257 )\r
258 {\r
259         ::RemoveCwdFromSearchPath();\r
260         g_hLib = ::LoadLibrary(L"UnEGG32.dll");\r
261         if (g_hLib == NULL)\r
262         {\r
263                 ::FreeLibrary(g_hLib);\r
264                 return TPI_ERROR_U_LOAD_LIBRARY;\r
265         }\r
266 \r
267         return TPI_ERROR_SUCCESS;\r
268 }\r
269 \r
270 int __stdcall FreePlugin\r
271 (\r
272         void * // _pReserved\r
273 )\r
274 {\r
275         ::FreeLibrary(g_hLib);\r
276         return TPI_ERROR_SUCCESS;\r
277 }\r
278 \r
279 int __stdcall OpenArchive\r
280 (\r
281         const wxString & _szArcName,\r
282         void * * _hArchive,\r
283         wxULongLong_t *\r
284 )\r
285 {\r
286         FARPROC fpProc = ::GetAPIAddress("IsValidArchive");\r
287         if (fpProc == NULL)\r
288         {\r
289                 return TPI_ERROR_U_USE_LIBRARY;\r
290         }\r
291 \r
292         egg_type eType;\r
293         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(const wchar_t *, egg_type *)) fpProc)(_szArcName.wchar_str(), & eType));\r
294         if (nErrorCode != TPI_ERROR_SUCCESS)\r
295         {\r
296                 return nErrorCode;\r
297         }\r
298 \r
299         fpProc = ::GetAPIAddress("CreateEgg");\r
300         if (fpProc == NULL)\r
301         {\r
302                 return TPI_ERROR_U_USE_LIBRARY;\r
303         }\r
304         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void **, eggevent::Proc, void *)) fpProc)(_hArchive, CallbackProc, _hArchive));\r
305         if (nErrorCode != TPI_ERROR_SUCCESS)\r
306         {\r
307                 return nErrorCode;\r
308         }\r
309         if (_hArchive == NULL)\r
310         {\r
311                 return TPI_ERROR_UNDEFINED;\r
312         }\r
313 \r
314         fpProc = ::GetAPIAddress("OpenArchive");\r
315         return fpProc == NULL ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void *, wchar_t *)) fpProc)(* _hArchive, _szArcName.wchar_str()));\r
316 }\r
317 \r
318 int __stdcall CloseArchive\r
319 (\r
320         void * _hArchive\r
321 )\r
322 {\r
323         FARPROC fpProc = ::GetAPIAddress("CloseArchive");\r
324         if (fpProc == NULL || _hArchive == NULL)\r
325         {\r
326                 return TPI_ERROR_U_USE_LIBRARY;\r
327         }\r
328         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(_hArchive));\r
329         if (nErrorCode != TPI_ERROR_SUCCESS)\r
330         {\r
331                 return nErrorCode;\r
332         }\r
333 \r
334         fpProc = ::GetAPIAddress("DestroyEgg");\r
335         return fpProc == NULL ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void **)) fpProc)(& _hArchive));\r
336 }\r
337 \r
338 int __stdcall GetFileInformation\r
339 (\r
340         void * _hArchive,\r
341         TPI_FILEINFO * _fiInfo,\r
342         bool _bFirst\r
343 )\r
344 {\r
345         static wxULongLong_t s_nFileId;\r
346         static size_t s_nFileCount;\r
347         if (_bFirst)\r
348         {\r
349                 s_nFileId = 0;\r
350                 FARPROC fpProc = ::GetAPIAddress("GetFileCount");\r
351                 if (fpProc == NULL)\r
352                 {\r
353                         return TPI_ERROR_U_USE_LIBRARY;\r
354                 }\r
355                 int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t *)) fpProc)(_hArchive, & s_nFileCount));\r
356                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
357                 {\r
358                         return nErrorCode;\r
359                 }\r
360         }\r
361         return s_nFileId >= s_nFileCount ? TPI_ERROR_S_ENDOFDATA : GetFileInformation2(_hArchive, _fiInfo, s_nFileId++);\r
362 }\r
363 \r
364 int __stdcall GetArchiveInformation\r
365 (\r
366         void *,\r
367         TPI_ARCHIVEINFO * _aiInfo\r
368 )\r
369 {\r
370         GetFormatInformation(& _aiInfo->fiInfo, true);\r
371         return TPI_ERROR_SUCCESS;\r
372 }\r
373 \r
374 int __stdcall Command\r
375 (\r
376         wxULongLong_t _eCommand,\r
377         TPI_SWITCHES * _swInfo,\r
378         const wxString & _szArcName,\r
379         const wxArrayString & _szFiles\r
380 )\r
381 {\r
382         if (_eCommand != TPI_COMMAND_EXTRACT)\r
383         {\r
384                 return TPI_ERROR_U_USE_LIBRARY;\r
385         }\r
386 \r
387         // 開きなおす。\r
388         void * hArc;\r
389         int nErrorCode = OpenArchive(_szArcName, & hArc);\r
390         if (nErrorCode != TPI_ERROR_SUCCESS)\r
391         {\r
392                 return nErrorCode;\r
393         }\r
394 \r
395         // グローバル変数にポインタを保存。\r
396         g_swInfo = _swInfo;\r
397         g_asFiles = & _szFiles;\r
398 \r
399         FARPROC fpProc = ::GetAPIAddress("Extract");\r
400         if (fpProc == NULL)\r
401         {\r
402                 return TPI_ERROR_U_USE_LIBRARY;\r
403         }\r
404         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(hArc));\r
405         if (nErrorCode != TPI_ERROR_SUCCESS)\r
406         {\r
407                 return nErrorCode;\r
408         }\r
409 \r
410         return CloseArchive(hArc);\r
411 }\r
412 \r
413 int __stdcall SetCallbackProc\r
414 (\r
415         TPI_PROC _prArcProc\r
416 )\r
417 {\r
418         // ポインタを保存。\r
419         if (_prArcProc == NULL)\r
420         {\r
421                 return TPI_ERROR_D_PARAMETER;\r
422         }\r
423         g_prProc = * _prArcProc;\r
424 \r
425         return TPI_ERROR_SUCCESS;\r
426 }\r
427 \r
428 #ifdef __cplusplus\r
429 }\r
430 #endif\r