OSDN Git Service

01dad010b55713fe3fdfc9698e0f9d3985334568
[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         if (_bFirst)\r
261         {\r
262                 wxStandardPaths p;\r
263                 szXPIPath = wxPathOnly(p.GetExecutablePath()) + wxT("/lib/");\r
264                 fs.Open(szXPIPath);\r
265 \r
266                 // 画像の情報を取得。\r
267                 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
268                 if (fpProc == NULL)\r
269                 {\r
270                         return TPI_ERROR_U_USE_LIBRARY;\r
271                 }\r
272                 PictureInfo picInfo;\r
273                 int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(szArcName.ToUTF8(), 0, 0, & picInfo));\r
274                 if (nErrorCode != TPI_ERROR_SUCCESS)\r
275                 {\r
276                         return nErrorCode;\r
277                 }\r
278                 nColorDepth = picInfo.colorDepth;\r
279                 ::LocalUnlock(picInfo.hInfo);\r
280                 ::LocalFree(picInfo.hInfo);\r
281         }\r
282 \r
283         if (_bFirst ? fs.GetFirst(& szXPIName, wxT("*.xpi")) : fs.GetNext(& szXPIName))\r
284         {\r
285                 do\r
286                 {\r
287                         // XPIをロード。\r
288                         wxString szLibName = szXPIPath + szXPIName;\r
289                         HMODULE hXPI = ::LoadLibrary(szLibName.wchar_str());\r
290                         if (hXPI == NULL)\r
291                         {\r
292                                 continue;\r
293                         }\r
294 \r
295                         // GetPluginInfoを実行。\r
296                         FARPROC fpProc = ::GetProcAddress(hXPI, "GetPluginInfo");\r
297                         char szTemp[20];\r
298                         if (fpProc == NULL\r
299                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szTemp, sizeof(szTemp)) <= 0\r
300                                 || szTemp[2] != 'X' || szTemp[3] != 'N'\r
301                                 || ((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) <= 0)\r
302                         {\r
303                                 ::FreeLibrary(hXPI);\r
304                                 continue;\r
305                         }\r
306 \r
307                         // 対応確認。\r
308                         fpProc = ::GetProcAddress(hXPI, "IsSupported");\r
309                         if (fpProc == NULL || ! ((BOOL (PASCAL *)(int)) fpProc)(nColorDepth))\r
310                         {\r
311                                 ::FreeLibrary(hXPI);\r
312                                 continue;\r
313                         }\r
314 \r
315                         _fiInfo->fnFileName = wxFileName(szArcName);\r
316                         _fiInfo->fnFileName.SetVolume(wxEmptyString);\r
317                         _fiInfo->fnFileName.SetPath(szXPIName);\r
318                         _fiInfo->fnFileName.SetExt(MB2String(szTemp));\r
319                         _fiInfo->szStoredName = _fiInfo->fnFileName.GetFullPath();\r
320                         return TPI_ERROR_SUCCESS;\r
321                 }\r
322                 while (fs.GetNext(& szXPIName));\r
323         }\r
324         return TPI_ERROR_S_ENDOFDATA;\r
325 }\r
326 \r
327 int __stdcall GetArchiveInformation\r
328 (\r
329         void * _hArchive,\r
330         TPI_ARCHIVEINFO * _aiInfo\r
331 )\r
332 {\r
333         // 画像の情報を取得。\r
334         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
335         if (fpProc == NULL)\r
336         {\r
337                 return TPI_ERROR_U_USE_LIBRARY;\r
338         }\r
339         PictureInfo piInfo;\r
340         int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(((wxString *) _hArchive)->ToUTF8(), 0, 0, & piInfo));\r
341         if (nErrorCode != TPI_ERROR_SUCCESS)\r
342         {\r
343                 return nErrorCode;\r
344         }\r
345         _aiInfo->szComment = MB2String((char *) ::LocalLock(piInfo.hInfo));\r
346         ::LocalUnlock(piInfo.hInfo);\r
347         ::LocalFree(piInfo.hInfo);\r
348 \r
349         // GetPluginInfoを実行。\r
350         fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");\r
351         if (fpProc != NULL)\r
352         {\r
353                 char szTemp[20];\r
354                 if (((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) > 0)\r
355                 {\r
356                         _aiInfo->fiInfo.szSuffix = MB2String(szTemp);\r
357                 }\r
358                 if (((int (PASCAL *)(int, char *, int)) fpProc)(3, szTemp, sizeof(szTemp)) > 0)\r
359                 {\r
360                         _aiInfo->fiInfo.szTypeName = MB2String(szTemp);\r
361                 }\r
362         }\r
363         _aiInfo->fiInfo.fArchive = false;\r
364         _aiInfo->fiInfo.szTPIName = wxT("xpiLibrary");\r
365         _aiInfo->fiInfo.eSupportedCommand = TPI_COMMAND_EXTRACT;\r
366 \r
367         return TPI_ERROR_SUCCESS;\r
368 }\r
369 \r
370 int __stdcall Command\r
371 (\r
372         wxULongLong_t _eCommand,\r
373         TPI_SWITCHES * _swInfo,\r
374         const wxString & _szArcName,\r
375         const wxArrayString & _asFiles\r
376 )\r
377 {\r
378         if (_eCommand != TPI_COMMAND_EXTRACT)\r
379         {\r
380                 return TPI_ERROR_D_UNSUPPORTED;\r
381         }\r
382 \r
383         // 画像の情報を取得。\r
384         FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPictureInfo");\r
385         if (fpProc == NULL)\r
386         {\r
387                 return TPI_ERROR_U_USE_LIBRARY;\r
388         }\r
389         PictureInfo picInfo;\r
390         int nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, PictureInfo *)) fpProc)(_szArcName.ToUTF8(), 0, 0, & picInfo));\r
391         if (nErrorCode != TPI_ERROR_SUCCESS)\r
392         {\r
393                 return nErrorCode;\r
394         }\r
395 \r
396         // コールバックを送信。\r
397         wxFileName _fnArcName(_szArcName);\r
398         TPI_PROCESSINFO piInfo;\r
399         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
400         piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
401         piInfo.fiInfo.fnFileName = _fnArcName;\r
402         if (CallbackProc(0, 0, (long) & piInfo))\r
403         {\r
404                 return TPI_ERROR_D_SKIPPED;\r
405         }\r
406 \r
407         // メモリ上に展開。\r
408         HANDLE hInfo, hMemory;\r
409         fpProc = ::GetProcAddress(g_hLib, "GetPicture");\r
410         if (fpProc == NULL)\r
411         {\r
412                 return TPI_ERROR_U_USE_LIBRARY;\r
413         }\r
414         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
415         if (nErrorCode == TPI_ERROR_SUCCESS && (hMemory == NULL || hInfo == NULL))\r
416         {\r
417                 return TPI_ERROR_UNDEFINED;\r
418         }\r
419         if (nErrorCode != TPI_ERROR_SUCCESS)\r
420         {\r
421                 return nErrorCode;\r
422         }\r
423 \r
424         for (size_t i = 0; i < _asFiles.GetCount(); i++)\r
425         {\r
426                 // XPIをロード。\r
427                 HMODULE hXPI = ::LoadLibrary(wxFileName(_asFiles[i]).GetPath().wchar_str());\r
428                 if (hXPI == NULL)\r
429                 {\r
430                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
431                         break;\r
432                 }\r
433 \r
434                 // GetPluginInfoを実行。\r
435                 FARPROC fpProc = ::GetProcAddress(hXPI, "GetPluginInfo");\r
436                 char szTemp[20];\r
437                 if (fpProc == NULL\r
438                         || ((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) <= 0)\r
439                 {\r
440                         ::FreeLibrary(hXPI);\r
441                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
442                         break;\r
443                 }\r
444 \r
445                 // コールバックを送信。\r
446                 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;\r
447                 piInfo.fiInfo.fnFileName = wxFileName(_asFiles[i]);\r
448                 piInfo.fnDestination = piInfo.fiInfo.fnFileName;\r
449                 piInfo.fnDestination.SetPath(_swInfo->fnDestinationDirectory.GetPath());\r
450                 if (CallbackProc(0, 0, (long) & piInfo))\r
451                 {\r
452                         ::FreeLibrary(hXPI);\r
453                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
454                         break;\r
455                 }\r
456 \r
457                 // 書き込み。\r
458                 piInfo.eStatus = TPI_STATUS_INPROCESS;\r
459                 fpProc = ::GetProcAddress(hXPI, "CreatePicture");\r
460                 if (fpProc == NULL)\r
461                 {\r
462                         ::FreeLibrary(hXPI);\r
463                         nErrorCode = TPI_ERROR_U_USE_LIBRARY;\r
464                         break;\r
465                 }\r
466                 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
467                 ::FreeLibrary(hXPI);\r
468 \r
469                 // 最後にコールバックを送信。\r
470                 piInfo.eStatus  = TPI_STATUS_ENDPROCESS;\r
471                 if (CallbackProc(0, 0, (long) & piInfo))\r
472                 {\r
473                         nErrorCode = TPI_ERROR_D_SKIPPED;\r
474                         break;\r
475                 }\r
476         }\r
477         ::LocalUnlock(hInfo);\r
478         ::LocalUnlock(hMemory);\r
479         ::LocalUnlock(picInfo.hInfo);\r
480         ::LocalFree(hInfo);\r
481         ::LocalFree(hMemory);\r
482         ::LocalFree(picInfo.hInfo);\r
483         if (nErrorCode != TPI_ERROR_SUCCESS)\r
484         {\r
485                 return nErrorCode;\r
486         }\r
487 \r
488         // 最終のコールバック。\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 int __stdcall SetCallbackProc\r
500 (\r
501         TPI_PROC _prArcProc\r
502 )\r
503 {\r
504         // ポインタを保存。\r
505         if (_prArcProc == NULL)\r
506         {\r
507                 return TPI_ERROR_D_PARAMETER;\r
508         }\r
509         g_prProc = * _prArcProc;\r
510 \r
511         return TPI_ERROR_SUCCESS;\r
512 }\r
513 \r
514 #ifdef __cplusplus\r
515 }\r
516 #endif\r