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
19 $Id: spiLibrary.cpp,v 1.9 2009/08/23 04:25:53 sirakaba Exp $
\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/dynlib.h>
\r
30 #include <wx/file.h>
\r
31 #include <wx/config.h>
\r
32 #include <wx/wfstream.h>
\r
33 #include <wx/stdpaths.h>
\r
34 #include <wx/filesys.h>
\r
36 #include <windows.h>
\r
37 #include <imagehlp.h>
\r
38 #include "spiLibrary.h"
\r
40 //******************************************************************************
\r
42 //******************************************************************************
\r
47 //******************************************************************************
\r
49 //******************************************************************************
\r
52 void __attribute__((destructor)) Detach(void)
\r
54 ::FreeLibrary(g_hLib);
\r
58 BOOL __stdcall DllMain(HMODULE, DWORD fdwReason, void *)
\r
62 case DLL_PROCESS_DETACH:
\r
63 ::FreeLibrary(g_hLib);
\r
70 //******************************************************************************
\r
72 //******************************************************************************
\r
74 int __stdcall CallbackProc(int _nNow, int _nMax, long _lData)
\r
76 //
\8d\
\91¢
\91Ì
\82ð
\8f\89\8aú
\89»
\81B
\r
77 TPI_PROCESSINFO piInfo;
\r
78 piInfo.uMessage = TPI_MESSAGE_STATUS;
\r
79 piInfo.uStatus = _nNow == 0 ? TPI_STATUS_BEGINPROCESS
\r
80 : _nNow == _nMax ? TPI_STATUS_ENDPROCESS
\r
81 : _nNow < 0 ? TPI_STATUS_OPENARCHIVE : TPI_STATUS_INPROCESS;
\r
82 piInfo.llProcessedSize = _nNow;
\r
83 piInfo.fiInfo.llUnpackedSize = _nMax;
\r
84 piInfo.fiInfo.fnFileName = * (wxFileName *) _lData;
\r
86 //
\83R
\81[
\83\8b\83o
\83b
\83N
\8aÖ
\90\94\82É
\91\97\90M
\81B
\r
87 return g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) == TPI_CALLBACK_CANCEL;
\r
90 //******************************************************************************
\r
92 //******************************************************************************
\r
94 int SpiErrorCodeConvert(int nSpiErrorCode)
\r
96 switch (nSpiErrorCode)
\r
98 case -1: return TPI_ERROR_U_USE_LIBRARY;
\r
99 case 0: return TPI_ERROR_SUCCESS;
\r
100 case 1: return TPI_ERROR_D_SKIPPED;
\r
101 case 2: return TPI_ERROR_ARC_UNSUPPORTED;
\r
102 case 3: return TPI_ERROR_ARC_BROKEN_MISC;
\r
103 case 4: return TPI_ERROR_D_OUTOFMEMORY;
\r
104 case 5: return TPI_ERROR_D_USEMEMORY;
\r
105 case 6: return TPI_ERROR_IO_ARC_READ;
\r
106 default: return TPI_ERROR_UNDEFINED;
\r
110 //******************************************************************************
\r
112 //******************************************************************************
\r
119 int __stdcall GetPluginInformation
\r
121 unsigned int _uInfoId,
\r
128 return TPI_ERROR_D_PARAMETER;
\r
130 switch (LOWORD(_uInfoId))
\r
132 case TPI_INFO_VERSION_MAJOR:
\r
133 case TPI_INFO_VERSION_MINOR:
\r
134 * (int *) _pPtr = 0;
\r
136 case TPI_INFO_VERSION_API:
\r
137 * (int *) _pPtr = 2;
\r
140 return TPI_ERROR_D_PARAMETER;
\r
142 return TPI_ERROR_SUCCESS;
\r
145 int __stdcall GetFormatInformation(TPI_FORMATINFO *, bool)
\r
147 return TPI_ERROR_D_UNSUPPORTED;
\r
150 int __stdcall LoadPlugin
\r
152 const wxString & _szArcName,
\r
157 wxString szSPIPath = wxPathOnly(p.GetExecutablePath()) + wxT("/lib/"), szSPIName = wxEmptyString;
\r
158 wxDir fs(szSPIPath);
\r
159 bool b = fs.GetFirst(& szSPIName, wxT("*.spi"));
\r
162 // SPI
\82ð
\83\8d\81[
\83h
\81B
\r
163 wxString szLibName = szSPIPath + szSPIName;
\r
164 g_hLib = ::LoadLibraryA(szLibName.char_str());
\r
165 if (g_hLib == NULL)
\r
167 b = fs.GetNext(& szSPIName);
\r
171 // GetPluginInfo
\82ð
\8eÀ
\8ds
\81B
\r
172 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");
\r
173 char szPluginType[5]; //
\8eí
\97Þ4bytes + NULL
\r
175 || ((int (PASCAL *)(int, char *, int)) fpProc)(0, szPluginType, sizeof(szPluginType)) < 0
\r
176 || szPluginType[2] != 'A' || szPluginType[3] != 'M')
\r
178 ::FreeLibrary(g_hLib);
\r
179 b = fs.GetNext(& szSPIName);
\r
183 //
\8f\91\8cÉ
\82É
\91Î
\89\9e\82µ
\82Ä
\82¢
\82é
\82©
\83`
\83F
\83b
\83N
\81B
\r
184 if (CheckArchive(_szArcName, NULL) == TPI_ERROR_SUCCESS)
\r
186 //
\91Î
\89\9e\82µ
\82Ä
\82¢
\82ê
\82Î
\8f\88\97\9d\82ð
\8fI
\97¹
\81B
\r
187 return TPI_ERROR_SUCCESS;
\r
190 b = fs.GetNext(& szSPIName);
\r
192 return TPI_ERROR_U_LOAD_LIBRARY;
\r
195 int __stdcall FreePlugin
\r
197 void * // _pReserved
\r
200 ::FreeLibrary(g_hLib);
\r
201 return TPI_ERROR_SUCCESS;
\r
204 int __stdcall CheckArchive
\r
206 const wxString & _szArcName,
\r
210 FARPROC fpProc = ::GetProcAddress(g_hLib, "IsSupported");
\r
211 if (fpProc == NULL)
\r
213 return TPI_ERROR_U_USE_LIBRARY;
\r
216 wxFile hFile(_szArcName, wxFile::read);
\r
217 if (! hFile.IsOpened())
\r
219 return TPI_ERROR_IO_ARC_OPEN;
\r
223 ::ZeroMemory(buffer, sizeof(buffer));
\r
224 if (hFile.Read(buffer, sizeof(buffer)) == wxInvalidOffset)
\r
227 return TPI_ERROR_IO_ARC_READ;
\r
230 if (! ((BOOL (PASCAL *)(const char *, unsigned long)) fpProc)(_szArcName.char_str(), (unsigned long) buffer))
\r
233 return TPI_ERROR_D_UNSUPPORTED;
\r
237 fpProc = ::GetProcAddress(g_hLib, "GetArchiveInfo");
\r
238 if (fpProc == NULL)
\r
240 return TPI_ERROR_U_USE_LIBRARY;
\r
244 int nReturnCode = SpiErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, HLOCAL *)) fpProc)(_szArcName.char_str(), 0, 0, & hMemory));
\r
245 if (nReturnCode == TPI_ERROR_SUCCESS)
\r
247 if (_nFileCount != NULL)
\r
249 * _nFileCount = int(::LocalSize(hMemory) / sizeof(fileInfo));
\r
251 ::LocalFree(hMemory);
\r
254 return nReturnCode;
\r
257 int __stdcall OpenArchive
\r
259 const wxString & _szArcName,
\r
263 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetArchiveInfo");
\r
264 if (fpProc == NULL)
\r
266 return TPI_ERROR_U_USE_LIBRARY;
\r
269 int nReturnCode = SpiErrorCodeConvert(((int (PASCAL *)(const char *, long, unsigned int, HLOCAL *)) fpProc)(_szArcName.char_str(), 0, 0, _hArchive));
\r
270 if (nReturnCode != TPI_ERROR_SUCCESS)
\r
272 return nReturnCode;
\r
275 return * _hArchive == NULL ? TPI_ERROR_IO_ARC_OPEN : nReturnCode;
\r
278 int __stdcall CloseArchive
\r
283 return ::LocalFree(_hArchive) == NULL ? TPI_ERROR_SUCCESS : TPI_ERROR_IO_ARC_CLOSE;
\r
286 int __stdcall GetFileInformation
\r
289 TPI_FILEINFO * _fiInfo,
\r
293 static unsigned int uFileCount, uFilePointer;
\r
298 uFileCount = (unsigned int) (::LocalSize(_hArchive) / sizeof(fileInfo));
\r
301 if (uFilePointer > uFileCount)
\r
303 return TPI_ERROR_UNDEFINED;
\r
306 fileInfo pfiInfo = ((fileInfo *) ::LocalLock(_hArchive))[uFilePointer];
\r
307 if (pfiInfo.method[0] == 0)
\r
309 //
\92\9a\94J
\82È
\83v
\83\89\83O
\83C
\83\93\82Ì
\82½
\82ß
\82Ì
\90\94\8d\87\82í
\82¹ (^^;
\r
310 uFileCount = uFilePointer;
\r
311 return TPI_ERROR_UNDEFINED;
\r
314 _fiInfo->dwAttribute = 0;
\r
315 _fiInfo->dwCRC32 = pfiInfo.crc;
\r
316 _fiInfo->llPackedSize = pfiInfo.compsize;
\r
317 _fiInfo->llUnpackedSize = pfiInfo.filesize;
\r
318 _fiInfo->wCompressRatio = pfiInfo.compsize >= pfiInfo.filesize ? 1000 : (WORD) (1000 * pfiInfo.compsize / pfiInfo.filesize);
\r
319 _fiInfo->llFileID = uFilePointer++;
\r
320 _fiInfo->tmModified = pfiInfo.timestamp;
\r
321 _fiInfo->szStoredName = MB2String(pfiInfo.path) + MB2String(pfiInfo.filename);
\r
322 _fiInfo->fnFileName = wxFileName::FileName(_fiInfo->szStoredName);
\r
323 _fiInfo->szMethod = MB2String((char *) pfiInfo.method);
\r
324 _fiInfo->pCustomInfo = (void *) pfiInfo.position;
\r
325 ::LocalUnlock(_hArchive);
\r
327 return TPI_ERROR_SUCCESS;
\r
330 int __stdcall GetArchiveInformation
\r
333 TPI_ARCHIVEINFO * _aiInfo
\r
336 // GetPluginInfo
\82ð
\8eÀ
\8ds
\81B
\r
337 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetPluginInfo");
\r
338 if (fpProc != NULL)
\r
341 if (((int (PASCAL *)(int, char *, int)) fpProc)(2, szTemp, sizeof(szTemp)) > 0)
\r
343 _aiInfo->fiInfo.szSuffix = MB2String(szTemp);
\r
345 if (((int (PASCAL *)(int, char *, int)) fpProc)(3, szTemp, sizeof(szTemp)) > 0)
\r
347 _aiInfo->fiInfo.szTypeName = MB2String(szTemp);
\r
350 _aiInfo->fiInfo.szTPIName = wxT("spiLibrary");
\r
351 _aiInfo->fiInfo.llSupportedCommand = TPI_COMMAND_EXTRACT;
\r
353 return TPI_ERROR_SUCCESS;
\r
356 int __stdcall Command
\r
358 unsigned int _uCommand,
\r
359 TPI_SWITCHES * _swInfo,
\r
360 const wxString & _szArcName,
\r
361 const wxArrayString & _szFiles
\r
364 if (_uCommand != TPI_COMMAND_EXTRACT)
\r
366 return TPI_ERROR_D_UNSUPPORTED;
\r
369 //
\93W
\8aJ
\8f\88\97\9d\82Ì
\82Ý
\82ð
\8ds
\82¤
\81B
\r
370 FARPROC fpProc = ::GetProcAddress(g_hLib, "GetFile");
\r
371 if (fpProc == NULL)
\r
373 return TPI_ERROR_U_USE_LIBRARY;
\r
376 //
\8f\91\8cÉ
\83n
\83\93\83h
\83\8b\82ð
\8eæ
\93¾
\81B
\r
378 int nResult = OpenArchive(_szArcName, & hArchive);
\r
379 if (nResult != TPI_ERROR_SUCCESS)
\r
384 //
\83R
\81[
\83\8b\83o
\83b
\83N
\82ð
\91\97\90M
\81B
\95Ö
\8bX
\8fã-1
\82ð
\91\97\90M
\81B
\r
385 wxFileName _fnArcName(_szArcName);
\r
386 if (CallbackProc(-1, 0, (long) & _fnArcName))
\r
388 return TPI_ERROR_D_SKIPPED;
\r
391 //
\8f\88\97\9d\8eÀ
\8ds
\81B
\r
392 TPI_FILEINFO fiInfo;
\r
393 nResult = GetFileInformation(hArchive, & fiInfo, TRUE);
\r
394 if (nResult == TPI_ERROR_SUCCESS)
\r
398 //
\83R
\81[
\83\8b\83o
\83b
\83N
\82ð
\91\97\90M
\81B
\r
399 if (CallbackProc(0, fiInfo.llUnpackedSize.ToULong(), (long) & fiInfo.fnFileName))
\r
401 nResult = TPI_ERROR_D_SKIPPED;
\r
405 //
\8f\88\97\9d\91Î
\8fÛ
\82©
\82Ç
\82¤
\82©
\94»
\92è
\81B
\r
406 if (_szFiles.Count() != 0)
\r
409 for (i = 0; i < _szFiles.Count(); i++)
\r
411 if (_szFiles[i] == fiInfo.szStoredName)
\r
416 if (i == _szFiles.Count())
\r
422 //
\8fo
\97Í
\96¼
\8dì
\90¬
\81B
\r
423 wxString szTargetPath = _swInfo->fnDestinationDirectory.GetPathWithSep();
\r
424 if (_swInfo->fStoreDirectoryPathes)
\r
426 //
\93W
\8aJ
\90æ
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8dì
\90¬
\81B
\r
427 szTargetPath += fiInfo.fnFileName.GetFullPath();
\r
428 wxFileName fnDest(szTargetPath);
\r
429 if (! fnDest.Mkdir(0777, wxPATH_MKDIR_FULL) || ::wxDirExists(fnDest.GetFullPath()))
\r
431 nResult = TPI_ERROR_IO_DIR_WRITE;
\r
437 szTargetPath += fiInfo.fnFileName.GetFullName();
\r
440 //
\83t
\83@
\83C
\83\8b\8fo
\97Í
\82É
\82Í
\91Î
\89\9e\82µ
\82Ä
\82È
\82¢
\82Ì
\82Å
\83\81\83\82\83\8a\8fo
\97Í
\82Å
\91ã
\8ds
\81B
\r
441 HLOCAL hMemory = NULL;
\r
442 nResult = SpiErrorCodeConvert(((int (PASCAL *)(char *, long, char *, unsigned int, FARPROC, long)) fpProc)(_szArcName.char_str(), (long) fiInfo.pCustomInfo, (char *) & hMemory, 0x0100, (FARPROC) CallbackProc, (long) & fiInfo.fnFileName));
\r
443 if (nResult == TPI_ERROR_SUCCESS && hMemory == NULL)
\r
445 nResult = TPI_ERROR_UNDEFINED;
\r
447 if (nResult != TPI_ERROR_SUCCESS)
\r
452 //
\93W
\8aJ
\90æ
\82É
\8fo
\97Í
\81B
\r
454 //
\8b
\90§
\8fã
\8f\91\82«
\82·
\82é
\82Ì
\82Å
\92\8d\88Ó
\81B
\r
455 if (! hFile.Create(szTargetPath, true))
\r
457 nResult = TPI_ERROR_IO_FILE_OPEN;
\r
461 bool bErrorOccured = hFile.Write(::LocalLock(hMemory), (size_t) fiInfo.llUnpackedSize.GetValue()) != fiInfo.llUnpackedSize;
\r
462 ::LocalUnlock(hMemory);
\r
463 ::LocalFree(hMemory);
\r
467 nResult = TPI_ERROR_IO_FILE_WRITE;
\r
470 nResult = TPI_ERROR_SUCCESS;
\r
472 //
\83R
\81[
\83\8b\83o
\83b
\83N
\82ð
\91\97\90M
\81B
\r
473 if (CallbackProc(fiInfo.llUnpackedSize.ToULong(), fiInfo.llUnpackedSize.ToULong(), (long) & fiInfo.fnFileName))
\r
475 nResult = TPI_ERROR_D_SKIPPED;
\r
479 while ((nResult = GetFileInformation(hArchive, & fiInfo, FALSE)) != TPI_ERROR_UNDEFINED);
\r
480 if (nResult == TPI_ERROR_UNDEFINED)
\r
482 //
\8fI
\92[
\82É
\92B
\82µ
\82½
\8fê
\8d\87\81B
\r
483 nResult = TPI_ERROR_SUCCESS;
\r
486 CloseArchive(hArchive);
\r
491 int __stdcall SetCallbackProc
\r
493 TPI_PROC _prArcProc
\r
496 //
\83|
\83C
\83\93\83^
\82ð
\95Û
\91¶
\81B
\r
497 if (_prArcProc == NULL)
\r
499 return TPI_ERROR_D_PARAMETER;
\r
501 g_prProc = * _prArcProc;
\r
503 return TPI_ERROR_SUCCESS;
\r