OSDN Git Service

パイプのバッファサイズを最大に変更。
[tpi/lychee.git] / src / plugin / cuiWrapper / cuiWrapper.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/config.h>\r
30 #include <wx/stdpaths.h>\r
31 #include <wx/xml/xml.h>\r
32 #include <wx/tokenzr.h>\r
33 #ifdef __WINDOWS__\r
34 #include <windows.h>\r
35 #endif\r
36 #include "cuiWrapper.h"\r
37 \r
38 //******************************************************************************\r
39 //    Global varients\r
40 //******************************************************************************\r
41 \r
42 struct g_LibInfo\r
43 {\r
44         wxString szExeFile;\r
45         wxString szExeFileAlt;\r
46         wxString szListCommand;\r
47         int nLibIndex;\r
48         wxXmlNode node;\r
49 }       g_LibInfo;\r
50 \r
51 TPI_PROC g_prProc;\r
52 wxString g_szCurrentArchive;\r
53 wxArrayString g_asOutput;\r
54 \r
55 //******************************************************************************\r
56 //    Entry\r
57 //******************************************************************************\r
58 \r
59 #ifdef __WINDOWS__\r
60 BOOL __stdcall DllMain(HMODULE, DWORD, void *)\r
61 {\r
62         return TRUE;\r
63 }\r
64 #endif\r
65 \r
66 //******************************************************************************\r
67 //    Inside Functions\r
68 //******************************************************************************\r
69 \r
70 int myExecute(wxString szCommandLine, wxString * szOutput, wxString szCwd, bool bCheckExist = false)\r
71 {\r
72         // Windows用の方法ではバッファサイズを有限にしか取れない?\r
73         // Linux用の方法ではコンソールが表示されてしまう。\r
74 #ifdef __LINUX__\r
75 #ifndef popen\r
76 #define popen _popen\r
77 #define pclose _pclose\r
78 #endif\r
79         wxString sz = ::wxGetCwd();\r
80         ::wxSetWorkingDirectory(szCwd);\r
81         FILE * fp = popen(szCommandLine.ToUTF8(), "r");\r
82         ::wxSetWorkingDirectory(sz);\r
83         if (fp == NULL)\r
84         {\r
85 //              wxMessageBox(wxString::Format(wxT("Error :\n\nCommandLine:\n%s"), szCommandLine.c_str()));\r
86                 return TPI_ERROR_U_USE_LIBRARY;\r
87         }\r
88 \r
89         if (bCheckExist)\r
90         {\r
91                 return TPI_ERROR_SUCCESS;\r
92         }\r
93 \r
94         if (szOutput != NULL)\r
95         {\r
96                 char sz[32769];\r
97                 while (! feof(fp))\r
98                 {\r
99                         memset(sz, 0, sizeof(sz));\r
100                         fread(sz, sizeof(char), sizeof(sz) - 1, fp);\r
101                         * szOutput += UTF82String(sz);\r
102                 }\r
103 //              ::wxMessageBox(* szOutput);\r
104         }\r
105 \r
106         pclose(fp);\r
107         return TPI_ERROR_SUCCESS;\r
108 #else\r
109         SECURITY_ATTRIBUTES sa;\r
110         memset(& sa, 0, sizeof(SECURITY_ATTRIBUTES));\r
111         sa.bInheritHandle = TRUE;\r
112         sa.nLength = sizeof(SECURITY_ATTRIBUTES);\r
113         HANDLE hRead, hWrite;\r
114         if (! ::CreatePipe(& hRead, & hWrite, & sa, 0xffffffff))\r
115         {\r
116                 return TPI_ERROR_U_USE_LIBRARY;\r
117         }\r
118         STARTUPINFO si;\r
119         memset(& si, 0, sizeof(STARTUPINFO));\r
120         si.cb = sizeof(STARTUPINFO);\r
121         si.dwFlags = STARTF_USESTDHANDLES;\r
122         si.hStdOutput = hWrite;\r
123         si.hStdError = hWrite;\r
124         PROCESS_INFORMATION pi;\r
125         if (! ::CreateProcess(NULL, szCommandLine.wchar_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, szCwd.IsEmpty() ? NULL : szCwd.wchar_str(), & si, & pi))\r
126         {\r
127                 return TPI_ERROR_U_USE_LIBRARY;\r
128         }\r
129 \r
130         ::WaitForInputIdle(pi.hProcess, INFINITE);\r
131         ::WaitForSingleObject(pi.hProcess, INFINITE);\r
132 \r
133         DWORD nErrorCode = 0;\r
134         ::GetExitCodeProcess(pi.hProcess, & nErrorCode);\r
135         ::CloseHandle(pi.hThread);\r
136         ::CloseHandle(pi.hProcess);\r
137 \r
138         if (bCheckExist)\r
139         {\r
140                 return TPI_ERROR_SUCCESS;\r
141         }\r
142 \r
143         if (szOutput != NULL)\r
144         {\r
145                 DWORD dwSize = 0;\r
146                 char sz[32769];\r
147                 for (wxULongLong llSize = 0; llSize < ::GetFileSize(hRead, NULL); llSize += dwSize)\r
148                 {\r
149                         memset(sz, 0, sizeof(sz));\r
150                         dwSize = 0;\r
151                         ::ReadFile(hRead, sz, sizeof(sz) - 1, & dwSize, NULL);\r
152                         * szOutput += UTF82String(sz);\r
153 //                      ::MessageBoxA(NULL, sz, NULL, 0);\r
154                 }\r
155         }\r
156         ::CloseHandle(hRead);\r
157         ::CloseHandle(hWrite);\r
158 \r
159         return nErrorCode == 0 ? TPI_ERROR_SUCCESS : TPI_ERROR_UNDEFINED;\r
160 #endif\r
161 }\r
162 \r
163 PosInfo MakePosInfo(wxString szPrefix)\r
164 {\r
165         PosInfo pi;\r
166         g_LibInfo.node.GetPropVal(wxT("list-") + szPrefix + wxT("-s"), wxEmptyString).ToULong(& pi.nStart);\r
167         g_LibInfo.node.GetPropVal(wxT("list-") + szPrefix + wxT("-c"), wxEmptyString).ToULong(& pi.nCount);\r
168         g_LibInfo.node.GetPropVal(wxT("list-") + szPrefix + wxT("-l"), wxT("0")).ToULong(& pi.nLine);\r
169         return pi;\r
170 }\r
171 \r
172 wxULongLong GetSize(PosInfo & pi, size_t uCurrent, wxArrayString & as)\r
173 {\r
174         if (pi.nStart == 0 && pi.nCount == 0)\r
175         {\r
176                 return 0;\r
177         }\r
178 \r
179         wxULongLong_t nTemp;\r
180         size_t nPos = uCurrent + pi.nLine;\r
181         wxString sz = pi.nCount == 0 ? as[nPos].Mid(pi.nStart) : as[nPos].Mid(pi.nStart, pi.nCount);\r
182         sz.ToULongLong(& nTemp);\r
183         return nTemp;\r
184 }\r
185 \r
186 //******************************************************************************\r
187 //    Functions\r
188 //******************************************************************************\r
189 \r
190 #ifdef __cplusplus\r
191 extern "C"\r
192 {\r
193 #endif\r
194 \r
195 int __stdcall GetPluginInformation\r
196 (\r
197         unsigned int _uInfoId,\r
198         wxULongLong,\r
199         void * _pPtr\r
200 )\r
201 {\r
202         if (_pPtr == NULL)\r
203         {\r
204                 return TPI_ERROR_D_PARAMETER;\r
205         }\r
206         switch (_uInfoId)\r
207         {\r
208         case TPI_INFO_VERSION_MAJOR:\r
209         case TPI_INFO_VERSION_MINOR:\r
210                 * (int *) _pPtr = 0;\r
211                 break;\r
212         case TPI_INFO_VERSION_API:\r
213                 * (int *) _pPtr = 2;\r
214                 break;\r
215         default:\r
216                 return TPI_ERROR_D_UNSUPPORTED;\r
217         }\r
218         return TPI_ERROR_SUCCESS;\r
219 }\r
220 \r
221 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
222 {\r
223         static unsigned int s_uFileID;\r
224         wxStandardPaths p;\r
225         wxXmlDocument config(wxPathOnly(p.GetExecutablePath()) + wxT("/lib/cuiWrapper.xml"));\r
226         // 一気に先頭のライブラリの情報を取得。\r
227         wxXmlNode * xmlLibrary = config.GetRoot()->GetChildren();\r
228 \r
229         if (_bFirst)\r
230         {\r
231                 // xml解析開始。\r
232                 s_uFileID = 0;\r
233         }\r
234         else\r
235         {\r
236                 for (unsigned int i = 0; i < s_uFileID && xmlLibrary != NULL; i++)\r
237                 {\r
238                         xmlLibrary = xmlLibrary->GetNext();\r
239                 }\r
240         }\r
241 \r
242         if (xmlLibrary == NULL || xmlLibrary->GetName() != wxT("library"))\r
243         {\r
244                 // 終端に達した場合。\r
245                 return TPI_ERROR_S_ENDOFDATA;\r
246         }\r
247 \r
248         MakeFormatInfo(wxT("cuiWrapper"), _fiInfo, xmlLibrary, s_uFileID++);\r
249         if (myExecute(xmlLibrary->GetPropVal(wxT("name"), wxEmptyString), NULL, wxEmptyString, true) != TPI_ERROR_SUCCESS)\r
250         {\r
251                 _fiInfo->llSupportedCommand = 0;\r
252         }\r
253 \r
254         return TPI_ERROR_SUCCESS;\r
255 }\r
256 \r
257 int __stdcall LoadPlugin\r
258 (\r
259         const wxString & _szArcName,\r
260         wxULongLong _llSubOption\r
261 )\r
262 {\r
263         // xml解析開始。\r
264         wxStandardPaths p;\r
265         wxXmlDocument config(wxPathOnly(p.GetExecutablePath()) + wxT("/lib/cuiWrapper.xml"));\r
266         if (! config.IsOk())\r
267         {\r
268                 return TPI_ERROR_UNDEFINED;\r
269         }\r
270         // 一気に先頭のライブラリの情報を取得。\r
271         wxXmlNode * xmlLibrary = config.GetRoot()->GetChildren();\r
272 \r
273         // 対象が存在するならば対応するライブラリを調査、\r
274         // 対象が存在しないならば指示されたライブラリをロード。\r
275         if (! ::wxFileExists(_szArcName))\r
276         {\r
277                 // 適当な位置まで移動。\r
278                 for (g_LibInfo.nLibIndex = 0; g_LibInfo.nLibIndex < _llSubOption && xmlLibrary != NULL; g_LibInfo.nLibIndex++)\r
279                 {\r
280                         xmlLibrary = xmlLibrary->GetNext();\r
281                 }\r
282                 if (xmlLibrary == NULL || xmlLibrary->GetName() != wxT("library"))\r
283                 {\r
284                         // xml文法エラー。\r
285                         return TPI_ERROR_UNDEFINED;\r
286                 }\r
287                 g_LibInfo.szExeFile = xmlLibrary->GetPropVal(wxT("name"), wxEmptyString);\r
288                 g_LibInfo.szExeFileAlt = xmlLibrary->GetPropVal(wxT("name-alt"), wxEmptyString);\r
289                 g_LibInfo.node = * xmlLibrary;\r
290 \r
291                 return TPI_ERROR_SUCCESS;\r
292         }\r
293 \r
294         // 無限ループに陥らないよう上限を設定。\r
295         for (g_LibInfo.nLibIndex = 0; g_LibInfo.nLibIndex < 300 && xmlLibrary != NULL; g_LibInfo.nLibIndex++)\r
296         {\r
297                 // ライブラリをロード。\r
298                 g_LibInfo.szExeFile = xmlLibrary->GetPropVal(wxT("name"), wxEmptyString);\r
299                 g_LibInfo.szExeFileAlt = xmlLibrary->GetPropVal(wxT("name-alt"), wxEmptyString);\r
300                 g_LibInfo.node = * xmlLibrary;\r
301 \r
302                 // 書庫に対応しているかチェック。\r
303                 if (CheckArchive(_szArcName, NULL) == TPI_ERROR_SUCCESS)\r
304                 {\r
305                         // 対応していれば処理を終了。\r
306                         return TPI_ERROR_SUCCESS;\r
307                 }\r
308 \r
309                 xmlLibrary = xmlLibrary->GetNext();\r
310         }\r
311 \r
312         return TPI_ERROR_U_LOAD_LIBRARY;\r
313 }\r
314 \r
315 int __stdcall FreePlugin\r
316 (\r
317         void * // _pReserved\r
318 )\r
319 {\r
320         return TPI_ERROR_SUCCESS;\r
321 }\r
322 \r
323 int __stdcall CheckArchive\r
324 (\r
325         const wxString & _szArcName,\r
326         wxULongLong * _llFileCount\r
327 )\r
328 {\r
329         wxFileName fnArchive(_szArcName);\r
330         wxArrayString asExt = ::wxStringTokenize(g_LibInfo.node.GetPropVal(wxT("suffix"), wxEmptyString), wxT(";"));\r
331         if (! g_LibInfo.node.HasProp(wxT("list")))\r
332         {\r
333                 return TPI_ERROR_ARC_UNSUPPORTED;\r
334         }\r
335 \r
336         for (size_t i = 0; i < asExt.GetCount(); i++)\r
337         {\r
338                 // .tar.XXXなど二重判定への対応。\r
339 //              if (asExt[i].IsSameAs(fnArchive.GetExt(), false))\r
340                 if (fnArchive.GetFullName().EndsWith(wxT('.') + asExt[i]))\r
341                 {\r
342                         // 開いて確認。先行してデータを取得しておく。\r
343                         int nErrorCode = OpenArchive(_szArcName, NULL);\r
344 \r
345                         // 対応。\r
346                         if (_llFileCount != NULL)\r
347                         {\r
348                                 // ファイル数は多めに取っておく。\r
349                                 * _llFileCount = g_asOutput.GetCount();\r
350                         }\r
351                         return nErrorCode;\r
352                 }\r
353         }\r
354 \r
355         return TPI_ERROR_ARC_UNSUPPORTED;\r
356 }\r
357 \r
358 int __stdcall OpenArchive\r
359 (\r
360         const wxString & _szArcName,\r
361         void * * _hArchive\r
362 )\r
363 {\r
364         if (g_szCurrentArchive != _szArcName)\r
365         {\r
366                 wxString szOutput;\r
367                 if (myExecute(g_LibInfo.szExeFile + wxT(" ") + MakeCommandLineSend(g_LibInfo.node.GetPropVal(wxT("list"), wxEmptyString), _szArcName, NULL, NULL, wxEmptyString), & szOutput, wxEmptyString) != TPI_ERROR_SUCCESS)\r
368                 {\r
369                         return TPI_ERROR_U_USE_LIBRARY;\r
370                 }\r
371                 g_szCurrentArchive = _szArcName;\r
372                 g_asOutput = ::wxStringTokenize(szOutput, wxT("\r\n"));\r
373                 g_asOutput.Shrink();\r
374         }\r
375         if (_hArchive != NULL)\r
376         {\r
377                 * _hArchive = & g_asOutput;\r
378         }\r
379         return g_asOutput.IsEmpty() ? TPI_ERROR_UNDEFINED : TPI_ERROR_SUCCESS;\r
380 }\r
381 \r
382 int __stdcall CloseArchive\r
383 (\r
384         void * _hArchive\r
385 )\r
386 {\r
387         ((wxArrayString *) _hArchive)->Clear();\r
388         return TPI_ERROR_SUCCESS;\r
389 }\r
390 \r
391 int __stdcall GetFileInformation\r
392 (\r
393         void * _hArchive,\r
394         TPI_FILEINFO * _fiInfo,\r
395         bool _bFirst\r
396 )\r
397 {\r
398         static size_t s_uCurrentLine;\r
399         static wxULongLong s_llFileID;\r
400         if (_hArchive == NULL)\r
401         {\r
402                 return TPI_ERROR_UNDEFINED;\r
403         }\r
404         wxArrayString asOutput = * (wxArrayString *) _hArchive;\r
405 \r
406         // XMLからの読み込みは初回に行う。\r
407         static wxString szEndLine, szDateFormat;\r
408         static unsigned long nProcessPerLine;\r
409         static PosInfo piFName, piPSize, piUSize, piDate;\r
410         if (_bFirst)\r
411         {\r
412                 s_llFileID = 0;\r
413                 wxString szStartLine = g_LibInfo.node.GetPropVal(wxT("list-line-s"), wxEmptyString);\r
414                 if (! szStartLine.IsEmpty())\r
415                 {\r
416                         // 開始行の次の行にセット。\r
417                         s_uCurrentLine = asOutput.Index(szStartLine) + 1;\r
418                         if (s_uCurrentLine == wxNOT_FOUND + 1)\r
419                         {\r
420                                 // 書庫が読み込めなかった?\r
421                                 return TPI_ERROR_ARC_UNSUPPORTED;\r
422                         }\r
423                 }\r
424 \r
425                 // 初期設定。\r
426                 g_LibInfo.node.GetPropVal(wxT("list-line-c"), wxT("1")).ToULong(& nProcessPerLine);\r
427                 szEndLine = g_LibInfo.node.GetPropVal(wxT("list-line-e"), szStartLine);\r
428                 szDateFormat = g_LibInfo.node.GetPropVal(wxT("list-date-f"), wxDefaultDateTimeFormat);\r
429                 piFName = MakePosInfo(wxT("fname"));\r
430                 piPSize = MakePosInfo(wxT("psize"));\r
431                 piUSize = MakePosInfo(wxT("usize"));\r
432                 piDate = MakePosInfo(wxT("date"));\r
433         }\r
434 \r
435         if (s_uCurrentLine >= asOutput.GetCount())\r
436         {\r
437                 // 書庫が読み込めなかった?\r
438                 return TPI_ERROR_ARC_UNSUPPORTED;\r
439         }\r
440 \r
441         // 最終行かどうか確認。\r
442         if (asOutput[s_uCurrentLine] == szEndLine)\r
443         {\r
444                 return TPI_ERROR_S_ENDOFDATA;\r
445         }\r
446 \r
447         // ファイル名を取得。\r
448         _fiInfo->szStoredName = piFName.nCount == 0 ? asOutput[s_uCurrentLine + piFName.nLine].Mid(piFName.nStart) : asOutput[s_uCurrentLine + piFName.nLine].Mid(piFName.nStart, piFName.nCount);\r
449         _fiInfo->szStoredName.Trim();\r
450         _fiInfo->fnFileName = wxFileName::wxFileName(_fiInfo->szStoredName);\r
451 \r
452         // サイズ取得。\r
453         _fiInfo->llPackedSize   = GetSize(piPSize, s_uCurrentLine, asOutput);\r
454         _fiInfo->llUnpackedSize = GetSize(piUSize, s_uCurrentLine, asOutput);\r
455 \r
456         // 更新時刻取得。\r
457         if (piDate.nStart != 0 || piDate.nCount != 0)\r
458         {\r
459                 _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
460         }\r
461 \r
462         // 最後に次の行へ進めておく。\r
463         _fiInfo->llFileID = s_llFileID++;\r
464         s_uCurrentLine += nProcessPerLine;\r
465 \r
466         return TPI_ERROR_SUCCESS;\r
467 }\r
468 \r
469 int __stdcall GetArchiveInformation\r
470 (\r
471         void *,\r
472         TPI_ARCHIVEINFO * _aiInfo\r
473 )\r
474 {\r
475         // 形式に関する情報を取得。\r
476         MakeFormatInfo(wxT("cuiWrapper"), & _aiInfo->fiInfo, & g_LibInfo.node, 0);\r
477         return TPI_ERROR_SUCCESS;\r
478 }\r
479 \r
480 int __stdcall Command\r
481 (\r
482         unsigned int _uCommand,\r
483         TPI_SWITCHES * _swInfo,\r
484         const wxString & _szArcName,\r
485         const wxArrayString & _szFiles\r
486 )\r
487 {\r
488         // xmlからコマンドラインを取得。\r
489         wxString szPath, szCommandLine;\r
490 \r
491         // APIアドレス取得。\r
492         if (! g_LibInfo.node.GetPropVal(\r
493                         _uCommand == TPI_COMMAND_ADD     ? wxT("add") :\r
494                         _uCommand == TPI_COMMAND_EXTRACT ? wxT("extract") : \r
495                         _uCommand == TPI_COMMAND_DELETE  ? wxT("delete") : \r
496                         _uCommand == TPI_COMMAND_UPDATE  ? wxT("update") : \r
497                         _uCommand == TPI_COMMAND_TEST    ? wxT("test") : \r
498                         _uCommand == TPI_COMMAND_REPAIR  ? wxT("repair") : \r
499                         _uCommand == TPI_COMMAND_MOVE    ? wxT("move") : \r
500                         _uCommand == TPI_COMMAND_SFX     ? wxT("sfx") : \r
501                         _uCommand == TPI_COMMAND_UNSFX   ? wxT("unsfx") : wxEmptyString, & szCommandLine))\r
502         {\r
503                 g_LibInfo.node.GetPropVal(\r
504                         _uCommand == TPI_COMMAND_ADD     ? wxT("add-alt") :\r
505                         _uCommand == TPI_COMMAND_EXTRACT ? wxT("extract-alt") : \r
506                         _uCommand == TPI_COMMAND_DELETE  ? wxT("delete-alt") : \r
507                         _uCommand == TPI_COMMAND_UPDATE  ? wxT("update-alt") : \r
508                         _uCommand == TPI_COMMAND_TEST    ? wxT("test-alt") : \r
509                         _uCommand == TPI_COMMAND_REPAIR  ? wxT("repair-alt") : \r
510                         _uCommand == TPI_COMMAND_MOVE    ? wxT("move-alt") : \r
511                         _uCommand == TPI_COMMAND_SFX     ? wxT("sfx-alt") : \r
512                         _uCommand == TPI_COMMAND_UNSFX   ? wxT("unsfx-alt") : wxEmptyString, & szCommandLine);\r
513         }\r
514 \r
515         if (szCommandLine.IsEmpty())\r
516         {\r
517                 return TPI_ERROR_U_USE_LIBRARY;\r
518         }\r
519 \r
520         // コマンドライン・レスポンスファイル作成。\r
521         wxString\r
522                 szResponceFileName = MakeResponceFile(_szFiles, g_LibInfo.node.GetPropVal(wxT("quote-resp"), wxT("1")) == wxT("1")),\r
523                 szCommandLineSend  = MakeCommandLineSend(szCommandLine, _szArcName, _swInfo, _szFiles, szResponceFileName);\r
524 \r
525         // コマンドライン実行。\r
526         wxString szOutput;\r
527         int nErrorCode = myExecute(g_LibInfo.szExeFile + wxT(" ") + szCommandLineSend, & szOutput, _swInfo->fnDestinationDirectory.GetFullPath());\r
528 \r
529         // レスポンスファイル削除。\r
530         ::wxRemoveFile(szResponceFileName);\r
531 \r
532         if (nErrorCode != TPI_ERROR_SUCCESS)\r
533         {\r
534 #ifdef __LINUX__\r
535                 ::wxMessageBox(wxString::Format(wxT("Error :\n%d\n\nCommandLine:\n%s\n\nOutput:\n%s"), nErrorCode, szCommandLineSend.c_str(), szOutput.c_str()));\r
536 #else\r
537                 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
538 #endif\r
539         }\r
540         return nErrorCode;\r
541 }\r
542 \r
543 int __stdcall SetCallbackProc\r
544 (\r
545         TPI_PROC _prArcProc\r
546 )\r
547 {\r
548         // ポインタを保存。\r
549         if (_prArcProc == NULL)\r
550         {\r
551                 return TPI_ERROR_D_PARAMETER;\r
552         }\r
553         g_prProc = * _prArcProc;\r
554 \r
555         return TPI_ERROR_SUCCESS;\r
556 }\r
557 \r
558 #ifdef __cplusplus\r
559 }\r
560 #endif\r