* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Client.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Client.c\r
79 // クライアントマネージャ\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 static CLIENT *client = NULL;\r
84 static LISTENER *cn_listener = NULL;\r
85 static LOCK *cn_listener_lock = NULL;\r
86 static UINT64 cn_next_allow = 0;\r
87 \r
88 #ifdef  OS_WIN32\r
89 \r
90 #endif  // OS_WIN32\r
91 \r
92 // 注意: VPN Client サービスを実装するこのソースコードの一部には、\r
93 // リエントラント (Reentrant: 再入可能) でないコードが含まれている。\r
94 // もともと VPN Client のサービスと GUI (クライアント接続マネージャ) は一体\r
95 // のものとして開発され、途中で分離された。その際に本来であれば TLS 等を用いて\r
96 // スレッドセーフにしなければならない部分が、もとのままになってしまっている。\r
97 // したがって、ごくまれに、GUI (クライアント接続マネージャ) や utvpncmd が\r
98 // 複数個、1 個の VPN Client サービスに対して接続して、ほぼ同時に何らかの\r
99 // 内部状態を変化させる処理を行ったとき、戻り値に不整合が生じる場合がある。\r
100 \r
101 // RPC_CLIENT_ENUM_ACCOUNT_ITEM を最終接続日時で逆ソート\r
102 int CiCompareClientAccountEnumItemByLastConnectDateTime(void *p1, void *p2)\r
103 {\r
104         RPC_CLIENT_ENUM_ACCOUNT_ITEM *a1, *a2;\r
105         if (p1 == NULL || p2 == NULL)\r
106         {\r
107                 return 0;\r
108         }\r
109         a1 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p1;\r
110         a2 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p2;\r
111         if (a1 == NULL || a2 == NULL)\r
112         {\r
113                 return 0;\r
114         }\r
115         if (a1->LastConnectDateTime > a2->LastConnectDateTime)\r
116         {\r
117                 return -1;\r
118         }\r
119         else if (a1->LastConnectDateTime < a2->LastConnectDateTime)\r
120         {\r
121                 return 1;\r
122         }\r
123 \r
124         return 0;\r
125 }\r
126 \r
127 // マシンが変更されていた場合はすべての仮想 LAN カードの MAC アドレスを乱数に設定する\r
128 // このあたりは急いで実装したのでコードがあまり美しくない。\r
129 // Q. なぜこのような処理が必要なのか?\r
130 // A. Windows をインストールし、次に VPN Client をインストールして仮想 LAN カード\r
131 //    を作成した状態を初期状態として HDD イメージをクローンし社内の複数の PC に\r
132 //    インストールするような企業が存在する。\r
133 //    そのような企業においてクローン後も仮想 LAN カードの MAC アドレスがすべて同一\r
134 //    であれば障害の理由になる可能性があるためである。\r
135 void CiChangeAllVLanMacAddressIfMachineChanged(CLIENT *c)\r
136 {\r
137         UCHAR current_hash[SHA1_SIZE];\r
138         UCHAR current_hash_old[SHA1_SIZE];\r
139         UCHAR saved_hash[SHA1_SIZE];\r
140         // 引数チェック\r
141         if (c == NULL)\r
142         {\r
143                 return;\r
144         }\r
145 \r
146 #ifdef OS_WIN32\r
147         if (MsIsAdmin() == false)\r
148         {\r
149                 return;\r
150         }\r
151 #endif\r
152 \r
153         // このあたりは急いで実装したのでコードがあまり美しくない。\r
154         CiGetCurrentMachineHash(current_hash);\r
155         CiGetCurrentMachineHashOld(current_hash_old);\r
156 \r
157         if (CiReadLastMachineHash(saved_hash) == false)\r
158         {\r
159                 CiWriteLastMachineHash(current_hash);\r
160                 return;\r
161         }\r
162 \r
163         if (Cmp(saved_hash, current_hash_old, SHA1_SIZE) == 0)\r
164         {\r
165                 CiWriteLastMachineHash(current_hash);\r
166                 return;\r
167         }\r
168 \r
169         if (Cmp(saved_hash, current_hash, SHA1_SIZE) == 0)\r
170         {\r
171                 return;\r
172         }\r
173 \r
174         if (CiWriteLastMachineHash(current_hash) == false)\r
175         {\r
176                 return;\r
177         }\r
178 \r
179         CiChangeAllVLanMacAddress(c);\r
180 }\r
181 \r
182 // 現在のマシンハッシュを取得する (古い方式)\r
183 // このあたりは急いで実装したのでコードがあまり美しくない。\r
184 void CiGetCurrentMachineHashOld(void *data)\r
185 {\r
186         char name[MAX_PATH];\r
187         char *product_id = NULL;\r
188         // 引数チェック\r
189         if (data == NULL)\r
190         {\r
191                 return;\r
192         }\r
193 \r
194 #ifdef  OS_WIN32\r
195         // プロダクト ID\r
196         product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");\r
197         if (product_id == NULL)\r
198         {\r
199                 product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");\r
200         }\r
201 \r
202         StrCpy(name, sizeof(name), product_id);\r
203 \r
204         Free(product_id);\r
205 \r
206 #else   // OS_WIN32\r
207         GetMachineName(name, sizeof(name));\r
208 #endif  // OS_WIN32\r
209 \r
210         Trim(name);\r
211         StrUpper(name);\r
212 \r
213         Hash(data, name, StrLen(name), true);\r
214 }\r
215 \r
216 // 現在のマシンハッシュを取得する\r
217 void CiGetCurrentMachineHash(void *data)\r
218 {\r
219         char name[MAX_PATH];\r
220         char *product_id = NULL;\r
221         // 引数チェック\r
222         if (data == NULL)\r
223         {\r
224                 return;\r
225         }\r
226 \r
227         GetMachineName(name, sizeof(name));\r
228 \r
229         Trim(name);\r
230         StrUpper(name);\r
231 \r
232         Hash(data, name, StrLen(name), true);\r
233 }\r
234 \r
235 // マシンハッシュを書き込む\r
236 bool CiWriteLastMachineHash(void *data)\r
237 {\r
238         // 引数チェック\r
239         if (data == NULL)\r
240         {\r
241                 return false;\r
242         }\r
243 \r
244 #ifdef OS_WIN32\r
245         if (MsRegWriteBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash_UTVPNClient", data, SHA1_SIZE, true) == false)\r
246         {\r
247                 return false;\r
248         }\r
249 \r
250         return true;\r
251 #else   // OS_WIN32\r
252         return false;\r
253 #endif  // OS_WIN32\r
254 }\r
255 \r
256 // 前回のマシンハッシュを取得する\r
257 bool CiReadLastMachineHash(void *data)\r
258 {\r
259         BUF *b = NULL;\r
260         // 引数チェック\r
261         if (data == NULL)\r
262         {\r
263                 return false;\r
264         }\r
265 \r
266 #ifdef OS_WIN32\r
267         b = MsRegReadBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash_UTVPNClient", true);\r
268         if (b == NULL)\r
269         {\r
270                 return false;\r
271         }\r
272         if (b->Size == SHA1_SIZE)\r
273         {\r
274                 Copy(data, b->Buf, b->Size);\r
275                 FreeBuf(b);\r
276 \r
277                 return true;\r
278         }\r
279 \r
280         FreeBuf(b);\r
281         return false;\r
282 #else   // OS_WIN32\r
283         return false;\r
284 #endif  // OS_WIN32\r
285 }\r
286 \r
287 // すべての仮想 LAN カードの MAC アドレスを乱数に設定する\r
288 void CiChangeAllVLanMacAddress(CLIENT *c)\r
289 {\r
290         RPC_CLIENT_ENUM_VLAN t;\r
291         // 引数チェック\r
292         if (c == NULL)\r
293         {\r
294                 return;\r
295         }\r
296 \r
297         Zero(&t, sizeof(t));\r
298         if (CtEnumVLan(c, &t))\r
299         {\r
300                 UINT i;\r
301 \r
302                 for (i = 0;i < t.NumItem;i++)\r
303                 {\r
304                         RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];\r
305                         UCHAR mac[6];\r
306 \r
307                         if (StrToMac(mac, e->MacAddress) && mac[1] == 0xAC)\r
308                         {\r
309                                 char *name = e->DeviceName;\r
310                                 RPC_CLIENT_SET_VLAN s;\r
311                                 UCHAR mac[6];\r
312 \r
313                                 GenMacAddress(mac);\r
314 \r
315                                 Zero(&s, sizeof(s));\r
316                                 StrCpy(s.DeviceName, sizeof(s.DeviceName), name);\r
317 \r
318                                 MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);\r
319 \r
320                                 CtSetVLan(c, &s);\r
321                         }\r
322                 }\r
323 \r
324                 CiFreeClientEnumVLan(&t);\r
325         }\r
326 }\r
327 \r
328 // 通知サービスの準備が完了するまで待機する\r
329 void CnWaitForCnServiceReady()\r
330 {\r
331         UINT64 start_time = Tick64();\r
332 \r
333         while ((start_time + (UINT64)CLIENT_WAIT_CN_READY_TIMEOUT) >= Tick64())\r
334         {\r
335                 if (CnIsCnServiceReady())\r
336                 {\r
337                         break;\r
338                 }\r
339 \r
340                 SleepThread(100);\r
341         }\r
342 }\r
343 \r
344 // 通知サービスの準備が完了しているかどうかチェックする\r
345 // このあたりは急いで実装したのでコードがあまり美しくない。\r
346 bool CnIsCnServiceReady()\r
347 {\r
348         SOCK *s;\r
349         // 通知サービスの起動を確認する\r
350         if (CnCheckAlreadyExists(false) == false)\r
351         {\r
352                 // 起動していない\r
353                 return false;\r
354         }\r
355 \r
356         // TCP ポートへの接続を試行する\r
357         s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, 500);\r
358         if (s == NULL)\r
359         {\r
360                 // TCP ポートを開いていない\r
361                 return false;\r
362         }\r
363 \r
364         Disconnect(s);\r
365         ReleaseSock(s);\r
366 \r
367         // 起動していた\r
368         return true;\r
369 }\r
370 \r
371 // すでに通知サービスが動作しているかどうかチェックする\r
372 bool CnCheckAlreadyExists(bool lock)\r
373 {\r
374         bool ret = false;\r
375 \r
376 #ifdef  OS_WIN32\r
377         ret = Win32CnCheckAlreadyExists(lock);\r
378 #endif\r
379 \r
380         return ret;\r
381 }\r
382 \r
383 typedef struct CNC_STATUS_PRINTER_WINDOW_PARAM\r
384 {\r
385         THREAD *Thread;\r
386         SESSION *Session;\r
387         SOCK *Sock;\r
388 } CNC_STATUS_PRINTER_WINDOW_PARAM;\r
389 \r
390 typedef struct CNC_CONNECT_ERROR_DLG_THREAD_PARAM\r
391 {\r
392         SESSION *Session;\r
393         SOCK *Sock;\r
394         bool HaltThread;\r
395         EVENT *Event;\r
396 } CNC_CONNECT_ERROR_DLG_THREAD_PARAM;\r
397 \r
398 \r
399 // Win32 における utvpnclient.exe のファイル名を取得する\r
400 char *CiGetVpnClientExeFileName()\r
401 {\r
402         if (Is64() == false)\r
403         {\r
404                 return CLIENT_WIN32_EXE_FILENAME;\r
405         }\r
406         else\r
407         {\r
408                 if (IsX64())\r
409                 {\r
410                         return CLIENT_WIN32_EXE_FILENAME_X64;\r
411                 }\r
412                 else\r
413                 {\r
414                         return CLIENT_WIN32_EXE_FILENAME_IA64;\r
415                 }\r
416         }\r
417 }\r
418 \r
419 // 証明書チェックダイアログクライアント強制停止用スレッド\r
420 void CncCheckCertHaltThread(THREAD *thread, void *param)\r
421 {\r
422         CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;\r
423         // 引数チェック\r
424         if (thread == NULL || param == NULL)\r
425         {\r
426                 return;\r
427         }\r
428 \r
429         while (true)\r
430         {\r
431                 if (dp->Session->Halt || dp->HaltThread)\r
432                 {\r
433                         break;\r
434                 }\r
435 \r
436                 Wait(dp->Event, 100);\r
437         }\r
438 \r
439         Disconnect(dp->Sock);\r
440 }\r
441 \r
442 // 証明書チェックダイアログの表示\r
443 void CncCheckCert(SESSION *session, UI_CHECKCERT *dlg)\r
444 {\r
445         SOCK *s;\r
446         PACK *p;\r
447         CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;\r
448         THREAD *t;\r
449         // 引数チェック\r
450         if (dlg == NULL || session == NULL)\r
451         {\r
452                 return;\r
453         }\r
454 \r
455         s = CncConnect();\r
456         if (s == NULL)\r
457         {\r
458                 return;\r
459         }\r
460 \r
461         p = NewPack();\r
462         PackAddStr(p, "function", "check_cert");\r
463         PackAddUniStr(p, "AccountName", dlg->AccountName);\r
464         PackAddStr(p, "ServerName", dlg->ServerName);\r
465         PackAddX(p, "x", dlg->x);\r
466         PackAddX(p, "parent_x", dlg->parent_x);\r
467         PackAddX(p, "old_x", dlg->old_x);\r
468         PackAddBool(p, "DiffWarning", dlg->DiffWarning);\r
469         PackAddBool(p, "Ok", dlg->Ok);\r
470         PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);\r
471 \r
472         SendPack(s, p);\r
473         FreePack(p);\r
474 \r
475         dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));\r
476         dp->Sock = s;\r
477         dp->Event = NewEvent();\r
478         dp->Session = session;\r
479 \r
480         t = NewThread(CncCheckCertHaltThread, dp);\r
481 \r
482         p = RecvPack(s);\r
483         if (p != NULL)\r
484         {\r
485                 dlg->Ok = PackGetBool(p, "Ok");\r
486                 dlg->DiffWarning = PackGetBool(p, "DiffWarning");\r
487                 dlg->SaveServerCert = PackGetBool(p, "SaveServerCert");\r
488 \r
489                 FreePack(p);\r
490         }\r
491 \r
492         dp->HaltThread = true;\r
493         Set(dp->Event);\r
494 \r
495         WaitThread(t, INFINITE);\r
496 \r
497         ReleaseEvent(dp->Event);\r
498         Free(dp);\r
499         ReleaseThread(t);\r
500 \r
501         Disconnect(s);\r
502         ReleaseSock(s);\r
503 }\r
504 \r
505 // スマートカード署名ダイアログ\r
506 bool CncSecureSignDlg(SECURE_SIGN *sign)\r
507 {\r
508         SOCK *s;\r
509         PACK *p;\r
510         bool ret = false;\r
511         // 引数チェック\r
512         if (sign == NULL)\r
513         {\r
514                 return false;\r
515         }\r
516 \r
517         s = CncConnect();\r
518         if (s == NULL)\r
519         {\r
520                 return false;\r
521         }\r
522 \r
523         p = NewPack();\r
524         PackAddStr(p, "function", "secure_sign");\r
525         OutRpcSecureSign(p, sign);\r
526 \r
527         SendPack(s, p);\r
528         FreePack(p);\r
529 \r
530         p = RecvPack(s);\r
531         if (p != NULL)\r
532         {\r
533                 ret = PackGetBool(p, "ret");\r
534 \r
535                 if (ret)\r
536                 {\r
537                         FreeRpcSecureSign(sign);\r
538 \r
539                         Zero(sign, sizeof(SECURE_SIGN));\r
540                         InRpcSecureSign(sign, p);\r
541                 }\r
542 \r
543                 FreePack(p);\r
544         }\r
545 \r
546         Disconnect(s);\r
547         ReleaseSock(s);\r
548 \r
549         return ret;\r
550 }\r
551 \r
552 // NIC 情報ダイアログの表示\r
553 SOCK *CncNicInfo(UI_NICINFO *info)\r
554 {\r
555         SOCK *s;\r
556         PACK *p;\r
557         bool ret = false;\r
558         // 引数チェック\r
559         if (info == NULL)\r
560         {\r
561                 return NULL;\r
562         }\r
563 \r
564         s = CncConnectEx(200);\r
565         if (s == NULL)\r
566         {\r
567                 return NULL;\r
568         }\r
569 \r
570         p = NewPack();\r
571         PackAddStr(p, "function", "nicinfo");\r
572         PackAddStr(p, "NicName", info->NicName);\r
573         PackAddUniStr(p, "AccountName", info->AccountName);\r
574 \r
575         SendPack(s, p);\r
576         FreePack(p);\r
577 \r
578         return s;\r
579 }\r
580 \r
581 // NIC 情報ダイアログを閉じる\r
582 void CncNicInfoFree(SOCK *s)\r
583 {\r
584         // 引数チェック\r
585         if (s == NULL)\r
586         {\r
587                 return;\r
588         }\r
589 \r
590         Disconnect(s);\r
591         ReleaseSock(s);\r
592 }\r
593 \r
594 // メッセージダイアログの表示\r
595 SOCK *CncMsgDlg(UI_MSG_DLG *dlg)\r
596 {\r
597         SOCK *s;\r
598         PACK *p;\r
599         bool ret = false;\r
600         char *utf;\r
601         // 引数チェック\r
602         if (dlg == NULL)\r
603         {\r
604                 return NULL;\r
605         }\r
606 \r
607         s = CncConnectEx(200);\r
608         if (s == NULL)\r
609         {\r
610                 return NULL;\r
611         }\r
612 \r
613         p = NewPack();\r
614         PackAddStr(p, "function", "msg_dialog");\r
615         PackAddStr(p, "ServerName", dlg->ServerName);\r
616         PackAddStr(p, "HubName", dlg->HubName);\r
617         utf = CopyUniToUtf(dlg->Msg);\r
618         PackAddData(p, "Msg", utf, StrLen(utf));\r
619         Free(utf);\r
620 \r
621         SendPack(s, p);\r
622         FreePack(p);\r
623 \r
624         return s;\r
625 }\r
626 \r
627 // メッセージダイアログを閉じる\r
628 void CndMsgDlgFree(SOCK *s)\r
629 {\r
630         // 引数チェック\r
631         if (s == NULL)\r
632         {\r
633                 return;\r
634         }\r
635 \r
636         Disconnect(s);\r
637         ReleaseSock(s);\r
638 }\r
639 \r
640 // パスワード入力ダイアログクライアント強制停止用スレッド\r
641 void CncPasswordDlgHaltThread(THREAD *thread, void *param)\r
642 {\r
643         CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;\r
644         // 引数チェック\r
645         if (thread == NULL || param == NULL)\r
646         {\r
647                 return;\r
648         }\r
649 \r
650         while (true)\r
651         {\r
652                 if (dp->Session->Halt || dp->HaltThread)\r
653                 {\r
654                         break;\r
655                 }\r
656 \r
657                 Wait(dp->Event, 100);\r
658         }\r
659 \r
660         Disconnect(dp->Sock);\r
661 }\r
662 \r
663 // パスワード入力ダイアログの表示\r
664 bool CncPasswordDlg(SESSION *session, UI_PASSWORD_DLG *dlg)\r
665 {\r
666         SOCK *s;\r
667         PACK *p;\r
668         CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;\r
669         THREAD *t;\r
670         bool ret = false;\r
671         // 引数チェック\r
672         if (dlg == NULL || session == NULL)\r
673         {\r
674                 return false;\r
675         }\r
676 \r
677         s = CncConnect();\r
678         if (s == NULL)\r
679         {\r
680                 Wait(session->HaltEvent, session->RetryInterval);\r
681                 return true;\r
682         }\r
683 \r
684         p = NewPack();\r
685         PackAddStr(p, "function", "password_dialog");\r
686         PackAddInt(p, "Type", dlg->Type);\r
687         PackAddStr(p, "Username", dlg->Username);\r
688         PackAddStr(p, "Password", dlg->Password);\r
689         PackAddStr(p, "ServerName", dlg->ServerName);\r
690         PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);\r
691         PackAddBool(p, "ProxyServer", dlg->ProxyServer);\r
692         PackAddBool(p, "AdminMode", dlg->AdminMode);\r
693         PackAddBool(p, "ShowNoSavePassword", dlg->ShowNoSavePassword);\r
694         PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);\r
695 \r
696         SendPack(s, p);\r
697         FreePack(p);\r
698 \r
699         dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));\r
700         dp->Session = session;\r
701         dp->Sock = s;\r
702         dp->Event = NewEvent();\r
703 \r
704         t = NewThread(CncConnectErrorDlgHaltThread, dp);\r
705 \r
706         p = RecvPack(s);\r
707         if (p != NULL)\r
708         {\r
709                 ret = PackGetBool(p, "ok");\r
710                 dlg->NoSavePassword = PackGetBool(p, "NoSavePassword");\r
711                 dlg->ProxyServer = PackGetBool(p, "ProxyServer");\r
712                 dlg->Type = PackGetInt(p, "Type");\r
713                 PackGetStr(p, "Username", dlg->Username, sizeof(dlg->Username));\r
714                 PackGetStr(p, "Password", dlg->Password, sizeof(dlg->Password));\r
715 \r
716                 FreePack(p);\r
717         }\r
718 \r
719         dp->HaltThread = true;\r
720         Set(dp->Event);\r
721 \r
722         WaitThread(t, INFINITE);\r
723 \r
724         ReleaseEvent(dp->Event);\r
725         Free(dp);\r
726         ReleaseThread(t);\r
727 \r
728         Disconnect(s);\r
729         ReleaseSock(s);\r
730 \r
731         return ret;\r
732 }\r
733 \r
734 // 接続エラーダイアログクライアント強制停止用スレッド\r
735 void CncConnectErrorDlgHaltThread(THREAD *thread, void *param)\r
736 {\r
737         CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;\r
738         // 引数チェック\r
739         if (thread == NULL || param == NULL)\r
740         {\r
741                 return;\r
742         }\r
743 \r
744         while (true)\r
745         {\r
746                 if (dp->Session->Halt || dp->HaltThread)\r
747                 {\r
748                         break;\r
749                 }\r
750 \r
751                 Wait(dp->Event, 100);\r
752         }\r
753 \r
754         Disconnect(dp->Sock);\r
755 }\r
756 \r
757 // 接続エラーダイアログの表示\r
758 bool CncConnectErrorDlg(SESSION *session, UI_CONNECTERROR_DLG *dlg)\r
759 {\r
760         SOCK *s;\r
761         PACK *p;\r
762         CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;\r
763         THREAD *t;\r
764         bool ret = false;\r
765         // 引数チェック\r
766         if (dlg == NULL || session == NULL)\r
767         {\r
768                 return false;\r
769         }\r
770 \r
771         s = CncConnect();\r
772         if (s == NULL)\r
773         {\r
774                 Wait(session->HaltEvent, session->RetryInterval);\r
775                 return true;\r
776         }\r
777 \r
778         p = NewPack();\r
779         PackAddStr(p, "function", "connecterror_dialog");\r
780         PackAddUniStr(p, "AccountName", dlg->AccountName);\r
781         PackAddStr(p, "ServerName", dlg->ServerName);\r
782         PackAddInt(p, "Err", dlg->Err);\r
783         PackAddInt(p, "CurrentRetryCount", dlg->CurrentRetryCount);\r
784         PackAddInt(p, "RetryLimit", dlg->RetryLimit);\r
785         PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);\r
786         PackAddBool(p, "HideWindow", dlg->HideWindow);\r
787 \r
788         SendPack(s, p);\r
789         FreePack(p);\r
790 \r
791         dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));\r
792         dp->Session = session;\r
793         dp->Sock = s;\r
794         dp->Event = NewEvent();\r
795 \r
796         t = NewThread(CncConnectErrorDlgHaltThread, dp);\r
797 \r
798         p = RecvPack(s);\r
799         if (p != NULL)\r
800         {\r
801                 ret = PackGetBool(p, "ok");\r
802                 dlg->HideWindow = PackGetBool(p, "HideWindow");\r
803 \r
804                 FreePack(p);\r
805         }\r
806 \r
807         dp->HaltThread = true;\r
808         Set(dp->Event);\r
809 \r
810         WaitThread(t, INFINITE);\r
811 \r
812         ReleaseEvent(dp->Event);\r
813         Free(dp);\r
814         ReleaseThread(t);\r
815 \r
816         Disconnect(s);\r
817         ReleaseSock(s);\r
818 \r
819         return ret;\r
820 }\r
821 \r
822 // ステータス表示器クライアント用スレッド\r
823 void CncStatusPrinterWindowThreadProc(THREAD *thread, void *param)\r
824 {\r
825         CNC_STATUS_PRINTER_WINDOW_PARAM *pp;\r
826         SOCK *sock;\r
827         PACK *p;\r
828         // 引数チェック\r
829         if (thread == NULL || param == NULL)\r
830         {\r
831                 return;\r
832         }\r
833 \r
834         pp = (CNC_STATUS_PRINTER_WINDOW_PARAM *)param;\r
835         sock = pp->Sock;\r
836         pp->Thread = thread;\r
837         AddRef(pp->Thread->ref);\r
838 \r
839         NoticeThreadInit(thread);\r
840 \r
841         p = RecvPack(sock);\r
842         if (p != NULL)\r
843         {\r
844                 // セッションを停止する\r
845                 StopSessionEx(pp->Session, true);\r
846 \r
847                 FreePack(p);\r
848         }\r
849 }\r
850 \r
851 // ステータス表示器クライアントの作成\r
852 SOCK *CncStatusPrinterWindowStart(SESSION *s)\r
853 {\r
854         SOCK *sock;\r
855         PACK *p;\r
856         THREAD *t;\r
857         CNC_STATUS_PRINTER_WINDOW_PARAM *param;\r
858         // 引数チェック\r
859         if (s == NULL)\r
860         {\r
861                 return NULL;\r
862         }\r
863 \r
864         sock = CncConnect();\r
865 \r
866         if (sock == NULL)\r
867         {\r
868                 return NULL;\r
869         }\r
870 \r
871         p = NewPack();\r
872         PackAddStr(p, "function", "status_printer");\r
873         PackAddUniStr(p, "account_name", s->Account->ClientOption->AccountName);\r
874 \r
875         if (SendPack(sock, p) == false)\r
876         {\r
877                 FreePack(p);\r
878                 ReleaseSock(sock);\r
879 \r
880                 return NULL;\r
881         }\r
882 \r
883         FreePack(p);\r
884 \r
885         param = ZeroMalloc(sizeof(CNC_STATUS_PRINTER_WINDOW_PARAM));\r
886         param->Sock = sock;\r
887         param->Session = s;\r
888 \r
889         sock->Param = param;\r
890 \r
891         t = NewThread(CncStatusPrinterWindowThreadProc, param);\r
892         WaitThreadInit(t);\r
893 \r
894         ReleaseThread(t);\r
895 \r
896         return sock;\r
897 }\r
898 \r
899 // ステータス表示器に対して文字列を送信\r
900 void CncStatusPrinterWindowPrint(SOCK *s, wchar_t *str)\r
901 {\r
902         CNC_STATUS_PRINTER_WINDOW_PARAM *param;\r
903         PACK *p;\r
904         // 引数チェック\r
905         if (s == NULL || str == NULL)\r
906         {\r
907                 return;\r
908         }\r
909 \r
910         param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;\r
911 \r
912         p = NewPack();\r
913         PackAddUniStr(p, "string", str);\r
914         SendPack(s, p);\r
915         FreePack(p);\r
916 }\r
917 \r
918 // ステータス表示器クライアントの停止\r
919 void CncStatusPrinterWindowStop(SOCK *s)\r
920 {\r
921         CNC_STATUS_PRINTER_WINDOW_PARAM *param;\r
922         // 引数チェック\r
923         if (s == NULL)\r
924         {\r
925                 return;\r
926         }\r
927 \r
928         param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;\r
929 \r
930         // クライアントソケット切断\r
931         Disconnect(s);\r
932 \r
933         // スレッド終了\r
934         WaitThread(param->Thread, INFINITE);\r
935         ReleaseThread(param->Thread);\r
936 \r
937         Free(param);\r
938         ReleaseSock(s);\r
939 }\r
940 \r
941 // Windows Vista 用のドライバインストーラの起動\r
942 bool CncExecDriverInstaller(char *arg)\r
943 {\r
944         SOCK *s = CncConnect();\r
945         PACK *p;\r
946         bool ret;\r
947         if (s == NULL)\r
948         {\r
949                 return false;\r
950         }\r
951 \r
952         p = NewPack();\r
953         PackAddStr(p, "function", "exec_driver_installer");\r
954         PackAddStr(p, "arg", arg);\r
955 \r
956         SendPack(s, p);\r
957         FreePack(p);\r
958 \r
959         p = RecvPack(s);\r
960         if (p == NULL)\r
961         {\r
962                 Disconnect(s);\r
963                 ReleaseSock(s);\r
964                 return false;\r
965         }\r
966 \r
967         ret = PackGetBool(p, "ret");\r
968 \r
969         FreePack(p);\r
970 \r
971         Disconnect(s);\r
972         ReleaseSock(s);\r
973 \r
974         return ret;\r
975 }\r
976 \r
977 // 現在動作しているクライアント通知サービスにソケットを解放させる\r
978 void CncReleaseSocket()\r
979 {\r
980         SOCK *s = CncConnect();\r
981         PACK *p;\r
982         if (s == NULL)\r
983         {\r
984                 return;\r
985         }\r
986 \r
987         p = NewPack();\r
988         PackAddStr(p, "function", "release_socket");\r
989 \r
990 #ifdef OS_WIN32\r
991         PackAddInt(p, "pid", MsGetProcessId());\r
992 #endif  // OS_WIN32\r
993 \r
994         SendPack(s, p);\r
995         FreePack(p);\r
996 \r
997         Disconnect(s);\r
998         ReleaseSock(s);\r
999 }\r
1000 \r
1001 // クライアント通知サービスのセッション ID の取得\r
1002 UINT CncGetSessionId()\r
1003 {\r
1004         SOCK *s = CncConnect();\r
1005         PACK *p;\r
1006         UINT ret;\r
1007         if (s == NULL)\r
1008         {\r
1009                 return INFINITE;\r
1010         }\r
1011 \r
1012         p = NewPack();\r
1013         PackAddStr(p, "function", "get_session_id");\r
1014 \r
1015         SendPack(s, p);\r
1016         FreePack(p);\r
1017 \r
1018         p = RecvPack(s);\r
1019         if (p == NULL)\r
1020         {\r
1021                 Disconnect(s);\r
1022                 ReleaseSock(s);\r
1023                 return INFINITE;\r
1024         }\r
1025 \r
1026         ret = PackGetInt(p, "session_id");\r
1027 \r
1028         FreePack(p);\r
1029 \r
1030         Disconnect(s);\r
1031         ReleaseSock(s);\r
1032 \r
1033         return ret;\r
1034 }\r
1035 \r
1036 // クライアント通知サービスのプロセスの終了\r
1037 void CncExit()\r
1038 {\r
1039         SOCK *s = CncConnectEx(256);\r
1040         PACK *p;\r
1041         if (s != NULL)\r
1042         {\r
1043                 p = NewPack();\r
1044                 PackAddStr(p, "function", "exit");\r
1045 \r
1046                 SendPack(s, p);\r
1047 \r
1048                 FreePack(p);\r
1049 \r
1050                 FreePack(RecvPack(s));\r
1051 \r
1052                 Disconnect(s);\r
1053                 ReleaseSock(s);\r
1054         }\r
1055 \r
1056 #ifdef  OS_WIN32\r
1057         MsKillOtherInstanceEx("utvpnclient");\r
1058 #endif  // OS_WIN32\r
1059 }\r
1060 \r
1061 // クライアント通知サービスへの接続\r
1062 SOCK *CncConnect()\r
1063 {\r
1064         return CncConnectEx(0);\r
1065 }\r
1066 SOCK *CncConnectEx(UINT timeout)\r
1067 {\r
1068         SOCK *s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, timeout);\r
1069 \r
1070         return s;\r
1071 }\r
1072 \r
1073 #ifdef  OS_WIN32\r
1074 \r
1075 // 証明書チェックダイアログ用スレッド\r
1076 void Win32CnCheckCertThreadProc(THREAD *thread, void *param)\r
1077 {\r
1078         UI_CHECKCERT *dlg;\r
1079         // 引数チェック\r
1080         if (thread == NULL || param == NULL)\r
1081         {\r
1082                 return;\r
1083         }\r
1084 \r
1085         dlg = (UI_CHECKCERT *)param;\r
1086 \r
1087         CheckCertDlg(dlg);\r
1088         {\r
1089                 PACK *p = NewPack();\r
1090 \r
1091                 PackAddBool(p, "Ok", dlg->Ok);\r
1092                 PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);\r
1093 \r
1094                 SendPack(dlg->Sock, p);\r
1095                 FreePack(p);\r
1096 \r
1097                 FreePack(RecvPack(dlg->Sock));\r
1098         }\r
1099 \r
1100         Disconnect(dlg->Sock);\r
1101 }\r
1102 \r
1103 // 証明書チェックダイアログ\r
1104 void Win32CnCheckCert(SOCK *s, PACK *p)\r
1105 {\r
1106         UI_CHECKCERT dlg;\r
1107         THREAD *t;\r
1108         Zero(&dlg, sizeof(dlg));\r
1109         // 引数チェック\r
1110         if (s == NULL || p == NULL)\r
1111         {\r
1112                 return;\r
1113         }\r
1114 \r
1115         PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));\r
1116         PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));\r
1117         dlg.x = PackGetX(p, "x");\r
1118         dlg.parent_x = PackGetX(p, "parent_x");\r
1119         dlg.old_x = PackGetX(p, "old_x");\r
1120         dlg.DiffWarning = PackGetBool(p, "DiffWarning");\r
1121         dlg.Ok = PackGetBool(p, "Ok");\r
1122         dlg.SaveServerCert = PackGetBool(p, "SaveServerCert");\r
1123         dlg.Sock = s;\r
1124 \r
1125         t = NewThread(Win32CnCheckCertThreadProc, &dlg);\r
1126 \r
1127         FreePack(RecvPack(s));\r
1128 \r
1129         dlg.Halt = true;\r
1130 \r
1131         WaitThread(t, INFINITE);\r
1132         ReleaseThread(t);\r
1133 \r
1134         FreeX(dlg.parent_x);\r
1135         FreeX(dlg.old_x);\r
1136         FreeX(dlg.x);\r
1137 }\r
1138 \r
1139 // メッセージ表示ダイアログスレッドプロシージャ\r
1140 void Win32CnMsgDlgThreadProc(THREAD *thread, void *param)\r
1141 {\r
1142         UI_MSG_DLG *dlg = (UI_MSG_DLG *)param;\r
1143         wchar_t tmp[MAX_SIZE];\r
1144         char url[MAX_SIZE];\r
1145         // 引数チェック\r
1146         if (thread == NULL || dlg == NULL)\r
1147         {\r
1148                 return;\r
1149         }\r
1150 \r
1151         UniFormat(tmp, sizeof(tmp), _UU("CM_MSG_TITLE"),\r
1152                 dlg->ServerName, dlg->HubName);\r
1153 \r
1154         if (IsURLMsg(dlg->Msg, url, sizeof(url)) == false)\r
1155         {\r
1156                 OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);\r
1157         }\r
1158         else\r
1159         {\r
1160                 if (MsExecute(url, NULL) == false)\r
1161                 {\r
1162                         OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);\r
1163                 }\r
1164         }\r
1165 \r
1166         Disconnect(dlg->Sock);\r
1167 }\r
1168 \r
1169 // NIC 情報ダイアログスレッドプロシージャ\r
1170 void Win32CnNicInfoThreadProc(THREAD *thread, void *param)\r
1171 {\r
1172         UI_NICINFO *info = (UI_NICINFO *)param;\r
1173         // 引数チェック\r
1174         if (thread == NULL || info == NULL)\r
1175         {\r
1176                 return;\r
1177         }\r
1178 \r
1179         if (MsIsNt())\r
1180         {\r
1181                 // Windows 9x 系ではダイアログを表示しない\r
1182                 NicInfo(info);\r
1183         }\r
1184 \r
1185         Disconnect(info->Sock);\r
1186 }\r
1187 \r
1188 // NIC 情報ダイアログ\r
1189 void Win32CnNicInfo(SOCK *s, PACK *p)\r
1190 {\r
1191         UI_NICINFO info;\r
1192         THREAD *t;\r
1193         Zero(&info, sizeof(info));\r
1194         // 引数チェック\r
1195         if (s == NULL || p == NULL)\r
1196         {\r
1197                 return;\r
1198         }\r
1199 \r
1200         PackGetStr(p, "NicName", info.NicName, sizeof(info.NicName));\r
1201         PackGetUniStr(p, "AccountName", info.AccountName, sizeof(info.AccountName));\r
1202 \r
1203         info.Sock = s;\r
1204 \r
1205         t = NewThread(Win32CnNicInfoThreadProc, &info);\r
1206 \r
1207         FreePack(RecvPack(s));\r
1208 \r
1209         info.Halt = true;\r
1210 \r
1211         WaitThread(t, INFINITE);\r
1212         ReleaseThread(t);\r
1213 }\r
1214 \r
1215 // メッセージ表示ダイアログ\r
1216 void Win32CnMsgDlg(SOCK *s, PACK *p)\r
1217 {\r
1218         UI_MSG_DLG dlg;\r
1219         THREAD *t;\r
1220         UINT utf_size;\r
1221         char *utf;\r
1222         wchar_t *msg;\r
1223         Zero(&dlg, sizeof(dlg));\r
1224         // 引数チェック\r
1225         if (s == NULL || p == NULL)\r
1226         {\r
1227                 return;\r
1228         }\r
1229 \r
1230         PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));\r
1231         PackGetStr(p, "HubName", dlg.HubName, sizeof(dlg.HubName));\r
1232 \r
1233         utf_size = PackGetDataSize(p, "Msg");\r
1234         utf = ZeroMalloc(utf_size + 8);\r
1235 \r
1236         PackGetData(p, "Msg", utf);\r
1237 \r
1238         msg = CopyUtfToUni(utf);\r
1239         Free(utf);\r
1240 \r
1241         dlg.Sock = s;\r
1242         dlg.Msg = msg;\r
1243 \r
1244         t = NewThread(Win32CnMsgDlgThreadProc, &dlg);\r
1245 \r
1246         FreePack(RecvPack(s));\r
1247 \r
1248         dlg.Halt = true;\r
1249 \r
1250         WaitThread(t, INFINITE);\r
1251         ReleaseThread(t);\r
1252 \r
1253         Free(msg);\r
1254 }\r
1255 \r
1256 // パスワード入力ダイアログ用スレッド\r
1257 void Win32CnPasswordDlgThreadProc(THREAD *thread, void *param)\r
1258 {\r
1259         UI_PASSWORD_DLG *dlg;\r
1260         // 引数チェック\r
1261         if (thread == NULL || param == NULL)\r
1262         {\r
1263                 return;\r
1264         }\r
1265 \r
1266         dlg = (UI_PASSWORD_DLG *)param;\r
1267 \r
1268         if (PasswordDlg(NULL, dlg))\r
1269         {\r
1270                 PACK *p = NewPack();\r
1271 \r
1272                 PackAddBool(p, "ok", true);\r
1273                 PackAddStr(p, "Username", dlg->Username);\r
1274                 PackAddStr(p, "Password", dlg->Password);\r
1275                 PackAddInt(p, "Type", dlg->Type);\r
1276                 PackAddBool(p, "ProxyServer", dlg->ProxyServer);\r
1277                 PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);\r
1278 \r
1279                 SendPack(dlg->Sock, p);\r
1280                 FreePack(p);\r
1281 \r
1282                 FreePack(RecvPack(dlg->Sock));\r
1283         }\r
1284 \r
1285         Disconnect(dlg->Sock);\r
1286 }\r
1287 \r
1288 // パスワード入力ダイアログ\r
1289 void Win32CnPasswordDlg(SOCK *s, PACK *p)\r
1290 {\r
1291         UI_PASSWORD_DLG dlg;\r
1292         THREAD *t = NULL;\r
1293         Zero(&dlg, sizeof(dlg));\r
1294         // 引数チェック\r
1295         if (s == NULL || p == NULL)\r
1296         {\r
1297                 return;\r
1298         }\r
1299 \r
1300         dlg.Type = PackGetInt(p, "Type");\r
1301         PackGetStr(p, "Username", dlg.Username, sizeof(dlg.Username));\r
1302         PackGetStr(p, "Password", dlg.Password, sizeof(dlg.Password));\r
1303         PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));\r
1304         dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");\r
1305         dlg.ProxyServer = PackGetBool(p, "ProxyServer");\r
1306         dlg.AdminMode = PackGetBool(p, "AdminMode");\r
1307         dlg.ShowNoSavePassword = PackGetBool(p, "ShowNoSavePassword");\r
1308         dlg.NoSavePassword = PackGetBool(p, "NoSavePassword");\r
1309         dlg.CancelEvent = NewEvent();\r
1310         dlg.Sock = s;\r
1311 \r
1312         t = NewThread(Win32CnPasswordDlgThreadProc, &dlg);\r
1313 \r
1314         FreePack(RecvPack(s));\r
1315 \r
1316         Set(dlg.CancelEvent);\r
1317 \r
1318         WaitThread(t, INFINITE);\r
1319         ReleaseEvent(dlg.CancelEvent);\r
1320         ReleaseThread(t);\r
1321 }\r
1322 \r
1323 // 接続エラーダイアログ用スレッド\r
1324 void Win32CnConnectErrorDlgThreadProc(THREAD *thread, void *param)\r
1325 {\r
1326         UI_CONNECTERROR_DLG *dlg;\r
1327         // 引数チェック\r
1328         if (thread == NULL || param == NULL)\r
1329         {\r
1330                 return;\r
1331         }\r
1332 \r
1333         dlg = (UI_CONNECTERROR_DLG *)param;\r
1334 \r
1335         if (ConnectErrorDlg(dlg))\r
1336         {\r
1337                 PACK *p = NewPack();\r
1338 \r
1339                 PackAddBool(p, "ok", true);\r
1340                 PackAddBool(p, "HideWindow", dlg->HideWindow);\r
1341 \r
1342                 SendPack(dlg->Sock, p);\r
1343                 FreePack(p);\r
1344 \r
1345                 FreePack(RecvPack(dlg->Sock));\r
1346         }\r
1347 \r
1348         Disconnect(dlg->Sock);\r
1349 }\r
1350 \r
1351 // 接続エラーダイアログ (Win32)\r
1352 void Win32CnConnectErrorDlg(SOCK *s, PACK *p)\r
1353 {\r
1354         UI_CONNECTERROR_DLG dlg;\r
1355         THREAD *t;\r
1356         Zero(&dlg, sizeof(dlg));\r
1357         // 引数チェック\r
1358         if (s == NULL || p == NULL)\r
1359         {\r
1360                 return;\r
1361         }\r
1362 \r
1363         PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));\r
1364         PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));\r
1365         dlg.Err = PackGetInt(p, "Err");\r
1366         dlg.CurrentRetryCount = PackGetInt(p, "CurrentRetryCount");\r
1367         dlg.RetryLimit = PackGetInt(p, "RetryLimit");\r
1368         dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");\r
1369         dlg.HideWindow = PackGetBool(p, "HideWindow");\r
1370         dlg.CancelEvent = NewEvent();\r
1371         dlg.Sock = s;\r
1372 \r
1373         t = NewThread(Win32CnConnectErrorDlgThreadProc, &dlg);\r
1374 \r
1375         FreePack(RecvPack(s));\r
1376 \r
1377         Set(dlg.CancelEvent);\r
1378 \r
1379         WaitThread(t, INFINITE);\r
1380         ReleaseEvent(dlg.CancelEvent);\r
1381         ReleaseThread(t);\r
1382 }\r
1383 \r
1384 // ステータス表示器 (Win32)\r
1385 void Win32CnStatusPrinter(SOCK *s, PACK *p)\r
1386 {\r
1387         STATUS_WINDOW *w;\r
1388         wchar_t account_name[MAX_ACCOUNT_NAME_LEN + 1];\r
1389         // 引数チェック\r
1390         if (s == NULL || p == NULL)\r
1391         {\r
1392                 return;\r
1393         }\r
1394 \r
1395         PackGetUniStr(p, "account_name", account_name, sizeof(account_name));\r
1396 \r
1397         w = StatusPrinterWindowStart(s, account_name);\r
1398 \r
1399         while (true)\r
1400         {\r
1401                 PACK *p = RecvPack(s);\r
1402 \r
1403                 if (p == NULL)\r
1404                 {\r
1405                         // 切断されたのでダイアログを終了する\r
1406                         break;\r
1407                 }\r
1408                 else\r
1409                 {\r
1410                         wchar_t tmp[MAX_SIZE];\r
1411 \r
1412                         // 文字列を書き換える\r
1413                         PackGetUniStr(p, "string", tmp, sizeof(tmp));\r
1414 \r
1415                         StatusPrinterWindowPrint(w, tmp);\r
1416 \r
1417                         FreePack(p);\r
1418                 }\r
1419         }\r
1420 \r
1421         StatusPrinterWindowStop(w);\r
1422 }\r
1423 \r
1424 // ドライバインストーラの起動 (Windows Vista 用)\r
1425 void Win32CnExecDriverInstaller(SOCK *s, PACK *p)\r
1426 {\r
1427         char arg[MAX_SIZE];\r
1428         bool ret;\r
1429         void *helper = NULL;\r
1430         // 引数チェック\r
1431         if (s == NULL || p == NULL)\r
1432         {\r
1433                 return;\r
1434         }\r
1435 \r
1436         if (PackGetStr(p, "arg", arg, sizeof(arg)) == false)\r
1437         {\r
1438                 return;\r
1439         }\r
1440 \r
1441         if (MsIsVista())\r
1442         {\r
1443                 helper = CmStartUacHelper();\r
1444         }\r
1445 \r
1446         ret = MsExecDriverInstaller(arg);\r
1447 \r
1448         CmStopUacHelper(helper);\r
1449 \r
1450         p = NewPack();\r
1451         PackAddBool(p, "ret", ret);\r
1452         SendPack(s, p);\r
1453 \r
1454         FreePack(p);\r
1455 }\r
1456 \r
1457 #endif  // OS_WIN32\r
1458 \r
1459 // ドライバインストーラの起動\r
1460 void CnExecDriverInstaller(SOCK *s, PACK *p)\r
1461 {\r
1462         // 引数チェック\r
1463         if (s == NULL || p == NULL)\r
1464         {\r
1465                 return;\r
1466         }\r
1467 \r
1468 #ifdef  OS_WIN32\r
1469         Win32CnExecDriverInstaller(s, p);\r
1470 #endif  // OS_WIN32\r
1471 }\r
1472 \r
1473 // 証明書確認ダイアログ\r
1474 void CnCheckCert(SOCK *s, PACK *p)\r
1475 {\r
1476         // 引数チェック\r
1477         if (s == NULL || p == NULL)\r
1478         {\r
1479                 return;\r
1480         }\r
1481 \r
1482 #ifdef  OS_WIN32\r
1483         Win32CnCheckCert(s, p);\r
1484 #endif  // OS_WIN32\r
1485 }\r
1486 \r
1487 // NIC 情報ダイアログ\r
1488 void CnNicInfo(SOCK *s, PACK *p)\r
1489 {\r
1490         // 引数チェック\r
1491         if (s == NULL || p == NULL)\r
1492         {\r
1493                 return;\r
1494         }\r
1495 \r
1496 #ifdef  OS_WIN32\r
1497         Win32CnNicInfo(s, p);\r
1498 #endif  // OS_WIN32\r
1499 }\r
1500 \r
1501 // メッセージ表示ダイアログ\r
1502 void CnMsgDlg(SOCK *s, PACK *p)\r
1503 {\r
1504         // 引数チェック\r
1505         if (s == NULL || p == NULL)\r
1506         {\r
1507                 return;\r
1508         }\r
1509 \r
1510 #ifdef  OS_WIN32\r
1511         Win32CnMsgDlg(s, p);\r
1512 #endif  // OS_WIN32\r
1513 }\r
1514 \r
1515 // パスワード入力ダイアログ\r
1516 void CnPasswordDlg(SOCK *s, PACK *p)\r
1517 {\r
1518         // 引数チェック\r
1519         if (s == NULL || p == NULL)\r
1520         {\r
1521                 return;\r
1522         }\r
1523 \r
1524 #ifdef  OS_WIN32\r
1525         Win32CnPasswordDlg(s, p);\r
1526 #endif  // OS_WIN32\r
1527 }\r
1528 \r
1529 // 接続エラーダイアログ\r
1530 void CnConnectErrorDlg(SOCK *s, PACK *p)\r
1531 {\r
1532         // 引数チェック\r
1533         if (s == NULL || p == NULL)\r
1534         {\r
1535                 return;\r
1536         }\r
1537 \r
1538 #ifdef  OS_WIN32\r
1539         Win32CnConnectErrorDlg(s, p);\r
1540 #endif  // OS_WIN32\r
1541 }\r
1542 \r
1543 // ステータス表示器\r
1544 void CnStatusPrinter(SOCK *s, PACK *p)\r
1545 {\r
1546         // 引数チェック\r
1547         if (s == NULL || p == NULL)\r
1548         {\r
1549                 return;\r
1550         }\r
1551 \r
1552 #ifdef  OS_WIN32\r
1553         Win32CnStatusPrinter(s, p);\r
1554 #endif  // OS_WIN32\r
1555 }\r
1556 \r
1557 // クライアント通知サービスリスナースレッド\r
1558 // このあたりは急いで実装したのでコードがあまり美しくない。\r
1559 void CnListenerProc(THREAD *thread, void *param)\r
1560 {\r
1561         TCP_ACCEPTED_PARAM *data = (TCP_ACCEPTED_PARAM *)param;\r
1562         SOCK *s;\r
1563         PACK *p;\r
1564         // 引数チェック\r
1565         if (data == NULL || thread == NULL)\r
1566         {\r
1567                 return;\r
1568         }\r
1569 \r
1570         s = data->s;\r
1571         AddRef(s->ref);\r
1572         NoticeThreadInit(thread);\r
1573 \r
1574         if (s->LocalIP.addr[0] == 127)\r
1575         {\r
1576                 p = RecvPack(s);\r
1577 \r
1578                 if (p != NULL)\r
1579                 {\r
1580                         char function[MAX_SIZE];\r
1581 \r
1582                         if (PackGetStr(p, "function", function, sizeof(function)))\r
1583                         {\r
1584                                 if (StrCmpi(function, "status_printer") == 0)\r
1585                                 {\r
1586                                         CnStatusPrinter(s, p);\r
1587                                 }\r
1588                                 else if (StrCmpi(function, "connecterror_dialog") == 0)\r
1589                                 {\r
1590                                         CnConnectErrorDlg(s, p);\r
1591                                 }\r
1592                                 else if (StrCmpi(function, "msg_dialog") == 0)\r
1593                                 {\r
1594                                         CnMsgDlg(s, p);\r
1595                                 }\r
1596                                 else if (StrCmpi(function, "nicinfo") == 0)\r
1597                                 {\r
1598                                         CnNicInfo(s, p);\r
1599                                 }\r
1600                                 else if (StrCmpi(function, "password_dialog") == 0)\r
1601                                 {\r
1602                                         CnPasswordDlg(s, p);\r
1603                                 }\r
1604                                 else if (StrCmpi(function, "secure_sign") == 0)\r
1605                                 {\r
1606                                         CnSecureSign(s, p);\r
1607                                 }\r
1608                                 else if (StrCmpi(function, "check_cert") == 0)\r
1609                                 {\r
1610                                         CnCheckCert(s, p);\r
1611                                 }\r
1612                                 else if (StrCmpi(function, "exit") == 0)\r
1613                                 {\r
1614 #ifdef  OS_WIN32\r
1615                                         MsTerminateProcess();\r
1616 #else   // OS_WIN32\r
1617                                         _exit(0);\r
1618 #endif  // OS_WIN32\r
1619                                 }\r
1620                                 else if (StrCmpi(function, "get_session_id") == 0)\r
1621                                 {\r
1622                                         PACK *p = NewPack();\r
1623 #ifdef  OS_WIN32\r
1624                                         PackAddInt(p, "session_id", MsGetCurrentTerminalSessionId());\r
1625 #endif  // OS_WIN32\r
1626                                         SendPack(s, p);\r
1627                                         FreePack(p);\r
1628                                 }\r
1629                                 else if (StrCmpi(function, "exec_driver_installer") == 0)\r
1630                                 {\r
1631                                         CnExecDriverInstaller(s, p);\r
1632                                 }\r
1633                                 else if (StrCmpi(function, "release_socket") == 0)\r
1634                                 {\r
1635                                         // リスナーを停止する\r
1636                                         CnReleaseSocket(s, p);\r
1637                                 }\r
1638                         }\r
1639 \r
1640                         FreePack(p);\r
1641                 }\r
1642         }\r
1643 \r
1644         Disconnect(s);\r
1645         ReleaseSock(s);\r
1646 }\r
1647 \r
1648 // Secure Sign を行う\r
1649 void CnSecureSign(SOCK *s, PACK *p)\r
1650 {\r
1651         SECURE_SIGN sign;\r
1652         bool ret = false;\r
1653         // 引数チェック\r
1654         if (s == NULL || p == NULL)\r
1655         {\r
1656                 return;\r
1657         }\r
1658 \r
1659         Zero(&sign, sizeof(sign));\r
1660         InRpcSecureSign(&sign, p);\r
1661 \r
1662 #ifdef  OS_WIN32\r
1663         // Win32: ダイアログを表示\r
1664         ret = Win32CiSecureSign(&sign);\r
1665 #else   // OS_WIN32\r
1666         // UNIX: 未実装\r
1667         ret = false;\r
1668 #endif  // OS_WIN32\r
1669 \r
1670         p = NewPack();\r
1671 \r
1672         OutRpcSecureSign(p, &sign);\r
1673         FreeRpcSecureSign(&sign);\r
1674 \r
1675         PackAddBool(p, "ret", ret);\r
1676 \r
1677         SendPack(s, p);\r
1678         FreePack(p);\r
1679 }\r
1680 \r
1681 // リスナーを停止する\r
1682 void CnReleaseSocket(SOCK *s, PACK *p)\r
1683 {\r
1684         UINT pid = 0;\r
1685         UINT current_pid = 0;\r
1686         // 引数チェック\r
1687         if (s == NULL || p == NULL)\r
1688         {\r
1689                 return;\r
1690         }\r
1691 \r
1692         pid = PackGetInt(p, "pid");\r
1693 \r
1694 #ifdef  OS_WIN32\r
1695         current_pid = MsGetProcessId();\r
1696 #endif  // OS_WIN32\r
1697 \r
1698         if (current_pid == pid)\r
1699         {\r
1700                 return;\r
1701         }\r
1702 \r
1703         Lock(cn_listener_lock);\r
1704         {\r
1705                 if (cn_listener != NULL)\r
1706                 {\r
1707                         if (cn_listener->Halt == false)\r
1708                         {\r
1709                                 StopListener(cn_listener);\r
1710 \r
1711                                 cn_next_allow = Tick64() + (6 * 1000);\r
1712                         }\r
1713                 }\r
1714         }\r
1715         Unlock(cn_listener_lock);\r
1716 }\r
1717 \r
1718 // クライアント通知サービスの開始\r
1719 void CnStart()\r
1720 {\r
1721         CEDAR *cedar;\r
1722         LISTENER *o;\r
1723         UINT last_cursor_hash = 0;\r
1724         bool last_session_active = false;\r
1725 \r
1726         cn_next_allow = 0;\r
1727         cn_listener_lock = NewLock();\r
1728 \r
1729 #ifdef  OS_WIN32\r
1730         MsSetShutdownParameters(0xff, 0x00000001);\r
1731         InitWinUi(_UU("CN_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));\r
1732 #endif  // OS_WIN32\r
1733 \r
1734         cedar = NewCedar(NULL, NULL);\r
1735 \r
1736         if (CnCheckAlreadyExists(true))\r
1737         {\r
1738                 // すでに起動している\r
1739                 ReleaseCedar(cedar);\r
1740 #ifdef  OS_WIN32\r
1741                 FreeWinUi();\r
1742 #endif  // OS_WIN32\r
1743                 return;\r
1744         }\r
1745 \r
1746 #ifdef  OS_WIN32\r
1747         MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY,\r
1748                 "NotifyServerProcessId", MsGetProcessId());\r
1749 #endif  // OS_WIN32\r
1750 \r
1751 BEGIN_LISTENER:\r
1752         Lock(cn_listener_lock);\r
1753         cn_listener = o = NewListenerEx(cedar, LISTENER_TCP, CLIENT_NOTIFY_PORT, CnListenerProc, NULL);\r
1754         Unlock(cn_listener_lock);\r
1755 \r
1756         while (true)\r
1757         {\r
1758                 UINT current_cursor_hash = 0;\r
1759                 bool cursor_changed = false;\r
1760 \r
1761 #ifdef  OS_WIN32\r
1762                 // 現在のカーソル位置を取得\r
1763                 current_cursor_hash = MsGetCursorPosHash();\r
1764 #endif  // OS_WIN32\r
1765 \r
1766                 if (last_cursor_hash != current_cursor_hash)\r
1767                 {\r
1768                         // カーソル位置をチェック\r
1769                         cursor_changed = true;\r
1770                         last_cursor_hash = current_cursor_hash;\r
1771                 }\r
1772 \r
1773                 Lock(cn_listener_lock);\r
1774 \r
1775                 // リスナーが開始した後一定間隔で状態をチェックする\r
1776                 if (cn_listener->Status == LISTENER_STATUS_TRYING || cn_listener->Halt)\r
1777                 {\r
1778                         bool session_active = false;\r
1779 #ifdef  OS_WIN32\r
1780                         session_active = MsIsCurrentTerminalSessionActive();\r
1781                         if (cursor_changed)\r
1782                         {\r
1783                                 // カーソル位置が変化してもターミナルセッションがアクティブでない\r
1784                                 // 場合は変化していないものと見なす\r
1785                                 if (session_active == false)\r
1786                                 {\r
1787                                         cursor_changed = false;\r
1788                                 }\r
1789                         }\r
1790                         if (last_session_active != session_active)\r
1791                         {\r
1792                                 // カーソルが変化していなくてもターミナルセッション\r
1793                                 // 前回と比較してアクティブになった場合はカーソルが変化した\r
1794                                 // ものとみなす\r
1795                                 last_session_active = session_active;\r
1796 \r
1797                                 if (session_active)\r
1798                                 {\r
1799                                         cursor_changed = true;\r
1800                                 }\r
1801                         }\r
1802 #endif  // OS_WIN32\r
1803 \r
1804                         // ポートが開けない場合\r
1805                         if (cn_next_allow <= Tick64())\r
1806                         {\r
1807                                 if (cursor_changed || cn_listener->Halt)\r
1808                                 {\r
1809                                         if (cursor_changed)\r
1810                                         {\r
1811                                                 // マウスカーソルが移動しているので自分がポートを開く権利を持っている\r
1812                                                 // と判断できる。\r
1813                                                 // そこで、他のプロセスが持っているポートを強制的に奪う。\r
1814                                                 CncReleaseSocket();\r
1815                                         }\r
1816 \r
1817                                         if (cn_listener->Halt)\r
1818                                         {\r
1819                                                 ReleaseListener(cn_listener);\r
1820                                                 cn_listener = NULL;\r
1821 \r
1822                                                 Unlock(cn_listener_lock);\r
1823                                                 goto BEGIN_LISTENER;\r
1824                                         }\r
1825                                 }\r
1826                         }\r
1827                 }\r
1828 \r
1829                 Unlock(cn_listener_lock);\r
1830 \r
1831                 SleepThread(1000);\r
1832         }\r
1833 }\r
1834 \r
1835 // バッファからアカウント情報を読み込む\r
1836 RPC_CLIENT_CREATE_ACCOUNT *CiCfgToAccount(BUF *b)\r
1837 {\r
1838         RPC_CLIENT_CREATE_ACCOUNT *t;\r
1839         FOLDER *f;\r
1840         ACCOUNT *a;\r
1841         // 引数チェック\r
1842         if (b == NULL)\r
1843         {\r
1844                 return NULL;\r
1845         }\r
1846 \r
1847         f = CfgBufTextToFolder(b);\r
1848         if (f == NULL)\r
1849         {\r
1850                 return NULL;\r
1851         }\r
1852 \r
1853         a = CiLoadClientAccount(f);\r
1854 \r
1855         CfgDeleteFolder(f);\r
1856 \r
1857         if (a == NULL)\r
1858         {\r
1859                 return NULL;\r
1860         }\r
1861 \r
1862         DeleteLock(a->lock);\r
1863 \r
1864         t = ZeroMalloc(sizeof(RPC_CLIENT_CREATE_ACCOUNT));\r
1865         t->ClientOption = a->ClientOption;\r
1866         t->ClientAuth = a->ClientAuth;\r
1867         t->StartupAccount = a->StartupAccount;\r
1868         t->CheckServerCert = a->CheckServerCert;\r
1869         t->ServerCert = a->ServerCert;\r
1870         Free(a);\r
1871 \r
1872         return t;\r
1873 }\r
1874 \r
1875 // アカウント情報をバッファに書き出す\r
1876 BUF *CiAccountToCfg(RPC_CLIENT_CREATE_ACCOUNT *t)\r
1877 {\r
1878         BUF *b;\r
1879         FOLDER *root;\r
1880         ACCOUNT a;\r
1881         // 引数チェック\r
1882         if (t == NULL)\r
1883         {\r
1884                 return NULL;\r
1885         }\r
1886 \r
1887         root = CfgCreateFolder(NULL, TAG_ROOT);\r
1888         Zero(&a, sizeof(a));\r
1889         a.ClientOption = t->ClientOption;\r
1890         a.ClientAuth = t->ClientAuth;\r
1891         a.CheckServerCert = t->CheckServerCert;\r
1892         a.ServerCert = t->ServerCert;\r
1893         a.StartupAccount = t->StartupAccount;\r
1894 \r
1895         CiWriteAccountData(root, &a);\r
1896 \r
1897         b = CfgFolderToBufEx(root, true, true);\r
1898         CfgDeleteFolder(root);\r
1899 \r
1900         return b;\r
1901 }\r
1902 \r
1903 // RPC ディスパッチルーチン\r
1904 PACK *CiRpcDispatch(RPC *rpc, char *name, PACK *p)\r
1905 {\r
1906         CLIENT *c = rpc->Param;\r
1907         PACK *ret;\r
1908         // 引数チェック\r
1909         if (rpc == NULL || name == NULL || p == NULL)\r
1910         {\r
1911                 return NULL;\r
1912         }\r
1913 \r
1914         ret = NewPack();\r
1915 \r
1916         if (StrCmpi(name, "GetClientVersion") == 0)\r
1917         {\r
1918                 RPC_CLIENT_VERSION a;\r
1919                 if (CtGetClientVersion(c, &a) == false)\r
1920                 {\r
1921                         RpcError(ret, c->Err);\r
1922                 }\r
1923                 else\r
1924                 {\r
1925                         OutRpcClientVersion(ret, &a);\r
1926                 }\r
1927         }\r
1928         else if (StrCmpi(name, "GetCmSetting") == 0)\r
1929         {\r
1930                 CM_SETTING a;\r
1931                 if (CtGetCmSetting(c, &a) == false)\r
1932                 {\r
1933                         RpcError(ret, c->Err);\r
1934                 }\r
1935                 else\r
1936                 {\r
1937                         OutRpcCmSetting(ret, &a);\r
1938                 }\r
1939         }\r
1940         else if (StrCmpi(name, "SetCmSetting") == 0)\r
1941         {\r
1942                 CM_SETTING a;\r
1943                 Zero(&a, sizeof(a));\r
1944                 InRpcCmSetting(&a, p);\r
1945                 if (CtSetCmSetting(c, &a) == false)\r
1946                 {\r
1947                         RpcError(ret, c->Err);\r
1948                 }\r
1949         }\r
1950         else if (StrCmpi(name, "SetPassword") == 0)\r
1951         {\r
1952                 RPC_CLIENT_PASSWORD a;\r
1953                 InRpcClientPassword(&a, p);\r
1954                 if (CtSetPassword(c, &a) == false)\r
1955                 {\r
1956                         RpcError(ret, c->Err);\r
1957                 }\r
1958         }\r
1959         else if (StrCmpi(name, "GetPasswordSetting") == 0)\r
1960         {\r
1961                 RPC_CLIENT_PASSWORD_SETTING a;\r
1962                 if (CtGetPasswordSetting(c, &a) == false)\r
1963                 {\r
1964                         RpcError(ret, c->Err);\r
1965                 }\r
1966                 else\r
1967                 {\r
1968                         OutRpcClientPasswordSetting(ret, &a);\r
1969                 }\r
1970         }\r
1971         else if (StrCmpi(name, "EnumCa") == 0)\r
1972         {\r
1973                 RPC_CLIENT_ENUM_CA a;\r
1974                 if (CtEnumCa(c, &a) == false)\r
1975                 {\r
1976                         RpcError(ret, c->Err);\r
1977                 }\r
1978                 else\r
1979                 {\r
1980                         OutRpcClientEnumCa(ret, &a);\r
1981                         CiFreeClientEnumCa(&a);\r
1982                 }\r
1983         }\r
1984         else if (StrCmpi(name, "AddCa") == 0)\r
1985         {\r
1986                 RPC_CERT a;\r
1987                 InRpcCert(&a, p);\r
1988                 if (CtAddCa(c, &a) == false)\r
1989                 {\r
1990                         RpcError(ret, c->Err);\r
1991                 }\r
1992                 FreeX(a.x);\r
1993         }\r
1994         else if (StrCmpi(name, "DeleteCa") == 0)\r
1995         {\r
1996                 RPC_CLIENT_DELETE_CA a;\r
1997                 InRpcClientDeleteCa(&a, p);\r
1998                 if (CtDeleteCa(c, &a) == false)\r
1999                 {\r
2000                         RpcError(ret, c->Err);\r
2001                 }\r
2002         }\r
2003         else if (StrCmpi(name, "GetCa") == 0)\r
2004         {\r
2005                 RPC_GET_CA a;\r
2006                 InRpcGetCa(&a, p);\r
2007                 if (CtGetCa(c, &a) == false)\r
2008                 {\r
2009                         RpcError(ret, c->Err);\r
2010                 }\r
2011                 else\r
2012                 {\r
2013                         OutRpcGetCa(ret, &a);\r
2014                 }\r
2015                 CiFreeGetCa(&a);\r
2016         }\r
2017         else if (StrCmpi(name, "EnumSecure") == 0)\r
2018         {\r
2019                 RPC_CLIENT_ENUM_SECURE a;\r
2020                 if (CtEnumSecure(c, &a) == false)\r
2021                 {\r
2022                         RpcError(ret, c->Err);\r
2023                 }\r
2024                 else\r
2025                 {\r
2026                         OutRpcClientEnumSecure(ret, &a);\r
2027                         CiFreeClientEnumSecure(&a);\r
2028                 }\r
2029         }\r
2030         else if (StrCmpi(name, "UseSecure") == 0)\r
2031         {\r
2032                 RPC_USE_SECURE a;\r
2033                 InRpcUseSecure(&a, p);\r
2034                 if (CtUseSecure(c, &a) == false)\r
2035                 {\r
2036                         RpcError(ret, c->Err);\r
2037                 }\r
2038         }\r
2039         else if (StrCmpi(name, "GetUseSecure") == 0)\r
2040         {\r
2041                 RPC_USE_SECURE a;\r
2042                 Zero(&a, sizeof(a));\r
2043                 if (CtGetUseSecure(c, &a) == false)\r
2044                 {\r
2045                         RpcError(ret, c->Err);\r
2046                 }\r
2047                 else\r
2048                 {\r
2049                         OutRpcUseSecure(ret, &a);\r
2050                 }\r
2051         }\r
2052         else if (StrCmpi(name, "EnumObjectInSecure") == 0)\r
2053         {\r
2054                 RPC_ENUM_OBJECT_IN_SECURE a;\r
2055                 if (CtEnumObjectInSecure(c, &a) == false)\r
2056                 {\r
2057                         RpcError(ret, c->Err);\r
2058                 }\r
2059                 else\r
2060                 {\r
2061                         OutRpcEnumObjectInSecure(ret, &a);\r
2062                         CiFreeEnumObjectInSecure(&a);\r
2063                 }\r
2064         }\r
2065         else if (StrCmpi(name, "CreateVLan") == 0)\r
2066         {\r
2067                 RPC_CLIENT_CREATE_VLAN a;\r
2068                 InRpcCreateVLan(&a, p);\r
2069                 if (CtCreateVLan(c, &a) == false)\r
2070                 {\r
2071                         RpcError(ret, c->Err);\r
2072                 }\r
2073         }\r
2074         else if (StrCmpi(name, "UpgradeVLan") == 0)\r
2075         {\r
2076                 RPC_CLIENT_CREATE_VLAN a;\r
2077                 InRpcCreateVLan(&a, p);\r
2078                 if (CtUpgradeVLan(c, &a) == false)\r
2079                 {\r
2080                         RpcError(ret, c->Err);\r
2081                 }\r
2082         }\r
2083         else if (StrCmpi(name, "GetVLan") == 0)\r
2084         {\r
2085                 RPC_CLIENT_GET_VLAN a;\r
2086                 InRpcClientGetVLan(&a, p);\r
2087                 if (CtGetVLan(c, &a) == false)\r
2088                 {\r
2089                         RpcError(ret, c->Err);\r
2090                 }\r
2091                 else\r
2092                 {\r
2093                         OutRpcClientGetVLan(ret, &a);\r
2094                 }\r
2095         }\r
2096         else if (StrCmpi(name, "SetVLan") == 0)\r
2097         {\r
2098                 RPC_CLIENT_SET_VLAN a;\r
2099                 InRpcClientSetVLan(&a, p);\r
2100                 if (CtSetVLan(c, &a) == false)\r
2101                 {\r
2102                         RpcError(ret, c->Err);\r
2103                 }\r
2104         }\r
2105         else if (StrCmpi(name, "EnumVLan") == 0)\r
2106         {\r
2107                 RPC_CLIENT_ENUM_VLAN a;\r
2108                 if (CtEnumVLan(c, &a) == false)\r
2109                 {\r
2110                         RpcError(ret, c->Err);\r
2111                 }\r
2112                 else\r
2113                 {\r
2114                         OutRpcClientEnumVLan(ret, &a);\r
2115                         CiFreeClientEnumVLan(&a);\r
2116                 }\r
2117         }\r
2118         else if (StrCmpi(name, "DeleteVLan") == 0)\r
2119         {\r
2120                 RPC_CLIENT_CREATE_VLAN a;\r
2121                 InRpcCreateVLan(&a, p);\r
2122                 if (CtDeleteVLan(c, &a) == false)\r
2123                 {\r
2124                         RpcError(ret, c->Err);\r
2125                 }\r
2126         }\r
2127         else if (StrCmpi(name, "EnableVLan") == 0)\r
2128         {\r
2129                 RPC_CLIENT_CREATE_VLAN a;\r
2130                 InRpcCreateVLan(&a, p);\r
2131                 if (CtEnableVLan(c, &a) == false)\r
2132                 {\r
2133                         RpcError(ret, c->Err);\r
2134                 }\r
2135         }\r
2136         else if (StrCmpi(name, "DisableVLan") == 0)\r
2137         {\r
2138                 RPC_CLIENT_CREATE_VLAN a;\r
2139                 InRpcCreateVLan(&a, p);\r
2140                 if (CtDisableVLan(c, &a) == false)\r
2141                 {\r
2142                         RpcError(ret, c->Err);\r
2143                 }\r
2144         }\r
2145         else if (StrCmpi(name, "CreateAccount") == 0)\r
2146         {\r
2147                 RPC_CLIENT_CREATE_ACCOUNT a;\r
2148                 InRpcClientCreateAccount(&a, p);\r
2149                 if (CtCreateAccount(c, &a) == false)\r
2150                 {\r
2151                         RpcError(ret, c->Err);\r
2152                 }\r
2153                 CiFreeClientCreateAccount(&a);\r
2154         }\r
2155         else if (StrCmpi(name, "EnumAccount") == 0)\r
2156         {\r
2157                 RPC_CLIENT_ENUM_ACCOUNT a;\r
2158                 if (CtEnumAccount(c, &a) == false)\r
2159                 {\r
2160                         RpcError(ret, c->Err);\r
2161                 }\r
2162                 else\r
2163                 {\r
2164                         OutRpcClientEnumAccount(ret, &a);\r
2165                         CiFreeClientEnumAccount(&a);\r
2166                 }\r
2167         }\r
2168         else if (StrCmpi(name, "DeleteAccount") == 0)\r
2169         {\r
2170                 RPC_CLIENT_DELETE_ACCOUNT a;\r
2171                 InRpcClientDeleteAccount(&a, p);\r
2172                 if (CtDeleteAccount(c, &a) == false)\r
2173                 {\r
2174                         RpcError(ret, c->Err);\r
2175                 }\r
2176         }\r
2177         else if (StrCmpi(name, "SetStartupAccount") == 0)\r
2178         {\r
2179                 RPC_CLIENT_DELETE_ACCOUNT a;\r
2180                 InRpcClientDeleteAccount(&a, p);\r
2181                 if (CtSetStartupAccount(c, &a) == false)\r
2182                 {\r
2183                         RpcError(ret, c->Err);\r
2184                 }\r
2185         }\r
2186         else if (StrCmpi(name, "RemoveStartupAccount") == 0)\r
2187         {\r
2188                 RPC_CLIENT_DELETE_ACCOUNT a;\r
2189                 InRpcClientDeleteAccount(&a, p);\r
2190                 if (CtRemoveStartupAccount(c, &a) == false)\r
2191                 {\r
2192                         RpcError(ret, c->Err);\r
2193                 }\r
2194         }\r
2195         else if (StrCmpi(name, "GetIssuer") == 0)\r
2196         {\r
2197                 RPC_GET_ISSUER a;\r
2198                 InRpcGetIssuer(&a, p);\r
2199                 if (CtGetIssuer(c, &a))\r
2200                 {\r
2201                         OutRpcGetIssuer(ret, &a);\r
2202                 }\r
2203                 else\r
2204                 {\r
2205                         RpcError(ret, c->Err);\r
2206                 }\r
2207                 CiFreeGetIssuer(&a);\r
2208         }\r
2209         else if (StrCmpi(name, "SetAccount") == 0)\r
2210         {\r
2211                 RPC_CLIENT_CREATE_ACCOUNT a;\r
2212                 InRpcClientCreateAccount(&a, p);\r
2213                 if (CtSetAccount(c, &a) == false)\r
2214                 {\r
2215                         RpcError(ret, c->Err);\r
2216                 }\r
2217                 CiFreeClientCreateAccount(&a);\r
2218         }\r
2219         else if (StrCmpi(name, "GetAccount") == 0)\r
2220         {\r
2221                 RPC_CLIENT_GET_ACCOUNT a;\r
2222                 InRpcClientGetAccount(&a, p);\r
2223                 if (CtGetAccount(c, &a) == false)\r
2224                 {\r
2225                         RpcError(ret, c->Err);\r
2226                 }\r
2227                 else\r
2228                 {\r
2229                         OutRpcClientGetAccount(ret, &a);\r
2230                 }\r
2231                 CiFreeClientGetAccount(&a);\r
2232         }\r
2233         else if (StrCmpi(name, "RenameAccount") == 0)\r
2234         {\r
2235                 RPC_RENAME_ACCOUNT a;\r
2236                 InRpcRenameAccount(&a, p);\r
2237                 if (CtRenameAccount(c, &a) == false)\r
2238                 {\r
2239                         RpcError(ret, c->Err);\r
2240                 }\r
2241         }\r
2242         else if (StrCmpi(name, "SetClientConfig") == 0)\r
2243         {\r
2244                 CLIENT_CONFIG a;\r
2245                 InRpcClientConfig(&a, p);\r
2246                 if (CtSetClientConfig(c, &a) == false)\r
2247                 {\r
2248                         RpcError(ret, c->Err);\r
2249                 }\r
2250         }\r
2251         else if (StrCmpi(name, "GetClientConfig") == 0)\r
2252         {\r
2253                 CLIENT_CONFIG a;\r
2254                 if (CtGetClientConfig(c, &a) == false)\r
2255                 {\r
2256                         RpcError(ret, c->Err);\r
2257                 }\r
2258                 else\r
2259                 {\r
2260                         OutRpcClientConfig(ret, &a);\r
2261                 }\r
2262         }\r
2263         else if (StrCmpi(name, "Connect") == 0)\r
2264         {\r
2265                 RPC_CLIENT_CONNECT a;\r
2266                 InRpcClientConnect(&a, p);\r
2267                 if (CtConnect(c, &a) == false)\r
2268                 {\r
2269                         RpcError(ret, c->Err);\r
2270                 }\r
2271         }\r
2272         else if (StrCmpi(name, "Disconnect") == 0)\r
2273         {\r
2274                 RPC_CLIENT_CONNECT a;\r
2275                 InRpcClientConnect(&a, p);\r
2276                 if (CtDisconnect(c, &a) == false)\r
2277                 {\r
2278                         RpcError(ret, c->Err);\r
2279                 }\r
2280         }\r
2281         else if (StrCmpi(name, "GetAccountStatus") == 0)\r
2282         {\r
2283                 RPC_CLIENT_GET_CONNECTION_STATUS a;\r
2284                 InRpcClientGetConnectionStatus(&a, p);\r
2285                 if (CtGetAccountStatus(c, &a) == false)\r
2286                 {\r
2287                         RpcError(ret, c->Err);\r
2288                 }\r
2289                 else\r
2290                 {\r
2291                         OutRpcClientGetConnectionStatus(ret, &a);\r
2292                 }\r
2293                 CiFreeClientGetConnectionStatus(&a);\r
2294         }\r
2295         else\r
2296         {\r
2297                 FreePack(ret);\r
2298                 ret = NULL;\r
2299         }\r
2300 \r
2301         return ret;\r
2302 }\r
2303 \r
2304 // CM_SETTING の設定\r
2305 UINT CcSetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)\r
2306 {\r
2307         PACK *ret, *p;\r
2308         UINT err;\r
2309         // 引数チェック\r
2310         if (r == NULL || a == NULL)\r
2311         {\r
2312                 return ERR_INTERNAL_ERROR;\r
2313         }\r
2314 \r
2315         p = NewPack();\r
2316         OutRpcCmSetting(p, a);\r
2317 \r
2318         ret = RpcCall(r->Rpc, "SetCmSetting", p);\r
2319 \r
2320         if (RpcIsOk(ret))\r
2321         {\r
2322                 FreePack(ret);\r
2323                 return 0;\r
2324         }\r
2325         else\r
2326         {\r
2327                 err = RpcGetError(ret);\r
2328                 FreePack(ret);\r
2329                 return err;\r
2330         }\r
2331 }\r
2332 \r
2333 // CM_SETTING の取得\r
2334 UINT CcGetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)\r
2335 {\r
2336         PACK *ret;\r
2337         // 引数チェック\r
2338         if (r == NULL || a == NULL)\r
2339         {\r
2340                 return ERR_INTERNAL_ERROR;\r
2341         }\r
2342 \r
2343         ret = RpcCall(r->Rpc, "GetCmSetting", NULL);\r
2344 \r
2345         if (RpcIsOk(ret))\r
2346         {\r
2347                 InRpcCmSetting(a, ret);\r
2348                 FreePack(ret);\r
2349                 return 0;\r
2350         }\r
2351         else\r
2352         {\r
2353                 UINT err = RpcGetError(ret);\r
2354                 FreePack(ret);\r
2355                 return err;\r
2356         }\r
2357 }\r
2358 \r
2359 // クライアントバージョンの取得\r
2360 UINT CcGetClientVersion(REMOTE_CLIENT *r, RPC_CLIENT_VERSION *a)\r
2361 {\r
2362         PACK *ret;\r
2363         // 引数チェック\r
2364         if (r == NULL || a == NULL)\r
2365         {\r
2366                 return ERR_INTERNAL_ERROR;\r
2367         }\r
2368 \r
2369         ret = RpcCall(r->Rpc, "GetClientVersion", NULL);\r
2370 \r
2371         if (RpcIsOk(ret))\r
2372         {\r
2373                 InRpcClientVersion(a, ret);\r
2374                 FreePack(ret);\r
2375                 return 0;\r
2376         }\r
2377         else\r
2378         {\r
2379                 UINT err = RpcGetError(ret);\r
2380                 FreePack(ret);\r
2381                 return err;\r
2382         }\r
2383 }\r
2384 \r
2385 // パスワードの設定\r
2386 UINT CcSetPassword(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD *pass)\r
2387 {\r
2388         PACK *ret, *p;\r
2389         // 引数チェック\r
2390         if (r == NULL || pass == NULL)\r
2391         {\r
2392                 return ERR_INTERNAL_ERROR;\r
2393         }\r
2394 \r
2395         p = NewPack();\r
2396 \r
2397         OutRpcClientPassword(p, pass);\r
2398 \r
2399         ret = RpcCall(r->Rpc, "SetPassword", p);\r
2400 \r
2401         if (RpcIsOk(ret))\r
2402         {\r
2403                 FreePack(ret);\r
2404                 return 0;\r
2405         }\r
2406         else\r
2407         {\r
2408                 UINT err = RpcGetError(ret);\r
2409                 FreePack(ret);\r
2410                 return err;\r
2411         }\r
2412 }\r
2413 \r
2414 // パスワード設定の取得\r
2415 UINT CcGetPasswordSetting(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD_SETTING *a)\r
2416 {\r
2417         PACK *ret;\r
2418         UINT err = 0;\r
2419         // 引数チェック\r
2420         if (r == NULL || a == NULL)\r
2421         {\r
2422                 return ERR_INTERNAL_ERROR;\r
2423         }\r
2424 \r
2425         ret = RpcCall(r->Rpc, "GetPasswordSetting", NULL);\r
2426 \r
2427         if (RpcIsOk(ret))\r
2428         {\r
2429                 InRpcClientPasswordSetting(a, ret);\r
2430         }\r
2431         else\r
2432         {\r
2433                 err = RpcGetError(ret);\r
2434         }\r
2435 \r
2436         FreePack(ret);\r
2437         return err;\r
2438 }\r
2439 \r
2440 // CA の列挙\r
2441 UINT CcEnumCa(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_CA *e)\r
2442 {\r
2443         PACK *ret;\r
2444         UINT err = 0;\r
2445         // 引数チェック\r
2446         if (r == NULL || e == NULL)\r
2447         {\r
2448                 return ERR_INTERNAL_ERROR;\r
2449         }\r
2450 \r
2451         ret = RpcCall(r->Rpc, "EnumCa", NULL);\r
2452 \r
2453         if (RpcIsOk(ret))\r
2454         {\r
2455                 InRpcClientEnumCa(e, ret);\r
2456         }\r
2457         else\r
2458         {\r
2459                 err = RpcGetError(ret);\r
2460         }\r
2461 \r
2462         FreePack(ret);\r
2463 \r
2464         return err;\r
2465 }\r
2466 \r
2467 // CA の追加\r
2468 UINT CcAddCa(REMOTE_CLIENT *r, RPC_CERT *cert)\r
2469 {\r
2470         PACK *p, *ret;\r
2471         UINT err = 0;\r
2472         // 引数チェック\r
2473         if (r == NULL || cert == NULL)\r
2474         {\r
2475                 return ERR_INTERNAL_ERROR;\r
2476         }\r
2477 \r
2478         p = NewPack();\r
2479         OutRpcCert(p, cert);\r
2480 \r
2481         ret = RpcCall(r->Rpc, "AddCa", p);\r
2482 \r
2483         if (RpcIsOk(ret) == false)\r
2484         {\r
2485                 err = RpcGetError(ret);\r
2486         }\r
2487 \r
2488         FreePack(ret);\r
2489 \r
2490         return err;\r
2491 }\r
2492 \r
2493 // CA の削除\r
2494 UINT CcDeleteCa(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_CA *c)\r
2495 {\r
2496         PACK *p, *ret;\r
2497         UINT err = 0;\r
2498         // 引数チェック\r
2499         if (r == NULL || c == NULL)\r
2500         {\r
2501                 return ERR_INTERNAL_ERROR;\r
2502         }\r
2503 \r
2504         p = NewPack();\r
2505         OutRpcClientDeleteCa(p, c);\r
2506 \r
2507         ret = RpcCall(r->Rpc, "DeleteCa", p);\r
2508 \r
2509         if (RpcIsOk(ret) == false)\r
2510         {\r
2511                 err = RpcGetError(ret);\r
2512         }\r
2513 \r
2514         FreePack(ret);\r
2515 \r
2516         return err;\r
2517 }\r
2518 \r
2519 // 署名者の取得\r
2520 UINT CcGetIssuer(REMOTE_CLIENT *r, RPC_GET_ISSUER *a)\r
2521 {\r
2522         PACK *p, *ret;\r
2523         UINT err = 0;\r
2524         // 引数チェック\r
2525         if (r == NULL || a == NULL)\r
2526         {\r
2527                 return ERR_INTERNAL_ERROR;\r
2528         }\r
2529 \r
2530         p = NewPack();\r
2531         OutRpcGetIssuer(p, a);\r
2532 \r
2533         ret = RpcCall(r->Rpc, "GetIssuer", p);\r
2534 \r
2535         if (RpcIsOk(ret))\r
2536         {\r
2537                 if (a->x != NULL)\r
2538                 {\r
2539                         FreeX(a->x);\r
2540                         a->x = NULL;\r
2541                 }\r
2542                 InRpcGetIssuer(a, ret);\r
2543         }\r
2544         else\r
2545         {\r
2546                 err = RpcGetError(ret);\r
2547         }\r
2548 \r
2549         FreePack(ret);\r
2550 \r
2551         return err;\r
2552 }\r
2553 \r
2554 // CA の取得\r
2555 UINT CcGetCa(REMOTE_CLIENT *r, RPC_GET_CA *get)\r
2556 {\r
2557         PACK *p, *ret;\r
2558         UINT err = 0;\r
2559         // 引数チェック\r
2560         if (r == NULL || get == NULL)\r
2561         {\r
2562                 return ERR_INTERNAL_ERROR;\r
2563         }\r
2564 \r
2565         p = NewPack();\r
2566         OutRpcGetCa(p, get);\r
2567 \r
2568         ret = RpcCall(r->Rpc, "GetCa", p);\r
2569 \r
2570         if (RpcIsOk(ret))\r
2571         {\r
2572                 InRpcGetCa(get, ret);\r
2573         }\r
2574         else\r
2575         {\r
2576                 err = RpcGetError(ret);\r
2577         }\r
2578 \r
2579         FreePack(ret);\r
2580 \r
2581         return err;\r
2582 }\r
2583 \r
2584 // セキュアデバイスの列挙\r
2585 UINT CcEnumSecure(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_SECURE *e)\r
2586 {\r
2587         PACK *ret;\r
2588         UINT err = 0;\r
2589         // 引数チェック\r
2590         if (r == NULL || e == NULL)\r
2591         {\r
2592                 return ERR_INTERNAL_ERROR;\r
2593         }\r
2594 \r
2595         ret = RpcCall(r->Rpc, "EnumSecure", NULL);\r
2596 \r
2597         if (RpcIsOk(ret))\r
2598         {\r
2599                 InRpcClientEnumSecure(e, ret);\r
2600         }\r
2601         else\r
2602         {\r
2603                 err = RpcGetError(ret);\r
2604         }\r
2605 \r
2606         FreePack(ret);\r
2607 \r
2608         return err;\r
2609 }\r
2610 \r
2611 // 使用しているセキュアデバイスの取得\r
2612 UINT CcGetUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)\r
2613 {\r
2614         PACK *p, *ret;\r
2615         UINT err = 0;\r
2616         // 引数チェック\r
2617         if (r == NULL || sec == NULL)\r
2618         {\r
2619                 return ERR_INTERNAL_ERROR;\r
2620         }\r
2621 \r
2622         p = NewPack();\r
2623 \r
2624         ret = RpcCall(r->Rpc, "GetUseSecure", p);\r
2625 \r
2626         if (RpcIsOk(ret) == false)\r
2627         {\r
2628                 err = RpcGetError(ret);\r
2629         }\r
2630         else\r
2631         {\r
2632                 InRpcUseSecure(sec, ret);\r
2633         }\r
2634 \r
2635         FreePack(ret);\r
2636 \r
2637         return err;\r
2638 }\r
2639 \r
2640 // セキュアデバイスの使用\r
2641 UINT CcUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)\r
2642 {\r
2643         PACK *p, *ret;\r
2644         UINT err = 0;\r
2645         // 引数チェック\r
2646         if (r == NULL || sec == NULL)\r
2647         {\r
2648                 return ERR_INTERNAL_ERROR;\r
2649         }\r
2650 \r
2651         p = NewPack();\r
2652         OutRpcUseSecure(p, sec);\r
2653 \r
2654         ret = RpcCall(r->Rpc, "UseSecure", p);\r
2655 \r
2656         if (RpcIsOk(ret) == false)\r
2657         {\r
2658                 err = RpcGetError(ret);\r
2659         }\r
2660 \r
2661         FreePack(ret);\r
2662 \r
2663         return err;\r
2664 }\r
2665 \r
2666 // セキュアデバイス内のオブジェクトの列挙\r
2667 UINT CcEnumObjectInSecure(REMOTE_CLIENT *r, RPC_ENUM_OBJECT_IN_SECURE *e)\r
2668 {\r
2669         PACK *ret;\r
2670         UINT err = 0;\r
2671         // 引数チェック\r
2672         if (r == NULL || e == NULL)\r
2673         {\r
2674                 return ERR_INTERNAL_ERROR;\r
2675         }\r
2676 \r
2677         ret = RpcCall(r->Rpc, "EnumObjectInSecure", NULL);\r
2678 \r
2679         if (RpcIsOk(ret))\r
2680         {\r
2681                 InRpcEnumObjectInSecure(e, ret);\r
2682         }\r
2683         else\r
2684         {\r
2685                 err = RpcGetError(ret);\r
2686         }\r
2687 \r
2688         FreePack(ret);\r
2689 \r
2690         return err;\r
2691 }\r
2692 \r
2693 // VLAN の作成\r
2694 UINT CcCreateVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)\r
2695 {\r
2696         PACK *ret, *p;\r
2697         UINT err = 0;\r
2698         char *s = NULL;\r
2699         // 引数チェック\r
2700         if (r == NULL || create == NULL)\r
2701         {\r
2702                 return ERR_INTERNAL_ERROR;\r
2703         }\r
2704 \r
2705         p = NewPack();\r
2706         OutRpcCreateVLan(p, create);\r
2707 \r
2708 #ifdef  OS_WIN32\r
2709         s = MsNoWarningSoundInit();\r
2710 #endif  // OS_WIN32\r
2711 \r
2712         ret = RpcCall(r->Rpc, "CreateVLan", p);\r
2713 \r
2714 #ifdef  OS_WIN32\r
2715         MsNoWarningSoundFree(s);\r
2716 #endif  // OS_WIN32\r
2717 \r
2718         if (RpcIsOk(ret) == false)\r
2719         {\r
2720                 err = RpcGetError(ret);\r
2721         }\r
2722 \r
2723         FreePack(ret);\r
2724 \r
2725         return err;\r
2726 }\r
2727 \r
2728 // VLAN のアップグレード\r
2729 UINT CcUpgradeVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)\r
2730 {\r
2731         PACK *ret, *p;\r
2732         UINT err = 0;\r
2733         char *s = NULL;\r
2734         // 引数チェック\r
2735         if (r == NULL || create == NULL)\r
2736         {\r
2737                 return ERR_INTERNAL_ERROR;\r
2738         }\r
2739 \r
2740         p = NewPack();\r
2741         OutRpcCreateVLan(p, create);\r
2742 \r
2743 #ifdef  OS_WIN32\r
2744         s = MsNoWarningSoundInit();\r
2745 #endif  // OS_WIN32\r
2746 \r
2747         ret = RpcCall(r->Rpc, "UpgradeVLan", p);\r
2748 \r
2749 #ifdef  OS_WIN32\r
2750         MsNoWarningSoundFree(s);\r
2751 #endif  // OS_WIN32\r
2752 \r
2753 \r
2754         if (RpcIsOk(ret) == false)\r
2755         {\r
2756                 err = RpcGetError(ret);\r
2757         }\r
2758 \r
2759         FreePack(ret);\r
2760 \r
2761         return err;\r
2762 }\r
2763 \r
2764 // VLAN の取得\r
2765 UINT CcGetVLan(REMOTE_CLIENT *r, RPC_CLIENT_GET_VLAN *get)\r
2766 {\r
2767         PACK *ret, *p;\r
2768         UINT err = 0;\r
2769         // 引数チェック\r
2770         if (r == NULL || get == NULL)\r
2771         {\r
2772                 return ERR_INTERNAL_ERROR;\r
2773         }\r
2774 \r
2775         p = NewPack();\r
2776         OutRpcClientGetVLan(p, get);\r
2777 \r
2778         ret = RpcCall(r->Rpc, "GetVLan", p);\r
2779 \r
2780         if (RpcIsOk(ret))\r
2781         {\r
2782                 InRpcClientGetVLan(get, ret);\r
2783         }\r
2784         else\r
2785         {\r
2786                 err = RpcGetError(ret);\r
2787         }\r
2788 \r
2789         FreePack(ret);\r
2790 \r
2791         return err;\r
2792 }\r
2793 \r
2794 // VLAN の設定\r
2795 UINT CcSetVLan(REMOTE_CLIENT *r, RPC_CLIENT_SET_VLAN *set)\r
2796 {\r
2797         PACK *ret, *p;\r
2798         UINT err = 0;\r
2799         // 引数チェック\r
2800         if (r == NULL || set == NULL)\r
2801         {\r
2802                 return ERR_INTERNAL_ERROR;\r
2803         }\r
2804 \r
2805         p = NewPack();\r
2806         OutRpcClientSetVLan(p, set);\r
2807 \r
2808         ret = RpcCall(r->Rpc, "SetVLan", p);\r
2809 \r
2810         if (RpcIsOk(ret) == false)\r
2811         {\r
2812                 err = RpcGetError(ret);\r
2813         }\r
2814 \r
2815         FreePack(ret);\r
2816 \r
2817         return err;\r
2818 }\r
2819 \r
2820 // VLAN の列挙\r
2821 UINT CcEnumVLan(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_VLAN *e)\r
2822 {\r
2823         PACK *ret;\r
2824         UINT err = 0;\r
2825         // 引数チェック\r
2826         if (r == NULL || e == NULL)\r
2827         {\r
2828                 return ERR_INTERNAL_ERROR;\r
2829         }\r
2830 \r
2831         ret = RpcCall(r->Rpc, "EnumVLan", NULL);\r
2832 \r
2833         if (RpcIsOk(ret))\r
2834         {\r
2835                 InRpcClientEnumVLan(e, ret);\r
2836         }\r
2837         else\r
2838         {\r
2839                 err = RpcGetError(ret);\r
2840         }\r
2841 \r
2842         FreePack(ret);\r
2843 \r
2844         return err;\r
2845 }\r
2846 \r
2847 // VLAN の削除\r
2848 UINT CcDeleteVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *d)\r
2849 {\r
2850         PACK *ret, *p;\r
2851         UINT err = 0;\r
2852         // 引数チェック\r
2853         if (r == NULL || d == NULL)\r
2854         {\r
2855                 return ERR_INTERNAL_ERROR;\r
2856         }\r
2857 \r
2858         p = NewPack();\r
2859         OutRpcCreateVLan(p, d);\r
2860 \r
2861         ret = RpcCall(r->Rpc, "DeleteVLan", p);\r
2862 \r
2863         if (RpcIsOk(ret) == false)\r
2864         {\r
2865                 err = RpcGetError(ret);\r
2866         }\r
2867 \r
2868         FreePack(ret);\r
2869 \r
2870         return err;\r
2871 }\r
2872 \r
2873 // VLAN の有効化\r
2874 UINT CcEnableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)\r
2875 {\r
2876         PACK *ret, *p;\r
2877         UINT err = 0;\r
2878         // 引数チェック\r
2879         if (r == NULL || vlan == NULL)\r
2880         {\r
2881                 return ERR_INTERNAL_ERROR;\r
2882         }\r
2883 \r
2884         p = NewPack();\r
2885         OutRpcCreateVLan(p, vlan);\r
2886 \r
2887         ret = RpcCall(r->Rpc, "EnableVLan", p);\r
2888 \r
2889         if (RpcIsOk(ret) == false)\r
2890         {\r
2891                 err = RpcGetError(ret);\r
2892         }\r
2893 \r
2894         FreePack(ret);\r
2895 \r
2896         return err;\r
2897 }\r
2898 \r
2899 // VLAN の無効化\r
2900 UINT CcDisableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)\r
2901 {\r
2902         PACK *ret, *p;\r
2903         UINT err = 0;\r
2904         // 引数チェック\r
2905         if (r == NULL || vlan == NULL)\r
2906         {\r
2907                 return ERR_INTERNAL_ERROR;\r
2908         }\r
2909 \r
2910         p = NewPack();\r
2911         OutRpcCreateVLan(p, vlan);\r
2912 \r
2913         ret = RpcCall(r->Rpc, "DisableVLan", p);\r
2914 \r
2915         if (RpcIsOk(ret) == false)\r
2916         {\r
2917                 err = RpcGetError(ret);\r
2918         }\r
2919 \r
2920         FreePack(ret);\r
2921 \r
2922         return err;\r
2923 }\r
2924 \r
2925 // アカウントの作成\r
2926 UINT CcCreateAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)\r
2927 {\r
2928         PACK *ret, *p;\r
2929         UINT err = 0;\r
2930         // 引数チェック\r
2931         if (r == NULL || a == NULL)\r
2932         {\r
2933                 return ERR_INTERNAL_ERROR;\r
2934         }\r
2935 \r
2936         p = NewPack();\r
2937         OutRpcClientCreateAccount(p, a);\r
2938 \r
2939         ret = RpcCall(r->Rpc, "CreateAccount", p);\r
2940 \r
2941         if (RpcIsOk(ret) == false)\r
2942         {\r
2943                 err = RpcGetError(ret);\r
2944         }\r
2945 \r
2946         FreePack(ret);\r
2947 \r
2948         return err;\r
2949 }\r
2950 \r
2951 // アカウントの列挙\r
2952 UINT CcEnumAccount(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_ACCOUNT *e)\r
2953 {\r
2954         PACK *ret;\r
2955         UINT err = 0;\r
2956         // 引数チェック\r
2957         if (r == NULL || e == NULL)\r
2958         {\r
2959                 return ERR_INTERNAL_ERROR;\r
2960         }\r
2961 \r
2962         ret = RpcCall(r->Rpc, "EnumAccount", NULL);\r
2963 \r
2964         if (RpcIsOk(ret))\r
2965         {\r
2966                 UINT i;\r
2967                 InRpcClientEnumAccount(e, ret);\r
2968 \r
2969                 for (i = 0;i < e->NumItem;i++)\r
2970                 {\r
2971                         RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = e->Items[i];\r
2972 \r
2973                         if (IsEmptyStr(t->HubName) && t->Port == 0)\r
2974                         {\r
2975                                 UINT err2;\r
2976                                 RPC_CLIENT_GET_ACCOUNT a;\r
2977 \r
2978                                 // 古いバージョンの VPN Client では列挙時に HUB 名とポート番号\r
2979                                 // を取得できないので、別途取得する。\r
2980                                 Zero(&a, sizeof(a));\r
2981                                 UniStrCpy(a.AccountName, sizeof(a.AccountName), t->AccountName);\r
2982                                 err2 = CcGetAccount(r, &a);\r
2983                                 if (err2 == ERR_NO_ERROR)\r
2984                                 {\r
2985                                         StrCpy(t->HubName, sizeof(t->HubName), a.ClientOption->HubName);\r
2986                                         t->Port = a.ClientOption->Port;\r
2987 \r
2988                                         CiFreeClientGetAccount(&a);\r
2989                                 }\r
2990                         }\r
2991                 }\r
2992         }\r
2993         else\r
2994         {\r
2995                 err = RpcGetError(ret);\r
2996         }\r
2997 \r
2998         FreePack(ret);\r
2999 \r
3000         return err;\r
3001 }\r
3002 \r
3003 // スタートアップを解除する\r
3004 UINT CcRemoveStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)\r
3005 {\r
3006         PACK *ret, *p;\r
3007         UINT err = 0;\r
3008         // 引数チェック\r
3009         if (r == NULL || a == NULL)\r
3010         {\r
3011                 return ERR_INTERNAL_ERROR;\r
3012         }\r
3013 \r
3014         p = NewPack();\r
3015         OutRpcClientDeleteAccount(p, a);\r
3016 \r
3017         ret = RpcCall(r->Rpc, "RemoveStartupAccount", p);\r
3018 \r
3019         if (RpcIsOk(ret) == false)\r
3020         {\r
3021                 err = RpcGetError(ret);\r
3022         }\r
3023 \r
3024         FreePack(ret);\r
3025 \r
3026         return err;\r
3027 }\r
3028 \r
3029 // スタートアップにする\r
3030 UINT CcSetStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)\r
3031 {\r
3032         PACK *ret, *p;\r
3033         UINT err = 0;\r
3034         // 引数チェック\r
3035         if (r == NULL || a == NULL)\r
3036         {\r
3037                 return ERR_INTERNAL_ERROR;\r
3038         }\r
3039 \r
3040         p = NewPack();\r
3041         OutRpcClientDeleteAccount(p, a);\r
3042 \r
3043         ret = RpcCall(r->Rpc, "SetStartupAccount", p);\r
3044 \r
3045         if (RpcIsOk(ret) == false)\r
3046         {\r
3047                 err = RpcGetError(ret);\r
3048         }\r
3049 \r
3050         FreePack(ret);\r
3051 \r
3052         return err;\r
3053 }\r
3054 \r
3055 // アカウントの削除\r
3056 UINT CcDeleteAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)\r
3057 {\r
3058         PACK *ret, *p;\r
3059         UINT err = 0;\r
3060         // 引数チェック\r
3061         if (r == NULL || a == NULL)\r
3062         {\r
3063                 return ERR_INTERNAL_ERROR;\r
3064         }\r
3065 \r
3066         p = NewPack();\r
3067         OutRpcClientDeleteAccount(p, a);\r
3068 \r
3069         ret = RpcCall(r->Rpc, "DeleteAccount", p);\r
3070 \r
3071         if (RpcIsOk(ret) == false)\r
3072         {\r
3073                 err = RpcGetError(ret);\r
3074         }\r
3075 \r
3076         FreePack(ret);\r
3077 \r
3078         return err;\r
3079 }\r
3080 \r
3081 // アカウントの設定\r
3082 UINT CcSetAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)\r
3083 {\r
3084         PACK *ret, *p;\r
3085         UINT err = 0;\r
3086         // 引数チェック\r
3087         if (r == NULL || a == NULL)\r
3088         {\r
3089                 return ERR_INTERNAL_ERROR;\r
3090         }\r
3091 \r
3092         p = NewPack();\r
3093         OutRpcClientCreateAccount(p, a);\r
3094 \r
3095         ret = RpcCall(r->Rpc, "SetAccount", p);\r
3096 \r
3097         if (RpcIsOk(ret) == false)\r
3098         {\r
3099                 err = RpcGetError(ret);\r
3100         }\r
3101 \r
3102         FreePack(ret);\r
3103 \r
3104         return err;\r
3105 }\r
3106 \r
3107 // アカウントの取得\r
3108 UINT CcGetAccount(REMOTE_CLIENT *r, RPC_CLIENT_GET_ACCOUNT *a)\r
3109 {\r
3110         PACK *ret, *p;\r
3111         UINT err = 0;\r
3112         // 引数チェック\r
3113         if (r == NULL || a == NULL)\r
3114         {\r
3115                 return ERR_INTERNAL_ERROR;\r
3116         }\r
3117 \r
3118         p = NewPack();\r
3119         OutRpcClientGetAccount(p, a);\r
3120 \r
3121         ret = RpcCall(r->Rpc, "GetAccount", p);\r
3122 \r
3123         if (RpcIsOk(ret))\r
3124         {\r
3125                 InRpcClientGetAccount(a, ret);\r
3126         }\r
3127         else\r
3128         {\r
3129                 err = RpcGetError(ret);\r
3130         }\r
3131 \r
3132         FreePack(ret);\r
3133 \r
3134         return err;\r
3135 }\r
3136 \r
3137 // アカウント名の変更\r
3138 UINT CcRenameAccount(REMOTE_CLIENT *r, RPC_RENAME_ACCOUNT *rename)\r
3139 {\r
3140         PACK *p, *ret;\r
3141         UINT err = 0;\r
3142         // 引数チェック\r
3143         if (r == NULL || rename == NULL)\r
3144         {\r
3145                 return ERR_INTERNAL_ERROR;\r
3146         }\r
3147 \r
3148         p = NewPack();\r
3149         OutRpcRenameAccount(p, rename);\r
3150 \r
3151         ret = RpcCall(r->Rpc, "RenameAccount", p);\r
3152 \r
3153         if (RpcIsOk(ret) == false)\r
3154         {\r
3155                 err = RpcGetError(ret);\r
3156         }\r
3157 \r
3158         FreePack(ret);\r
3159 \r
3160         return err;\r
3161 }\r
3162 \r
3163 // クライアント設定の設定\r
3164 UINT CcSetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)\r
3165 {\r
3166         PACK *p, *ret;\r
3167         UINT err = 0;\r
3168         // 引数チェック\r
3169         if (r == NULL || o == NULL)\r
3170         {\r
3171                 return ERR_INTERNAL_ERROR;\r
3172         }\r
3173 \r
3174         p = NewPack();\r
3175         OutRpcClientConfig(p, o);\r
3176 \r
3177         ret = RpcCall(r->Rpc, "SetClientConfig", p);\r
3178 \r
3179         if (RpcIsOk(ret) == false)\r
3180         {\r
3181                 err = RpcGetError(ret);\r
3182         }\r
3183 \r
3184         FreePack(ret);\r
3185 \r
3186         return err;\r
3187 }\r
3188 \r
3189 // クライアント設定の取得\r
3190 UINT CcGetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)\r
3191 {\r
3192         PACK *ret;\r
3193         UINT err = 0;\r
3194         // 引数チェック\r
3195         if (r == NULL || o == NULL)\r
3196         {\r
3197                 return ERR_INTERNAL_ERROR;\r
3198         }\r
3199 \r
3200         ret = RpcCall(r->Rpc, "GetClientConfig", NULL);\r
3201 \r
3202         if (RpcIsOk(ret))\r
3203         {\r
3204                 InRpcClientConfig(o, ret);\r
3205         }\r
3206         else\r
3207         {\r
3208                 err = RpcGetError(ret);\r
3209         }\r
3210 \r
3211         FreePack(ret);\r
3212 \r
3213         return err;\r
3214 }\r
3215 \r
3216 // サービスをフォアグラウンドプロセスに設定する\r
3217 void CcSetServiceToForegroundProcess(REMOTE_CLIENT *r)\r
3218 {\r
3219         // 引数チェック\r
3220         if (r == NULL)\r
3221         {\r
3222                 return;\r
3223         }\r
3224         // 廃止\r
3225 /*\r
3226         if (r->Rpc != NULL && r->Rpc->Sock != NULL && r->Rpc->Sock->RemoteIP.addr[0] == 127)\r
3227         {\r
3228                 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) &&\r
3229                         GET_KETA(GetOsInfo()->OsType, 100) >= 2)\r
3230                 {\r
3231                         // Windows 2000 以降でのみこの操作は行う\r
3232                         RPC_CLIENT_VERSION v;\r
3233                         Zero(&v, sizeof(v));\r
3234 \r
3235                         if (r->ClientBuildInt == 0)\r
3236                         {\r
3237                                 CcGetClientVersion(r, &v);\r
3238                                 r->ClientBuildInt = v.ClientBuildInt;\r
3239                                 r->ProcessId = v.ProcessId;\r
3240                         }\r
3241                         if (r->ProcessId != 0 && r->ClientBuildInt <= 5080)\r
3242                         {\r
3243 #ifdef  OS_WIN32\r
3244                                 // サービスプロセスをフォアグラウンドウインドウに設定する\r
3245                                 AllowFGWindow(v.ProcessId);\r
3246 #endif  // OS_WIN32\r
3247                         }\r
3248                 }\r
3249         }*/\r
3250 }\r
3251 \r
3252 // 接続\r
3253 UINT CcConnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)\r
3254 {\r
3255         PACK *ret, *p;\r
3256         UINT err = 0;\r
3257         // 引数チェック\r
3258         if (r == NULL || connect == NULL)\r
3259         {\r
3260                 return ERR_INTERNAL_ERROR;\r
3261         }\r
3262 \r
3263         CcSetServiceToForegroundProcess(r);\r
3264 \r
3265         p = NewPack();\r
3266         OutRpcClientConnect(p, connect);\r
3267 \r
3268         ret = RpcCall(r->Rpc, "Connect", p);\r
3269 \r
3270         if (RpcIsOk(ret) == false)\r
3271         {\r
3272                 err = RpcGetError(ret);\r
3273         }\r
3274 \r
3275         FreePack(ret);\r
3276 \r
3277         return err;\r
3278 }\r
3279 \r
3280 // 切断\r
3281 UINT CcDisconnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)\r
3282 {\r
3283         PACK *ret, *p;\r
3284         UINT err = 0;\r
3285         // 引数チェック\r
3286         if (r == NULL || connect == NULL)\r
3287         {\r
3288                 return ERR_INTERNAL_ERROR;\r
3289         }\r
3290 \r
3291         CcSetServiceToForegroundProcess(r);\r
3292 \r
3293         p = NewPack();\r
3294         OutRpcClientConnect(p, connect);\r
3295 \r
3296         ret = RpcCall(r->Rpc, "Disconnect", p);\r
3297 \r
3298         if (RpcIsOk(ret) == false)\r
3299         {\r
3300                 err = RpcGetError(ret);\r
3301         }\r
3302 \r
3303         FreePack(ret);\r
3304 \r
3305         return err;\r
3306 }\r
3307 \r
3308 // アカウント状況の取得\r
3309 UINT CcGetAccountStatus(REMOTE_CLIENT *r, RPC_CLIENT_GET_CONNECTION_STATUS *st)\r
3310 {\r
3311         PACK *ret, *p;\r
3312         UINT err = 0;\r
3313         // 引数チェック\r
3314         if (r == NULL || st == NULL)\r
3315         {\r
3316                 return ERR_INTERNAL_ERROR;\r
3317         }\r
3318 \r
3319         p = NewPack();\r
3320         OutRpcClientGetConnectionStatus(p, st);\r
3321 \r
3322         ret = RpcCall(r->Rpc, "GetAccountStatus", p);\r
3323 \r
3324         if (RpcIsOk(ret))\r
3325         {\r
3326                 InRpcClientGetConnectionStatus(st, ret);\r
3327         }\r
3328         else\r
3329         {\r
3330                 err = RpcGetError(ret);\r
3331         }\r
3332 \r
3333         FreePack(ret);\r
3334 \r
3335         return err;\r
3336 }\r
3337 \r
3338 \r
3339 // クライアントサービスが接続マネージャに対して通知を送信する\r
3340 void CiNotify(CLIENT *c)\r
3341 {\r
3342         // 引数チェック\r
3343         if (c == NULL)\r
3344         {\r
3345                 return;\r
3346         }\r
3347 \r
3348         // すべての通知イベントを起動する\r
3349         LockList(c->NotifyCancelList);\r
3350         {\r
3351                 UINT i;\r
3352                 for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)\r
3353                 {\r
3354                         CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);\r
3355                         Cancel(cancel);\r
3356                 }\r
3357         }\r
3358         UnlockList(c->NotifyCancelList);\r
3359 }\r
3360 \r
3361 // RPC_CLIENT_ENUM_ACCOUNT の解放\r
3362 void CiFreeClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *a)\r
3363 {\r
3364         UINT i;\r
3365         // 引数チェック\r
3366         if (a == NULL)\r
3367         {\r
3368                 return;\r
3369         }\r
3370 \r
3371         for (i = 0;i < a->NumItem;i++)\r
3372         {\r
3373                 RPC_CLIENT_ENUM_ACCOUNT_ITEM *e = a->Items[i];\r
3374                 Free(e);\r
3375         }\r
3376         Free(a->Items);\r
3377 }\r
3378 \r
3379 \r
3380 // 一定時間ごとに設定ファイルを保存するスレッド\r
3381 void CiSaverThread(THREAD *t, void *param)\r
3382 {\r
3383         CLIENT *c = (CLIENT *)param;\r
3384         // 引数チェック\r
3385         if (t == NULL || param == NULL)\r
3386         {\r
3387                 return;\r
3388         }\r
3389 \r
3390         NoticeThreadInit(t);\r
3391 \r
3392         // 一定時間待つ\r
3393         while (c->Halt == false)\r
3394         {\r
3395                 Wait(c->SaverHalter, CLIENT_SAVER_INTERVAL);\r
3396 \r
3397                 // 保存\r
3398                 CiSaveConfigurationFile(c);\r
3399         }\r
3400 }\r
3401 \r
3402 // 設定データ自動保存の初期化\r
3403 void CiInitSaver(CLIENT *c)\r
3404 {\r
3405         // 引数チェック\r
3406         if (c == NULL)\r
3407         {\r
3408                 return;\r
3409         }\r
3410 \r
3411         c->SaverHalter = NewEvent();\r
3412 \r
3413         c->SaverThread = NewThread(CiSaverThread, c);\r
3414         WaitThreadInit(c->SaverThread);\r
3415 }\r
3416 \r
3417 // 設定データ自動保存の解放\r
3418 void CiFreeSaver(CLIENT *c)\r
3419 {\r
3420         // 引数チェック\r
3421         if (c == NULL)\r
3422         {\r
3423                 return;\r
3424         }\r
3425 \r
3426         c->Halt = true;\r
3427         Set(c->SaverHalter);\r
3428         WaitThread(c->SaverThread, INFINITE);\r
3429         ReleaseThread(c->SaverThread);\r
3430 \r
3431         ReleaseEvent(c->SaverHalter);\r
3432 }\r
3433 \r
3434 // CM_SETTING\r
3435 void InRpcCmSetting(CM_SETTING *c, PACK *p)\r
3436 {\r
3437         // 引数チェック\r
3438         if (c == NULL || p == NULL)\r
3439         {\r
3440                 return;\r
3441         }\r
3442 \r
3443         Zero(c, sizeof(CM_SETTING));\r
3444         c->EasyMode = PackGetBool(p, "EasyMode");\r
3445         c->LockMode = PackGetBool(p, "LockMode");\r
3446         PackGetData2(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));\r
3447 }\r
3448 void OutRpcCmSetting(PACK *p, CM_SETTING *c)\r
3449 {\r
3450         // 引数チェック\r
3451         if (c == NULL || p == NULL)\r
3452         {\r
3453                 return;\r
3454         }\r
3455 \r
3456         PackAddBool(p, "EasyMode", c->EasyMode);\r
3457         PackAddBool(p, "LockMode", c->LockMode);\r
3458         PackAddData(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));\r
3459 }\r
3460 \r
3461 // CLIENT_CONFIG\r
3462 void InRpcClientConfig(CLIENT_CONFIG *c, PACK *p)\r
3463 {\r
3464         // 引数チェック\r
3465         if (c == NULL || p == NULL)\r
3466         {\r
3467                 return;\r
3468         }\r
3469 \r
3470         Zero(c, sizeof(CLIENT_CONFIG));\r
3471         c->UseKeepConnect = PackGetInt(p, "UseKeepConnect") == 0 ? false : true;\r
3472         c->KeepConnectPort = PackGetInt(p, "KeepConnectPort");\r
3473         c->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol");\r
3474         c->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval");\r
3475         c->AllowRemoteConfig = PackGetInt(p, "AllowRemoteConfig") == 0 ? false : true;\r
3476         PackGetStr(p, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));\r
3477 }\r
3478 void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c)\r
3479 {\r
3480         // 引数チェック\r
3481         if (c == NULL || p == NULL)\r
3482         {\r
3483                 return;\r
3484         }\r
3485 \r
3486         PackAddInt(p, "UseKeepConnect", c->UseKeepConnect);\r
3487         PackAddInt(p, "KeepConnectPort", c->KeepConnectPort);\r
3488         PackAddInt(p, "KeepConnectProtocol", c->KeepConnectProtocol);\r
3489         PackAddInt(p, "KeepConnectInterval", c->KeepConnectInterval);\r
3490         PackAddInt(p, "AllowRemoteConfig", c->AllowRemoteConfig);\r
3491         PackAddStr(p, "KeepConnectHost", c->KeepConnectHost);\r
3492 }\r
3493 \r
3494 // RPC_CLIENT_VERSION\r
3495 void InRpcClientVersion(RPC_CLIENT_VERSION *ver, PACK *p)\r
3496 {\r
3497         // 引数チェック\r
3498         if (ver == NULL || p == NULL)\r
3499         {\r
3500                 return;\r
3501         }\r
3502 \r
3503         Zero(ver, sizeof(RPC_CLIENT_VERSION));\r
3504         PackGetStr(p, "ClientProductName", ver->ClientProductName, sizeof(ver->ClientProductName));\r
3505         PackGetStr(p, "ClientVersionString", ver->ClientVersionString, sizeof(ver->ClientVersionString));\r
3506         PackGetStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString));\r
3507         ver->ClientVerInt = PackGetInt(p, "ClientVerInt");\r
3508         ver->ClientBuildInt = PackGetInt(p, "ClientBuildInt");\r
3509         ver->ProcessId = PackGetInt(p, "ProcessId");\r
3510         ver->OsType = PackGetInt(p, "OsType");\r
3511 }\r
3512 void OutRpcClientVersion(PACK *p, RPC_CLIENT_VERSION *ver)\r
3513 {\r
3514         // 引数チェック\r
3515         if (ver == NULL || p == NULL)\r
3516         {\r
3517                 return;\r
3518         }\r
3519 \r
3520         PackAddStr(p, "ClientProductName", ver->ClientProductName);\r
3521         PackAddStr(p, "ClientVersionString", ver->ClientVersionString);\r
3522         PackAddStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString);\r
3523         PackAddInt(p, "ClientVerInt", ver->ClientVerInt);\r
3524         PackAddInt(p, "ClientBuildInt", ver->ClientBuildInt);\r
3525         PackAddInt(p, "ProcessId", ver->ProcessId);\r
3526         PackAddInt(p, "OsType", ver->OsType);\r
3527 }\r
3528 \r
3529 // RPC_CLIENT_PASSWORD\r
3530 void InRpcClientPassword(RPC_CLIENT_PASSWORD *pw, PACK *p)\r
3531 {\r
3532         // 引数チェック\r
3533         if (pw == NULL || p == NULL)\r
3534         {\r
3535                 return;\r
3536         }\r
3537 \r
3538         Zero(pw, sizeof(RPC_CLIENT_PASSWORD));\r
3539         PackGetStr(p, "Password", pw->Password, sizeof(pw->Password));\r
3540         pw->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly");\r
3541 }\r
3542 void OutRpcClientPassword(PACK *p, RPC_CLIENT_PASSWORD *pw)\r
3543 {\r
3544         // 引数チェック\r
3545         if (pw == NULL || p == NULL)\r
3546         {\r
3547                 return;\r
3548         }\r
3549 \r
3550         PackAddStr(p, "Password", pw->Password);\r
3551         PackAddInt(p, "PasswordRemoteOnly", pw->PasswordRemoteOnly);\r
3552 }\r
3553 \r
3554 // RPC_CLIENT_PASSWORD_SETTING\r
3555 void InRpcClientPasswordSetting(RPC_CLIENT_PASSWORD_SETTING *a, PACK *p)\r
3556 {\r
3557         // 引数チェック\r
3558         if (a == NULL || p == NULL)\r
3559         {\r
3560                 return;\r
3561         }\r
3562 \r
3563         Zero(a, sizeof(RPC_CLIENT_PASSWORD_SETTING));\r
3564 \r
3565         a->IsPasswordPresented = PackGetInt(p, "IsPasswordPresented") == 0 ? false : true;\r
3566         a->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly") == 0 ? false : true;\r
3567 }\r
3568 void OutRpcClientPasswordSetting(PACK *p, RPC_CLIENT_PASSWORD_SETTING *a)\r
3569 {\r
3570         // 引数チェック\r
3571         if (a == NULL || p == NULL)\r
3572         {\r
3573                 return;\r
3574         }\r
3575 \r
3576         PackAddInt(p, "IsPasswordPresented", a->IsPasswordPresented);\r
3577         PackAddInt(p, "PasswordRemoteOnly", a->PasswordRemoteOnly);\r
3578 }\r
3579 \r
3580 // RPC_CLIENT_ENUM_CA\r
3581 void InRpcClientEnumCa(RPC_CLIENT_ENUM_CA *e, PACK *p)\r
3582 {\r
3583         UINT i;\r
3584         // 引数チェック\r
3585         if (e == NULL || p == NULL)\r
3586         {\r
3587                 return;\r
3588         }\r
3589 \r
3590         Zero(e, sizeof(RPC_CLIENT_ENUM_CA));\r
3591         e->NumItem = PackGetNum(p, "NumItem");\r
3592 \r
3593         e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);\r
3594         for (i = 0;i < e->NumItem;i++)\r
3595         {\r
3596                 RPC_CLIENT_ENUM_CA_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));\r
3597                 e->Items[i] = item;\r
3598 \r
3599                 item->Key = PackGetIntEx(p, "Key", i);\r
3600                 PackGetUniStrEx(p, "SubjectName", item->SubjectName, sizeof(item->SubjectName), i);\r
3601                 PackGetUniStrEx(p, "IssuerName", item->IssuerName, sizeof(item->IssuerName), i);\r
3602                 item->Expires = PackGetInt64Ex(p, "Expires", i);\r
3603         }\r
3604 }\r
3605 void OutRpcClientEnumCa(PACK *p, RPC_CLIENT_ENUM_CA *e)\r
3606 {\r
3607         UINT i;\r
3608         // 引数チェック\r
3609         if (e == NULL || p == NULL)\r
3610         {\r
3611                 return;\r
3612         }\r
3613 \r
3614         PackAddNum(p, "NumItem", e->NumItem);\r
3615 \r
3616         for (i = 0;i < e->NumItem;i++)\r
3617         {\r
3618                 RPC_CLIENT_ENUM_CA_ITEM *item = e->Items[i];\r
3619                 PackAddIntEx(p, "Key", item->Key, i, e->NumItem);\r
3620                 PackAddUniStrEx(p, "SubjectName", item->SubjectName, i, e->NumItem);\r
3621                 PackAddUniStrEx(p, "IssuerName", item->IssuerName, i, e->NumItem);\r
3622                 PackAddInt64Ex(p, "Expires", item->Expires, i, e->NumItem);\r
3623         }\r
3624 }\r
3625 \r
3626 // RPC_GET_ISSUER\r
3627 void InRpcGetIssuer(RPC_GET_ISSUER *c, PACK *p)\r
3628 {\r
3629         BUF *b;\r
3630         // 引数チェック\r
3631         if (c == NULL || p == NULL)\r
3632         {\r
3633                 return;\r
3634         }\r
3635 \r
3636         Zero(c, sizeof(RPC_GET_ISSUER));\r
3637         b = PackGetBuf(p, "x");\r
3638         if (b != NULL)\r
3639         {\r
3640                 if (c->x != NULL)\r
3641                 {\r
3642                         FreeX(c->x);\r
3643                 }\r
3644                 c->x = BufToX(b, false);\r
3645                 FreeBuf(b);\r
3646         }\r
3647 \r
3648         b = PackGetBuf(p, "issuer_x");\r
3649         if (b != NULL)\r
3650         {\r
3651                 c->issuer_x = BufToX(b, false);\r
3652                 FreeBuf(b);\r
3653         }\r
3654 }\r
3655 void OutRpcGetIssuer(PACK *p, RPC_GET_ISSUER *c)\r
3656 {\r
3657         BUF *b;\r
3658         // 引数チェック\r
3659         if (p == NULL || c == NULL)\r
3660         {\r
3661                 return;\r
3662         }\r
3663 \r
3664         if (c->x != NULL)\r
3665         {\r
3666                 b = XToBuf(c->x, false);\r
3667 \r
3668                 PackAddBuf(p, "x", b);\r
3669                 FreeBuf(b);\r
3670         }\r
3671 \r
3672         if (c->issuer_x != NULL)\r
3673         {\r
3674                 b = XToBuf(c->issuer_x, false);\r
3675 \r
3676                 PackAddBuf(p, "issuer_x", b);\r
3677                 FreeBuf(b);\r
3678         }\r
3679 }\r
3680 \r
3681 // TRAFFIC_EX\r
3682 void InRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i)\r
3683 {\r
3684         // 引数チェック\r
3685         if (t == NULL || p == NULL)\r
3686         {\r
3687                 return;\r
3688         }\r
3689 \r
3690         Zero(t, sizeof(TRAFFIC));\r
3691         t->Recv.BroadcastBytes = PackGetInt64Ex(p, "Ex.Recv.BroadcastBytes", i);\r
3692         t->Recv.BroadcastCount = PackGetInt64Ex(p, "Ex.Recv.BroadcastCount", i);\r
3693         t->Recv.UnicastBytes = PackGetInt64Ex(p, "Ex.Recv.UnicastBytes", i);\r
3694         t->Recv.UnicastCount = PackGetInt64Ex(p, "Ex.Recv.UnicastCount", i);\r
3695         t->Send.BroadcastBytes = PackGetInt64Ex(p, "Ex.Send.BroadcastBytes", i);\r
3696         t->Send.BroadcastCount = PackGetInt64Ex(p, "Ex.Send.BroadcastCount", i);\r
3697         t->Send.UnicastBytes = PackGetInt64Ex(p, "Ex.Send.UnicastBytes", i);\r
3698         t->Send.UnicastCount = PackGetInt64Ex(p, "Ex.Send.UnicastCount", i);\r
3699 }\r
3700 void OutRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i, UINT num)\r
3701 {\r
3702         // 引数チェック\r
3703         if (t == NULL || p == NULL)\r
3704         {\r
3705                 return;\r
3706         }\r
3707 \r
3708         PackAddInt64Ex(p, "Ex.Recv.BroadcastBytes", t->Recv.BroadcastBytes, i, num);\r
3709         PackAddInt64Ex(p, "Ex.Recv.BroadcastCount", t->Recv.BroadcastCount, i, num);\r
3710         PackAddInt64Ex(p, "Ex.Recv.UnicastBytes", t->Recv.UnicastBytes, i, num);\r
3711         PackAddInt64Ex(p, "Ex.Recv.UnicastCount", t->Recv.UnicastCount, i, num);\r
3712         PackAddInt64Ex(p, "Ex.Send.BroadcastBytes", t->Send.BroadcastBytes, i, num);\r
3713         PackAddInt64Ex(p, "Ex.Send.BroadcastCount", t->Send.BroadcastCount, i, num);\r
3714         PackAddInt64Ex(p, "Ex.Send.UnicastBytes", t->Send.UnicastBytes, i, num);\r
3715         PackAddInt64Ex(p, "Ex.Send.UnicastCount", t->Send.UnicastCount, i, num);\r
3716 }\r
3717 \r
3718 // TRAFFIC\r
3719 void InRpcTraffic(TRAFFIC *t, PACK *p)\r
3720 {\r
3721         // 引数チェック\r
3722         if (t == NULL || p == NULL)\r
3723         {\r
3724                 return;\r
3725         }\r
3726 \r
3727         Zero(t, sizeof(TRAFFIC));\r
3728         t->Recv.BroadcastBytes = PackGetInt64(p, "Recv.BroadcastBytes");\r
3729         t->Recv.BroadcastCount = PackGetInt64(p, "Recv.BroadcastCount");\r
3730         t->Recv.UnicastBytes = PackGetInt64(p, "Recv.UnicastBytes");\r
3731         t->Recv.UnicastCount = PackGetInt64(p, "Recv.UnicastCount");\r
3732         t->Send.BroadcastBytes = PackGetInt64(p, "Send.BroadcastBytes");\r
3733         t->Send.BroadcastCount = PackGetInt64(p, "Send.BroadcastCount");\r
3734         t->Send.UnicastBytes = PackGetInt64(p, "Send.UnicastBytes");\r
3735         t->Send.UnicastCount = PackGetInt64(p, "Send.UnicastCount");\r
3736 }\r
3737 void OutRpcTraffic(PACK *p, TRAFFIC *t)\r
3738 {\r
3739         // 引数チェック\r
3740         if (t == NULL || p == NULL)\r
3741         {\r
3742                 return;\r
3743         }\r
3744 \r
3745         PackAddInt64(p, "Recv.BroadcastBytes", t->Recv.BroadcastBytes);\r
3746         PackAddInt64(p, "Recv.BroadcastCount", t->Recv.BroadcastCount);\r
3747         PackAddInt64(p, "Recv.UnicastBytes", t->Recv.UnicastBytes);\r
3748         PackAddInt64(p, "Recv.UnicastCount", t->Recv.UnicastCount);\r
3749         PackAddInt64(p, "Send.BroadcastBytes", t->Send.BroadcastBytes);\r
3750         PackAddInt64(p, "Send.BroadcastCount", t->Send.BroadcastCount);\r
3751         PackAddInt64(p, "Send.UnicastBytes", t->Send.UnicastBytes);\r
3752         PackAddInt64(p, "Send.UnicastCount", t->Send.UnicastCount);\r
3753 }\r
3754 \r
3755 // RPC_CERT\r
3756 void InRpcCert(RPC_CERT *c, PACK *p)\r
3757 {\r
3758         BUF *b;\r
3759         // 引数チェック\r
3760         if (c == NULL || p == NULL)\r
3761         {\r
3762                 return;\r
3763         }\r
3764 \r
3765         Zero(c, sizeof(RPC_CERT));\r
3766         b = PackGetBuf(p, "x");\r
3767         if (b == NULL)\r
3768         {\r
3769                 return;\r
3770         }\r
3771 \r
3772         c->x = BufToX(b, false);\r
3773         FreeBuf(b);\r
3774 }\r
3775 void OutRpcCert(PACK *p, RPC_CERT *c)\r
3776 {\r
3777         BUF *b;\r
3778         // 引数チェック\r
3779         if (p == NULL || c == NULL)\r
3780         {\r
3781                 return;\r
3782         }\r
3783 \r
3784         if (c->x != NULL)\r
3785         {\r
3786                 b = XToBuf(c->x, false);\r
3787 \r
3788                 PackAddBuf(p, "x", b);\r
3789 \r
3790                 FreeBuf(b);\r
3791         }\r
3792 }\r
3793 \r
3794 // RPC_CLIENT_DELETE_CA\r
3795 void InRpcClientDeleteCa(RPC_CLIENT_DELETE_CA *c, PACK *p)\r
3796 {\r
3797         // 引数チェック\r
3798         if (c == NULL || p == NULL)\r
3799         {\r
3800                 return;\r
3801         }\r
3802 \r
3803         Zero(c, sizeof(RPC_CLIENT_DELETE_CA));\r
3804         c->Key = PackGetInt(p, "Key");\r
3805 }\r
3806 void OutRpcClientDeleteCa(PACK *p, RPC_CLIENT_DELETE_CA *c)\r
3807 {\r
3808         // 引数チェック\r
3809         if (c == NULL || p == NULL)\r
3810         {\r
3811                 return;\r
3812         }\r
3813 \r
3814         PackAddInt(p, "Key", c->Key);\r
3815 }\r
3816 \r
3817 // RPC_GET_CA\r
3818 void InRpcGetCa(RPC_GET_CA *c, PACK *p)\r
3819 {\r
3820         BUF *b;\r
3821         // 引数チェック\r
3822         if (c == NULL || p == NULL)\r
3823         {\r
3824                 return;\r
3825         }\r
3826 \r
3827         Zero(c, sizeof(RPC_GET_CA));\r
3828 \r
3829         c->Key = PackGetInt(p, "Key");\r
3830 \r
3831         b = PackGetBuf(p, "x");\r
3832         if (b != NULL)\r
3833         {\r
3834                 c->x = BufToX(b, false);\r
3835 \r
3836                 FreeBuf(b);\r
3837         }\r
3838 }\r
3839 void OutRpcGetCa(PACK *p, RPC_GET_CA *c)\r
3840 {\r
3841         // 引数チェック\r
3842         if (c == NULL || p == NULL)\r
3843         {\r
3844                 return;\r
3845         }\r
3846 \r
3847         PackAddInt(p, "Key", c->Key);\r
3848 \r
3849         if (c->x != NULL)\r
3850         {\r
3851                 BUF *b = XToBuf(c->x, false);\r
3852 \r
3853                 PackAddBuf(p, "x", b);\r
3854 \r
3855                 FreeBuf(b);\r
3856         }\r
3857 }\r
3858 \r
3859 // RPC_CLIENT_ENUM_SECURE\r
3860 void InRpcClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e, PACK *p)\r
3861 {\r
3862         UINT i;\r
3863         // 引数チェック\r
3864         if (e == NULL || p == NULL)\r
3865         {\r
3866                 return;\r
3867         }\r
3868 \r
3869         Zero(e, sizeof(RPC_CLIENT_ENUM_SECURE));\r
3870 \r
3871         e->NumItem = PackGetNum(p, "NumItem");\r
3872         e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);\r
3873         for (i = 0;i < e->NumItem;i++)\r
3874         {\r
3875                 RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));\r
3876 \r
3877                 item->DeviceId = PackGetIntEx(p, "DeviceId", i);\r
3878                 item->Type = PackGetIntEx(p, "Type", i);\r
3879                 PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);\r
3880                 PackGetStrEx(p, "Manufacturer", item->Manufacturer, sizeof(item->Manufacturer), i);\r
3881         }\r
3882 }\r
3883 void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e)\r
3884 {\r
3885         UINT i;\r
3886         // 引数チェック\r
3887         if (e == NULL || p == NULL)\r
3888         {\r
3889                 return;\r
3890         }\r
3891 \r
3892         PackAddNum(p, "NumItem", e->NumItem);\r
3893 \r
3894         for (i = 0;i < e->NumItem;i++)\r
3895         {\r
3896                 RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i];\r
3897 \r
3898                 PackAddIntEx(p, "DeviceId", item->DeviceId, i, e->NumItem);\r
3899                 PackAddIntEx(p, "Type", item->Type, i, e->NumItem);\r
3900                 PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);\r
3901                 PackAddStrEx(p, "Manufacturer", item->Manufacturer, i, e->NumItem);\r
3902         }\r
3903 }\r
3904 \r
3905 // RPC_USE_SECURE\r
3906 void InRpcUseSecure(RPC_USE_SECURE *u, PACK *p)\r
3907 {\r
3908         // 引数チェック\r
3909         if (u == NULL || p == NULL)\r
3910         {\r
3911                 return;\r
3912         }\r
3913 \r
3914         Zero(u, sizeof(RPC_USE_SECURE));\r
3915         u->DeviceId = PackGetInt(p, "DeviceId");\r
3916 }\r
3917 void OutRpcUseSecure(PACK *p, RPC_USE_SECURE *u)\r
3918 {\r
3919         // 引数チェック\r
3920         if (u == NULL || p == NULL)\r
3921         {\r
3922                 return;\r
3923         }\r
3924 \r
3925         PackAddInt(p, "DeviceId", u->DeviceId);\r
3926 }\r
3927 \r
3928 // RPC_ENUM_OBJECT_IN_SECURE の解放\r
3929 void CiFreeEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *a)\r
3930 {\r
3931         UINT i;\r
3932         // 引数チェック\r
3933         if (a == NULL)\r
3934         {\r
3935                 return;\r
3936         }\r
3937 \r
3938         for (i = 0;i < a->NumItem;i++)\r
3939         {\r
3940                 Free(a->ItemName[i]);\r
3941         }\r
3942         Free(a->ItemName);\r
3943         Free(a->ItemType);\r
3944 }\r
3945 \r
3946 // RPC_ENUM_OBJECT_IN_SECURE\r
3947 void InRpcEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *e, PACK *p)\r
3948 {\r
3949         UINT i;\r
3950         // 引数チェック\r
3951         if (e == NULL || p == NULL)\r
3952         {\r
3953                 return;\r
3954         }\r
3955 \r
3956         Zero(e, sizeof(RPC_ENUM_OBJECT_IN_SECURE));\r
3957 \r
3958         e->NumItem = PackGetNum(p, "NumItem");\r
3959         e->hWnd = PackGetInt(p, "hWnd");\r
3960         e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);\r
3961         e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);\r
3962 \r
3963         for (i = 0;i < e->NumItem;i++)\r
3964         {\r
3965                 char name[MAX_SIZE];\r
3966 \r
3967                 Zero(name, sizeof(name));\r
3968                 PackGetStrEx(p, "ItemName", name, sizeof(name), i);\r
3969                 e->ItemName[i] = CopyStr(name);\r
3970 \r
3971                 e->ItemType[i] = PackGetIntEx(p, "ItemType", i) ? true : false;\r
3972         }\r
3973 }\r
3974 void OutRpcEnumObjectInSecure(PACK *p, RPC_ENUM_OBJECT_IN_SECURE *e)\r
3975 {\r
3976         UINT i;\r
3977         // 引数チェック\r
3978         if (e == NULL || p == NULL)\r
3979         {\r
3980                 return;\r
3981         }\r
3982 \r
3983         PackAddNum(p, "NumItem", e->NumItem);\r
3984         PackAddInt(p, "hWnd", e->hWnd);\r
3985 \r
3986         for (i = 0;i < e->NumItem;i++)\r
3987         {\r
3988                 PackAddStrEx(p, "ItemName", e->ItemName[i], i, e->NumItem);\r
3989                 PackAddIntEx(p, "ItemType", e->ItemType[i], i, e->NumItem);\r
3990         }\r
3991 }\r
3992 \r
3993 // RPC_CLIENT_CREATE_VLAN\r
3994 void InRpcCreateVLan(RPC_CLIENT_CREATE_VLAN *v, PACK *p)\r
3995 {\r
3996         // 引数チェック\r
3997         if (v == NULL || p == NULL)\r
3998         {\r
3999                 return;\r
4000         }\r
4001 \r
4002         Zero(v, sizeof(RPC_CLIENT_CREATE_VLAN));\r
4003         PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));\r
4004 }\r
4005 void OutRpcCreateVLan(PACK *p, RPC_CLIENT_CREATE_VLAN *v)\r
4006 {\r
4007         // 引数チェック\r
4008         if (v == NULL || p == NULL)\r
4009         {\r
4010                 return;\r
4011         }\r
4012 \r
4013         PackAddStr(p, "DeviceName", v->DeviceName);\r
4014 }\r
4015 \r
4016 // RPC_CLIENT_GET_VLAN\r
4017 void InRpcClientGetVLan(RPC_CLIENT_GET_VLAN *v, PACK *p)\r
4018 {\r
4019         // 引数チェック\r
4020         if (v == NULL || p == NULL)\r
4021         {\r
4022                 return;\r
4023         }\r
4024 \r
4025         Zero(v, sizeof(RPC_CLIENT_GET_VLAN));\r
4026         PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));\r
4027         v->Enabled = PackGetInt(p, "Enabled") ? true : false;\r
4028         PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));\r
4029         PackGetStr(p, "Version", v->Version, sizeof(v->Version));\r
4030         PackGetStr(p, "FileName", v->FileName, sizeof(v->FileName));\r
4031         PackGetStr(p, "Guid", v->Guid, sizeof(v->Guid));\r
4032 }\r
4033 void OutRpcClientGetVLan(PACK *p, RPC_CLIENT_GET_VLAN *v)\r
4034 {\r
4035         // 引数チェック\r
4036         if (v == NULL || p == NULL)\r
4037         {\r
4038                 return;\r
4039         }\r
4040 \r
4041         PackAddStr(p, "DeviceName", v->DeviceName);\r
4042         PackAddInt(p, "Enabled", v->Enabled);\r
4043         PackAddStr(p, "MacAddress", v->MacAddress);\r
4044         PackAddStr(p, "Version", v->Version);\r
4045         PackAddStr(p, "FileName", v->FileName);\r
4046         PackAddStr(p, "Guid", v->Guid);\r
4047 }\r
4048 \r
4049 // RPC_CLIENT_SET_VLAN\r
4050 void InRpcClientSetVLan(RPC_CLIENT_SET_VLAN *v, PACK *p)\r
4051 {\r
4052         // 引数チェック\r
4053         if (v == NULL || p == NULL)\r
4054         {\r
4055                 return;\r
4056         }\r
4057 \r
4058         Zero(v, sizeof(RPC_CLIENT_SET_VLAN));\r
4059         PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));\r
4060         PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));\r
4061 }\r
4062 void OutRpcClientSetVLan(PACK *p, RPC_CLIENT_SET_VLAN *v)\r
4063 {\r
4064         // 引数チェック\r
4065         if (v == NULL || p == NULL)\r
4066         {\r
4067                 return;\r
4068         }\r
4069 \r
4070         PackAddStr(p, "DeviceName", v->DeviceName);\r
4071         PackAddStr(p, "MacAddress", v->MacAddress);\r
4072 }\r
4073 \r
4074 // RPC_CLIENT_ENUM_VLAN\r
4075 void InRpcClientEnumVLan(RPC_CLIENT_ENUM_VLAN *v, PACK *p)\r
4076 {\r
4077         UINT i;\r
4078         // 引数チェック\r
4079         if (v == NULL || p == NULL)\r
4080         {\r
4081                 return;\r
4082         }\r
4083 \r
4084         Zero(v, sizeof(RPC_CLIENT_ENUM_VLAN));\r
4085         v->NumItem = PackGetNum(p, "NumItem");\r
4086         v->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * v->NumItem);\r
4087 \r
4088         for (i = 0;i < v->NumItem;i++)\r
4089         {\r
4090                 RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i] =\r
4091                         ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));\r
4092 \r
4093                 PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);\r
4094                 item->Enabled = PackGetIntEx(p, "Enabled", i) ? true : false;\r
4095                 PackGetStrEx(p, "MacAddress", item->MacAddress, sizeof(item->MacAddress), i);\r
4096                 PackGetStrEx(p, "Version", item->Version, sizeof(item->Version), i);\r
4097         }\r
4098 }\r
4099 void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v)\r
4100 {\r
4101         UINT i;\r
4102         // 引数チェック\r
4103         if (v == NULL || p == NULL)\r
4104         {\r
4105                 return;\r
4106         }\r
4107 \r
4108         PackAddNum(p, "NumItem", v->NumItem);\r
4109 \r
4110         for (i = 0;i < v->NumItem;i++)\r
4111         {\r
4112                 RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i];\r
4113 \r
4114                 PackAddStrEx(p, "DeviceName", item->DeviceName, i, v->NumItem);\r
4115                 PackAddIntEx(p, "Enabled", item->Enabled, i, v->NumItem);\r
4116                 PackAddStrEx(p, "MacAddress", item->MacAddress, i, v->NumItem);\r
4117                 PackAddStrEx(p, "Version", item->Version, i, v->NumItem);\r
4118         }\r
4119 }\r
4120 \r
4121 // CLIENT_OPTION\r
4122 void InRpcClientOption(CLIENT_OPTION *c, PACK *p)\r
4123 {\r
4124         // 引数チェック\r
4125         if (c == NULL || p == NULL)\r
4126         {\r
4127                 return;\r
4128         }\r
4129 \r
4130         Zero(c, sizeof(CLIENT_OPTION));\r
4131 \r
4132         PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));\r
4133         PackGetStr(p, "Hostname", c->Hostname, sizeof(c->Hostname));\r
4134         c->Port = PackGetInt(p, "Port");\r
4135         c->PortUDP = PackGetInt(p, "PortUDP");\r
4136         c->ProxyType = PackGetInt(p, "ProxyType");\r
4137         c->ProxyPort = PackGetInt(p, "ProxyPort");\r
4138         c->NumRetry = PackGetInt(p, "NumRetry");\r
4139         c->RetryInterval = PackGetInt(p, "RetryInterval");\r
4140         c->MaxConnection = PackGetInt(p, "MaxConnection");\r
4141         c->AdditionalConnectionInterval = PackGetInt(p, "AdditionalConnectionInterval");\r
4142         c->ConnectionDisconnectSpan = PackGetInt(p, "ConnectionDisconnectSpan");\r
4143         c->HideStatusWindow = PackGetBool(p, "HideStatusWindow");\r
4144         c->HideNicInfoWindow = PackGetBool(p, "HideNicInfoWindow");\r
4145         c->DisableQoS = PackGetBool(p, "DisableQoS");\r
4146         PackGetStr(p, "ProxyName", c->ProxyName, sizeof(c->ProxyName));\r
4147         PackGetStr(p, "ProxyUsername", c->ProxyUsername, sizeof(c->ProxyUsername));\r
4148         PackGetStr(p, "ProxyPassword", c->ProxyPassword, sizeof(c->ProxyPassword));\r
4149         PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName));\r
4150         PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName));\r
4151         c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;\r
4152         c->UseCompress = PackGetInt(p, "UseCompress") ? true : false;\r
4153         c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;\r
4154         c->NoRoutingTracking = PackGetInt(p, "NoRoutingTracking") ? true : false;\r
4155         c->RequireMonitorMode = PackGetBool(p, "RequireMonitorMode");\r
4156         c->RequireBridgeRoutingMode = PackGetBool(p, "RequireBridgeRoutingMode");\r
4157         c->FromAdminPack = PackGetBool(p, "FromAdminPack");\r
4158         c->NoTls1 = PackGetBool(p, "NoTls1");\r
4159 }\r
4160 void OutRpcClientOption(PACK *p, CLIENT_OPTION *c)\r
4161 {\r
4162         // 引数チェック\r
4163         if (c == NULL || p == NULL)\r
4164         {\r
4165                 return;\r
4166         }\r
4167 \r
4168         PackAddUniStr(p, "AccountName", c->AccountName);\r
4169         PackAddStr(p, "Hostname", c->Hostname);\r
4170         PackAddStr(p, "ProxyName", c->ProxyName);\r
4171         PackAddStr(p, "ProxyUsername", c->ProxyUsername);\r
4172         PackAddStr(p, "ProxyPassword", c->ProxyPassword);\r
4173         PackAddStr(p, "HubName", c->HubName);\r
4174         PackAddStr(p, "DeviceName", c->DeviceName);\r
4175         PackAddInt(p, "Port", c->Port);\r
4176         PackAddInt(p, "PortUDP", c->PortUDP);\r
4177         PackAddInt(p, "ProxyType", c->ProxyType);\r
4178         PackAddInt(p, "ProxyPort", c->ProxyPort);\r
4179         PackAddInt(p, "NumRetry", c->NumRetry);\r
4180         PackAddInt(p, "RetryInterval", c->RetryInterval);\r
4181         PackAddInt(p, "MaxConnection", c->MaxConnection);\r
4182         PackAddInt(p, "UseEncrypt", c->UseEncrypt);\r
4183         PackAddInt(p, "UseCompress", c->UseCompress);\r
4184         PackAddInt(p, "HalfConnection", c->HalfConnection);\r
4185         PackAddInt(p, "NoRoutingTracking", c->NoRoutingTracking);\r
4186         PackAddInt(p, "AdditionalConnectionInterval", c->AdditionalConnectionInterval);\r
4187         PackAddInt(p, "ConnectionDisconnectSpan", c->ConnectionDisconnectSpan);\r
4188         PackAddBool(p, "HideStatusWindow", c->HideStatusWindow);\r
4189         PackAddBool(p, "HideNicInfoWindow", c->HideNicInfoWindow);\r
4190         PackAddBool(p, "RequireMonitorMode", c->RequireMonitorMode);\r
4191         PackAddBool(p, "RequireBridgeRoutingMode", c->RequireBridgeRoutingMode);\r
4192         PackAddBool(p, "DisableQoS", c->DisableQoS);\r
4193         PackAddBool(p, "FromAdminPack", c->FromAdminPack);\r
4194         PackAddBool(p, "NoTls1", c->NoTls1);\r
4195 }\r
4196 \r
4197 // CLIENT_AUTH\r
4198 void InRpcClientAuth(CLIENT_AUTH *c, PACK *p)\r
4199 {\r
4200         BUF *b;\r
4201         // 引数チェック\r
4202         if (c == NULL || p == NULL)\r
4203         {\r
4204                 return;\r
4205         }\r
4206 \r
4207         Zero(c, sizeof(CLIENT_AUTH));\r
4208         c->AuthType = PackGetInt(p, "AuthType");\r
4209         PackGetStr(p, "Username", c->Username, sizeof(c->Username));\r
4210 \r
4211         switch (c->AuthType)\r
4212         {\r
4213         case CLIENT_AUTHTYPE_ANONYMOUS:\r
4214                 break;\r
4215 \r
4216         case CLIENT_AUTHTYPE_PASSWORD:\r
4217                 if (PackGetDataSize(p, "HashedPassword") == SHA1_SIZE)\r
4218                 {\r
4219                         PackGetData(p, "HashedPassword", c->HashedPassword);\r
4220                 }\r
4221                 break;\r
4222 \r
4223         case CLIENT_AUTHTYPE_PLAIN_PASSWORD:\r
4224                 PackGetStr(p, "PlainPassword", c->PlainPassword, sizeof(c->PlainPassword));\r
4225                 break;\r
4226 \r
4227         case CLIENT_AUTHTYPE_CERT:\r
4228                 b = PackGetBuf(p, "ClientX");\r
4229                 if (b != NULL)\r
4230                 {\r
4231                         c->ClientX = BufToX(b, false);\r
4232                         FreeBuf(b);\r
4233                 }\r
4234                 b = PackGetBuf(p, "ClientK");\r
4235                 if (b != NULL)\r
4236                 {\r
4237                         c->ClientK = BufToK(b, true, false, NULL);\r
4238                         FreeBuf(b);\r
4239                 }\r
4240                 break;\r
4241 \r
4242         case CLIENT_AUTHTYPE_SECURE:\r
4243                 PackGetStr(p, "SecurePublicCertName", c->SecurePublicCertName, sizeof(c->SecurePublicCertName));\r
4244                 PackGetStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName, sizeof(c->SecurePrivateKeyName));\r
4245                 break;\r
4246         }\r
4247 }\r
4248 void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c)\r
4249 {\r
4250         BUF *b;\r
4251         // 引数チェック\r
4252         if (c == NULL || p == NULL)\r
4253         {\r
4254                 return;\r
4255         }\r
4256 \r
4257         PackAddInt(p, "AuthType", c->AuthType);\r
4258         PackAddStr(p, "Username", c->Username);\r
4259 \r
4260         switch (c->AuthType)\r
4261         {\r
4262         case CLIENT_AUTHTYPE_ANONYMOUS:\r
4263                 break;\r
4264 \r
4265         case CLIENT_AUTHTYPE_PASSWORD:\r
4266                 PackAddData(p, "HashedPassword", c->HashedPassword, SHA1_SIZE);\r
4267                 break;\r
4268 \r
4269         case CLIENT_AUTHTYPE_PLAIN_PASSWORD:\r
4270                 PackAddStr(p, "PlainPassword", c->PlainPassword);\r
4271                 break;\r
4272 \r
4273         case CLIENT_AUTHTYPE_CERT:\r
4274                 b = XToBuf(c->ClientX, false);\r
4275                 if (b != NULL)\r
4276                 {\r
4277                         PackAddBuf(p, "ClientX", b);\r
4278                         FreeBuf(b);\r
4279                 }\r
4280                 b = KToBuf(c->ClientK, false, NULL);\r
4281                 if (b != NULL)\r
4282                 {\r
4283                         PackAddBuf(p, "ClientK", b);\r
4284                         FreeBuf(b);\r
4285                 }\r
4286                 break;\r
4287 \r
4288         case CLIENT_AUTHTYPE_SECURE:\r
4289                 PackAddStr(p, "SecurePublicCertName", c->SecurePublicCertName);\r
4290                 PackAddStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName);\r
4291                 break;\r
4292         }\r
4293 }\r
4294 \r
4295 // RPC_CLIENT_CREATE_ACCOUNT\r
4296 void InRpcClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *c, PACK *p)\r
4297 {\r
4298         BUF *b;\r
4299         // 引数チェック\r
4300         if (c == NULL || p == NULL)\r
4301         {\r
4302                 return;\r
4303         }\r
4304 \r
4305         Zero(c, sizeof(RPC_CLIENT_CREATE_ACCOUNT));\r
4306         c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
4307         c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
4308 \r
4309         InRpcClientOption(c->ClientOption, p);\r
4310         InRpcClientAuth(c->ClientAuth, p);\r
4311 \r
4312         c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;\r
4313         c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;\r
4314         b = PackGetBuf(p, "ServerCert");\r
4315         if (b != NULL)\r
4316         {\r
4317                 c->ServerCert = BufToX(b, false);\r
4318                 FreeBuf(b);\r
4319         }\r
4320         PackGetData2(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));\r
4321 }\r
4322 void OutRpcClientCreateAccount(PACK *p, RPC_CLIENT_CREATE_ACCOUNT *c)\r
4323 {\r
4324         BUF *b;\r
4325         // 引数チェック\r
4326         if (c == NULL || p == NULL)\r
4327         {\r
4328                 return;\r
4329         }\r
4330 \r
4331         OutRpcClientOption(p, c->ClientOption);\r
4332         OutRpcClientAuth(p, c->ClientAuth);\r
4333 \r
4334         PackAddInt(p, "StartupAccount", c->StartupAccount);\r
4335         PackAddInt(p, "CheckServerCert", c->CheckServerCert);\r
4336         if (c->ServerCert != NULL)\r
4337         {\r
4338                 b = XToBuf(c->ServerCert, false);\r
4339                 if (b != NULL)\r
4340                 {\r
4341                         PackAddBuf(p, "ServerCert", b);\r
4342                         FreeBuf(b);\r
4343                 }\r
4344         }\r
4345         PackAddData(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));\r
4346 }\r
4347 \r
4348 // RPC_CLIENT_ENUM_ACCOUNT\r
4349 void InRpcClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *e, PACK *p)\r
4350 {\r
4351         UINT i;\r
4352         // 引数チェック\r
4353         if (e == NULL || p == NULL)\r
4354         {\r
4355                 return;\r
4356         }\r
4357 \r
4358         Zero(e, sizeof(RPC_CLIENT_ENUM_ACCOUNT));\r
4359 \r
4360         e->NumItem = PackGetNum(p, "NumItem");\r
4361         e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);\r
4362 \r
4363         for (i = 0;i < e->NumItem;i++)\r
4364         {\r
4365                 RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i] =\r
4366                         ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));\r
4367 \r
4368                 PackGetUniStrEx(p, "AccountName", item->AccountName, sizeof(item->AccountName), i);\r
4369                 PackGetStrEx(p, "UserName", item->UserName, sizeof(item->UserName), i);\r
4370                 PackGetStrEx(p, "ServerName", item->ServerName, sizeof(item->ServerName), i);\r
4371                 PackGetStrEx(p, "ProxyName", item->ProxyName, sizeof(item->ProxyName), i);\r
4372                 PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);\r
4373                 item->ProxyType = PackGetIntEx(p, "ProxyType", i);\r
4374                 item->Active = PackGetIntEx(p, "Active", i) ? true : false;\r
4375                 item->StartupAccount = PackGetIntEx(p, "StartupAccount", i) ? true : false;\r
4376                 item->Connected = PackGetBoolEx(p, "Connected", i);\r
4377                 item->Port = PackGetIntEx(p, "Port", i);\r
4378                 PackGetStrEx(p, "HubName", item->HubName, sizeof(item->HubName), i);\r
4379                 item->CreateDateTime = PackGetInt64Ex(p, "CreateDateTime", i);\r
4380                 item->UpdateDateTime = PackGetInt64Ex(p, "UpdateDateTime", i);\r
4381                 item->LastConnectDateTime = PackGetInt64Ex(p, "LastConnectDateTime", i);\r
4382         }\r
4383 }\r
4384 void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e)\r
4385 {\r
4386         UINT i;\r
4387         // 引数チェック\r
4388         if (e == NULL || p == NULL)\r
4389         {\r
4390                 return;\r
4391         }\r
4392 \r
4393         PackAddNum(p, "NumItem", e->NumItem);\r
4394 \r
4395         for (i = 0;i < e->NumItem;i++)\r
4396         {\r
4397                 RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i];\r
4398 \r
4399                 PackAddUniStrEx(p, "AccountName", item->AccountName, i, e->NumItem);\r
4400                 PackAddStrEx(p, "UserName", item->UserName, i, e->NumItem);\r
4401                 PackAddStrEx(p, "ServerName", item->ServerName, i, e->NumItem);\r
4402                 PackAddStrEx(p, "ProxyName", item->ProxyName, i, e->NumItem);\r
4403                 PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);\r
4404                 PackAddIntEx(p, "ProxyType", item->ProxyType, i, e->NumItem);\r
4405                 PackAddIntEx(p, "Active", item->Active, i, e->NumItem);\r
4406                 PackAddIntEx(p, "StartupAccount", item->StartupAccount, i, e->NumItem);\r
4407                 PackAddBoolEx(p, "Connected", item->Connected, i, e->NumItem);\r
4408                 PackAddIntEx(p, "Port", item->Port, i, e->NumItem);\r
4409                 PackAddStrEx(p, "HubName", item->HubName, i, e->NumItem);\r
4410                 PackAddInt64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);\r
4411                 PackAddInt64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);\r
4412                 PackAddInt64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);\r
4413         }\r
4414 }\r
4415 \r
4416 // RPC_CLIENT_DELETE_ACCOUNT\r
4417 void InRpcClientDeleteAccount(RPC_CLIENT_DELETE_ACCOUNT *a, PACK *p)\r
4418 {\r
4419         // 引数チェック\r
4420         if (a == NULL || p == NULL)\r
4421         {\r
4422                 return;\r
4423         }\r
4424 \r
4425         Zero(a, sizeof(RPC_CLIENT_DELETE_ACCOUNT));\r
4426         PackGetUniStr(p, "AccountName", a->AccountName, sizeof(a->AccountName));\r
4427 }\r
4428 void OutRpcClientDeleteAccount(PACK *p, RPC_CLIENT_DELETE_ACCOUNT *a)\r
4429 {\r
4430         // 引数チェック\r
4431         if (a == NULL || p == NULL)\r
4432         {\r
4433                 return;\r
4434         }\r
4435 \r
4436         PackAddUniStr(p, "AccountName", a->AccountName);\r
4437 }\r
4438 \r
4439 // RPC_RENAME_ACCOUNT\r
4440 void InRpcRenameAccount(RPC_RENAME_ACCOUNT *a, PACK *p)\r
4441 {\r
4442         // 引数チェック\r
4443         if (a == NULL || p == NULL)\r
4444         {\r
4445                 return;\r
4446         }\r
4447 \r
4448         Zero(a, sizeof(RPC_RENAME_ACCOUNT));\r
4449 \r
4450         PackGetUniStr(p, "OldName", a->OldName, sizeof(a->OldName));\r
4451         PackGetUniStr(p, "NewName", a->NewName, sizeof(a->NewName));\r
4452 }\r
4453 void OutRpcRenameAccount(PACK *p, RPC_RENAME_ACCOUNT *a)\r
4454 {\r
4455         // 引数チェック\r
4456         if (a == NULL || p == NULL)\r
4457         {\r
4458                 return;\r
4459         }\r
4460 \r
4461         PackAddUniStr(p, "OldName", a->OldName);\r
4462         PackAddUniStr(p, "NewName", a->NewName);\r
4463 }\r
4464 \r
4465 // RPC_CLIENT_GET_ACCOUNT\r
4466 void InRpcClientGetAccount(RPC_CLIENT_GET_ACCOUNT *c, PACK *p)\r
4467 {\r
4468         BUF *b;\r
4469         // 引数チェック\r
4470         if (c == NULL || p == NULL)\r
4471         {\r
4472                 return;\r
4473         }\r
4474 \r
4475         Zero(c, sizeof(RPC_CLIENT_GET_ACCOUNT));\r
4476 \r
4477         c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
4478         c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
4479 \r
4480         PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));\r
4481         c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;\r
4482         c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;\r
4483         b = PackGetBuf(p, "ServerCert");\r
4484         if (b != NULL)\r
4485         {\r
4486                 c->ServerCert = BufToX(b, false);\r
4487                 FreeBuf(b);\r
4488         }\r
4489 \r
4490         InRpcClientOption(c->ClientOption, p);\r
4491         InRpcClientAuth(c->ClientAuth, p);\r
4492 \r
4493         c->CreateDateTime = PackGetInt64(p, "CreateDateTime");\r
4494         c->UpdateDateTime = PackGetInt64(p, "UpdateDateTime");\r
4495         c->LastConnectDateTime = PackGetInt64(p, "LastConnectDateTime");\r
4496 \r
4497         PackGetData2(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);\r
4498 }\r
4499 void OutRpcClientGetAccount(PACK *p, RPC_CLIENT_GET_ACCOUNT *c)\r
4500 {\r
4501         BUF *b;\r
4502         // 引数チェック\r
4503         if (c == NULL || p == NULL)\r
4504         {\r
4505                 return;\r
4506         }\r
4507 \r
4508         PackAddUniStr(p, "AccountName", c->AccountName);\r
4509         PackAddInt(p, "StartupAccount", c->StartupAccount);\r
4510         PackAddInt(p, "CheckServerCert", c->CheckServerCert);\r
4511 \r
4512         if (c->ServerCert != NULL)\r
4513         {\r
4514                 b = XToBuf(c->ServerCert, false);\r
4515                 if (b != NULL)\r
4516                 {\r
4517                         PackAddBuf(p, "ServerCert", b);\r
4518                         FreeBuf(b);\r
4519                 }\r
4520         }\r
4521 \r
4522         OutRpcClientOption(p, c->ClientOption);\r
4523         OutRpcClientAuth(p, c->ClientAuth);\r
4524 \r
4525         PackAddData(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);\r
4526 \r
4527         PackAddInt64(p, "CreateDateTime", c->CreateDateTime);\r
4528         PackAddInt64(p, "UpdateDateTime", c->UpdateDateTime);\r
4529         PackAddInt64(p, "LastConnectDateTime", c->LastConnectDateTime);\r
4530 }\r
4531 \r
4532 // RPC_CLIENT_CONNECT\r
4533 void InRpcClientConnect(RPC_CLIENT_CONNECT *c, PACK *p)\r
4534 {\r
4535         // 引数チェック\r
4536         if (c == NULL || p == NULL)\r
4537         {\r
4538                 return;\r
4539         }\r
4540 \r
4541         Zero(c, sizeof(RPC_CLIENT_CONNECT));\r
4542 \r
4543         PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));\r
4544 }\r
4545 void OutRpcClientConnect(PACK *p, RPC_CLIENT_CONNECT *c)\r
4546 {\r
4547         // 引数チェック\r
4548         if (c == NULL || p == NULL)\r
4549         {\r
4550                 return;\r
4551         }\r
4552 \r
4553         PackAddUniStr(p, "AccountName", c->AccountName);\r
4554 }\r
4555 \r
4556 // POLICY\r
4557 void InRpcPolicy(POLICY *o, PACK *p)\r
4558 {\r
4559         POLICY *pol;\r
4560         // 引数チェック\r
4561         if (o == NULL || p == NULL)\r
4562         {\r
4563                 return;\r
4564         }\r
4565 \r
4566         pol = PackGetPolicy(p);\r
4567         Copy(o, pol, sizeof(POLICY));\r
4568         Free(pol);\r
4569 }\r
4570 void OutRpcPolicy(PACK *p, POLICY *o)\r
4571 {\r
4572         // 引数チェック\r
4573         if (o == NULL || p == NULL)\r
4574         {\r
4575                 return;\r
4576         }\r
4577 \r
4578         PackAddPolicy(p, o);\r
4579 }\r
4580 \r
4581 // RPC_CLIENT_GET_CONNECTION_STATUS\r
4582 void InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *s, PACK *p)\r
4583 {\r
4584         BUF *b;\r
4585         // 引数チェック\r
4586         if (s == NULL || p == NULL)\r
4587         {\r
4588                 return;\r
4589         }\r
4590 \r
4591         Zero(s, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));\r
4592 \r
4593         PackGetUniStr(p, "AccountName", s->AccountName, sizeof(s->AccountName));\r
4594 \r
4595         PackGetStr(p, "ServerName", s->ServerName, sizeof(s->ServerName));\r
4596         PackGetStr(p, "ServerProductName", s->ServerProductName, sizeof(s->ServerProductName));\r
4597         PackGetStr(p, "CipherName", s->CipherName, sizeof(s->CipherName));\r
4598         PackGetStr(p, "SessionName", s->SessionName, sizeof(s->SessionName));\r
4599         PackGetStr(p, "ConnectionName", s->ConnectionName, sizeof(s->ConnectionName));\r
4600 \r
4601         if (PackGetDataSize(p, "SessionKey") == SHA1_SIZE)\r
4602         {\r
4603                 PackGetData(p, "SessionKey", s->SessionKey);\r
4604         }\r
4605 \r
4606         s->SessionStatus = PackGetInt(p, "SessionStatus");\r
4607         s->ServerPort = PackGetInt(p, "ServerPort");\r
4608         s->ServerProductVer = PackGetInt(p, "ServerProductVer");\r
4609         s->ServerProductBuild = PackGetInt(p, "ServerProductBuild");\r
4610         s->NumConnectionsEatablished = PackGetInt(p, "NumConnectionsEatablished");\r
4611         s->MaxTcpConnections = PackGetInt(p, "MaxTcpConnections");\r
4612         s->NumTcpConnections = PackGetInt(p, "NumTcpConnections");\r
4613         s->NumTcpConnectionsUpload = PackGetInt(p, "NumTcpConnectionsUpload");\r
4614         s->NumTcpConnectionsDownload = PackGetInt(p, "NumTcpConnectionsDownload");\r
4615 \r
4616         s->StartTime = PackGetInt64(p, "StartTime");\r
4617         s->FirstConnectionEstablisiedTime = PackGetInt64(p, "FirstConnectionEstablisiedTime");\r
4618         s->CurrentConnectionEstablishTime = PackGetInt64(p, "CurrentConnectionEstablishTime");\r
4619         s->TotalSendSize = PackGetInt64(p, "TotalSendSize");\r
4620         s->TotalRecvSize = PackGetInt64(p, "TotalRecvSize");\r
4621         s->TotalSendSizeReal = PackGetInt64(p, "TotalSendSizeReal");\r
4622         s->TotalRecvSizeReal = PackGetInt64(p, "TotalRecvSizeReal");\r
4623 \r
4624         s->Active = PackGetInt(p, "Active") ? true : false;\r
4625         s->Connected = PackGetInt(p, "Connected") ? true : false;\r
4626         s->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;\r
4627         s->QoS = PackGetInt(p, "QoS") ? true : false;\r
4628         s->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;\r
4629         s->UseCompress = PackGetInt(p, "UseCompress") ? true : false;\r
4630 \r
4631         s->IsBridgeMode = PackGetBool(p, "IsBridgeMode");\r
4632         s->IsMonitorMode = PackGetBool(p, "IsMonitorMode");\r
4633 \r
4634         s->VLanId = PackGetInt(p, "VLanId");\r
4635 \r
4636         b = PackGetBuf(p, "ServerX");\r
4637         if (b != NULL)\r
4638         {\r
4639                 s->ServerX = BufToX(b, false);\r
4640                 FreeBuf(b);\r
4641         }\r
4642 \r
4643         b = PackGetBuf(p, "ClientX");\r
4644         if (b != NULL)\r
4645         {\r
4646                 s->ClientX = BufToX(b, false);\r
4647                 FreeBuf(b);\r
4648         }\r
4649 \r
4650         InRpcPolicy(&s->Policy, p);\r
4651 \r
4652         InRpcTraffic(&s->Traffic, p);\r
4653 }\r
4654 void OutRpcClientGetConnectionStatus(PACK *p, RPC_CLIENT_GET_CONNECTION_STATUS *c)\r
4655 {\r
4656         BUF *b;\r
4657         // 引数チェック\r
4658         if (p == NULL || c == NULL)\r
4659         {\r
4660                 return;\r
4661         }\r
4662 \r
4663         PackAddUniStr(p, "AccountName", c->AccountName);\r
4664 \r
4665         PackAddStr(p, "ServerName", c->ServerName);\r
4666         PackAddStr(p, "ServerProductName", c->ServerProductName);\r
4667         PackAddStr(p, "CipherName", c->CipherName);\r
4668         PackAddStr(p, "SessionName", c->SessionName);\r
4669         PackAddStr(p, "ConnectionName", c->ConnectionName);\r
4670 \r
4671         PackAddData(p, "SessionKey", c->SessionKey, SHA1_SIZE);\r
4672 \r
4673         PackAddInt(p, "Active", c->Active);\r
4674         PackAddInt(p, "Connected", c->Connected);\r
4675         PackAddInt(p, "SessionStatus", c->SessionStatus);\r
4676         PackAddInt(p, "ServerPort", c->ServerPort);\r
4677         PackAddInt(p, "ServerProductVer", c->ServerProductVer);\r
4678         PackAddInt(p, "ServerProductBuild", c->ServerProductBuild);\r
4679         PackAddInt(p, "NumConnectionsEatablished", c->NumConnectionsEatablished);\r
4680         PackAddInt(p, "HalfConnection", c->HalfConnection);\r
4681         PackAddInt(p, "QoS", c->QoS);\r
4682         PackAddInt(p, "MaxTcpConnections", c->MaxTcpConnections);\r
4683         PackAddInt(p, "NumTcpConnections", c->NumTcpConnections);\r
4684         PackAddInt(p, "NumTcpConnectionsUpload", c->NumTcpConnectionsUpload);\r
4685         PackAddInt(p, "NumTcpConnectionsDownload", c->NumTcpConnectionsDownload);\r
4686         PackAddInt(p, "UseEncrypt", c->UseEncrypt);\r
4687         PackAddInt(p, "UseCompress", c->UseCompress);\r
4688 \r
4689         PackAddBool(p, "IsBridgeMode", c->IsBridgeMode);\r
4690         PackAddBool(p, "IsMonitorMode", c->IsMonitorMode);\r
4691 \r
4692         PackAddInt64(p, "StartTime", c->StartTime);\r
4693         PackAddInt64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);\r
4694         PackAddInt64(p, "CurrentConnectionEstablishTime", c->CurrentConnectionEstablishTime);\r
4695         PackAddInt64(p, "TotalSendSize", c->TotalSendSize);\r
4696         PackAddInt64(p, "TotalRecvSize", c->TotalRecvSize);\r
4697         PackAddInt64(p, "TotalSendSizeReal", c->TotalSendSizeReal);\r
4698         PackAddInt64(p, "TotalRecvSizeReal", c->TotalRecvSizeReal);\r
4699 \r
4700         PackAddInt(p, "VLanId", c->VLanId);\r
4701 \r
4702         OutRpcPolicy(p, &c->Policy);\r
4703 \r
4704         OutRpcTraffic(p, &c->Traffic);\r
4705 \r
4706         if (c->ServerX != NULL)\r
4707         {\r
4708                 b = XToBuf(c->ServerX, false);\r
4709                 PackAddBuf(p, "ServerX", b);\r
4710                 FreeBuf(b);\r
4711         }\r
4712 \r
4713         if (c->ClientX != NULL)\r
4714         {\r
4715                 b = XToBuf(c->ClientX, false);\r
4716                 PackAddBuf(p, "ClientX", b);\r
4717                 FreeBuf(b);\r
4718         }\r
4719 }\r
4720 \r
4721 void InRpcClientNotify(RPC_CLIENT_NOTIFY *n, PACK *p)\r
4722 {\r
4723         // 引数チェック\r
4724         if (n == NULL || p == NULL)\r
4725         {\r
4726                 return;\r
4727         }\r
4728 \r
4729         Zero(n, sizeof(RPC_CLIENT_NOTIFY));\r
4730 \r
4731         n->NotifyCode = PackGetInt(p, "NotifyCode");\r
4732 }\r
4733 void OutRpcClientNotify(PACK *p, RPC_CLIENT_NOTIFY *n)\r
4734 {\r
4735         // 引数チェック\r
4736         if (n == NULL || p == NULL)\r
4737         {\r
4738                 return;\r
4739         }\r
4740 \r
4741         PackAddInt(p, "NotifyCode", n->NotifyCode);\r
4742 }\r
4743 \r
4744 // 通知メイン\r
4745 void CiNotifyMain(CLIENT *c, SOCK *s)\r
4746 {\r
4747         CANCEL *cancel;\r
4748         // 引数チェック\r
4749         if (c == NULL || s == NULL)\r
4750         {\r
4751                 return;\r
4752         }\r
4753 \r
4754         // キャンセルを登録\r
4755         cancel = NewCancel();\r
4756         LockList(c->NotifyCancelList);\r
4757         {\r
4758                 Add(c->NotifyCancelList, cancel);\r
4759         }\r
4760         UnlockList(c->NotifyCancelList);\r
4761 \r
4762         // 待機\r
4763         while (true)\r
4764         {\r
4765                 char ch = '@';\r
4766                 SOCKSET set;\r
4767                 InitSockSet(&set);\r
4768                 AddSockSet(&set, s);\r
4769                 Select(&set, INFINITE, cancel, NULL);\r
4770 \r
4771                 if (c->Halt)\r
4772                 {\r
4773                         // 強制終了\r
4774                         break;\r
4775                 }\r
4776 \r
4777                 // 1 バイト送信\r
4778                 if (Send(s, &ch, 1, false) == 0)\r
4779                 {\r
4780                         // 切断された\r
4781                         break;\r
4782                 }\r
4783         }\r
4784 \r
4785         // 切断\r
4786         Disconnect(s);\r
4787 \r
4788         // キャンセルを登録解除\r
4789         LockList(c->NotifyCancelList);\r
4790         {\r
4791                 Delete(c->NotifyCancelList, cancel);\r
4792         }\r
4793         UnlockList(c->NotifyCancelList);\r
4794 \r
4795         ReleaseCancel(cancel);\r
4796 }\r
4797 \r
4798 // RPC 受付コード\r
4799 void CiRpcAccepted(CLIENT *c, SOCK *s)\r
4800 {\r
4801         UCHAR hashed_password[SHA1_SIZE];\r
4802         UINT rpc_mode;\r
4803         UINT retcode;\r
4804         RPC *rpc;\r
4805         // 引数チェック\r
4806         if (c == NULL || s == NULL)\r
4807         {\r
4808                 return;\r
4809         }\r
4810 \r
4811         // RPC モード受信\r
4812         if (RecvAll(s, &rpc_mode, sizeof(UINT), false) == false)\r
4813         {\r
4814                 return;\r
4815         }\r
4816 \r
4817         rpc_mode = Endian32(rpc_mode);\r
4818 \r
4819         if (rpc_mode == CLIENT_RPC_MODE_NOTIFY)\r
4820         {\r
4821                 // 通知モード\r
4822                 CiNotifyMain(c, s);\r
4823                 return;\r
4824         }\r
4825         else if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT || rpc_mode == CLIENT_RPC_MODE_SHORTCUT_DISCONNECT)\r
4826         {\r
4827                 // ショートカットキー受信\r
4828                 UCHAR key[SHA1_SIZE];\r
4829                 UINT err = ERR_NO_ERROR;\r
4830                 if (RecvAll(s, key, SHA1_SIZE, false))\r
4831                 {\r
4832                         UINT i;\r
4833                         wchar_t title[MAX_ACCOUNT_NAME_LEN + 1];\r
4834                         bool ok = false;\r
4835                         // 指定された接続設定に接続する\r
4836                         LockList(c->AccountList);\r
4837                         {\r
4838                                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
4839                                 {\r
4840                                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
4841                                         Lock(a->lock);\r
4842                                         {\r
4843                                                 if (Cmp(a->ShortcutKey, key, SHA1_SIZE) == 0)\r
4844                                                 {\r
4845                                                         ok = true;\r
4846                                                         UniStrCpy(title, sizeof(title), a->ClientOption->AccountName);\r
4847                                                 }\r
4848                                         }\r
4849                                         Unlock(a->lock);\r
4850                                 }\r
4851                         }\r
4852                         UnlockList(c->AccountList);\r
4853 \r
4854                         if (ok == false)\r
4855                         {\r
4856                                 err = ERR_ACCOUNT_NOT_FOUND;\r
4857                         }\r
4858                         else\r
4859                         {\r
4860                                 RPC_CLIENT_CONNECT t;\r
4861                                 Zero(&t, sizeof(t));\r
4862                                 UniStrCpy(t.AccountName, sizeof(t.AccountName), title);\r
4863 \r
4864                                 if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT)\r
4865                                 {\r
4866                                         // 接続\r
4867                                         if (CtConnect(c, &t))\r
4868                                         {\r
4869                                                 err = ERR_NO_ERROR;\r
4870                                         }\r
4871                                         else\r
4872                                         {\r
4873                                                 err = c->Err;\r
4874                                         }\r
4875                                 }\r
4876                                 else\r
4877                                 {\r
4878                                         // 接続\r
4879                                         if (CtDisconnect(c, &t))\r
4880                                         {\r
4881                                                 err = ERR_NO_ERROR;\r
4882                                         }\r
4883                                         else\r
4884                                         {\r
4885                                                 err = c->Err;\r
4886                                         }\r
4887                                 }\r
4888                         }\r
4889 \r
4890                         err = Endian32(err);\r
4891                         SendAll(s, &err, sizeof(UINT), false);\r
4892                         RecvAll(s, &err, sizeof(UINT), false);\r
4893                 }\r
4894                 return;\r
4895         }\r
4896 \r
4897         // パスワード受信\r
4898         if (RecvAll(s, hashed_password, SHA1_SIZE, false) == false)\r
4899         {\r
4900                 return;\r
4901         }\r
4902 \r
4903         retcode = 0;\r
4904 \r
4905         // パスワード比較\r
4906         if (Cmp(hashed_password, c->EncryptedPassword, SHA1_SIZE) != 0)\r
4907         {\r
4908                 retcode = 1;\r
4909         }\r
4910 \r
4911         if (c->PasswordRemoteOnly && s->RemoteIP.addr[0] == 127)\r
4912         {\r
4913                 // リモートのみパスワードを要求するモードで、ローカルから接続された場合は\r
4914                 // パスワードを常に正しいと見なす\r
4915                 retcode = 0;\r
4916         }\r
4917 \r
4918         Lock(c->lock);\r
4919         {\r
4920                 if (c->Config.AllowRemoteConfig == false)\r
4921                 {\r
4922                         // リモート管理が禁止されている場合は\r
4923                         // このコネクションが外部からのものであるかどうか識別する\r
4924                         if (s->RemoteIP.addr[0] != 127)\r
4925                         {\r
4926                                 retcode = 2;\r
4927                         }\r
4928                 }\r
4929         }\r
4930         Unlock(c->lock);\r
4931 \r
4932         retcode = Endian32(retcode);\r
4933         // エラーコード送信\r
4934         if (SendAll(s, &retcode, sizeof(UINT), false) == false)\r
4935         {\r
4936                 return;\r
4937         }\r
4938 \r
4939 \r
4940 \r
4941         if (retcode != 0)\r
4942         {\r
4943                 // エラーによる切断\r
4944                 return;\r
4945         }\r
4946 \r
4947         // RPC サーバー作成\r
4948         rpc = StartRpcServer(s, CiRpcDispatch, c);\r
4949 \r
4950         // RPC サーバー動作\r
4951         RpcServer(rpc);\r
4952 \r
4953         // RPC サーバーの解放\r
4954         EndRpc(rpc);\r
4955 }\r
4956 \r
4957 // RPC 受付スレッド\r
4958 void CiRpcAcceptThread(THREAD *thread, void *param)\r
4959 {\r
4960         CLIENT_RPC_CONNECTION *conn;\r
4961         CLIENT *c;\r
4962         SOCK *s;\r
4963         // 引数チェック\r
4964         if (thread == NULL || param == NULL)\r
4965         {\r
4966                 return;\r
4967         }\r
4968 \r
4969         conn = (CLIENT_RPC_CONNECTION *)param;\r
4970         s = conn->Sock;\r
4971         c = conn->Client;\r
4972         AddRef(s->ref);\r
4973 \r
4974         // RPC コネクションリストに追加\r
4975         LockList(c->RpcConnectionList);\r
4976         {\r
4977                 Add(c->RpcConnectionList, conn);\r
4978         }\r
4979         UnlockList(c->RpcConnectionList);\r
4980 \r
4981         NoticeThreadInit(thread);\r
4982 \r
4983         // メイン処理\r
4984         CiRpcAccepted(c, s);\r
4985 \r
4986         // コネクションリストから解放\r
4987         LockList(c->RpcConnectionList);\r
4988         {\r
4989                 Delete(c->RpcConnectionList, conn);\r
4990         }\r
4991         UnlockList(c->RpcConnectionList);\r
4992 \r
4993         ReleaseSock(conn->Sock);\r
4994         ReleaseThread(conn->Thread);\r
4995         Free(conn);\r
4996 \r
4997         Disconnect(s);\r
4998         ReleaseSock(s);\r
4999 }\r
5000 \r
5001 // RPC サーバースレッド\r
5002 void CiRpcServerThread(THREAD *thread, void *param)\r
5003 {\r
5004         CLIENT *c;\r
5005         SOCK *listener;\r
5006         UINT i;\r
5007         LIST *thread_list;\r
5008         // 引数チェック\r
5009         if (thread == NULL || param == NULL)\r
5010         {\r
5011                 return;\r
5012         }\r
5013 \r
5014         c = (CLIENT *)param;\r
5015 \r
5016         // RPC コネクションリスト\r
5017         c->RpcConnectionList = NewList(NULL);\r
5018 \r
5019         // ポートを開く\r
5020         listener = NULL;\r
5021         for (i = CLIENT_CONFIG_PORT;i < (CLIENT_CONFIG_PORT + 5);i++)\r
5022         {\r
5023                 listener = Listen(i);\r
5024                 if (listener != NULL)\r
5025                 {\r
5026                         break;\r
5027                 }\r
5028         }\r
5029 \r
5030         if (listener == NULL)\r
5031         {\r
5032                 // エラー\r
5033                 Alert("SoftEther UT-VPN Client RPC Port Open Failed.", CEDAR_CLIENT_STR);\r
5034                 return;\r
5035         }\r
5036 \r
5037         c->RpcListener = listener;\r
5038         AddRef(listener->ref);\r
5039 \r
5040         NoticeThreadInit(thread);\r
5041 \r
5042         while (true)\r
5043         {\r
5044                 // クライアント接続を待機\r
5045                 CLIENT_RPC_CONNECTION *conn;\r
5046                 SOCK *s = Accept(listener);\r
5047                 if (s == NULL)\r
5048                 {\r
5049                         // 停止\r
5050                         break;\r
5051                 }\r
5052 \r
5053                 // クライアント処理用スレッドを作成する\r
5054                 conn = ZeroMalloc(sizeof(CLIENT_RPC_CONNECTION));\r
5055                 conn->Client = c;\r
5056                 conn->Sock = s;\r
5057                 AddRef(s->ref);\r
5058 \r
5059                 conn->Thread = NewThread(CiRpcAcceptThread, (void *)conn);\r
5060                 WaitThreadInit(conn->Thread);\r
5061 \r
5062                 ReleaseSock(s);\r
5063         }\r
5064 \r
5065         // リスナーを解放\r
5066         ReleaseSock(listener);\r
5067 \r
5068         thread_list = NewListFast(NULL);\r
5069 \r
5070         // すべての通知イベントを起動する\r
5071         LockList(c->NotifyCancelList);\r
5072         {\r
5073                 UINT i;\r
5074                 for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)\r
5075                 {\r
5076                         CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);\r
5077                         Cancel(cancel);\r
5078                 }\r
5079         }\r
5080         UnlockList(c->NotifyCancelList);\r
5081 \r
5082         // まだ接続しているすべてのコネクションを切断する\r
5083         LockList(c->RpcConnectionList);\r
5084         {\r
5085                 for (i = 0;i < LIST_NUM(c->RpcConnectionList);i++)\r
5086                 {\r
5087                         CLIENT_RPC_CONNECTION *cc = LIST_DATA(c->RpcConnectionList, i);\r
5088                         AddRef(cc->Thread->ref);\r
5089                         Add(thread_list, cc->Thread);\r
5090                         Disconnect(cc->Sock);\r
5091                 }\r
5092         }\r
5093         UnlockList(c->RpcConnectionList);\r
5094 \r
5095         for (i = 0;i < LIST_NUM(thread_list);i++)\r
5096         {\r
5097                 THREAD *t = LIST_DATA(thread_list, i);\r
5098                 WaitThread(t, INFINITE);\r
5099                 ReleaseThread(t);\r
5100         }\r
5101 \r
5102         ReleaseList(c->RpcConnectionList);\r
5103         ReleaseList(thread_list);\r
5104 }\r
5105 \r
5106 // Keep を開始\r
5107 void CiInitKeep(CLIENT *c)\r
5108 {\r
5109         // 引数チェック\r
5110         if (c == NULL)\r
5111         {\r
5112                 return;\r
5113         }\r
5114 \r
5115         c->Keep = StartKeep();\r
5116 \r
5117         // 設定の適用\r
5118         if (c->Config.UseKeepConnect)\r
5119         {\r
5120                 KEEP *k = c->Keep;\r
5121                 Lock(k->lock);\r
5122                 {\r
5123                         StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);\r
5124                         k->ServerPort = c->Config.KeepConnectPort;\r
5125                         k->Interval = c->Config.KeepConnectInterval * 1000;\r
5126                         k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;\r
5127                         k->Enable = true;\r
5128                 }\r
5129                 Unlock(k->lock);\r
5130         }\r
5131 }\r
5132 \r
5133 // Keep を停止\r
5134 void CiFreeKeep(CLIENT *c)\r
5135 {\r
5136         // 引数チェック\r
5137         if (c == NULL)\r
5138         {\r
5139                 return;\r
5140         }\r
5141 \r
5142         StopKeep(c->Keep);\r
5143         c->Keep = NULL;\r
5144 }\r
5145 \r
5146 // RPC を開始\r
5147 void CiStartRpcServer(CLIENT *c)\r
5148 {\r
5149         // 引数チェック\r
5150         if (c == NULL)\r
5151         {\r
5152                 return;\r
5153         }\r
5154 \r
5155         c->RpcThread = NewThread(CiRpcServerThread, (void *)c);\r
5156         WaitThreadInit(c->RpcThread);\r
5157 }\r
5158 \r
5159 // RPC を終了\r
5160 void CiStopRpcServer(CLIENT *c)\r
5161 {\r
5162         // 引数チェック\r
5163         if (c == NULL)\r
5164         {\r
5165                 return;\r
5166         }\r
5167 \r
5168         Disconnect(c->RpcListener);\r
5169         ReleaseSock(c->RpcListener);\r
5170 \r
5171         WaitThread(c->RpcThread, INFINITE);\r
5172         ReleaseThread(c->RpcThread);\r
5173 }\r
5174 \r
5175 // 次の通知を待機する\r
5176 bool CcWaitNotify(NOTIFY_CLIENT *n)\r
5177 {\r
5178         UCHAR c;\r
5179         // 引数チェック\r
5180         if (n == NULL)\r
5181         {\r
5182                 return false;\r
5183         }\r
5184 \r
5185         // 1 文字受信する\r
5186         if (RecvAll(n->Sock, &c, 1, false) == false)\r
5187         {\r
5188                 // 切断された\r
5189                 return false;\r
5190         }\r
5191 \r
5192         return true;\r
5193 }\r
5194 \r
5195 // 通知クライアントとして接続する\r
5196 NOTIFY_CLIENT *CcConnectNotify(REMOTE_CLIENT *rc)\r
5197 {\r
5198         NOTIFY_CLIENT *n;\r
5199         SOCK *s;\r
5200         char tmp[MAX_SIZE];\r
5201         bool rpc_mode = false;\r
5202         UINT port;\r
5203         // 引数チェック\r
5204         if (rc == NULL || rc->Rpc == NULL || rc->Rpc->Sock == NULL)\r
5205         {\r
5206                 return NULL;\r
5207         }\r
5208 \r
5209         // 接続\r
5210         IPToStr(tmp, sizeof(tmp), &rc->Rpc->Sock->RemoteIP);\r
5211         port = rc->Rpc->Sock->RemotePort;\r
5212 \r
5213         s = Connect(tmp, port);\r
5214         if (s == NULL)\r
5215         {\r
5216                 return NULL;\r
5217         }\r
5218 \r
5219         rpc_mode = Endian32(rpc_mode);\r
5220         if (SendAll(s, &rpc_mode, sizeof(rpc_mode), false) == false)\r
5221         {\r
5222                 ReleaseSock(s);\r
5223                 return NULL;\r
5224         }\r
5225 \r
5226         n = ZeroMalloc(sizeof(NOTIFY_CLIENT));\r
5227         n->Sock = s;\r
5228 \r
5229         return n;\r
5230 }\r
5231 \r
5232 // 通知クライアントを停止する\r
5233 void CcStopNotify(NOTIFY_CLIENT *n)\r
5234 {\r
5235         // 引数チェック\r
5236         if (n == NULL)\r
5237         {\r
5238                 return;\r
5239         }\r
5240 \r
5241         Disconnect(n->Sock);\r
5242 }\r
5243 \r
5244 // 通知クライアントを削除する\r
5245 void CcDisconnectNotify(NOTIFY_CLIENT *n)\r
5246 {\r
5247         // 引数チェック\r
5248         if (n == NULL)\r
5249         {\r
5250                 return;\r
5251         }\r
5252 \r
5253         // 切断\r
5254         Disconnect(n->Sock);\r
5255         ReleaseSock(n->Sock);\r
5256 \r
5257         // メモリ解放\r
5258         Free(n);\r
5259 }\r
5260 \r
5261 // リモート接続を切断する\r
5262 void CcDisconnectRpc(REMOTE_CLIENT *rc)\r
5263 {\r
5264         // 引数チェック\r
5265         if (rc == NULL)\r
5266         {\r
5267                 return;\r
5268         }\r
5269 \r
5270         RpcFree(rc->Rpc);\r
5271         Free(rc);\r
5272 }\r
5273 \r
5274 // クライアントに接続しショートカット接続設定を起動する\r
5275 UINT CcShortcut(UCHAR *key)\r
5276 {\r
5277         UINT ret;\r
5278         // 引数チェック\r
5279         if (key == NULL)\r
5280         {\r
5281                 return ERR_INVALID_PARAMETER;\r
5282         }\r
5283 \r
5284         CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, false, 0);\r
5285 \r
5286         return ret;\r
5287 }\r
5288 \r
5289 // 接続中のショートカット接続を切断する\r
5290 UINT CcShortcutDisconnect(UCHAR *key)\r
5291 {\r
5292         UINT ret;\r
5293         // 引数チェック\r
5294         if (key == NULL)\r
5295         {\r
5296                 return ERR_INVALID_PARAMETER;\r
5297         }\r
5298 \r
5299         CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, true, 0);\r
5300 \r
5301         return ret;\r
5302 }\r
5303 \r
5304 // クライアントにリモート接続する\r
5305 REMOTE_CLIENT *CcConnectRpc(char *server_name, char *password, bool *bad_pass, bool *no_remote, UINT wait_retry)\r
5306 {\r
5307         return CcConnectRpcEx(server_name, password, bad_pass, no_remote, NULL, NULL, false, wait_retry);\r
5308 }\r
5309 REMOTE_CLIENT *CcConnectRpcEx(char *server_name, char *password, bool *bad_pass, bool *no_remote, UCHAR *key, UINT *key_error_code, bool shortcut_disconnect, UINT wait_retry)\r
5310 {\r
5311         SOCK *s;\r
5312         UINT i;\r
5313         UINT retcode;\r
5314         UINT rpc_mode = CLIENT_RPC_MODE_MANAGEMENT;\r
5315         RPC *rpc;\r
5316         REMOTE_CLIENT *ret;\r
5317         UCHAR hash_password[SHA1_SIZE];\r
5318         UINT port_start;\r
5319         UINT64 try_started = 0;\r
5320         bool ok;\r
5321         // 引数チェック\r
5322         if (server_name == NULL)\r
5323         {\r
5324                 return NULL;\r
5325         }\r
5326         if (password == NULL)\r
5327         {\r
5328                 password = "";\r
5329         }\r
5330 \r
5331         if (key_error_code != NULL)\r
5332         {\r
5333                 *key_error_code = ERR_NO_ERROR;\r
5334         }\r
5335 \r
5336         if (bad_pass != NULL)\r
5337         {\r
5338                 *bad_pass = false;\r
5339         }\r
5340 \r
5341         if (no_remote != NULL)\r
5342         {\r
5343                 *no_remote = false;\r
5344         }\r
5345 \r
5346         port_start = CLIENT_CONFIG_PORT - 1;\r
5347 \r
5348 RETRY:\r
5349         port_start++;\r
5350 \r
5351         if (port_start >= (CLIENT_CONFIG_PORT + 5))\r
5352         {\r
5353                 return NULL;\r
5354         }\r
5355 \r
5356         ok = false;\r
5357 \r
5358         while (true)\r
5359         {\r
5360                 for (i = port_start;i < (CLIENT_CONFIG_PORT + 5);i++)\r
5361                 {\r
5362                         if (CheckTCPPort(server_name, i))\r
5363                         {\r
5364                                 ok = true;\r
5365                                 break;\r
5366                         }\r
5367                 }\r
5368 \r
5369                 if (ok)\r
5370                 {\r
5371                         break;\r
5372                 }\r
5373 \r
5374                 if (wait_retry == 0)\r
5375                 {\r
5376                         break;\r
5377                 }\r
5378 \r
5379                 if (try_started == 0)\r
5380                 {\r
5381                         try_started = Tick64();\r
5382                 }\r
5383 \r
5384                 if ((try_started + (UINT64)wait_retry) <= Tick64())\r
5385                 {\r
5386                         break;\r
5387                 }\r
5388         }\r
5389 \r
5390         if (ok == false)\r
5391         {\r
5392                 if (key_error_code)\r
5393                 {\r
5394                         *key_error_code = ERR_CONNECT_FAILED;\r
5395                 }\r
5396                 return NULL;\r
5397         }\r
5398 \r
5399         port_start = i;\r
5400 \r
5401         s = Connect(server_name, i);\r
5402         if (s == NULL)\r
5403         {\r
5404                 if (key_error_code)\r
5405                 {\r
5406                         *key_error_code = ERR_CONNECT_FAILED;\r
5407                 }\r
5408                 goto RETRY;\r
5409         }\r
5410 \r
5411         Hash(hash_password, password, StrLen(password), true);\r
5412 \r
5413         if (key != NULL)\r
5414         {\r
5415                 if (shortcut_disconnect == false)\r
5416                 {\r
5417                         rpc_mode = CLIENT_RPC_MODE_SHORTCUT;\r
5418                 }\r
5419                 else\r
5420                 {\r
5421                         rpc_mode = CLIENT_RPC_MODE_SHORTCUT_DISCONNECT;\r
5422                 }\r
5423         }\r
5424 \r
5425         rpc_mode = Endian32(rpc_mode);\r
5426         SendAdd(s, &rpc_mode, sizeof(UINT));\r
5427 \r
5428         if (key != NULL)\r
5429         {\r
5430                 SendAdd(s, key, SHA1_SIZE);\r
5431         }\r
5432         else\r
5433         {\r
5434                 SendAdd(s, hash_password, SHA1_SIZE);\r
5435         }\r
5436 \r
5437         if (SendNow(s, false) == false)\r
5438         {\r
5439                 ReleaseSock(s);\r
5440                 goto RETRY;\r
5441         }\r
5442 \r
5443         if (RecvAll(s, &retcode, sizeof(UINT), false) == false)\r
5444         {\r
5445                 ReleaseSock(s);\r
5446                 goto RETRY;\r
5447         }\r
5448 \r
5449         retcode = Endian32(retcode);\r
5450 \r
5451         if (retcode >= 1024)\r
5452         {\r
5453                 goto RETRY;\r
5454         }\r
5455 \r
5456         if (key != NULL)\r
5457         {\r
5458                 if (key_error_code)\r
5459                 {\r
5460                         *key_error_code = retcode;\r
5461                 }\r
5462                 SendAll(s, &retcode, sizeof(UINT), false);\r
5463                 ReleaseSock(s);\r
5464                 return NULL;\r
5465         }\r
5466 \r
5467         switch (retcode)\r
5468         {\r
5469         case 1:\r
5470                 if (bad_pass != NULL)\r
5471                 {\r
5472                         *bad_pass = true;\r
5473                 }\r
5474                 break;\r
5475         case 2:\r
5476                 if (no_remote != NULL)\r
5477                 {\r
5478                         *no_remote = true;\r
5479                 }\r
5480                 break;\r
5481         }\r
5482 \r
5483         if (retcode != 0)\r
5484         {\r
5485                 ReleaseSock(s);\r
5486                 return NULL;\r
5487         }\r
5488 \r
5489         rpc = StartRpcClient(s, NULL);\r
5490 \r
5491         ReleaseSock(s);\r
5492 \r
5493         ret = ZeroMalloc(sizeof(REMOTE_CLIENT));\r
5494         ret->Rpc = rpc;\r
5495         rpc->Param = ret;\r
5496 \r
5497         if (ret != NULL)\r
5498         {\r
5499                 RPC_CLIENT_VERSION t;\r
5500                 Zero(&t, sizeof(t));\r
5501                 CcGetClientVersion(ret, &t);\r
5502                 ret->OsType = t.OsType;\r
5503                 ret->Unix = OS_IS_UNIX(ret->OsType);\r
5504                 ret->Win9x = OS_IS_WINDOWS_9X(ret->OsType);\r
5505         }\r
5506 \r
5507         return ret;\r
5508 }\r
5509 \r
5510 // セッションから RPC_CLIENT_GET_CONNECTION_STATUS を取得\r
5511 void CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st, SESSION *s)\r
5512 {\r
5513         // 引数チェック\r
5514         if (st == NULL || s == NULL)\r
5515         {\r
5516                 return;\r
5517         }\r
5518 \r
5519         Lock(s->lock);\r
5520         {\r
5521                 // 動作フラグ\r
5522                 st->Active = true;\r
5523 \r
5524                 // セッションステータス\r
5525                 st->SessionStatus = s->ClientStatus;\r
5526 \r
5527                 // アカウント名\r
5528                 UniStrCpy(st->AccountName, sizeof(st->AccountName), s->ClientOption->AccountName);\r
5529 \r
5530                 if (s->ClientStatus == CLIENT_STATUS_ESTABLISHED && s->Connection != NULL)\r
5531                 {\r
5532                         Lock(s->Connection->lock);\r
5533                         {\r
5534                                 // 接続済みフラグ\r
5535                                 st->Connected = true;\r
5536                                 // 製品名\r
5537                                 StrCpy(st->ServerProductName, sizeof(st->ServerProductName), s->Connection->ServerStr);\r
5538                                 // バージョン\r
5539                                 st->ServerProductVer = s->Connection->ServerVer;\r
5540                                 // ビルド番号\r
5541                                 st->ServerProductBuild = s->Connection->ServerBuild;\r
5542                                 // サーバー証明書\r
5543                                 st->ServerX = CloneX(s->Connection->ServerX);\r
5544                                 // クライアント証明書\r
5545                                 st->ClientX = CloneX(s->Connection->ClientX);\r
5546                                 // このコネクションの接続完了時刻\r
5547                                 st->CurrentConnectionEstablishTime = TickToTime(s->CurrentConnectionEstablishTime);\r
5548                                 // 最大の TCP コネクション数\r
5549                                 st->MaxTcpConnections = s->MaxConnection;\r
5550                                 // ハーフコネクション\r
5551                                 st->HalfConnection = s->HalfConnection;\r
5552                                 // VLAN\r
5553                                 st->VLanId = s->VLanId;\r
5554                                 // VoIP / QoS\r
5555                                 st->QoS = s->QoS;\r
5556                                 if (s->Connection->Protocol == CONNECTION_TCP)\r
5557                                 {\r
5558                                         UINT i;\r
5559                                         // 現在の TCP コネクション数\r
5560                                         LockList(s->Connection->Tcp->TcpSockList);\r
5561                                         {\r
5562                                                 st->NumTcpConnections = LIST_NUM(s->Connection->Tcp->TcpSockList);\r
5563                                                 if (st->HalfConnection)\r
5564                                                 {\r
5565                                                         for (i = 0;i < st->NumTcpConnections;i++)\r
5566                                                         {\r
5567                                                                 TCPSOCK *ts = LIST_DATA(s->Connection->Tcp->TcpSockList, i);\r
5568                                                                 if (ts->Direction & TCP_SERVER_TO_CLIENT)\r
5569                                                                 {\r
5570                                                                         st->NumTcpConnectionsDownload++;\r
5571                                                                 }\r
5572                                                                 else\r
5573                                                                 {\r
5574                                                                         st->NumTcpConnectionsUpload++;\r
5575                                                                 }\r
5576                                                         }\r
5577                                                 }\r
5578                                         }\r
5579                                         UnlockList(s->Connection->Tcp->TcpSockList);\r
5580                                 }\r
5581                                 // 暗号化の使用\r
5582                                 st->UseEncrypt = s->UseEncrypt;\r
5583                                 if (st->UseEncrypt)\r
5584                                 {\r
5585                                         StrCpy(st->CipherName, sizeof(st->CipherName), s->Connection->CipherName);\r
5586                                 }\r
5587                                 // 圧縮の使用\r
5588                                 st->UseCompress = s->UseCompress;\r
5589                                 // セッションキー\r
5590                                 Copy(st->SessionKey, s->SessionKey, SHA1_SIZE);\r
5591                                 // ポリシー\r
5592                                 Copy(&st->Policy, s->Policy, sizeof(POLICY));\r
5593                                 // データサイズ\r
5594                                 if (s->ServerMode == false)\r
5595                                 {\r
5596                                         st->TotalSendSize = s->TotalSendSize;\r
5597                                         st->TotalRecvSize = s->TotalRecvSize;\r
5598                                         st->TotalRecvSizeReal = s->TotalRecvSizeReal;\r
5599                                         st->TotalSendSizeReal = s->TotalSendSizeReal;\r
5600                                 }\r
5601                                 else\r
5602                                 {\r
5603                                         st->TotalSendSize = s->TotalRecvSize;\r
5604                                         st->TotalRecvSize = s->TotalSendSize;\r
5605                                         st->TotalRecvSizeReal = s->TotalSendSizeReal;\r
5606                                         st->TotalSendSizeReal = s->TotalRecvSizeReal;\r
5607                                 }\r
5608                                 // セッション名\r
5609                                 StrCpy(st->SessionName, sizeof(st->SessionName), s->Name);\r
5610                                 // コネクション名\r
5611                                 StrCpy(st->ConnectionName, sizeof(st->ConnectionName), s->Connection->Name);\r
5612                                 // サーバー名\r
5613                                 StrCpy(st->ServerName, sizeof(st->ServerName), s->Connection->ServerName);\r
5614                                 // ポート番号\r
5615                                 st->ServerPort = s->Connection->ServerPort;\r
5616                                 // トラフィックデータ\r
5617                                 Lock(s->TrafficLock);\r
5618                                 {\r
5619                                         Copy(&st->Traffic, s->Traffic, sizeof(TRAFFIC));\r
5620                                 }\r
5621                                 Unlock(s->TrafficLock);\r
5622 \r
5623                                 st->IsBridgeMode = s->IsBridgeMode;\r
5624                                 st->IsMonitorMode = s->IsMonitorMode;\r
5625                         }\r
5626                         Unlock(s->Connection->lock);\r
5627                 }\r
5628                 // 接続開始時刻\r
5629                 st->StartTime = TickToTime(s->CreatedTime);\r
5630                 // 最初のコネクションの接続完了時刻\r
5631                 st->FirstConnectionEstablisiedTime = TickToTime(s->FirstConnectionEstablisiedTime);\r
5632                 // これまでに確立したコネクション数\r
5633                 st->NumConnectionsEatablished = s->NumConnectionsEatablished;\r
5634         }\r
5635         Unlock(s->lock);\r
5636 }\r
5637 \r
5638 // 接続ステータスの取得\r
5639 bool CtGetAccountStatus(CLIENT *c, RPC_CLIENT_GET_CONNECTION_STATUS *st)\r
5640 {\r
5641         // 引数チェック\r
5642         if (c == NULL || st == NULL)\r
5643         {\r
5644                 return false;\r
5645         }\r
5646 \r
5647         LockList(c->AccountList);\r
5648         {\r
5649                 ACCOUNT t, *r;\r
5650 \r
5651                 // アカウントを検索\r
5652                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
5653                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), st->AccountName);\r
5654 \r
5655                 r = Search(c->AccountList, &t);\r
5656                 if (r == NULL)\r
5657                 {\r
5658                         // 指定したアカウントは見つからない\r
5659                         UnlockList(c->AccountList);\r
5660 \r
5661                         Free(t.ClientOption);\r
5662                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
5663                         return false;\r
5664                 }\r
5665 \r
5666                 Free(t.ClientOption);\r
5667 \r
5668                 Lock(r->lock);\r
5669                 {\r
5670                         Zero(st, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));\r
5671                         if (r->ClientSession != NULL)\r
5672                         {\r
5673                                 SESSION *s = r->ClientSession;\r
5674                                 CiGetSessionStatus(st, s);\r
5675                         }\r
5676                 }\r
5677                 Unlock(r->lock);\r
5678         }\r
5679         UnlockList(c->AccountList);\r
5680 \r
5681         return true;\r
5682 }\r
5683 \r
5684 // 接続ステータスの解放\r
5685 void CiFreeClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st)\r
5686 {\r
5687         // 引数チェック\r
5688         if (st == NULL)\r
5689         {\r
5690                 return;\r
5691         }\r
5692 \r
5693         if (st->ServerX != NULL)\r
5694         {\r
5695                 FreeX(st->ServerX);\r
5696         }\r
5697 \r
5698         if (st->ClientX != NULL)\r
5699         {\r
5700                 FreeX(st->ClientX);\r
5701         }\r
5702 }\r
5703 \r
5704 // サーバー証明書の確認プロシージャ\r
5705 bool CiCheckCertProc(SESSION *s, CONNECTION *c, X *server_x, bool *expired)\r
5706 {\r
5707 #ifdef  OS_WIN32\r
5708         ACCOUNT *a;\r
5709         X *old_x = NULL;\r
5710         UI_CHECKCERT dlg;\r
5711         // 引数チェック\r
5712         if (s == NULL || c == NULL || server_x == NULL)\r
5713         {\r
5714                 return false;\r
5715         }\r
5716 \r
5717         if (expired != NULL)\r
5718         {\r
5719                 *expired = false;\r
5720         }\r
5721 \r
5722         Zero(&dlg, sizeof(dlg));\r
5723 \r
5724         a = s->Account;\r
5725         if (a == NULL)\r
5726         {\r
5727                 return false;\r
5728         }\r
5729 \r
5730         Lock(a->lock);\r
5731         {\r
5732                 if (a->CheckServerCert == false)\r
5733                 {\r
5734                         // サーバー証明書を検証しない\r
5735                         Unlock(a->lock);\r
5736                         return true;\r
5737                 }\r
5738 \r
5739                 if (a->ServerCert != NULL)\r
5740                 {\r
5741                         old_x = CloneX(a->ServerCert);\r
5742                 }\r
5743         }\r
5744         Unlock(a->lock);\r
5745 \r
5746         if (CheckXDateNow(server_x) == false)\r
5747         {\r
5748                 // 有効期限が切れている\r
5749                 if (old_x != NULL)\r
5750                 {\r
5751                         FreeX(old_x);\r
5752                 }\r
5753 \r
5754                 if (expired != NULL)\r
5755                 {\r
5756                         *expired = true;\r
5757                 }\r
5758 \r
5759                 return false;\r
5760         }\r
5761 \r
5762         if (old_x != NULL)\r
5763         {\r
5764                 if (CompareX(old_x, server_x))\r
5765                 {\r
5766                         // すでに登録されている証明書と完全一致した\r
5767                         if (old_x != NULL)\r
5768                         {\r
5769                                 FreeX(old_x);\r
5770                         }\r
5771                         return true;\r
5772                 }\r
5773                 else\r
5774                 {\r
5775                         dlg.DiffWarning = true;\r
5776                 }\r
5777         }\r
5778 \r
5779         // この証明書は信頼できないのでダイアログボックスを出して確認する\r
5780         UniStrCpy(dlg.AccountName, sizeof(dlg.AccountName), a->ClientOption->AccountName);\r
5781         StrCpy(dlg.ServerName, sizeof(dlg.ServerName), a->ClientOption->Hostname);\r
5782         dlg.x = server_x;\r
5783         dlg.old_x = old_x;\r
5784         \r
5785         dlg.Session = s;\r
5786         AddRef(s->ref);\r
5787 \r
5788         CncCheckCert(s, &dlg);\r
5789 \r
5790         ReleaseSession(s);\r
5791 \r
5792         if (old_x != NULL)\r
5793         {\r
5794                 FreeX(old_x);\r
5795         }\r
5796 \r
5797         if (dlg.Ok && dlg.SaveServerCert)\r
5798         {\r
5799                 // このサーバー証明書を保存し次回から信頼する\r
5800                 Lock(a->lock);\r
5801                 {\r
5802                         if (a->ServerCert != NULL)\r
5803                         {\r
5804                                 FreeX(a->ServerCert);\r
5805                         }\r
5806 \r
5807                         a->ServerCert = CloneX(server_x);\r
5808                 }\r
5809                 Unlock(a->lock);\r
5810                 CiSaveConfigurationFile(s->Cedar->Client);\r
5811         }\r
5812 \r
5813         return dlg.Ok;\r
5814 #else   // OS_WIN32\r
5815         ACCOUNT *a;\r
5816         X *old_x = NULL;\r
5817         // 引数チェック\r
5818         if (s == NULL || c == NULL || server_x == NULL)\r
5819         {\r
5820                 return false;\r
5821         }\r
5822 \r
5823         if (expired != NULL)\r
5824         {\r
5825                 *expired = false;\r
5826         }\r
5827 \r
5828         a = s->Account;\r
5829         if (a == NULL)\r
5830         {\r
5831                 return false;\r
5832         }\r
5833 \r
5834         Lock(a->lock);\r
5835         {\r
5836                 if (a->CheckServerCert == false)\r
5837                 {\r
5838                         // サーバー証明書を検証しない\r
5839                         Unlock(a->lock);\r
5840                         return true;\r
5841                 }\r
5842 \r
5843                 if (a->ServerCert != NULL)\r
5844                 {\r
5845                         old_x = CloneX(a->ServerCert);\r
5846                 }\r
5847         }\r
5848         Unlock(a->lock);\r
5849 \r
5850         if (CheckXDateNow(server_x) == false)\r
5851         {\r
5852                 // 有効期限が切れている\r
5853                 if (old_x != NULL)\r
5854                 {\r
5855                         FreeX(old_x);\r
5856                 }\r
5857 \r
5858                 if (expired != NULL)\r
5859                 {\r
5860                         *expired = true;\r
5861                 }\r
5862 \r
5863                 return false;\r
5864         }\r
5865 \r
5866         if (old_x != NULL)\r
5867         {\r
5868                 if (CompareX(old_x, server_x))\r
5869                 {\r
5870                         // すでに登録されている証明書と完全一致した\r
5871                         if (old_x != NULL)\r
5872                         {\r
5873                                 FreeX(old_x);\r
5874                         }\r
5875                         return true;\r
5876                 }\r
5877                 else\r
5878                 {\r
5879                         // 不一致\r
5880                         if (old_x != NULL)\r
5881                         {\r
5882                                 FreeX(old_x);\r
5883                         }\r
5884                         return false;\r
5885                 }\r
5886         }\r
5887 \r
5888         if (old_x != NULL)\r
5889         {\r
5890                 FreeX(old_x);\r
5891         }\r
5892 \r
5893         return false;\r
5894 #endif  // OS_WIN32\r
5895 }\r
5896 \r
5897 // セキュアデバイスを使用した署名プロシージャ\r
5898 bool CiSecureSignProc(SESSION *s, CONNECTION *c, SECURE_SIGN *sign)\r
5899 {\r
5900         // Win32 の場合は UI を使用することができる\r
5901         return CncSecureSignDlg(sign);\r
5902 }\r
5903 \r
5904 #ifdef  OS_WIN32\r
5905 // 署名プロシージャ (Win32 用)\r
5906 bool Win32CiSecureSign(SECURE_SIGN *sign)\r
5907 {\r
5908         bool ret = false;\r
5909         BUF *random;\r
5910         // 引数チェック\r
5911         if (sign == NULL)\r
5912         {\r
5913                 return false;\r
5914         }\r
5915 \r
5916         random = NewBuf();\r
5917         WriteBuf(random, sign->Random, SHA1_SIZE);\r
5918 \r
5919         // バッチ処理\r
5920         {\r
5921                 WINUI_SECURE_BATCH batch[] =\r
5922                 {\r
5923                         {WINUI_SECURE_READ_CERT, sign->SecurePublicCertName, true, NULL, NULL, NULL, NULL, NULL, NULL},\r
5924                         {WINUI_SECURE_SIGN_WITH_KEY, sign->SecurePrivateKeyName, true, random, NULL, NULL, NULL, NULL, NULL}\r
5925                 };\r
5926 \r
5927                 if (SecureDeviceWindow(NULL, batch, sizeof(batch) / sizeof(batch[0]),\r
5928                         sign->UseSecureDeviceId, sign->BitmapId) == false)\r
5929                 {\r
5930                         // 失敗\r
5931                         if (batch[0].OutputX != 0)\r
5932                         {\r
5933                                 FreeX(batch[0].OutputX);\r
5934                         }\r
5935                         ret = false;\r
5936                 }\r
5937                 else\r
5938                 {\r
5939                         // 成功\r
5940                         ret = true;\r
5941                         sign->ClientCert = batch[0].OutputX;\r
5942                         Copy(sign->Signature, batch[1].OutputSign, 128);\r
5943                 }\r
5944         }\r
5945 \r
5946         FreeBuf(random);\r
5947 \r
5948         return ret;\r
5949 }\r
5950 #endif  // OS_WIN32\r
5951 \r
5952 // 切断\r
5953 bool CtDisconnect(CLIENT *c, RPC_CLIENT_CONNECT *connect)\r
5954 {\r
5955         bool ret = false;\r
5956         ACCOUNT t, *r;\r
5957         SESSION *s = NULL;\r
5958         // 引数チェック\r
5959         if (c == NULL || connect == NULL)\r
5960         {\r
5961                 return false;\r
5962         }\r
5963 \r
5964         LockList(c->AccountList);\r
5965         {\r
5966 \r
5967                 // アカウントを検索\r
5968                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
5969                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);\r
5970 \r
5971                 r = Search(c->AccountList, &t);\r
5972                 if (r == NULL)\r
5973                 {\r
5974                         // 指定したアカウントは見つからない\r
5975                         UnlockList(c->AccountList);\r
5976 \r
5977                         Free(t.ClientOption);\r
5978                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
5979                         return false;\r
5980                 }\r
5981 \r
5982                 Free(t.ClientOption);\r
5983 \r
5984                 Lock(r->lock);\r
5985                 {\r
5986                         if (r->ClientSession == NULL)\r
5987                         {\r
5988                                 // 接続していない\r
5989                                 CiSetError(c, ERR_ACCOUNT_INACTIVE);\r
5990                         }\r
5991                         else\r
5992                         {\r
5993                                 s = r->ClientSession;\r
5994                                 AddRef(s->ref);\r
5995                                 // 切断完了\r
5996                                 r->ClientSession = NULL;\r
5997                                 ret = true;\r
5998                         }\r
5999                 }\r
6000                 Unlock(r->lock);\r
6001         }\r
6002         UnlockList(c->AccountList);\r
6003 \r
6004         if (s != NULL)\r
6005         {\r
6006                 // 接続を切断 (切断完了まで待機)\r
6007                 CLog(c, "LC_DISCONNECT", connect->AccountName);\r
6008                 StopSession(s);\r
6009                 ReleaseSession(s);\r
6010         }\r
6011 \r
6012         if (ret != false)\r
6013         {\r
6014                 CiNotify(c);\r
6015         }\r
6016 \r
6017         return ret;\r
6018 }\r
6019 \r
6020 // 接続\r
6021 bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect)\r
6022 {\r
6023         bool ret = false;\r
6024         RPC_CLIENT_ENUM_VLAN t;\r
6025         // 引数チェック\r
6026         if (c == NULL || connect == NULL)\r
6027         {\r
6028                 return false;\r
6029         }\r
6030 \r
6031         Lock(c->lockForConnect);\r
6032         {\r
6033                 Zero(&t, sizeof(t));\r
6034                 if (CtEnumVLan(c, &t))\r
6035                 {\r
6036                         if (t.NumItem == 0)\r
6037                         {\r
6038                                 // システムに仮想 LAN カードが 1 枚も無い\r
6039                                 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) || OS_IS_UNIX(GetOsInfo()->OsType))\r
6040                                 {\r
6041                                         // Windows NT 系または Linux 系の場合のみ、自動的に "VPN" という名前の\r
6042                                         // 新しい仮想 LAN カードを作成する\r
6043                                         RPC_CLIENT_CREATE_VLAN t;\r
6044 \r
6045                                         Zero(&t, sizeof(t));\r
6046                                         StrCpy(t.DeviceName, sizeof(t.DeviceName), "VPN");\r
6047                                         CtCreateVLan(c,  &t);\r
6048                                 }\r
6049                         }\r
6050 \r
6051                         CiFreeClientEnumVLan(&t);\r
6052                 }\r
6053         }\r
6054         Unlock(c->lockForConnect);\r
6055 \r
6056         CiNormalizeAccountVLan(c);\r
6057 \r
6058         LockList(c->AccountList);\r
6059         {\r
6060                 ACCOUNT t, *r;\r
6061                 bool unix_disabled = false;\r
6062 \r
6063                 // アカウントを検索\r
6064                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6065                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);\r
6066 \r
6067                 r = Search(c->AccountList, &t);\r
6068                 if (r == NULL)\r
6069                 {\r
6070                         // 指定したアカウントは見つからない\r
6071                         UnlockList(c->AccountList);\r
6072 \r
6073                         Free(t.ClientOption);\r
6074                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6075                         return false;\r
6076                 }\r
6077 \r
6078                 Free(t.ClientOption);\r
6079 \r
6080 #ifndef OS_WIN32\r
6081                 // 仮想 LAN カードを検索する\r
6082                 LockList(c->UnixVLanList);\r
6083                 {\r
6084                         UNIX_VLAN *v, t;\r
6085 \r
6086                         Zero(&t, sizeof(t));\r
6087                         StrCpy(t.Name, sizeof(t.Name), r->ClientOption->DeviceName);\r
6088 \r
6089                         v = Search(c->UnixVLanList, &t);\r
6090                         if (v == NULL)\r
6091                         {\r
6092                                 UnlockList(c->UnixVLanList);\r
6093                                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
6094                                 return false;\r
6095                         }\r
6096 \r
6097                         unix_disabled = v->Enabled ? false : true;\r
6098                 }\r
6099                 UnlockList(c->UnixVLanList);\r
6100 #endif  // OS_WIN32\r
6101 \r
6102                 Lock(r->lock);\r
6103                 {\r
6104                         bool already_used = false;\r
6105                         UINT i;\r
6106 \r
6107                         if (r->ClientSession != NULL)\r
6108                         {\r
6109                                 // すでに接続中\r
6110                                 CiSetError(c, ERR_ACCOUNT_ACTIVE);\r
6111                         }\r
6112                         else if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE &&\r
6113                                 client->UseSecureDeviceId == 0)\r
6114                         {\r
6115                                 // セキュアデバイスが指定されていない\r
6116                                 CiSetError(c, ERR_NO_SECURE_DEVICE_SPECIFIED);\r
6117                         }\r
6118 #ifdef  OS_WIN32\r
6119                         else if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, r->ClientOption->DeviceName) == false)\r
6120                         {\r
6121                                 // 仮想 LAN カードが見つからない\r
6122                                 CiSetError(c, ERR_VLAN_FOR_ACCOUNT_NOT_FOUND);\r
6123                                 CiNotify(c);\r
6124                         }\r
6125                         else if (MsIsVLanEnabled(r->ClientOption->DeviceName) == false)\r
6126                         {\r
6127                                 // 仮想 LAN カードは無効化されている\r
6128                                 CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);\r
6129                                 CiNotify(c);\r
6130                         }\r
6131 #else   // OS_WIN32\r
6132                         else if (unix_disabled)\r
6133                         {\r
6134                                 // 仮想 LAN カードは無効化されている\r
6135                                 CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);\r
6136                                 CiNotify(c);\r
6137                         }\r
6138 #endif  // OS_WIN32\r
6139                         else\r
6140                         {\r
6141                                 // 仮想 LAN カードがすでに別のアカウントで使用されているかどうか調べる\r
6142                                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
6143                                 {\r
6144                                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
6145                                         if (a != r)\r
6146                                         {\r
6147                                                 if (StrCmpi(a->ClientOption->DeviceName,\r
6148                                                         r->ClientOption->DeviceName) == 0)\r
6149                                                 {\r
6150                                                         if (a->ClientSession != NULL)\r
6151                                                         {\r
6152                                                                 already_used = true;\r
6153                                                                 break;\r
6154                                                         }\r
6155                                                 }\r
6156                                         }\r
6157                                 }\r
6158 \r
6159                                 if (already_used)\r
6160                                 {\r
6161                                         CiSetError(c, ERR_VLAN_FOR_ACCOUNT_USED);\r
6162                                 }\r
6163                                 else\r
6164                                 {\r
6165                                         // 接続を開始\r
6166                                         PACKET_ADAPTER *pa = VLanGetPacketAdapter();\r
6167 \r
6168                                         if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)\r
6169                                         {\r
6170                                                 // セキュアデバイス認証のためのプロシージャを登録する\r
6171                                                 r->ClientAuth->SecureSignProc = CiSecureSignProc;\r
6172                                         }\r
6173                                         else\r
6174                                         {\r
6175                                                 r->ClientAuth->SecureSignProc = NULL;\r
6176                                         }\r
6177 \r
6178                                         if (r->CheckServerCert)\r
6179                                         {\r
6180                                                 // サーバー証明書確認のためのプロシージャを登録する\r
6181                                                 r->ClientAuth->CheckCertProc = CiCheckCertProc;\r
6182                                         }\r
6183                                         else\r
6184                                         {\r
6185                                                 r->ClientAuth->CheckCertProc = NULL;\r
6186                                         }\r
6187 \r
6188                                         r->StatusPrinter = CiClientStatusPrinter;\r
6189                                         r->LastConnectDateTime = SystemTime64();\r
6190 \r
6191                                         CLog(c, "LC_CONNECT", connect->AccountName);\r
6192 \r
6193                                         r->ClientSession = NewClientSessionEx(c->Cedar, r->ClientOption, r->ClientAuth, pa, r);\r
6194                                         Notify(r->ClientSession, CLIENT_NOTIFY_ACCOUNT_CHANGED);\r
6195 \r
6196                                         ret = true;\r
6197                                 }\r
6198                         }\r
6199                 }\r
6200                 Unlock(r->lock);\r
6201 \r
6202         }\r
6203         UnlockList(c->AccountList);\r
6204 \r
6205         CiSaveConfigurationFile(c);\r
6206 \r
6207         return ret;\r
6208 }\r
6209 \r
6210 // アカウント情報の取得\r
6211 bool CtGetAccount(CLIENT *c, RPC_CLIENT_GET_ACCOUNT *a)\r
6212 {\r
6213         // 引数チェック\r
6214         if (c == NULL || a == NULL)\r
6215         {\r
6216                 return false;\r
6217         }\r
6218 \r
6219         LockList(c->AccountList);\r
6220         {\r
6221                 ACCOUNT t, *r;\r
6222 \r
6223                 // アカウントを検索\r
6224                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6225                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);\r
6226 \r
6227                 r = Search(c->AccountList, &t);\r
6228                 if (r == NULL)\r
6229                 {\r
6230                         // 指定したアカウントは見つからない\r
6231                         UnlockList(c->AccountList);\r
6232 \r
6233                         Free(t.ClientOption);\r
6234                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6235                         return false;\r
6236                 }\r
6237 \r
6238                 Free(t.ClientOption);\r
6239 \r
6240                 Lock(r->lock);\r
6241                 {\r
6242                         // クライアントオプションをコピー\r
6243                         if (a->ClientOption != NULL)\r
6244                         {\r
6245                                 Free(a->ClientOption);\r
6246                         }\r
6247                         a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6248                         Copy(a->ClientOption, r->ClientOption, sizeof(CLIENT_OPTION));\r
6249 \r
6250                         // 認証データをコピー\r
6251                         if (a->ClientAuth != NULL)\r
6252                         {\r
6253                                 CiFreeClientAuth(a->ClientAuth);\r
6254                         }\r
6255                         a->ClientAuth = CopyClientAuth(r->ClientAuth);\r
6256 \r
6257                         a->StartupAccount = r->StartupAccount;\r
6258 \r
6259                         a->CheckServerCert = r->CheckServerCert;\r
6260                         a->ServerCert = NULL;\r
6261                         if (r->ServerCert != NULL)\r
6262                         {\r
6263                                 a->ServerCert = CloneX(r->ServerCert);\r
6264                         }\r
6265 \r
6266                         // ショートカットキー\r
6267                         Copy(a->ShortcutKey, r->ShortcutKey, SHA1_SIZE);\r
6268 \r
6269                         a->CreateDateTime = r->CreateDateTime;\r
6270                         a->LastConnectDateTime = r->LastConnectDateTime;\r
6271                         a->UpdateDateTime = r->UpdateDateTime;\r
6272                 }\r
6273                 Unlock(r->lock);\r
6274 \r
6275         }\r
6276         UnlockList(c->AccountList);\r
6277 \r
6278         return true;\r
6279 }\r
6280 \r
6281 // アカウント名の変更\r
6282 bool CtRenameAccount(CLIENT *c, RPC_RENAME_ACCOUNT *rename)\r
6283 {\r
6284         bool ret;\r
6285         // 引数チェック\r
6286         if (c == NULL || rename == NULL)\r
6287         {\r
6288                 return false;\r
6289         }\r
6290 \r
6291         ret = false;\r
6292 \r
6293         if (UniStrCmp(rename->NewName, rename->OldName) == 0)\r
6294         {\r
6295                 // 名前が変更されていない\r
6296                 return true;\r
6297         }\r
6298 \r
6299         LockList(c->AccountList);\r
6300         {\r
6301                 ACCOUNT t, *r, *r2;\r
6302 \r
6303                 if (UniStrLen(rename->NewName) == 0)\r
6304                 {\r
6305                         // 名前が不正\r
6306                         CiSetError(c, ERR_INVALID_VALUE);\r
6307                         UnlockList(c->AccountList);\r
6308                         return false;\r
6309                 }\r
6310 \r
6311                 // 古いアカウント名を検索\r
6312                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6313                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->OldName);\r
6314 \r
6315                 r = Search(c->AccountList, &t);\r
6316                 if (r == NULL)\r
6317                 {\r
6318                         // 指定したアカウントは見つからない\r
6319                         UnlockList(c->AccountList);\r
6320 \r
6321                         Free(t.ClientOption);\r
6322                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6323                         return false;\r
6324                 }\r
6325 \r
6326                 Free(t.ClientOption);\r
6327 \r
6328                 // 新しいアカウント名を検索\r
6329                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6330                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->NewName);\r
6331 \r
6332                 r2 = Search(c->AccountList, &t);\r
6333                 if (r2 != NULL)\r
6334                 {\r
6335                         // 指定した名前のアカウントはすでに存在する\r
6336                         UnlockList(c->AccountList);\r
6337 \r
6338                         Free(t.ClientOption);\r
6339                         CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);\r
6340                         return false;\r
6341                 }\r
6342 \r
6343                 Free(t.ClientOption);\r
6344 \r
6345                 Lock(r->lock);\r
6346                 {\r
6347                         // アカウントの動作状態チェック\r
6348                         if (r->ClientSession != NULL)\r
6349                         {\r
6350                                 // アカウントは動作中\r
6351                                 Unlock(r->lock);\r
6352                                 UnlockList(c->AccountList);\r
6353                                 CiSetError(c, ERR_ACCOUNT_ACTIVE);\r
6354 \r
6355                                 return false;\r
6356                         }\r
6357 \r
6358                         // アカウント名を更新\r
6359                         UniStrCpy(r->ClientOption->AccountName, sizeof(r->ClientOption->AccountName),\r
6360                                 rename->NewName);\r
6361 \r
6362                         CLog(c, "LC_RENAME_ACCOUNT", rename->OldName, rename->NewName);\r
6363 \r
6364                         ret = true;\r
6365                 }\r
6366                 Unlock(r->lock);\r
6367 \r
6368                 Sort(c->AccountList);\r
6369 \r
6370         }\r
6371         UnlockList(c->AccountList);\r
6372 \r
6373         CiSaveConfigurationFile(c);\r
6374 \r
6375         CiNotify(c);\r
6376 \r
6377         return ret;\r
6378 }\r
6379 \r
6380 // クライアント設定の設定\r
6381 bool CtSetClientConfig(CLIENT *c, CLIENT_CONFIG *o)\r
6382 {\r
6383         KEEP *k;\r
6384         // 引数チェック\r
6385         if (c == NULL || o == NULL)\r
6386         {\r
6387                 return false;\r
6388         }\r
6389 \r
6390         if (o->UseKeepConnect)\r
6391         {\r
6392                 if (IsEmptyStr(o->KeepConnectHost) ||\r
6393                         o->KeepConnectPort == 0 ||\r
6394                         o->KeepConnectPort >= 65536)\r
6395                 {\r
6396                         CiSetError(c, ERR_INVALID_PARAMETER);\r
6397                         return false;\r
6398                 }\r
6399         }\r
6400 \r
6401         Lock(c->lock);\r
6402         {\r
6403                 Copy(&c->Config, o, sizeof(CLIENT_CONFIG));\r
6404         }\r
6405         Unlock(c->lock);\r
6406 \r
6407         // 設定の保存\r
6408         CiSaveConfigurationFile(c);\r
6409 \r
6410         // Keep Connect の適用\r
6411         k = c->Keep;\r
6412         Lock(k->lock);\r
6413         {\r
6414                 if (o->UseKeepConnect)\r
6415                 {\r
6416                         StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);\r
6417                         k->ServerPort = c->Config.KeepConnectPort;\r
6418                         k->Interval = c->Config.KeepConnectInterval * 1000;\r
6419                         k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;\r
6420                         k->Enable = true;\r
6421                 }\r
6422                 else\r
6423                 {\r
6424                         k->Enable = false;\r
6425                 }\r
6426         }\r
6427         Unlock(k->lock);\r
6428 \r
6429         return true;\r
6430 }\r
6431 \r
6432 // ククライアント設定の取得\r
6433 bool CtGetClientConfig(CLIENT *c, CLIENT_CONFIG *o)\r
6434 {\r
6435         // 引数チェック\r
6436         if (c == NULL || o == NULL)\r
6437         {\r
6438                 return false;\r
6439         }\r
6440 \r
6441         Lock(c->lock);\r
6442         {\r
6443                 Copy(o, &c->Config, sizeof(CLIENT_CONFIG));\r
6444         }\r
6445         Unlock(c->lock);\r
6446 \r
6447         return true;\r
6448 }\r
6449 \r
6450 // アカウントのスタートアップ属性を解除する\r
6451 bool CtRemoveStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a)\r
6452 {\r
6453         bool ret;\r
6454         // 引数チェック\r
6455         if (c == NULL || a == NULL)\r
6456         {\r
6457                 return false;\r
6458         }\r
6459 \r
6460         ret = false;\r
6461 \r
6462         LockList(c->AccountList);\r
6463         {\r
6464                 ACCOUNT t, *r;\r
6465                 // アカウントの検索\r
6466 \r
6467                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6468                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);\r
6469 \r
6470                 r = Search(c->AccountList, &t);\r
6471                 if (r == NULL)\r
6472                 {\r
6473                         // 指定したアカウントは見つからない\r
6474                         UnlockList(c->AccountList);\r
6475 \r
6476                         Free(t.ClientOption);\r
6477                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6478                         return false;\r
6479                 }\r
6480 \r
6481                 Free(t.ClientOption);\r
6482 \r
6483                 Lock(r->lock);\r
6484                 {\r
6485                         // スタートアップアカウントを解除する\r
6486                         ret = true;\r
6487                         r->StartupAccount = false;\r
6488                 }\r
6489                 Unlock(r->lock);\r
6490         }\r
6491         UnlockList(c->AccountList);\r
6492 \r
6493         if (ret)\r
6494         {\r
6495                 CiSaveConfigurationFile(c);\r
6496                 CiNotify(c);\r
6497         }\r
6498 \r
6499         return ret;\r
6500 }\r
6501 \r
6502 // アカウントをスタートアップアカウントにする\r
6503 bool CtSetStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a)\r
6504 {\r
6505         bool ret;\r
6506         // 引数チェック\r
6507         if (c == NULL || a == NULL)\r
6508         {\r
6509                 return false;\r
6510         }\r
6511 \r
6512         ret = false;\r
6513 \r
6514         LockList(c->AccountList);\r
6515         {\r
6516                 ACCOUNT t, *r;\r
6517                 // アカウントの検索\r
6518 \r
6519                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6520                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);\r
6521 \r
6522                 r = Search(c->AccountList, &t);\r
6523                 if (r == NULL)\r
6524                 {\r
6525                         // 指定したアカウントは見つからない\r
6526                         UnlockList(c->AccountList);\r
6527 \r
6528                         Free(t.ClientOption);\r
6529                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6530                         return false;\r
6531                 }\r
6532 \r
6533                 Free(t.ClientOption);\r
6534 \r
6535                 Lock(r->lock);\r
6536                 {\r
6537                         // スタートアップアカウントにする\r
6538                         ret = true;\r
6539                         r->StartupAccount = true;\r
6540                 }\r
6541                 Unlock(r->lock);\r
6542         }\r
6543         UnlockList(c->AccountList);\r
6544 \r
6545         if (ret)\r
6546         {\r
6547                 CiSaveConfigurationFile(c);\r
6548                 CiNotify(c);\r
6549         }\r
6550 \r
6551         return ret;\r
6552 }\r
6553 \r
6554 // アカウントの削除\r
6555 bool CtDeleteAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a)\r
6556 {\r
6557         bool ret;\r
6558         // 引数チェック\r
6559         if (c == NULL || a == NULL)\r
6560         {\r
6561                 return false;\r
6562         }\r
6563 \r
6564         ret = false;\r
6565 \r
6566         LockList(c->AccountList);\r
6567         {\r
6568                 ACCOUNT t, *r;\r
6569                 // アカウントの検索\r
6570 \r
6571                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6572                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);\r
6573 \r
6574                 r = Search(c->AccountList, &t);\r
6575                 if (r == NULL)\r
6576                 {\r
6577                         // 指定したアカウントは見つからない\r
6578                         UnlockList(c->AccountList);\r
6579 \r
6580                         Free(t.ClientOption);\r
6581                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6582                         return false;\r
6583                 }\r
6584 \r
6585                 Free(t.ClientOption);\r
6586 \r
6587                 Lock(r->lock);\r
6588                 {\r
6589                         // アカウントの動作状態チェック\r
6590                         if (r->ClientSession != NULL)\r
6591                         {\r
6592                                 // アカウントは動作中\r
6593                                 Unlock(r->lock);\r
6594                                 UnlockList(c->AccountList);\r
6595                                 CiSetError(c, ERR_ACCOUNT_ACTIVE);\r
6596 \r
6597                                 return false;\r
6598                         }\r
6599 \r
6600                         // このアカウントをリストから削除する\r
6601                         Delete(c->AccountList, r);\r
6602                 }\r
6603                 Unlock(r->lock);\r
6604 \r
6605                 // このアカウントのメモリを解放する\r
6606                 CiFreeAccount(r);\r
6607 \r
6608                 CLog(c, "LC_DELETE_ACCOUNT", a->AccountName);\r
6609                 ret = true;\r
6610 \r
6611         }\r
6612         UnlockList(c->AccountList);\r
6613 \r
6614         if (ret)\r
6615         {\r
6616                 CiSaveConfigurationFile(c);\r
6617                 CiNotify(c);\r
6618         }\r
6619 \r
6620         return ret;\r
6621 }\r
6622 \r
6623 // アカウントの列挙\r
6624 bool CtEnumAccount(CLIENT *c, RPC_CLIENT_ENUM_ACCOUNT *e)\r
6625 {\r
6626         // 引数チェック\r
6627         if (c == NULL || e == NULL)\r
6628         {\r
6629                 return false;\r
6630         }\r
6631 \r
6632         LockList(c->AccountList);\r
6633         {\r
6634                 UINT i;\r
6635                 // アカウント件数\r
6636                 e->NumItem = LIST_NUM(c->AccountList);\r
6637                 e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);\r
6638 \r
6639                 for (i = 0;i < e->NumItem;i++)\r
6640                 {\r
6641                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
6642                         RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));\r
6643                         e->Items[i] = item;\r
6644 \r
6645                         // アカウント名\r
6646                         UniStrCpy(item->AccountName, sizeof(item->AccountName), a->ClientOption->AccountName);\r
6647 \r
6648                         // ユーザー名\r
6649                         StrCpy(item->UserName, sizeof(item->UserName), a->ClientAuth->Username);\r
6650 \r
6651                         // サーバー名\r
6652                         StrCpy(item->ServerName, sizeof(item->ServerName), a->ClientOption->Hostname);\r
6653 \r
6654                         // プロキシ種類\r
6655                         item->ProxyType = a->ClientOption->ProxyType;\r
6656 \r
6657                         // デバイス名\r
6658                         StrCpy(item->DeviceName, sizeof(item->DeviceName), a->ClientOption->DeviceName);\r
6659 \r
6660                         // プロキシ情報\r
6661                         if (item->ProxyType != PROXY_DIRECT)\r
6662                         {\r
6663                                 StrCpy(item->ProxyName, sizeof(item->ProxyName), a->ClientOption->ProxyName);\r
6664                         }\r
6665 \r
6666                         // スタートアップ\r
6667                         item->StartupAccount = a->StartupAccount;\r
6668 \r
6669                         // 動作フラグ\r
6670                         item->Active = (a->ClientSession == NULL ? false : true);\r
6671 \r
6672                         // 接続フラグ\r
6673                         item->Connected = (item->Active == false) ? false : a->ClientSession->ConnectSucceed;\r
6674 \r
6675                         // ポート番号\r
6676                         item->Port = a->ClientOption->Port;\r
6677 \r
6678                         // 仮想 HUB 名\r
6679                         StrCpy(item->HubName, sizeof(item->HubName), a->ClientOption->HubName);\r
6680 \r
6681                         item->CreateDateTime = a->CreateDateTime;\r
6682                         item->LastConnectDateTime = a->LastConnectDateTime;\r
6683                         item->UpdateDateTime = a->UpdateDateTime;\r
6684                 }\r
6685         }\r
6686         UnlockList(c->AccountList);\r
6687 \r
6688         return true;\r
6689 }\r
6690 \r
6691 // アカウントの設定\r
6692 bool CtSetAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a)\r
6693 {\r
6694         // 引数チェック\r
6695         if (c == NULL || a == NULL)\r
6696         {\r
6697                 return false;\r
6698         }\r
6699 \r
6700         // 既存のアカウントが存在するかどうかチェック\r
6701         LockList(c->AccountList);\r
6702         {\r
6703                 ACCOUNT t, *ret;\r
6704                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6705                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),\r
6706                         a->ClientOption->AccountName);\r
6707 \r
6708                 ret = Search(c->AccountList, &t);\r
6709                 if (ret == NULL)\r
6710                 {\r
6711                         // 存在しない\r
6712                         UnlockList(c->AccountList);\r
6713                         Free(t.ClientOption);\r
6714 \r
6715                         CiSetError(c, ERR_ACCOUNT_NOT_FOUND);\r
6716 \r
6717                         return false;\r
6718                 }\r
6719                 Free(t.ClientOption);\r
6720 \r
6721                 if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)\r
6722                 {\r
6723                         if (a->ClientAuth->ClientX == NULL ||\r
6724                                 a->ClientAuth->ClientX->is_compatible_bit == false ||\r
6725                                 a->ClientAuth->ClientK == NULL)\r
6726                         {\r
6727                                 // クライアント証明書が不正\r
6728                                 UnlockList(c->AccountList);\r
6729                                 CiSetError(c, ERR_NOT_RSA_1024);\r
6730                                 return false;\r
6731                         }\r
6732                 }\r
6733 \r
6734                 if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)\r
6735                 {\r
6736                         // サーバー証明書が不正\r
6737                         UnlockList(c->AccountList);\r
6738                         CiSetError(c, ERR_NOT_RSA_1024);\r
6739                         return false;\r
6740                 }\r
6741 \r
6742                 Lock(ret->lock);\r
6743                 {\r
6744 \r
6745 #if     0\r
6746                         // 現在のバージョンではアカウント動作中でも設定の書き換えは行われる\r
6747                         // (ただし次回接続時まで設定は適用されない)\r
6748                         if (ret->ClientSession != NULL)\r
6749                         {\r
6750                                 // アカウントが動作中である\r
6751                                 Unlock(ret->lock);\r
6752                                 UnlockList(c->AccountList);\r
6753 \r
6754                                 CiSetError(c, ERR_ACCOUNT_ACTIVE);\r
6755 \r
6756                                 return false;\r
6757                         }\r
6758 #endif\r
6759 \r
6760                         // クライアント認証データの削除\r
6761                         CiFreeClientAuth(ret->ClientAuth);\r
6762 \r
6763                         // クライアント認証データのコピー\r
6764                         ret->ClientAuth = CopyClientAuth(a->ClientAuth);\r
6765 \r
6766                         // クライアントオプションの削除\r
6767                         Free(ret->ClientOption);\r
6768 \r
6769                         // クライアントオプションのコピー\r
6770                         ret->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6771                         Copy(ret->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));\r
6772 \r
6773                         ret->StartupAccount = a->StartupAccount;\r
6774 \r
6775                         ret->CheckServerCert = a->CheckServerCert;\r
6776 \r
6777                         if (a->ServerCert != NULL)\r
6778                         {\r
6779                                 if (ret->ServerCert != NULL)\r
6780                                 {\r
6781                                         FreeX(ret->ServerCert);\r
6782                                 }\r
6783                                 ret->ServerCert = CloneX(a->ServerCert);\r
6784                         }\r
6785                         else\r
6786                         {\r
6787                                 if (ret->ServerCert != NULL)\r
6788                                 {\r
6789                                         FreeX(ret->ServerCert);\r
6790                                 }\r
6791                                 ret->ServerCert = false;\r
6792                         }\r
6793 \r
6794                         ret->UpdateDateTime = SystemTime64();\r
6795                 }\r
6796                 Unlock(ret->lock);\r
6797         }\r
6798         UnlockList(c->AccountList);\r
6799 \r
6800         CiSaveConfigurationFile(c);\r
6801 \r
6802         CiNotify(c);\r
6803 \r
6804         return true;\r
6805 }\r
6806 \r
6807 // アカウントの作成\r
6808 bool CtCreateAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a)\r
6809 {\r
6810         // 引数チェック\r
6811         if (c == NULL || a == NULL)\r
6812         {\r
6813                 return false;\r
6814         }\r
6815 \r
6816         // 既存のアカウントが存在するかどうかチェック\r
6817         LockList(c->AccountList);\r
6818         {\r
6819                 ACCOUNT t, *ret, *new_account;\r
6820                 t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6821                 UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),\r
6822                         a->ClientOption->AccountName);\r
6823 \r
6824                 ret = Search(c->AccountList, &t);\r
6825                 if (ret != NULL)\r
6826                 {\r
6827                         // すでに存在する\r
6828                         UnlockList(c->AccountList);\r
6829                         Free(t.ClientOption);\r
6830 \r
6831                         CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);\r
6832 \r
6833                         return false;\r
6834                 }\r
6835 \r
6836                 Free(t.ClientOption);\r
6837 \r
6838                 if (UniStrLen(a->ClientOption->AccountName) == 0)\r
6839                 {\r
6840                         // 名前が不正\r
6841                         UnlockList(c->AccountList);\r
6842                         CiSetError(c, ERR_INVALID_VALUE);\r
6843                         return false;\r
6844                 }\r
6845 \r
6846                 if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)\r
6847                 {\r
6848                         if (a->ClientAuth->ClientX == NULL ||\r
6849                                 a->ClientAuth->ClientX->is_compatible_bit == false ||\r
6850                                 a->ClientAuth->ClientK == NULL)\r
6851                         {\r
6852                                 // クライアント証明書が不正\r
6853                                 UnlockList(c->AccountList);\r
6854                                 CiSetError(c, ERR_NOT_RSA_1024);\r
6855                                 return false;\r
6856                         }\r
6857                 }\r
6858 \r
6859                 if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)\r
6860                 {\r
6861                         // サーバー証明書が不正\r
6862                         UnlockList(c->AccountList);\r
6863                         CiSetError(c, ERR_NOT_RSA_1024);\r
6864                         return false;\r
6865                 }\r
6866 \r
6867                 // 新しいアカウントを追加する\r
6868                 new_account = ZeroMalloc(sizeof(ACCOUNT));\r
6869                 new_account->lock = NewLock();\r
6870 \r
6871                 // クライアント認証データのコピー\r
6872                 new_account->ClientAuth = CopyClientAuth(a->ClientAuth);\r
6873 \r
6874                 // クライアントオプションのコピー\r
6875                 new_account->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
6876                 Copy(new_account->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));\r
6877 \r
6878                 new_account->StartupAccount = a->StartupAccount;\r
6879 \r
6880                 new_account->CheckServerCert = a->CheckServerCert;\r
6881                 if (a->ServerCert != NULL)\r
6882                 {\r
6883                         new_account->ServerCert = CloneX(a->ServerCert);\r
6884                 }\r
6885 \r
6886                 // ショートカットキー\r
6887                 if (IsZero(a->ShortcutKey, SHA1_SIZE))\r
6888                 {\r
6889                         Rand(new_account->ShortcutKey, SHA1_SIZE);\r
6890                 }\r
6891                 else\r
6892                 {\r
6893                         Copy(new_account->ShortcutKey, a->ShortcutKey, SHA1_SIZE);\r
6894                 }\r
6895 \r
6896                 new_account->CreateDateTime = new_account->UpdateDateTime = SystemTime64();\r
6897 \r
6898                 // リストに挿入する\r
6899                 Insert(c->AccountList, new_account);\r
6900 \r
6901                 CLog(c, "LC_NEW_ACCOUNT", a->ClientOption->AccountName);\r
6902         }\r
6903         UnlockList(c->AccountList);\r
6904 \r
6905         CiNormalizeAccountVLan(c);\r
6906 \r
6907         CiSaveConfigurationFile(c);\r
6908 \r
6909         CiNotify(c);\r
6910 \r
6911         return true;\r
6912 }\r
6913 \r
6914 // アカウント取得構造体の解放\r
6915 void CiFreeClientGetAccount(RPC_CLIENT_GET_ACCOUNT *a)\r
6916 {\r
6917         // 引数チェック\r
6918         if (a == NULL)\r
6919         {\r
6920                 return;\r
6921         }\r
6922 \r
6923         // アカウント情報の解放\r
6924         if (a->ServerCert != NULL)\r
6925         {\r
6926                 FreeX(a->ServerCert);\r
6927         }\r
6928         CiFreeClientAuth(a->ClientAuth);\r
6929         Free(a->ClientOption);\r
6930 }\r
6931 \r
6932 // アカウント作成構造体の解放\r
6933 void CiFreeClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *a)\r
6934 {\r
6935         // 引数チェック\r
6936         if (a == NULL)\r
6937         {\r
6938                 return;\r
6939         }\r
6940 \r
6941         // アカウント情報の解放\r
6942         if (a->ServerCert != NULL)\r
6943         {\r
6944                 FreeX(a->ServerCert);\r
6945         }\r
6946         CiFreeClientAuth(a->ClientAuth);\r
6947         Free(a->ClientOption);\r
6948 }\r
6949 \r
6950 // 仮想 LAN カードの停止\r
6951 bool CtDisableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)\r
6952 {\r
6953         UINT i;\r
6954         bool used;\r
6955         // 引数チェック\r
6956         if (c == NULL || vlan == NULL)\r
6957         {\r
6958                 return false;\r
6959         }\r
6960 \r
6961 #ifndef OS_WIN32\r
6962 \r
6963         if (GetOsInfo()->OsType == OSTYPE_MACOS_X)\r
6964         {\r
6965                 // MacOS X では仮想 LAN カードは増減できない\r
6966                 CiSetError(c, ERR_NOT_SUPPORTED);\r
6967                 return false;\r
6968         }\r
6969 \r
6970         // 指定した名前の仮想 LAN カードが 1 つ以上のアカウントによって使用されていない\r
6971         // かどうか確認する\r
6972         used = false;\r
6973         LockList(c->AccountList);\r
6974         {\r
6975                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
6976                 {\r
6977                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
6978                         if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)\r
6979                         {\r
6980                                 Lock(a->lock);\r
6981                                 {\r
6982                                         if (a->ClientSession != NULL)\r
6983                                         {\r
6984                                                 used = true;\r
6985                                         }\r
6986                                 }\r
6987                                 Unlock(a->lock);\r
6988                         }\r
6989                 }\r
6990         }\r
6991         UnlockList(c->AccountList);\r
6992 \r
6993         // 仮想 LAN カードを検索する\r
6994         LockList(c->UnixVLanList);\r
6995         {\r
6996                 UNIX_VLAN *v, t;\r
6997 \r
6998                 Zero(&t, sizeof(t));\r
6999                 StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);\r
7000 \r
7001                 v = Search(c->UnixVLanList, &t);\r
7002                 if (v == NULL)\r
7003                 {\r
7004                         UnlockList(c->UnixVLanList);\r
7005                         CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7006                         return false;\r
7007                 }\r
7008 \r
7009                 // 停止する\r
7010                 v->Enabled = false;\r
7011         }\r
7012         UnlockList(c->UnixVLanList);\r
7013 \r
7014         CiSaveConfigurationFile(c);\r
7015         CiNotify(c);\r
7016 \r
7017         return true;\r
7018 \r
7019 #else   // OS_WIN32\r
7020 \r
7021         // 指定した名前の仮想 LAN カードが 1 つ以上のアカウントによって使用されていない\r
7022         // かどうか確認する\r
7023         used = false;\r
7024         LockList(c->AccountList);\r
7025         {\r
7026                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
7027                 {\r
7028                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
7029                         if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)\r
7030                         {\r
7031                                 Lock(a->lock);\r
7032                                 {\r
7033                                         if (a->ClientSession != NULL)\r
7034                                         {\r
7035                                                 used = true;\r
7036                                         }\r
7037                                 }\r
7038                                 Unlock(a->lock);\r
7039                         }\r
7040                 }\r
7041         }\r
7042         UnlockList(c->AccountList);\r
7043 \r
7044 #if     0\r
7045         if (used)\r
7046         {\r
7047                 // 使用中\r
7048                 CiSetError(c, ERR_VLAN_IS_USED);\r
7049                 return false;\r
7050         }\r
7051 #endif\r
7052 \r
7053 \r
7054         // 仮想 LAN カードが存在しているかチェック\r
7055         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false)\r
7056         {\r
7057                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7058                 CiNotify(c);\r
7059                 return false;\r
7060         }\r
7061 \r
7062 \r
7063         if (MsIs64BitWindows() && Is32() && MsIsAdmin())\r
7064         {\r
7065                 // Windows は 64 bit だがこのコードは 32 bit であるので\r
7066                 // driver_installer を起動して処理を実行する\r
7067                 char tmp[MAX_SIZE];\r
7068 \r
7069                 Format(tmp, sizeof(tmp), "disablevlan %s", vlan->DeviceName);\r
7070 \r
7071                 if (MsExecDriverInstaller(tmp) == false)\r
7072                 {\r
7073                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7074                         CiNotify(c);\r
7075                         return false;\r
7076                 }\r
7077         }\r
7078         else\r
7079         {\r
7080                 // 仮想 LAN カードを停止\r
7081                 if (MsDisableVLan(vlan->DeviceName) == false)\r
7082                 {\r
7083                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7084                         CiNotify(c);\r
7085                         return false;\r
7086                 }\r
7087         }\r
7088 \r
7089         CiNotify(c);\r
7090 \r
7091         return true;\r
7092 \r
7093 #endif  // OS_WIN32\r
7094 \r
7095 }\r
7096 \r
7097 // 仮想 LAN カードの開始\r
7098 bool CtEnableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)\r
7099 {\r
7100         // 引数チェック\r
7101         if (c == NULL || vlan == NULL)\r
7102         {\r
7103                 return false;\r
7104         }\r
7105 \r
7106 #ifndef OS_WIN32\r
7107 \r
7108         if (GetOsInfo()->OsType == OSTYPE_MACOS_X)\r
7109         {\r
7110                 // MacOS X では仮想 LAN カードは増減できない\r
7111                 CiSetError(c, ERR_NOT_SUPPORTED);\r
7112                 return false;\r
7113         }\r
7114 \r
7115         // 仮想 LAN カードを検索する\r
7116         LockList(c->UnixVLanList);\r
7117         {\r
7118                 UNIX_VLAN *v, t;\r
7119 \r
7120                 Zero(&t, sizeof(t));\r
7121                 StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);\r
7122 \r
7123                 v = Search(c->UnixVLanList, &t);\r
7124                 if (v == NULL)\r
7125                 {\r
7126                         UnlockList(c->UnixVLanList);\r
7127                         CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7128                         return false;\r
7129                 }\r
7130 \r
7131                 // 有効にする\r
7132                 v->Enabled = true;\r
7133         }\r
7134         UnlockList(c->UnixVLanList);\r
7135 \r
7136         CiSaveConfigurationFile(c);\r
7137         CiNotify(c);\r
7138 \r
7139         return true;\r
7140 \r
7141 #else   // OS_WIN32\r
7142 \r
7143         // 仮想 LAN カードが存在しているかチェック\r
7144         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false)\r
7145         {\r
7146                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7147                 CiNotify(c);\r
7148                 return false;\r
7149         }\r
7150 \r
7151         if (MsIs64BitWindows() && Is32() && MsIsAdmin())\r
7152         {\r
7153                 // Windows は 64 bit だがこのコードは 32 bit であるので\r
7154                 // driver_installer を起動して処理を実行する\r
7155                 char tmp[MAX_SIZE];\r
7156 \r
7157                 Format(tmp, sizeof(tmp), "enablevlan %s", vlan->DeviceName);\r
7158 \r
7159                 if (MsExecDriverInstaller(tmp) == false)\r
7160                 {\r
7161                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7162                         CiNotify(c);\r
7163                         return false;\r
7164                 }\r
7165         }\r
7166         else\r
7167         {\r
7168                 // 仮想 LAN カードを開始\r
7169                 if (MsEnableVLan(vlan->DeviceName) == false)\r
7170                 {\r
7171                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7172                         CiNotify(c);\r
7173                         return false;\r
7174                 }\r
7175         }\r
7176 \r
7177         CiNotify(c);\r
7178 \r
7179         return true;\r
7180 \r
7181 #endif  // OS_WIN32\r
7182 \r
7183 }\r
7184 \r
7185 // 仮想 LAN カードの削除\r
7186 bool CtDeleteVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *d)\r
7187 {\r
7188         UINT i;\r
7189         bool used;\r
7190         // 引数チェック\r
7191         if (c == NULL || d == NULL)\r
7192         {\r
7193                 return false;\r
7194         }\r
7195 \r
7196 #ifndef OS_WIN32\r
7197 \r
7198         if (GetOsInfo()->OsType == OSTYPE_MACOS_X)\r
7199         {\r
7200                 // MacOS X では仮想 LAN カードは増減できない\r
7201                 CiSetError(c, ERR_NOT_SUPPORTED);\r
7202                 return false;\r
7203         }\r
7204 \r
7205         // 指定した名前の仮想 LAN カードが 1 つ以上のアカウントによって使用されていない\r
7206         // かどうか確認する\r
7207         used = false;\r
7208         LockList(c->AccountList);\r
7209         {\r
7210                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
7211                 {\r
7212                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
7213                         if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)\r
7214                         {\r
7215                                 used = true;\r
7216                         }\r
7217                 }\r
7218         }\r
7219         UnlockList(c->AccountList);\r
7220 \r
7221 #if     0\r
7222         if (used)\r
7223         {\r
7224                 // 使用中\r
7225                 CiSetError(c, ERR_VLAN_IS_USED);\r
7226                 return false;\r
7227         }\r
7228 #endif\r
7229 \r
7230         // 仮想 LAN カードを検索する\r
7231         LockList(c->UnixVLanList);\r
7232         {\r
7233                 UNIX_VLAN *v, t;\r
7234 \r
7235                 Zero(&t, sizeof(t));\r
7236                 StrCpy(t.Name, sizeof(t.Name), d->DeviceName);\r
7237 \r
7238                 v = Search(c->UnixVLanList, &t);\r
7239                 if (v == NULL)\r
7240                 {\r
7241                         UnlockList(c->UnixVLanList);\r
7242                         CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7243                         return false;\r
7244                 }\r
7245 \r
7246                 // 削除する\r
7247                 if (Delete(c->UnixVLanList, v))\r
7248                 {\r
7249                         Free(v);\r
7250                 }\r
7251 \r
7252                 CLog(c, "LC_DELETE_VLAN", d->DeviceName);\r
7253 \r
7254                 UnixVLanDelete(d->DeviceName);\r
7255         }\r
7256         UnlockList(c->UnixVLanList);\r
7257 \r
7258         CiNormalizeAccountVLan(c);\r
7259 \r
7260         CiSaveConfigurationFile(c);\r
7261         CiNotify(c);\r
7262 \r
7263         return true;\r
7264 \r
7265 #else   // OS_WIN32\r
7266 \r
7267         if (MsIsNt() == false)\r
7268         {\r
7269                 // Win9x では使用できない\r
7270                 CiSetError(c, ERR_NOT_SUPPORTED);\r
7271                 return false;\r
7272         }\r
7273 \r
7274         // 仮想 LAN カードが存在しているかチェック\r
7275         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, d->DeviceName) == false)\r
7276         {\r
7277                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7278                 return false;\r
7279         }\r
7280 \r
7281         // 指定した名前の仮想 LAN カードが 1 つ以上のアカウントによって使用されていない\r
7282         // かどうか確認する\r
7283         used = false;\r
7284         LockList(c->AccountList);\r
7285         {\r
7286                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
7287                 {\r
7288                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
7289                         if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)\r
7290                         {\r
7291                                 used = true;\r
7292                         }\r
7293                 }\r
7294         }\r
7295         UnlockList(c->AccountList);\r
7296 \r
7297 #if     0\r
7298         if (used)\r
7299         {\r
7300                 // 使用中\r
7301                 CiSetError(c, ERR_VLAN_IS_USED);\r
7302                 return false;\r
7303         }\r
7304 #endif\r
7305 \r
7306         if (MsIs64BitWindows() && Is32() && MsIsAdmin())\r
7307         {\r
7308                 // Windows は 64 bit だがこのコードは 32 bit であるので\r
7309                 // driver_installer を起動して処理を実行する\r
7310                 char tmp[MAX_SIZE];\r
7311 \r
7312                 Format(tmp, sizeof(tmp), "uninstvlan %s", d->DeviceName);\r
7313 \r
7314                 if (MsExecDriverInstaller(tmp) == false)\r
7315                 {\r
7316                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7317                         return false;\r
7318                 }\r
7319         }\r
7320         else\r
7321         {\r
7322                 // 仮想 LAN カードを直接削除\r
7323                 if (MsUninstallVLan(d->DeviceName) == false)\r
7324                 {\r
7325                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7326                         CiNotify(c);\r
7327                         return false;\r
7328                 }\r
7329         }\r
7330 \r
7331         CLog(c, "LC_DELETE_VLAN", d->DeviceName);\r
7332 \r
7333         CiNormalizeAccountVLan(c);\r
7334 \r
7335         CiNotify(c);\r
7336 \r
7337         return true;\r
7338 \r
7339 #endif  // OS_WIN32\r
7340 \r
7341 }\r
7342 \r
7343 // 最初の VLAN の名前を取得\r
7344 char *CiGetFirstVLan(CLIENT *c)\r
7345 {\r
7346         char *ret = NULL;\r
7347         RPC_CLIENT_ENUM_VLAN t;\r
7348         // 引数チェック\r
7349         if (c == NULL)\r
7350         {\r
7351                 return NULL;\r
7352         }\r
7353 \r
7354         Zero(&t, sizeof(t));\r
7355         if (CtEnumVLan(c, &t) == false)\r
7356         {\r
7357                 return NULL;\r
7358         }\r
7359 \r
7360         if (t.NumItem >= 1)\r
7361         {\r
7362                 UINT i;\r
7363                 char *tmp = t.Items[0]->DeviceName;\r
7364 \r
7365                 for (i = 0;i < t.NumItem;i++)\r
7366                 {\r
7367                         if (t.Items[i]->Enabled)\r
7368                         {\r
7369                                 tmp = t.Items[i]->DeviceName;\r
7370                         }\r
7371                 }\r
7372 \r
7373                 ret = CopyStr(tmp);\r
7374         }\r
7375 \r
7376         CiFreeClientEnumVLan(&t);\r
7377 \r
7378         return ret;\r
7379 }\r
7380 \r
7381 // 仮想 LAN カードの列挙\r
7382 bool CtEnumVLan(CLIENT *c, RPC_CLIENT_ENUM_VLAN *e)\r
7383 {\r
7384         UINT i;\r
7385         TOKEN_LIST *t;\r
7386         // 引数チェック\r
7387         if (c == NULL || e == NULL)\r
7388         {\r
7389                 return false;\r
7390         }\r
7391 \r
7392 #ifndef OS_WIN32\r
7393 \r
7394         LockList(c->UnixVLanList);\r
7395         {\r
7396                 e->NumItem = LIST_NUM(c->UnixVLanList);\r
7397                 e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);\r
7398 \r
7399                 for (i = 0;i < e->NumItem;i++)\r
7400                 {\r
7401                         RPC_CLIENT_ENUM_VLAN_ITEM *item;\r
7402                         UNIX_VLAN *v;\r
7403 \r
7404                         v = LIST_DATA(c->UnixVLanList, i);\r
7405                         e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));\r
7406                         item = e->Items[i];\r
7407 \r
7408                         item->Enabled = v->Enabled;\r
7409                         BinToStr(item->MacAddress, sizeof(item->MacAddress), v->MacAddress, 6);\r
7410                         StrCpy(item->DeviceName, sizeof(item->DeviceName), v->Name);\r
7411                         StrCpy(item->Version, sizeof(item->Version), c->Cedar->VerString);\r
7412                 }\r
7413         }\r
7414         UnlockList(c->UnixVLanList);\r
7415 \r
7416         return true;\r
7417 \r
7418 #else   // OS_WIN32\r
7419 \r
7420         // 列挙\r
7421         t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");\r
7422         if (t == NULL)\r
7423         {\r
7424                 // 列挙失敗\r
7425                 e->NumItem = 0;\r
7426                 e->Items = ZeroMalloc(0);\r
7427         }\r
7428         else\r
7429         {\r
7430                 // 列挙成功\r
7431                 e->NumItem = t->NumTokens;\r
7432                 e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);\r
7433 \r
7434                 for (i = 0;i < e->NumItem;i++)\r
7435                 {\r
7436                         char *tmp;\r
7437                         RPC_CLIENT_ENUM_VLAN_ITEM *item;\r
7438                         e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));\r
7439                         item = e->Items[i];\r
7440 \r
7441                         StrCpy(item->DeviceName, sizeof(item->DeviceName), t->Token[i]);\r
7442                         item->Enabled = MsIsVLanEnabled(item->DeviceName);\r
7443 \r
7444                         tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, item->DeviceName);\r
7445 \r
7446                         StrCpy(item->MacAddress, sizeof(item->MacAddress), tmp);\r
7447                         Free(tmp);\r
7448 \r
7449                         tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, item->DeviceName);\r
7450 \r
7451                         StrCpy(item->Version, sizeof(item->Version), tmp);\r
7452                         Free(tmp);\r
7453                 }\r
7454 \r
7455                 FreeToken(t);\r
7456         }\r
7457 \r
7458         return true;\r
7459 \r
7460 #endif  // OS_WIN32\r
7461 }\r
7462 \r
7463 // 仮想 LAN カード列挙体の解放\r
7464 void CiFreeClientEnumVLan(RPC_CLIENT_ENUM_VLAN *e)\r
7465 {\r
7466         UINT i;\r
7467         // 引数チェック\r
7468         if (e == NULL)\r
7469         {\r
7470                 return;\r
7471         }\r
7472 \r
7473         for (i = 0;i < e->NumItem;i++)\r
7474         {\r
7475                 Free(e->Items[i]);\r
7476         }\r
7477         Free(e->Items);\r
7478 }\r
7479 \r
7480 // 仮想 LAN カードに関する情報の設定\r
7481 bool CtSetVLan(CLIENT *c, RPC_CLIENT_SET_VLAN *set)\r
7482 {\r
7483         // 引数チェック\r
7484         if (c == NULL || set == NULL)\r
7485         {\r
7486                 return false;\r
7487         }\r
7488 \r
7489 #ifndef OS_WIN32\r
7490 \r
7491         LockList(c->UnixVLanList);\r
7492         {\r
7493                 UNIX_VLAN t, *r;\r
7494                 Zero(&t, sizeof(t));\r
7495                 StrCpy(t.Name, sizeof(t.Name), set->DeviceName);\r
7496 \r
7497                 r = Search(c->UnixVLanList, &t);\r
7498                 if (r == NULL)\r
7499                 {\r
7500                         // 存在しない\r
7501                         CiSetError(c, ERR_VLAN_ALREADY_EXISTS);\r
7502                         UnlockList(c->UnixVLanList);\r
7503                         return false;\r
7504                 }\r
7505 \r
7506                 StrToMac(r->MacAddress, set->MacAddress);\r
7507         }\r
7508         UnlockList(c->UnixVLanList);\r
7509 \r
7510         CiSaveConfigurationFile(c);\r
7511         CiNotify(c);\r
7512 \r
7513         return true;\r
7514 \r
7515 #else   // OS_WIN32\r
7516 \r
7517         // 指定された名前の仮想 LAN カードが存在するかチェック\r
7518         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, set->DeviceName) == false)\r
7519         {\r
7520                 // 存在していない\r
7521                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7522                 return false;\r
7523         }\r
7524 \r
7525         // MAC アドレスの設定\r
7526         MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, set->DeviceName, set->MacAddress);\r
7527 \r
7528         CiNotify(c);\r
7529 \r
7530         return true;\r
7531 \r
7532 #endif  // OS_WIN32\r
7533 }\r
7534 \r
7535 // 仮想 LAN カードに関する情報の取得\r
7536 bool CtGetVLan(CLIENT *c, RPC_CLIENT_GET_VLAN *get)\r
7537 {\r
7538         char *tmp;\r
7539         // 引数チェック\r
7540         if (c == NULL || get == NULL)\r
7541         {\r
7542                 return false;\r
7543         }\r
7544 \r
7545 #ifndef OS_WIN32\r
7546 \r
7547         // サポートされていない\r
7548         CiSetError(c, ERR_NOT_SUPPORTED);\r
7549         return false;\r
7550 \r
7551 #else   // OS_WIN32\r
7552 \r
7553         // 指定された名前の仮想 LAN カードが存在するかチェック\r
7554         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, get->DeviceName) == false)\r
7555         {\r
7556                 // 存在していない\r
7557                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7558                 return false;\r
7559         }\r
7560 \r
7561         // 動作状況\r
7562         get->Enabled = MsIsVLanEnabled(get->DeviceName);\r
7563 \r
7564         // MAC アドレス\r
7565         tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, get->DeviceName);\r
7566         StrCpy(get->MacAddress, sizeof(get->MacAddress), tmp);\r
7567         Free(tmp);\r
7568 \r
7569         // バージョン\r
7570         tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, get->DeviceName);\r
7571         StrCpy(get->Version, sizeof(get->Version), tmp);\r
7572         Free(tmp);\r
7573 \r
7574         // ファイル名\r
7575         tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG, get->DeviceName);\r
7576         StrCpy(get->FileName, sizeof(get->FileName), tmp);\r
7577         Free(tmp);\r
7578 \r
7579         // GUID\r
7580         tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG, get->DeviceName);\r
7581         StrCpy(get->Guid, sizeof(get->Guid), tmp);\r
7582         Free(tmp);\r
7583 \r
7584         return true;\r
7585 \r
7586 #endif  // OS_WIN32\r
7587 }\r
7588 \r
7589 // 仮想 LAN カードのアップグレード\r
7590 bool CtUpgradeVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)\r
7591 {\r
7592 #ifdef  OS_WIN32\r
7593         KAKUSHI *k = NULL;\r
7594 #endif  // OS_WIN32\r
7595 \r
7596         // 引数チェック\r
7597         if (c == NULL || create == NULL)\r
7598         {\r
7599                 return false;\r
7600         }\r
7601 \r
7602 #ifndef OS_WIN32\r
7603 \r
7604         // 常に成功\r
7605         return true;\r
7606 \r
7607 #else   // OS_WIN32\r
7608 \r
7609         if (MsIsNt() == false)\r
7610         {\r
7611                 // Win9x では不可\r
7612                 CiSetError(c, ERR_NOT_SUPPORTED);\r
7613                 return false;\r
7614         }\r
7615 \r
7616         // 指定された名前の LAN カードがすでに存在していないかどうかチェックする\r
7617         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) == false)\r
7618         {\r
7619                 // 存在していない\r
7620                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7621                 CiNotify(c);\r
7622                 return false;\r
7623         }\r
7624 \r
7625         if (MsIsVista() == false)\r
7626         {\r
7627                 k = InitKakushi();      \r
7628         }\r
7629 \r
7630 \r
7631         if (MsIsVista() == false)\r
7632         {\r
7633                 // インストールを行う (Windows Vista 以外)\r
7634                 if (MsUpgradeVLan(VLAN_ADAPTER_NAME_TAG,\r
7635                         VLAN_CONNECTION_NAME,\r
7636                         create->DeviceName) == false)\r
7637                 {\r
7638                         // インストール失敗\r
7639                         FreeKakushi(k);\r
7640                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7641                         CiNotify(c);\r
7642                         return false;\r
7643                 }\r
7644         }\r
7645         else\r
7646         {\r
7647                 // インストールを行う (Windows Vista)\r
7648                 char tmp[MAX_SIZE];\r
7649 \r
7650                 Format(tmp, sizeof(tmp), "upgradevlan %s", create->DeviceName);\r
7651 \r
7652                 if (CncExecDriverInstaller(tmp) == false)\r
7653                 {\r
7654                         // インストール失敗\r
7655                         FreeKakushi(k);\r
7656                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7657                         CiNotify(c);\r
7658                         return false;\r
7659                 }\r
7660         }\r
7661 \r
7662         FreeKakushi(k);\r
7663 \r
7664         CLog(c, "LC_UPDATE_VLAN", create->DeviceName);\r
7665 \r
7666         CiNotify(c);\r
7667 \r
7668         return true;\r
7669 \r
7670 #endif  // OS_WIN32\r
7671 }\r
7672 \r
7673 // 仮想 LAN カードの作成\r
7674 bool CtCreateVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)\r
7675 {\r
7676         TOKEN_LIST *t;\r
7677         UINT max_len;\r
7678 \r
7679 #ifdef  OS_WIN32\r
7680         KAKUSHI *k = NULL;\r
7681 #endif  // OS_WIN32\r
7682 \r
7683         // 引数チェック\r
7684         if (c == NULL || create == NULL)\r
7685         {\r
7686                 return false;\r
7687         }\r
7688 \r
7689 #ifndef OS_WIN32\r
7690 \r
7691         // Win32 以外\r
7692         if (GetOsInfo()->OsType == OSTYPE_MACOS_X)\r
7693         {\r
7694                 // MacOS X では仮想 LAN カードは増減できない\r
7695                 CiSetError(c, ERR_NOT_SUPPORTED);\r
7696                 return false;\r
7697         }\r
7698 \r
7699         // 指定された名前が有効かどうかチェックする\r
7700         if (IsSafeStr(create->DeviceName) == false)\r
7701         {\r
7702                 // 名前が不正\r
7703                 CiSetError(c, ERR_VLAN_INVALID_NAME);\r
7704                 return false;\r
7705         }\r
7706 \r
7707         // 指定した名前の LAN カードがすでに存在していないかどうかチェックする\r
7708         LockList(c->UnixVLanList);\r
7709         {\r
7710                 UNIX_VLAN t, *r;\r
7711                 Zero(&t, sizeof(t));\r
7712                 StrCpy(t.Name, sizeof(t.Name), create->DeviceName);\r
7713 \r
7714                 r = Search(c->UnixVLanList, &t);\r
7715                 if (r != NULL)\r
7716                 {\r
7717                         // すでに存在している\r
7718                         CiSetError(c, ERR_VLAN_ALREADY_EXISTS);\r
7719                         UnlockList(c->UnixVLanList);\r
7720                         return false;\r
7721                 }\r
7722 \r
7723                 // 登録する\r
7724                 r = ZeroMalloc(sizeof(UNIX_VLAN));\r
7725                 r->Enabled = true;\r
7726                 GenMacAddress(r->MacAddress);\r
7727                 StrCpy(r->Name, sizeof(r->Name), create->DeviceName);\r
7728 \r
7729                 // tap 作成\r
7730                 if (UnixVLanCreate(r->Name, r->MacAddress) == false)\r
7731                 {\r
7732                         // 失敗\r
7733                         Free(r);\r
7734                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7735                         UnlockList(c->UnixVLanList);\r
7736                         return false;\r
7737                 }\r
7738 \r
7739                 CLog(c, "LC_CREATE_VLAN", create->DeviceName);\r
7740 \r
7741                 Add(c->UnixVLanList, r);\r
7742         }\r
7743         UnlockList(c->UnixVLanList);\r
7744 \r
7745         CiNormalizeAccountVLan(c);\r
7746 \r
7747         CiNotify(c);\r
7748         CiSaveConfigurationFile(c);\r
7749 \r
7750         return true;\r
7751 \r
7752 #else   // OS_WIN32\r
7753 \r
7754         if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))\r
7755         {\r
7756                 // Win9x では LAN カードは 1 個しか作成できない\r
7757                 TOKEN_LIST *t;\r
7758 \r
7759                 t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");\r
7760                 if (t != NULL)\r
7761                 {\r
7762                         if (t->NumTokens >= 1)\r
7763                         {\r
7764                                 FreeToken(t);\r
7765                                 CiSetError(c, ERR_NOT_SUPPORTED);\r
7766                                 return false;\r
7767                         }\r
7768                         FreeToken(t);\r
7769                 }\r
7770         }\r
7771 \r
7772         // 指定された名前が有効かどうかチェックする\r
7773         if (IsSafeStr(create->DeviceName) == false)\r
7774         {\r
7775                 // 名前が不正\r
7776                 CiSetError(c, ERR_VLAN_INVALID_NAME);\r
7777                 return false;\r
7778         }\r
7779 \r
7780         max_len = MsIsNt() ? MAX_DEVICE_NAME_LEN : MAX_DEVICE_NAME_LEN_9X;\r
7781         if (StrLen(create->DeviceName) > max_len)\r
7782         {\r
7783                 // 名前が長すぎる\r
7784                 CiSetError(c, ERR_VLAN_INVALID_NAME);\r
7785                 return false;\r
7786         }\r
7787 \r
7788         // 指定された名前の LAN カードがすでに存在していないかどうかチェックする\r
7789         if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName))\r
7790         {\r
7791                 // すでに存在している\r
7792                 CiSetError(c, ERR_VLAN_ALREADY_EXISTS);\r
7793                 return false;\r
7794         }\r
7795 \r
7796         if (MsIsNt())\r
7797         {\r
7798                 if (MsIsVista() == false)\r
7799                 {\r
7800                         k = InitKakushi();\r
7801                 }\r
7802         }\r
7803 \r
7804         if (MsIsVista() == false)\r
7805         {\r
7806                 // インストールを行う (Windows Vista 以外)\r
7807                 if (MsInstallVLan(VLAN_ADAPTER_NAME_TAG, VLAN_CONNECTION_NAME, create->DeviceName) == false)\r
7808                 {\r
7809                         // インストール失敗\r
7810                         FreeKakushi(k);\r
7811                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7812                         CiNotify(c);\r
7813                         return false;\r
7814                 }\r
7815         }\r
7816         else\r
7817         {\r
7818                 // インストールを行う (Windows Vista)\r
7819                 char tmp[MAX_SIZE];\r
7820 \r
7821                 Format(tmp, sizeof(tmp), "instvlan %s", create->DeviceName);\r
7822 \r
7823                 if (CncExecDriverInstaller(tmp) == false)\r
7824                 {\r
7825                         // インストール失敗\r
7826                         FreeKakushi(k);\r
7827                         CiSetError(c, ERR_VLAN_INSTALL_ERROR);\r
7828                         CiNotify(c);\r
7829                         return false;\r
7830                 }\r
7831         }\r
7832 \r
7833         FreeKakushi(k);\r
7834 \r
7835         t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");\r
7836         if (t->NumTokens == 1)\r
7837         {\r
7838                 UINT i;\r
7839                 // インストールを行った結果、仮想 LAN カードが 1 つになった場合は\r
7840                 // 既存のすべてのアカウントの仮想 LAN カードをこの仮想 LAN カードにセットする\r
7841                 LockList(c->AccountList);\r
7842                 {\r
7843                         for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
7844                         {\r
7845                                 ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
7846                                 Lock(a->lock);\r
7847                                 {\r
7848                                         if (a->ClientOption != NULL)\r
7849                                         {\r
7850                                                 StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), create->DeviceName);\r
7851                                         }\r
7852                                 }\r
7853                                 Unlock(a->lock);\r
7854                         }\r
7855                 }\r
7856                 UnlockList(c->AccountList);\r
7857         }\r
7858         FreeToken(t);\r
7859 \r
7860         CLog(c, "LC_CREATE_VLAN", create->DeviceName);\r
7861 \r
7862         CiNormalizeAccountVLan(c);\r
7863 \r
7864         CiNotify(c);\r
7865 \r
7866         CiSaveConfigurationFile(c);\r
7867 \r
7868         if (MsIsNt() == false)\r
7869         {\r
7870                 if (GetOsInfo()->OsType == OSTYPE_WINDOWS_ME)\r
7871                 {\r
7872                         // Windows Me の場合は警告表示\r
7873                         MsgBox(NULL, 0x00000040L, _UU("CM_9X_VLAN_ME_MESSAGE"));\r
7874                 }\r
7875 \r
7876                 ReleaseThread(NewThread(Win9xRebootThread, NULL));\r
7877         }\r
7878 \r
7879         return true;\r
7880 \r
7881 #endif  // OS_WIN32\r
7882 }\r
7883 \r
7884 // セキュアデバイス内のオブジェクト列挙\r
7885 bool CtEnumObjectInSecure(CLIENT *c, RPC_ENUM_OBJECT_IN_SECURE *e)\r
7886 {\r
7887         UINT i;\r
7888         // 引数チェック\r
7889         if (c == NULL || e == NULL)\r
7890         {\r
7891                 return false;\r
7892         }\r
7893 \r
7894         e->NumItem = 5;\r
7895         e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);\r
7896         e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);\r
7897 \r
7898         for (i = 0;i < e->NumItem;i++)\r
7899         {\r
7900                 char tmp[MAX_SIZE];\r
7901                 Format(tmp, sizeof(tmp), "Test Object %u", i);\r
7902                 e->ItemName[i] = CopyStr(tmp);\r
7903                 e->ItemType[i] = (i % 2 == 0) ? false : true;\r
7904         }\r
7905 \r
7906         return true;\r
7907 }\r
7908 \r
7909 // 使用するセキュアデバイスの取得\r
7910 bool CtGetUseSecure(CLIENT *c, RPC_USE_SECURE *sec)\r
7911 {\r
7912         // 引数チェック\r
7913         if (c == NULL || sec == NULL)\r
7914         {\r
7915                 return false;\r
7916         }\r
7917 \r
7918         sec->DeviceId = c->UseSecureDeviceId;\r
7919 \r
7920         return true;\r
7921 }\r
7922 \r
7923 // 使用するセキュアデバイスの指定\r
7924 bool CtUseSecure(CLIENT *c, RPC_USE_SECURE *sec)\r
7925 {\r
7926         // 引数チェック\r
7927         if (c == NULL || sec == NULL)\r
7928         {\r
7929                 return false;\r
7930         }\r
7931 \r
7932 // クライアントマネージャに指定されたデバイスが存在するかどうかチェックしない\r
7933 /*      if (CheckSecureDeviceId(sec->DeviceId))\r
7934         {\r
7935                 c->UseSecureDeviceId = sec->DeviceId;\r
7936         }\r
7937         else\r
7938         {\r
7939                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
7940                 return false;\r
7941         }\r
7942 */\r
7943         c->UseSecureDeviceId = sec->DeviceId;\r
7944 \r
7945         CiSaveConfigurationFile(c);\r
7946 \r
7947         return true;\r
7948 }\r
7949 \r
7950 // セキュアデバイスの列挙\r
7951 bool CtEnumSecure(CLIENT *c, RPC_CLIENT_ENUM_SECURE *e)\r
7952 {\r
7953         LIST *o;\r
7954         UINT i;\r
7955         // 引数チェック\r
7956         if (c == NULL || e == NULL)\r
7957         {\r
7958                 return false;\r
7959         }\r
7960 \r
7961         o = GetSecureDeviceList();\r
7962 \r
7963         e->NumItem = LIST_NUM(o);\r
7964         e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);\r
7965 \r
7966         for (i = 0;i < LIST_NUM(o);i++)\r
7967         {\r
7968                 RPC_CLIENT_ENUM_SECURE_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));\r
7969                 SECURE_DEVICE *s = LIST_DATA(o, i);\r
7970 \r
7971                 item->DeviceId = s->Id;\r
7972                 StrCpy(item->DeviceName, sizeof(item->DeviceName), s->DeviceName);\r
7973                 StrCpy(item->Manufacturer, sizeof(item->Manufacturer), s->Manufacturer);\r
7974                 item->Type = s->Type;\r
7975 \r
7976                 e->Items[i] = item;\r
7977         }\r
7978 \r
7979         return true;\r
7980 }\r
7981 \r
7982 // セキュアデバイス列挙体の解放\r
7983 void CiFreeClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e)\r
7984 {\r
7985         UINT i;\r
7986         // 引数チェック\r
7987         if (e == NULL)\r
7988         {\r
7989                 return;\r
7990         }\r
7991 \r
7992         for (i = 0;i < e->NumItem;i++)\r
7993         {\r
7994                 Free(e->Items[i]);\r
7995         }\r
7996         Free(e->Items);\r
7997 }\r
7998 \r
7999 // RPC_GET_ISSUER の解放\r
8000 void CiFreeGetIssuer(RPC_GET_ISSUER *a)\r
8001 {\r
8002         // 引数チェック\r
8003         if (a == NULL)\r
8004         {\r
8005                 return;\r
8006         }\r
8007 \r
8008         if (a->issuer_x != NULL)\r
8009         {\r
8010                 FreeX(a->issuer_x);\r
8011         }\r
8012         if (a->x != NULL)\r
8013         {\r
8014                 FreeX(a->x);\r
8015         }\r
8016 }\r
8017 \r
8018 // 署名者の取得\r
8019 bool CtGetIssuer(CLIENT *c, RPC_GET_ISSUER *a)\r
8020 {\r
8021         X *x;\r
8022         // 引数チェック\r
8023         if (c == NULL || a == NULL)\r
8024         {\r
8025                 return false;\r
8026         }\r
8027 \r
8028         x = FindCaSignedX(c->Cedar->CaList, a->x);\r
8029         if (x == NULL)\r
8030         {\r
8031                 CiSetError(c, ERR_OBJECT_NOT_FOUND);;\r
8032                 return false;\r
8033         }\r
8034         else\r
8035         {\r
8036                 a->issuer_x = x;\r
8037                 if (a->x != NULL)\r
8038                 {\r
8039                         FreeX(a->x);\r
8040                         a->x = NULL;\r
8041                 }\r
8042                 return true;\r
8043         }\r
8044 }\r
8045 \r
8046 // CA 証明書の取得\r
8047 bool CtGetCa(CLIENT *c, RPC_GET_CA *get)\r
8048 {\r
8049         bool ret = true;\r
8050         X *cert = NULL;\r
8051         // 引数チェック\r
8052         if (c == NULL || get == NULL)\r
8053         {\r
8054                 return false;\r
8055         }\r
8056 \r
8057         LockList(c->Cedar->CaList);\r
8058         {\r
8059                 UINT i;\r
8060 \r
8061                 for (i = 0;i < LIST_NUM(c->Cedar->CaList);i++)\r
8062                 {\r
8063                         X *x = LIST_DATA(c->Cedar->CaList, i);\r
8064 \r
8065                         if (POINTER_TO_KEY(x) == get->Key)\r
8066                         {\r
8067                                 cert = CloneX(x);\r
8068                                 break;\r
8069                         }\r
8070                 }\r
8071         }\r
8072         UnlockList(c->Cedar->CaList);\r
8073 \r
8074         if (cert == NULL)\r
8075         {\r
8076                 // 証明書は存在しない\r
8077                 ret = false;\r
8078                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
8079         }\r
8080         else\r
8081         {\r
8082                 ret = true;\r
8083                 get->x = cert;\r
8084         }\r
8085 \r
8086         return ret;\r
8087 }\r
8088 \r
8089 // CA 証明書の削除\r
8090 bool CtDeleteCa(CLIENT *c, RPC_CLIENT_DELETE_CA *p)\r
8091 {\r
8092         bool ret;\r
8093         // 引数チェック\r
8094         if (c == NULL || p == NULL)\r
8095         {\r
8096                 return false;\r
8097         }\r
8098 \r
8099         ret = DeleteCa(c->Cedar, p->Key);\r
8100 \r
8101         if (ret == false)\r
8102         {\r
8103                 CiSetError(c, ERR_OBJECT_NOT_FOUND);\r
8104         }\r
8105 \r
8106         CiSaveConfigurationFile(c);\r
8107 \r
8108         return ret;\r
8109 }\r
8110 \r
8111 // CA 証明書の追加\r
8112 bool CtAddCa(CLIENT *c, RPC_CERT *cert)\r
8113 {\r
8114         // 引数チェック\r
8115         if (c == NULL || cert == NULL)\r
8116         {\r
8117                 return false;\r
8118         }\r
8119 \r
8120         if (cert->x->is_compatible_bit == false)\r
8121         {\r
8122                 CiSetError(c, ERR_NOT_RSA_1024);\r
8123                 return false;\r
8124         }\r
8125 \r
8126         AddCa(c->Cedar, cert->x);\r
8127 \r
8128         CiSaveConfigurationFile(c);\r
8129 \r
8130         return true;\r
8131 }\r
8132 \r
8133 // 信頼する CA の列挙\r
8134 bool CtEnumCa(CLIENT *c, RPC_CLIENT_ENUM_CA *e)\r
8135 {\r
8136         // 引数チェック\r
8137         if (c == NULL || e == NULL)\r
8138         {\r
8139                 return false;\r
8140         }\r
8141 \r
8142         Zero(e, sizeof(RPC_CLIENT_ENUM_CA));\r
8143 \r
8144         LockList(c->Cedar->CaList);\r
8145         {\r
8146                 UINT i;\r
8147                 e->NumItem = LIST_NUM(c->Cedar->CaList);\r
8148                 e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);\r
8149 \r
8150                 for (i = 0;i < e->NumItem;i++)\r
8151                 {\r
8152                         X *x = LIST_DATA(c->Cedar->CaList, i);\r
8153                         e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));\r
8154                         GetAllNameFromNameEx(e->Items[i]->SubjectName, sizeof(e->Items[i]->SubjectName), x->subject_name);\r
8155                         GetAllNameFromNameEx(e->Items[i]->IssuerName, sizeof(e->Items[i]->IssuerName), x->issuer_name);\r
8156                         e->Items[i]->Expires = x->notAfter;\r
8157                         e->Items[i]->Key = POINTER_TO_KEY(x);\r
8158                 }\r
8159         }\r
8160         UnlockList(c->Cedar->CaList);\r
8161 \r
8162         return true;\r
8163 }\r
8164 \r
8165 // CA 列挙体を解放する\r
8166 void CiFreeClientEnumCa(RPC_CLIENT_ENUM_CA *e)\r
8167 {\r
8168         UINT i;\r
8169         // 引数チェック\r
8170         if (e == NULL)\r
8171         {\r
8172                 return;\r
8173         }\r
8174 \r
8175         for (i = 0;i < e->NumItem;i++)\r
8176         {\r
8177                 RPC_CLIENT_ENUM_CA_ITEM *ca = e->Items[i];\r
8178                 Free(ca);\r
8179         }\r
8180         Free(e->Items);\r
8181 }\r
8182 \r
8183 // パスワードの設定の取得\r
8184 bool CtGetPasswordSetting(CLIENT *c, RPC_CLIENT_PASSWORD_SETTING *a)\r
8185 {\r
8186         UCHAR hash[SHA1_SIZE];\r
8187         // 引数チェック\r
8188         if (c == NULL || a == NULL)\r
8189         {\r
8190                 return false;\r
8191         }\r
8192 \r
8193         Hash(hash, "", 0, true);\r
8194         if (Cmp(hash, c->EncryptedPassword, SHA1_SIZE) == 0)\r
8195         {\r
8196                 a->IsPasswordPresented = false;\r
8197         }\r
8198         else\r
8199         {\r
8200                 a->IsPasswordPresented = true;\r
8201         }\r
8202 \r
8203         a->PasswordRemoteOnly = c->PasswordRemoteOnly;\r
8204 \r
8205         return true;\r
8206 }\r
8207 \r
8208 // パスワードの設定\r
8209 bool CtSetPassword(CLIENT *c, RPC_CLIENT_PASSWORD *pass)\r
8210 {\r
8211         char *str;\r
8212         if (c == NULL)\r
8213         {\r
8214                 return false;\r
8215         }\r
8216         if (pass->Password == NULL)\r
8217         {\r
8218                 str = "";\r
8219         }\r
8220         else\r
8221         {\r
8222                 str = pass->Password;\r
8223         }\r
8224 \r
8225         if (StrCmp(str, "********") != 0)\r
8226         {\r
8227                 // パスワードのハッシュ\r
8228                 Hash(c->EncryptedPassword, str, StrLen(str), true);\r
8229         }\r
8230 \r
8231         c->PasswordRemoteOnly = pass->PasswordRemoteOnly;\r
8232 \r
8233         CLog(c, "LC_SET_PASSWORD");\r
8234 \r
8235         CiSaveConfigurationFile(c);\r
8236 \r
8237         return true;\r
8238 }\r
8239 \r
8240 // クライアントエラーコードの設定\r
8241 void CiSetError(CLIENT *c, UINT err)\r
8242 {\r
8243         // 引数チェック\r
8244         if (c == NULL)\r
8245         {\r
8246                 return;\r
8247         }\r
8248 \r
8249         c->Err = err;\r
8250 }\r
8251 \r
8252 // UNIX 仮想 LAN カード比較関数\r
8253 int CiCompareUnixVLan(void *p1, void *p2)\r
8254 {\r
8255         UNIX_VLAN *v1, *v2;\r
8256         if (p1 == NULL || p2 == NULL)\r
8257         {\r
8258                 return 0;\r
8259         }\r
8260         v1 = *(UNIX_VLAN **)p1;\r
8261         v2 = *(UNIX_VLAN **)p2;\r
8262         if (v1 == NULL || v2 == NULL)\r
8263         {\r
8264                 return 0;\r
8265         }\r
8266 \r
8267         return StrCmpi(v1->Name, v2->Name);\r
8268 }\r
8269 \r
8270 // 不正な VLAN 名が指定されているアカウントの設定を修正する\r
8271 void CiNormalizeAccountVLan(CLIENT *c)\r
8272 {\r
8273         bool b = false;\r
8274         char *name;\r
8275         UINT i;\r
8276         // 引数チェック\r
8277         if (c == NULL)\r
8278         {\r
8279                 return;\r
8280         }\r
8281 \r
8282         name = CiGetFirstVLan(c);\r
8283 \r
8284         if (name != NULL)\r
8285         {\r
8286                 LockList(c->AccountList);\r
8287                 {\r
8288                         for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
8289                         {\r
8290                                 ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
8291 \r
8292                                 Lock(a->lock);\r
8293                                 {\r
8294                                         if (a->ClientOption != NULL)\r
8295                                         {\r
8296                                                 if (CiIsVLan(c, a->ClientOption->DeviceName) == false)\r
8297                                                 {\r
8298                                                         StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),\r
8299                                                                 name);\r
8300                                                         b = true;\r
8301                                                 }\r
8302                                         }\r
8303                                 }\r
8304                                 Unlock(a->lock);\r
8305                         }\r
8306                 }\r
8307                 UnlockList(c->AccountList);\r
8308 \r
8309                 Free(name);\r
8310         }\r
8311 \r
8312         if (b)\r
8313         {\r
8314                 CiNotify(c);\r
8315                 CiSaveConfigurationFile(c);\r
8316         }\r
8317 }\r
8318 \r
8319 // 指定した名前の仮想 LAN カードが存在しているかどうか調べる\r
8320 bool CiIsVLan(CLIENT *c, char *name)\r
8321 {\r
8322         // 引数チェック\r
8323         if (c == NULL || name == NULL)\r
8324         {\r
8325                 return false;\r
8326         }\r
8327 \r
8328 #ifdef  OS_WIN32\r
8329         {\r
8330                 TOKEN_LIST *t;\r
8331                 UINT i;\r
8332 \r
8333                 t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");\r
8334                 if (t == NULL)\r
8335                 {\r
8336                         return false;\r
8337                 }\r
8338 \r
8339                 for (i = 0;i < t->NumTokens;i++)\r
8340                 {\r
8341                         if (StrCmpi(t->Token[i], name) == 0)\r
8342                         {\r
8343                                 FreeToken(t);\r
8344                                 return true;\r
8345                         }\r
8346                 }\r
8347 \r
8348                 FreeToken(t);\r
8349 \r
8350                 return false;\r
8351         }\r
8352 #else   // OS_WIN32\r
8353         {\r
8354                 UNIX_VLAN *v;\r
8355                 UINT i;\r
8356                 bool ret = false;\r
8357 \r
8358                 LockList(c->UnixVLanList);\r
8359                 {\r
8360                         for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)\r
8361                         {\r
8362                                 v = (UNIX_VLAN *)LIST_DATA(c->UnixVLanList, i);\r
8363                                 if (StrCmpi(v->Name, name) == 0)\r
8364                                 {\r
8365                                         ret = true;\r
8366                                 }\r
8367                         }\r
8368                 }\r
8369                 UnlockList(c->UnixVLanList);\r
8370 \r
8371                 return ret;\r
8372         }\r
8373 #endif  // OS_WIN32\r
8374 }\r
8375 \r
8376 // すべての接続アカウントにおいて、存在しない仮想 LAN カードが指定されている場合で\r
8377 // 現在の仮想 LAN カードが 1 枚だけの場合は、その仮想 LAN カードに指定しなおす\r
8378 void CiSetVLanToDefault(CLIENT *c)\r
8379 {\r
8380         char device_name[MAX_SIZE];\r
8381         // 引数チェック\r
8382         if (c == NULL)\r
8383         {\r
8384                 return;\r
8385         }\r
8386 \r
8387 #ifdef  OS_WIN32\r
8388         {\r
8389                 TOKEN_LIST *t;\r
8390 \r
8391                 t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");\r
8392                 if (t == NULL)\r
8393                 {\r
8394                         return;\r
8395                 }\r
8396                 if (t->NumTokens != 1)\r
8397                 {\r
8398                         FreeToken(t);\r
8399                         return;\r
8400                 }\r
8401                 StrCpy(device_name, sizeof(device_name), t->Token[0]);\r
8402                 FreeToken(t);\r
8403         }\r
8404 #else   // OS_WIN32\r
8405         {\r
8406                 UINT i;\r
8407                 UNIX_VLAN *v;\r
8408 \r
8409                 LockList(c->UnixVLanList);\r
8410 \r
8411                 if (LIST_NUM(c->UnixVLanList) != 1)\r
8412                 {\r
8413                         UnlockList(c->UnixVLanList);\r
8414                         return;\r
8415                 }\r
8416                 v = LIST_DATA(c->UnixVLanList, 0);\r
8417                 StrCpy(device_name, sizeof(device_name), v->Name);\r
8418 \r
8419                 UnlockList(c->UnixVLanList);\r
8420         }\r
8421 #endif  // OS_WIN32\r
8422 \r
8423         {\r
8424                 UINT i;\r
8425                 LockList(c->AccountList);\r
8426                 {\r
8427                         for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
8428                         {\r
8429                                 ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
8430 \r
8431                                 Lock(a->lock);\r
8432                                 {\r
8433                                         if (CiIsVLan(c, a->ClientOption->DeviceName) == false)\r
8434                                         {\r
8435                                                 StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),\r
8436                                                         device_name);\r
8437                                         }\r
8438                                 }\r
8439                                 Unlock(a->lock);\r
8440                         }\r
8441                 }\r
8442                 UnlockList(c->AccountList);\r
8443         }\r
8444 }\r
8445 \r
8446 // 設定の初期化\r
8447 void CiInitConfiguration(CLIENT *c)\r
8448 {\r
8449         // 引数チェック\r
8450         if (c == NULL)\r
8451         {\r
8452                 return;\r
8453         }\r
8454 \r
8455 #ifdef  OS_UNIX\r
8456         // VLAN 初期化\r
8457         UnixVLanInit();\r
8458 #endif   // OS_UNIX\r
8459 \r
8460         // アカウントリスト\r
8461         c->AccountList = NewList(CiCompareAccount);\r
8462 \r
8463         // Unix 版 VLAN リスト\r
8464         if (OS_IS_UNIX(GetOsInfo()->OsType))\r
8465         {\r
8466                 c->UnixVLanList = NewList(CiCompareUnixVLan);\r
8467         }\r
8468 \r
8469         // 設定ファイルの読み込み\r
8470         CLog(c, "LC_LOAD_CONFIG_1");\r
8471         if (CiLoadConfigurationFile(c) == false)\r
8472         {\r
8473                 CLog(c, "LC_LOAD_CONFIG_3");\r
8474                 // 設定ファイルが存在しないので初期設定を行う\r
8475                 // パスワードを空にする\r
8476                 Hash(c->EncryptedPassword, "", 0, true);\r
8477                 // クライアント設定を初期化\r
8478                 if (OS_IS_WINDOWS(GetOsInfo()->OsType))\r
8479                 {\r
8480                         // Windows の場合はリモートを禁止\r
8481                         c->Config.AllowRemoteConfig = false;\r
8482                 }\r
8483                 else\r
8484                 {\r
8485                         // UNIX の場合もリモートを禁止\r
8486                         c->Config.AllowRemoteConfig = false;\r
8487                 }\r
8488                 StrCpy(c->Config.KeepConnectHost, sizeof(c->Config.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);\r
8489                 c->Config.KeepConnectPort = CLIENT_DEFAULT_KEEPALIVE_PORT;\r
8490                 c->Config.KeepConnectProtocol = CONNECTION_UDP;\r
8491                 c->Config.KeepConnectInterval = CLIENT_DEFAULT_KEEPALIVE_INTERVAL;\r
8492                 c->Config.UseKeepConnect = false;       // Client ではデフォルトでは接続維持機能を使用しない\r
8493                 // 自動ファイル削除器\r
8494                 c->Eraser = NewEraser(c->Logger, 0);\r
8495         }\r
8496         else\r
8497         {\r
8498                 CLog(c, "LC_LOAD_CONFIG_2");\r
8499         }\r
8500 \r
8501         // 仮想 LAN カードの適切な設定\r
8502         CiSetVLanToDefault(c);\r
8503 }\r
8504 \r
8505 // 設定の解放\r
8506 void CiFreeConfiguration(CLIENT *c)\r
8507 {\r
8508         UINT i;\r
8509         // 引数チェック\r
8510         if (c == NULL)\r
8511         {\r
8512                 return;\r
8513         }\r
8514 \r
8515         // 設定ファイルへ書き込み\r
8516         CiSaveConfigurationFile(c);\r
8517 \r
8518         // 設定ファイル解放\r
8519         FreeCfgRw(c->CfgRw);\r
8520 \r
8521         // アカウントリストの解放\r
8522         for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
8523         {\r
8524                 ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
8525 \r
8526                 CiFreeAccount(a);\r
8527         }\r
8528         ReleaseList(c->AccountList);\r
8529 \r
8530         if (c->UnixVLanList != NULL)\r
8531         {\r
8532                 // UNIX 版 VLAN リストの解放\r
8533                 for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)\r
8534                 {\r
8535                         UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);\r
8536                         Free(v);\r
8537                 }\r
8538                 ReleaseList(c->UnixVLanList);\r
8539         }\r
8540         c->UnixVLanList = NULL;\r
8541 \r
8542 #ifdef  OS_UNIX\r
8543         // VLAN 解放\r
8544         UnixVLanFree();\r
8545 #endif  // OS_UNIX\r
8546 }\r
8547 \r
8548 // 証明書取得データの解放\r
8549 void CiFreeGetCa(RPC_GET_CA *a)\r
8550 {\r
8551         // 引数チェック\r
8552         if (a == NULL)\r
8553         {\r
8554                 return;\r
8555         }\r
8556 \r
8557         FreeX(a->x);\r
8558 }\r
8559 \r
8560 // クライアント認証データの解放\r
8561 void CiFreeClientAuth(CLIENT_AUTH *auth)\r
8562 {\r
8563         // 引数チェック\r
8564         if (auth == NULL)\r
8565         {\r
8566                 return;\r
8567         }\r
8568 \r
8569         if (auth->ClientX != NULL)\r
8570         {\r
8571                 FreeX(auth->ClientX);\r
8572         }\r
8573         if (auth->ClientK != NULL)\r
8574         {\r
8575                 FreeK(auth->ClientK);\r
8576         }\r
8577 \r
8578         Free(auth);\r
8579 }\r
8580 \r
8581 // アカウントの解放\r
8582 void CiFreeAccount(ACCOUNT *a)\r
8583 {\r
8584         // 引数チェック\r
8585         if (a == NULL)\r
8586         {\r
8587                 return;\r
8588         }\r
8589 \r
8590         // ロック解放\r
8591         DeleteLock(a->lock);\r
8592 \r
8593         // クライアントオプションの解放\r
8594         Free(a->ClientOption);\r
8595 \r
8596         // クライアント認証データの解放\r
8597         CiFreeClientAuth(a->ClientAuth);\r
8598 \r
8599         if (a->ServerCert != NULL)\r
8600         {\r
8601                 FreeX(a->ServerCert);\r
8602         }\r
8603 \r
8604         Free(a);\r
8605 }\r
8606 \r
8607 // アカウントのソート\r
8608 int CiCompareAccount(void *p1, void *p2)\r
8609 {\r
8610         ACCOUNT *a1, *a2;\r
8611         if (p1 == NULL || p2 == NULL)\r
8612         {\r
8613                 return 0;\r
8614         }\r
8615         a1 = *(ACCOUNT **)p1;\r
8616         a2 = *(ACCOUNT **)p2;\r
8617         if (a1 == NULL || a2 == NULL)\r
8618         {\r
8619                 return 0;\r
8620         }\r
8621 \r
8622         return UniStrCmpi(a1->ClientOption->AccountName, a2->ClientOption->AccountName);\r
8623 }\r
8624 \r
8625 // クライアントコンフィグレーションの読み込み\r
8626 void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f)\r
8627 {\r
8628         // 引数チェック\r
8629         if (c == NULL || f == NULL)\r
8630         {\r
8631                 return;\r
8632         }\r
8633 \r
8634         c->UseKeepConnect = CfgGetBool(f, "UseKeepConnect");\r
8635         CfgGetStr(f, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));\r
8636         c->KeepConnectPort = CfgGetInt(f, "KeepConnectPort");\r
8637         c->KeepConnectProtocol = CfgGetInt(f, "KeepConnectProtocol");\r
8638         c->AllowRemoteConfig = CfgGetBool(f, "AllowRemoteConfig");\r
8639         c->KeepConnectInterval = MAKESURE(CfgGetInt(f, "KeepConnectInterval"), KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);\r
8640 }\r
8641 \r
8642 // クライアント認証データの読み込み\r
8643 CLIENT_AUTH *CiLoadClientAuth(FOLDER *f)\r
8644 {\r
8645         CLIENT_AUTH *a;\r
8646         char *s;\r
8647         BUF *b;\r
8648         // 引数チェック\r
8649         if (f == NULL)\r
8650         {\r
8651                 return NULL;\r
8652         }\r
8653 \r
8654         a = ZeroMalloc(sizeof(CLIENT_AUTH));\r
8655 \r
8656         a->AuthType = CfgGetInt(f, "AuthType");\r
8657         CfgGetStr(f, "Username", a->Username, sizeof(a->Username));\r
8658 \r
8659         switch (a->AuthType)\r
8660         {\r
8661         case CLIENT_AUTHTYPE_ANONYMOUS:\r
8662                 break;\r
8663 \r
8664         case CLIENT_AUTHTYPE_PASSWORD:\r
8665                 CfgGetByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);\r
8666                 break;\r
8667 \r
8668         case CLIENT_AUTHTYPE_PLAIN_PASSWORD:\r
8669                 b = CfgGetBuf(f, "EncryptedPassword");\r
8670                 if (b != NULL)\r
8671                 {\r
8672                         s = DecryptPassword(b);\r
8673                         StrCpy(a->PlainPassword, sizeof(a->PlainPassword), s);\r
8674                         Free(s);\r
8675                         FreeBuf(b);\r
8676                 }\r
8677                 break;\r
8678 \r
8679         case CLIENT_AUTHTYPE_CERT:\r
8680                 b = CfgGetBuf(f, "ClientCert");\r
8681                 if (b != NULL)\r
8682                 {\r
8683                         a->ClientX = BufToX(b, false);\r
8684                 }\r
8685                 FreeBuf(b);\r
8686                 b = CfgGetBuf(f, "ClientKey");\r
8687                 if (b != NULL)\r
8688                 {\r
8689                         a->ClientK = BufToK(b, true, false, NULL);\r
8690                 }\r
8691                 FreeBuf(b);\r
8692                 break;\r
8693 \r
8694         case CLIENT_AUTHTYPE_SECURE:\r
8695                 CfgGetStr(f, "SecurePublicCertName", a->SecurePublicCertName, sizeof(a->SecurePublicCertName));\r
8696                 CfgGetStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName, sizeof(a->SecurePrivateKeyName));\r
8697                 break;\r
8698         }\r
8699 \r
8700         return a;\r
8701 }\r
8702 \r
8703 // クライアントオプションの読み込み\r
8704 CLIENT_OPTION *CiLoadClientOption(FOLDER *f)\r
8705 {\r
8706         CLIENT_OPTION *o;\r
8707         char *s;\r
8708         BUF *b;\r
8709         // 引数チェック\r
8710         if (f == NULL)\r
8711         {\r
8712                 return NULL;\r
8713         }\r
8714 \r
8715         o = ZeroMalloc(sizeof(CLIENT_OPTION));\r
8716 \r
8717         CfgGetUniStr(f, "AccountName", o->AccountName, sizeof(o->AccountName));\r
8718         CfgGetStr(f, "Hostname", o->Hostname, sizeof(o->Hostname));\r
8719         o->Port = CfgGetInt(f, "Port");\r
8720         o->PortUDP = CfgGetInt(f, "PortUDP");\r
8721         o->ProxyType = CfgGetInt(f, "ProxyType");\r
8722         CfgGetStr(f, "ProxyName", o->ProxyName, sizeof(o->ProxyName));\r
8723         o->ProxyPort = CfgGetInt(f, "ProxyPort");\r
8724         CfgGetStr(f, "ProxyUsername", o->ProxyUsername, sizeof(o->ProxyUsername));\r
8725         b = CfgGetBuf(f, "ProxyPassword");\r
8726         s = DecryptPassword(b);\r
8727         StrCpy(o->ProxyPassword, sizeof(o->ProxyPassword), s);\r
8728         Free(s);\r
8729         FreeBuf(b);\r
8730         o->NumRetry = CfgGetInt(f, "NumRetry");\r
8731         o->RetryInterval = CfgGetInt(f, "RetryInterval");\r
8732         CfgGetStr(f, "HubName", o->HubName, sizeof(o->HubName));\r
8733         o->MaxConnection = CfgGetInt(f, "MaxConnection");\r
8734         o->UseEncrypt = CfgGetBool(f, "UseEncrypt");\r
8735         o->UseCompress = CfgGetBool(f, "UseCompress");\r
8736         o->HalfConnection = CfgGetBool(f, "HalfConnection");\r
8737         o->NoRoutingTracking = CfgGetBool(f, "NoRoutingTracking");\r
8738         CfgGetStr(f, "DeviceName", o->DeviceName, sizeof(o->DeviceName));\r
8739         o->AdditionalConnectionInterval = CfgGetInt(f, "AdditionalConnectionInterval");\r
8740         o->HideStatusWindow = CfgGetBool(f, "HideStatusWindow");\r
8741         o->HideNicInfoWindow = CfgGetBool(f, "HideNicInfoWindow");\r
8742         o->ConnectionDisconnectSpan = CfgGetInt(f, "ConnectionDisconnectSpan");\r
8743         o->RequireMonitorMode = CfgGetBool(f, "RequireMonitorMode");\r
8744         o->RequireBridgeRoutingMode = CfgGetBool(f, "RequireBridgeRoutingMode");\r
8745         o->DisableQoS = CfgGetBool(f, "DisableQoS");\r
8746         o->FromAdminPack = CfgGetBool(f, "FromAdminPack");\r
8747         o->NoTls1 = CfgGetBool(f, "NoTls1");\r
8748 \r
8749         return o;\r
8750 }\r
8751 \r
8752 // アカウントデータの読み込み\r
8753 ACCOUNT *CiLoadClientAccount(FOLDER *f)\r
8754 {\r
8755         ACCOUNT *a;\r
8756         FOLDER *client_option_folder, *client_auth_folder;\r
8757         BUF *b;\r
8758         char tmp[64];\r
8759         // 引数チェック\r
8760         if (f == NULL)\r
8761         {\r
8762                 return NULL;\r
8763         }\r
8764 \r
8765         client_option_folder = CfgGetFolder(f, "ClientOption");\r
8766 \r
8767         if (client_option_folder != NULL)\r
8768         {\r
8769                 // すでに登録されているアカウント名と一致するかどうか比較する\r
8770         }\r
8771 \r
8772         client_auth_folder = CfgGetFolder(f, "ClientAuth");\r
8773 \r
8774         if (client_option_folder == NULL || client_auth_folder == NULL)\r
8775         {\r
8776                 return NULL;\r
8777         }\r
8778 \r
8779         a = ZeroMalloc(sizeof(ACCOUNT));\r
8780         a->lock = NewLock();\r
8781 \r
8782         a->ClientOption = CiLoadClientOption(client_option_folder);\r
8783         a->ClientAuth = CiLoadClientAuth(client_auth_folder);\r
8784 \r
8785         a->StartupAccount = CfgGetBool(f, "StartupAccount");\r
8786         a->CheckServerCert = CfgGetBool(f, "CheckServerCert");\r
8787         a->CreateDateTime = CfgGetInt64(f, "CreateDateTime");\r
8788         a->UpdateDateTime = CfgGetInt64(f, "UpdateDateTime");\r
8789         a->LastConnectDateTime = CfgGetInt64(f, "LastConnectDateTime");\r
8790 \r
8791         b = CfgGetBuf(f, "ServerCert");\r
8792         if (b != NULL)\r
8793         {\r
8794                 a->ServerCert = BufToX(b, false);\r
8795                 FreeBuf(b);\r
8796         }\r
8797 \r
8798         if (CfgGetStr(f, "ShortcutKey", tmp, sizeof(tmp)))\r
8799         {\r
8800                 BUF *b = StrToBin(tmp);\r
8801                 if (b->Size == SHA1_SIZE)\r
8802                 {\r
8803                         Copy(a->ShortcutKey, b->Buf, SHA1_SIZE);\r
8804                 }\r
8805                 FreeBuf(b);\r
8806         }\r
8807 \r
8808         if (IsZero(a->ShortcutKey, SHA1_SIZE))\r
8809         {\r
8810                 Rand(a->ShortcutKey, SHA1_SIZE);\r
8811         }\r
8812 \r
8813         return a;\r
8814 }\r
8815 \r
8816 // アカウントデータベースの読み込み\r
8817 void CiLoadAccountDatabase(CLIENT *c, FOLDER *f)\r
8818 {\r
8819         TOKEN_LIST *t;\r
8820         UINT i;\r
8821         // 引数チェック\r
8822         if (c == NULL || f == NULL)\r
8823         {\r
8824                 return;\r
8825         }\r
8826 \r
8827         t = CfgEnumFolderToTokenList(f);\r
8828         if (t == NULL)\r
8829         {\r
8830                 return;\r
8831         }\r
8832 \r
8833         for (i = 0;i < t->NumTokens;i++)\r
8834         {\r
8835                 FOLDER *ff = CfgGetFolder(f, t->Token[i]);\r
8836 \r
8837                 if (ff != NULL)\r
8838                 {\r
8839                         ACCOUNT *a = CiLoadClientAccount(ff);\r
8840                         if (a != NULL)\r
8841                         {\r
8842                                 Add(c->AccountList, a);\r
8843                         }\r
8844                 }\r
8845         }\r
8846 \r
8847         Sort(c->AccountList);\r
8848 \r
8849         FreeToken(t);\r
8850 }\r
8851 \r
8852 // ルート CA 証明書を読み込む\r
8853 void CiLoadCACert(CLIENT *c, FOLDER *f)\r
8854 {\r
8855         BUF *b;\r
8856         X *x;\r
8857         // 引数チェック\r
8858         if (c == NULL || f == NULL)\r
8859         {\r
8860                 return;\r
8861         }\r
8862 \r
8863         b = CfgGetBuf(f, "X509");\r
8864         if (b == NULL)\r
8865         {\r
8866                 return;\r
8867         }\r
8868 \r
8869         x = BufToX(b, false);\r
8870 \r
8871         AddCa(c->Cedar, x);\r
8872 \r
8873         FreeX(x);\r
8874 \r
8875         FreeBuf(b);\r
8876 }\r
8877 \r
8878 // ルート CA リストを読み込む\r
8879 void CiLoadCAList(CLIENT *c, FOLDER *f)\r
8880 {\r
8881         CEDAR *cedar;\r
8882         TOKEN_LIST *t;\r
8883         // 引数チェック\r
8884         if (c == NULL || f == NULL)\r
8885         {\r
8886                 return;\r
8887         }\r
8888 \r
8889         t = CfgEnumFolderToTokenList(f);\r
8890 \r
8891         cedar = c->Cedar;\r
8892 \r
8893         LockList(cedar->CaList);\r
8894         {\r
8895                 UINT i;\r
8896                 for (i = 0;i < t->NumTokens;i++)\r
8897                 {\r
8898                         FOLDER *folder = CfgGetFolder(f, t->Token[i]);\r
8899                         CiLoadCACert(c, folder);\r
8900                 }\r
8901         }\r
8902         UnlockList(cedar->CaList);\r
8903 \r
8904         FreeToken(t);\r
8905 }\r
8906 \r
8907 // VLAN を読み込む\r
8908 void CiLoadVLan(CLIENT *c, FOLDER *f)\r
8909 {\r
8910         char tmp[MAX_SIZE];\r
8911         UCHAR addr[6];\r
8912         BUF *b;\r
8913         UNIX_VLAN *v;\r
8914         // 引数チェック\r
8915         if (c == NULL || f == NULL)\r
8916         {\r
8917                 return;\r
8918         }\r
8919 \r
8920         if (CfgGetStr(f, "MacAddress", tmp, sizeof(tmp)) == false)\r
8921         {\r
8922                 return;\r
8923         }\r
8924 \r
8925         b = StrToBin(tmp);\r
8926         if (b == NULL)\r
8927         {\r
8928                 return;\r
8929         }\r
8930 \r
8931         if (b->Size != 6)\r
8932         {\r
8933                 FreeBuf(b);\r
8934                 return;\r
8935         }\r
8936 \r
8937         Copy(addr, b->Buf, 6);\r
8938 \r
8939         FreeBuf(b);\r
8940 \r
8941         if (IsZero(addr, 6))\r
8942         {\r
8943                 return;\r
8944         }\r
8945 \r
8946         v = ZeroMalloc(sizeof(UNIX_VLAN));\r
8947         Copy(v->MacAddress, addr, 6);\r
8948         StrCpy(v->Name, sizeof(v->Name), f->Name);\r
8949         v->Enabled = CfgGetBool(f, "Enabled");\r
8950 \r
8951         Add(c->UnixVLanList, v);\r
8952 \r
8953 #ifdef  OS_UNIX\r
8954         UnixVLanCreate(v->Name, v->MacAddress);\r
8955 #endif  // OS_UNIX\r
8956 }\r
8957 \r
8958 // VLAN リストを読み込む\r
8959 void CiLoadVLanList(CLIENT *c, FOLDER *f)\r
8960 {\r
8961         TOKEN_LIST *t;\r
8962         // 引数チェック\r
8963         if (c == NULL || f == NULL)\r
8964         {\r
8965                 return;\r
8966         }\r
8967 \r
8968         t = CfgEnumFolderToTokenList(f);\r
8969 \r
8970         LockList(c->UnixVLanList);\r
8971         {\r
8972                 UINT i;\r
8973                 for (i = 0;i < t->NumTokens;i++)\r
8974                 {\r
8975                         FOLDER *folder = CfgGetFolder(f, t->Token[i]);\r
8976                         CiLoadVLan(c, folder);\r
8977                 }\r
8978         }\r
8979         UnlockList(c->UnixVLanList);\r
8980 \r
8981         FreeToken(t);\r
8982 }\r
8983 \r
8984 // 設定ファイルから設定の読み込み\r
8985 bool CiReadSettingFromCfg(CLIENT *c, FOLDER *root)\r
8986 {\r
8987         FOLDER *config;\r
8988         FOLDER *cert;\r
8989         FOLDER *db;\r
8990         FOLDER *vlan;\r
8991         FOLDER *cmsetting;\r
8992         char user_agent[MAX_SIZE];\r
8993         // 引数チェック\r
8994         if (c == NULL || root == NULL)\r
8995         {\r
8996                 return false;\r
8997         }\r
8998 \r
8999         // Config と AccountDatabase の両方が無い場合は設定を初期化する\r
9000         config = CfgGetFolder(root, "Config");\r
9001         if (config == NULL)\r
9002         {\r
9003                 return false;\r
9004         }\r
9005 \r
9006         db = CfgGetFolder(root, "AccountDatabase");\r
9007         if (db == NULL)\r
9008         {\r
9009                 return false;\r
9010         }\r
9011 \r
9012         cmsetting = CfgGetFolder(root, "ClientManagerSetting");\r
9013 \r
9014         CiLoadClientConfig(&c->Config, config);\r
9015 \r
9016         // 自動ファイル削除器\r
9017         c->Eraser = NewEraser(c->Logger, CfgGetInt64(config, "AutoDeleteCheckDiskFreeSpaceMin"));\r
9018 \r
9019         if (OS_IS_UNIX(GetOsInfo()->OsType) && GetOsInfo()->OsType != OSTYPE_MACOS_X)\r
9020         {\r
9021                 // Unix 版仮想 LAN カード一覧の読み込み (MacOS の場合はしない)\r
9022                 vlan = CfgGetFolder(root, "UnixVLan");\r
9023                 if (vlan != NULL)\r
9024                 {\r
9025                         CiLoadVLanList(c, vlan);\r
9026                 }\r
9027         }\r
9028 \r
9029         if (GetOsInfo()->OsType == OSTYPE_MACOS_X)\r
9030         {\r
9031 #ifdef  OS_UNIX\r
9032                 UNIX_VLAN *uv;\r
9033 \r
9034                 // MacOS X の場合は Tap を作成する\r
9035                 if (UnixVLanCreate(CLIENT_MACOS_TAP_NAME, NULL) == false)\r
9036                 {\r
9037                         // 失敗 (強制終了)\r
9038                         CLog(c, "LC_TAP_NOT_FOUND");\r
9039                         Alert("tun/tap driver not found.", NULL);\r
9040                         exit(0);\r
9041                 }\r
9042 \r
9043                 uv = ZeroMalloc(sizeof(UNIX_VLAN));\r
9044                 uv->Enabled = true;\r
9045                 StrCpy(uv->Name, sizeof(uv->Name), CLIENT_MACOS_TAP_NAME);\r
9046                 Add(c->UnixVLanList, uv);\r
9047 #endif  // OS_UNIX\r
9048         }\r
9049 \r
9050         CiLoadAccountDatabase(c, db);\r
9051 \r
9052         if (CfgGetByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE) == false)\r
9053         {\r
9054                 Hash(c->EncryptedPassword, "", 0, true);\r
9055         }\r
9056 \r
9057         c->PasswordRemoteOnly = CfgGetBool(root, "PasswordRemoteOnly");\r
9058         c->UseSecureDeviceId = CfgGetInt(root, "UseSecureDeviceId");\r
9059 \r
9060         if (CfgGetStr(root, "UserAgent", user_agent, sizeof(user_agent)))\r
9061         {\r
9062                 if (IsEmptyStr(user_agent) == false)\r
9063                 {\r
9064                         Free(c->Cedar->HttpUserAgent);\r
9065                         c->Cedar->HttpUserAgent = CopyStr(user_agent);\r
9066                 }\r
9067         }\r
9068 \r
9069         cert = CfgGetFolder(root, "RootCA");\r
9070         if (cert != NULL)\r
9071         {\r
9072                 CiLoadCAList(c, cert);\r
9073         }\r
9074 \r
9075         c->DontSavePassword = CfgGetBool(root, "DontSavePassword");\r
9076 \r
9077         if (cmsetting != NULL)\r
9078         {\r
9079                 UINT ostype = GetOsInfo()->OsType;\r
9080                 // CM_SETTING\r
9081                 CM_SETTING *s = c->CmSetting;\r
9082 \r
9083                 if (OS_IS_UNIX(ostype) || OS_IS_WINDOWS_NT(ostype))\r
9084                 {\r
9085                         s->EasyMode = CfgGetBool(cmsetting, "EasyMode");\r
9086                 }\r
9087 \r
9088                 s->LockMode = CfgGetBool(cmsetting, "LockMode");\r
9089                 CfgGetByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));\r
9090         }\r
9091 \r
9092         return true;\r
9093 }\r
9094 \r
9095 // 設定ファイルの読み込み\r
9096 bool CiLoadConfigurationFile(CLIENT *c)\r
9097 {\r
9098         bool ret;\r
9099         FOLDER *root;\r
9100         // 引数チェック\r
9101         if (c == NULL)\r
9102         {\r
9103                 return false;\r
9104         }\r
9105 \r
9106         // 設定ファイルの読み込み\r
9107         c->CfgRw = NewCfgRw(&root, CLIENT_CONFIG_FILE_NAME);\r
9108 \r
9109         if (root == NULL)\r
9110         {\r
9111                 return false;\r
9112         }\r
9113 \r
9114         ret = CiReadSettingFromCfg(c, root);\r
9115 \r
9116         CfgDeleteFolder(root);\r
9117 \r
9118         return ret;\r
9119 }\r
9120 \r
9121 // CLIENT_CONFIG を書き込む\r
9122 void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config)\r
9123 {\r
9124         // 引数チェック\r
9125         if (cc == NULL || config == NULL)\r
9126         {\r
9127                 return;\r
9128         }\r
9129 \r
9130         CfgAddBool(cc, "UseKeepConnect", config->UseKeepConnect);\r
9131         CfgAddStr(cc, "KeepConnectHost", config->KeepConnectHost);\r
9132         CfgAddInt(cc, "KeepConnectPort", config->KeepConnectPort);\r
9133         CfgAddInt(cc, "KeepConnectProtocol", config->KeepConnectProtocol);\r
9134         CfgAddBool(cc, "AllowRemoteConfig", config->AllowRemoteConfig);\r
9135         CfgAddInt(cc, "KeepConnectInterval", config->KeepConnectInterval);\r
9136 }\r
9137 \r
9138 // クライアント認証データを書き込む\r
9139 void CiWriteClientAuth(FOLDER *f, CLIENT_AUTH *a)\r
9140 {\r
9141         BUF *b;\r
9142         // 引数チェック\r
9143         if (f == NULL || a == NULL)\r
9144         {\r
9145                 return;\r
9146         }\r
9147 \r
9148         CfgAddInt(f, "AuthType", a->AuthType);\r
9149         CfgAddStr(f, "Username", a->Username);\r
9150 \r
9151         switch (a->AuthType)\r
9152         {\r
9153         case CLIENT_AUTHTYPE_ANONYMOUS:\r
9154                 break;\r
9155 \r
9156         case CLIENT_AUTHTYPE_PASSWORD:\r
9157                 CfgAddByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);\r
9158                 break;\r
9159 \r
9160         case CLIENT_AUTHTYPE_PLAIN_PASSWORD:\r
9161                 b = EncryptPassword(a->PlainPassword);\r
9162                 CfgAddByte(f, "EncryptedPassword", b->Buf, b->Size);\r
9163                 FreeBuf(b);\r
9164                 break;\r
9165 \r
9166         case CLIENT_AUTHTYPE_CERT:\r
9167                 if (a->ClientK != NULL && a->ClientX != NULL)\r
9168                 {\r
9169                         b = XToBuf(a->ClientX, false);\r
9170                         CfgAddByte(f, "ClientCert", b->Buf, b->Size);\r
9171                         FreeBuf(b);\r
9172 \r
9173                         b = KToBuf(a->ClientK, false, NULL);\r
9174                         CfgAddByte(f, "ClientKey", b->Buf, b->Size);\r
9175                         FreeBuf(b);\r
9176                 }\r
9177                 break;\r
9178 \r
9179         case CLIENT_AUTHTYPE_SECURE:\r
9180                 CfgAddStr(f, "SecurePublicCertName", a->SecurePublicCertName);\r
9181                 CfgAddStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName);\r
9182                 break;\r
9183         }\r
9184 }\r
9185 \r
9186 // クライアントオプションを書き込む\r
9187 void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o)\r
9188 {\r
9189         BUF *b;\r
9190         // 引数チェック\r
9191         if (f == NULL || o == NULL)\r
9192         {\r
9193                 return;\r
9194         }\r
9195 \r
9196         CfgAddUniStr(f, "AccountName", o->AccountName);\r
9197         CfgAddStr(f, "Hostname", o->Hostname);\r
9198         CfgAddInt(f, "Port", o->Port);\r
9199         CfgAddInt(f, "PortUDP", o->PortUDP);\r
9200         CfgAddInt(f, "ProxyType", o->ProxyType);\r
9201         CfgAddStr(f, "ProxyName", o->ProxyName);\r
9202         CfgAddInt(f, "ProxyPort", o->ProxyPort);\r
9203         CfgAddStr(f, "ProxyUsername", o->ProxyUsername);\r
9204         b = EncryptPassword(o->ProxyPassword);\r
9205         CfgAddByte(f, "ProxyPassword", b->Buf, b->Size);\r
9206         FreeBuf(b);\r
9207         CfgAddInt(f, "NumRetry", o->NumRetry);\r
9208         CfgAddInt(f, "RetryInterval", o->RetryInterval);\r
9209         CfgAddStr(f, "HubName", o->HubName);\r
9210         CfgAddInt(f, "MaxConnection", o->MaxConnection);\r
9211         CfgAddBool(f, "UseEncrypt", o->UseEncrypt);\r
9212         CfgAddBool(f, "UseCompress", o->UseCompress);\r
9213         CfgAddBool(f, "HalfConnection", o->HalfConnection);\r
9214         CfgAddBool(f, "NoRoutingTracking", o->NoRoutingTracking);\r
9215         CfgAddStr(f, "DeviceName", o->DeviceName);\r
9216         CfgAddInt(f, "AdditionalConnectionInterval", o->AdditionalConnectionInterval);\r
9217         CfgAddBool(f, "HideStatusWindow", o->HideStatusWindow);\r
9218         CfgAddBool(f, "HideNicInfoWindow", o->HideNicInfoWindow);\r
9219         CfgAddInt(f, "ConnectionDisconnectSpan", o->ConnectionDisconnectSpan);\r
9220         CfgAddBool(f, "RequireMonitorMode", o->RequireMonitorMode);\r
9221         CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode);\r
9222         CfgAddBool(f, "DisableQoS", o->DisableQoS);\r
9223         CfgAddBool(f, "NoTls1", o->NoTls1);\r
9224 \r
9225         if (o->FromAdminPack)\r
9226         {\r
9227                 CfgAddBool(f, "FromAdminPack", o->FromAdminPack);\r
9228         }\r
9229 }\r
9230 \r
9231 // パスワードの解読\r
9232 char *DecryptPassword(BUF *b)\r
9233 {\r
9234         char *str;\r
9235         char *key = "EncryptPassword";\r
9236         CRYPT *c;\r
9237         // 引数チェック\r
9238         if (b == NULL)\r
9239         {\r
9240                 return CopyStr("");\r
9241         }\r
9242 \r
9243         str = ZeroMalloc(b->Size + 1);\r
9244         c = NewCrypt(key, sizeof(key));\r
9245         Encrypt(c, str, b->Buf, b->Size);\r
9246         FreeCrypt(c);\r
9247 \r
9248         str[b->Size] = 0;\r
9249 \r
9250         return str;\r
9251 }\r
9252 \r
9253 // パスワードの暗号化\r
9254 BUF *EncryptPassword(char *password)\r
9255 {\r
9256         UCHAR *tmp;\r
9257         UINT size;\r
9258         char *key = "EncryptPassword";\r
9259         CRYPT *c;\r
9260         BUF *b;\r
9261         // 引数チェック\r
9262         if (password == NULL)\r
9263         {\r
9264                 password = "";\r
9265         }\r
9266 \r
9267         size = StrLen(password) + 1;\r
9268         tmp = ZeroMalloc(size);\r
9269 \r
9270         c = NewCrypt(key, sizeof(key));\r
9271         Encrypt(c, tmp, password, size - 1);\r
9272         FreeCrypt(c);\r
9273 \r
9274         b = NewBuf();\r
9275         WriteBuf(b, tmp, size - 1);\r
9276         SeekBuf(b, 0, 0);\r
9277         Free(tmp);\r
9278 \r
9279         return b;\r
9280 }\r
9281 \r
9282 // アカウントデータを書き込む\r
9283 void CiWriteAccountData(FOLDER *f, ACCOUNT *a)\r
9284 {\r
9285         // 引数チェック\r
9286         if (f == NULL || a == NULL)\r
9287         {\r
9288                 return;\r
9289         }\r
9290 \r
9291         // クライアントオプション\r
9292         CiWriteClientOption(CfgCreateFolder(f, "ClientOption"), a->ClientOption);\r
9293 \r
9294         // クライアント認証データ\r
9295         CiWriteClientAuth(CfgCreateFolder(f, "ClientAuth"), a->ClientAuth);\r
9296 \r
9297         // スタートアップアカウント\r
9298         CfgAddBool(f, "StartupAccount", a->StartupAccount);\r
9299 \r
9300         // サーバー証明書チェックフラグ\r
9301         CfgAddBool(f, "CheckServerCert", a->CheckServerCert);\r
9302 \r
9303         // 日時\r
9304         CfgAddInt64(f, "CreateDateTime", a->CreateDateTime);\r
9305         CfgAddInt64(f, "UpdateDateTime", a->UpdateDateTime);\r
9306         CfgAddInt64(f, "LastConnectDateTime", a->LastConnectDateTime);\r
9307 \r
9308         // サーバー証明書本体\r
9309         if (a->ServerCert != NULL)\r
9310         {\r
9311                 BUF *b = XToBuf(a->ServerCert, false);\r
9312                 if (b != NULL)\r
9313                 {\r
9314                         CfgAddBuf(f, "ServerCert", b);\r
9315                         FreeBuf(b);\r
9316                 }\r
9317         }\r
9318 \r
9319         // ショートカットキー\r
9320         if (IsZero(a->ShortcutKey, SHA1_SIZE) == false)\r
9321         {\r
9322                 char tmp[64];\r
9323                 BinToStr(tmp, sizeof(tmp), a->ShortcutKey, SHA1_SIZE);\r
9324                 CfgAddStr(f, "ShortcutKey", tmp);\r
9325         }\r
9326 }\r
9327 \r
9328 // アカウントデータベースを書き込む\r
9329 void CiWriteAccountDatabase(CLIENT *c, FOLDER *f)\r
9330 {\r
9331         char name[MAX_SIZE];\r
9332         // 引数チェック\r
9333         if (c == NULL || f == NULL)\r
9334         {\r
9335                 return;\r
9336         }\r
9337 \r
9338         LockList(c->AccountList);\r
9339         {\r
9340                 UINT i;\r
9341                 for (i = 0;i < LIST_NUM(c->AccountList);i++)\r
9342                 {\r
9343                         ACCOUNT *a = LIST_DATA(c->AccountList, i);\r
9344                         Format(name, sizeof(name), "Account%u", i);\r
9345                         Lock(a->lock);\r
9346                         {\r
9347                                 CiWriteAccountData(CfgCreateFolder(f, name), a);\r
9348                         }\r
9349                         Unlock(a->lock);\r
9350                 }\r
9351         }\r
9352         UnlockList(c->AccountList);\r
9353 }\r
9354 \r
9355 // CA 証明書を書き込む\r
9356 void CiWriteCACert(CLIENT *c, FOLDER *f, X *x)\r
9357 {\r
9358         BUF *b;\r
9359         // 引数チェック\r
9360         if (c == NULL || f == NULL || x == NULL)\r
9361         {\r
9362                 return;\r
9363         }\r
9364 \r
9365         b = XToBuf(x, false);\r
9366         CfgAddBuf(f, "X509", b);\r
9367         FreeBuf(b);\r
9368 }\r
9369 \r
9370 // VLAN を書き込む\r
9371 void CiWriteVLan(CLIENT *c, FOLDER *f, UNIX_VLAN *v)\r
9372 {\r
9373         char tmp[MAX_SIZE];\r
9374         // 引数チェック\r
9375         if (c == NULL || f == NULL || v == NULL)\r
9376         {\r
9377                 return;\r
9378         }\r
9379 \r
9380         MacToStr(tmp, sizeof(tmp), v->MacAddress);\r
9381         CfgAddStr(f, "MacAddress", tmp);\r
9382         CfgAddBool(f, "Enabled", v->Enabled);\r
9383 }\r
9384 \r
9385 // VLAN リストを書き込む\r
9386 void CiWriteVLanList(CLIENT *c, FOLDER *f)\r
9387 {\r
9388         // 引数チェック\r
9389         if (c == NULL || f == NULL)\r
9390         {\r
9391                 return;\r
9392         }\r
9393 \r
9394         LockList(c->UnixVLanList);\r
9395         {\r
9396                 UINT i;\r
9397                 for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)\r
9398                 {\r
9399                         UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);\r
9400                         CiWriteVLan(c, CfgCreateFolder(f, v->Name), v);\r
9401                 }\r
9402         }\r
9403         UnlockList(c->UnixVLanList);\r
9404 }\r
9405 \r
9406 // CA リストを書き込む\r
9407 void CiWriteCAList(CLIENT *c, FOLDER *f)\r
9408 {\r
9409         CEDAR *cedar;\r
9410         // 引数チェック\r
9411         if (c == NULL || f == NULL)\r
9412         {\r
9413                 return;\r
9414         }\r
9415 \r
9416         cedar = c->Cedar;\r
9417 \r
9418         LockList(cedar->CaList);\r
9419         {\r
9420                 UINT i;\r
9421                 for (i = 0;i < LIST_NUM(cedar->CaList);i++)\r
9422                 {\r
9423                         char tmp[MAX_SIZE];\r
9424                         X *x = LIST_DATA(cedar->CaList, i);\r
9425                         Format(tmp, sizeof(tmp), "Certificate%u", i);\r
9426                         CiWriteCACert(c, CfgCreateFolder(f, tmp), x);\r
9427                 }\r
9428         }\r
9429         UnlockList(cedar->CaList);\r
9430 }\r
9431 \r
9432 // 現在の設定を ROOT に書き込む\r
9433 void CiWriteSettingToCfg(CLIENT *c, FOLDER *root)\r
9434 {\r
9435         FOLDER *cc;\r
9436         FOLDER *account_database;\r
9437         FOLDER *ca;\r
9438         FOLDER *vlan;\r
9439         FOLDER *cmsetting;\r
9440         // 引数チェック\r
9441         if (c == NULL || root == NULL)\r
9442         {\r
9443                 return;\r
9444         }\r
9445 \r
9446         cmsetting = CfgCreateFolder(root, "ClientManagerSetting");\r
9447 \r
9448         // CLIENT_CONFIG\r
9449         cc = CfgCreateFolder(root, "Config");\r
9450         CiWriteClientConfig(cc, &c->Config);\r
9451 \r
9452         // 自動ファイル削除器\r
9453         CfgAddInt64(cc, "AutoDeleteCheckDiskFreeSpaceMin", c->Eraser->MinFreeSpace);\r
9454 \r
9455         // Account Database\r
9456         account_database = CfgCreateFolder(root, "AccountDatabase");\r
9457         CiWriteAccountDatabase(c, account_database);\r
9458 \r
9459         // CA\r
9460         ca = CfgCreateFolder(root, "RootCA");\r
9461         CiWriteCAList(c, ca);\r
9462 \r
9463         // VLAN\r
9464         if (OS_IS_UNIX(GetOsInfo()->OsType) && GetOsInfo()->OsType != OSTYPE_MACOS_X)\r
9465         {\r
9466                 vlan = CfgCreateFolder(root, "UnixVLan");\r
9467                 CiWriteVLanList(c, vlan);\r
9468         }\r
9469 \r
9470         // Password\r
9471         CfgAddByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE);\r
9472         CfgAddBool(root, "PasswordRemoteOnly", c->PasswordRemoteOnly);\r
9473 \r
9474         // UseSecureDeviceId\r
9475         CfgAddInt(root, "UseSecureDeviceId", c->UseSecureDeviceId);\r
9476 \r
9477         // DontSavePassword\r
9478         CfgAddBool(root, "DontSavePassword", c->DontSavePassword);\r
9479 \r
9480         // UserAgent\r
9481         if (c->Cedar != NULL)\r
9482         {\r
9483                 CfgAddStr(root, "UserAgent", c->Cedar->HttpUserAgent);\r
9484         }\r
9485 \r
9486         if (cmsetting != NULL)\r
9487         {\r
9488                 CM_SETTING *s = c->CmSetting;\r
9489 \r
9490                 CfgAddBool(cmsetting, "EasyMode", s->EasyMode);\r
9491                 CfgAddBool(cmsetting, "LockMode", s->LockMode);\r
9492 \r
9493                 if (IsZero(s->HashedPassword, sizeof(s->HashedPassword)) == false)\r
9494                 {\r
9495                         CfgAddByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));\r
9496                 }\r
9497         }\r
9498 }\r
9499 \r
9500 // 設定ファイルへ書き込み\r
9501 void CiSaveConfigurationFile(CLIENT *c)\r
9502 {\r
9503         FOLDER *root;\r
9504         // 引数チェック\r
9505         if (c == NULL)\r
9506         {\r
9507                 return;\r
9508         }\r
9509         \r
9510         // 設定ファイルを保存しない\r
9511         if(c->NoSaveConfig)\r
9512         {\r
9513                 return;\r
9514         }\r
9515 \r
9516         root = CfgCreateFolder(NULL, TAG_ROOT);\r
9517         CiWriteSettingToCfg(c, root);\r
9518 \r
9519         SaveCfgRw(c->CfgRw, root);\r
9520 \r
9521         CfgDeleteFolder(root);\r
9522 }\r
9523 \r
9524 // CM_SETTING の設定\r
9525 bool CtSetCmSetting(CLIENT *c, CM_SETTING *s)\r
9526 {\r
9527         // 引数チェック\r
9528         if (c == NULL || s == NULL)\r
9529         {\r
9530                 return false;\r
9531         }\r
9532 \r
9533         Copy(c->CmSetting, s, sizeof(CM_SETTING));\r
9534 \r
9535         CiSaveConfigurationFile(c);\r
9536 \r
9537         return true;\r
9538 }\r
9539 \r
9540 // CM_SETTING の取得\r
9541 bool CtGetCmSetting(CLIENT *c, CM_SETTING *s)\r
9542 {\r
9543         // 引数チェック\r
9544         if (c == NULL || s == NULL)\r
9545         {\r
9546                 return false;\r
9547         }\r
9548 \r
9549         Copy(s, c->CmSetting, sizeof(CM_SETTING));\r
9550         \r
9551         return true;\r
9552 }\r
9553 \r
9554 // クライアントバージョンの取得\r
9555 bool CtGetClientVersion(CLIENT *c, RPC_CLIENT_VERSION *ver)\r
9556 {\r
9557         // 引数チェック\r
9558         if (ver == NULL)\r
9559         {\r
9560                 return false;\r
9561         }\r
9562 \r
9563         Zero(ver, sizeof(RPC_CLIENT_VERSION));\r
9564         StrCpy(ver->ClientProductName, sizeof(ver->ClientProductName), CEDAR_CLIENT_STR);\r
9565         StrCpy(ver->ClientVersionString, sizeof(ver->ClientVersionString), c->Cedar->VerString);\r
9566         StrCpy(ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString), c->Cedar->BuildInfo);\r
9567         ver->ClientVerInt = c->Cedar->Version;\r
9568         ver->ClientBuildInt = c->Cedar->Build;\r
9569 \r
9570 #ifdef  OS_WIN32\r
9571         ver->ProcessId = MsGetProcessId();\r
9572 #endif  // OS_WIN32\r
9573 \r
9574         ver->OsType = GetOsInfo()->OsType;\r
9575 \r
9576         return true;\r
9577 }\r
9578 \r
9579 // クライアントオブジェクトの作成\r
9580 CLIENT *CiNewClient()\r
9581 {\r
9582         CLIENT *c = ZeroMalloc(sizeof(CLIENT));\r
9583 \r
9584 //      StartCedarLog();\r
9585 \r
9586         c->CmSetting = ZeroMalloc(sizeof(CM_SETTING));\r
9587 \r
9588         c->SockList = NewSockList();\r
9589 \r
9590         c->lock = NewLock();\r
9591         c->lockForConnect = NewLock();\r
9592         c->ref = NewRef();\r
9593 \r
9594         c->Cedar = NewCedar(NULL, NULL);\r
9595 \r
9596         c->Cedar->Client = c;\r
9597 \r
9598         c->NotifyCancelList = NewList(NULL);\r
9599 \r
9600         Hash(c->EncryptedPassword, "", 0, true);\r
9601 \r
9602         // ログ設定\r
9603         if(c->NoSaveLog == false)\r
9604         {\r
9605                 MakeDir(CLIENT_LOG_DIR_NAME);\r
9606                 c->Logger = NewLog(CLIENT_LOG_DIR_NAME, CLIENT_LOG_PREFIX, LOG_SWITCH_DAY);\r
9607         }\r
9608 \r
9609         CLog(c, "L_LINE");\r
9610         CLog(c, "LC_START_2", CEDAR_CLIENT_STR, c->Cedar->VerString);\r
9611         CLog(c, "LC_START_3", c->Cedar->BuildInfo);\r
9612         CLog(c, "LC_START_1");\r
9613 \r
9614 #ifdef  OS_WIN32\r
9615         {\r
9616                 // Win32 UI の初期化\r
9617                 wchar_t tmp[MAX_SIZE];\r
9618                 StrToUni(tmp, sizeof(tmp), CEDAR_CLIENT_STR);\r
9619 \r
9620                 InitWinUi(tmp, _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));\r
9621         }\r
9622 #endif  // OS_WIN32\r
9623 \r
9624         // 設定の初期化\r
9625         CiInitConfiguration(c);\r
9626 \r
9627         // 優先順位を上げる\r
9628         OSSetHighPriority();\r
9629 \r
9630 #ifdef  OS_WIN32\r
9631         // Win9x の場合、すべての仮想 LAN カードの DHCP アドレスを解放する\r
9632         if (MsIsNt() == false)\r
9633         {\r
9634                 Win32ReleaseAllDhcp9x(true);\r
9635         }\r
9636 #endif  // OS_WIN32\r
9637 \r
9638         CiChangeAllVLanMacAddressIfMachineChanged(c);\r
9639 \r
9640         return c;\r
9641 }\r
9642 \r
9643 // クライアントのクリーンアップ\r
9644 void CiCleanupClient(CLIENT *c)\r
9645 {\r
9646         // 引数チェック\r
9647         if (c == NULL)\r
9648         {\r
9649                 return;\r
9650         }\r
9651 \r
9652         // 設定の解放\r
9653         CiFreeConfiguration(c);\r
9654 \r
9655 #ifdef  OS_WIN32\r
9656         // Win32 UI の解放\r
9657         FreeWinUi();\r
9658 #endif  // OS_WIN32\r
9659 \r
9660         CLog(c, "LC_END");\r
9661         CLog(c, "L_LINE");\r
9662         FreeEraser(c->Eraser);\r
9663         FreeLog(c->Logger);\r
9664         c->Logger = NULL;\r
9665 \r
9666         ReleaseCedar(c->Cedar);\r
9667 \r
9668         DeleteLock(c->lockForConnect);\r
9669         DeleteLock(c->lock);\r
9670 \r
9671         ReleaseList(c->NotifyCancelList);\r
9672 \r
9673         FreeSockList(c->SockList);\r
9674 \r
9675         Free(c->CmSetting);\r
9676 \r
9677         Free(c);\r
9678 \r
9679 #ifdef  OS_WIN32\r
9680         // Win9x の場合、すべての仮想 LAN カードの DHCP アドレスを解放する\r
9681         if (MsIsNt() == false)\r
9682         {\r
9683                 Win32ReleaseAllDhcp9x(true);\r
9684         }\r
9685 #endif  // OS_WIN32\r
9686 \r
9687         StopCedarLog();\r
9688 }\r
9689 \r
9690 // クライアントの解放\r
9691 void CtReleaseClient(CLIENT *c)\r
9692 {\r
9693         // 引数チェック\r
9694         if (c == NULL)\r
9695         {\r
9696                 return;\r
9697         }\r
9698 \r
9699         if (Release(c->ref) == 0)\r
9700         {\r
9701                 CiCleanupClient(c);\r
9702         }\r
9703 }\r
9704 \r
9705 // クライアントプログラムの動作開始\r
9706 void CtStartClient()\r
9707 {\r
9708         UINT i;\r
9709         LIST *o;\r
9710         if (client != NULL)\r
9711         {\r
9712                 // すでに動作している\r
9713                 return;\r
9714         }\r
9715 \r
9716         // OS チェック\r
9717         CiCheckOs();\r
9718 \r
9719 #ifdef  OS_WIN32\r
9720         RegistWindowsFirewallAll();\r
9721 #endif\r
9722 \r
9723         // クライアントの作成\r
9724         client = CiNewClient();\r
9725 \r
9726         // Keep を開始\r
9727         CiInitKeep(client);\r
9728 \r
9729         // RPC サーバーを開始\r
9730         CiStartRpcServer(client);\r
9731 \r
9732         // 設定データ自動保存を開始\r
9733         CiInitSaver(client);\r
9734 \r
9735         // スタートアップ接続を開始する\r
9736         o = NewListFast(NULL);\r
9737         LockList(client->AccountList);\r
9738         {\r
9739                 for (i = 0;i < LIST_NUM(client->AccountList);i++)\r
9740                 {\r
9741                         ACCOUNT *a = LIST_DATA(client->AccountList, i);\r
9742                         Lock(a->lock);\r
9743                         {\r
9744                                 if (a->StartupAccount)\r
9745                                 {\r
9746                                         Add(o, CopyUniStr(a->ClientOption->AccountName));\r
9747                                 }\r
9748                         }\r
9749                         Unlock(a->lock);\r
9750                 }\r
9751         }\r
9752         UnlockList(client->AccountList);\r
9753 \r
9754         for (i = 0;i < LIST_NUM(o);i++)\r
9755         {\r
9756                 wchar_t *s = LIST_DATA(o, i);\r
9757                 RPC_CLIENT_CONNECT c;\r
9758                 Zero(&c, sizeof(c));\r
9759                 UniStrCpy(c.AccountName, sizeof(c.AccountName), s);\r
9760                 CtConnect(client, &c);\r
9761                 Free(s);\r
9762         }\r
9763         ReleaseList(o);\r
9764 }\r
9765 \r
9766 // クライアントプログラムの動作終了\r
9767 void CtStopClient()\r
9768 {\r
9769         UINT i, num;\r
9770         ACCOUNT **account_list;\r
9771         if (client == NULL)\r
9772         {\r
9773                 // まだ動作していない\r
9774                 return;\r
9775         }\r
9776 \r
9777         // 停止フラグ\r
9778         client->Halt = true;\r
9779 \r
9780         // RPC をすべて切断\r
9781         CiStopRpcServer(client);\r
9782 \r
9783         // クライアント通知サービスを終了\r
9784         CncExit();\r
9785 \r
9786         // Keep を終了\r
9787         CiFreeKeep(client);\r
9788 \r
9789         // 接続中のアカウントをすべて切断\r
9790         LockList(client->AccountList);\r
9791         {\r
9792                 num = LIST_NUM(client->AccountList);\r
9793                 account_list = ToArray(client->AccountList);\r
9794         }\r
9795         UnlockList(client->AccountList);\r
9796 \r
9797         for (i = 0;i < num;i++)\r
9798         {\r
9799                 ACCOUNT *a = account_list[i];\r
9800                 SESSION *s = NULL;\r
9801 \r
9802                 Lock(a->lock);\r
9803                 {\r
9804                         if (a->ClientSession != NULL)\r
9805                         {\r
9806                                 s = a->ClientSession;\r
9807                                 AddRef(s->ref);\r
9808                         }\r
9809                 }\r
9810                 Unlock(a->lock);\r
9811 \r
9812                 if (s != NULL)\r
9813                 {\r
9814                         StopSession(s);\r
9815                         ReleaseSession(s);\r
9816                         Lock(a->lock);\r
9817                         {\r
9818                                 if (a->ClientSession != NULL)\r
9819                                 {\r
9820                                         ReleaseSession(a->ClientSession);\r
9821                                         a->ClientSession = NULL;\r
9822                                 }\r
9823                         }\r
9824                         Unlock(a->lock);\r
9825                 }\r
9826         }\r
9827 \r
9828         Free(account_list);\r
9829 \r
9830         // 設定データ自動保存を停止\r
9831         CiFreeSaver(client);\r
9832 \r
9833         // クライアントの解放\r
9834         CtReleaseClient(client);\r
9835         client = NULL;\r
9836 }\r
9837 \r
9838 // OS チェック\r
9839 void CiCheckOs()\r
9840 {\r
9841         // OS の種類の取得\r
9842         OS_INFO *info = GetOsInfo();\r
9843 \r
9844         if (OS_IS_WINDOWS(info->OsType))\r
9845         {\r
9846                 bool ok = IS_CLIENT_SUPPORTED_OS(info->OsType);\r
9847 \r
9848                 if (ok == false)\r
9849                 {\r
9850                         Alert(\r
9851                                 "SoftEther UT-VPN Client doesn't support this Windows Operating System.\n"\r
9852                                 "SoftEther UT-VPN Client requires Windows 98 SE, Windows Me, Windows 2000, Windows XP, Windows Server 2003 or Greater.\n\n"\r
9853                                 "Please contact your system administrator.", "SoftEther UT-VPN Client");\r
9854                         exit(0);\r
9855                 }\r
9856         }\r
9857 }\r
9858 \r
9859 // クライアントオブジェクトの取得\r
9860 CLIENT *CtGetClient()\r
9861 {\r
9862         if (client == NULL)\r
9863         {\r
9864                 return NULL;\r
9865         }\r
9866 \r
9867         AddRef(client->ref);\r
9868 \r
9869         return client;\r
9870 }\r
9871 \r
9872 // クライアントステータス表示器\r
9873 void CiClientStatusPrinter(SESSION *s, wchar_t *status)\r
9874 {\r
9875 #ifdef  OS_WIN32\r
9876         ACCOUNT *a;\r
9877         // 引数チェック\r
9878         if (s == NULL || status == NULL)\r
9879         {\r
9880                 return;\r
9881         }\r
9882 \r
9883         a = s->Account;\r
9884         if (a == NULL)\r
9885         {\r
9886                 return;\r
9887         }\r
9888 \r
9889         if (UniStrCmpi(status, L"init") == 0)\r
9890         {\r
9891                 if (a->StatusWindow == NULL && s->Win32HideConnectWindow == false)\r
9892                 {\r
9893                         a->StatusWindow = CncStatusPrinterWindowStart(s);\r
9894                 }\r
9895         }\r
9896         else if (UniStrCmpi(status, L"free") == 0)\r
9897         {\r
9898                 if (a->StatusWindow != NULL)\r
9899                 {\r
9900                         CncStatusPrinterWindowStop(a->StatusWindow);\r
9901                         a->StatusWindow = NULL;\r
9902                 }\r
9903         }\r
9904         else\r
9905         {\r
9906                 if (a->StatusWindow != NULL)\r
9907                 {\r
9908                         CncStatusPrinterWindowPrint(a->StatusWindow, status);\r
9909                 }\r
9910         }\r
9911 #else   // OS_WIN32\r
9912         UniPrint(L"Status: %s\n", status);\r
9913 #endif  // OS_WIN32\r
9914 }\r
9915 \r
9916 \r