OSDN Git Service

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