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