OSDN Git Service

バッファのサイズ指定が不適切であったのを修正。
[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         default:\r
111                 return TPI_ERROR_D_PARAMETER;\r
112         }\r
113         return TPI_ERROR_SUCCESS;\r
114 }\r
115 \r
116 int __stdcall GetFormatInformation(TPI_FORMATINFO *, bool)\r
117 {\r
118         return TPI_ERROR_D_UNSUPPORTED;\r
119 }\r
120 \r
121 int __stdcall LoadPlugin\r
122 (\r
123         const wxString & _szArcName,\r
124         wxULongLong_t\r
125 )\r
126 {\r
127         // ファイルを開く。\r
128         wxFile hFile;\r
129         if (! hFile.Exists(_szArcName) || ! hFile.Open(_szArcName, wxFile::read))\r
130         {\r
131                 return TPI_ERROR_IO_ARC_OPEN;\r
132         }\r
133 \r
134         // 最初の2KBを読み込み。\r
135         char buffer[2050];\r
136         ::ZeroMemory(buffer, sizeof(buffer));\r
137         if (hFile.Read(buffer, sizeof(buffer)) == wxInvalidOffset)\r
138         {\r
139                 hFile.Close();\r
140                 return TPI_ERROR_IO_ARC_READ;\r
141         }\r
142         hFile.Close();\r
143 \r
144         wxStandardPaths p;\r
145         wxString szSPIPath = wxPathOnly(p.GetExecutablePath()) + wxT("/lib/"), szSPIName;\r
146         wxDir fs(szSPIPath);\r
147         if (fs.GetFirst(& szSPIName, wxT("*.spi")))\r
148         {\r
149                 do\r
150                 {\r
151                         // SPIをロード。\r
152                         g_hLib = ::LoadLibrary((szSPIPath + szSPIName).wchar_str());\r
153                         if (g_hLib == NULL)\r
154                         {\r
155                                 continue;\r
156                         }\r
157 \r
158                         // GetPluginInfoを実行。\r
159                         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");\r
160                         char szPluginType[5]; // 種類4bytes + NULL\r
161                         if (fpProc == NULL\r
162                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szPluginType, sizeof(szPluginType)) <= 0\r
163                                 || szPluginType[2] != 'I' || szPluginType[3] != 'N')\r
164                         {\r
165                                 ::FreeLibrary(g_hLib);\r
166                                 continue;\r
167                         }\r
168 \r
169                         // 書庫に対応しているかチェック。\r
170                         fpProc = ::GetProcAddress(g_hLib, "IsSupported");\r
171                         if (fpProc == NULL)\r
172                         {\r
173                                 ::FreeLibrary(g_hLib);\r
174                                 continue;\r
175                         }\r
176 \r
177                         if (((BOOL (PASCAL *)(const char *, unsigned long)) fpProc)(_szArcName.ToUTF8(), (unsigned long) buffer))\r
178                         {\r
179                                 // 対応していれば処理を終了。\r
180                                 return TPI_ERROR_SUCCESS;\r
181                         }\r
182                 }\r
183                 while (fs.GetNext(& szSPIName));\r
184         }\r
185         return TPI_ERROR_U_LOAD_LIBRARY;\r
186 }\r
187 \r
188 int __stdcall FreePlugin\r
189 (\r
190         void * // _pReserved\r
191 )\r
192 {\r
193         ::FreeLibrary(g_hLib);\r
194         return TPI_ERROR_SUCCESS;\r
195 }\r
196 \r
197 int __stdcall OpenArchive\r
198 (\r
199         const wxString & _szArcName,\r
200         void * * _hArchive,\r
201         wxULongLong_t *\r
202 )\r
203 {\r
204         * _hArchive = new wxString(_szArcName);\r
205         return TPI_ERROR_SUCCESS;\r
206 }\r
207 \r
208 int __stdcall CloseArchive\r
209 (\r
210         void * _hArchive\r
211 )\r
212 {\r
213         delete (wxString *) _hArchive;\r
214         return TPI_ERROR_SUCCESS;\r
215 }\r
216 \r
217 int __stdcall GetFileInformation\r
218 (\r
219         void * _hArchive,\r
220         TPI_FILEINFO * _fiInfo,\r
221         bool _bFirst\r
222 )\r
223 {\r
224         static wxString szXPIPath, szXPIName, szArcName = * (wxString *) _hArchive;\r
225         static int nColorDepth;\r
226         static wxDir fs;\r
227         if (_bFirst)\r
228         {\r
229                 wxStandardPaths p;\r
230                 szXPIPath = wxPathOnly(p.GetExecutablePath()) + wxT("/lib/");\r
231                 fs.Open(szXPIPath);\r
232 \r
233                 // 画像の情報を取得。\r
234                 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
235                 if (fpProc == NULL)\r
236                 {\r
237                         return TPI_ERROR_U_USE_LIBRARY;\r
238                 }\r
239                 PictureInfo picInfo;\r
240                 int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(szArcName.ToUTF8(), 0, 0, & picInfo));\r
241                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
242                 {\r
243                         return nErrorCode;\r
244                 }\r
245                 nColorDepth = picInfo.colorDepth;\r
246                 ::LocalUnlock(picInfo.hInfo);\r
247                 ::LocalFree(picInfo.hInfo);\r
248         }\r
249 \r
250         if (_bFirst ? fs.GetFirst(& szXPIName, wxT("*.xpi")) : fs.GetNext(& szXPIName))\r
251         {\r
252                 do\r
253                 {\r
254                         // XPIをロード。\r
255                         HMODULE hXPI = ::LoadLibrary((szXPIPath + szXPIName).wchar_str());\r
256                         if (hXPI == NULL)\r
257                         {\r
258                                 continue;\r
259                         }\r
260 \r
261                         // GetPluginInfoを実行。\r
262                         FARPROC fpProc = ::GetProcAddress(hXPI, "GetPluginInfo");\r
263                         char szTemp[20];\r
264                         if (fpProc == NULL\r
265                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szTemp, sizeof(szTemp)) <= 0\r
266                                 || szTemp[2] != 'X' || szTemp[3] != 'N'\r
267                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) <= 0)\r
268                         {\r
269                                 ::FreeLibrary(hXPI);\r
270                                 continue;\r
271                         }\r
272 \r
273                         // 対応確認。\r
274                         fpProc = ::GetProcAddress(hXPI, "IsSupported");\r
275                         if (fpProc == NULL || ! ((BOOL (PASCAL *)(int)) fpProc)(nColorDepth))\r
276                         {\r
277                                 ::FreeLibrary(hXPI);\r
278                                 continue;\r
279                         }\r
280 \r
281                         _fiInfo->fnFileName = wxFileName(szArcName);\r
282                         _fiInfo->fnFileName.SetVolume(wxEmptyString);\r
283                         _fiInfo->fnFileName.SetPath(szXPIName);\r
284                         _fiInfo->fnFileName.SetExt(MB2String(szTemp));\r
285                         _fiInfo->szStoredName = _fiInfo->fnFileName.GetFullPath();\r
286                         return TPI_ERROR_SUCCESS;\r
287                 }\r
288                 while (fs.GetNext(& szXPIName));\r
289         }\r
290         return TPI_ERROR_S_ENDOFDATA;\r
291 }\r
292 \r
293 int __stdcall GetArchiveInformation\r
294 (\r
295         void * _hArchive,\r
296         TPI_ARCHIVEINFO * _aiInfo\r
297 )\r
298 {\r
299         // 画像の情報を取得。\r
300         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
301         if (fpProc == NULL)\r
302         {\r
303                 return TPI_ERROR_U_USE_LIBRARY;\r
304         }\r
305         PictureInfo piInfo;\r
306         int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(((wxString *) _hArchive)->ToUTF8(), 0, 0, & piInfo));\r
307         if (nErrorCode != TPI_ERROR_SUCCESS)\r
308         {\r
309                 return nErrorCode;\r
310         }\r
311         _aiInfo->szComment = MB2String((char *) ::LocalLock(piInfo.hInfo));\r
312         ::LocalUnlock(piInfo.hInfo);\r
313         ::LocalFree(piInfo.hInfo);\r
314 \r
315         // GetPluginInfoを実行。\r
316         fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");\r
317         if (fpProc != NULL)\r
318         {\r
319                 char szTemp[257];\r
320                 memset(szTemp, 0, sizeof(szTemp));\r
321                 if (((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp) - 1) > 0)\r
322                 {\r
323                         _aiInfo->fiInfo.szSuffix = MB2String(szTemp);\r
324                 }\r
325                 if (((int (PASCAL *)(int, char *, int)) fpProc)(3, szTemp, sizeof(szTemp) - 1) > 0)\r
326                 {\r
327                         _aiInfo->fiInfo.szTypeName = MB2String(szTemp);\r
328                 }\r
329         }\r
330         _aiInfo->fiInfo.fArchive = false;\r
331         _aiInfo->fiInfo.szTPIName = wxT("xpiLibrary");\r
332         _aiInfo->fiInfo.eSupportedCommand = TPI_COMMAND_EXTRACT;\r
333 \r
334         return TPI_ERROR_SUCCESS;\r
335 }\r
336 \r
337 int __stdcall Command\r
338 (\r
339         wxULongLong_t _eCommand,\r
340         TPI_SWITCHES * _swInfo,\r
341         const wxString & _szArcName,\r
342         const wxArrayString & _asFiles\r
343 )\r
344 {\r
345         if (_eCommand != TPI_COMMAND_EXTRACT)\r
346         {\r
347                 return TPI_ERROR_D_UNSUPPORTED;\r
348         }\r
349 \r
350         // 画像の情報を取得。\r
351         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
352         if (fpProc == NULL)\r
353         {\r
354                 return TPI_ERROR_U_USE_LIBRARY;\r
355         }\r
356         PictureInfo picInfo;\r
357         int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(_szArcName.ToUTF8(), 0, 0, & picInfo));\r
358         if (nErrorCode != TPI_ERROR_SUCCESS)\r
359         {\r
360                 return nErrorCode;\r
361         }\r
362 \r
363         // コールバックを送信。\r
364         wxFileName _fnArcName(_szArcName);\r
365         TPI_PROCESSINFO piInfo;\r
366         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
367         piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
368         piInfo.fiInfo.fnFileName = _fnArcName;\r
369         if (CallbackProc(0, 0, (long) & piInfo))\r
370         {\r
371                 return TPI_ERROR_D_SKIPPED;\r
372         }\r
373 \r
374         // メモリ上に展開。\r
375         HANDLE hInfo, hMemory;\r
376         fpProc = ::GetProcAddress(g_hLib, "GetPicture");\r
377         if (fpProc == NULL)\r
378         {\r
379                 return TPI_ERROR_U_USE_LIBRARY;\r
380         }\r
381         nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, HANDLE *, HANDLE *, FARPROC, long)) fpProc)(_szArcName.ToUTF8(), 0, 0, & hInfo, & hMemory, (FARPROC) CallbackProc, (long) & piInfo));\r
382         if (nErrorCode == TPI_ERROR_SUCCESS && (hMemory == NULL || hInfo == NULL))\r
383         {\r
384                 return TPI_ERROR_UNDEFINED;\r
385         }\r
386         if (nErrorCode != TPI_ERROR_SUCCESS)\r
387         {\r
388                 return nErrorCode;\r
389         }\r
390 \r
391         wxString szXPIPath;\r
392         {\r
393                 wxStandardPaths p;\r
394                 szXPIPath = wxPathOnly(p.GetExecutablePath()) + wxT("/lib/");\r
395         }\r
396 \r
397         for (size_t i = 0; i < _asFiles.GetCount(); i++)\r
398         {\r
399                 // 処理を行うか確認。\r
400                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
401                 piInfo.eStatus = TPI_PARAM_DEST;\r
402                 piInfo.fiInfo.fnFileName = wxFileName(_asFiles[i]);\r
403                 piInfo.fnDestination = piInfo.fiInfo.fnFileName;\r
404                 piInfo.fnDestination.SetPath(_swInfo->fnDestinationDirectory.GetPath());\r
405                 if (CallbackProc(0, 0, (long) & piInfo))\r
406                 {\r
407                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
408                         break;\r
409                 }\r
410                 if (! piInfo.fnDestination.IsOk())\r
411                 {\r
412                         continue;\r
413                 }\r
414 \r
415                 // XPIをロード。\r
416                 HMODULE hXPI = ::LoadLibrary((szXPIPath + piInfo.fiInfo.fnFileName.GetPath()).wchar_str());\r
417                 if (hXPI == NULL)\r
418                 {\r
419                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
420                         break;\r
421                 }\r
422 \r
423                 // GetPluginInfoを実行。\r
424                 FARPROC fpProc = ::GetProcAddress(hXPI, "GetPluginInfo");\r
425                 char szTemp[20];\r
426                 if (fpProc == NULL\r
427                         || ((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) <= 0)\r
428                 {\r
429                         ::FreeLibrary(hXPI);\r
430                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
431                         break;\r
432                 }\r
433 \r
434                 // コールバックを送信。\r
435                 piInfo.eMessage = TPI_MESSAGE_STATUS;\r
436                 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;\r
437                 if (CallbackProc(0, 0, (long) & piInfo))\r
438                 {\r
439                         ::FreeLibrary(hXPI);\r
440                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
441                         break;\r
442                 }\r
443 \r
444                 // 書き込み。\r
445                 piInfo.eStatus = TPI_STATUS_INPROCESS;\r
446                 fpProc = ::GetProcAddress(hXPI, "CreatePicture");\r
447                 if (fpProc == NULL)\r
448                 {\r
449                         ::FreeLibrary(hXPI);\r
450                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
451                         break;\r
452                 }\r
453                 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
454                 ::FreeLibrary(hXPI);\r
455 \r
456                 // 最後にコールバックを送信。\r
457                 piInfo.eStatus  = TPI_STATUS_ENDPROCESS;\r
458                 if (CallbackProc(0, 0, (long) & piInfo))\r
459                 {\r
460                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
461                         break;\r
462                 }\r
463         }\r
464         ::LocalUnlock(hInfo);\r
465         ::LocalUnlock(hMemory);\r
466         ::LocalUnlock(picInfo.hInfo);\r
467         ::LocalFree(hInfo);\r
468         ::LocalFree(hMemory);\r
469         ::LocalFree(picInfo.hInfo);\r
470         if (nErrorCode != TPI_ERROR_SUCCESS)\r
471         {\r
472                 return nErrorCode;\r
473         }\r
474 \r
475         // 最終のコールバック。\r
476         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
477         piInfo.eStatus  = TPI_STATUS_CLOSEARCHIVE;\r
478         piInfo.fiInfo.fnFileName = _fnArcName;\r
479         if (CallbackProc(0, 0, (long) & piInfo))\r
480         {\r
481                 return TPI_ERROR_D_SKIPPED;\r
482         }\r
483 \r
484         return TPI_ERROR_SUCCESS;\r
485 }\r
486 \r
487 int __stdcall SetCallbackProc\r
488 (\r
489         TPI_PROC _prArcProc\r
490 )\r
491 {\r
492         // ポインタを保存。\r
493         if (_prArcProc == NULL)\r
494         {\r
495                 return TPI_ERROR_D_PARAMETER;\r
496         }\r
497         g_prProc = * _prArcProc;\r
498 \r
499         return TPI_ERROR_SUCCESS;\r
500 }\r
501 \r
502 #ifdef __cplusplus\r
503 }\r
504 #endif\r