OSDN Git Service

CheckArchiveからnFileCountを削除。
[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 CheckArchive\r
233 (\r
234         const wxString & _szArcName\r
235 )\r
236 {\r
237         FARPROC fpProc = ::GetAPIAddress("IsValidArchive");\r
238         if (fpProc == NULL)\r
239         {\r
240                 return TPI_ERROR_U_USE_LIBRARY;\r
241         }\r
242 \r
243         egg_type eType;\r
244         return ErrorCodeConvert(((UINT (__cdecl *)(const wchar_t *, egg_type *)) fpProc)(_szArcName.wchar_str(), & eType));\r
245 }\r
246 \r
247 int __stdcall OpenArchive\r
248 (\r
249         const wxString & _szArcName,\r
250         void * * _hArchive,\r
251         wxULongLong_t *\r
252 )\r
253 {\r
254         FARPROC fpProc = ::GetAPIAddress("CreateEgg");\r
255         if (fpProc == NULL)\r
256         {\r
257                 return TPI_ERROR_U_USE_LIBRARY;\r
258         }\r
259         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void **, eggevent::Proc, void *)) fpProc)(_hArchive, CallbackProc, _hArchive));\r
260         if (nErrorCode != TPI_ERROR_SUCCESS)\r
261         {\r
262                 return nErrorCode;\r
263         }\r
264         if (_hArchive == NULL)\r
265         {\r
266                 return TPI_ERROR_UNDEFINED;\r
267         }\r
268 \r
269         fpProc = ::GetAPIAddress("OpenArchive");\r
270         return fpProc == NULL ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void *, wchar_t *)) fpProc)(* _hArchive, _szArcName.wchar_str()));\r
271 }\r
272 \r
273 int __stdcall CloseArchive\r
274 (\r
275         void * _hArchive\r
276 )\r
277 {\r
278         FARPROC fpProc = ::GetAPIAddress("CloseArchive");\r
279         if (fpProc == NULL || _hArchive == NULL)\r
280         {\r
281                 return TPI_ERROR_U_USE_LIBRARY;\r
282         }\r
283         int nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(_hArchive));\r
284         if (nErrorCode != TPI_ERROR_SUCCESS)\r
285         {\r
286                 return nErrorCode;\r
287         }\r
288 \r
289         fpProc = ::GetAPIAddress("DestroyEgg");\r
290         return fpProc == NULL ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((UINT (__cdecl *)(void **)) fpProc)(& _hArchive));\r
291 }\r
292 \r
293 int __stdcall GetFileInformation\r
294 (\r
295         void * _hArchive,\r
296         TPI_FILEINFO * _fiInfo,\r
297         bool _bFirst\r
298 )\r
299 {\r
300         static wxULongLong_t s_nFileId;\r
301         static size_t s_nFileCount;\r
302         static FARPROC fpProc;\r
303         int nErrorCode;\r
304 \r
305         if (_bFirst)\r
306         {\r
307                 s_nFileId = 0;\r
308                 fpProc = ::GetAPIAddress("GetFileCount");\r
309                 if (fpProc == NULL)\r
310                 {\r
311                         return TPI_ERROR_U_USE_LIBRARY;\r
312                 }\r
313                 nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t *)) fpProc)(_hArchive, & s_nFileCount));\r
314                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
315                 {\r
316                         return nErrorCode;\r
317                 }\r
318 \r
319                 fpProc = ::GetAPIAddress("GetFileHeader");\r
320                 if (fpProc == NULL)\r
321                 {\r
322                         return TPI_ERROR_U_USE_LIBRARY;\r
323                 }\r
324         }\r
325         if (s_nFileId >= s_nFileCount)\r
326         {\r
327                 return TPI_ERROR_S_ENDOFDATA;\r
328         }\r
329 \r
330         EGGFileHeader fhInfo;\r
331         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *, size_t, EGGFileHeader *)) fpProc)(_hArchive, s_nFileId, & fhInfo));\r
332         if (nErrorCode == TPI_ERROR_SUCCESS)\r
333         {\r
334                 _fiInfo->dwAttribute    = fhInfo.attribute;\r
335                 if (fhInfo.encrypted)\r
336                 {\r
337                         _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
338                 }\r
339                 _fiInfo->dwCRC32        = fhInfo.crc;\r
340                 _fiInfo->nPackedSize    = fhInfo.packedSize;\r
341                 _fiInfo->nUnpackedSize  = fhInfo.unpackedSize;\r
342                 _fiInfo->tmModified     = fhInfo.lastModified;\r
343                 _fiInfo->szComment      = WC2String(fhInfo.comment);\r
344                 _fiInfo->szStoredName   = WC2String(fhInfo.fileName);\r
345                 _fiInfo->szMethod       = fhInfo.method == 2 ? wxT("ALZ") : fhInfo.method == 0 ? wxT("EGG") : wxT("unknown");\r
346                 _fiInfo->nFileId        = s_nFileId++;\r
347                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName);\r
348         }\r
349 \r
350         return nErrorCode;\r
351 }\r
352 \r
353 int __stdcall GetArchiveInformation\r
354 (\r
355         void *,\r
356         TPI_ARCHIVEINFO * _aiInfo\r
357 )\r
358 {\r
359         GetFormatInformation(& _aiInfo->fiInfo, true);\r
360         return TPI_ERROR_SUCCESS;\r
361 }\r
362 \r
363 int __stdcall Command\r
364 (\r
365         wxULongLong_t _eCommand,\r
366         TPI_SWITCHES * _swInfo,\r
367         const wxString & _szArcName,\r
368         const wxArrayString & _szFiles\r
369 )\r
370 {\r
371         if (_eCommand != TPI_COMMAND_EXTRACT)\r
372         {\r
373                 return TPI_ERROR_U_USE_LIBRARY;\r
374         }\r
375 \r
376         // 開きなおす。\r
377         void * hArc;\r
378         int nErrorCode = OpenArchive(_szArcName, & hArc);\r
379         if (nErrorCode != TPI_ERROR_SUCCESS)\r
380         {\r
381                 return nErrorCode;\r
382         }\r
383 \r
384         // グローバル変数にポインタを保存。\r
385         g_swInfo = _swInfo;\r
386         g_asFiles = & _szFiles;\r
387 \r
388         FARPROC fpProc = ::GetAPIAddress("Extract");\r
389         if (fpProc == NULL)\r
390         {\r
391                 return TPI_ERROR_U_USE_LIBRARY;\r
392         }\r
393         nErrorCode = ErrorCodeConvert(((UINT (__cdecl *)(void *)) fpProc)(hArc));\r
394         if (nErrorCode != TPI_ERROR_SUCCESS)\r
395         {\r
396                 return nErrorCode;\r
397         }\r
398 \r
399         return CloseArchive(hArc);\r
400 }\r
401 \r
402 int __stdcall SetCallbackProc\r
403 (\r
404         TPI_PROC _prArcProc\r
405 )\r
406 {\r
407         // ポインタを保存。\r
408         if (_prArcProc == NULL)\r
409         {\r
410                 return TPI_ERROR_D_PARAMETER;\r
411         }\r
412         g_prProc = * _prArcProc;\r
413 \r
414         return TPI_ERROR_SUCCESS;\r
415 }\r
416 \r
417 #ifdef __cplusplus\r
418 }\r
419 #endif\r