1 /*******************************************************************************
\r
2 TPI - flexible but useless plug-in framework.
\r
3 Copyright (C) 2002-2009 Silky
\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
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
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
20 *******************************************************************************/
\r
22 //******************************************************************************
\r
24 //******************************************************************************
\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
32 #include <windows.h>
\r
33 #include "spiLibrary.h"
\r
35 //******************************************************************************
\r
37 //******************************************************************************
\r
42 //******************************************************************************
\r
44 //******************************************************************************
\r
46 int __stdcall CallbackProc(int _nNow, int, long _lData)
\r
49 TPI_PROCESSINFO * piInfo = (TPI_PROCESSINFO *) _lData;
\r
50 piInfo->nProcessedSize = _nNow;
\r
53 return g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, piInfo) == TPI_CALLBACK_CANCEL;
\r
56 //******************************************************************************
\r
58 //******************************************************************************
\r
60 int ErrorCodeConvert(int nErrorCode)
\r
64 case -1: return TPI_ERROR_U_USE_LIBRARY;
\r
65 case 0: return TPI_ERROR_SUCCESS;
\r
66 case 1: return TPI_ERROR_D_SKIPPED;
\r
67 case 2: return TPI_ERROR_ARC_UNSUPPORTED;
\r
68 case 3: return TPI_ERROR_ARC_BROKEN_MISC;
\r
69 case 4: return TPI_ERROR_D_OUTOFMEMORY;
\r
70 case 5: return TPI_ERROR_D_USEMEMORY;
\r
71 case 6: return TPI_ERROR_IO_ARC_READ;
\r
72 default: return TPI_ERROR_UNDEFINED;
\r
76 //******************************************************************************
\r
78 //******************************************************************************
\r
85 int __stdcall GetPluginInformation
\r
87 unsigned int _uInfoId,
\r
94 return TPI_ERROR_D_PARAMETER;
\r
98 case TPI_INFO_VERSION_MAJOR:
\r
99 case TPI_INFO_VERSION_MINOR:
\r
100 * (int *) _pPtr = 0;
\r
102 case TPI_INFO_VERSION_API:
\r
103 * (int *) _pPtr = 2;
\r
106 return TPI_ERROR_D_PARAMETER;
\r
108 return TPI_ERROR_SUCCESS;
\r
111 int __stdcall GetFormatInformation(TPI_FORMATINFO *, bool)
\r
113 return TPI_ERROR_D_UNSUPPORTED;
\r
116 int __stdcall LoadPlugin
\r
118 const wxString & _szArcName,
\r
124 if (! hFile.Exists(_szArcName) || ! hFile.Open(_szArcName, wxFile::read))
\r
126 return TPI_ERROR_IO_ARC_OPEN;
\r
131 ::ZeroMemory(buffer, sizeof(buffer));
\r
132 if (hFile.Read(buffer, sizeof(buffer)) == wxInvalidOffset)
\r
135 return TPI_ERROR_IO_ARC_READ;
\r
140 wxString szSPIPath = wxPathOnly(p.GetExecutablePath()) + wxT("/lib/"), szSPIName;
\r
141 wxDir fs(szSPIPath);
\r
142 if (fs.GetFirst(& szSPIName, wxT("*.spi")))
\r
147 g_hLib = ::LoadLibrary((szSPIPath + szSPIName).wchar_str());
\r
148 if (g_hLib == NULL)
\r
153 // GetPluginInfoを実行。
\r
154 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");
\r
155 char szPluginType[5]; // 種類4bytes + NULL
\r
157 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szPluginType, sizeof(szPluginType)) <= 0
\r
158 || szPluginType[2] != 'A' || szPluginType[3] != 'M')
\r
160 ::FreeLibrary(g_hLib);
\r
165 fpProc = ::GetProcAddress(g_hLib, "IsSupported");
\r
166 if (fpProc == NULL)
\r
168 ::FreeLibrary(g_hLib);
\r
172 if (((BOOL (PASCAL *)(const char *, unsigned long)) fpProc)(_szArcName.ToUTF8(), (unsigned long) buffer))
\r
175 return TPI_ERROR_SUCCESS;
\r
178 while (fs.GetNext(& szSPIName));
\r
180 return TPI_ERROR_U_LOAD_LIBRARY;
\r
183 int __stdcall FreePlugin
\r
185 void * // _pReserved
\r
188 ::FreeLibrary(g_hLib);
\r
189 return TPI_ERROR_SUCCESS;
\r
192 int __stdcall OpenArchive
\r
194 const wxString & _szArcName,
\r
195 void * * _hArchive,
\r
196 wxULongLong_t * _nFileCount
\r
199 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetArchiveInfo");
\r
200 if (fpProc == NULL)
\r
202 return TPI_ERROR_U_USE_LIBRARY;
\r
205 int nReturnCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, HLOCAL *)) fpProc)(_szArcName.ToUTF8(), 0, 0, _hArchive));
\r
206 if (nReturnCode != TPI_ERROR_SUCCESS)
\r
208 return nReturnCode;
\r
210 if (_nFileCount != NULL)
\r
212 * _nFileCount = ::LocalSize(* _hArchive) / sizeof(fileInfo);
\r
214 return * _hArchive == NULL ? TPI_ERROR_IO_ARC_OPEN : nReturnCode;
\r
217 int __stdcall CloseArchive
\r
222 return ::LocalFree(_hArchive) == NULL ? TPI_ERROR_SUCCESS : TPI_ERROR_IO_ARC_CLOSE;
\r
225 int __stdcall GetFileInformation
\r
228 TPI_FILEINFO * _fiInfo,
\r
232 static wxULongLong_t nFileCount, nFilePointer;
\r
237 nFileCount = ::LocalSize(_hArchive) / sizeof(fileInfo);
\r
240 if (nFilePointer > nFileCount)
\r
242 return TPI_ERROR_S_ENDOFDATA;
\r
245 fileInfo pfiInfo = ((fileInfo *) ::LocalLock(_hArchive))[nFilePointer];
\r
246 if (pfiInfo.method[0] == 0)
\r
248 // 丁寧なプラグインのための数合わせ (^^;
\r
249 nFileCount = nFilePointer;
\r
250 return TPI_ERROR_S_ENDOFDATA;
\r
253 _fiInfo->dwAttribute = 0;
\r
254 _fiInfo->dwCRC32 = pfiInfo.crc;
\r
255 _fiInfo->nPackedSize = pfiInfo.compsize;
\r
256 _fiInfo->nUnpackedSize = pfiInfo.filesize;
\r
257 _fiInfo->wCompressRatio = pfiInfo.compsize >= pfiInfo.filesize ? 1000 : (WORD) (1000 * pfiInfo.compsize / pfiInfo.filesize);
\r
258 _fiInfo->nFileId = nFilePointer++;
\r
259 _fiInfo->tmModified = pfiInfo.timestamp;
\r
260 _fiInfo->szStoredName = MB2String(pfiInfo.path) + MB2String(pfiInfo.filename);
\r
261 _fiInfo->fnFileName = wxFileName(_fiInfo->szStoredName);
\r
262 _fiInfo->szMethod = MB2String((char *) pfiInfo.method);
\r
263 _fiInfo->pCustomInfo = (void *) pfiInfo.position;
\r
264 ::LocalUnlock(_hArchive);
\r
266 return TPI_ERROR_SUCCESS;
\r
269 int __stdcall GetArchiveInformation
\r
272 TPI_ARCHIVEINFO * _aiInfo
\r
275 // GetPluginInfoを実行。
\r
276 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");
\r
277 if (fpProc != NULL)
\r
280 memset(szTemp, 0, sizeof(szTemp));
\r
281 if (((int (PASCAL *)(int, char *, int)) fpProc)(1, szTemp, sizeof(szTemp) - 1) > 0)
\r
283 _aiInfo->fiInfo.szEngineName = MB2String(szTemp);
\r
285 if (((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp) - 1) > 0)
\r
287 _aiInfo->fiInfo.szSuffix = MB2String(szTemp);
\r
289 if (((int (PASCAL *)(int, char *, int)) fpProc)(3, szTemp, sizeof(szTemp) - 1) > 0)
\r
291 _aiInfo->fiInfo.szTypeName = MB2String(szTemp);
\r
294 _aiInfo->fiInfo.szTPIName = wxT("spiLibrary");
\r
295 _aiInfo->fiInfo.eSupportedCommand = TPI_COMMAND_EXTRACT;
\r
297 return TPI_ERROR_SUCCESS;
\r
300 int __stdcall Command
\r
302 wxULongLong_t _eCommand,
\r
303 TPI_SWITCHES * _swInfo,
\r
304 const wxString & _szArcName,
\r
305 const wxArrayString & _szFiles
\r
308 if (_eCommand != TPI_COMMAND_EXTRACT)
\r
310 return TPI_ERROR_D_UNSUPPORTED;
\r
314 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetFile");
\r
315 if (fpProc == NULL)
\r
317 return TPI_ERROR_U_USE_LIBRARY;
\r
322 int nErrorCode = OpenArchive(_szArcName, & hArchive);
\r
323 if (nErrorCode != TPI_ERROR_SUCCESS)
\r
329 wxFileName _fnArcName(_szArcName);
\r
330 TPI_PROCESSINFO piInfo;
\r
331 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
332 piInfo.eStatus = TPI_STATUS_OPENARCHIVE;
\r
333 piInfo.fiInfo.fnFileName = _fnArcName;
\r
334 if (CallbackProc(0, 0, (long) & piInfo))
\r
336 return TPI_ERROR_D_SKIPPED;
\r
340 piInfo.eStatus = TPI_STATUS_INPROCESS;
\r
341 nErrorCode = GetFileInformation(hArchive, & piInfo.fiInfo, true);
\r
342 if (nErrorCode == TPI_ERROR_SUCCESS)
\r
347 if ((! _szFiles.IsEmpty()) && _szFiles.Index(piInfo.fiInfo.szStoredName) == wxNOT_FOUND)
\r
353 piInfo.eMessage = TPI_MESSAGE_ASK;
\r
354 piInfo.eStatus = TPI_PARAM_DEST;
\r
355 piInfo.fnDestination = wxFileName(_swInfo->fnDestinationDirectory.GetPathWithSep() + (_swInfo->fStoreDirectoryPathes ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetFullName()));
\r
356 if (CallbackProc(0, 0, (long) & piInfo))
\r
358 nErrorCode = TPI_ERROR_D_SKIPPED;
\r
361 if (! piInfo.fnDestination.IsOk())
\r
367 if (! piInfo.fnDestination.Mkdir(0777, wxPATH_MKDIR_FULL))
\r
369 nErrorCode = TPI_ERROR_IO_DIR_WRITE;
\r
374 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
375 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;
\r
376 if (CallbackProc(0, 0, (long) & piInfo))
\r
378 nErrorCode = TPI_ERROR_D_SKIPPED;
\r
381 piInfo.eStatus = TPI_STATUS_INPROCESS;
\r
383 // ファイル出力には対応してないのでメモリ出力で代行。
\r
384 HLOCAL hMemory = NULL;
\r
385 nErrorCode = ErrorCodeConvert(((int (PASCAL *)(const char *, long, char *, unsigned int, FARPROC, long)) fpProc)(_szArcName.ToUTF8(), (long) piInfo.fiInfo.pCustomInfo, (char *) & hMemory, 0x0100, (FARPROC) CallbackProc, (long) & piInfo));
\r
386 if (nErrorCode == TPI_ERROR_SUCCESS && hMemory == NULL)
\r
388 nErrorCode = TPI_ERROR_UNDEFINED;
\r
390 if (nErrorCode != TPI_ERROR_SUCCESS)
\r
397 if (! hFile.Create(piInfo.fnDestination.GetFullPath()))
\r
399 nErrorCode = TPI_ERROR_IO_FILE_OPEN;
\r
403 bool bErrorOccured = hFile.Write(::LocalLock(hMemory), piInfo.fiInfo.nUnpackedSize) != piInfo.fiInfo.nUnpackedSize;
\r
404 ::LocalUnlock(hMemory);
\r
405 ::LocalFree(hMemory);
\r
409 nErrorCode = TPI_ERROR_IO_FILE_WRITE;
\r
412 nErrorCode = TPI_ERROR_SUCCESS;
\r
415 piInfo.eStatus = TPI_STATUS_ENDPROCESS;
\r
416 if (CallbackProc(0, 0, (long) & piInfo))
\r
418 nErrorCode = TPI_ERROR_D_SKIPPED;
\r
422 while ((nErrorCode = GetFileInformation(hArchive, & piInfo.fiInfo, false)) != TPI_ERROR_S_ENDOFDATA);
\r
423 if (nErrorCode == TPI_ERROR_S_ENDOFDATA)
\r
426 nErrorCode = TPI_ERROR_SUCCESS;
\r
429 CloseArchive(hArchive);
\r
434 int __stdcall SetCallbackProc
\r
436 TPI_PROC _prArcProc
\r
440 if (_prArcProc == NULL)
\r
442 return TPI_ERROR_D_PARAMETER;
\r
444 g_prProc = * _prArcProc;
\r
446 return TPI_ERROR_SUCCESS;
\r