OSDN Git Service

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