OSDN Git Service

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