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: cuiWrapper.cpp,v 1.26 2009/09/27 13:41:02 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/config.h>
\r
30 #include <wx/stdpaths.h>
\r
31 #include <wx/xml/xml.h>
\r
32 #include <wx/tokenzr.h>
\r
33 #include <windows.h>
\r
34 #include "cuiWrapper.h"
\r
36 //******************************************************************************
\r
38 //******************************************************************************
\r
43 wxString szExeFileAlt;
\r
44 wxString szListCommand;
\r
50 wxString g_szCurrentArchive;
\r
51 wxArrayString g_asOutput;
\r
53 //******************************************************************************
\r
55 //******************************************************************************
\r
57 BOOL __stdcall DllMain(HMODULE, DWORD, void *)
\r
62 //******************************************************************************
\r
64 //******************************************************************************
\r
66 DWORD myExecute(wxString szCommandLine, wxString * szOutput, wxString szCwd, bool bCheckExist = false)
\r
69 wxString sz = ::wxGetCwd();
\r
70 ::wxSetWorkingDirectory(szCwd);
\r
71 FILE * fp = popen(szCommandLine.char_str(), "r");
\r
72 ::wxSetWorkingDirectory(sz);
\r
75 // wxMessageBox(wxString::Format(wxT("Error :\n\nCommandLine:\n%s"), szCommandLine.c_str()));
\r
76 return TPI_ERROR_U_USE_LIBRARY;
\r
81 return TPI_ERROR_SUCCESS;
\r
84 if (szOutput != NULL)
\r
87 memset(sz, 0, sizeof(sz));
\r
90 fread(sz, sizeof(char), sizeof(sz) - 1, fp);
\r
91 * szOutput += MB2String(sz);
\r
93 // ::wxMessageBox(* szOutput);
\r
97 return TPI_ERROR_SUCCESS;
\r
99 SECURITY_ATTRIBUTES sa;
\r
100 memset(& sa, 0, sizeof(SECURITY_ATTRIBUTES));
\r
101 sa.bInheritHandle = TRUE;
\r
102 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
103 HANDLE hRead, hWrite;
\r
104 if (! ::CreatePipe(& hRead, & hWrite, & sa, 65537))
\r
106 return TPI_ERROR_U_USE_LIBRARY;
\r
109 memset(& si, 0, sizeof(STARTUPINFO));
\r
110 si.cb = sizeof(STARTUPINFO);
\r
111 si.dwFlags = STARTF_USESTDHANDLES;
\r
112 si.hStdOutput = hWrite;
\r
113 si.hStdError = hWrite;
\r
114 PROCESS_INFORMATION pi;
\r
115 if (! ::CreateProcess(NULL, szCommandLine.wchar_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, szCwd.IsEmpty() ? NULL : szCwd.wchar_str(), & si, & pi))
\r
117 return TPI_ERROR_U_USE_LIBRARY;
\r
120 ::WaitForInputIdle(pi.hProcess, INFINITE);
\r
121 ::WaitForSingleObject(pi.hProcess, INFINITE);
\r
123 DWORD nErrorCode = 0;
\r
124 ::GetExitCodeProcess(pi.hProcess, & nErrorCode);
\r
125 ::CloseHandle(pi.hThread);
\r
126 ::CloseHandle(pi.hProcess);
\r
130 return TPI_ERROR_SUCCESS;
\r
133 if (szOutput != NULL)
\r
137 memset(sz, 0, sizeof(sz));
\r
138 for (wxULongLong llSize = 0; llSize < ::GetFileSize(hRead, NULL); llSize += dwSize)
\r
141 ::ReadFile(hRead, sz, sizeof(sz) - 1, & dwSize, NULL);
\r
142 * szOutput += MB2String(sz);
\r
143 // ::MessageBoxA(NULL, sz, NULL, 0);
\r
146 ::CloseHandle(hRead);
\r
147 ::CloseHandle(hWrite);
\r
149 return nErrorCode == 0 ? TPI_ERROR_SUCCESS : TPI_ERROR_UNDEFINED;
\r
153 PosInfo MakePosInfo(wxString szPrefix)
\r
156 g_LibInfo.node.GetPropVal(wxT("list-") + szPrefix + wxT("-s"), wxEmptyString).ToULong(& pi.nStart);
\r
157 g_LibInfo.node.GetPropVal(wxT("list-") + szPrefix + wxT("-c"), wxEmptyString).ToULong(& pi.nCount);
\r
158 g_LibInfo.node.GetPropVal(wxT("list-") + szPrefix + wxT("-l"), wxT("0")).ToULong(& pi.nLine);
\r
162 wxULongLong GetSize(PosInfo & pi, size_t uCurrent, wxArrayString & as)
\r
164 if (pi.nStart == 0 && pi.nCount == 0)
\r
169 wxULongLong_t nTemp;
\r
170 size_t nPos = uCurrent + pi.nLine;
\r
171 wxString sz = pi.nCount == 0 ? as[nPos].Mid(pi.nStart) : as[nPos].Mid(pi.nStart, pi.nCount);
\r
172 sz.ToULongLong(& nTemp);
\r
176 //******************************************************************************
\r
178 //******************************************************************************
\r
185 int __stdcall GetPluginInformation
\r
187 unsigned int _uInfoId,
\r
194 return TPI_ERROR_D_PARAMETER;
\r
196 switch (LOWORD(_uInfoId))
\r
198 case TPI_INFO_VERSION_MAJOR:
\r
199 case TPI_INFO_VERSION_MINOR:
\r
200 * (int *) _pPtr = 0;
\r
202 case TPI_INFO_VERSION_API:
\r
203 * (int *) _pPtr = 2;
\r
206 return TPI_ERROR_D_UNSUPPORTED;
\r
208 return TPI_ERROR_SUCCESS;
\r
211 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)
\r
213 static unsigned int s_uFileID;
\r
215 wxXmlDocument config(wxPathOnly(p.GetExecutablePath()) + wxT("/lib/cuiWrapper.xml"));
\r
216 //
\88ê
\8bC
\82É
\90æ
\93ª
\82Ì
\83\89\83C
\83u
\83\89\83\8a\82Ì
\8fî
\95ñ
\82ð
\8eæ
\93¾
\81B
\r
217 wxXmlNode * xmlLibrary = config.GetRoot()->GetChildren();
\r
221 // xml
\89ð
\90Í
\8aJ
\8en
\81B
\r
226 for (unsigned int i = 0; i < s_uFileID && xmlLibrary != NULL; i++)
\r
228 xmlLibrary = xmlLibrary->GetNext();
\r
232 if (xmlLibrary == NULL || xmlLibrary->GetName() != wxT("library"))
\r
234 // xml
\95¶
\96@
\83G
\83\89\81[
\81B
\r
235 return TPI_ERROR_UNDEFINED;
\r
238 _fiInfo->szTypeName = xmlLibrary->GetPropVal(wxT("typename"),wxEmptyString);
\r
239 _fiInfo->szSuffix = xmlLibrary->GetPropVal(wxT("suffix"), wxEmptyString);
\r
240 _fiInfo->szEngineName = xmlLibrary->GetPropVal(wxT("name"), wxEmptyString);
\r
241 _fiInfo->szTPIName = wxT("cuiWrapper");
\r
242 _fiInfo->llSupportedCommand = myExecute(xmlLibrary->GetPropVal(wxT("name"), wxEmptyString), NULL, wxEmptyString, true) == TPI_ERROR_SUCCESS ? SupportedCommand(xmlLibrary) : 0;
\r
243 _fiInfo->llTypeId = s_uFileID++;
\r
244 SupportedSwitch(xmlLibrary, _fiInfo);
\r
246 return TPI_ERROR_SUCCESS;
\r
249 int __stdcall LoadPlugin
\r
251 const wxString & _szArcName,
\r
252 wxULongLong _llSubOption
\r
255 // xml
\89ð
\90Í
\8aJ
\8en
\81B
\r
257 wxXmlDocument config(wxPathOnly(p.GetExecutablePath()) + wxT("/lib/cuiWrapper.xml"));
\r
258 if (! config.IsOk())
\r
260 return TPI_ERROR_UNDEFINED;
\r
262 //
\88ê
\8bC
\82É
\90æ
\93ª
\82Ì
\83\89\83C
\83u
\83\89\83\8a\82Ì
\8fî
\95ñ
\82ð
\8eæ
\93¾
\81B
\r
263 wxXmlNode * xmlLibrary = config.GetRoot()->GetChildren();
\r
265 //
\91Î
\8fÛ
\82ª
\91¶
\8dÝ
\82·
\82é
\82È
\82ç
\82Î
\91Î
\89\9e\82·
\82é
\83\89\83C
\83u
\83\89\83\8a\82ð
\92²
\8d¸
\81A
\r
266 //
\91Î
\8fÛ
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82È
\82ç
\82Î
\8ew
\8e¦
\82³
\82ê
\82½
\83\89\83C
\83u
\83\89\83\8a\82ð
\83\8d\81[
\83h
\81B
\r
267 if (! ::wxFileExists(_szArcName))
\r
269 //
\93K
\93\96\82È
\88Ê
\92u
\82Ü
\82Å
\88Ú
\93®
\81B
\r
270 for (g_LibInfo.nLibIndex = 0; g_LibInfo.nLibIndex < _llSubOption && xmlLibrary != NULL; g_LibInfo.nLibIndex++)
\r
272 xmlLibrary = xmlLibrary->GetNext();
\r
274 if (xmlLibrary == NULL || xmlLibrary->GetName() != wxT("library"))
\r
276 // xml
\95¶
\96@
\83G
\83\89\81[
\81B
\r
277 return TPI_ERROR_UNDEFINED;
\r
279 g_LibInfo.szExeFile = xmlLibrary->GetPropVal(wxT("name"), wxEmptyString);
\r
280 g_LibInfo.szExeFileAlt = xmlLibrary->GetPropVal(wxT("name-alt"), wxEmptyString);
\r
281 g_LibInfo.node = * xmlLibrary;
\r
283 return TPI_ERROR_SUCCESS;
\r
286 //
\96³
\8cÀ
\83\8b\81[
\83v
\82É
\8a×
\82ç
\82È
\82¢
\82æ
\82¤
\8fã
\8cÀ
\82ð
\90Ý
\92è
\81B
\r
287 for (g_LibInfo.nLibIndex = 0; g_LibInfo.nLibIndex < 300 && xmlLibrary != NULL; g_LibInfo.nLibIndex++)
\r
289 //
\83\89\83C
\83u
\83\89\83\8a\82ð
\83\8d\81[
\83h
\81B
\r
290 g_LibInfo.szExeFile = xmlLibrary->GetPropVal(wxT("name"), wxEmptyString);
\r
291 g_LibInfo.szExeFileAlt = xmlLibrary->GetPropVal(wxT("name-alt"), wxEmptyString);
\r
292 g_LibInfo.node = * xmlLibrary;
\r
294 //
\8f\91\8cÉ
\82É
\91Î
\89\9e\82µ
\82Ä
\82¢
\82é
\82©
\83`
\83F
\83b
\83N
\81B
\r
295 if (CheckArchive(_szArcName, NULL) == TPI_ERROR_SUCCESS)
\r
297 //
\91Î
\89\9e\82µ
\82Ä
\82¢
\82ê
\82Î
\8f\88\97\9d\82ð
\8fI
\97¹
\81B
\r
298 return TPI_ERROR_SUCCESS;
\r
301 xmlLibrary = xmlLibrary->GetNext();
\r
304 return TPI_ERROR_U_LOAD_LIBRARY;
\r
307 int __stdcall FreePlugin
\r
309 void * // _pReserved
\r
312 return TPI_ERROR_SUCCESS;
\r
315 int __stdcall CheckArchive
\r
317 const wxString & _szArcName,
\r
321 wxFileName fnArchive(_szArcName);
\r
322 wxArrayString asExt = ::wxStringTokenize(g_LibInfo.node.GetPropVal(wxT("suffix"), wxEmptyString), wxT(";"));
\r
323 if (! g_LibInfo.node.HasProp(wxT("list")))
\r
325 return TPI_ERROR_ARC_UNSUPPORTED;
\r
328 for (size_t i = 0; i < asExt.GetCount(); i++)
\r
330 // .tar.XXX
\82È
\82Ç
\93ñ
\8fd
\94»
\92è
\82Ö
\82Ì
\91Î
\89\9e\81B
\r
331 // if (asExt[i].IsSameAs(fnArchive.GetExt(), false))
\r
332 if (fnArchive.GetFullName().EndsWith(wxT('.') + asExt[i]))
\r
334 //
\8aJ
\82¢
\82Ä
\8am
\94F
\81B
\90æ
\8ds
\82µ
\82Ä
\83f
\81[
\83^
\82ð
\8eæ
\93¾
\82µ
\82Ä
\82¨
\82
\81B
\r
335 int nErrorCode = OpenArchive(_szArcName, NULL);
\r
338 if (_nFileCount != NULL)
\r
340 //
\83t
\83@
\83C
\83\8b\90\94\82Í
\91½
\82ß
\82É
\8eæ
\82Á
\82Ä
\82¨
\82
\81B
\r
341 * _nFileCount = g_asOutput.Count();
\r
347 return TPI_ERROR_ARC_UNSUPPORTED;
\r
350 int __stdcall OpenArchive
\r
352 const wxString & _szArcName,
\r
356 if (g_szCurrentArchive != _szArcName)
\r
359 if (myExecute(g_LibInfo.szExeFile + wxT(" ") + MakeCommandLineSend(g_LibInfo.node.GetPropVal(wxT("list"), wxEmptyString), _szArcName, NULL, NULL, wxEmptyString), & szOutput, wxEmptyString) != TPI_ERROR_SUCCESS)
\r
361 return TPI_ERROR_U_USE_LIBRARY;
\r
363 g_szCurrentArchive = _szArcName;
\r
364 g_asOutput = ::wxStringTokenize(szOutput, wxT("\r\n"));
\r
366 if (_hArchive != NULL)
\r
368 * _hArchive = & g_asOutput;
\r
370 return g_asOutput.Count() == 0 ? TPI_ERROR_UNDEFINED : TPI_ERROR_SUCCESS;
\r
373 int __stdcall CloseArchive
\r
378 ((wxArrayString *) _hArchive)->Clear();
\r
379 return TPI_ERROR_SUCCESS;
\r
382 int __stdcall GetFileInformation
\r
385 TPI_FILEINFO * _fiInfo,
\r
389 static size_t s_uCurrentLine;
\r
390 static wxULongLong s_llFileID;
\r
391 if (_hArchive == NULL)
\r
393 return TPI_ERROR_UNDEFINED;
\r
395 wxArrayString asOutput = * (wxArrayString *) _hArchive;
\r
397 // XML
\82©
\82ç
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
\82Í
\8f\89\89ñ
\82É
\8ds
\82¤
\81B
\r
398 static wxString szEndLine, szDateFormat;
\r
399 static unsigned long nProcessPerLine;
\r
400 static PosInfo piFName, piPSize, piUSize, piDate;
\r
404 wxString szStartLine = g_LibInfo.node.GetPropVal(wxT("list-line-s"), wxEmptyString);
\r
405 if (! szStartLine.IsEmpty())
\r
407 for (s_uCurrentLine = 0; s_uCurrentLine < asOutput.Count(); s_uCurrentLine++)
\r
409 if (asOutput[s_uCurrentLine] == szStartLine)
\r
411 //
\8e\9f\82Ì
\8ds
\82Ö
\90i
\82ñ
\82Å
\8fI
\97¹
\81B
\r
418 //
\8f\89\8aú
\90Ý
\92è
\81B
\r
419 g_LibInfo.node.GetPropVal(wxT("list-line-c"), wxT("1")).ToULong(& nProcessPerLine);
\r
420 szEndLine = g_LibInfo.node.GetPropVal(wxT("list-line-e"), szStartLine);
\r
421 szDateFormat = g_LibInfo.node.GetPropVal(wxT("list-date-f"), wxDefaultDateTimeFormat);
\r
422 piFName = MakePosInfo(wxT("fname"));
\r
423 piPSize = MakePosInfo(wxT("psize"));
\r
424 piUSize = MakePosInfo(wxT("usize"));
\r
425 piDate = MakePosInfo(wxT("date"));
\r
428 if (s_uCurrentLine >= asOutput.Count())
\r
430 //
\8f\91\8cÉ
\82ª
\93Ç
\82Ý
\8d\9e\82ß
\82È
\82©
\82Á
\82½
\81H
\r
431 return TPI_ERROR_ARC_UNSUPPORTED;
\r
434 //
\8dÅ
\8fI
\8ds
\82©
\82Ç
\82¤
\82©
\8am
\94F
\81B
\r
435 if (asOutput[s_uCurrentLine] == szEndLine)
\r
437 return TPI_ERROR_UNDEFINED;
\r
440 //
\83t
\83@
\83C
\83\8b\96¼
\82ð
\8eæ
\93¾
\81B
\r
441 _fiInfo->szStoredName = piFName.nCount == 0 ? asOutput[s_uCurrentLine + piFName.nLine].Mid(piFName.nStart) : asOutput[s_uCurrentLine + piFName.nLine].Mid(piFName.nStart, piFName.nCount);
\r
442 _fiInfo->szStoredName.Trim();
\r
443 _fiInfo->fnFileName = wxFileName::wxFileName(_fiInfo->szStoredName);
\r
445 //
\83T
\83C
\83Y
\8eæ
\93¾
\81B
\r
446 _fiInfo->llPackedSize = GetSize(piPSize, s_uCurrentLine, asOutput);
\r
447 _fiInfo->llUnpackedSize = GetSize(piUSize, s_uCurrentLine, asOutput);
\r
449 //
\8dX
\90V
\8e\9e\8d\8f\8eæ
\93¾
\81B
\r
450 if (piDate.nStart != 0 || piDate.nCount != 0)
\r
452 _fiInfo->tmModified.ParseFormat(piDate.nCount == 0 ? asOutput[s_uCurrentLine + piDate.nLine].Mid(piDate.nStart) : asOutput[s_uCurrentLine + piDate.nLine].Mid(piDate.nStart, piDate.nCount), szDateFormat);
\r
455 //
\8dÅ
\8cã
\82É
\8e\9f\82Ì
\8ds
\82Ö
\90i
\82ß
\82Ä
\82¨
\82
\81B
\r
456 _fiInfo->llFileID = s_llFileID++;
\r
457 s_uCurrentLine += nProcessPerLine;
\r
459 return TPI_ERROR_SUCCESS;
\r
462 int __stdcall GetArchiveInformation
\r
468 return TPI_ERROR_SUCCESS;
\r
471 int __stdcall Command
\r
473 unsigned int _uCommand,
\r
474 TPI_SWITCHES * _swInfo,
\r
475 const wxString & _szArcName,
\r
476 const wxArrayString & _szFiles
\r
479 // xml
\82©
\82ç
\83R
\83}
\83\93\83h
\83\89\83C
\83\93\82ð
\8eæ
\93¾
\81B
\r
480 wxString szPath, szCommandLine;
\r
482 // API
\83A
\83h
\83\8c\83X
\8eæ
\93¾
\81B
\r
483 if (! g_LibInfo.node.GetPropVal(
\r
484 _uCommand == TPI_COMMAND_ADD ? wxT("add") :
\r
485 _uCommand == TPI_COMMAND_EXTRACT ? wxT("extract") :
\r
486 _uCommand == TPI_COMMAND_DELETE ? wxT("delete") :
\r
487 _uCommand == TPI_COMMAND_UPDATE ? wxT("update") :
\r
488 _uCommand == TPI_COMMAND_TEST ? wxT("test") :
\r
489 _uCommand == TPI_COMMAND_REPAIR ? wxT("repair") :
\r
490 _uCommand == TPI_COMMAND_MOVE ? wxT("move") :
\r
491 _uCommand == TPI_COMMAND_SFX ? wxT("sfx") :
\r
492 _uCommand == TPI_COMMAND_UNSFX ? wxT("unsfx") : wxEmptyString, & szCommandLine))
\r
494 g_LibInfo.node.GetPropVal(
\r
495 _uCommand == TPI_COMMAND_ADD ? wxT("add-alt") :
\r
496 _uCommand == TPI_COMMAND_EXTRACT ? wxT("extract-alt") :
\r
497 _uCommand == TPI_COMMAND_DELETE ? wxT("delete-alt") :
\r
498 _uCommand == TPI_COMMAND_UPDATE ? wxT("update-alt") :
\r
499 _uCommand == TPI_COMMAND_TEST ? wxT("test-alt") :
\r
500 _uCommand == TPI_COMMAND_REPAIR ? wxT("repair-alt") :
\r
501 _uCommand == TPI_COMMAND_MOVE ? wxT("move-alt") :
\r
502 _uCommand == TPI_COMMAND_SFX ? wxT("sfx-alt") :
\r
503 _uCommand == TPI_COMMAND_UNSFX ? wxT("unsfx-alt") : wxEmptyString, & szCommandLine);
\r
506 if (szCommandLine.IsEmpty())
\r
508 return TPI_ERROR_U_USE_LIBRARY;
\r
511 //
\83R
\83}
\83\93\83h
\83\89\83C
\83\93\81E
\83\8c\83X
\83|
\83\93\83X
\83t
\83@
\83C
\83\8b\8dì
\90¬
\81B
\r
513 szResponceFileName = MakeResponceFile(_szFiles, g_LibInfo.node.GetPropVal(wxT("quote-resp"), wxT("1")) == wxT("1")),
\r
514 szCommandLineSend = MakeCommandLineSend(szCommandLine, _szArcName, _swInfo, _szFiles, szResponceFileName);
\r
516 //
\83R
\83}
\83\93\83h
\83\89\83C
\83\93\8eÀ
\8ds
\81B
\r
518 DWORD nErrorCode = myExecute(g_LibInfo.szExeFile + wxT(" ") + szCommandLineSend, & szOutput, _swInfo->fnDestinationDirectory.GetFullPath());
\r
520 //
\83\8c\83X
\83|
\83\93\83X
\83t
\83@
\83C
\83\8b\8dí
\8f\9c\81B
\r
521 ::wxRemoveFile(szResponceFileName);
\r
523 if (nErrorCode != TPI_ERROR_SUCCESS)
\r
526 ::wxMessageBox(wxString::Format(wxT("Error :\n%d\n\nCommandLine:\n%s\n\nOutput:\n%s"), nErrorCode, szCommandLineSend.c_str(), szOutput.c_str()));
\r
528 MessageBox(NULL, wxString::Format(wxT("Error :\n%d\n\nCommandLine:\n%s\n\nOutput:\n%s"), nErrorCode, szCommandLineSend.c_str(), szOutput.c_str()), NULL, 0);
\r
534 int __stdcall SetCallbackProc
\r
536 TPI_PROC _prArcProc
\r
539 //
\83|
\83C
\83\93\83^
\82ð
\95Û
\91¶
\81B
\r
540 if (_prArcProc == NULL)
\r
542 return TPI_ERROR_D_PARAMETER;
\r
544 g_prProc = * _prArcProc;
\r
546 return TPI_ERROR_SUCCESS;
\r