OSDN Git Service

wxFile::Close()はデストラクタで自動的に実行されるものを用いるよう変更。
[tpi/lychee.git] / src / plugin / xpiLibrary / xpiLibrary.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 <wx/file.h>\r
30 #include <wx/stdpaths.h>\r
31 #include <wx/dir.h>\r
32 #include <windows.h>\r
33 #include "xpiLibrary.h"\r
34 \r
35 //******************************************************************************\r
36 //    Global varients\r
37 //******************************************************************************\r
38 \r
39 HMODULE g_hLib;\r
40 TPI_PROC g_prProc;\r
41 \r
42 //******************************************************************************\r
43 //    Callback Wrapper\r
44 //******************************************************************************\r
45 \r
46 int __stdcall CallbackProc(int _nNow, int _nMax, long _lData)\r
47 {\r
48         // 構造体を初期化。\r
49         TPI_PROCESSINFO * piInfo = (TPI_PROCESSINFO *) _lData;\r
50         piInfo->nProcessedSize          = _nNow;\r
51         piInfo->fiInfo.nUnpackedSize    = _nMax;\r
52 \r
53         // コールバック関数に送信。\r
54         return g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, piInfo) == TPI_CALLBACK_CANCEL;\r
55 }\r
56 \r
57 //******************************************************************************\r
58 //    Inside Functions\r
59 //******************************************************************************\r
60 \r
61 int ErrorCodeConvert(int nErrorCode)\r
62 {\r
63         switch (nErrorCode)\r
64         {\r
65         case -1:case XPI_NO_FUNCTION:       return TPI_ERROR_U_USE_LIBRARY;\r
66         case 0:                             return TPI_ERROR_SUCCESS;\r
67         case 1: case XPI_ABORT:             return TPI_ERROR_D_SKIPPED;\r
68         case 2: case XPI_NOT_SUPPRORT:      return TPI_ERROR_ARC_UNSUPPORTED;\r
69         case 3: case XPI_OUT_OF_ORDER:      return TPI_ERROR_ARC_BROKEN_MISC;\r
70         case 4: case XPI_NO_MEMORY:         return TPI_ERROR_D_OUTOFMEMORY;\r
71         case 5: case XPI_MEMORY_ERROR:      return TPI_ERROR_D_USEMEMORY;\r
72         case 6: case XPI_FILE_READ_ERROR:   return TPI_ERROR_IO_ARC_READ;\r
73                         case XPI_OTHER_ERROR:           return TPI_ERROR_UNDEFINED;\r
74                         case XPI_WINDOW_ERROR:      return TPI_ERROR_UNDEFINED;\r
75                         case XPI_FILE_WRITE_ERROR:  return TPI_ERROR_IO_FILE_WRITE;\r
76                         case XPI_END_OF_FILE:       return TPI_ERROR_ARC_BROKEN_MISC;\r
77         default:                            return TPI_ERROR_UNDEFINED;\r
78         }\r
79 }\r
80 \r
81 //******************************************************************************\r
82 //    Functions\r
83 //******************************************************************************\r
84 \r
85 #ifdef __cplusplus\r
86 extern "C"\r
87 {\r
88 #endif\r
89 \r
90 int __stdcall GetPluginInformation\r
91 (\r
92         unsigned int _uInfoId,\r
93         wxULongLong_t,\r
94         void * _pPtr\r
95 )\r
96 {\r
97         if (_pPtr == NULL)\r
98         {\r
99                 return TPI_ERROR_D_PARAMETER;\r
100         }\r
101         switch (_uInfoId)\r
102         {\r
103         case TPI_INFO_VERSION_MAJOR:\r
104         case TPI_INFO_VERSION_MINOR:\r
105                 * (int *) _pPtr = 0;\r
106                 break;\r
107         case TPI_INFO_VERSION_API:\r
108                 * (int *) _pPtr = 2;\r
109                 break;\r
110         case TPI_INFO_HANDLE_ON_COMMAND:\r
111                 * (int *) _pPtr = 0;\r
112                 break;\r
113         default:\r
114                 return TPI_ERROR_D_PARAMETER;\r
115         }\r
116         return TPI_ERROR_SUCCESS;\r
117 }\r
118 \r
119 int __stdcall GetFormatInformation(TPI_FORMATINFO *, bool)\r
120 {\r
121         return TPI_ERROR_D_UNSUPPORTED;\r
122 }\r
123 \r
124 int __stdcall LoadPlugin\r
125 (\r
126         const wxString & _szArcName,\r
127         TPI_PROC _prProc,\r
128         wxULongLong_t\r
129 )\r
130 {\r
131         // ファイルを開く。\r
132         char buffer[2050];\r
133         {\r
134                 wxFile hFile;\r
135                 if (! hFile.Exists(_szArcName) || ! hFile.Open(_szArcName, wxFile::read))\r
136                 {\r
137                         return TPI_ERROR_IO_ARC_OPEN;\r
138                 }\r
139 \r
140                 // 最初の2KBを読み込み。\r
141                 ::ZeroMemory(buffer, sizeof(buffer));\r
142                 if (hFile.Read(buffer, sizeof(buffer)) == wxInvalidOffset)\r
143                 {\r
144                         return TPI_ERROR_IO_ARC_READ;\r
145                 }\r
146         }\r
147 \r
148         wxString szSPIPath = wxPathOnly(wxStandardPaths::Get().GetExecutablePath()) + wxT("/lib/"), szSPIName;\r
149         wxDir fs(szSPIPath);\r
150         if (fs.GetFirst(& szSPIName, wxT("*.spi")))\r
151         {\r
152                 do\r
153                 {\r
154                         // SPIをロード。\r
155                         g_hLib = ::LoadLibrary((szSPIPath + szSPIName).wchar_str());\r
156                         if (g_hLib == NULL)\r
157                         {\r
158                                 continue;\r
159                         }\r
160 \r
161                         // GetPluginInfoを実行。\r
162                         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");\r
163                         char szPluginType[5]; // 種類4bytes + NULL\r
164                         if (fpProc == NULL\r
165                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szPluginType, sizeof(szPluginType)) <= 0\r
166                                 || szPluginType[2] != 'I' || szPluginType[3] != 'N')\r
167                         {\r
168                                 ::FreeLibrary(g_hLib);\r
169                                 continue;\r
170                         }\r
171 \r
172                         // 書庫に対応しているかチェック。\r
173                         fpProc = ::GetProcAddress(g_hLib, "IsSupported");\r
174                         if (fpProc == NULL)\r
175                         {\r
176                                 ::FreeLibrary(g_hLib);\r
177                                 continue;\r
178                         }\r
179 \r
180                         if (((BOOL (PASCAL *)(const char *, unsigned long)) fpProc)(_szArcName.ToUTF8(), (unsigned long) buffer))\r
181                         {\r
182                                 // コールバック関数を設定。\r
183                                 if (_prProc != NULL)\r
184                                 {\r
185                                         g_prProc = * _prProc;\r
186                                 }\r
187                                 return TPI_ERROR_SUCCESS;\r
188                         }\r
189                 }\r
190                 while (fs.GetNext(& szSPIName));\r
191         }\r
192         return TPI_ERROR_U_LOAD_LIBRARY;\r
193 }\r
194 \r
195 int __stdcall FreePlugin\r
196 (\r
197         void * // _pReserved\r
198 )\r
199 {\r
200         ::FreeLibrary(g_hLib);\r
201         return TPI_ERROR_SUCCESS;\r
202 }\r
203 \r
204 int __stdcall OpenArchive\r
205 (\r
206         const wxString & _szArcName,\r
207         void * * _hArchive,\r
208         wxULongLong_t *\r
209 )\r
210 {\r
211         * _hArchive = new wxString(_szArcName);\r
212         return TPI_ERROR_SUCCESS;\r
213 }\r
214 \r
215 int __stdcall CloseArchive\r
216 (\r
217         void * _hArchive\r
218 )\r
219 {\r
220         delete (wxString *) _hArchive;\r
221         return TPI_ERROR_SUCCESS;\r
222 }\r
223 \r
224 int __stdcall GetFileInformation\r
225 (\r
226         void * _hArchive,\r
227         TPI_FILEINFO * _fiInfo,\r
228         bool _bFirst\r
229 )\r
230 {\r
231         static wxString szXPIPath, szXPIName, szArcName = * (wxString *) _hArchive;\r
232         static int nColorDepth;\r
233         static wxDir fs;\r
234         if (_bFirst)\r
235         {\r
236                 szXPIPath = wxPathOnly(wxStandardPaths::Get().GetExecutablePath()) + wxT("/lib/");\r
237                 fs.Open(szXPIPath);\r
238 \r
239                 // 画像の情報を取得。\r
240                 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
241                 if (fpProc == NULL)\r
242                 {\r
243                         return TPI_ERROR_U_USE_LIBRARY;\r
244                 }\r
245                 PictureInfo picInfo;\r
246                 int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(szArcName.ToUTF8(), 0, 0, & picInfo));\r
247                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
248                 {\r
249                         return nErrorCode;\r
250                 }\r
251                 nColorDepth = picInfo.colorDepth;\r
252                 ::LocalUnlock(picInfo.hInfo);\r
253                 ::LocalFree(picInfo.hInfo);\r
254         }\r
255 \r
256         if (_bFirst ? fs.GetFirst(& szXPIName, wxT("*.xpi")) : fs.GetNext(& szXPIName))\r
257         {\r
258                 do\r
259                 {\r
260                         // XPIをロード。\r
261                         HMODULE hXPI = ::LoadLibrary((szXPIPath + szXPIName).wchar_str());\r
262                         if (hXPI == NULL)\r
263                         {\r
264                                 continue;\r
265                         }\r
266 \r
267                         // GetPluginInfoを実行。\r
268                         FARPROC fpProc = ::GetProcAddress(hXPI, "GetPluginInfo");\r
269                         char szTemp[513];\r
270                         memset(szTemp, 0, sizeof(szTemp));\r
271                         if (fpProc == NULL\r
272                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szTemp, sizeof(szTemp) - 1) <= 0\r
273                                 || szTemp[2] != 'X' || szTemp[3] != 'N')\r
274                         {\r
275                                 ::FreeLibrary(hXPI);\r
276                                 continue;\r
277                         }\r
278 \r
279                         _fiInfo->fnFileName = wxFileName(szArcName);\r
280                         _fiInfo->fnFileName.SetVolume(wxEmptyString);\r
281                         _fiInfo->fnFileName.SetPath(szXPIName);\r
282                         if (((int (PASCAL *)(int, char *, int)) fpProc)(1, szTemp, sizeof(szTemp) - 1) > 0)\r
283                         {\r
284                                 _fiInfo->szComment = MB2String(szTemp);\r
285                         }\r
286                         if (((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp) - 1) > 0)\r
287                         {\r
288                                 _fiInfo->fnFileName.SetExt(MB2String(szTemp));\r
289                         }\r
290                         _fiInfo->szStoredName = _fiInfo->fnFileName.GetFullPath();\r
291 \r
292                         // 対応確認。\r
293                         fpProc = ::GetProcAddress(hXPI, "IsSupported");\r
294                         if (fpProc == NULL || ! ((BOOL (PASCAL *)(int)) fpProc)(nColorDepth))\r
295                         {\r
296                                 ::FreeLibrary(hXPI);\r
297                                 continue;\r
298                         }\r
299                         return TPI_ERROR_SUCCESS;\r
300                 }\r
301                 while (fs.GetNext(& szXPIName));\r
302         }\r
303         return TPI_ERROR_S_ENDOFDATA;\r
304 }\r
305 \r
306 int __stdcall GetArchiveInformation\r
307 (\r
308         void * _hArchive,\r
309         TPI_ARCHIVEINFO * _aiInfo\r
310 )\r
311 {\r
312         // 画像の情報を取得。\r
313         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
314         if (fpProc == NULL)\r
315         {\r
316                 return TPI_ERROR_U_USE_LIBRARY;\r
317         }\r
318         PictureInfo piInfo;\r
319         int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(((wxString *) _hArchive)->ToUTF8(), 0, 0, & piInfo));\r
320         if (nErrorCode != TPI_ERROR_SUCCESS)\r
321         {\r
322                 return nErrorCode;\r
323         }\r
324         _aiInfo->szComment = MB2String((char *) ::LocalLock(piInfo.hInfo));\r
325         ::LocalUnlock(piInfo.hInfo);\r
326         ::LocalFree(piInfo.hInfo);\r
327 \r
328         // GetPluginInfoを実行。\r
329         fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");\r
330         if (fpProc != NULL)\r
331         {\r
332                 char szTemp[513];\r
333                 memset(szTemp, 0, sizeof(szTemp));\r
334                 if (((int (PASCAL *)(int, char *, int)) fpProc)(1, szTemp, sizeof(szTemp) - 1) > 0)\r
335                 {\r
336                         _aiInfo->fiInfo.szEngineName = MB2String(szTemp);\r
337                 }\r
338                 if (((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp) - 1) > 0)\r
339                 {\r
340                         _aiInfo->fiInfo.szSuffix = MB2String(szTemp);\r
341                 }\r
342                 if (((int (PASCAL *)(int, char *, int)) fpProc)(3, szTemp, sizeof(szTemp) - 1) > 0)\r
343                 {\r
344                         _aiInfo->fiInfo.szTypeName = MB2String(szTemp);\r
345                 }\r
346         }\r
347         _aiInfo->fiInfo.fArchive = false;\r
348         _aiInfo->fiInfo.szTPIName = wxT("xpiLibrary");\r
349         _aiInfo->fiInfo.eSupportedCommand = TPI_COMMAND_EXTRACT;\r
350 \r
351         return TPI_ERROR_SUCCESS;\r
352 }\r
353 \r
354 int __stdcall Command\r
355 (\r
356         wxULongLong_t _eCommand,\r
357         TPI_SWITCHES * _swInfo,\r
358         void *,// _hArchive,\r
359         const wxArrayString & _asFiles\r
360 )\r
361 {\r
362         if (_eCommand != TPI_COMMAND_EXTRACT)\r
363         {\r
364                 return TPI_ERROR_D_UNSUPPORTED;\r
365         }\r
366 \r
367         // 画像の情報を取得。\r
368         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
369         if (fpProc == NULL)\r
370         {\r
371                 return TPI_ERROR_U_USE_LIBRARY;\r
372         }\r
373         PictureInfo picInfo;\r
374         int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(_swInfo->szArcName.ToUTF8(), 0, 0, & picInfo));\r
375         if (nErrorCode != TPI_ERROR_SUCCESS)\r
376         {\r
377                 return nErrorCode;\r
378         }\r
379 \r
380         // コールバックを送信。\r
381         wxFileName _fnArcName(_swInfo->szArcName);\r
382         TPI_PROCESSINFO piInfo;\r
383         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
384         piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
385         piInfo.fiInfo.fnFileName = _fnArcName;\r
386         if (CallbackProc(0, 0, (long) & piInfo))\r
387         {\r
388                 return TPI_ERROR_D_SKIPPED;\r
389         }\r
390 \r
391         // メモリ上に展開。\r
392         HANDLE hInfo, hMemory;\r
393         fpProc = ::GetProcAddress(g_hLib, "GetPicture");\r
394         if (fpProc == NULL)\r
395         {\r
396                 return TPI_ERROR_U_USE_LIBRARY;\r
397         }\r
398         nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, HANDLE *, HANDLE *, FARPROC, long)) fpProc)(_swInfo->szArcName.ToUTF8(), 0, 0, & hInfo, & hMemory, (FARPROC) CallbackProc, (long) & piInfo));\r
399         if (nErrorCode == TPI_ERROR_SUCCESS && (hMemory == NULL || hInfo == NULL))\r
400         {\r
401                 return TPI_ERROR_UNDEFINED;\r
402         }\r
403         if (nErrorCode != TPI_ERROR_SUCCESS)\r
404         {\r
405                 return nErrorCode;\r
406         }\r
407 \r
408         wxString szXPIPath = wxPathOnly(wxStandardPaths::Get().GetExecutablePath()) + wxT("/lib/");\r
409         for (size_t i = 0; i < _asFiles.GetCount(); i++)\r
410         {\r
411                 // 処理を行うか確認。\r
412                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
413                 piInfo.eStatus = TPI_PARAM_DEST;\r
414                 piInfo.fiInfo.fnFileName = wxFileName(_asFiles[i]);\r
415                 piInfo.fnDestination = piInfo.fiInfo.fnFileName;\r
416                 piInfo.fnDestination.SetPath(_swInfo->fnDestinationDirectory.GetPath());\r
417                 if (CallbackProc(0, 0, (long) & piInfo))\r
418                 {\r
419                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
420                         break;\r
421                 }\r
422                 if (! piInfo.fnDestination.IsOk())\r
423                 {\r
424                         continue;\r
425                 }\r
426 \r
427                 // XPIをロード。\r
428                 HMODULE hXPI = ::LoadLibrary((szXPIPath + piInfo.fiInfo.fnFileName.GetPath()).wchar_str());\r
429                 if (hXPI == NULL)\r
430                 {\r
431                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
432                         break;\r
433                 }\r
434 \r
435                 // GetPluginInfoを実行。\r
436                 FARPROC fpProc = ::GetProcAddress(hXPI, "GetPluginInfo");\r
437                 char szTemp[20];\r
438                 if (fpProc == NULL\r
439                         || ((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) <= 0)\r
440                 {\r
441                         ::FreeLibrary(hXPI);\r
442                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
443                         break;\r
444                 }\r
445 \r
446                 // コールバックを送信。\r
447                 piInfo.eMessage = TPI_MESSAGE_STATUS;\r
448                 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;\r
449                 if (CallbackProc(0, 0, (long) & piInfo))\r
450                 {\r
451                         ::FreeLibrary(hXPI);\r
452                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
453                         break;\r
454                 }\r
455 \r
456                 // 書き込み。\r
457                 piInfo.eStatus = TPI_STATUS_INPROCESS;\r
458                 fpProc = ::GetProcAddress(hXPI, "CreatePicture");\r
459                 if (fpProc == NULL)\r
460                 {\r
461                         ::FreeLibrary(hXPI);\r
462                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
463                         break;\r
464                 }\r
465                 nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, HANDLE *, HANDLE *, PictureInfo *, FARPROC, long)) fpProc)(piInfo.fnDestination.GetFullPath().ToUTF8(), 0, & hInfo, & hMemory, & picInfo, (FARPROC) CallbackProc, (long) & piInfo));\r
466                 ::FreeLibrary(hXPI);\r
467 \r
468                 // 最後にコールバックを送信。\r
469                 piInfo.eStatus  = TPI_STATUS_ENDPROCESS;\r
470                 if (CallbackProc(0, 0, (long) & piInfo))\r
471                 {\r
472                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
473                         break;\r
474                 }\r
475         }\r
476         ::LocalUnlock(hInfo);\r
477         ::LocalUnlock(hMemory);\r
478         ::LocalUnlock(picInfo.hInfo);\r
479         ::LocalFree(hInfo);\r
480         ::LocalFree(hMemory);\r
481         ::LocalFree(picInfo.hInfo);\r
482         if (nErrorCode != TPI_ERROR_SUCCESS)\r
483         {\r
484                 return nErrorCode;\r
485         }\r
486 \r
487         // 最終のコールバック。\r
488         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
489         piInfo.eStatus  = TPI_STATUS_CLOSEARCHIVE;\r
490         piInfo.fiInfo.fnFileName = _fnArcName;\r
491         if (CallbackProc(0, 0, (long) & piInfo))\r
492         {\r
493                 return TPI_ERROR_D_SKIPPED;\r
494         }\r
495 \r
496         return TPI_ERROR_SUCCESS;\r
497 }\r
498 \r
499 #ifdef __cplusplus\r
500 }\r
501 #endif\r