source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Client.c @ 86521dd

trunk
Last change on this file since 86521dd was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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