OSDN Git Service

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