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 #define wxUSE_DYNLIB_CLASS 1
\r
27 #include "../../common/header/plugin.h"
\r
28 #include "../../common/header/plugin-extra.h"
\r
29 #include "../../common/library/library.h"
\r
30 #include <wx/dynlib.h>
\r
33 //******************************************************************************
\r
35 //******************************************************************************
\r
37 wxDynamicLibrary g_hLib;
\r
39 char g_szComment[64001];
\r
40 RAROpenArchiveDataEx g_oaInfo;
\r
42 //******************************************************************************
\r
44 //******************************************************************************
\r
46 int __stdcall CallbackProc(unsigned int msg, long p, long P1, long P2)
\r
49 static TPI_PROCESSINFO pi;
\r
50 TPI_PROCESSINFO * piInfo = p == 0 ? & pi : (TPI_PROCESSINFO *) p;
\r
54 case UCM_CHANGEVOLUME:
\r
59 piInfo->eMessage = TPI_MESSAGE_ASK;
\r
60 piInfo->eStatus = TPI_PARAM_NEXTVOLUME;
\r
61 piInfo->szParam.Empty();
\r
63 case RAR_VOL_NOTIFY:
\r
65 piInfo->eMessage = TPI_MESSAGE_STATUS;
\r
66 piInfo->eStatus = TPI_STATUS_OPENARCHIVE;
\r
67 piInfo->fiInfo.fnFileName = wxFileName(UTF82String((char *) P1));
\r
73 case UCM_PROCESSDATA:
\r
74 piInfo->eMessage = TPI_MESSAGE_STATUS;
\r
75 piInfo->eStatus = TPI_STATUS_INPROCESS;
\r
76 piInfo->nProcessedSize += P2;
\r
78 case UCM_NEEDPASSWORD:
\r
79 piInfo->eMessage = TPI_MESSAGE_ASK;
\r
80 piInfo->eStatus = TPI_PARAM_PASSWORD;
\r
81 piInfo->szParam.Empty();
\r
88 if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, piInfo) == TPI_CALLBACK_CONTINUE)
\r
90 if (msg != UCM_PROCESSDATA && P2 != RAR_VOL_NOTIFY)
\r
92 strncpy((char *) P1, piInfo->szParam.char_str(), (msg == UCM_CHANGEVOLUME ? 1024 : P2) - 1);
\r
102 //******************************************************************************
\r
103 // Inside Functions
\r
104 //******************************************************************************
\r
106 int ErrorCodeConvert(int nErrorCode)
\r
108 switch (nErrorCode)
\r
110 case 0: return TPI_ERROR_SUCCESS;
\r
111 case 1: return TPI_ERROR_SUCCESS;
\r
112 case ERAR_END_ARCHIVE: return TPI_ERROR_S_ENDOFDATA;
\r
113 case ERAR_NO_MEMORY: return TPI_ERROR_D_OUTOFMEMORY;
\r
114 case ERAR_BAD_DATA: return TPI_ERROR_ARC_BROKEN_MISC;
\r
115 case ERAR_BAD_ARCHIVE: return TPI_ERROR_ARC_UNSUPPORTED;
\r
116 case ERAR_UNKNOWN_FORMAT: return TPI_ERROR_ARC_ENCRYPTED;
\r
117 case ERAR_EOPEN: return TPI_ERROR_IO_ARC_OPEN;
\r
118 case ERAR_ECREATE: return TPI_ERROR_IO_FILE_OPEN;
\r
119 case ERAR_ECLOSE: return TPI_ERROR_IO_CLOSE;
\r
120 case ERAR_EREAD: return TPI_ERROR_IO_ARC_READ;
\r
121 case ERAR_EWRITE: return TPI_ERROR_IO_FILE_WRITE;
\r
122 case ERAR_SMALL_BUF: return TPI_ERROR_UNDEFINED;
\r
123 case ERAR_UNKNOWN: return TPI_ERROR_UNDEFINED;
\r
124 case ERAR_MISSING_PASSWORD: return TPI_ERROR_ARC_ENCRYPTED;
\r
125 default: return TPI_ERROR_UNDEFINED;
\r
129 //******************************************************************************
\r
131 //******************************************************************************
\r
138 int __stdcall GetPluginInformation
\r
140 unsigned int _uInfoId,
\r
147 return TPI_ERROR_D_PARAMETER;
\r
151 case TPI_INFO_VERSION_MAJOR:
\r
152 case TPI_INFO_VERSION_MINOR:
\r
153 * (int *) _pPtr = 0;
\r
155 case TPI_INFO_VERSION_API:
\r
156 * (int *) _pPtr = 2;
\r
158 case TPI_INFO_HANDLE_ON_COMMAND:
\r
159 * (int *) _pPtr = 0;
\r
162 return TPI_ERROR_D_UNSUPPORTED;
\r
164 return TPI_ERROR_SUCCESS;
\r
167 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)
\r
171 return TPI_ERROR_S_ENDOFDATA;
\r
174 _fiInfo->szTypeName = wxT("RAR");
\r
175 _fiInfo->szSuffix = wxT("rar");
\r
176 _fiInfo->szEngineName = g_hLib.CanonicalizeName(wxT("unrar"));
\r
177 _fiInfo->szTPIName = wxT("rarArc");
\r
178 _fiInfo->nTypeId = 0;
\r
179 _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;
\r
180 _fiInfo->fArchive = true;
\r
181 _fiInfo->fComment = true;
\r
182 _fiInfo->fSFX = true;
\r
183 _fiInfo->fSolid = true;
\r
184 _fiInfo->fEncryptPassword = true;
\r
185 _fiInfo->fMultiVolume = true;
\r
187 return TPI_ERROR_SUCCESS;
\r
190 int __stdcall LoadPlugin
\r
197 ::RemoveCwdFromSearchPath();
\r
198 g_hLib.Load(g_hLib.CanonicalizeName(wxT("unrar")), wxDL_QUIET);
\r
199 if (! g_hLib.IsLoaded())
\r
202 return TPI_ERROR_U_LOAD_LIBRARY;
\r
206 if (_prProc != NULL)
\r
208 g_prProc = * _prProc;
\r
210 return TPI_ERROR_SUCCESS;
\r
213 int __stdcall FreePlugin
\r
215 void * // _pReserved
\r
219 return TPI_ERROR_SUCCESS;
\r
222 int __stdcall OpenArchive
\r
224 const wxString & _szArcName,
\r
225 void * * _hArchive,
\r
229 if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))
\r
231 return TPI_ERROR_U_USE_LIBRARY;
\r
233 void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));
\r
236 return TPI_ERROR_U_USE_LIBRARY;
\r
239 memset(& g_oaInfo, 0, sizeof(g_oaInfo));
\r
240 g_oaInfo.ArcName = NULL;
\r
241 // g_oaInfo.ArcNameW = _szArcName.wchar_str();
\r
242 g_oaInfo.ArcNameW = (wchar_t *) malloc((_szArcName.Len() + 1) * sizeof(wchar_t));
\r
243 wcscpy(g_oaInfo.ArcNameW, _szArcName.wchar_str());
\r
244 g_oaInfo.OpenMode = RAR_OM_LIST;
\r
245 g_oaInfo.CmtBuf = g_szComment;
\r
246 g_oaInfo.CmtBufSize = sizeof(g_szComment) - 1;
\r
247 g_oaInfo.Callback = CallbackProc;
\r
248 * _hArchive = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& g_oaInfo);
\r
249 free(g_oaInfo.ArcNameW);
\r
250 return * _hArchive == NULL ? TPI_ERROR_UNDEFINED : ErrorCodeConvert(g_oaInfo.OpenResult);
\r
253 int __stdcall CloseArchive
\r
258 if (! g_hLib.HasSymbol(wxT("RARCloseArchive")))
\r
260 return TPI_ERROR_U_USE_LIBRARY;
\r
262 void * p = g_hLib.GetSymbol(wxT("RARCloseArchive"));
\r
263 return (! p || _hArchive == NULL) ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((int (__stdcall *)(void *)) p)(_hArchive));
\r
266 int __stdcall GetFileInformation
\r
269 TPI_FILEINFO * _fiInfo,
\r
273 static wxULongLong_t s_nFileId;
\r
274 static void * pR, * pP;
\r
280 pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL;
\r
281 pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;
\r
284 return TPI_ERROR_U_USE_LIBRARY;
\r
288 RARHeaderDataEx hdInfo;
\r
289 char szComment[64001];
\r
290 hdInfo.CmtBuf = szComment;
\r
291 hdInfo.CmtBufSize = sizeof(szComment) - 1;
\r
292 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(_hArchive, & hdInfo));
\r
293 if (nErrorCode == TPI_ERROR_SUCCESS)
\r
295 if (hdInfo.HostOS == 3)
\r
297 _fiInfo->wPermission = hdInfo.FileAttr;
\r
301 _fiInfo->dwAttribute = hdInfo.FileAttr;
\r
303 if (hdInfo.Flags & 0x04)
\r
305 _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;
\r
307 _fiInfo->dwCRC32 = hdInfo.FileCRC;
\r
308 _fiInfo->nPackedSize = hdInfo.PackSizeHigh;
\r
309 _fiInfo->nPackedSize = _fiInfo->nPackedSize << 32;
\r
310 _fiInfo->nPackedSize += hdInfo.PackSize;
\r
311 _fiInfo->nUnpackedSize = hdInfo.UnpSizeHigh;
\r
312 _fiInfo->nUnpackedSize = _fiInfo->nUnpackedSize << 32;
\r
313 _fiInfo->nUnpackedSize += hdInfo.UnpSize;
\r
314 _fiInfo->tmModify.SetFromDOS(hdInfo.FileTime);
\r
315 _fiInfo->eOSType = hdInfo.HostOS;
\r
316 _fiInfo->szStoredName = WC2String(hdInfo.FileNameW);
\r
317 _fiInfo->szMethod.Printf(wxT("%x"), hdInfo.Method);
\r
318 _fiInfo->szComment = UTF82String(hdInfo.CmtBuf);
\r
319 _fiInfo->nFileId = s_nFileId++;
\r
320 _fiInfo->fnFileName = wxFileName(_fiInfo->szStoredName);
\r
323 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(_hArchive, RAR_SKIP, NULL, NULL));
\r
329 int __stdcall GetArchiveInformation
\r
332 TPI_ARCHIVEINFO * _aiInfo
\r
335 _aiInfo->fSolid = (g_oaInfo.Flags & 0x0008) == 1;
\r
336 _aiInfo->fEncryptHeader = (g_oaInfo.Flags & 0x0080) == 1;
\r
337 _aiInfo->szComment = UTF82String(g_szComment);
\r
338 GetFormatInformation(& _aiInfo->fiInfo, true);
\r
339 return TPI_ERROR_SUCCESS;
\r
342 int __stdcall Command
\r
344 wxULongLong_t _eCommand,
\r
345 TPI_SWITCHES * _swInfo,
\r
346 void *,// _hArchive,
\r
347 const wxArrayString & _szFiles
\r
350 if (_eCommand != TPI_COMMAND_EXTRACT && _eCommand != TPI_COMMAND_TEST)
\r
352 return TPI_ERROR_U_USE_LIBRARY;
\r
356 if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))
\r
358 return TPI_ERROR_U_USE_LIBRARY;
\r
360 void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));
\r
363 return TPI_ERROR_U_USE_LIBRARY;
\r
366 TPI_PROCESSINFO piInfo;
\r
367 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
368 piInfo.eStatus = TPI_STATUS_OPENARCHIVE;
\r
369 piInfo.fiInfo.fnFileName = wxFileName(_swInfo->szArcName);
\r
370 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)
\r
372 return TPI_ERROR_D_SKIPPED;
\r
374 RAROpenArchiveDataEx oaInfo;
\r
375 memset(& oaInfo, 0, sizeof(oaInfo));
\r
376 oaInfo.ArcName = NULL;
\r
377 // oaInfo.ArcNameW = _swInfo->szArcName.wchar_str();
\r
378 oaInfo.ArcNameW = (wchar_t *) malloc((_swInfo->szArcName.Len() + 1) * sizeof(wchar_t));
\r
379 wcscpy(oaInfo.ArcNameW, _swInfo->szArcName.wchar_str());
\r
380 oaInfo.OpenMode = RAR_OM_EXTRACT;
\r
381 oaInfo.CmtBufSize = 0;
\r
382 oaInfo.Callback = CallbackProc;
\r
383 oaInfo.UserData = (long) & piInfo;
\r
384 void * hArc = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& oaInfo);
\r
385 free(oaInfo.ArcNameW);
\r
388 return TPI_ERROR_UNDEFINED;
\r
390 int nErrorCode = ErrorCodeConvert(oaInfo.OpenResult);
\r
391 if (nErrorCode != TPI_ERROR_SUCCESS)
\r
397 * pS = g_hLib.HasSymbol(wxT("RARSetPassword")) ? g_hLib.GetSymbol(wxT("RARSetPassword")) : NULL,
\r
398 * pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL,
\r
399 * pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;
\r
402 CloseArchive(hArc);
\r
403 return TPI_ERROR_U_USE_LIBRARY;
\r
407 ((void (__stdcall *)(void *, char *)) pS)(hArc, _swInfo->szPassword.char_str());
\r
410 RARHeaderDataEx hdInfo;
\r
411 while (nErrorCode == TPI_ERROR_SUCCESS && ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(hArc, & hdInfo)) == TPI_ERROR_SUCCESS)
\r
413 piInfo.fiInfo.fnFileName = wxFileName(WC2String(hdInfo.FileNameW));
\r
414 piInfo.fnDestination = wxFileName(_swInfo->fnDestinationDirectory.GetPathWithSep() + (_swInfo->fStoreDirectoryPathes ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetFullName()));
\r
415 bool bSkip = _szFiles.GetCount() != 0 && _szFiles.Index(piInfo.fiInfo.fnFileName.GetFullPath()) == wxNOT_FOUND;
\r
416 if (! bSkip && _eCommand == TPI_COMMAND_EXTRACT)
\r
419 piInfo.eMessage = TPI_MESSAGE_ASK;
\r
420 piInfo.eStatus = TPI_PARAM_DEST;
\r
421 piInfo.fiInfo.nUnpackedSize = hdInfo.UnpSizeHigh;
\r
422 piInfo.fiInfo.nUnpackedSize = piInfo.fiInfo.nUnpackedSize << 32;
\r
423 piInfo.fiInfo.nUnpackedSize += hdInfo.UnpSize;
\r
424 piInfo.fiInfo.tmModify.SetFromDOS(hdInfo.FileTime);
\r
425 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)
\r
427 nErrorCode = TPI_ERROR_D_SKIPPED;
\r
430 bSkip = ! piInfo.fnDestination.IsOk();
\r
436 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
437 piInfo.eStatus = TPI_STATUS_BEGINPROCESS;
\r
438 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)
\r
440 nErrorCode = TPI_ERROR_D_SKIPPED;
\r
445 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(hArc, bSkip ? RAR_SKIP : _eCommand == TPI_COMMAND_EXTRACT ? RAR_EXTRACT : RAR_TEST, NULL, piInfo.fnDestination.GetFullPath().wchar_str()));
\r
450 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
451 piInfo.eStatus = TPI_STATUS_ENDPROCESS;
\r
452 if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)
\r
454 nErrorCode = TPI_ERROR_D_SKIPPED;
\r
459 CloseArchive(hArc);
\r