OSDN Git Service

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