* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / SM.c
diff --git a/utvpn/utvpn-unix-v101-7101-public/src/Cedar/SM.c b/utvpn/utvpn-unix-v101-7101-public/src/Cedar/SM.c
new file mode 100644 (file)
index 0000000..d773f1a
--- /dev/null
@@ -0,0 +1,17688 @@
+// SoftEther UT-VPN SourceCode\r
+// \r
+// Copyright (C) 2004-2010 SoftEther Corporation.\r
+// Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
+// Copyright (C) 2003-2010 Daiyuu Nobori.\r
+// All Rights Reserved.\r
+// \r
+// http://utvpn.tsukuba.ac.jp/\r
+// \r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// version 2 as published by the Free Software Foundation.\r
+// \r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+// \r
+// You should have received a copy of the GNU General Public License version 2\r
+// along with this program; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+// \r
+// このファイルは GPL バージョン 2 ライセンスで公開されています。\r
+// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
+// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
+// を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
+// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
+// \r
+// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
+// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
+// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
+// ホストされています。\r
+// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
+// および、試験または研究のために利用が行われることを想定して配布\r
+// しています。\r
+// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
+// あります。\r
+// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
+// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
+// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
+// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
+// に組み込みさせていただきます。\r
+// \r
+// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
+// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
+// \r
+// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
+// (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
+// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
+// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
+// ください。\r
+// \r
+// お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
+// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
+// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
+// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
+// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
+// 公益保護にご協力いただきますようお願い申し上げます。\r
+// \r
+// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
+// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
+// を保護するための努力を行います。\r
+// \r
+// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
+// 日本国内の脆弱性情報届出受付公的機関:\r
+//         独立行政法人 情報処理推進機構\r
+//         http://www.ipa.go.jp/security/vuln/report/\r
+// \r
+// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
+// 連絡先: http://www.softether.co.jp/jp/contact/\r
+\r
+// -----------------------------------------------\r
+// [ChangeLog]\r
+// 2010.05.20\r
+//  新規リリース by SoftEther\r
+// -----------------------------------------------\r
+\r
+// SM.c\r
+// Win32 用 SoftEther UT-VPN Server Manager\r
+\r
+\r
+#ifdef WIN32\r
+\r
+#define        SM_C\r
+#define        CM_C\r
+#define        NM_C\r
+\r
+#define        _WIN32_WINNT            0x0502\r
+#define        WINVER                          0x0502\r
+#include <winsock2.h>\r
+#include <windows.h>\r
+#include <wincrypt.h>\r
+#include <wininet.h>\r
+#include <shlobj.h>\r
+#include <commctrl.h>\r
+#include <Dbghelp.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <wchar.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <errno.h>\r
+#include <Mayaqua/Mayaqua.h>\r
+#include <Cedar/Cedar.h>\r
+#include "CMInner.h"\r
+#include "SMInner.h"\r
+#include "NMInner.h"\r
+#include "../PenCore/resource.h"\r
+\r
+// グローバル変数\r
+static SM *sm = NULL;\r
+static bool link_create_now = false;\r
+\r
+// メッセージ設定\r
+void SmHubMsg(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_MSG, SmHubMsgDlg, s);\r
+}\r
+\r
+// メッセージダイアログプロシージャ\r
+UINT SmHubMsgDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_HUB *s = (SM_EDIT_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmHubMsgDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_TEXT:\r
+                       SmHubMsgDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       SmHubMsgDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case C_USEMSG:\r
+                       SmHubMsgDlgUpdate(hWnd, s);\r
+\r
+                       if (IsChecked(hWnd, C_USEMSG))\r
+                       {\r
+                               FocusEx(hWnd, E_TEXT);\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// メッセージダイアログ初期化\r
+void SmHubMsgDlgInit(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       RPC_MSG t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (MsIsVista())\r
+       {\r
+               SetFont(hWnd, E_TEXT, GetMeiryoFont());\r
+       }\r
+       else\r
+       {\r
+               DlgFont(hWnd, E_TEXT, 11, false);\r
+       }\r
+\r
+       FormatText(hWnd, S_MSG_2, s->HubName);\r
+\r
+       LimitText(hWnd, E_TEXT, HUB_MAXMSG_LEN);\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (CALL(hWnd, ScGetHubMsg(s->p->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       if (UniIsEmptyStr(t.Msg) == false)\r
+       {\r
+               SetText(hWnd, E_TEXT, t.Msg);\r
+\r
+               Check(hWnd, C_USEMSG, true);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, C_USEMSG, false);\r
+       }\r
+\r
+       FreeRpcMsg(&t);\r
+\r
+       SmHubMsgDlgUpdate(hWnd, s);\r
+}\r
+\r
+// OK ボタン\r
+void SmHubMsgDlgOnOk(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       RPC_MSG t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (IsChecked(hWnd, C_USEMSG) == false)\r
+       {\r
+               t.Msg = CopyUniStr(L"");\r
+       }\r
+       else\r
+       {\r
+               t.Msg = GetText(hWnd, E_TEXT);\r
+       }\r
+\r
+       if (CALL(hWnd, ScSetHubMsg(s->p->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeRpcMsg(&t);\r
+\r
+       EndDialog(hWnd, 1);\r
+}\r
+\r
+// メッセージダイアログ更新\r
+void SmHubMsgDlgUpdate(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       bool b = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, E_TEXT, IsChecked(hWnd, C_USEMSG));\r
+\r
+       if (IsChecked(hWnd, C_USEMSG))\r
+       {\r
+               wchar_t *s = GetText(hWnd, E_TEXT);\r
+\r
+               b = !IsEmptyUniStr(s);\r
+\r
+               Free(s);\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+}\r
+\r
+// VLAN ユーティリティ\r
+void SmVLan(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_VLAN, SmVLanDlg, s);\r
+}\r
+\r
+// VLAN ダイアログ\r
+UINT SmVLanDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *s = (SM_SERVER *)param;\r
+       NMHDR *n;\r
+\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmVLanDlgInit(hWnd, s);\r
+\r
+               if (LvNum(hWnd, L_LIST) == 0)\r
+               {\r
+                       Disable(hWnd, L_LIST);\r
+                       SetTimer(hWnd, 1, 100, NULL);\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_VLAN_NOTHING"),\r
+                               s->CurrentSetting->ClientOption.Hostname);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_ENABLE:\r
+               case B_DISABLE:\r
+                       {\r
+                               UINT i = LvGetSelected(hWnd, L_LIST);\r
+                               if (i != INFINITE)\r
+                               {\r
+                                       char *name = LvGetStrA(hWnd, L_LIST, i, 0);\r
+\r
+                                       if (IsEmptyStr(name) == false)\r
+                                       {\r
+                                               RPC_TEST t;\r
+\r
+                                               Zero(&t, sizeof(t));\r
+\r
+                                               StrCpy(t.StrValue, sizeof(t.StrValue), name);\r
+                                               t.IntValue = BOOL_TO_INT(wParam == B_ENABLE);\r
+\r
+                                               if (CALL(hWnd, ScSetEnableEthVLan(s->Rpc, &t)))\r
+                                               {\r
+                                                       SmVLanDlgRefresh(hWnd, s);\r
+\r
+                                                       if (wParam == B_ENABLE)\r
+                                                       {\r
+                                                               MsgBoxEx(hWnd, MB_ICONINFORMATION,\r
+                                                                       _UU("SM_VLAN_MSG_1"),\r
+                                                                       name, name, name);\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               MsgBoxEx(hWnd, MB_ICONINFORMATION,\r
+                                                                       _UU("SM_VLAN_MSG_2"),\r
+                                                                       name);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       Free(name);\r
+                               }\r
+                               break;\r
+                       }\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmVLanDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// VLAN ダイアログ初期化\r
+void SmVLanDlgInit(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_VLAN_COLUMN_0"), 245);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_VLAN_COLUMN_1"), 75);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_VLAN_COLUMN_2"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_VLAN_COLUMN_3"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_VLAN_COLUMN_4"), 290);\r
+       LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_VLAN_COLUMN_5"), 430);\r
+\r
+       SmVLanDlgRefresh(hWnd, s);\r
+}\r
+\r
+// VLAN ダイアログ内容更新\r
+void SmVLanDlgRefresh(HWND hWnd, SM_SERVER *s)\r
+{\r
+       LVB *b;\r
+       RPC_ENUM_ETH_VLAN t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumEthVLan(s->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_VLAN_ITEM *e = &t.Items[i];\r
+\r
+               if (e->Support)\r
+               {\r
+                       wchar_t tmp0[MAX_SIZE];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t *tmp3;\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       wchar_t tmp5[MAX_SIZE];\r
+\r
+                       StrToUni(tmp0, sizeof(tmp0), e->DeviceName);\r
+                       StrToUni(tmp1, sizeof(tmp1), e->DriverType);\r
+                       StrToUni(tmp2, sizeof(tmp2), e->DriverName);\r
+                       tmp3 = (e->Enabled ? _UU("SM_VLAN_YES") : _UU("SM_VLAN_NO"));\r
+                       StrToUni(tmp4, sizeof(tmp4), e->Guid);\r
+                       StrToUni(tmp5, sizeof(tmp5), e->DeviceInstanceId);\r
+\r
+                       LvInsertAdd(b,\r
+                               e->Enabled ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE, 0, 6,\r
+                               tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);\r
+               }\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_LIST);\r
+\r
+       FreeRpcEnumEthVLan(&t);\r
+\r
+       SmVLanDlgUpdate(hWnd, s);\r
+}\r
+\r
+// VLAN ダイアログコントロール更新\r
+void SmVLanDlgUpdate(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSingleSelected(hWnd, L_LIST) == false)\r
+       {\r
+               Disable(hWnd, B_ENABLE);\r
+               Disable(hWnd, B_DISABLE);\r
+       }\r
+       else\r
+       {\r
+               UINT i = LvGetSelected(hWnd, L_LIST);\r
+               if (i != INFINITE)\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_LIST, i, 3);\r
+\r
+                       if (UniStrCmpi(s, _UU("SM_VLAN_YES")) != 0)\r
+                       {\r
+                               Enable(hWnd, B_ENABLE);\r
+                               Disable(hWnd, B_DISABLE);\r
+                       }\r
+                       else\r
+                       {\r
+                               Enable(hWnd, B_DISABLE);\r
+                               Disable(hWnd, B_ENABLE);\r
+                       }\r
+\r
+                       Free(s);\r
+               }\r
+       }\r
+}\r
+\r
+// 現在の VPN Server / VPN Bridge の状態が初期状態かどうか調べる\r
+bool SmSetupIsNew(SM_SERVER *s)\r
+{\r
+       RPC *rpc;\r
+       bool is_bridge;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       bool check_hub = false;\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (s->ServerAdminMode == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       rpc = s->Rpc;\r
+       is_bridge =s->Bridge;\r
+\r
+       // ローカルブリッジのサポート\r
+       if (true)\r
+       {\r
+               RPC_BRIDGE_SUPPORT t;\r
+\r
+               Zero(&t, sizeof(t));\r
+\r
+               if (ScGetBridgeSupport(rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       if (t.IsBridgeSupportedOs == false ||\r
+                               t.IsWinPcapNeeded)\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       // サーバー種類\r
+       if (is_bridge == false)\r
+       {\r
+               bool b = false;\r
+               RPC_SERVER_INFO t;\r
+\r
+               Zero(&t, sizeof(t));\r
+               if (ScGetServerInfo(rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       if (t.ServerType != SERVER_TYPE_STANDALONE)\r
+                       {\r
+                               b = true;\r
+                       }\r
+\r
+                       FreeRpcServerInfo(&t);\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               if (b)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       // ローカルブリッジ\r
+       if (true)\r
+       {\r
+               RPC_ENUM_LOCALBRIDGE t;\r
+               bool b = false;\r
+\r
+               Zero(&t, sizeof(t));\r
+               if (ScEnumLocalBridge(rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       if (t.NumItem != 0)\r
+                       {\r
+                               b = true;\r
+                       }\r
+                       FreeRpcEnumLocalBridge(&t);\r
+               }\r
+\r
+               if (b)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       // 仮想 HUB\r
+\r
+       check_hub = false;\r
+\r
+       if (is_bridge == false)\r
+       {\r
+               RPC_ENUM_HUB t;\r
+               bool b = false;\r
+\r
+               Zero(&t, sizeof(t));\r
+               if (ScEnumHub(rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       if (t.NumHub >= 2)\r
+                       {\r
+                               b = true;\r
+                       }\r
+                       else if (t.NumHub == 1)\r
+                       {\r
+                               if (StrCmpi(t.Hubs[0].HubName, SERVER_DEFAULT_HUB_NAME) != 0)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       check_hub = true;\r
+                               }\r
+                       }\r
+\r
+                       FreeRpcEnumHub(&t);\r
+               }\r
+\r
+               if (b)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               check_hub = true;\r
+       }\r
+\r
+       // 仮想 HUB の状態\r
+       if (is_bridge == false)\r
+       {\r
+               StrCpy(hubname, sizeof(hubname), SERVER_DEFAULT_HUB_NAME);\r
+       }\r
+       else\r
+       {\r
+               StrCpy(hubname, sizeof(hubname), SERVER_DEFAULT_BRIDGE_NAME);\r
+       }\r
+\r
+       if (check_hub)\r
+       {\r
+               if (true)\r
+               {\r
+                       // 仮想 HUB 内のオブジェクト数\r
+                       RPC_HUB_STATUS t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScGetHubStatus(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               if (t.NumSessions != 0 || t.NumAccessLists != 0 ||\r
+                                       t.NumUsers != 0 || t.NumGroups != 0 ||\r
+                                       t.NumMacTables != 0 || t.NumIpTables != 0 ||\r
+                                       t.SecureNATEnabled)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (true)\r
+               {\r
+                       // カスケード接続\r
+                       RPC_ENUM_LINK t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScEnumLink(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               bool b = false;\r
+\r
+                               if (t.NumLink != 0)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+\r
+                               FreeRpcEnumLink(&t);\r
+\r
+                               if (b)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       // 信頼する証明書一覧\r
+                       RPC_HUB_ENUM_CA t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScEnumCa(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               bool b = false;\r
+\r
+                               if (t.NumCa != 0)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+\r
+                               FreeRpcHubEnumCa(&t);\r
+\r
+                               if (b)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       // 無効な証明書一覧\r
+                       RPC_ENUM_CRL t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScEnumCrl(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               bool b = false;\r
+\r
+                               if (t.NumItem != 0)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+\r
+                               FreeRpcEnumCrl(&t);\r
+\r
+                               if (b)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       // 認証サーバーの設定\r
+                       RPC_RADIUS t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScGetHubRadius(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               if (IsEmptyStr(t.RadiusServerName) == false)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       // 仮想 HUB の設定\r
+                       RPC_CREATE_HUB t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScGetHub(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               if (t.HubOption.NoEnum || t.HubOption.MaxSession != 0 ||\r
+                                       t.Online == false)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       // IP アクセス制御リスト\r
+                       RPC_AC_LIST t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScGetAcList(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               bool b = false;\r
+                               if (LIST_NUM(t.o) != 0)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+                               FreeRpcAcList(&t);\r
+\r
+                               if (b)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       // AO\r
+                       RPC_ADMIN_OPTION t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+                       if (ScGetHubAdminOptions(rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               bool b = false;\r
+                               UINT i;\r
+\r
+                               for (i = 0;i < t.NumItem;i++)\r
+                               {\r
+                                       if (t.Items[i].Value != 0)\r
+                                       {\r
+                                               b = true;\r
+                                       }\r
+                               }\r
+\r
+                               FreeRpcAdminOption(&t);\r
+\r
+                               if (b)\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // 仮想レイヤ 3 スイッチ\r
+       if (is_bridge == false)\r
+       {\r
+               RPC_ENUM_L3SW t;\r
+               bool b = false;\r
+\r
+               Zero(&t, sizeof(t));\r
+               if (ScEnumL3Switch(rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       if (t.NumItem != 0)\r
+                       {\r
+                               b = true;\r
+                       }\r
+\r
+                       FreeRpcEnumL3Sw(&t);\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               if (b)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// セットアップ手順ダイアログ初期化\r
+void SmSetupStepDlgInit(HWND hWnd, SM_SETUP *s)\r
+{\r
+       bool b;\r
+       RPC_ENUM_ETH t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_SETUP);\r
+\r
+       DlgFont(hWnd, S_1_1, 0, true);\r
+       DlgFont(hWnd, S_2_1, 0, true);\r
+       DlgFont(hWnd, S_3_1, 0, true);\r
+\r
+       b = false;\r
+       if (s->UseRemote)\r
+       {\r
+               b = true;\r
+       }\r
+       if (s->UseSite && s->UseSiteEdge == false)\r
+       {\r
+               b = true;\r
+       }\r
+\r
+       SetEnable(hWnd, S_1_1, b);\r
+       SetEnable(hWnd, S_1_2, b);\r
+       SetEnable(hWnd, B_USER, b);\r
+\r
+       b = false;\r
+       if (s->UseSiteEdge)\r
+       {\r
+               b = true;\r
+       }\r
+\r
+       SetEnable(hWnd, S_2_1, b);\r
+       SetEnable(hWnd, S_2_2, b);\r
+       SetEnable(hWnd, B_CASCADE, b);\r
+\r
+       CbReset(hWnd, C_DEVICE);\r
+       CbSetHeight(hWnd, C_DEVICE, 18);\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       CbAddStr(hWnd, C_DEVICE, _UU("SM_SETUP_SELECT"), 0);\r
+\r
+       if (CALL(hWnd, ScEnumEthernet(s->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               wchar_t tmp[MAX_PATH];\r
+               RPC_ENUM_ETH_ITEM *e = &t.Items[i];\r
+\r
+               StrToUni(tmp, sizeof(tmp), e->DeviceName);\r
+\r
+               CbAddStr(hWnd, C_DEVICE, tmp, 1);\r
+       }\r
+\r
+       FreeRpcEnumEth(&t);\r
+\r
+       s->Flag1 = false;\r
+       s->Flag2 = false;\r
+}\r
+\r
+// 閉じる\r
+void SmSetupOnClose(HWND hWnd, SM_SETUP *s)\r
+{\r
+       wchar_t *tmp;\r
+       char name[MAX_PATH];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       tmp = CbGetStr(hWnd, C_DEVICE);\r
+\r
+       if (tmp != NULL)\r
+       {\r
+               UniToStr(name, sizeof(name), tmp);\r
+\r
+               if (CbGetSelect(hWnd, C_DEVICE) != 0)\r
+               {\r
+                       RPC_LOCALBRIDGE t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       t.Active = true;\r
+                       StrCpy(t.DeviceName, sizeof(t.DeviceName), name);\r
+                       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                       t.Online = true;\r
+                       t.TapMode = false;\r
+\r
+                       if (CALL(hWnd, ScAddLocalBridge(s->Rpc, &t)) == false)\r
+                       {\r
+                               Free(tmp);\r
+                               return;\r
+                       }\r
+               }\r
+               Free(tmp);\r
+       }\r
+\r
+       EndDialog(hWnd, 0);\r
+}\r
+\r
+// セットアップ手順ダイアログプロシージャ\r
+UINT SmSetupStepDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SETUP *s = (SM_SETUP *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmSetupStepDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_USER:\r
+                       // ユーザー作成\r
+                       if (true)\r
+                       {\r
+                               SM_HUB h;\r
+\r
+                               Zero(&h, sizeof(h));\r
+                               h.HubName = s->HubName;\r
+                               h.p = s->s;\r
+                               h.Rpc = s->Rpc;\r
+\r
+                               SmUserListDlgEx(hWnd, &h, NULL, s->Flag1 ? false : true);\r
+\r
+                               s->Flag1 = true;\r
+                       }\r
+                       break;\r
+\r
+               case B_CASCADE:\r
+                       // カスケード接続作成\r
+                       if (true)\r
+                       {\r
+                               SM_HUB h;\r
+\r
+                               Zero(&h, sizeof(h));\r
+                               h.HubName = s->HubName;\r
+                               h.p = s->s;\r
+                               h.Rpc = s->Rpc;\r
+\r
+                               SmLinkDlgEx(hWnd, &h, s->Flag2 ? false : true);\r
+                               s->Flag2 = true;\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // 閉じるボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               // 終了\r
+               SmSetupOnClose(hWnd, s);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// セットアップ手順ダイアログ\r
+void SmSetupStep(HWND hWnd, SM_SETUP *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_SETUP_STEP, SmSetupStepDlg, s);\r
+}\r
+\r
+// セットアップによる初期化を行う\r
+bool SmSetupInit(HWND hWnd, SM_SETUP *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (s->IsBridge == false)\r
+       {\r
+               if (SmSetupDeleteAllLayer3(hWnd, s) == false)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               if (SmSetupDeleteAllHub(hWnd, s) == false)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (SmSetupDeleteAllObjectInBridgeHub(hWnd, s) == false)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       if (SmSetupDeleteAllLocalBridge(hWnd, s) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (s->IsBridge == false)\r
+       {\r
+               // 仮想 HUB の作成\r
+               RPC_CREATE_HUB t;\r
+               char *password = "";\r
+\r
+               Zero(&t, sizeof(t));\r
+               Hash(t.HashedPassword, password, StrLen(password), true);\r
+               HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, password);\r
+               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+               t.HubType = HUB_TYPE_STANDALONE;\r
+               t.Online = true;\r
+\r
+               if (CALL(hWnd, ScCreateHub(s->Rpc, &t)) == false)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// すべての VPN Bridge 用の仮想 HUB 内のオブジェクトを削除\r
+bool SmSetupDeleteAllObjectInBridgeHub(HWND hWnd, SM_SETUP *s)\r
+{\r
+       char *hubname = SERVER_DEFAULT_BRIDGE_NAME;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (true)\r
+       {\r
+               RPC_ENUM_LINK t;\r
+               UINT i;\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+               if (CALL(hWnd, ScEnumLink(s->Rpc, &t)) == false)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               for (i = 0;i < t.NumLink;i++)\r
+               {\r
+                       RPC_ENUM_LINK_ITEM *e = &t.Links[i];\r
+                       RPC_LINK a;\r
+\r
+                       Zero(&a, sizeof(a));\r
+                       StrCpy(a.HubName, sizeof(a.HubName), hubname);\r
+                       UniStrCpy(a.AccountName, sizeof(a.AccountName), e->AccountName);\r
+\r
+                       if (CALL(hWnd, ScDeleteLink(s->Rpc, &a)) == false)\r
+                       {\r
+                               FreeRpcEnumLink(&t);\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               FreeRpcEnumLink(&t);\r
+       }\r
+\r
+       if (true)\r
+       {\r
+               RPC_HUB t;\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+\r
+               if (CALL(hWnd, ScDisableSecureNAT(s->Rpc, &t)) == false)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// すべての仮想レイヤ 3 スイッチの削除\r
+bool SmSetupDeleteAllLayer3(HWND hWnd, SM_SETUP *s)\r
+{\r
+       RPC_ENUM_L3SW t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if(CALL(hWnd, ScEnumL3Switch(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_L3SW_ITEM *e = &t.Items[i];\r
+               RPC_L3SW tt;\r
+\r
+               Zero(&tt, sizeof(tt));\r
+               StrCpy(tt.Name, sizeof(tt.Name), e->Name);\r
+\r
+               if (CALL(hWnd, ScDelL3Switch(s->Rpc, &tt)) == false)\r
+               {\r
+                       FreeRpcEnumL3Sw(&t);\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumL3Sw(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// すべてのローカルブリッジの削除\r
+bool SmSetupDeleteAllLocalBridge(HWND hWnd, SM_SETUP *s)\r
+{\r
+       RPC_ENUM_LOCALBRIDGE t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumLocalBridge(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_LOCALBRIDGE *e = &t.Items[i];\r
+\r
+               if (CALL(hWnd, ScDeleteLocalBridge(s->Rpc, e)) == false)\r
+               {\r
+                       FreeRpcEnumLocalBridge(&t);\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumLocalBridge(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// すべての仮想 HUB の削除\r
+bool SmSetupDeleteAllHub(HWND hWnd, SM_SETUP *s)\r
+{\r
+       RPC_ENUM_HUB t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumHub(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       for (i = 0;i < t.NumHub;i++)\r
+       {\r
+               RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];\r
+               RPC_DELETE_HUB tt;\r
+\r
+               Zero(&tt, sizeof(tt));\r
+               StrCpy(tt.HubName, sizeof(tt.HubName), e->HubName);\r
+\r
+               if (CALL(hWnd, ScDeleteHub(s->Rpc, &tt)) == false)\r
+               {\r
+                       FreeRpcEnumHub(&t);\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumHub(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// 仮想 HUB のコントロール更新\r
+void SmSetupHubDlgUpdate(HWND hWnd, SM_SETUP *s)\r
+{\r
+       bool ok = true;\r
+       char tmp[MAX_HUBNAME_LEN + 1];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxtA(hWnd, E_HUBNAME, tmp, sizeof(tmp));\r
+\r
+       if (IsEmptyStr(tmp) || IsSafeStr(tmp) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// 仮想 HUB 作成ダイアログ\r
+UINT SmSetupHubDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SETUP *s = (SM_SETUP *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SetTextA(hWnd, E_HUBNAME, "VPN");\r
+               FocusEx(hWnd, E_HUBNAME);\r
+               SmSetupHubDlgUpdate(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               SmSetupHubDlgUpdate(hWnd, s);\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       GetTxtA(hWnd, E_HUBNAME, s->HubName, sizeof(s->HubName));\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// セットアップダイアログの [次へ] ボタン\r
+void SmSetupDlgOnOk(HWND hWnd, SM_SETUP *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (MsgBox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, _UU("SM_SETUP_WARNING")) == IDNO)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s->UseRemote = IsChecked(hWnd, C_REMOTE);\r
+       s->UseSite = IsChecked(hWnd, C_SITE);\r
+       s->UseSiteEdge = IsChecked(hWnd, C_EDGE);\r
+\r
+       if (s->IsBridge)\r
+       {\r
+               StrCpy(s->HubName, sizeof(s->HubName), SERVER_DEFAULT_BRIDGE_NAME);\r
+       }\r
+       else\r
+       {\r
+               if (Dialog(hWnd, D_SM_SETUP_HUB, SmSetupHubDlg, s) == false)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       // 初期化 (既存オブジェクトの抹消)\r
+       if (SmSetupInit(hWnd, s) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 手順の実行\r
+       SmSetupStep(hWnd, s);\r
+\r
+       // ダイアログを閉じる\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// セットアップダイアログ初期化\r
+void SmSetupDlgInit(HWND hWnd, SM_SETUP *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_SETUP);\r
+       DlgFont(hWnd, S_TITLE, 14, true);\r
+       DlgFont(hWnd, C_REMOTE, 0, true);\r
+       DlgFont(hWnd, C_SITE, 0, true);\r
+       DlgFont(hWnd, C_OTHER, 0, true);\r
+\r
+       if (s->IsBridge)\r
+       {\r
+               SetText(hWnd, B_BOLD, _UU("SM_SETUP_BRIDGE_ONLY"));\r
+               SetText(hWnd, C_EDGE, _UU("SM_SETUP_BRIDGE_EDGE"));\r
+\r
+               Check(hWnd, C_SITE, true);\r
+               Check(hWnd, C_EDGE, true);\r
+               Focus(hWnd, C_SITE);\r
+       }\r
+\r
+       SmSetupDlgUpdate(hWnd, s);\r
+}\r
+\r
+// セットアップダイアログ更新\r
+void SmSetupDlgUpdate(HWND hWnd, SM_SETUP *s)\r
+{\r
+       bool enable_remote = true;\r
+       bool enable_site = true;\r
+       bool enable_site_center = true;\r
+       bool enable_detail = true;\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (s->IsBridge)\r
+       {\r
+               enable_remote = false;\r
+               enable_site_center = false;\r
+               enable_detail = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, C_OTHER))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, C_REMOTE, enable_remote && IsChecked(hWnd, C_OTHER) == false);\r
+       SetEnable(hWnd, S_REMOTE_1, enable_remote && IsChecked(hWnd, C_OTHER) == false);\r
+\r
+       SetEnable(hWnd, C_SITE, enable_site && IsChecked(hWnd, C_OTHER) == false);\r
+       SetEnable(hWnd, S_SITE_1, enable_site && IsChecked(hWnd, C_OTHER) == false);\r
+       SetEnable(hWnd, S_SITE_2, enable_site && IsChecked(hWnd, C_SITE) && IsChecked(hWnd, C_OTHER) == false);\r
+       SetEnable(hWnd, C_CENTER, enable_site && enable_site_center && IsChecked(hWnd, C_SITE) && IsChecked(hWnd, C_OTHER) == false);\r
+       SetEnable(hWnd, C_EDGE, enable_site && IsChecked(hWnd, C_SITE) && IsChecked(hWnd, C_OTHER) == false);\r
+\r
+       SetEnable(hWnd, C_OTHER, enable_detail);\r
+       SetEnable(hWnd, S_OTHER, enable_detail);\r
+\r
+       if (IsChecked(hWnd, C_REMOTE) == false && IsChecked(hWnd, C_SITE) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, C_SITE))\r
+       {\r
+               if (IsChecked(hWnd, C_CENTER) == false && IsChecked(hWnd, C_EDGE) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+\r
+       SetText(hWnd, S_INFO,\r
+               IsChecked(hWnd, C_OTHER) ? _UU("SM_SETUP_INFO_2") : _UU("SM_SETUP_INFO_1"));\r
+}\r
+\r
+// セットアップダイアログ\r
+UINT SmSetupDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SETUP *s = (SM_SETUP *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmSetupDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               SmSetupDlgUpdate(hWnd, s);\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       SmSetupDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// セットアップ\r
+bool SmSetup(HWND hWnd, SM_SERVER *s)\r
+{\r
+       SM_SETUP ss;\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&ss, sizeof(ss));\r
+       ss.s = s;\r
+       ss.IsBridge = ss.s->Bridge;\r
+       ss.Rpc = s->Rpc;\r
+\r
+       if (Dialog(hWnd, D_SM_SETUP, SmSetupDlg, &ss) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// ライセンス登録処理\r
+void SmLicenseAddDlgOnOk(HWND hWnd, SM_SERVER *s)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmLicenseAddDlgGetText(hWnd, tmp, sizeof(tmp));\r
+\r
+       if (true)\r
+       {\r
+               RPC_TEST t;\r
+\r
+               Disable(hWnd, IDOK);\r
+               Disable(hWnd, IDCANCEL);\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.StrValue, sizeof(t.StrValue), tmp);\r
+\r
+               if (CALL(hWnd, ScAddLicenseKey(s->Rpc, &t)) == false)\r
+               {\r
+                       FocusEx(hWnd, B_KEY6);\r
+               }\r
+               else\r
+               {\r
+                       EndDialog(hWnd, true);\r
+               }\r
+\r
+               Enable(hWnd, IDOK);\r
+               Enable(hWnd, IDCANCEL);\r
+       }\r
+}\r
+\r
+// テキスト入力のシフト処理\r
+void SmLicenseAddDlgShiftTextItem(HWND hWnd, UINT id1, UINT id2, UINT *next_focus)\r
+{\r
+       char *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || next_focus == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s = GetTextA(hWnd, id1);\r
+       if (StrLen(s) >= 6)\r
+       {\r
+               char *s2 = CopyStr(s);\r
+               char tmp[MAX_SIZE];\r
+               s2[6] = 0;\r
+               SetTextA(hWnd, id1, s2);\r
+               Free(s2);\r
+\r
+               if (id2 != 0)\r
+               {\r
+                       GetTxtA(hWnd, id2, tmp, sizeof(tmp));\r
+\r
+                       StrCat(tmp, sizeof(tmp), s + 6);\r
+                       ReplaceStrEx(tmp, sizeof(tmp), tmp, "-", "", false);\r
+\r
+                       SetTextA(hWnd, id2, tmp);\r
+\r
+                       *next_focus = id2;\r
+               }\r
+               else\r
+               {\r
+                       *next_focus = IDOK;\r
+               }\r
+       }\r
+\r
+       Free(s);\r
+}\r
+\r
+// 入力データをテキスト化\r
+void SmLicenseAddDlgGetText(HWND hWnd, char *str, UINT size)\r
+{\r
+       char *k1, *k2, *k3, *k4, *k5, *k6;\r
+       // 引数チェック\r
+       if (hWnd == NULL || str == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       k1 = GetTextA(hWnd, B_KEY1);\r
+       k2 = GetTextA(hWnd, B_KEY2);\r
+       k3 = GetTextA(hWnd, B_KEY3);\r
+       k4 = GetTextA(hWnd, B_KEY4);\r
+       k5 = GetTextA(hWnd, B_KEY5);\r
+       k6 = GetTextA(hWnd, B_KEY6);\r
+\r
+       Format(str, size, "%s-%s-%s-%s-%s-%s", k1, k2, k3, k4, k5, k6);\r
+\r
+       Free(k1);\r
+       Free(k2);\r
+       Free(k3);\r
+       Free(k4);\r
+       Free(k5);\r
+       Free(k6);\r
+}\r
+\r
+// ライセンス追加ダイアログ更新\r
+void SmLicenseAddDlgUpdate(HWND hWnd, SM_SERVER *s)\r
+{\r
+       UINT next_focus = 0;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (s == NULL || hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmLicenseAddDlgShiftTextItem(hWnd, B_KEY1, B_KEY2, &next_focus);\r
+       SmLicenseAddDlgShiftTextItem(hWnd, B_KEY2, B_KEY3, &next_focus);\r
+       SmLicenseAddDlgShiftTextItem(hWnd, B_KEY3, B_KEY4, &next_focus);\r
+       SmLicenseAddDlgShiftTextItem(hWnd, B_KEY4, B_KEY5, &next_focus);\r
+       SmLicenseAddDlgShiftTextItem(hWnd, B_KEY5, B_KEY6, &next_focus);\r
+       SmLicenseAddDlgShiftTextItem(hWnd, B_KEY6, 0, &next_focus);\r
+\r
+       if ((IsFocus(hWnd, B_KEY1) && GetTextLen(hWnd, B_KEY1, true) <= 5) ||\r
+               (IsFocus(hWnd, B_KEY2) && GetTextLen(hWnd, B_KEY2, true) <= 5) ||\r
+               (IsFocus(hWnd, B_KEY3) && GetTextLen(hWnd, B_KEY3, true) <= 5) ||\r
+               (IsFocus(hWnd, B_KEY4) && GetTextLen(hWnd, B_KEY4, true) <= 5) ||\r
+               (IsFocus(hWnd, B_KEY5) && GetTextLen(hWnd, B_KEY5, true) <= 5) ||\r
+               (IsFocus(hWnd, B_KEY6) && GetTextLen(hWnd, B_KEY6, true) <= 5))\r
+       {\r
+               next_focus = 0;\r
+       }\r
+\r
+       if (next_focus != 0)\r
+       {\r
+               Focus(hWnd, next_focus);\r
+       }\r
+\r
+       SmLicenseAddDlgGetText(hWnd, tmp, sizeof(tmp));\r
+\r
+       SetEnable(hWnd, IDOK, true);\r
+}\r
+\r
+// ライセンス追加ダイアログ初期化\r
+void SmLicenseAddDlgInit(HWND hWnd, SM_SERVER *s)\r
+{\r
+       HFONT h;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       h = GetFont("Arial", 10, true, false, false, false);\r
+       SetFont(hWnd, B_KEY1, h);\r
+       SetFont(hWnd, B_KEY2, h);\r
+       SetFont(hWnd, B_KEY3, h);\r
+       SetFont(hWnd, B_KEY4, h);\r
+       SetFont(hWnd, B_KEY5, h);\r
+       SetFont(hWnd, B_KEY6, h);\r
+\r
+       DlgFont(hWnd, S_INFO, 10, true);\r
+\r
+       SmLicenseAddDlgUpdate(hWnd, s);\r
+}\r
+\r
+// ライセンスの追加ダイアログ\r
+UINT SmLicenseAddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *s = (SM_SERVER *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmLicenseAddDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case B_KEY1:\r
+               case B_KEY2:\r
+               case B_KEY3:\r
+               case B_KEY4:\r
+               case B_KEY5:\r
+               case B_KEY6:\r
+                       switch (HIWORD(wParam))\r
+                       {\r
+                       case EN_CHANGE:\r
+                               SmLicenseAddDlgUpdate(hWnd, s);\r
+\r
+                               switch (LOWORD(wParam))\r
+                               {\r
+                               case B_KEY2:\r
+                                       if (GetTextLen(hWnd, B_KEY2, true) == 0)\r
+                                       {\r
+                                               FocusEx(hWnd, B_KEY1);\r
+                                       }\r
+                                       break;\r
+                               case B_KEY3:\r
+                                       if (GetTextLen(hWnd, B_KEY3, true) == 0)\r
+                                       {\r
+                                               FocusEx(hWnd, B_KEY2);\r
+                                       }\r
+                                       break;\r
+                               case B_KEY4:\r
+                                       if (GetTextLen(hWnd, B_KEY4, true) == 0)\r
+                                       {\r
+                                               FocusEx(hWnd, B_KEY3);\r
+                                       }\r
+                                       break;\r
+                               case B_KEY5:\r
+                                       if (GetTextLen(hWnd, B_KEY5, true) == 0)\r
+                                       {\r
+                                               FocusEx(hWnd, B_KEY4);\r
+                                       }\r
+                                       break;\r
+                               case B_KEY6:\r
+                                       if (GetTextLen(hWnd, B_KEY6, true) == 0)\r
+                                       {\r
+                                               FocusEx(hWnd, B_KEY5);\r
+                                       }\r
+                                       break;\r
+                               }\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       SmLicenseAddDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ライセンスの追加\r
+bool SmLicenseAdd(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return Dialog(hWnd, D_SM_LICENSE_ADD, SmLicenseAddDlg, s);\r
+}\r
+\r
+// ライセンスダイアログ初期化\r
+void SmLicenseDlgInit(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_CERT);\r
+\r
+       DlgFont(hWnd, S_BOLD, 0, true);\r
+       DlgFont(hWnd, S_BOLD2, 0, true);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_LICENSE_COLUMN_1"), 50);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_LICENSE_COLUMN_2"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_LICENSE_COLUMN_3"), 290);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_LICENSE_COLUMN_4"), 150);\r
+       LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_LICENSE_COLUMN_5"), 120);\r
+       LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_LICENSE_COLUMN_6"), 250);\r
+       LvInsertColumn(hWnd, L_LIST, 6, _UU("SM_LICENSE_COLUMN_7"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 7, _UU("SM_LICENSE_COLUMN_8"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 8, _UU("SM_LICENSE_COLUMN_9"), 100);\r
+\r
+       LvInitEx(hWnd, L_STATUS, true);\r
+       LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 100);\r
+       LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 100);\r
+\r
+       SmLicenseDlgRefresh(hWnd, s);\r
+}\r
+\r
+// ライセンスダイアログ更新\r
+void SmLicenseDlgRefresh(HWND hWnd, SM_SERVER *s)\r
+{\r
+       RPC_ENUM_LICENSE_KEY t;\r
+       RPC_LICENSE_STATUS st;\r
+       UINT i;\r
+       wchar_t tmp[MAX_SIZE];\r
+       LVB *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       if (CALL(hWnd, ScEnumLicenseKey(s->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               wchar_t tmp1[32], tmp2[LICENSE_KEYSTR_LEN + 1], tmp3[LICENSE_MAX_PRODUCT_NAME_LEN + 1],\r
+                       *tmp4, tmp5[128], tmp6[LICENSE_LICENSEID_STR_LEN + 1], tmp7[64],\r
+                       tmp8[64], tmp9[64];\r
+               RPC_ENUM_LICENSE_KEY_ITEM *e = &t.Items[i];\r
+\r
+               UniToStru(tmp1, e->Id);\r
+               StrToUni(tmp2, sizeof(tmp2), e->LicenseKey);\r
+               StrToUni(tmp3, sizeof(tmp3), e->LicenseName);\r
+               tmp4 = LiGetLicenseStatusStr(e->Status);\r
+               if (e->Expires == 0)\r
+               {\r
+                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_LICENSE_NO_EXPIRES"));\r
+               }\r
+               else\r
+               {\r
+                       GetDateStrEx64(tmp5, sizeof(tmp5), e->Expires, NULL);\r
+               }\r
+               StrToUni(tmp6, sizeof(tmp6), e->LicenseId);\r
+               UniToStru(tmp7, e->ProductId);\r
+               UniFormat(tmp8, sizeof(tmp8), L"%I64u", e->SystemId);\r
+               UniToStru(tmp9, e->SerialId);\r
+\r
+               LvInsertAdd(b,\r
+                       e->Status == LICENSE_STATUS_OK ? ICO_PASS : ICO_DISCARD,\r
+                       (void *)e->Id, 9,\r
+                       tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_LIST);\r
+\r
+       FreeRpcEnumLicenseKey(&t);\r
+\r
+       Zero(&st, sizeof(st));\r
+\r
+       if (CALL(hWnd, ScGetLicenseStatus(s->Rpc, &st)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       if (st.EditionId == LICENSE_EDITION_VPN3_NO_LICENSE)\r
+       {\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_NO_LICENSE_COLUMN"), _UU("SM_NO_LICENSE"));\r
+       }\r
+       else\r
+       {\r
+               // 製品エディション名\r
+               StrToUni(tmp, sizeof(tmp), st.EditionStr);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_EDITION"), tmp);\r
+\r
+               // リリース日付\r
+               if (st.ReleaseDate != 0)\r
+               {\r
+                       GetDateStrEx64(tmp, sizeof(tmp), st.ReleaseDate, NULL);\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_RELEASE"), tmp);\r
+               }\r
+\r
+               // 現在のシステム ID\r
+               UniFormat(tmp, sizeof(tmp), L"%I64u", st.SystemId);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SYSTEM_ID"), tmp);\r
+\r
+               // 現在の製品ライセンスの有効期限\r
+               if (st.SystemExpires == 0)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_NO_EXPIRES"));\r
+               }\r
+               else\r
+               {\r
+                       GetDateStrEx64(tmp, sizeof(tmp), st.SystemExpires, NULL);\r
+               }\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_EXPIRES"), tmp);\r
+\r
+               // サブスクリプション (サポート) 契約\r
+               if (st.NeedSubscription == false)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONEED"));\r
+               }\r
+               else\r
+               {\r
+                       if (st.SubscriptionExpires == 0)\r
+                       {\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               wchar_t dtstr[MAX_PATH];\r
+\r
+                               GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);\r
+\r
+                               UniFormat(tmp, sizeof(tmp),\r
+                                       st.IsSubscriptionExpired ? _UU("SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED") :  _UU("SM_LICENSE_STATUS_SUBSCRIPTION_VALID"),\r
+                                       dtstr);\r
+                       }\r
+               }\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SUBSCRIPTION"), tmp);\r
+\r
+               if (st.NeedSubscription == false && st.SubscriptionExpires != 0)\r
+               {\r
+                       wchar_t dtstr[MAX_PATH];\r
+\r
+                       GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);\r
+\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR"), tmp);\r
+               }\r
+\r
+               if (st.NeedSubscription && st.SubscriptionExpires != 0)\r
+               {\r
+                       wchar_t dtstr[MAX_PATH];\r
+\r
+                       GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR"), dtstr);\r
+\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD"), tmp);\r
+               }\r
+\r
+               if (GetCapsBool(s->CapsList, "b_vpn3"))\r
+               {\r
+                       // ユーザー作成可能数\r
+                       if (st.NumUserCreationLicense == INFINITE)\r
+                       {\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniToStru(tmp, st.NumUserCreationLicense);\r
+                       }\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_NUM_USER"), tmp);\r
+               }\r
+\r
+               // クライアント同時接続可能数\r
+               if (st.NumClientConnectLicense == INFINITE)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp, st.NumClientConnectLicense);\r
+               }\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_NUM_CLIENT"), tmp);\r
+\r
+               // ブリッジ同時接続可能数\r
+               if (st.NumBridgeConnectLicense == INFINITE)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp, st.NumBridgeConnectLicense);\r
+               }\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_NUM_BRIDGE"), tmp);\r
+\r
+               // エンタープライズ機能の利用可否\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_LICENSE_STATUS_ENTERPRISE"),\r
+                       st.AllowEnterpriseFunction ? _UU("SM_LICENSE_STATUS_ENTERPRISE_YES") : _UU("SM_LICENSE_STATUS_ENTERPRISE_NO"));\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       if (LvNum(hWnd, L_STATUS) >= 1)\r
+       {\r
+               LvAutoSize(hWnd, L_STATUS);\r
+       }\r
+\r
+       SmLicenseDlgUpdate(hWnd, s);\r
+}\r
+\r
+// ライセンスダイアログコントロール更新\r
+void SmLicenseDlgUpdate(HWND hWnd, SM_SERVER *s)\r
+{\r
+       bool b = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = LvIsSingleSelected(hWnd, L_LIST);\r
+\r
+       SetEnable(hWnd, B_DEL, b);\r
+       SetEnable(hWnd, IDOK, b);\r
+}\r
+\r
+// ライセンスダイアログ\r
+UINT SmLicenseDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *s = (SM_SERVER *)param;\r
+       NMHDR *n;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmLicenseDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_LIST:\r
+                       case L_STATUS:\r
+                               SmLicenseDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               UINT i = LvGetSelected(hWnd, L_LIST);\r
+\r
+                               if (i != INFINITE)\r
+                               {\r
+                                       char *s = LvGetStrA(hWnd, L_LIST, i, 1);\r
+                                       char tmp[MAX_SIZE];\r
+\r
+                                       Format(tmp, sizeof(tmp), _SS("LICENSE_SUPPORT_URL"), s);\r
+                                       ShellExecute(hWnd, "open", tmp, NULL, NULL, SW_SHOW);\r
+\r
+                                       Free(s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_OBTAIN:\r
+                       ShellExecute(hWnd, "open", _SS("LICENSE_INFO_URL"), NULL, NULL, SW_SHOW);\r
+                       break;\r
+\r
+               case B_ADD:\r
+                       if (SmLicenseAdd(hWnd, s))\r
+                       {\r
+                               SmLicenseDlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DEL:\r
+                       if (IsEnable(hWnd, B_DEL))\r
+                       {\r
+                               UINT id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));\r
+\r
+                               if (id != 0)\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_LICENSE_DELETE_MSG")) == IDYES)\r
+                                       {\r
+                                               RPC_TEST t;\r
+\r
+                                               Zero(&t, sizeof(t));\r
+                                               t.IntValue = id;\r
+\r
+                                               if (CALL(hWnd, ScDelLicenseKey(s->Rpc, &t)))\r
+                                               {\r
+                                                       SmLicenseDlgRefresh(hWnd, s);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+// ライセンスの追加と削除\r
+void SmLicense(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_LICENSE, SmLicenseDlg, s);\r
+\r
+       FreeCapsList(s->CapsList);\r
+       s->CapsList = ScGetCapsEx(s->Rpc);\r
+}\r
+\r
+// ログ保存プロシージャ\r
+UINT SmSaveLogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_READ_LOG_FILE *p = (SM_READ_LOG_FILE *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               FormatText(hWnd, S_INFO, p->filepath);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+               case B_SAVE:\r
+                       if (p->Buffer != NULL)\r
+                       {\r
+                               char filename[MAX_PATH];\r
+\r
+                               Format(filename, sizeof(filename), "%s_%s", p->server_name, p->filepath);\r
+                               ConvertSafeFileName(filename, sizeof(filename), filename);\r
+\r
+                               if (wParam == IDOK)\r
+                               {\r
+                                       // エディタで開く\r
+                                       char fullpath[MAX_PATH];\r
+\r
+                                       Format(fullpath, sizeof(fullpath), "%s\\%s",\r
+                                               MsGetMyTempDir(), filename);\r
+\r
+                                       if (DumpBuf(p->Buffer, fullpath) == false)\r
+                                       {\r
+                                               MsgBoxEx(hWnd, MB_ICONSTOP, _UU("SM_READ_SAVE_TMP_FAILED"),\r
+                                                       fullpath);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (((UINT)ShellExecute(hWnd, "open", fullpath, NULL, NULL, SW_SHOWNORMAL)) > 32)\r
+                                               {\r
+                                                       EndDialog(hWnd, true);\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_READ_SAVE_OPEN_ERROR"), fullpath);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       // ファイルに保存する\r
+                                       wchar_t def[MAX_PATH];\r
+                                       wchar_t *uni_path;\r
+\r
+                                       StrToUni(def, sizeof(def), filename);\r
+                                       \r
+                                       uni_path = SaveDlg(hWnd, _UU("SM_READ_SAVE_DLG_FILTER"), _UU("SM_READ_SAVE_DLG_TITLE"),\r
+                                               def, L".log");\r
+\r
+                                       if (uni_path != NULL)\r
+                                       {\r
+                                               char path[MAX_PATH];\r
+\r
+                                               UniToStr(path, sizeof(path), uni_path);\r
+                                               Free(uni_path);\r
+\r
+                                               if (DumpBuf(p->Buffer, path) == false)\r
+                                               {\r
+                                                       MsgBox(hWnd, MB_ICONSTOP, _UU("SM_READ_SAVE_FAILED"));\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       EndDialog(hWnd, true);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ダウンロードコールバックプロシージャ\r
+bool SmReadLogFileProc(DOWNLOAD_PROGRESS *g)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char size1[64], size2[64];\r
+       SM_READ_LOG_FILE *p;\r
+       HWND hWnd;\r
+       // 引数チェック\r
+       if (g == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       p = (SM_READ_LOG_FILE *)g->Param;\r
+       hWnd = p->hWnd;\r
+\r
+       SetPos(hWnd, P_PROGRESS, g->ProgressPercent);\r
+\r
+       ToStrByte(size1, sizeof(size1), g->CurrentSize);\r
+       ToStrByte(size2, sizeof(size2), g->TotalSize);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_READ_LOG_FILE_INFO_2"), size2, size1);\r
+\r
+       SetText(hWnd, S_INFO, tmp);\r
+\r
+       DoEvents(hWnd);\r
+\r
+       return p->cancel_flag ? false : true;\r
+}\r
+\r
+// ログファイルダウンロードダイアログプロシージャ\r
+UINT SmReadLogFile(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_READ_LOG_FILE *p = (SM_READ_LOG_FILE *)param;\r
+       BUF *buf;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               p->hWnd = hWnd;\r
+               SetFont(hWnd, S_INFO, Font(11, true));\r
+               SetText(hWnd, S_INFO, _UU("SM_READ_LOG_FILE_INFO_1"));\r
+               DisableClose(hWnd);\r
+               FormatText(hWnd, S_INFO2, p->filepath);\r
+               SetRange(hWnd, P_PROGRESS, 0, 100);\r
+\r
+               SetTimer(hWnd, 1, 100, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       buf = DownloadFileFromServer(p->s->Rpc, p->server_name, p->filepath, p->totalsize, SmReadLogFileProc, p);\r
+                       if (buf == NULL)\r
+                       {\r
+                               if (p->cancel_flag == false)\r
+                               {\r
+                                       // ダウンロード失敗\r
+                                       MsgBox(hWnd, MB_ICONSTOP, _UU("SM_READ_LOG_FILE_ERROR"));\r
+                               }\r
+                               EndDialog(hWnd, false);\r
+                       }\r
+                       else\r
+                       {\r
+                               // ダウンロード成功\r
+                               p->Buffer = buf;\r
+                               Dialog(hWnd, D_SM_SAVE_LOG, SmSaveLogProc, p);\r
+                               FreeBuf(buf);\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDCANCEL:\r
+                       p->cancel_flag = true;\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ログファイルのダウンロードを開始する\r
+void SmLogFileStartDownload(HWND hWnd, SM_SERVER *s, char *server_name, char *filepath, UINT totalsize)\r
+{\r
+       SM_READ_LOG_FILE p;\r
+       // 引数チェック\r
+       if (hWnd == NULL || server_name == NULL || filepath == NULL || totalsize == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       p.filepath = filepath;\r
+       p.s = s;\r
+       p.server_name = server_name;\r
+       p.totalsize = totalsize;\r
+\r
+       Dialog(hWnd, D_SM_READ_LOG_FILE, SmReadLogFile, &p);\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmLogFileDlgInit(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_LOG2);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_LOG_FILE_COLUMN_1"), 250);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_LOG_FILE_COLUMN_2"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_LOG_FILE_COLUMN_3"), 130);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_LOG_FILE_COLUMN_4"), 110);\r
+\r
+       SmLogFileDlgRefresh(hWnd, p);\r
+}\r
+\r
+// ダイアログ内容更新\r
+void SmLogFileDlgRefresh(HWND hWnd, SM_SERVER *p)\r
+{\r
+       UINT i;\r
+       LVB *v;\r
+       RPC_ENUM_LOG_FILE t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumLogFile(p->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       v = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t.Items[i];\r
+               wchar_t tmp1[MAX_PATH], tmp2[128], tmp3[128], tmp4[MAX_HOST_NAME_LEN + 1];\r
+               char tmp[MAX_SIZE];\r
+\r
+               StrToUni(tmp1, sizeof(tmp1), e->FilePath);\r
+\r
+               ToStrByte(tmp, sizeof(tmp), e->FileSize);\r
+               StrToUni(tmp2, sizeof(tmp2), tmp);\r
+\r
+               GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->UpdatedTime));\r
+\r
+               StrToUni(tmp4, sizeof(tmp4), e->ServerName);\r
+\r
+               LvInsertAdd(v, ICO_LOG2, (void *)e->FileSize, 4, tmp1, tmp2, tmp3, tmp4);\r
+       }\r
+\r
+       LvInsertEndEx(v, hWnd, L_LIST, true);\r
+\r
+       if (t.NumItem != 0)\r
+       {\r
+               LvAutoSize(hWnd, L_LIST);\r
+       }\r
+\r
+       FreeRpcEnumLogFile(&t);\r
+\r
+       SmLogFileDlgUpdate(hWnd, p);\r
+}\r
+\r
+// ダイアログコントロール更新\r
+void SmLogFileDlgUpdate(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));\r
+}\r
+\r
+// ログファイルダイアログプロシージャ\r
+UINT SmLogFileDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmLogFileDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               UINT i = LvGetSelected(hWnd, L_LIST);\r
+                               if (i != INFINITE)\r
+                               {\r
+                                       UINT size = (UINT)LvGetParam(hWnd, L_LIST, i);\r
+                                       char *server_name;\r
+                                       char *filepath;\r
+\r
+                                       server_name = LvGetStrA(hWnd, L_LIST, i, 3);\r
+                                       filepath = LvGetStrA(hWnd, L_LIST, i, 0);\r
+                                       SmLogFileStartDownload(hWnd, p, server_name, filepath, size);\r
+                                       Free(filepath);\r
+                                       Free(server_name);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       SmLogFileDlgRefresh(hWnd, p);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_LIST:\r
+                               SmLogFileDlgUpdate(hWnd, p);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmHubEditAcDlgInit(HWND hWnd, SM_EDIT_AC *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, R_IPV6, GetCapsBool(p->e->s->p->CapsList, "b_support_ipv6_ac"));\r
+\r
+       if (p->id == 0)\r
+       {\r
+               UINT i, v;\r
+\r
+               Check(hWnd, R_SINGLE, true);\r
+               Check(hWnd, R_PASS, true);\r
+               Check(hWnd, R_IPV4, true);\r
+\r
+               v = 0;\r
+\r
+               for (i = 0;i < LIST_NUM(p->e->AcList);i++)\r
+               {\r
+                       AC *ac = LIST_DATA(p->e->AcList, i);\r
+\r
+                       v = MAX(v, ac->Priority);\r
+               }\r
+\r
+               v += 100;\r
+\r
+               SetInt(hWnd, E_PRIORITY, v);\r
+       }\r
+       else\r
+       {\r
+               AC *ac = GetAc(p->e->AcList, p->id);\r
+\r
+               if (ac == NULL)\r
+               {\r
+                       EndDialog(hWnd, false);\r
+                       return;\r
+               }\r
+\r
+               Check(hWnd, R_SINGLE, ac->Masked == false);\r
+               Check(hWnd, R_MASKED, ac->Masked);\r
+               Check(hWnd, R_IPV4, IsIP4(&ac->IpAddress));\r
+               Check(hWnd, R_IPV6, IsIP6(&ac->IpAddress));\r
+\r
+               if (IsIP4(&ac->IpAddress))\r
+               {\r
+                       IpSet(hWnd, E_IP, IPToUINT(&ac->IpAddress));\r
+               }\r
+               else\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+\r
+                       IPToStr(tmp, sizeof(tmp), &ac->IpAddress);\r
+                       SetTextA(hWnd, E_IPV6, tmp);\r
+               }\r
+\r
+               if (ac->Masked)\r
+               {\r
+                       if (IsIP4(&ac->IpAddress))\r
+                       {\r
+                               IpSet(hWnd, E_MASK, IPToUINT(&ac->SubnetMask));\r
+                       }\r
+                       else\r
+                       {\r
+                               char tmp[MAX_SIZE];\r
+\r
+                               MaskToStrEx(tmp, sizeof(tmp), &ac->SubnetMask, false);\r
+\r
+                               if (IsNum(tmp))\r
+                               {\r
+                                       StrCatLeft(tmp, sizeof(tmp), "/");\r
+                               }\r
+\r
+                               SetTextA(hWnd, E_MASKV6, tmp);\r
+                       }\r
+               }\r
+\r
+               Check(hWnd, R_PASS, ac->Deny == false);\r
+               Check(hWnd, R_DENY, ac->Deny);\r
+               SetInt(hWnd, E_PRIORITY, ac->Priority);\r
+\r
+               Free(ac);\r
+       }\r
+\r
+       Focus(hWnd, E_IP);\r
+\r
+       SmHubEditAcDlgUpdate(hWnd, p);\r
+}\r
+\r
+// ダイアログ更新\r
+void SmHubEditAcDlgUpdate(HWND hWnd, SM_EDIT_AC *p)\r
+{\r
+       bool b = true;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_SINGLE))\r
+       {\r
+               if (IsChecked(hWnd, R_IPV6) == false)\r
+               {\r
+                       Show(hWnd, E_IP);\r
+                       Hide(hWnd, E_IPV6);\r
+\r
+                       if (IpIsFilled(hWnd, E_IP) == false)\r
+                       {\r
+                               b = false;\r
+                       }\r
+\r
+                       if (IpGet(hWnd, E_IP) == 0 || IpGet(hWnd, E_IP) == 0xffffffff)\r
+                       {\r
+                               b = false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       Show(hWnd, E_IPV6);\r
+                       Hide(hWnd, E_IP);\r
+\r
+                       GetTxtA(hWnd, E_IPV6, tmp, sizeof(tmp));\r
+\r
+                       if (IsStrIPv6Address(tmp) == false)\r
+                       {\r
+                               b = false;\r
+                       }\r
+               }\r
+\r
+               Hide(hWnd, S_MASK);\r
+               Hide(hWnd, E_MASK);\r
+               Hide(hWnd, E_MASKV6);\r
+       }\r
+       else\r
+       {\r
+               if (IsChecked(hWnd, R_IPV6) == false)\r
+               {\r
+                       Show(hWnd, E_IP);\r
+                       Hide(hWnd, E_IPV6);\r
+\r
+                       if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false)\r
+                       {\r
+                               b = false;\r
+                       }\r
+\r
+                       if (IpGet(hWnd, E_IP) == 0xffffffff)\r
+                       {\r
+                               b = false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       char tmp1[MAX_SIZE], tmp2[MAX_SIZE];\r
+\r
+                       Show(hWnd, E_IPV6);\r
+                       Hide(hWnd, E_IP);\r
+\r
+                       GetTxtA(hWnd, E_IPV6, tmp1, sizeof(tmp1));\r
+                       GetTxtA(hWnd, E_MASKV6, tmp2, sizeof(tmp2));\r
+\r
+                       if (!(IsIpStr6(tmp1) && IsIpMask6(tmp2)))\r
+                       {\r
+                               b = false;\r
+                       }\r
+               }\r
+\r
+               Show(hWnd, S_MASK);\r
+               SetShow(hWnd, E_MASK, !IsChecked(hWnd, R_IPV6));\r
+               SetShow(hWnd, E_MASKV6, IsChecked(hWnd, R_IPV6));\r
+       }\r
+\r
+       if (GetInt(hWnd, E_PRIORITY) == 0)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       SetIcon(hWnd, S_ICON, IsChecked(hWnd, R_PASS) ? ICO_INTERNET : ICO_INTERNET_X);\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+}\r
+\r
+// ダイアログで OK ボタンがクリックされた\r
+void SmHubEditAcDlgOnOk(HWND hWnd, SM_EDIT_AC *p)\r
+{\r
+       AC ac;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&ac, sizeof(ac));\r
+       ac.Deny = IsChecked(hWnd, R_DENY);\r
+       ac.Priority = GetInt(hWnd, E_PRIORITY);\r
+\r
+       if (IsChecked(hWnd, R_IPV6) == false)\r
+       {\r
+               UINTToIP(&ac.IpAddress, IpGet(hWnd, E_IP));\r
+       }\r
+       else\r
+       {\r
+               GetTxtA(hWnd, E_IPV6, tmp, sizeof(tmp));\r
+\r
+               StrToIP6(&ac.IpAddress, tmp);\r
+       }\r
+\r
+       ac.Masked = IsChecked(hWnd, R_MASKED);\r
+\r
+       if (ac.Masked)\r
+       {\r
+               if (IsChecked(hWnd, R_IPV6) == false)\r
+               {\r
+                       UINTToIP(&ac.SubnetMask, IpGet(hWnd, E_MASK));\r
+               }\r
+               else\r
+               {\r
+                       GetTxtA(hWnd, E_MASKV6, tmp, sizeof(tmp));\r
+\r
+                       StrToMask6(&ac.SubnetMask, tmp);\r
+               }\r
+       }\r
+\r
+       if (p->id != 0)\r
+       {\r
+               SetAc(p->e->AcList, p->id, &ac);\r
+       }\r
+       else\r
+       {\r
+               AddAc(p->e->AcList, &ac);\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// AC 編集ダイアログ\r
+UINT SmHubEditAcDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_AC *p = (SM_EDIT_AC *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmHubEditAcDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_SINGLE:\r
+               case R_MASKED:\r
+               case E_IP:\r
+               case E_MASK:\r
+               case R_PASS:\r
+               case R_DENY:\r
+               case E_PRIORITY:\r
+               case R_IPV4:\r
+               case R_IPV6:\r
+               case E_IPV6:\r
+               case E_MASKV6:\r
+                       SmHubEditAcDlgUpdate(hWnd, p);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case R_IPV4:\r
+               case R_IPV6:\r
+               case R_SINGLE:\r
+               case R_MASKED:\r
+                       if (IsChecked(hWnd, R_IPV6) == false)\r
+                       {\r
+                               if (IpIsFilled(hWnd, E_IP))\r
+                               {\r
+                                       Focus(hWnd, E_MASK);\r
+                               }\r
+                               else\r
+                               {\r
+                                       Focus(hWnd, E_IP);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               char tmp[MAX_SIZE];\r
+\r
+                               GetTxtA(hWnd, E_IPV6, tmp, sizeof(tmp));\r
+\r
+                               if (IsStrIPv6Address(tmp))\r
+                               {\r
+                                       FocusEx(hWnd, E_MASKV6);\r
+                               }\r
+                               else\r
+                               {\r
+                                       FocusEx(hWnd, E_IPV6);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       SmHubEditAcDlgOnOk(hWnd, p);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmHubAcDlgInit(HWND hWnd, SM_EDIT_AC_LIST *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_INTERNET);\r
+\r
+       FormatText(hWnd, S_TITLE, p->s->HubName);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_AC_COLUMN_1"), 40);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_AC_COLUMN_2"), 80);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_AC_COLUMN_3"), 90);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_AC_COLUMN_4"), 170);\r
+\r
+       SmHubAcDlgRefresh(hWnd, p);\r
+}\r
+\r
+// ダイアログコントロール更新\r
+void SmHubAcDlgUpdate(HWND hWnd, SM_EDIT_AC_LIST *p)\r
+{\r
+       bool b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = LvIsSingleSelected(hWnd, L_LIST);\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+       SetEnable(hWnd, B_DELETE, b);\r
+}\r
+\r
+// ダイアログ内容更新\r
+void SmHubAcDlgRefresh(HWND hWnd, SM_EDIT_AC_LIST *p)\r
+{\r
+       UINT i;\r
+       LVB *v;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       v = LvInsertStart();\r
+\r
+       for (i = 0;i < LIST_NUM(p->AcList);i++)\r
+       {\r
+               wchar_t tmp1[32], *tmp2, tmp3[MAX_SIZE], tmp4[32];\r
+               char *tmp_str;\r
+               AC *ac = LIST_DATA(p->AcList, i);\r
+\r
+               UniToStru(tmp1, ac->Id);\r
+               tmp2 = ac->Deny ? _UU("SM_AC_DENY") : _UU("SM_AC_PASS");\r
+               tmp_str = GenerateAcStr(ac);\r
+               StrToUni(tmp3, sizeof(tmp3), tmp_str);\r
+\r
+               Free(tmp_str);\r
+\r
+               UniToStru(tmp4, ac->Priority);\r
+\r
+               LvInsertAdd(v, ac->Deny ? ICO_INTERNET_X : ICO_INTERNET,\r
+                       (void *)ac->Id, 4, tmp1, tmp4, tmp2, tmp3);\r
+       }\r
+\r
+       LvInsertEnd(v, hWnd, L_LIST);\r
+       LvSortEx(hWnd, L_LIST, 0, false, true);\r
+\r
+\r
+       SmHubAcDlgUpdate(hWnd, p);\r
+}\r
+\r
+// アクセス制御リスト編集ダイアログ\r
+UINT SmHubAcDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       SM_EDIT_AC_LIST *p = (SM_EDIT_AC_LIST *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmHubAcDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               SM_EDIT_AC s;\r
+                               Zero(&s, sizeof(s));\r
+\r
+                               s.e = p;\r
+                               s.id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));\r
+\r
+                               if (Dialog(hWnd, D_SM_AC, SmHubEditAcDlgProc, &s))\r
+                               {\r
+                                       SmHubAcDlgRefresh(hWnd, p);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_ADD:\r
+                       if (IsEnable(hWnd, B_ADD))\r
+                       {\r
+                               SM_EDIT_AC s;\r
+                               Zero(&s, sizeof(s));\r
+\r
+                               s.e = p;\r
+\r
+                               if (Dialog(hWnd, D_SM_AC, SmHubEditAcDlgProc, &s))\r
+                               {\r
+                                       SmHubAcDlgRefresh(hWnd, p);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       if (IsEnable(hWnd, B_DELETE))\r
+                       {\r
+                               UINT id = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));\r
+\r
+                               if (DelAc(p->AcList, id))\r
+                               {\r
+                                       SmHubAcDlgRefresh(hWnd, p);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_SAVE:\r
+                       if (IsEnable(hWnd, B_SAVE))\r
+                       {\r
+                               RPC_AC_LIST t;\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), p->s->HubName);\r
+                               t.o = CloneAcList(p->AcList);\r
+\r
+                               if (CALL(hWnd, ScSetAcList(p->s->p->Rpc, &t)))\r
+                               {\r
+                                       EndDialog(hWnd, true);\r
+                               }\r
+\r
+                               FreeRpcAcList(&t);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_LIST:\r
+                               SmHubAcDlgUpdate(hWnd, p);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+// アクセス制御リスト編集\r
+void SmHubAc(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       SM_EDIT_AC_LIST p;\r
+       RPC_AC_LIST t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (CALL(hWnd, ScGetAcList(s->p->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       p.s = s;\r
+       p.AcList = CloneAcList(t.o);\r
+\r
+       FreeRpcAcList(&t);\r
+\r
+       Dialog(hWnd, D_SM_AC_LIST, SmHubAcDlgProc, &p);\r
+\r
+       FreeAcList(p.AcList);\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmEditCrlDlgInit(HWND hWnd, SM_EDIT_CRL *c)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (c->NewCrl == false)\r
+       {\r
+               RPC_CRL t;\r
+               CRL *crl;\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.HubName, sizeof(t.HubName), c->s->HubName);\r
+               t.Key = c->Key;\r
+\r
+               if (CALL(hWnd, ScGetCrl(c->s->Rpc, &t)) == false)\r
+               {\r
+                       EndDialog(hWnd, false);\r
+                       return;\r
+               }\r
+\r
+               crl = t.Crl;\r
+\r
+               SmEditCrlDlgSetName(hWnd, crl->Name);\r
+               SmEditCrlDlgSetSerial(hWnd, crl->Serial);\r
+               SmEditCrlDlgSetHash(hWnd, crl->DigestMD5, crl->DigestSHA1);\r
+\r
+               FreeRpcCrl(&t);\r
+       }\r
+\r
+       SmEditCrlDlgUpdate(hWnd, c);\r
+}\r
+\r
+// コントロール更新\r
+void SmEditCrlDlgUpdate(HWND hWnd, SM_EDIT_CRL *c)\r
+{\r
+       bool b = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, E_CN, IsChecked(hWnd, R_CN));\r
+       SetEnable(hWnd, E_O, IsChecked(hWnd, R_O));\r
+       SetEnable(hWnd, E_OU, IsChecked(hWnd, R_OU));\r
+       SetEnable(hWnd, E_C, IsChecked(hWnd, R_C));\r
+       SetEnable(hWnd, E_ST, IsChecked(hWnd, R_ST));\r
+       SetEnable(hWnd, E_L, IsChecked(hWnd, R_L));\r
+       SetEnable(hWnd, E_SERI, IsChecked(hWnd, R_SERI));\r
+       SetEnable(hWnd, E_MD5_HASH, IsChecked(hWnd, R_MD5_HASH));\r
+       SetEnable(hWnd, E_SHA1_HASH, IsChecked(hWnd, R_SHA1_HASH));\r
+\r
+       if (IsChecked(hWnd, R_CN))\r
+       {\r
+               if (IsEmpty(hWnd, E_CN))\r
+               {\r
+                       b = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_O))\r
+       {\r
+               if (IsEmpty(hWnd, E_O))\r
+               {\r
+                       b = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_OU))\r
+       {\r
+               if (IsEmpty(hWnd, E_OU))\r
+               {\r
+                       b = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_C))\r
+       {\r
+               if (IsEmpty(hWnd, E_C))\r
+               {\r
+                       b = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_ST))\r
+       {\r
+               if (IsEmpty(hWnd, E_ST))\r
+               {\r
+                       b = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_L))\r
+       {\r
+               if (IsEmpty(hWnd, E_L))\r
+               {\r
+                       b = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_SERI))\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               BUF *buf;\r
+\r
+               GetTxtA(hWnd, E_SERI, tmp, sizeof(tmp));\r
+               buf = StrToBin(tmp);\r
+\r
+               if (buf->Size == 0)\r
+               {\r
+                       b = false;\r
+               }\r
+\r
+               FreeBuf(buf);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_MD5_HASH))\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               BUF *buf;\r
+\r
+               GetTxtA(hWnd, E_MD5_HASH, tmp, sizeof(tmp));\r
+               buf = StrToBin(tmp);\r
+\r
+               if (buf->Size != MD5_SIZE)\r
+               {\r
+                       b = false;\r
+               }\r
+\r
+               FreeBuf(buf);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_SHA1_HASH))\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               BUF *buf;\r
+\r
+               GetTxtA(hWnd, E_SHA1_HASH, tmp, sizeof(tmp));\r
+               buf = StrToBin(tmp);\r
+\r
+               if (buf->Size != SHA1_SIZE)\r
+               {\r
+                       b = false;\r
+               }\r
+\r
+               FreeBuf(buf);\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+}\r
+\r
+// OK ボタンクリック\r
+void SmEditCrlDlgOnOk(HWND hWnd, SM_EDIT_CRL *c)\r
+{\r
+       CRL *crl;\r
+       NAME *n;\r
+       RPC_CRL t;\r
+       bool empty = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       crl = ZeroMalloc(sizeof(CRL));\r
+       crl->Name = ZeroMalloc(sizeof(NAME));\r
+       n = crl->Name;\r
+\r
+       if (IsChecked(hWnd, R_CN))\r
+       {\r
+               n->CommonName = GetText(hWnd, E_CN);\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_O))\r
+       {\r
+               n->Organization = GetText(hWnd, E_O);\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_OU))\r
+       {\r
+               n->Unit = GetText(hWnd, E_OU);\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_C))\r
+       {\r
+               n->Country = GetText(hWnd, E_C);\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_ST))\r
+       {\r
+               n->State = GetText(hWnd, E_ST);\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_L))\r
+       {\r
+               n->Local = GetText(hWnd, E_L);\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_SERI))\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               BUF *b;\r
+\r
+               GetTxtA(hWnd, E_SERI, tmp, sizeof(tmp));\r
+               b = StrToBin(tmp);\r
+\r
+               if (b != NULL && b->Size >= 1)\r
+               {\r
+                       crl->Serial = NewXSerial(b->Buf, b->Size);\r
+               }\r
+\r
+               FreeBuf(b);\r
+\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_MD5_HASH))\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               BUF *b;\r
+\r
+               GetTxtA(hWnd, E_MD5_HASH, tmp, sizeof(tmp));\r
+               b = StrToBin(tmp);\r
+\r
+               if (b != NULL && b->Size == MD5_SIZE)\r
+               {\r
+                       Copy(crl->DigestMD5, b->Buf, MD5_SIZE);\r
+               }\r
+\r
+               FreeBuf(b);\r
+\r
+               empty = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_SHA1_HASH))\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               BUF *b;\r
+\r
+               GetTxtA(hWnd, E_SHA1_HASH, tmp, sizeof(tmp));\r
+               b = StrToBin(tmp);\r
+\r
+               if (b != NULL && b->Size == SHA1_SIZE)\r
+               {\r
+                       Copy(crl->DigestSHA1, b->Buf, SHA1_SIZE);\r
+               }\r
+\r
+               FreeBuf(b);\r
+\r
+               empty = false;\r
+       }\r
+\r
+       if (empty)\r
+       {\r
+               if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CRL_EMPTY_MSG")) == IDNO)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (c->NewCrl)\r
+       {\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.HubName, sizeof(t.HubName), c->s->HubName);\r
+               t.Crl = crl;\r
+\r
+               if (CALL(hWnd, ScAddCrl(c->s->Rpc, &t)))\r
+               {\r
+                       EndDialog(hWnd, true);\r
+               }\r
+\r
+               FreeRpcCrl(&t);\r
+       }\r
+       else\r
+       {\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.HubName, sizeof(t.HubName), c->s->HubName);\r
+               t.Crl = crl;\r
+               t.Key = c->Key;\r
+\r
+               if (CALL(hWnd, ScSetCrl(c->s->Rpc, &t)))\r
+               {\r
+                       EndDialog(hWnd, true);\r
+               }\r
+\r
+               FreeRpcCrl(&t);\r
+       }\r
+}\r
+\r
+// 証明書の読み込み\r
+void SmEditCrlDlgOnLoad(HWND hWnd, SM_EDIT_CRL *c)\r
+{\r
+       X *x;\r
+       // 引数チェック\r
+       if (hWnd == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (CmLoadXFromFileOrSecureCard(hWnd, &x))\r
+       {\r
+               UCHAR md5[MD5_SIZE], sha1[SHA1_SIZE];\r
+\r
+               SmEditCrlDlgSetName(hWnd, x->subject_name);\r
+               SmEditCrlDlgSetSerial(hWnd, x->serial);\r
+               GetXDigest(x, md5, false);\r
+               GetXDigest(x, sha1, true);\r
+               SmEditCrlDlgSetHash(hWnd, md5, sha1);\r
+\r
+               FreeX(x);\r
+\r
+               SmEditCrlDlgUpdate(hWnd, c);\r
+       }\r
+}\r
+\r
+// ダイアログにハッシュ情報を設定する\r
+void SmEditCrlDlgSetHash(HWND hWnd, UCHAR *hash_md5, UCHAR *hash_sha1)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (hash_md5 != NULL && IsZero(hash_md5, MD5_SIZE) == false)\r
+       {\r
+               Check(hWnd, R_MD5_HASH, true);\r
+               BinToStrEx(tmp, sizeof(tmp), hash_md5, MD5_SIZE);\r
+               SetTextA(hWnd, E_MD5_HASH, tmp);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_MD5_HASH, false);\r
+       }\r
+\r
+       if (hash_sha1 != NULL && IsZero(hash_sha1, SHA1_SIZE) == false)\r
+       {\r
+               Check(hWnd, R_SHA1_HASH, true);\r
+               BinToStrEx(tmp, sizeof(tmp), hash_sha1, SHA1_SIZE);\r
+               SetTextA(hWnd, E_SHA1_HASH, tmp);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_SHA1_HASH, false);\r
+       }\r
+}\r
+\r
+// ダイアログにシリアル番号を設定する\r
+void SmEditCrlDlgSetSerial(HWND hWnd, X_SERIAL *serial)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || serial == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       BinToStrEx(tmp, sizeof(tmp), serial->data, serial->size);\r
+\r
+       Check(hWnd, R_SERI, true);\r
+\r
+       SetTextA(hWnd, E_SERI, tmp);\r
+}\r
+\r
+// ダイアログに名前状況を設定する\r
+void SmEditCrlDlgSetName(HWND hWnd, NAME *name)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // CN\r
+       if (UniIsEmptyStr(name->CommonName))\r
+       {\r
+               Check(hWnd, R_CN, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_CN, true);\r
+               SetText(hWnd, E_CN, name->CommonName);\r
+       }\r
+\r
+       // O\r
+       if (UniIsEmptyStr(name->Organization))\r
+       {\r
+               Check(hWnd, R_O, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_O, true);\r
+               SetText(hWnd, E_O, name->Organization);\r
+       }\r
+\r
+       // OU\r
+       if (UniIsEmptyStr(name->Unit))\r
+       {\r
+               Check(hWnd, R_OU, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_OU, true);\r
+               SetText(hWnd, E_OU, name->Unit);\r
+       }\r
+\r
+       // C\r
+       if (UniIsEmptyStr(name->Country))\r
+       {\r
+               Check(hWnd, R_C, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_C, true);\r
+               SetText(hWnd, E_C, name->Country);\r
+       }\r
+\r
+       // ST\r
+       if (UniIsEmptyStr(name->State))\r
+       {\r
+               Check(hWnd, R_ST, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_ST, true);\r
+               SetText(hWnd, E_ST, name->State);\r
+       }\r
+\r
+       // L\r
+       if (UniIsEmptyStr(name->Local))\r
+       {\r
+               Check(hWnd, R_L, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_L, true);\r
+               SetText(hWnd, E_L, name->Local);\r
+       }\r
+}\r
+\r
+// CRL 編集ダイアログプロシージャ\r
+UINT SmEditCrlDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_CRL *c = (SM_EDIT_CRL *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmEditCrlDlgInit(hWnd, c);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_CN:\r
+               case E_CN:\r
+               case R_O:\r
+               case E_O:\r
+               case R_OU:\r
+               case E_OU:\r
+               case R_C:\r
+               case E_C:\r
+               case R_ST:\r
+               case E_ST:\r
+               case R_L:\r
+               case E_L:\r
+               case R_SERI:\r
+               case E_SERI:\r
+               case R_MD5_HASH:\r
+               case E_MD5_HASH:\r
+               case R_SHA1_HASH:\r
+               case E_SHA1_HASH:\r
+                       SmEditCrlDlgUpdate(hWnd, c);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case B_LOAD:\r
+                       SmEditCrlDlgOnLoad(hWnd, c);\r
+                       break;\r
+\r
+               case IDOK:\r
+                       SmEditCrlDlgOnOk(hWnd, c);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_CN:\r
+                       FocusEx(hWnd, E_CN);\r
+                       break;\r
+\r
+               case R_O:\r
+                       FocusEx(hWnd, E_O);\r
+                       break;\r
+\r
+               case R_OU:\r
+                       FocusEx(hWnd, E_OU);\r
+                       break;\r
+\r
+               case R_C:\r
+                       FocusEx(hWnd, E_C);\r
+                       break;\r
+\r
+               case R_ST:\r
+                       FocusEx(hWnd, E_ST);\r
+                       break;\r
+\r
+               case R_L:\r
+                       FocusEx(hWnd, E_L);\r
+                       break;\r
+\r
+               case R_SERI:\r
+                       FocusEx(hWnd, E_SERI);\r
+                       break;\r
+\r
+               case R_MD5_HASH:\r
+                       FocusEx(hWnd, E_MD5_HASH);\r
+                       break;\r
+\r
+               case R_SHA1_HASH:\r
+                       FocusEx(hWnd, E_SHA1_HASH);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmCrlDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_CERT_X);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_CRL_COLUMN_1"), 555);\r
+\r
+       SmCrlDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmCrlDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));\r
+       SetEnable(hWnd, B_DELETE, LvIsSingleSelected(hWnd, L_LIST));\r
+}\r
+\r
+// 内容更新\r
+void SmCrlDlgRefresh(HWND hWnd, SM_HUB *s)\r
+{\r
+       UINT i;\r
+       RPC_ENUM_CRL t;\r
+       LVB *v;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumCrl(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       v = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_CRL_ITEM *e = &t.Items[i];\r
+               LvInsertAdd(v, ICO_CERT_X, (void *)e->Key, 1, e->CrlInfo);\r
+       }\r
+\r
+       LvInsertEndEx(v, hWnd, L_LIST, true);\r
+\r
+       if (t.NumItem >= 1)\r
+       {\r
+               LvAutoSize(hWnd, L_LIST);\r
+       }\r
+\r
+       FreeRpcEnumCrl(&t);\r
+\r
+       SmCrlDlgUpdate(hWnd, s);\r
+}\r
+\r
+// 無効な証明書一覧ダイアログプロシージャ\r
+UINT SmCrlDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_CRL c;\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       NMHDR *n;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmCrlDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_ADD:\r
+                       Zero(&c, sizeof(c));\r
+                       c.NewCrl = true;\r
+                       c.s = s;\r
+\r
+                       if (Dialog(hWnd, D_SM_EDIT_CRL, SmEditCrlDlgProc, &c))\r
+                       {\r
+                               SmCrlDlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       if (IsEnable(hWnd, B_DELETE))\r
+                       {\r
+                               if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CRL_DELETE_MSG")) == IDYES)\r
+                               {\r
+                                       RPC_CRL t;\r
+\r
+                                       Zero(&t, sizeof(t));\r
+                                       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                                       t.Key = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));\r
+\r
+                                       if (CALL(hWnd, ScDelCrl(s->Rpc, &t)))\r
+                                       {\r
+                                               SmCrlDlgRefresh(hWnd, s);\r
+                                       }\r
+\r
+                                       FreeRpcCrl(&t);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               SM_EDIT_CRL c;\r
+\r
+                               Zero(&c, sizeof(c));\r
+                               c.NewCrl = false;\r
+                               c.s = s;\r
+                               c.Key = (UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST));\r
+\r
+                               if (Dialog(hWnd, D_SM_EDIT_CRL, SmEditCrlDlgProc, &c))\r
+                               {\r
+                                       SmCrlDlgRefresh(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_LIST:\r
+                               SmCrlDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+// スマートカードマネージャ\r
+void SmSecureManager(HWND hWnd)\r
+{\r
+       UINT id = SmGetCurrentSecureIdFromReg();\r
+\r
+       if (id == 0)\r
+       {\r
+               id = SmSelectSecureId(hWnd);\r
+       }\r
+\r
+       if (id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CmSecureManager(hWnd, id);\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmSelectKeyPairDlgInit(HWND hWnd, SM_SECURE_KEYPAIR *k)\r
+{\r
+       SECURE_DEVICE *dev;\r
+       // 引数チェック\r
+       if (hWnd == NULL || k == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       dev = GetSecureDevice(k->Id);\r
+       if (dev != NULL)\r
+       {\r
+               FormatText(hWnd, S_INFO, dev->DeviceName);\r
+       }\r
+\r
+       LvInit(hWnd, L_CERT);\r
+       LvInsertColumn(hWnd, L_CERT, 0, _UU("SEC_MGR_COLUMN1"), 200);\r
+       LvInsertColumn(hWnd, L_CERT, 1, _UU("SEC_MGR_COLUMN2"), 110);\r
+\r
+       LvInit(hWnd, L_KEY);\r
+       LvInsertColumn(hWnd, L_KEY, 0, _UU("SEC_MGR_COLUMN1"), 200);\r
+       LvInsertColumn(hWnd, L_KEY, 1, _UU("SEC_MGR_COLUMN2"), 110);\r
+\r
+       SetEnable(hWnd, L_CERT, k->UseCert);\r
+       SetEnable(hWnd, B_BOLD1, k->UseCert);\r
+       SetEnable(hWnd, L_KEY, k->UseKey);\r
+       SetEnable(hWnd, B_BOLD2, k->UseKey);\r
+\r
+       SetFont(hWnd, B_BOLD1, Font(0, true));\r
+       SetFont(hWnd, B_BOLD2, Font(0, true));\r
+\r
+       SmSelectKeyPairDlgUpdate(hWnd, k);\r
+}\r
+\r
+// ダイアログコントロール更新\r
+void SmSelectKeyPairDlgUpdate(HWND hWnd, SM_SECURE_KEYPAIR *k)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || k == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (k->UseCert)\r
+       {\r
+               if (LvIsSingleSelected(hWnd, L_CERT) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+               else\r
+               {\r
+                       char *name = LvGetSelectedStrA(hWnd, L_CERT, 0);\r
+                       if (name != NULL)\r
+                       {\r
+                               if (LvIsSingleSelected(hWnd, L_KEY) == false)\r
+                               {\r
+                                       if ((k->Flag++) == 0)\r
+                                       {\r
+                                               LvSelect(hWnd, L_KEY, LvSearchStrA(hWnd, L_KEY, 0, name));\r
+                                       }\r
+                               }\r
+                               Free(name);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (k->UseKey)\r
+       {\r
+               if (LvIsSingleSelected(hWnd, L_KEY) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+               else\r
+               {\r
+                       char *name = LvGetSelectedStrA(hWnd, L_KEY, 0);\r
+                       if (name != NULL)\r
+                       {\r
+                               if (LvIsSingleSelected(hWnd, L_CERT) == false)\r
+                               {\r
+                                       if ((k->Flag++) == 0)\r
+                                       {\r
+                                               LvSelect(hWnd, L_CERT, LvSearchStrA(hWnd, L_CERT, 0, name));\r
+                                       }\r
+                               }\r
+                               Free(name);\r
+                       }\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// コンテンツ更新\r
+void SmSelectKeyPairDlgRefresh(HWND hWnd, SM_SECURE_KEYPAIR *k)\r
+{\r
+       bool ret;\r
+       LIST *o;\r
+       WINUI_SECURE_BATCH batch[] =\r
+       {\r
+               {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},\r
+       };\r
+       // 引数チェック\r
+       if (hWnd == NULL || k == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       ret = SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), k->Id, k->BitmapId);\r
+\r
+       if (ret == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       o = batch[0].EnumList;\r
+       if (o != NULL)\r
+       {\r
+               if (k->UseCert)\r
+               {\r
+                       CmSecureManagerDlgPrintListEx(hWnd, L_CERT, o, SEC_X);\r
+               }\r
+\r
+               if (k->UseKey)\r
+               {\r
+                       CmSecureManagerDlgPrintListEx(hWnd, L_KEY, o, SEC_K);\r
+               }\r
+\r
+               FreeEnumSecObject(o);\r
+       }\r
+\r
+       // コントロール更新\r
+       SmSelectKeyPairDlgUpdate(hWnd, k);\r
+}\r
+\r
+// キーペア読み込みダイアログプロシージャ\r
+UINT SmSelectKeyPairDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       SM_SECURE_KEYPAIR *k = (SM_SECURE_KEYPAIR *)param;\r
+       char *s1, *s2;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmSelectKeyPairDlgInit(hWnd, k);\r
+\r
+               SetTimer(hWnd, 1, 1, NULL);\r
+               SetTimer(hWnd, 2, 100, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       SmSelectKeyPairDlgRefresh(hWnd, k);\r
+                       break;\r
+\r
+               case 2:\r
+                       SmSelectKeyPairDlgUpdate(hWnd, k);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       s1 = LvGetSelectedStrA(hWnd, L_CERT, 0);\r
+                       s2 = LvGetSelectedStrA(hWnd, L_KEY, 0);\r
+                       if (k->UseCert)\r
+                       {\r
+                               StrCpy(k->CertName, sizeof(k->CertName), s1);\r
+                       }\r
+                       if (k->UseKey)\r
+                       {\r
+                               StrCpy(k->KeyName, sizeof(k->KeyName), s2);\r
+                       }\r
+                       Free(s1);\r
+                       Free(s2);\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_CERT:\r
+               case L_KEY:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmSelectKeyPairDlgUpdate(hWnd, k);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// キーペアをスマートカードから読み込む\r
+bool SmSelectKeyPair(HWND hWnd, char *cert_name, UINT cert_name_size, char *key_name, UINT key_name_size)\r
+{\r
+       return SmSelectKeyPairEx(hWnd, cert_name, cert_name_size, key_name, key_name_size, 0);\r
+}\r
+bool SmSelectKeyPairEx(HWND hWnd, char *cert_name, UINT cert_name_size, char *key_name, UINT key_name_size, UINT bitmap_id)\r
+{\r
+       SM_SECURE_KEYPAIR p;\r
+       // 引数チェック\r
+       if (hWnd == NULL || (cert_name == NULL && key_name == NULL))\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       p.Id = SmGetCurrentSecureId(hWnd);\r
+       if (p.Id == 0)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       p.UseCert = (cert_name == NULL) ? false : true;\r
+       p.UseKey = (key_name == NULL) ? false : true;\r
+       p.BitmapId = bitmap_id;\r
+\r
+       if (Dialog(hWnd, D_SM_SELECT_KEYPAIR, SmSelectKeyPairDlg, &p) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (p.UseCert)\r
+       {\r
+               StrCpy(cert_name, cert_name_size, p.CertName);\r
+       }\r
+       if (p.UseKey)\r
+       {\r
+               StrCpy(key_name, key_name_size, p.KeyName);\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// スマートカード番号をユーザーに選択させる\r
+UINT SmSelectSecureId(HWND hWnd)\r
+{\r
+       UINT id = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId");\r
+       UINT ret;\r
+\r
+       if (id != 0 && CheckSecureDeviceId(id) == false)\r
+       {\r
+               id = 0;\r
+       }\r
+\r
+       ret = CmSelectSecure(hWnd, id);\r
+       if (ret == 0)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       SmWriteSelectSecureIdReg(ret);\r
+\r
+       return ret;\r
+}\r
+\r
+// 現在のスマートカード番号をレジストリに書き込む\r
+void SmWriteSelectSecureIdReg(UINT id)\r
+{\r
+       MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId", id);\r
+}\r
+\r
+// 現在のスマートカード番号を取得する\r
+UINT SmGetCurrentSecureId(HWND hWnd)\r
+{\r
+       // 現在の設定をロード\r
+       UINT id = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId");\r
+\r
+       // 正常かどうかチェック\r
+       if (id == 0 || CheckSecureDeviceId(id) == false)\r
+       {\r
+               // 不正な場合はスマートカードデバイス番号を選択させる\r
+               id = SmSelectSecureId(hWnd);\r
+       }\r
+\r
+       return id;\r
+}\r
+\r
+// レジストリから現在のスマートカード番号を取得する\r
+UINT SmGetCurrentSecureIdFromReg()\r
+{\r
+       // 現在の設定をロード\r
+       UINT id = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DeviceId");\r
+\r
+       // 正常かどうかチェック\r
+       if (id == 0 || CheckSecureDeviceId(id) == false)\r
+       {\r
+               id = 0;\r
+       }\r
+\r
+       return id;\r
+}\r
+\r
+// 指定した名前の L3 スイッチが開始されているかどうか取得する\r
+bool SmL3IsSwActive(SM_SERVER *s, char *name)\r
+{\r
+       bool ret = false;\r
+       UINT i;\r
+       RPC_ENUM_L3SW t;\r
+       // 引数チェック\r
+       if (s == NULL || name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (ScEnumL3Switch(s->Rpc, &t) == ERR_NO_ERROR)\r
+       {\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_ENUM_L3SW_ITEM *e = &t.Items[i];\r
+                       if (StrCmpi(e->Name, name) == 0)\r
+                       {\r
+                               if (e->Active)\r
+                               {\r
+                                       ret = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               FreeRpcEnumL3Sw(&t);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmL3SwTableDlgInit(HWND hWnd, SM_L3SW *w)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmL3SwTableDlgUpdate(hWnd, w);\r
+}\r
+\r
+// コントロール更新\r
+void SmL3SwTableDlgUpdate(HWND hWnd, SM_L3SW *w)\r
+{\r
+       bool b = true;\r
+       UINT ip;\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IpIsFilled(hWnd, E_NETWORK) == false ||\r
+               IpIsFilled(hWnd, E_MASK) == false ||\r
+               IpIsFilled(hWnd, E_GATEWAY) == false)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       ip = IpGet(hWnd, E_GATEWAY);\r
+       if (ip == 0 || ip == 0xffffffff)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (GetInt(hWnd, E_METRIC) == 0)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (IsNetworkAddress32(IpGet(hWnd, E_NETWORK), IpGet(hWnd, E_MASK)) == false)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+}\r
+\r
+UINT SmL3SwTableDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_L3SW *w = (SM_L3SW *)param;\r
+       RPC_L3TABLE t;\r
+\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmL3SwTableDlgInit(hWnd, w);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_NETWORK:\r
+               case E_MASK:\r
+               case E_GATEWAY:\r
+               case E_METRIC:\r
+                       SmL3SwTableDlgUpdate(hWnd, w);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+                       t.NetworkAddress = IpGet(hWnd, E_NETWORK);\r
+                       t.SubnetMask = IpGet(hWnd, E_MASK);\r
+                       t.GatewayAddress = IpGet(hWnd, E_GATEWAY);\r
+                       t.Metric = GetInt(hWnd, E_METRIC);\r
+\r
+                       if (CALL(hWnd, ScAddL3Table(w->s->Rpc, &t)))\r
+                       {\r
+                               EndDialog(hWnd, 1);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmL3SwIfDlgInit(HWND hWnd, SM_L3SW *w)\r
+{\r
+       RPC_ENUM_HUB t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       if (CALL(hWnd, ScEnumHub(w->s->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       CbReset(hWnd, E_HUBNAME);\r
+       CbSetHeight(hWnd, E_HUBNAME, 18);\r
+\r
+       for (i = 0;i < t.NumHub;i++)\r
+       {\r
+               RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];\r
+\r
+               if (e->HubType != HUB_TYPE_FARM_DYNAMIC)\r
+               {\r
+                       CbAddStrA(hWnd, E_HUBNAME, e->HubName, 0);\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumHub(&t);\r
+\r
+       SetTextA(hWnd, E_HUBNAME, "");\r
+\r
+       SmL3SwIfDlgUpdate(hWnd, w);\r
+}\r
+\r
+// コントロール更新\r
+void SmL3SwIfDlgUpdate(HWND hWnd, SM_L3SW *w)\r
+{\r
+       bool b = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsEmpty(hWnd, E_HUBNAME))\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (IpGet(hWnd, E_IP) == 0 || IpGet(hWnd, E_IP) == 0xffffffff)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (IsSubnetMask32(IpGet(hWnd, E_MASK)) == false)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+}\r
+\r
+// 仮想インターフェイスの追加ダイアログ\r
+UINT SmL3SwIfDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_L3SW *w = (SM_L3SW *)param;\r
+       char *hubname;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmL3SwIfDlgInit(hWnd, w);\r
+\r
+               SetTimer(hWnd, 1, 250, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       SmL3SwIfDlgUpdate(hWnd, w);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_HUBNAME:\r
+               case E_IP:\r
+               case E_MASK:\r
+                       SmL3SwIfDlgUpdate(hWnd, w);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       hubname = GetTextA(hWnd, E_HUBNAME);\r
+                       if (hubname != NULL)\r
+                       {\r
+                               RPC_L3IF t;\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), hubname);\r
+                               t.IpAddress = IpGet(hWnd, E_IP);\r
+                               t.SubnetMask = IpGet(hWnd, E_MASK);\r
+                               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+\r
+                               if (CALL(hWnd, ScAddL3If(w->s->Rpc, &t)))\r
+                               {\r
+                                       EndDialog(hWnd, 1);\r
+                               }\r
+\r
+                               Free(hubname);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 初期化\r
+void SmL3SwDlgInit(HWND hWnd, SM_L3SW *w)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_SWITCH_OFFLINE);\r
+\r
+       FormatText(hWnd, 0, w->SwitchName);\r
+\r
+       SetFont(hWnd, S_BOLD1, Font(0, true));\r
+       SetFont(hWnd, S_BOLD2, Font(0, true));\r
+\r
+       LvInit(hWnd, L_IF);\r
+       LvInsertColumn(hWnd, L_IF, 0, _UU("SM_L3_SW_IF_COLUMN1"), 150);\r
+       LvInsertColumn(hWnd, L_IF, 1, _UU("SM_L3_SW_IF_COLUMN2"), 150);\r
+       LvInsertColumn(hWnd, L_IF, 2, _UU("SM_L3_SW_IF_COLUMN3"), 180);\r
+\r
+       LvInit(hWnd, L_TABLE);\r
+       LvInsertColumn(hWnd, L_TABLE, 0, _UU("SM_L3_SW_TABLE_COLUMN1"), 130);\r
+       LvInsertColumn(hWnd, L_TABLE, 1, _UU("SM_L3_SW_TABLE_COLUMN2"), 130);\r
+       LvInsertColumn(hWnd, L_TABLE, 2, _UU("SM_L3_SW_TABLE_COLUMN3"), 130);\r
+       LvInsertColumn(hWnd, L_TABLE, 3, _UU("SM_L3_SW_TABLE_COLUMN4"), 100);\r
+\r
+       w->Enable = SmL3IsSwActive(w->s, w->SwitchName) ? false : true;\r
+\r
+       SmL3SwDlgRefresh(hWnd, w);\r
+}\r
+\r
+// コントロール更新\r
+void SmL3SwDlgUpdate(HWND hWnd, SM_L3SW *w)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, B_ADD_IF, w->s->ServerAdminMode && w->Enable);\r
+       SetEnable(hWnd, B_ADD_TABLE, w->s->ServerAdminMode && w->Enable);\r
+       SetEnable(hWnd, B_DEL_IF, LvIsSingleSelected(hWnd, L_IF) && w->s->ServerAdminMode && w->Enable);\r
+       SetEnable(hWnd, B_DEL_TABLE, LvIsSingleSelected(hWnd, L_TABLE) && w->s->ServerAdminMode && w->Enable);\r
+       SetEnable(hWnd, B_START, w->s->ServerAdminMode && w->Enable);\r
+       SetEnable(hWnd, B_STOP, w->s->ServerAdminMode && (w->Enable == false));\r
+}\r
+\r
+// 内容更新\r
+void SmL3SwDlgRefresh(HWND hWnd, SM_L3SW *w)\r
+{\r
+       UINT i;\r
+       wchar_t tmp1[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       wchar_t tmp3[MAX_SIZE];\r
+       wchar_t tmp4[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || w == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 仮想インターフェイス一覧\r
+       {\r
+               RPC_ENUM_L3IF t;\r
+               LVB *v;\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+\r
+               if (CALL(hWnd, ScEnumL3If(w->s->Rpc, &t)) == false)\r
+               {\r
+                       Close(hWnd);\r
+                       return;\r
+               }\r
+\r
+               v = LvInsertStart();\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_L3IF *e = &t.Items[i];\r
+\r
+                       IPToUniStr32(tmp1, sizeof(tmp1), e->IpAddress);\r
+                       IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);\r
+                       StrToUni(tmp3, sizeof(tmp3), e->HubName);\r
+\r
+                       LvInsertAdd(v, ICO_NIC_ONLINE, NULL, 3, tmp1, tmp2, tmp3);\r
+               }\r
+\r
+               LvReset(hWnd, L_IF);\r
+\r
+               LvInsertEnd(v, hWnd, L_IF);\r
+\r
+               FreeRpcEnumL3If(&t);\r
+       }\r
+\r
+       // ルーティングテーブル一覧\r
+       {\r
+               RPC_ENUM_L3TABLE t;\r
+               LVB *v;\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+\r
+               if (CALL(hWnd, ScEnumL3Table(w->s->Rpc, &t)) == false)\r
+               {\r
+                       Close(hWnd);\r
+                       return;\r
+               }\r
+\r
+               v = LvInsertStart();\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_L3TABLE *e = &t.Items[i];\r
+\r
+                       IPToUniStr32(tmp1, sizeof(tmp1), e->NetworkAddress);\r
+                       IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);\r
+                       IPToUniStr32(tmp3, sizeof(tmp3), e->GatewayAddress);\r
+                       UniToStru(tmp4, e->Metric);\r
+\r
+                       LvInsertAdd(v, ICO_PROTOCOL, NULL, 4, tmp1, tmp2, tmp3, tmp4);\r
+               }\r
+\r
+               LvReset(hWnd, L_TABLE);\r
+\r
+               LvInsertEnd(v, hWnd, L_TABLE);\r
+\r
+               FreeRpcEnumL3Table(&t);\r
+       }\r
+\r
+       SmL3SwDlgUpdate(hWnd, w);\r
+}\r
+\r
+// L3 スイッチの編集ダイアログ\r
+UINT SmL3SwDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_L3SW *w = (SM_L3SW *)param;\r
+       NMHDR *n;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmL3SwDlgInit(hWnd, w);\r
+\r
+               SetTimer(hWnd, 1, 1000, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       w->Enable = SmL3IsSwActive(w->s, w->SwitchName) ? false : true;\r
+                       SmL3SwDlgUpdate(hWnd, w);\r
+                       SetTimer(hWnd, 1, 1000, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_START:\r
+                       if (IsEnable(hWnd, B_START))\r
+                       {\r
+                               RPC_L3SW t;\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+\r
+                               if (CALL(hWnd, ScStartL3Switch(w->s->Rpc, &t)))\r
+                               {\r
+                                       SmL3SwDlgUpdate(hWnd, w);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_STOP:\r
+                       if (IsEnable(hWnd, B_STOP))\r
+                       {\r
+                               RPC_L3SW t;\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+\r
+                               if (CALL(hWnd, ScStopL3Switch(w->s->Rpc, &t)))\r
+                               {\r
+                                       SmL3SwDlgUpdate(hWnd, w);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_ADD_IF:\r
+                       if (Dialog(hWnd, D_SM_L3_SW_IF, SmL3SwIfDlg, w))\r
+                       {\r
+                               SmL3SwDlgRefresh(hWnd, w);\r
+                       }\r
+                       break;\r
+\r
+               case B_DEL_IF:\r
+                       if (LvIsSingleSelected(hWnd, L_IF))\r
+                       {\r
+                               RPC_L3IF t;\r
+                               char *tmp1, *tmp2, *tmp3;\r
+\r
+                               tmp1 = LvGetSelectedStrA(hWnd, L_IF, 0);\r
+                               tmp2 = LvGetSelectedStrA(hWnd, L_IF, 1);\r
+                               tmp3 = LvGetSelectedStrA(hWnd, L_IF, 2);\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+                               t.IpAddress = StrToIP32(tmp1);\r
+                               t.SubnetMask = StrToIP32(tmp2);\r
+                               StrCpy(t.HubName, sizeof(t.HubName), tmp3);\r
+\r
+                               if (CALL(hWnd, ScDelL3If(w->s->Rpc, &t)))\r
+                               {\r
+                                       SmL3SwDlgRefresh(hWnd, w);\r
+                               }\r
+\r
+                               Free(tmp1);\r
+                               Free(tmp2);\r
+                               Free(tmp3);\r
+                       }\r
+                       break;\r
+\r
+               case B_ADD_TABLE:\r
+                       if (Dialog(hWnd, D_SM_L3_SW_TABLE, SmL3SwTableDlg, w))\r
+                       {\r
+                               SmL3SwDlgRefresh(hWnd, w);\r
+                       }\r
+                       break;\r
+\r
+               case B_DEL_TABLE:\r
+                       if (LvIsSingleSelected(hWnd, L_TABLE))\r
+                       {\r
+                               RPC_L3TABLE t;\r
+                               char *tmp1, *tmp2, *tmp3, *tmp4;\r
+\r
+                               tmp1 = LvGetSelectedStrA(hWnd, L_TABLE, 0);\r
+                               tmp2 = LvGetSelectedStrA(hWnd, L_TABLE, 1);\r
+                               tmp3 = LvGetSelectedStrA(hWnd, L_TABLE, 2);\r
+                               tmp4 = LvGetSelectedStrA(hWnd, L_TABLE, 3);\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.Name, sizeof(t.Name), w->SwitchName);\r
+                               t.NetworkAddress = StrToIP32(tmp1);\r
+                               t.SubnetMask = StrToIP32(tmp2);\r
+                               t.GatewayAddress = StrToIP32(tmp3);\r
+                               t.Metric = ToInt(tmp4);\r
+\r
+                               if (CALL(hWnd, ScDelL3Table(w->s->Rpc, &t)))\r
+                               {\r
+                                       SmL3SwDlgRefresh(hWnd, w);\r
+                               }\r
+\r
+                               Free(tmp1);\r
+                               Free(tmp2);\r
+                               Free(tmp3);\r
+                               Free(tmp4);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_IF:\r
+               case L_TABLE:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmL3SwDlgUpdate(hWnd, w);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// コントロール更新\r
+void SmL3AddDlgUpdate(HWND hWnd, SM_SERVER *s)\r
+{\r
+       char *tmp;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       tmp = GetTextA(hWnd, E_NAME);\r
+\r
+       SetEnable(hWnd, IDOK, IsEmptyStr(tmp) == false && IsSafeStr(tmp));\r
+\r
+       Free(tmp);\r
+}\r
+\r
+// 新しい L3 スイッチの作成ダイアログ\r
+UINT SmL3AddDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *s = (SM_SERVER *)param;\r
+       RPC_L3SW t;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               LimitText(hWnd, E_NAME, MAX_HUBNAME_LEN);\r
+               SmL3AddDlgUpdate(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_NAME:\r
+                       SmL3AddDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       Zero(&t, sizeof(t));\r
+                       GetTxtA(hWnd, E_NAME, t.Name, sizeof(t.Name));\r
+                       if (CALL(hWnd, ScAddL3Switch(s->Rpc, &t)))\r
+                       {\r
+                               EndDialog(hWnd, 1);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmL3DlgInit(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetFont(hWnd, S_BOLD, Font(0, true));\r
+\r
+       SetIcon(hWnd, 0, ICO_SWITCH);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_L3_SW_COLUMN1"), 150);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_L3_SW_COLUMN2"), 120);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_L3_SW_COLUMN3"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_L3_SW_COLUMN4"), 100);\r
+\r
+       SmL3DlgRefresh(hWnd, s);\r
+}\r
+\r
+// ダイアログコントロール更新\r
+void SmL3DlgUpdate(HWND hWnd, SM_SERVER *s)\r
+{\r
+       bool b = false;\r
+       bool active = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSingleSelected(hWnd, L_LIST))\r
+       {\r
+               wchar_t *tmp;\r
+               UINT i;\r
+               b = true;\r
+               i = LvGetSelected(hWnd, L_LIST);\r
+               if (i != INFINITE)\r
+               {\r
+                       tmp = LvGetStr(hWnd, L_LIST, i, 1);\r
+                       if (UniStrCmpi(tmp, _UU("SM_L3_SW_ST_F_F")) != 0)\r
+                       {\r
+                               active = true;\r
+                       }\r
+                       Free(tmp);\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, B_START, b && (active == false));\r
+       SetEnable(hWnd, B_STOP, b && (active != false));\r
+       SetEnable(hWnd, IDOK, b);\r
+       SetEnable(hWnd, B_DELETE, b);\r
+}\r
+\r
+// ダイアログ内容更新\r
+void SmL3DlgRefresh(HWND hWnd, SM_SERVER *s)\r
+{\r
+       RPC_ENUM_L3SW t;\r
+       UINT i;\r
+       LVB *v;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumL3Switch(s->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       v = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_L3SW_ITEM *e = &t.Items[i];\r
+               wchar_t tmp1[MAX_SIZE], *tmp2, tmp3[64], tmp4[64];\r
+\r
+               StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+               if (e->Active == false)\r
+               {\r
+                       tmp2 = _UU("SM_L3_SW_ST_F_F");\r
+               }\r
+               else if (e->Online == false)\r
+               {\r
+                       tmp2 = _UU("SM_L3_SW_ST_T_F");\r
+               }\r
+               else\r
+               {\r
+                       tmp2 = _UU("SM_L3_SW_ST_T_T");\r
+               }\r
+               UniToStru(tmp3, e->NumInterfaces);\r
+               UniToStru(tmp4, e->NumTables);\r
+\r
+               LvInsertAdd(v, e->Active ? ICO_SWITCH : ICO_SWITCH_OFFLINE, NULL,\r
+                       4, tmp1, tmp2, tmp3, tmp4);\r
+       }\r
+\r
+       LvInsertEnd(v, hWnd, L_LIST);\r
+\r
+       FreeRpcEnumL3Sw(&t);\r
+\r
+       SmL3DlgUpdate(hWnd, s);\r
+}\r
+\r
+// L3 ダイアログプロシージャ\r
+UINT SmL3Dlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       SM_SERVER *s = (SM_SERVER *)param;\r
+       RPC_L3SW t;\r
+       char *name;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmL3DlgInit(hWnd, s);\r
+\r
+               SetTimer(hWnd, 1, 1000, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               KillTimer(hWnd, 1);\r
+               SmL3DlgRefresh(hWnd, s);\r
+               SetTimer(hWnd, 1, 1000, NULL);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_ADD:\r
+                       // 追加\r
+                       if (Dialog(hWnd, D_SM_L3_ADD, SmL3AddDlg, s))\r
+                       {\r
+                               SmL3DlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_START:\r
+                       // 動作開始\r
+                       name = LvGetSelectedStrA(hWnd, L_LIST, 0);\r
+                       if (name != NULL)\r
+                       {\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.Name, sizeof(t.Name), name);\r
+\r
+                               if (CALL(hWnd, ScStartL3Switch(s->Rpc, &t)))\r
+                               {\r
+                                       SmL3DlgRefresh(hWnd, s);\r
+                               }\r
+\r
+                               Free(name);\r
+                       }\r
+                       break;\r
+\r
+               case B_STOP:\r
+                       // 動作停止\r
+                       name = LvGetSelectedStrA(hWnd, L_LIST, 0);\r
+                       if (name != NULL)\r
+                       {\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.Name, sizeof(t.Name), name);\r
+\r
+                               if (CALL(hWnd, ScStopL3Switch(s->Rpc, &t)))\r
+                               {\r
+                                       SmL3DlgRefresh(hWnd, s);\r
+                               }\r
+\r
+                               Free(name);\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // 編集\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               name = LvGetSelectedStrA(hWnd, L_LIST, 0);\r
+                               if (name != NULL)\r
+                               {\r
+                                       SM_L3SW w;\r
+                                       Zero(&w, sizeof(w));\r
+                                       w.s = s;\r
+                                       w.SwitchName = name;\r
+\r
+                                       Dialog(hWnd, D_SM_L3_SW, SmL3SwDlg, &w);\r
+\r
+                                       Free(name);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       name = LvGetSelectedStrA(hWnd, L_LIST, 0);\r
+                       if (name != NULL)\r
+                       {\r
+                               if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,\r
+                                       _UU("SM_L3_SW_DEL_MSG"), name) == IDYES)\r
+                               {\r
+                                       Zero(&t, sizeof(t));\r
+                                       StrCpy(t.Name, sizeof(t.Name), name);\r
+\r
+                                       if (CALL(hWnd, ScDelL3Switch(s->Rpc, &t)))\r
+                                       {\r
+                                               SmL3DlgRefresh(hWnd, s);\r
+                                       }\r
+                               }\r
+\r
+                               Free(name);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // 閉じる\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmL3DlgUpdate(hWnd, s);\r
+                               break;\r
+\r
+                       case NM_DBLCLK:\r
+                               Command(hWnd, IDOK);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// L3 ダイアログ\r
+void SmL3(HWND hWnd, SM_SERVER *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_L3, SmL3Dlg, s);\r
+}\r
+\r
+// 管理オプション値用ダイアログ\r
+UINT SmHubAdminOptionValueDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_AO *a = (SM_EDIT_AO *)param;\r
+       UINT i;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CbReset(hWnd, C_NAME);\r
+               for (i = 0;i < a->DefaultOptions.NumItem;i++)\r
+               {\r
+                       wchar_t tmp[MAX_PATH];\r
+                       StrToUni(tmp, sizeof(tmp), a->DefaultOptions.Items[i].Name);\r
+                       CbAddStr(hWnd, C_NAME, tmp, 0);\r
+               }\r
+               if (a->NewMode == false)\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+\r
+                       SetTextA(hWnd, C_NAME, a->Name);\r
+                       ToStr(tmp, a->Value);\r
+\r
+                       SetTextA(hWnd, E_VALUE, tmp);\r
+               }\r
+               else\r
+               {\r
+                       SetTextA(hWnd, C_NAME, "");\r
+               }\r
+               SmHubAdminOptionValueDlgUpdate(hWnd, a);\r
+               if (a->NewMode == false)\r
+               {\r
+                       FocusEx(hWnd, E_VALUE);\r
+                       Disable(hWnd, C_NAME);\r
+               }\r
+               else\r
+               {\r
+                       FocusEx(hWnd, C_NAME);\r
+               }\r
+\r
+               SetTimer(hWnd, 1, 100, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               SmHubAdminOptionValueDlgUpdate(hWnd, a);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (a->NewMode)\r
+                       {\r
+                               GetTxtA(hWnd, C_NAME, a->Name, sizeof(a->Name));\r
+                       }\r
+\r
+                       GetTxtA(hWnd, E_VALUE, tmp, sizeof(tmp));\r
+                       a->Value = ToInt(tmp);\r
+\r
+                       Trim(a->Name);\r
+\r
+                       if (StartWith(a->Name, "no") || StartWith(a->Name, "allow") || StartWith(a->Name, "deny")\r
+                                || StartWith(a->Name, "filter") || StartWith(a->Name, "fix") || StartWith(a->Name, "force")\r
+                                || StartWith(a->Name, "use") || StartWith(a->Name, "b_") || StartWith(a->Name, "is")\r
+                                || StartWith(a->Name, "manage") || StartWith(a->Name, "yield")\r
+                                || StartWith(a->Name, "permit") || StartWith(a->Name, "yes") || StartWith(a->Name, "ok")\r
+                                || StartWith(a->Name, "do") || StartWith(a->Name, "only") || StartWith(a->Name, "disable"))\r
+                       {\r
+                               if (StrCmpi(tmp, "0") != 0 && StrCmpi(tmp, "1") != 0)\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_TRUE_OR_FALSE"));\r
+                                       FocusEx(hWnd, E_VALUE);\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+\r
+               SmHubAdminOptionValueDlgUpdate(hWnd, a);\r
+\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 管理オプション値用ダイアログ コントロール更新\r
+void SmHubAdminOptionValueDlgUpdate(HWND hWnd, SM_EDIT_AO *a)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxtA(hWnd, C_NAME, tmp, sizeof(tmp));\r
+\r
+       SetEnable(hWnd, IDOK, IsEmpty(hWnd, C_NAME) == false && IsEmpty(hWnd, E_VALUE) == false &&\r
+               IsSafeStr(tmp));\r
+}\r
+\r
+// 初期化\r
+void SmHubAdminOptionDlgInit(HWND hWnd, SM_EDIT_AO *a)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_USER_ADMIN);\r
+\r
+       if (a->e->p->ServerAdminMode)\r
+       {\r
+               a->CanChange = true;\r
+       }\r
+       else\r
+       {\r
+               if (a->ExtOption == false)\r
+               {\r
+                       for (i = 0;i < a->CurrentOptions.NumItem;i++)\r
+                       {\r
+                               if (StrCmpi(a->CurrentOptions.Items[i].Name, "allow_hub_admin_change_option") == 0)\r
+                               {\r
+                                       if (a->CurrentOptions.Items[i].Value != 0)\r
+                                       {\r
+                                               a->CanChange = true;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       a->CanChange = true;\r
+               }\r
+       }\r
+\r
+       FormatText(hWnd, S_INFO, a->e->HubName);\r
+\r
+       DlgFont(hWnd, S_BOLD, 0, true);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_AO_COLUMN_1"), 260);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_AO_COLUMN_2"), 100);\r
+\r
+       for (i = 0;i < a->CurrentOptions.NumItem;i++)\r
+       {\r
+               ADMIN_OPTION *e = &a->CurrentOptions.Items[i];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+\r
+               StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+               UniToStru(tmp2, e->Value);\r
+\r
+               LvInsert(hWnd, L_LIST, ICO_LOG, NULL, 2, tmp1, tmp2);\r
+                       \r
+       }\r
+\r
+       if (a->ExtOption)\r
+       {\r
+               SetIcon(hWnd, S_ICON, ICO_LINK2);\r
+               SetIcon(hWnd, 0, ICO_LINK2);\r
+\r
+               SetText(hWnd, 0, _UU("SM_HUBEXT_OPTION_TITLE"));\r
+               SetText(hWnd, S_STATIC1, _UU("SM_HUBEXT_OPTION_STATIC1"));\r
+               SetText(hWnd, S_STATIC2, _UU("SM_HUBEXT_OPTION_STATIC2"));\r
+       }\r
+\r
+       // コントロール更新\r
+       SmHubAdminOptionDlgUpdate(hWnd, a);\r
+}\r
+\r
+// コントロール更新\r
+void SmHubAdminOptionDlgUpdate(HWND hWnd, SM_EDIT_AO *a)\r
+{\r
+       bool b = false;\r
+       wchar_t *helpstr;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       helpstr = _UU("HUB_AO_CLICK");\r
+\r
+       SetEnable(hWnd, IDOK, a->CanChange);\r
+       SetEnable(hWnd, B_ADD, a->CanChange);\r
+       SetEnable(hWnd, B_EDIT, a->CanChange && (LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false));\r
+\r
+       if (LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false)\r
+       {\r
+               UINT i;\r
+               i = LvGetSelected(hWnd, L_LIST);\r
+\r
+               if (a->CanChange)\r
+               {\r
+\r
+                       b = true;\r
+\r
+                       if (i != INFINITE)\r
+                       {\r
+                               char *name = LvGetStrA(hWnd, L_LIST, i, 0);\r
+                               if (name != NULL)\r
+                               {\r
+                                       UINT j;\r
+\r
+                                       for (j = 0;j < a->DefaultOptions.NumItem;j++)\r
+                                       {\r
+                                               if (StrCmpi(a->DefaultOptions.Items[j].Name, name) == 0)\r
+                                               {\r
+                                                       b = false;\r
+                                               }\r
+                                       }\r
+                                       Free(name);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (i != INFINITE)\r
+               {\r
+                       char *name = LvGetStrA(hWnd, L_LIST, i, 0);\r
+                       if (name != NULL)\r
+                       {\r
+                               helpstr = GetHubAdminOptionHelpString(name);\r
+                       }\r
+                       Free(name);\r
+               }\r
+       }\r
+       SetEnable(hWnd, B_DELETE, b);\r
+\r
+       SetText(hWnd, E_HELP, helpstr);\r
+}\r
+\r
+// 保存\r
+void SmHubAdminOptionDlgOk(HWND hWnd, SM_EDIT_AO *a)\r
+{\r
+       UINT i, num;\r
+       RPC_ADMIN_OPTION t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       num = LvNum(hWnd, L_LIST);\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), a->e->HubName);\r
+       t.NumItem = num;\r
+       t.Items = ZeroMalloc(sizeof(ADMIN_OPTION) * num);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               char *name = LvGetStrA(hWnd, L_LIST, i, 0);\r
+               char *s_value = LvGetStrA(hWnd, L_LIST, i, 1);\r
+               ADMIN_OPTION *a = &t.Items[i];\r
+\r
+               StrCpy(a->Name, sizeof(a->Name), name);\r
+               a->Value = ToInt(s_value);\r
+\r
+               Free(name);\r
+               Free(s_value);\r
+       }\r
+\r
+       if (a->ExtOption == false)\r
+       {\r
+               if (CALL(hWnd, ScSetHubAdminOptions(a->e->p->Rpc, &t)))\r
+               {\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_AO_SET_OK"));\r
+                       EndDialog(hWnd, true);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (CALL(hWnd, ScSetHubExtOptions(a->e->p->Rpc, &t)))\r
+               {\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_EXT_OPTION_SET_OK"));\r
+                       EndDialog(hWnd, true);\r
+               }\r
+       }\r
+\r
+       FreeRpcAdminOption(&t);\r
+}\r
+\r
+// 仮想 HUB 管理オプションダイアログ\r
+UINT SmHubAdminOptionDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_AO *a = (SM_EDIT_AO *)param;\r
+       NMHDR *n;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmHubAdminOptionDlgInit(hWnd, a);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_ADD:\r
+                       a->NewMode = true;\r
+                       StrCpy(a->Name, sizeof(a->Name), "");\r
+                       a->Value = 0;\r
+                       if (Dialog(hWnd, D_SM_AO_VALUE, SmHubAdminOptionValueDlg,\r
+                               a))\r
+                       {\r
+                               wchar_t tmp1[MAX_SIZE];\r
+                               wchar_t tmp2[MAX_SIZE];\r
+                               StrToUni(tmp1, sizeof(tmp1), a->Name);\r
+                               UniToStru(tmp2, a->Value);\r
+\r
+                               LvInsert(hWnd, L_LIST, ICO_LOG, NULL, 2, tmp1, tmp2);\r
+                       }\r
+                       break;\r
+\r
+               case B_EDIT:\r
+                       i = LvGetSelected(hWnd, L_LIST);\r
+                       if (i != INFINITE && a->CanChange)\r
+                       {\r
+                               char *name, *value;\r
+                               name = LvGetStrA(hWnd, L_LIST, i, 0);\r
+                               value = LvGetStrA(hWnd, L_LIST, i, 1);\r
+                               a->NewMode = false;\r
+                               StrCpy(a->Name, sizeof(a->Name), name);\r
+                               a->Value = ToInt(value);\r
+\r
+                               if (Dialog(hWnd, D_SM_AO_VALUE, SmHubAdminOptionValueDlg,\r
+                                       a))\r
+                               {\r
+                                       char tmp[MAX_PATH];\r
+                                       ToStr(tmp, a->Value);\r
+                                       LvSetItemA(hWnd, L_LIST, i, 1, tmp);\r
+                               }\r
+\r
+                               Free(name);\r
+                               Free(value);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       i = LvGetSelected(hWnd, L_LIST);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               LvDeleteItem(hWnd, L_LIST, i);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case IDOK:\r
+                       SmHubAdminOptionDlgOk(hWnd, a);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmHubAdminOptionDlgUpdate(hWnd, a);\r
+                               break;\r
+\r
+                       case NM_DBLCLK:\r
+                               Command(hWnd, B_EDIT);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB 拡張オプション\r
+void SmHubExtOption(HWND hWnd, SM_EDIT_HUB *e)\r
+{\r
+       SM_EDIT_AO a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || e == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       a.e = e;\r
+       a.ExtOption = true;\r
+\r
+       StrCpy(a.CurrentOptions.HubName, sizeof(a.CurrentOptions.HubName), e->HubName);\r
+\r
+       // 現在のサーバー上のオプションを取得する\r
+       if (CALL(hWnd, ScGetHubExtOptions(e->p->Rpc, &a.CurrentOptions)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_ADMIN_OPTION, SmHubAdminOptionDlg, &a);\r
+\r
+       FreeRpcAdminOption(&a.CurrentOptions);\r
+       FreeRpcAdminOption(&a.DefaultOptions);\r
+}\r
+\r
+// 仮想 HUB 管理オプション\r
+void SmHubAdminOption(HWND hWnd, SM_EDIT_HUB *e)\r
+{\r
+       SM_EDIT_AO a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || e == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       a.e = e;\r
+\r
+       StrCpy(a.CurrentOptions.HubName, sizeof(a.CurrentOptions.HubName), e->HubName);\r
+\r
+       // 現在のサーバー上のオプションを取得する\r
+       if (CALL(hWnd, ScGetHubAdminOptions(e->p->Rpc, &a.CurrentOptions)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       ScGetDefaultHubAdminOptions(e->p->Rpc, &a.DefaultOptions);\r
+\r
+       Dialog(hWnd, D_SM_ADMIN_OPTION, SmHubAdminOptionDlg, &a);\r
+\r
+       FreeRpcAdminOption(&a.CurrentOptions);\r
+       FreeRpcAdminOption(&a.DefaultOptions);\r
+}\r
+\r
+// 初期化\r
+void SmConfigDlgInit(HWND hWnd, SM_CONFIG *c)\r
+{\r
+       wchar_t *tmp;\r
+       UINT tmp_size;\r
+       // 引数チェック\r
+       if (hWnd == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Focus(hWnd, IDCANCEL);\r
+\r
+       SetIcon(hWnd, 0, ICO_MACHINE);\r
+\r
+       SetFont(hWnd, E_CONFIG, GetFont(_SS("DEFAULT_FONT_2"), 0, false, false,\r
+               false, false));\r
+\r
+       FormatText(hWnd, IDC_INFO, c->s->ServerName);\r
+\r
+       // UTF-8 から Unicode に変換\r
+       tmp_size = CalcUtf8ToUni(c->Config.FileData, StrLen(c->Config.FileData)) + 1;\r
+       tmp = ZeroMalloc(tmp_size);\r
+       Utf8ToUni(tmp, tmp_size, c->Config.FileData, StrLen(c->Config.FileData));\r
+\r
+       SetText(hWnd, E_CONFIG, tmp);\r
+\r
+       Free(tmp);\r
+}\r
+\r
+// config 編集ダイアログ\r
+UINT SmConfigDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_CONFIG *c = (SM_CONFIG *)param;\r
+       char *filename;\r
+       wchar_t *filename_unicode;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmConfigDlgInit(hWnd, c);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_EXPORT:\r
+                       StrToUni(tmp, sizeof(tmp), c->Config.FileName);\r
+                       filename_unicode = SaveDlg(hWnd, _UU("DLG_CONFIG_FILES"), _UU("DLG_SAVE_CONFIG"), tmp, L".config");\r
+                       if (filename_unicode != NULL)\r
+                       {\r
+                               BUF *b = NewBuf();\r
+                               filename = CopyUniToStr(filename_unicode);\r
+                               WriteBuf(b, c->Config.FileData, StrLen(c->Config.FileData));\r
+                               if (DumpBuf(b, filename))\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_CONFIG_SAVED"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONSTOP, _UU("SM_CONFIG_SAVE_FAILED"));\r
+                               }\r
+                               FreeBuf(b);\r
+                               Free(filename);\r
+                               Free(filename_unicode);\r
+                       }\r
+                       break;\r
+\r
+               case B_IMPORT:\r
+                       filename_unicode = OpenDlg(hWnd, _UU("DLG_CONFIG_FILES"), _UU("DLG_OPEN_CONFIG"));\r
+                       if (filename_unicode != NULL)\r
+                       {\r
+                               BUF *b;\r
+                               filename = CopyUniToStr(filename_unicode);\r
+                               b = ReadDump(filename);\r
+                               if (b != NULL)\r
+                               {\r
+                                       RPC_CONFIG t;\r
+\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_CONFIG_CONFIRM")) == IDYES)\r
+                                       {\r
+                                               Zero(&t, sizeof(t));\r
+                                               t.FileData = ZeroMalloc(b->Size + 1);\r
+                                               Copy(t.FileData, b->Buf, b->Size);\r
+\r
+                                               if (CALL(hWnd, ScSetConfig(c->s->Rpc, &t)))\r
+                                               {\r
+                                                       // 成功\r
+                                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_CONFIG_WRITE_OK"));\r
+                                                       _exit(0);\r
+                                               }\r
+\r
+                                               FreeRpcConfig(&t);\r
+\r
+                                               FreeRpcConfig(&t);\r
+                                               FreeBuf(b);\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONSTOP, _UU("SM_CONFIG_OPEN_FAILED"));\r
+                               }\r
+                               Free(filename);\r
+                               Free(filename_unicode);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// config 編集ダイアログを表示する\r
+void SmConfig(HWND hWnd, SM_SERVER *s)\r
+{\r
+       SM_CONFIG c;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&c, sizeof(c));\r
+\r
+       c.s = s;\r
+\r
+       // 現在の config をサーバーから取得\r
+       if (CALL(hWnd, ScGetConfig(s->Rpc, &c.Config)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // ダイアログ表示\r
+       Dialog(hWnd, D_SM_CONFIG, SmConfigDlg, &c);\r
+\r
+       // 解放\r
+       FreeRpcConfig(&c.Config);\r
+}\r
+\r
+// ブリッジダイアログ初期化\r
+void SmBridgeDlgInit(HWND hWnd, SM_SERVER *s)\r
+{\r
+       UINT i;\r
+       RPC_ENUM_ETH t;\r
+       RPC_SERVER_INFO si;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_BRIDGE_COLUMN_1"), 50);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_BRIDGE_COLUMN_2"), 145);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_BRIDGE_COLUMN_3"), 300);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_BRIDGE_COLUMN_4"), 100);\r
+\r
+       SmBridgeDlgRefresh(hWnd, s);\r
+\r
+       SetShow(hWnd, B_VLAN, GetCapsBool(s->CapsList, "b_support_eth_vlan"));\r
+\r
+       SetIcon(hWnd, 0, ICO_BRIDGE);\r
+\r
+       // サーバー情報を取得\r
+       Zero(&si, sizeof(si));\r
+       ScGetServerInfo(s->Rpc, &si);\r
+       if (GetCapsBool(s->CapsList, "b_tap_supported") == false)\r
+       {\r
+               // tap はサポートしていない\r
+               Hide(hWnd, R_TAP);\r
+               Hide(hWnd, S_TAP_1);\r
+               Hide(hWnd, E_TAPNAME);\r
+               Hide(hWnd, S_TAP_2);\r
+               Hide(hWnd, R_BRIDGE);\r
+               Hide(hWnd, S_STATIC5);\r
+       }\r
+       Check(hWnd, R_BRIDGE, true);\r
+       FreeRpcServerInfo(&si);\r
+\r
+       // Ethernet 列挙\r
+       Zero(&t, sizeof(t));\r
+       ScEnumEthernet(s->Rpc, &t);\r
+\r
+       CbReset(hWnd, E_NICNAME);\r
+       CbSetHeight(hWnd, E_NICNAME, 18);\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_ITEM *e = &t.Items[i];\r
+               if(UniIsEmptyStr(e->NetworkConnectionName) == false)\r
+               {\r
+                       wchar_t ncname[MAX_SIZE * 2];\r
+                       UniFormat(ncname, sizeof(ncname), BRIDGE_NETWORK_CONNECTION_STR, e->NetworkConnectionName, e->DeviceName);\r
+                       CbAddStr(hWnd, E_NICNAME, ncname, 0);\r
+               }\r
+               else\r
+               {\r
+                       wchar_t *s = CopyStrToUni(e->DeviceName);\r
+                       CbAddStr(hWnd, E_NICNAME, s, 0);\r
+                       Free(s);\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumEth(&t);\r
+\r
+       // 仮想 HUB 列挙\r
+       {\r
+               RPC_ENUM_HUB t;\r
+               Zero(&t, sizeof(t));\r
+\r
+               ScEnumHub(s->Rpc, &t);\r
+\r
+               CbReset(hWnd, E_HUBNAME);\r
+               CbSetHeight(hWnd, E_HUBNAME, 18);\r
+\r
+               for (i = 0;i < t.NumHub;i++)\r
+               {\r
+                       RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];\r
+                       wchar_t *s = CopyStrToUni(e->HubName);\r
+\r
+                       if (e->HubType != HUB_TYPE_FARM_DYNAMIC)\r
+                       {\r
+                               CbAddStr(hWnd, E_HUBNAME, s, 0);\r
+                       }\r
+                       Free(s);\r
+               }\r
+\r
+               SetText(hWnd, E_HUBNAME, L"");\r
+\r
+               FreeRpcEnumHub(&t);\r
+       }\r
+\r
+       if (s->Bridge)\r
+       {\r
+               SetTextA(hWnd, E_HUBNAME, "BRIDGE");\r
+       }\r
+\r
+       Focus(hWnd, E_HUBNAME);\r
+       \r
+       SmBridgeDlgUpdate(hWnd, s);\r
+\r
+       SetTimer(hWnd, 1, 1000, NULL);\r
+}\r
+\r
+// ブリッジダイアログコントロール更新\r
+void SmBridgeDlgUpdate(HWND hWnd, SM_SERVER *s)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsMasked(hWnd, L_LIST) && LvIsMultiMasked(hWnd, L_LIST) == false)\r
+       {\r
+               Enable(hWnd, B_DELETE);\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, B_DELETE);\r
+       }\r
+\r
+       if (IsEmpty(hWnd, E_HUBNAME))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_TAP) == false)\r
+       {\r
+               // ブリッジモード\r
+               Enable(hWnd, S_ETH_1);\r
+               Enable(hWnd, E_NICNAME);\r
+               Disable(hWnd, S_TAP_1);\r
+               Disable(hWnd, S_TAP_2);\r
+               Disable(hWnd, E_TAPNAME);\r
+               SetText(hWnd, S_INFO, _UU("SM_BRIDGE_INFO_1"));\r
+               SetIcon(hWnd, S_ICON, ICO_NIC_ONLINE);\r
+               if (IsEmpty(hWnd, E_NICNAME))\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               // tap モード\r
+               Disable(hWnd, S_ETH_1);\r
+               Disable(hWnd, E_NICNAME);\r
+               Enable(hWnd, S_TAP_1);\r
+               Enable(hWnd, S_TAP_2);\r
+               Enable(hWnd, E_TAPNAME);\r
+               SetText(hWnd, S_INFO, _UU("SM_BRIDGE_INFO_2"));\r
+               SetIcon(hWnd, S_ICON, ICO_PROTOCOL);\r
+               GetTxtA(hWnd, E_TAPNAME, tmp, sizeof(tmp));\r
+               if (IsEmptyStr(tmp))\r
+               {\r
+                       ok = false;\r
+               }\r
+               else\r
+               {\r
+                       if (IsSafeStr(tmp) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+                       if (StrLen(tmp) >= 12)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// ブリッジダイアログ更新\r
+void SmBridgeDlgRefresh(HWND hWnd, SM_SERVER *s)\r
+{\r
+       LVB *lvb;\r
+       RPC_ENUM_LOCALBRIDGE t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       lvb = LvInsertStart();\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       ScEnumLocalBridge(s->Rpc, &t);\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_LOCALBRIDGE *e = &t.Items[i];\r
+               wchar_t name[MAX_SIZE];\r
+               wchar_t nic[MAX_SIZE];\r
+               wchar_t hub[MAX_SIZE];\r
+               wchar_t *status = _UU("SM_BRIDGE_OFFLINE");\r
+\r
+               UniToStru(name, i + 1);\r
+               StrToUni(nic, sizeof(nic), e->DeviceName);\r
+               StrToUni(hub, sizeof(hub), e->HubName);\r
+\r
+               if (e->Online)\r
+               {\r
+                       status = e->Active ? _UU("SM_BRIDGE_ONLINE") : _UU("SM_BRIDGE_ERROR");\r
+               }\r
+\r
+               LvInsertAdd(lvb, e->TapMode == false ? (e->Active ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE) : ICO_PROTOCOL,\r
+                       NULL, 4, name, hub, nic, status);\r
+       }\r
+\r
+       FreeRpcEnumLocalBridge(&t);\r
+\r
+       LvInsertEnd(lvb, hWnd, L_LIST);\r
+\r
+       SmBridgeDlgUpdate(hWnd, s);\r
+}\r
+\r
+// ローカルブリッジの追加\r
+void SmBridgeDlgOnOk(HWND hWnd, SM_SERVER *s)\r
+{\r
+       char nic[MAX_SIZE];\r
+       char hub[MAX_SIZE];\r
+       RPC_LOCALBRIDGE t;\r
+       bool tapmode = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxtA(hWnd, E_HUBNAME, hub, sizeof(hub));\r
+\r
+       Zero(nic, sizeof(nic));\r
+\r
+       if (IsChecked(hWnd, R_TAP) == false)\r
+       {\r
+               wchar_t nctmp[MAX_SIZE * 2];\r
+               if(GetCapsBool(s->CapsList, "b_support_network_connection_name") && GetTxt(hWnd, E_NICNAME, nctmp, sizeof(nctmp)))\r
+               {\r
+                       RPC_ENUM_ETH et;\r
+                       UINT i;\r
+                       Zero(&et, sizeof(et));\r
+                       ScEnumEthernet(s->Rpc, &et);\r
+                       for(i = 0; i < et.NumItem; i++)\r
+                       {\r
+                               RPC_ENUM_ETH_ITEM *e = &et.Items[i];\r
+                               if(UniIsEmptyStr(e->NetworkConnectionName) == false)\r
+                               {\r
+                                       wchar_t ncname[MAX_SIZE * 2];\r
+                                       UniFormat(ncname, sizeof(ncname), BRIDGE_NETWORK_CONNECTION_STR, e->NetworkConnectionName, e->DeviceName);\r
+                                       if(UniStrCmp(ncname, nctmp) == 0)\r
+                                       {\r
+                                               StrCpy(nic, sizeof(nic), e->DeviceName);\r
+                                               break;\r
+                                       }\r
+                               }               \r
+                       }\r
+                       FreeRpcEnumEth(&et);\r
+\r
+                       if (IsEmptyStr(nic))\r
+                       {\r
+                               GetTxtA(hWnd, E_NICNAME, nic, sizeof(nic));\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       GetTxtA(hWnd, E_NICNAME, nic, sizeof(nic));\r
+               }\r
+       }\r
+       else\r
+       {\r
+               tapmode = true;\r
+               GetTxtA(hWnd, E_TAPNAME, nic, sizeof(nic));\r
+       }\r
+\r
+       Trim(hub);\r
+       Trim(nic);\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), nic);\r
+       StrCpy(t.HubName, sizeof(t.HubName), hub);\r
+       t.TapMode = tapmode;\r
+\r
+       if (InStrEx(t.DeviceName, "vpn", false) || InStrEx(t.DeviceName, "tun", false)\r
+               || InStrEx(t.DeviceName, "tap", false))\r
+       {\r
+               // VPN デバイスにローカルブリッジしようとしている\r
+               if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,\r
+                       _UU("SM_BRIDGE_VPN"),\r
+                       t.DeviceName) == IDNO)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       // Intel 製 LAN カードなどに関する警告\r
+       if (tapmode == false)\r
+       {\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_INTEL"));\r
+       }\r
+\r
+       if (CALL(hWnd, ScAddLocalBridge(s->Rpc, &t)) == false)\r
+       {\r
+               Focus(hWnd, E_HUBNAME);\r
+               return;\r
+       }\r
+\r
+       SetText(hWnd, E_HUBNAME, L"");\r
+       Focus(hWnd, E_HUBNAME);\r
+\r
+       if (tapmode)\r
+       {\r
+               SetTextA(hWnd, E_TAPNAME, "");\r
+       }\r
+\r
+       SmBridgeDlgRefresh(hWnd, s);\r
+\r
+       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_OK"));\r
+}\r
+\r
+// ブリッジダイアログプロシージャ\r
+UINT SmBridgeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       SM_SERVER *s = (SM_SERVER *)param;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmBridgeDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_HUBNAME:\r
+               case E_NICNAME:\r
+               case R_BRIDGE:\r
+               case R_TAP:\r
+               case E_TAPNAME:\r
+                       SmBridgeDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case R_BRIDGE:\r
+                       Focus(hWnd, E_NICNAME);\r
+                       break;\r
+\r
+               case R_TAP:\r
+                       FocusEx(hWnd, E_TAPNAME);\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // 追加\r
+                       SmBridgeDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // 閉じる\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_VLAN:\r
+                       // VLAN ユーティリティ\r
+                       SmVLan(hWnd, s);\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       i = LvGetSelected(hWnd, L_LIST);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               wchar_t *nic, *hub;\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               RPC_LOCALBRIDGE t;\r
+\r
+                               hub = LvGetStr(hWnd, L_LIST, i, 1);\r
+                               nic = LvGetStr(hWnd, L_LIST, i, 2);\r
+\r
+                               UniFormat(tmp, sizeof(tmp), _UU("SM_BRIDGE_DELETE"),\r
+                                       hub, nic);\r
+\r
+                               if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, tmp) == IDYES)\r
+                               {\r
+                                       Zero(&t, sizeof(t));\r
+                                       UniToStr(t.DeviceName, sizeof(t.DeviceName), nic);\r
+                                       UniToStr(t.HubName, sizeof(t.HubName), hub);\r
+\r
+                                       if (CALL(hWnd, ScDeleteLocalBridge(s->Rpc, &t)))\r
+                                       {\r
+                                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_DELETE_OK"));\r
+                                               SmBridgeDlgRefresh(hWnd, s);\r
+                                       }\r
+                               }\r
+\r
+                               Free(hub);\r
+                               Free(nic);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       SmBridgeDlgRefresh(hWnd, s);\r
+                       SetTimer(hWnd, 1, 1000, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_LIST:\r
+                               SmBridgeDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// WinPcap のインストール作業\r
+void SmInstallWinPcap(HWND hWnd, SM_SERVER *s)\r
+{\r
+       wchar_t temp_name[MAX_SIZE];\r
+       IO *io;\r
+       BUF *buf;\r
+\r
+       // インストールを開始するかどうか質問する\r
+       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_BRIDGE_WPCAP_INSTALL")) == IDNO)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 一時ファイル名を生成\r
+       UniFormat(temp_name, sizeof(temp_name), L"%s\\winpcap_installer.exe", MsGetTempDirW());\r
+\r
+       // hamcore から読み込む\r
+       buf = ReadDump(MsIsNt() ? "|winpcap_installer.exe" : "|winpcap_installer_win9x.exe");\r
+       if (buf == NULL)\r
+       {\r
+RES_ERROR:\r
+               MsgBox(hWnd, MB_ICONSTOP, _UU("SM_BRIDGE_RESOURCE"));\r
+               return;\r
+       }\r
+\r
+       // 一時ファイルに書き出す\r
+       io = FileCreateW(temp_name);\r
+       if (io == NULL)\r
+       {\r
+               FreeBuf(buf);\r
+               goto RES_ERROR;\r
+       }\r
+\r
+       FileWrite(io, buf->Buf, buf->Size);\r
+       FileClose(io);\r
+\r
+       FreeBuf(buf);\r
+\r
+       // 実行する\r
+       if (RunW(temp_name, NULL, false, true) == false)\r
+       {\r
+               // 失敗\r
+               FileDeleteW(temp_name);\r
+               goto RES_ERROR;\r
+       }\r
+\r
+       FileDeleteW(temp_name);\r
+\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 終了後のメッセージ\r
+       if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) == false)\r
+       {\r
+               // コンピュータの再起動が必要\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_WPCAP_REBOOT1"));\r
+       }\r
+       else\r
+       {\r
+               // サービスの再起動が必要\r
+               if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_BRIDGE_WPCAP_REBOOT2")) == IDNO)\r
+               {\r
+                       // 再起動しない\r
+               }\r
+               else\r
+               {\r
+                       // 再起動する\r
+                       RPC_TEST t;\r
+                       Zero(&t, sizeof(t));\r
+                       ScRebootServer(s->Rpc, &t);\r
+\r
+                       SleepThread(500);\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       CALL(hWnd, ScTest(s->Rpc, &t));\r
+               }\r
+       }\r
+}\r
+\r
+// ブリッジダイアログ\r
+void SmBridgeDlg(HWND hWnd, SM_SERVER *s)\r
+{\r
+       RPC_BRIDGE_SUPPORT t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // まずサーバー側のブリッジ対応状況を調べる\r
+       Zero(&t, sizeof(t));\r
+       if (CALLEX(hWnd, ScGetBridgeSupport(s->Rpc, &t)) != ERR_NO_ERROR)\r
+       {\r
+               // 古いバージョンなので未対応\r
+               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_BRIDGE_TOO_OLD_VER"));\r
+               return;\r
+       }\r
+\r
+       if (t.IsBridgeSupportedOs == false)\r
+       {\r
+               // OS がブリッジに対応していない\r
+               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SM_BRIDGE_UNSUPPORTED"));\r
+               return;\r
+       }\r
+\r
+       if (t.IsWinPcapNeeded)\r
+       {\r
+               if (s->Rpc->Sock->RemoteIP.addr[0] != 127)\r
+               {\r
+                       // WinPcap が必要だがリモート管理モードなので何も出来ない\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_WPCAP_REMOTE"));\r
+                       return;\r
+               }\r
+               else\r
+               {\r
+                       // WinPcap が必要でローカル管理モードである\r
+                       if (MsIsAdmin())\r
+                       {\r
+                               // Administrators である\r
+                               SmInstallWinPcap(hWnd, s);\r
+                               return;\r
+                       }\r
+                       else\r
+                       {\r
+                               // Administrators でない\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_BRIDGE_WPCAP_ROOT"));\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_BRIDGE, SmBridgeDlgProc, s);\r
+}\r
+\r
+// SecureNAT 画面更新\r
+void SmSNATDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       bool b;\r
+       RPC_HUB_STATUS t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       if (CALL(hWnd, ScGetHubStatus(s->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       b = t.SecureNATEnabled;\r
+\r
+       if (b)\r
+       {\r
+               Disable(hWnd, B_ENABLE);\r
+               Enable(hWnd, B_DISABLE);\r
+               Enable(hWnd, B_NAT);\r
+               Enable(hWnd, B_DHCP);\r
+               Enable(hWnd, B_STATUS);\r
+       }\r
+       else\r
+       {\r
+               Enable(hWnd, B_ENABLE);\r
+               Disable(hWnd, B_DISABLE);\r
+               Disable(hWnd, B_NAT);\r
+               Disable(hWnd, B_DHCP);\r
+               Disable(hWnd, B_STATUS);\r
+       }\r
+}\r
+\r
+// SecureNAT 設定画面\r
+UINT SmSNATDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       RPC_HUB t;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SetIcon(hWnd, 0, ICO_ROUTER);\r
+               DlgFont(hWnd, S_WARNING, (_GETLANG() == 0 || _GETLANG() == 2) ? 13 : 10, true);\r
+               FormatText(hWnd, S_TITLE, s->HubName);\r
+               SmSNATDlgUpdate(hWnd, s);\r
+\r
+               SetTimer(hWnd, 1, 1000, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               if (wParam == 1)\r
+               {\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       SmSNATDlgUpdate(hWnd, s);\r
+\r
+                       SetTimer(hWnd, 1, 1000, NULL);\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_ENABLE:\r
+                       if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_OKCANCEL | MB_DEFBUTTON2,\r
+                               _UU("SM_SECURE_NAT_MSG")) == IDOK)\r
+                       {\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                               CALL(hWnd, ScEnableSecureNAT(s->Rpc, &t));\r
+                               SmSNATDlgUpdate(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DISABLE:\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                       CALL(hWnd, ScDisableSecureNAT(s->Rpc, &t));\r
+                       SmSNATDlgUpdate(hWnd, s);\r
+                       break;\r
+\r
+               case B_CONFIG:\r
+                       NmEditVhOption(hWnd, s);\r
+                       break;\r
+\r
+               case B_NAT:\r
+                       NmNat(hWnd, s);\r
+                       break;\r
+\r
+               case B_DHCP:\r
+                       NmDhcp(hWnd, s);\r
+                       break;\r
+\r
+               case B_STATUS:\r
+                       SmStatusDlg(hWnd, s->p, s, false, true, _UU("SM_SNAT_STATUS"), ICO_ROUTER,\r
+                               NULL, NmStatus);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 初期化\r
+void SmCreateCertDlgInit(HWND hWnd, SM_CERT *s)\r
+{\r
+       UINT cert_sign;\r
+       UINT cert_days;\r
+       char *reg_o, *reg_ou, *reg_c, *reg_st, *reg_l;\r
+       UINT bits[] = {1024, 1536, 2048, 3072, 4096 };\r
+       UINT i;\r
+       UINT last_bit;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetTextA(hWnd, E_CN, s->default_cn);\r
+\r
+       last_bit = MsRegReadInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Bits");\r
+       if (last_bit == 0)\r
+       {\r
+               last_bit = 1024;\r
+       }\r
+\r
+       CbReset(hWnd, C_BITS);\r
+       for (i = 0;i < sizeof(bits) / sizeof(bits[0]);i++)\r
+       {\r
+               char tmp[MAX_PATH];\r
+               UINT index;\r
+\r
+               ToStr(tmp, bits[i]);\r
+\r
+               index = CbAddStrA(hWnd, C_BITS, tmp, bits[i]);\r
+       }\r
+\r
+       CbSelect(hWnd, C_BITS, 1024);\r
+       CbSelect(hWnd, C_BITS, last_bit);\r
+\r
+       reg_o = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "O");\r
+       reg_ou = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "OU");\r
+       reg_c = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "C");\r
+       reg_st = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "ST");\r
+       reg_l = MsRegReadStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "L");\r
+       SetTextA(hWnd, E_O, reg_o);\r
+       SetTextA(hWnd, E_OU, reg_ou);\r
+       SetTextA(hWnd, E_C, reg_c);\r
+       SetTextA(hWnd, E_ST, reg_st);\r
+       SetTextA(hWnd, E_L, reg_l);\r
+       Free(reg_o);\r
+       Free(reg_ou);\r
+       Free(reg_c);\r
+       Free(reg_st);\r
+       Free(reg_l);\r
+\r
+       LimitText(hWnd, E_C, 2);\r
+\r
+       cert_sign = MsRegReadInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Sign");\r
+       cert_days = MsRegReadInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Days");\r
+\r
+       Check(hWnd, R_ROOT_CERT, cert_sign ? false : true);\r
+       Check(hWnd, R_SIGNED_CERT, cert_sign ? true : false);\r
+\r
+       if (cert_days == 0)\r
+       {\r
+               cert_days = 3650;\r
+       }\r
+\r
+       SetIntEx(hWnd, E_EXPIRE, cert_days);\r
+\r
+       SmCreateCertDlgUpdate(hWnd, s);\r
+\r
+       FocusEx(hWnd, E_CN);\r
+}\r
+\r
+// 更新\r
+void SmCreateCertDlgUpdate(HWND hWnd, SM_CERT *s)\r
+{\r
+       bool ok = true;\r
+       bool b;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsEmpty(hWnd, E_CN) && IsEmpty(hWnd, E_O) && IsEmpty(hWnd, E_OU) &&\r
+               IsEmpty(hWnd, E_ST) && IsEmpty(hWnd, E_L))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       i = GetInt(hWnd, E_EXPIRE);\r
+       if (i == 0 || i >= (365 * 30))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       b = IsChecked(hWnd, R_SIGNED_CERT);\r
+\r
+       SetEnable(hWnd, S_LOAD_1, b);\r
+       SetEnable(hWnd, B_LOAD, b);\r
+       SetEnable(hWnd, S_LOAD_2, b);\r
+\r
+       if (b && (s->root_k == NULL || s->root_x == NULL))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK ボタン\r
+void SmCreateCertDlgOnOk(HWND hWnd, SM_CERT *s)\r
+{\r
+       wchar_t cn[MAX_SIZE], o[MAX_SIZE], ou[MAX_SIZE], c[MAX_SIZE], st[MAX_SIZE], l[MAX_SIZE];\r
+       char *reg_o, *reg_ou, *reg_c, *reg_st, *reg_l;\r
+       UINT days;\r
+       bool sign;\r
+       char serial[MAX_SIZE * 2];\r
+       X *x;\r
+       K *pub;\r
+       K *pri;\r
+       NAME *n;\r
+       X_SERIAL *x_serial;\r
+       BUF *buf;\r
+       UINT bits;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxt(hWnd, E_CN, cn, sizeof(cn));\r
+       GetTxt(hWnd, E_O, o, sizeof(o));\r
+       GetTxt(hWnd, E_OU, ou, sizeof(ou));\r
+       GetTxt(hWnd, E_C, c, sizeof(c));\r
+       GetTxt(hWnd, E_ST, st, sizeof(st));\r
+       GetTxt(hWnd, E_L, l, sizeof(l));\r
+       GetTxtA(hWnd, E_SERIAL, serial, sizeof(serial));\r
+\r
+       bits = CbGetSelect(hWnd, C_BITS);\r
+       if (bits == INFINITE)\r
+       {\r
+               bits = 1024;\r
+       }\r
+\r
+       buf = StrToBin(serial);\r
+       if (buf == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (buf->Size > 1)\r
+       {\r
+               x_serial = NewXSerial(buf->Buf, buf->Size);\r
+       }\r
+       else\r
+       {\r
+               x_serial = NULL;\r
+       }\r
+\r
+       FreeBuf(buf);\r
+\r
+       n = NewName(UniStrLen(cn) ? cn : NULL,\r
+               UniStrLen(o) ? o : NULL,\r
+               UniStrLen(ou) ? ou : NULL,\r
+               UniStrLen(c) ? c : NULL,\r
+               UniStrLen(st) ? st : NULL,\r
+               UniStrLen(l) ? l : NULL);\r
+\r
+       days = GetInt(hWnd, E_EXPIRE);\r
+\r
+       sign = IsChecked(hWnd, R_SIGNED_CERT);\r
+\r
+       MsRegWriteInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Sign", sign);\r
+       MsRegWriteInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Days", days);\r
+       MsRegWriteInt(REG_CURRENT_USER, SM_CERT_REG_KEY, "Bits", bits);\r
+\r
+       RsaGen(&pri, &pub, bits);\r
+\r
+       if (sign == false)\r
+       {\r
+               x = NewRootX(pub, pri, n, days, x_serial);\r
+       }\r
+       else\r
+       {\r
+               x = NewX(pub, s->root_k, s->root_x, n, days, x_serial);\r
+       }\r
+\r
+       FreeName(n);\r
+\r
+       FreeXSerial(x_serial);\r
+\r
+       if (x == NULL)\r
+       {\r
+               FreeX(x);\r
+               FreeK(pub);\r
+               FreeK(pri);\r
+               return;\r
+       }\r
+\r
+       if (s->do_not_save == false)\r
+       {\r
+               if (SmSaveKeyPairDlg(hWnd, x, pri) == false)\r
+               {\r
+                       FreeX(x);\r
+                       FreeK(pub);\r
+                       FreeK(pri);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       s->x = x;\r
+       s->k = pri;\r
+       FreeK(pub);\r
+\r
+       reg_o = GetTextA(hWnd, E_O);\r
+       reg_ou = GetTextA(hWnd, E_OU);\r
+       reg_c = GetTextA(hWnd, E_C);\r
+       reg_st = GetTextA(hWnd, E_ST);\r
+       reg_l = GetTextA(hWnd, E_L);\r
+       MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "O", reg_o);\r
+       MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "OU", reg_ou);\r
+       MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "C", reg_c);\r
+       MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "ST", reg_st);\r
+       MsRegWriteStr(REG_CURRENT_USER, SM_CERT_REG_KEY, "L", reg_l);\r
+       Free(reg_o);\r
+       Free(reg_ou);\r
+       Free(reg_c);\r
+       Free(reg_st);\r
+       Free(reg_l);\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// 証明書作成画面\r
+UINT SmCreateCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_CERT *s = (SM_CERT *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmCreateCertDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_ROOT_CERT:\r
+               case R_SIGNED_CERT:\r
+               case B_LOAD:\r
+               case E_CN:\r
+               case E_O:\r
+               case E_OU:\r
+               case E_C:\r
+               case E_ST:\r
+               case E_L:\r
+               case E_EXPIRE:\r
+                       SmCreateCertDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmCreateCertDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case R_ROOT_CERT:\r
+                       if (IsChecked(hWnd, R_ROOT_CERT))\r
+                       {\r
+                               FocusEx(hWnd, E_CN);\r
+                       }\r
+                       break;\r
+\r
+               case B_LOAD:\r
+                       // 証明書読み込み\r
+                       if (1)\r
+                       {\r
+                               X *x;\r
+                               K *k;\r
+                               if (CmLoadXAndK(hWnd, &x, &k))\r
+                               {\r
+                                       wchar_t tmp[MAX_SIZE];\r
+                                       FreeX(s->root_x);\r
+                                       FreeK(s->root_k);\r
+                                       s->root_x = x;\r
+                                       s->root_k = k;\r
+\r
+                                       SmGetCertInfoStr(tmp, sizeof(tmp), x);\r
+                                       SetText(hWnd, S_LOAD_2, tmp);\r
+                                       SmCreateCertDlgUpdate(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 証明書ツール\r
+bool SmCreateCert(HWND hWnd, X **x, K **k, bool do_not_save, char *default_cn)\r
+{\r
+       bool ret;\r
+       SM_CERT s;\r
+       Zero(&s, sizeof(s));\r
+\r
+       if (default_cn == NULL)\r
+       {\r
+               default_cn = "";\r
+       }\r
+\r
+       s.default_cn = default_cn;\r
+\r
+       s.do_not_save = do_not_save;\r
+\r
+       ret = Dialog(hWnd, D_SM_CREATE_CERT, SmCreateCertDlgProc, &s);\r
+\r
+       if (ret)\r
+       {\r
+               if (x != NULL)\r
+               {\r
+                       *x = CloneX(s.x);\r
+               }\r
+\r
+               if (k != NULL)\r
+               {\r
+                       *k = CloneK(s.k);\r
+               }\r
+       }\r
+\r
+       FreeX(s.x);\r
+       FreeK(s.k);\r
+       FreeX(s.root_x);\r
+       FreeK(s.root_k);\r
+\r
+       return ret;\r
+}\r
+\r
+// 初期化\r
+void SmIpTableDlgInit(HWND hWnd, SM_TABLE *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_PROTOCOL);\r
+       FormatText(hWnd, S_TITLE, s->Hub->HubName);\r
+\r
+       if (s->SessionName != NULL)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               GetTxt(hWnd, S_TITLE, tmp, sizeof(tmp));\r
+               UniFormat(tmp2, sizeof(tmp2), _UU("SM_SESSION_FILTER"), s->SessionName);\r
+               UniStrCat(tmp, sizeof(tmp), tmp2);\r
+               SetText(hWnd, S_TITLE, tmp);\r
+       }\r
+\r
+       LvInit(hWnd, L_TABLE);\r
+       LvInsertColumn(hWnd, L_TABLE, 0, _UU("SM_IP_COLUMN_1"), 190);\r
+       LvInsertColumn(hWnd, L_TABLE, 1, _UU("SM_IP_COLUMN_2"), 140);\r
+       LvInsertColumn(hWnd, L_TABLE, 2, _UU("SM_IP_COLUMN_3"), 133);\r
+       LvInsertColumn(hWnd, L_TABLE, 3, _UU("SM_IP_COLUMN_4"), 133);\r
+       LvInsertColumn(hWnd, L_TABLE, 4, _UU("SM_IP_COLUMN_5"), 133);\r
+       LvSetStyle(hWnd, L_TABLE, LVS_EX_GRIDLINES);\r
+\r
+       SmIpTableDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmIpTableDlgUpdate(HWND hWnd, SM_TABLE *s)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_TABLE) == false || LvIsMultiMasked(hWnd, L_TABLE))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, B_DELETE, ok);\r
+}\r
+\r
+// 内容更新\r
+void SmIpTableDlgRefresh(HWND hWnd, SM_TABLE *s)\r
+{\r
+       UINT i;\r
+       RPC_ENUM_IP_TABLE t;\r
+       UINT old_selected = 0;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumIpTable(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       i = LvGetSelected(hWnd, L_TABLE);\r
+       if (i != INFINITE)\r
+       {\r
+               old_selected = (UINT)LvGetParam(hWnd, L_TABLE, i);\r
+       }\r
+\r
+       LvReset(hWnd, L_TABLE);\r
+\r
+       for (i = 0;i < t.NumIpTable;i++)\r
+       {\r
+               char str[MAX_SIZE];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp4[MAX_SIZE];\r
+               wchar_t tmp5[MAX_SIZE];\r
+               RPC_ENUM_IP_TABLE_ITEM *e = &t.IpTables[i];\r
+\r
+               if (s->SessionName == NULL || StrCmpi(e->SessionName, s->SessionName) == 0)\r
+               {\r
+                       StrToUni(tmp1, sizeof(tmp1), e->SessionName);\r
+\r
+                       if (e->DhcpAllocated == false)\r
+                       {\r
+                               IPToStr(str, sizeof(str), &e->IpV6);\r
+                               StrToUni(tmp2, sizeof(tmp2), str);\r
+                       }\r
+                       else\r
+                       {\r
+                               IPToStr(str, sizeof(str), &e->IpV6);\r
+                               UniFormat(tmp2, sizeof(tmp2), _UU("SM_MAC_IP_DHCP"), str);\r
+                       }\r
+\r
+                       GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));\r
+\r
+                       GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));\r
+\r
+                       if (StrLen(e->RemoteHostname) == 0)\r
+                       {\r
+                               UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);\r
+                       }\r
+\r
+                       LvInsert(hWnd, L_TABLE, e->DhcpAllocated ? ICO_PROTOCOL_DHCP : ICO_PROTOCOL, (void *)e->Key, 5,\r
+                               tmp1, tmp2, tmp3, tmp4, tmp5);\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumIpTable(&t);\r
+\r
+       if (old_selected != 0)\r
+       {\r
+               LvSelect(hWnd, L_TABLE, LvSearchParam(hWnd, L_TABLE, (void *)old_selected));\r
+       }\r
+\r
+       SmIpTableDlgUpdate(hWnd, s);\r
+}\r
+\r
+// IP アドレステーブルダイアログプロシージャ\r
+UINT SmIpTableDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_TABLE *s = (SM_TABLE *)param;\r
+       NMHDR *n;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmIpTableDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_DELETE:\r
+                       // 削除\r
+                       i = LvGetSelected(hWnd, L_TABLE);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               RPC_DELETE_TABLE t;\r
+                               UINT key = (UINT)LvGetParam(hWnd, L_TABLE, i);\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+                               t.Key = key;\r
+                               if (CALL(hWnd, ScDeleteIpTable(s->Rpc, &t)))\r
+                               {\r
+                                       LvDeleteItem(hWnd, L_TABLE, i);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmIpTableDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_TABLE:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmIpTableDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アドレステーブルダイアログ\r
+void SmIpTableDlg(HWND hWnd, SM_HUB *s, char *session_name)\r
+{\r
+       SM_TABLE t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Hub = s;\r
+       t.Rpc = s->Rpc;\r
+       t.SessionName = session_name;\r
+\r
+       Dialog(hWnd, D_SM_IP, SmIpTableDlgProc, &t);\r
+}\r
+\r
+\r
+// 初期化\r
+void SmMacTableDlgInit(HWND hWnd, SM_TABLE *s)\r
+{\r
+       UINT i = 0;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_NIC_ONLINE);\r
+       FormatText(hWnd, S_TITLE, s->Hub->HubName);\r
+\r
+       if (s->SessionName != NULL)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               GetTxt(hWnd, S_TITLE, tmp, sizeof(tmp));\r
+               UniFormat(tmp2, sizeof(tmp2), _UU("SM_SESSION_FILTER"), s->SessionName);\r
+               UniStrCat(tmp, sizeof(tmp), tmp2);\r
+               SetText(hWnd, S_TITLE, tmp);\r
+       }\r
+\r
+       LvInit(hWnd, L_TABLE);\r
+       LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_1"), 190);\r
+       if (GetCapsBool(s->Hub->p->CapsList, "b_support_vlan"))\r
+       {\r
+               LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_1A"), 65);\r
+       }\r
+       LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_2"), 140);\r
+       LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_3"), 133);\r
+       LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_4"), 133);\r
+       LvInsertColumn(hWnd, L_TABLE, i++, _UU("SM_MAC_COLUMN_5"), 133);\r
+       LvSetStyle(hWnd, L_TABLE, LVS_EX_GRIDLINES);\r
+\r
+       SmMacTableDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmMacTableDlgUpdate(HWND hWnd, SM_TABLE *s)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_TABLE) == false || LvIsMultiMasked(hWnd, L_TABLE))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, B_DELETE, ok);\r
+}\r
+\r
+// 内容更新\r
+void SmMacTableDlgRefresh(HWND hWnd, SM_TABLE *s)\r
+{\r
+       UINT i;\r
+       RPC_ENUM_MAC_TABLE t;\r
+       UINT old_selected = 0;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumMacTable(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       i = LvGetSelected(hWnd, L_TABLE);\r
+       if (i != INFINITE)\r
+       {\r
+               old_selected = (UINT)LvGetParam(hWnd, L_TABLE, i);\r
+       }\r
+\r
+       LvReset(hWnd, L_TABLE);\r
+\r
+       for (i = 0;i < t.NumMacTable;i++)\r
+       {\r
+               char str[MAX_SIZE];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp4[MAX_SIZE];\r
+               wchar_t tmp5[MAX_SIZE];\r
+               wchar_t tmp6[MAX_SIZE];\r
+               RPC_ENUM_MAC_TABLE_ITEM *e = &t.MacTables[i];\r
+\r
+               if (s->SessionName == NULL || StrCmpi(e->SessionName, s->SessionName) == 0)\r
+               {\r
+                       StrToUni(tmp1, sizeof(tmp1), e->SessionName);\r
+\r
+                       MacToStr(str, sizeof(str), e->MacAddress);\r
+                       StrToUni(tmp2, sizeof(tmp2), str);\r
+\r
+                       GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));\r
+\r
+                       GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));\r
+\r
+                       if (StrLen(e->RemoteHostname) == 0)\r
+                       {\r
+                               UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);\r
+                       }\r
+\r
+                       UniToStru(tmp6, e->VlanId);\r
+                       if (e->VlanId == 0)\r
+                       {\r
+                               UniStrCpy(tmp6, sizeof(tmp6), _UU("CM_ST_NONE"));\r
+                       }\r
+\r
+                       if (GetCapsBool(s->Hub->p->CapsList, "b_support_vlan"))\r
+                       {\r
+                               LvInsert(hWnd, L_TABLE, ICO_NIC_ONLINE, (void *)e->Key, 6,\r
+                                       tmp1, tmp6, tmp2, tmp3, tmp4, tmp5);\r
+                       }\r
+                       else\r
+                       {\r
+                               LvInsert(hWnd, L_TABLE, ICO_NIC_ONLINE, (void *)e->Key, 5,\r
+                                       tmp1, tmp2, tmp3, tmp4, tmp5);\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeRpcEnumMacTable(&t);\r
+\r
+       if (old_selected != 0)\r
+       {\r
+               LvSelect(hWnd, L_TABLE, LvSearchParam(hWnd, L_TABLE, (void *)old_selected));\r
+       }\r
+\r
+       SmMacTableDlgUpdate(hWnd, s);\r
+}\r
+\r
+// MAC アドレステーブルダイアログプロシージャ\r
+UINT SmMacTableDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_TABLE *s = (SM_TABLE *)param;\r
+       NMHDR *n;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmMacTableDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_DELETE:\r
+                       // 削除\r
+                       i = LvGetSelected(hWnd, L_TABLE);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               RPC_DELETE_TABLE t;\r
+                               UINT key = (UINT)LvGetParam(hWnd, L_TABLE, i);\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+                               t.Key = key;\r
+                               if (CALL(hWnd, ScDeleteMacTable(s->Rpc, &t)))\r
+                               {\r
+                                       LvDeleteItem(hWnd, L_TABLE, i);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmMacTableDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_TABLE:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmMacTableDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);\r
+\r
+       return 0;\r
+}\r
+\r
+// MAC アドレステーブルダイアログ\r
+void SmMacTableDlg(HWND hWnd, SM_HUB *s, char *session_name)\r
+{\r
+       SM_TABLE t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Hub = s;\r
+       t.Rpc = s->Rpc;\r
+       t.SessionName = session_name;\r
+\r
+       Dialog(hWnd, D_SM_MAC, SmMacTableDlgProc, &t);\r
+}\r
+\r
+// 初期化\r
+void SmSessionDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_VPN);\r
+       FormatText(hWnd, 0, s->HubName);\r
+       FormatText(hWnd, S_TITLE, s->HubName);\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_SESS_COLUMN_1"), 176);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_SESS_COLUMN_8"), 58);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_SESS_COLUMN_2"), 62);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_SESS_COLUMN_3"), 78);\r
+       LvInsertColumn(hWnd, L_LIST, 4, _UU("SM_SESS_COLUMN_4"), 122);\r
+       LvInsertColumn(hWnd, L_LIST, 5, _UU("SM_SESS_COLUMN_5"), 68);\r
+       LvInsertColumn(hWnd, L_LIST, 6, _UU("SM_SESS_COLUMN_6"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 7, _UU("SM_SESS_COLUMN_7"), 100);\r
+       LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);\r
+\r
+       if (s->p->ServerType == SERVER_TYPE_FARM_CONTROLLER && GetCapsBool(s->p->CapsList, "b_support_cluster_admin") == false)\r
+       {\r
+               Show(hWnd, S_FARM_INFO_1);\r
+               Show(hWnd, S_FARM_INFO_2);\r
+       }\r
+\r
+       SmSessionDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロールを更新する\r
+void SmSessionDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       bool ok = true;\r
+       bool ok2 = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_LIST) == false || LvIsMultiMasked(hWnd, L_LIST))\r
+       {\r
+               ok = false;\r
+               ok2 = false;\r
+       }\r
+       else\r
+       {\r
+               UINT i = LvGetSelected(hWnd, L_LIST);\r
+               if (i != INFINITE)\r
+               {\r
+                       void *p = LvGetParam(hWnd, L_LIST, i);\r
+                       if (((bool)p) != false)\r
+                       {\r
+                               if (GetCapsBool(s->p->CapsList, "b_support_cluster_admin") == false)\r
+                               {\r
+                                       ok = false;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (s->p->ServerInfo.ServerBuildInt < 2844)\r
+       {\r
+               // セッションのリモート管理非対応 Ver\r
+               ok2 = ok;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok2);\r
+       SetEnable(hWnd, B_DISCONNECT, ok2);\r
+       SetEnable(hWnd, B_SESSION_IP_TABLE, ok);\r
+       SetEnable(hWnd, B_SESSION_MAC_TABLE, ok);\r
+}\r
+\r
+// リストを更新する\r
+void SmSessionDlgRefresh(HWND hWnd, SM_HUB *s)\r
+{\r
+       LVB *b;\r
+       UINT i;\r
+       wchar_t *old_select;\r
+       RPC_ENUM_SESSION t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumSession(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       old_select = LvGetSelectedStr(hWnd, L_LIST, 0);\r
+\r
+       LvReset(hWnd, L_LIST);\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumSession;i++)\r
+       {\r
+               RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t *tmp2;\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp4[MAX_SIZE];\r
+               wchar_t tmp5[MAX_SIZE];\r
+               wchar_t tmp6[MAX_SIZE];\r
+               wchar_t tmp7[MAX_SIZE];\r
+               wchar_t tmp8[MAX_SIZE];\r
+               bool free_tmp2 = false;\r
+               UINT icon;\r
+\r
+               StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+\r
+               tmp2 = _UU("SM_SESS_NORMAL");\r
+               icon = ICO_VPN;\r
+               if (s->p->ServerType != SERVER_TYPE_STANDALONE)\r
+               {\r
+                       if (e->RemoteSession)\r
+                       {\r
+                               tmp2 = ZeroMalloc(MAX_SIZE);\r
+                               UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_REMOTE"), e->RemoteHostname);\r
+                               icon = ICO_VPN;\r
+                               free_tmp2 = true;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (StrLen(e->RemoteHostname) == 0)\r
+                               {\r
+                                       tmp2 = _UU("SM_SESS_LOCAL");\r
+                               }\r
+                               else\r
+                               {\r
+                                       tmp2 = ZeroMalloc(MAX_SIZE);\r
+                                       UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_LOCAL_2"), e->RemoteHostname);\r
+                                       free_tmp2 = true;\r
+                               }\r
+                       }\r
+               }\r
+               if (e->LinkMode)\r
+               {\r
+                       if (free_tmp2)\r
+                       {\r
+                               Free(tmp2);\r
+                               free_tmp2 = false;\r
+                       }\r
+                       tmp2 = _UU("SM_SESS_LINK");\r
+                       icon = ICO_CASCADE;\r
+               }\r
+               else if (e->SecureNATMode)\r
+               {\r
+                       /*if (free_tmp2)\r
+                       {\r
+                               Free(tmp2);\r
+                               free_tmp2 = false;\r
+                       }\r
+                       tmp2 = _UU("SM_SESS_SNAT");*/\r
+                       icon = ICO_ROUTER;\r
+               }\r
+               else if (e->BridgeMode)\r
+               {\r
+                       icon = ICO_BRIDGE;\r
+               }\r
+               else if (e->Layer3Mode)\r
+               {\r
+                       icon = ICO_SWITCH;\r
+               }\r
+\r
+               StrToUni(tmp3, sizeof(tmp3), e->Username);\r
+\r
+               StrToUni(tmp4, sizeof(tmp4), e->Hostname);\r
+               if (e->LinkMode)\r
+               {\r
+                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LINK_HOSTNAME"));\r
+               }\r
+               else if (e->SecureNATMode)\r
+               {\r
+                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_SNAT_HOSTNAME"));\r
+               }\r
+               else if (e->BridgeMode)\r
+               {\r
+                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_BRIDGE_HOSTNAME"));\r
+               }\r
+               else if (StartWith(e->Username, L3_USERNAME))\r
+               {\r
+                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LAYER3_HOSTNAME"));\r
+               }\r
+\r
+               UniFormat(tmp5, sizeof(tmp5), L"%u / %u", e->CurrentNumTcp, e->MaxNumTcp);\r
+               if (e->LinkMode)\r
+               {\r
+                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_LINK_TCP"));\r
+               }\r
+               else if (e->SecureNATMode)\r
+               {\r
+                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_SNAT_TCP"));\r
+               }\r
+               else if (e->BridgeMode)\r
+               {\r
+                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_BRIDGE_TCP"));\r
+               }\r
+\r
+               if (e->VLanId == 0)\r
+               {\r
+                       UniStrCpy(tmp8, sizeof(tmp8), _UU("CM_ST_NO_VLAN"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp8, e->VLanId);\r
+               }\r
+\r
+               UniToStr3(tmp6, sizeof(tmp6), e->PacketSize);\r
+               UniToStr3(tmp7, sizeof(tmp7), e->PacketNum);\r
+\r
+               if (icon == ICO_VPN)\r
+               {\r
+                       if (e->Client_BridgeMode)\r
+                       {\r
+                               icon = ICO_SESSION_BRIDGE;\r
+                       }\r
+                       else if (e->Client_MonitorMode)\r
+                       {\r
+                               icon = ICO_SESSION_MONITOR;\r
+                       }\r
+               }\r
+\r
+               LvInsertAdd(b, icon, (void *)(e->RemoteSession), 8, tmp1, tmp8, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);\r
+\r
+               if (free_tmp2)\r
+               {\r
+                       Free(tmp2);\r
+               }\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_LIST);\r
+\r
+       if (old_select != NULL && UniStrLen(old_select) != 0)\r
+       {\r
+               UINT i = LvSearchStr(hWnd, L_LIST, 0, old_select);\r
+               if (i != INFINITE)\r
+               {\r
+                       LvSelect(hWnd, L_LIST, i);\r
+               }\r
+       }\r
+\r
+       Free(old_select);\r
+\r
+       FreeRpcEnumSession(&t);\r
+\r
+       SmSessionDlgUpdate(hWnd, s);\r
+}\r
+\r
+// NODE_INFO の表示\r
+void SmPrintNodeInfo(LVB *b, NODE_INFO *info)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (b == NULL || info == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientProductName);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_NAME"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), L"%u.%02u", Endian32(info->ClientProductVer) / 100, Endian32(info->ClientProductVer) % 100);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_VER"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), L"Build %u", Endian32(info->ClientProductBuild));\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_BUILD"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientOsName);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_OS_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientOsVer);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_OS_VER"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientOsProductId);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_OS_PID"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientHostname);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_HOST"), tmp);\r
+\r
+       IPToStr4or6(str, sizeof(str), info->ClientIpAddress, info->ClientIpAddress6);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_IP"), tmp);\r
+\r
+       UniToStru(tmp, Endian32(info->ClientPort));\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_CLIENT_PORT"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ServerHostname);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_SERVER_HOST"), tmp);\r
+\r
+       IPToStr4or6(str, sizeof(str), info->ServerIpAddress, info->ServerIpAddress6);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_SERVER_IP"), tmp);\r
+\r
+       UniToStru(tmp, Endian32(info->ServerPort));\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_SERVER_PORT"), tmp);\r
+\r
+       if (StrLen(info->ProxyHostname) != 0)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), info->ProxyHostname);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_PROXY_HOSTNAME"), tmp);\r
+\r
+               IPToStr4or6(str, sizeof(str), info->ProxyIpAddress, info->ProxyIpAddress6);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_PROXY_IP"), tmp);\r
+\r
+               UniToStru(tmp, Endian32(info->ProxyPort));\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_NODE_PROXY_PORT"), tmp);\r
+       }\r
+}\r
+\r
+// セッション ステータスの更新\r
+bool SmRefreshSessionStatus(HWND hWnd, SM_SERVER *s, void *param)\r
+{\r
+       LVB *b;\r
+       SM_SESSION_STATUS *status = (SM_SESSION_STATUS *)param;\r
+       RPC_SESSION_STATUS t;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL || param == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), status->Hub->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), status->SessionName);\r
+\r
+       if (CALL(hWnd, ScGetSessionStatus(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       if (t.ClientIp != 0)\r
+       {\r
+               IPToStr4or6(str, sizeof(str), t.ClientIp, t.ClientIp6);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_CLIENT_IP"), tmp);\r
+       }\r
+\r
+       if (StrLen(t.ClientHostName) != 0)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), t.ClientHostName);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_CLIENT_HOSTNAME"), tmp);\r
+       }\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.Username);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("SM_SESS_STATUS_USERNAME"), tmp);\r
+\r
+       if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), t.RealUsername);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_SESS_STATUS_REALUSER"), tmp);\r
+       }\r
+\r
+       if (IsEmptyStr(t.GroupName) == false)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), t.GroupName);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("SM_SESS_STATUS_GROUPNAME"), tmp);\r
+       }\r
+\r
+       CmPrintStatusToListViewEx(b, &t.Status, true);\r
+\r
+       if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0 &&\r
+               StartWith(t.Username, L3_USERNAME) == false)\r
+       {\r
+               SmPrintNodeInfo(b, &t.NodeInfo);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcSessionStatus(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// セッション管理ダイアログプロシージャ\r
+UINT SmSessionDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       wchar_t *tmp;\r
+       wchar_t tmp2[MAX_SIZE];\r
+       char name[MAX_SIZE];\r
+       NMHDR *n;\r
+       SM_SESSION_STATUS status;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       tmp = LvGetSelectedStr(hWnd, L_LIST, 0);\r
+       UniToStr(name, sizeof(name), tmp);\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmSessionDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               // セッション状態表示\r
+                               UniFormat(tmp2, sizeof(tmp2), _UU("SM_SESS_STATUS_CAPTION"), name);\r
+                               Zero(&status, sizeof(status));\r
+                               status.Hub = s;\r
+                               status.SessionName = name;\r
+                               SmStatusDlg(hWnd, s->p, &status, true, true, tmp2, ICO_VPN,\r
+                                       NULL, SmRefreshSessionStatus);\r
+                       }\r
+                       break;\r
+\r
+               case B_DISCONNECT:\r
+                       // 切断\r
+                       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                               _UU("SM_SESS_DISCONNECT_MSG"), name) == IDYES)\r
+                       {\r
+                               RPC_DELETE_SESSION t;\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                               StrCpy(t.Name, sizeof(t.Name), name);\r
+\r
+                               if (CALL(hWnd, ScDeleteSession(s->Rpc, &t)))\r
+                               {\r
+                                       SmSessionDlgRefresh(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmSessionDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_SESSION_IP_TABLE:\r
+                       // IP テーブル\r
+                       SmIpTableDlg(hWnd, s, name);\r
+                       break;\r
+\r
+               case B_SESSION_MAC_TABLE:\r
+                       // MAC テーブル\r
+                       SmMacTableDlg(hWnd, s, name);\r
+                       break;\r
+\r
+               case B_MAC_TABLE:\r
+                       // MAC テーブル一覧\r
+                       SmMacTableDlg(hWnd, s, NULL);\r
+                       break;\r
+\r
+               case B_IP_TABLE:\r
+                       // IP テーブル一覧\r
+                       SmIpTableDlg(hWnd, s, NULL);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_LIST:\r
+                               SmSessionDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       Free(tmp);\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+// セッション管理ダイアログ\r
+void SmSessionDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_SESSION, SmSessionDlgProc, s);\r
+}\r
+\r
+// 証明書一覧更新\r
+void SmCaDlgRefresh(HWND hWnd, SM_HUB *s)\r
+{\r
+       LVB *b;\r
+       UINT i;\r
+       RPC_HUB_ENUM_CA t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       if (CALL(hWnd, ScEnumCa(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumCa;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               RPC_HUB_ENUM_CA_ITEM *e = &t.Ca[i];\r
+\r
+               GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(e->Expires), NULL);\r
+\r
+               LvInsertAdd(b, ICO_SERVER_CERT, (void *)e->Key, 3,\r
+                       e->SubjectName, e->IssuerName, tmp);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_CERT);\r
+\r
+       FreeRpcHubEnumCa(&t);\r
+\r
+       SmCaDlgUpdate(hWnd, s);\r
+}\r
+\r
+// 初期化\r
+void SmCaDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_SERVER_CERT);\r
+\r
+       LvInit(hWnd, L_CERT);\r
+       LvInsertColumn(hWnd, L_CERT, 0, _UU("CM_CERT_COLUMN_1"), 190);\r
+       LvInsertColumn(hWnd, L_CERT, 1, _UU("CM_CERT_COLUMN_2"), 190);\r
+       LvInsertColumn(hWnd, L_CERT, 2, _UU("CM_CERT_COLUMN_3"), 160);\r
+\r
+       SmCaDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmCaDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, B_DELETE, LvIsSelected(hWnd, L_CERT));\r
+       SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_CERT));\r
+}\r
+\r
+// OK\r
+void SmCaDlgOnOk(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+}\r
+\r
+// CA 追加ダイアログ\r
+bool SmCaDlgAdd(HWND hWnd, SM_HUB *s)\r
+{\r
+       X *x;\r
+       RPC_HUB_ADD_CA t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (CmLoadXFromFileOrSecureCard(hWnd, &x) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       t.Cert = x;\r
+\r
+       if (CALL(hWnd, ScAddCa(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       FreeRpcHubAddCa(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// CA 一覧ダイアログプロシージャ\r
+UINT SmCaDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       UINT i, key;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmCaDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_IMPORT:\r
+                       // 追加\r
+                       if (SmCaDlgAdd(hWnd, s))\r
+                       {\r
+                               SmCaDlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       i = LvGetSelected(hWnd, L_CERT);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               key = (UINT)LvGetParam(hWnd, L_CERT, i);\r
+                               if (key != 0)\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                                               _UU("CM_CERT_DELETE_MSG")) == IDYES)\r
+                                       {\r
+                                               RPC_HUB_DELETE_CA t;\r
+                                               Zero(&t, sizeof(t));\r
+                                               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                                               t.Key = key;\r
+\r
+                                               if (CALL(hWnd, ScDeleteCa(s->Rpc, &t)))\r
+                                               {\r
+                                                       SmCaDlgRefresh(hWnd, s);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // 表示\r
+                       i = LvGetSelected(hWnd, L_CERT);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               key = (UINT)LvGetParam(hWnd, L_CERT, i);\r
+                               if (key != 0)\r
+                               {\r
+                                       RPC_HUB_GET_CA t;\r
+                                       Zero(&t, sizeof(t));\r
+                                       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                                       t.Key = key;\r
+\r
+                                       if (CALL(hWnd, ScGetCa(s->Rpc, &t)))\r
+                                       {\r
+                                               CertDlg(hWnd, t.Cert, NULL, true);\r
+                                               FreeRpcHubGetCa(&t);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_CERT:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmCaDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_CERT);\r
+\r
+       return 0;\r
+}\r
+\r
+// CA 一覧ダイアログ\r
+void SmCaDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_CA, SmCaDlgProc, s);\r
+}\r
+\r
+// 初期化\r
+void SmLogDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       RPC_HUB_LOG t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_LOG2);\r
+\r
+       FormatText(hWnd, S_TITLE, s->HubName);\r
+\r
+       CbSetHeight(hWnd, C_SEC_SWITCH, 18);\r
+       CbSetHeight(hWnd, C_PACKET_SWITCH, 18);\r
+\r
+       // コントロール初期化\r
+       CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_0"), 0);\r
+       CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_1"), 1);\r
+       CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_2"), 2);\r
+       CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_3"), 3);\r
+       CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_4"), 4);\r
+       CbAddStr(hWnd, C_SEC_SWITCH, _UU("SM_LOG_SWITCH_5"), 5);\r
+       CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_0"), 0);\r
+       CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_1"), 1);\r
+       CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_2"), 2);\r
+       CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_3"), 3);\r
+       CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_4"), 4);\r
+       CbAddStr(hWnd, C_PACKET_SWITCH, _UU("SM_LOG_SWITCH_5"), 5);\r
+\r
+       // ログ設定を取得\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       if (CALL(hWnd, ScGetHubLog(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       Check(hWnd, B_SEC, t.LogSetting.SaveSecurityLog);\r
+       CbSelect(hWnd, C_SEC_SWITCH, t.LogSetting.SecurityLogSwitchType);\r
+\r
+       Check(hWnd, B_PACKET, t.LogSetting.SavePacketLog);\r
+       CbSelect(hWnd, C_PACKET_SWITCH, t.LogSetting.PacketLogSwitchType);\r
+\r
+       Check(hWnd, B_PACKET_0_0, t.LogSetting.PacketLogConfig[0] == 0);\r
+       Check(hWnd, B_PACKET_0_1, t.LogSetting.PacketLogConfig[0] == 1);\r
+       Check(hWnd, B_PACKET_0_2, t.LogSetting.PacketLogConfig[0] == 2);\r
+\r
+       Check(hWnd, B_PACKET_1_0, t.LogSetting.PacketLogConfig[1] == 0);\r
+       Check(hWnd, B_PACKET_1_1, t.LogSetting.PacketLogConfig[1] == 1);\r
+       Check(hWnd, B_PACKET_1_2, t.LogSetting.PacketLogConfig[1] == 2);\r
+\r
+       Check(hWnd, B_PACKET_2_0, t.LogSetting.PacketLogConfig[2] == 0);\r
+       Check(hWnd, B_PACKET_2_1, t.LogSetting.PacketLogConfig[2] == 1);\r
+       Check(hWnd, B_PACKET_2_2, t.LogSetting.PacketLogConfig[2] == 2);\r
+\r
+       Check(hWnd, B_PACKET_3_0, t.LogSetting.PacketLogConfig[3] == 0);\r
+       Check(hWnd, B_PACKET_3_1, t.LogSetting.PacketLogConfig[3] == 1);\r
+       Check(hWnd, B_PACKET_3_2, t.LogSetting.PacketLogConfig[3] == 2);\r
+\r
+       Check(hWnd, B_PACKET_4_0, t.LogSetting.PacketLogConfig[4] == 0);\r
+       Check(hWnd, B_PACKET_4_1, t.LogSetting.PacketLogConfig[4] == 1);\r
+       Check(hWnd, B_PACKET_4_2, t.LogSetting.PacketLogConfig[4] == 2);\r
+\r
+       Check(hWnd, B_PACKET_5_0, t.LogSetting.PacketLogConfig[5] == 0);\r
+       Check(hWnd, B_PACKET_5_1, t.LogSetting.PacketLogConfig[5] == 1);\r
+       Check(hWnd, B_PACKET_5_2, t.LogSetting.PacketLogConfig[5] == 2);\r
+\r
+       Check(hWnd, B_PACKET_6_0, t.LogSetting.PacketLogConfig[6] == 0);\r
+       Check(hWnd, B_PACKET_6_1, t.LogSetting.PacketLogConfig[6] == 1);\r
+       Check(hWnd, B_PACKET_6_2, t.LogSetting.PacketLogConfig[6] == 2);\r
+\r
+       Check(hWnd, B_PACKET_7_0, t.LogSetting.PacketLogConfig[7] == 0);\r
+       Check(hWnd, B_PACKET_7_1, t.LogSetting.PacketLogConfig[7] == 1);\r
+       Check(hWnd, B_PACKET_7_2, t.LogSetting.PacketLogConfig[7] == 2);\r
+\r
+       SmLogDlgUpdate(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmLogDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       bool b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = IsChecked(hWnd, B_SEC);\r
+       SetEnable(hWnd, S_SEC, b);\r
+       SetEnable(hWnd, C_SEC_SWITCH, b);\r
+\r
+       b = IsChecked(hWnd, B_PACKET);\r
+       SetEnable(hWnd, S_PACKET, b);\r
+       SetEnable(hWnd, C_PACKET_SWITCH, b);\r
+       SetEnable(hWnd, S_PACKET_0, b);\r
+       SetEnable(hWnd, S_PACKET_1, b);\r
+       SetEnable(hWnd, S_PACKET_2, b);\r
+       SetEnable(hWnd, S_PACKET_3, b);\r
+       SetEnable(hWnd, S_PACKET_4, b);\r
+       SetEnable(hWnd, S_PACKET_5, b);\r
+       SetEnable(hWnd, S_PACKET_6, b);\r
+       SetEnable(hWnd, S_PACKET_7, b);\r
+       SetEnable(hWnd, B_PACKET_0_0, b); SetEnable(hWnd, B_PACKET_0_1, b); SetEnable(hWnd, B_PACKET_0_2, b);\r
+       SetEnable(hWnd, B_PACKET_1_0, b); SetEnable(hWnd, B_PACKET_1_1, b); SetEnable(hWnd, B_PACKET_1_2, b);\r
+       SetEnable(hWnd, B_PACKET_2_0, b); SetEnable(hWnd, B_PACKET_2_1, b); SetEnable(hWnd, B_PACKET_2_2, b);\r
+       SetEnable(hWnd, B_PACKET_3_0, b); SetEnable(hWnd, B_PACKET_3_1, b); SetEnable(hWnd, B_PACKET_3_2, b);\r
+       SetEnable(hWnd, B_PACKET_4_0, b); SetEnable(hWnd, B_PACKET_4_1, b); SetEnable(hWnd, B_PACKET_4_2, b);\r
+       SetEnable(hWnd, B_PACKET_5_0, b); SetEnable(hWnd, B_PACKET_5_1, b); SetEnable(hWnd, B_PACKET_5_2, b);\r
+       SetEnable(hWnd, B_PACKET_6_0, b); SetEnable(hWnd, B_PACKET_6_1, b); SetEnable(hWnd, B_PACKET_6_2, b);\r
+       SetEnable(hWnd, B_PACKET_7_0, b); SetEnable(hWnd, B_PACKET_7_1, b); SetEnable(hWnd, B_PACKET_7_2, b);\r
+}\r
+\r
+// OK\r
+void SmLogDlgOnOk(HWND hWnd, SM_HUB *s)\r
+{\r
+       HUB_LOG g;\r
+       RPC_HUB_LOG t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&g, sizeof(g));\r
+       g.SaveSecurityLog = IsChecked(hWnd, B_SEC);\r
+       g.SavePacketLog = IsChecked(hWnd, B_PACKET);\r
+       g.SecurityLogSwitchType = CbGetSelect(hWnd, C_SEC_SWITCH);\r
+       g.PacketLogSwitchType = CbGetSelect(hWnd, C_PACKET_SWITCH);\r
+\r
+       g.PacketLogConfig[0] = IsChecked(hWnd, B_PACKET_0_0) ? 0 : IsChecked(hWnd, B_PACKET_0_1) ? 1 : 2;\r
+       g.PacketLogConfig[1] = IsChecked(hWnd, B_PACKET_1_0) ? 0 : IsChecked(hWnd, B_PACKET_1_1) ? 1 : 2;\r
+       g.PacketLogConfig[2] = IsChecked(hWnd, B_PACKET_2_0) ? 0 : IsChecked(hWnd, B_PACKET_2_1) ? 1 : 2;\r
+       g.PacketLogConfig[3] = IsChecked(hWnd, B_PACKET_3_0) ? 0 : IsChecked(hWnd, B_PACKET_3_1) ? 1 : 2;\r
+       g.PacketLogConfig[4] = IsChecked(hWnd, B_PACKET_4_0) ? 0 : IsChecked(hWnd, B_PACKET_4_1) ? 1 : 2;\r
+       g.PacketLogConfig[5] = IsChecked(hWnd, B_PACKET_5_0) ? 0 : IsChecked(hWnd, B_PACKET_5_1) ? 1 : 2;\r
+       g.PacketLogConfig[6] = IsChecked(hWnd, B_PACKET_6_0) ? 0 : IsChecked(hWnd, B_PACKET_6_1) ? 1 : 2;\r
+       g.PacketLogConfig[7] = IsChecked(hWnd, B_PACKET_7_0) ? 0 : IsChecked(hWnd, B_PACKET_7_1) ? 1 : 2;\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       Copy(&t.LogSetting, &g, sizeof(HUB_LOG));\r
+\r
+       if (CALL(hWnd, ScSetHubLog(s->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// ログ保存設定ダイアログ\r
+UINT SmLogDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmLogDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case B_SEC:\r
+               case B_PACKET:\r
+                       SmLogDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmLogDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のステータスの表示\r
+bool SmRefreshLinkStatus(HWND hWnd, SM_SERVER *s, void *param)\r
+{\r
+       SM_LINK *k = (SM_LINK *)param;\r
+       RPC_LINK_STATUS t;\r
+       LVB *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL || param == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), k->Hub->HubName);\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), k->AccountName);\r
+\r
+       if (CALL(hWnd, ScGetLinkStatus(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       CmPrintStatusToListView(b, &t.Status);\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcLinkStatus(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// リンクの編集\r
+bool SmLinkEdit(HWND hWnd, SM_HUB *s, wchar_t *name)\r
+{\r
+       CM_ACCOUNT a;\r
+       RPC_CREATE_LINK t;\r
+       bool ret = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL || name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), name);\r
+\r
+       if (CALL(hWnd, ScGetLink(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       a.Hub = s;\r
+       a.EditMode = true;\r
+       a.LinkMode = true;\r
+       a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       a.OnlineFlag = t.Online;\r
+       Copy(a.ClientOption, t.ClientOption, sizeof(CLIENT_OPTION));\r
+       a.ClientAuth = CopyClientAuth(t.ClientAuth);\r
+       Copy(&a.Policy, &t.Policy, sizeof(POLICY));\r
+       a.CheckServerCert = t.CheckServerCert;\r
+       a.ServerCert = CloneX(t.ServerCert);\r
+       a.HideTrustCert = GetCapsBool(s->p->CapsList, "b_support_config_hub");\r
+       FreeRpcCreateLink(&t);\r
+\r
+       a.PolicyVer = s->p->PolicyVer;\r
+\r
+       if (GetCapsBool(s->p->CapsList, "b_support_cascade_client_cert") == false)\r
+       {\r
+               a.HideClientCertAuth = true;\r
+       }\r
+\r
+       a.HideSecureAuth = true;\r
+\r
+       ret = CmEditAccountDlg(hWnd, &a);\r
+\r
+       FreeX(a.ServerCert);\r
+       Free(a.ClientOption);\r
+       CiFreeClientAuth(a.ClientAuth);\r
+\r
+       return ret;\r
+}\r
+\r
+// 新しいリンクの作成\r
+bool SmLinkCreate(HWND hWnd, SM_HUB *s)\r
+{\r
+       return SmLinkCreateEx(hWnd, s, false);\r
+}\r
+bool SmLinkCreateEx(HWND hWnd, SM_HUB *s, bool connectNow)\r
+{\r
+       CM_ACCOUNT a;\r
+       bool ret = false;;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+\r
+       a.Hub = s;\r
+       a.EditMode = false;\r
+       a.LinkMode = true;\r
+       a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       a.OnlineFlag = false;\r
+       a.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
+       a.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;\r
+       Copy(&a.Policy, GetDefaultPolicy(), sizeof(POLICY));\r
+       a.ClientOption->Port = 443;     // デフォルトポート番号\r
+       a.ClientOption->NumRetry = INFINITE;\r
+       a.ClientOption->RetryInterval = 15;\r
+       a.ClientOption->MaxConnection = 8;\r
+       a.ClientOption->UseEncrypt = true;\r
+       a.ClientOption->HalfConnection = false;\r
+       a.ClientOption->AdditionalConnectionInterval = 1;\r
+       a.ClientOption->RequireBridgeRoutingMode = true;\r
+       a.Link_ConnectNow = connectNow;\r
+\r
+       a.PolicyVer = s->p->PolicyVer;\r
+\r
+       if (GetCapsBool(s->p->CapsList, "b_support_cascade_client_cert") == false)\r
+       {\r
+               a.HideClientCertAuth = true;\r
+       }\r
+\r
+       a.HideSecureAuth = true;\r
+\r
+       ret = CmEditAccountDlg(hWnd, &a);\r
+\r
+       FreeX(a.ServerCert);\r
+       Free(a.ClientOption);\r
+       CiFreeClientAuth(a.ClientAuth);\r
+\r
+       return ret;\r
+}\r
+\r
+// 初期化\r
+void SmLinkDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_LINK);\r
+\r
+       FormatText(hWnd, 0, s->HubName);\r
+\r
+       LvInit(hWnd, L_LINK);\r
+\r
+       LvInsertColumn(hWnd, L_LINK, 0, _UU("SM_LINK_COLUMN_1"), 120);\r
+       LvInsertColumn(hWnd, L_LINK, 1, _UU("SM_LINK_COLUMN_2"), 150);\r
+       LvInsertColumn(hWnd, L_LINK, 2, _UU("SM_LINK_COLUMN_3"), 180);\r
+       LvInsertColumn(hWnd, L_LINK, 3, _UU("SM_LINK_COLUMN_4"), 130);\r
+       LvInsertColumn(hWnd, L_LINK, 4, _UU("SM_LINK_COLUMN_5"), 130);\r
+\r
+       LvSetStyle(hWnd, L_LINK, LVS_EX_GRIDLINES);\r
+\r
+       SmLinkDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmLinkDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       bool ok = true;\r
+       bool online = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_LINK) == false || LvIsMultiMasked(hWnd, L_LINK))\r
+       {\r
+               ok = false;\r
+       }\r
+       else\r
+       {\r
+               online = (bool)LvGetParam(hWnd, L_LINK, LvGetSelected(hWnd, L_LINK));\r
+       }\r
+\r
+       SetEnable(hWnd, B_EDIT, ok);\r
+       SetEnable(hWnd, B_ONLINE, ok && (online == false));\r
+       SetEnable(hWnd, B_OFFLINE, ok && online);\r
+       SetEnable(hWnd, IDOK, ok && online);\r
+       SetEnable(hWnd, B_DELETE, ok);\r
+       SetEnable(hWnd, B_RENAME, ok);\r
+}\r
+\r
+// 内容更新\r
+void SmLinkDlgRefresh(HWND hWnd, SM_HUB *s)\r
+{\r
+       LVB *b;\r
+       RPC_ENUM_LINK t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       if (CALL(hWnd, ScEnumLink(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumLink;i++)\r
+       {\r
+               RPC_ENUM_LINK_ITEM *e = &t.Links[i];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp4[MAX_SIZE];\r
+               UINT icon = ICO_CASCADE;\r
+\r
+               GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);\r
+               StrToUni(tmp2, sizeof(tmp2), e->Hostname);\r
+               StrToUni(tmp3, sizeof(tmp3), e->HubName);\r
+\r
+               if (e->Online == false)\r
+               {\r
+                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_OFFLINE"));\r
+               }\r
+               else\r
+               {\r
+                       if (e->Connected)\r
+                       {\r
+                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ONLINE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               if (e->LastError != 0)\r
+                               {\r
+                                       UniFormat(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ERROR"), e->LastError, _E(e->LastError));\r
+                               }\r
+                               else\r
+                               {\r
+                                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_CONNECTING"));\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (e->Online == false)\r
+               {\r
+                       icon = ICO_CASCADE_OFFLINE;\r
+               }\r
+               else\r
+               {\r
+                       if (e->Connected == false && e->LastError != 0)\r
+                       {\r
+                               icon = ICO_CASCADE_ERROR;\r
+                       }\r
+                       else\r
+                       {\r
+                               icon = ICO_CASCADE;\r
+                       }\r
+               }\r
+\r
+               LvInsertAdd(b,\r
+                       icon, (void *)e->Online, 5,\r
+                       e->AccountName, tmp4, tmp1, tmp2, tmp3);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_LINK);\r
+\r
+       FreeRpcEnumLink(&t);\r
+\r
+       SmLinkDlgUpdate(hWnd, s);\r
+}\r
+\r
+\r
+// リンク一覧ダイアログプロシージャ\r
+UINT SmLinkDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       wchar_t *str;\r
+       NMHDR *n;\r
+       NMLVDISPINFOW *disp_info;\r
+       NMLVKEYDOWN *key;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       str = LvGetSelectedStr(hWnd, L_LINK, 0);\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmLinkDlgInit(hWnd, s);\r
+\r
+               if (link_create_now)\r
+               {\r
+                       if (SmLinkCreateEx(hWnd, s, true))\r
+                       {\r
+                               SmLinkDlgRefresh(hWnd, s);\r
+                       }\r
+               }\r
+\r
+               SetTimer(hWnd, 1, 1000, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       SmLinkDlgRefresh(hWnd, s);\r
+                       SetTimer(hWnd, 1, 1000, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_CREATE:\r
+                       // 新規作成\r
+                       if (SmLinkCreate(hWnd, s))\r
+                       {\r
+                               SmLinkDlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_EDIT:\r
+                       // 編集\r
+                       if (str != NULL)\r
+                       {\r
+                               if (SmLinkEdit(hWnd, s, str))\r
+                               {\r
+                                       SmLinkDlgRefresh(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_ONLINE:\r
+                       // オンライン\r
+                       if (str != NULL)\r
+                       {\r
+                               RPC_LINK t;\r
+                               Zero(&t, sizeof(t));\r
+                               UniStrCpy(t.AccountName, sizeof(t.AccountName), str);\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+                               if (CALL(hWnd, ScSetLinkOnline(s->Rpc, &t)))\r
+                               {\r
+                                       SmLinkDlgRefresh(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_OFFLINE:\r
+                       // オフライン\r
+                       if (str != NULL)\r
+                       {\r
+                               RPC_LINK t;\r
+                               Zero(&t, sizeof(t));\r
+                               UniStrCpy(t.AccountName, sizeof(t.AccountName), str);\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+                               if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,\r
+                                       _UU("SM_LINK_OFFLINE_MSG"), t.AccountName) == IDYES)\r
+                               {\r
+                                       if (CALL(hWnd, ScSetLinkOffline(s->Rpc, &t)))\r
+                                       {\r
+                                               SmLinkDlgRefresh(hWnd, s);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // 状態\r
+                       if (str != NULL)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               SM_LINK t;\r
+                               Zero(&t, sizeof(t));\r
+                               t.Hub = s;\r
+                               t.AccountName = str;\r
+                               UniFormat(tmp, sizeof(tmp), _UU("SM_LINK_STATUS_CAPTION"), str);\r
+                               SmStatusDlg(hWnd, s->p, &t, true, true, tmp,\r
+                                       ICO_CASCADE, NULL, SmRefreshLinkStatus);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       if (str != NULL)\r
+                       {\r
+                               RPC_LINK t;\r
+                               Zero(&t, sizeof(t));\r
+                               UniStrCpy(t.AccountName, sizeof(t.AccountName), str);\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+                               if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2,\r
+                                       _UU("SM_LINK_DELETE_MSG"), t.AccountName) == IDYES)\r
+                               {\r
+                                       if (CALL(hWnd, ScDeleteLink(s->Rpc, &t)))\r
+                                       {\r
+                                               SmLinkDlgRefresh(hWnd, s);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmLinkDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_RENAME:\r
+                       // 名前の変更\r
+                       Focus(hWnd, L_LINK);\r
+                       LvRename(hWnd, L_LINK, LvGetSelected(hWnd, L_LINK));\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_LINK:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               // 選択状態の変更\r
+                               SmLinkDlgUpdate(hWnd, s);\r
+                               break;\r
+\r
+                       case LVN_ENDLABELEDITW:\r
+                               // 名前の変更\r
+                               disp_info = (NMLVDISPINFOW *)n;\r
+                               if (disp_info->item.pszText != NULL)\r
+                               {\r
+                                       wchar_t *new_name = disp_info->item.pszText;\r
+                                       wchar_t *old_name = LvGetStr(hWnd, L_LINK, disp_info->item.iItem, 0);\r
+\r
+                                       if (old_name != NULL)\r
+                                       {\r
+                                               if (UniStrCmp(new_name, old_name) != 0 && UniIsEmptyStr(new_name) == false)\r
+                                               {\r
+                                                       RPC_RENAME_LINK t;\r
+                                                       Zero(&t, sizeof(t));\r
+                                                       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+                                                       UniStrCpy(t.OldAccountName, sizeof(t.OldAccountName), old_name);\r
+                                                       UniStrCpy(t.NewAccountName, sizeof(t.NewAccountName), new_name);\r
+                                                       if (CALL(hWnd, ScRenameLink(s->Rpc, &t)))\r
+                                                       {\r
+                                                               SmLinkDlgRefresh(hWnd, s);\r
+                                                       }\r
+                                               }\r
+\r
+                                               Free(old_name);\r
+                                       }\r
+                               }\r
+                               break;\r
+\r
+                       case LVN_KEYDOWN:\r
+                               // キー押下\r
+                               key = (NMLVKEYDOWN *)n;\r
+                               if (key != NULL)\r
+                               {\r
+                                       bool ctrl, alt;\r
+                                       UINT code = key->wVKey;\r
+                                       ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;\r
+                                       alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;\r
+\r
+                                       if (code == VK_F2)\r
+                                       {\r
+                                               Command(hWnd, B_RENAME);\r
+                                       }\r
+                               }\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       Free(str);\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LINK);\r
+\r
+       return 0;\r
+}\r
+\r
+// リンク一覧ダイアログ\r
+void SmLinkDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       SmLinkDlgEx(hWnd, s, false);\r
+}\r
+void SmLinkDlgEx(HWND hWnd, SM_HUB *s, bool createNow)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       link_create_now = createNow;\r
+\r
+       Dialog(hWnd, D_SM_LINK, SmLinkDlgProc, s);\r
+}\r
+\r
+// 初期化\r
+void SmRadiusDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       RPC_RADIUS t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_TOWER);\r
+\r
+       FormatText(hWnd, S_TITLE, s->HubName);\r
+       FormatText(hWnd, S_RADIUS_7, RADIUS_RETRY_INTERVAL, RADIUS_RETRY_TIMEOUT);\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (CALL(hWnd, ScGetHubRadius(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       Check(hWnd, R_USE_RADIUS, StrLen(t.RadiusServerName) != 0);\r
+\r
+       if (StrLen(t.RadiusServerName) != 0)\r
+       {\r
+               SetTextA(hWnd, E_HOSTNAME, t.RadiusServerName);\r
+               SetIntEx(hWnd, E_PORT, t.RadiusPort);\r
+               SetTextA(hWnd, E_SECRET1, t.RadiusSecret);\r
+               SetTextA(hWnd, E_SECRET2, t.RadiusSecret);\r
+               SetIntEx(hWnd, E_RADIUS_RETRY_INTERVAL, t.RadiusRetryInterval);\r
+               FocusEx(hWnd, E_HOSTNAME);\r
+       }\r
+       else\r
+       {\r
+               SetInt(hWnd, E_PORT, RADIUS_DEFAULT_PORT);\r
+               SetInt(hWnd, E_RADIUS_RETRY_INTERVAL, RADIUS_RETRY_INTERVAL);\r
+       }\r
+\r
+       SmRadiusDlgUpdate(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmRadiusDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       bool ok = true;\r
+       bool b, b1;\r
+       char tmp1[MAX_SIZE];\r
+       char tmp2[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b1 = GetCapsBool(s->p->CapsList, "b_support_radius_retry_interval_and_several_servers");\r
+       if(b1 == false)\r
+       {\r
+               Hide(hWnd, S_RADIUS_7);\r
+               Hide(hWnd, S_RADIUS_8);\r
+               Hide(hWnd, S_RADIUS_9);\r
+               Hide(hWnd, E_RADIUS_RETRY_INTERVAL);\r
+       }\r
+\r
+       b = IsChecked(hWnd, R_USE_RADIUS);\r
+\r
+       SetEnable(hWnd, S_RADIUS_1, b);\r
+       SetEnable(hWnd, S_RADIUS_2, b);\r
+       SetEnable(hWnd, S_RADIUS_3, b);\r
+       SetEnable(hWnd, S_RADIUS3, b);\r
+       SetEnable(hWnd, S_RADIUS_4, b);\r
+       SetEnable(hWnd, S_RADIUS_5, b);\r
+       SetEnable(hWnd, S_RADIUS_6, b);\r
+       SetEnable(hWnd, S_RADIUS_7, b);\r
+       SetEnable(hWnd, S_RADIUS_8, b);\r
+       SetEnable(hWnd, S_RADIUS_9, b);\r
+       SetEnable(hWnd, E_HOSTNAME, b);\r
+       SetEnable(hWnd, E_PORT, b);\r
+       SetEnable(hWnd, E_SECRET1, b);\r
+       SetEnable(hWnd, E_SECRET2, b);\r
+       SetEnable(hWnd, E_RADIUS_RETRY_INTERVAL, b);\r
+\r
+       if (b)\r
+       {\r
+               UINT p, m;\r
+               GetTxtA(hWnd, E_SECRET1, tmp1, sizeof(tmp1));\r
+               GetTxtA(hWnd, E_SECRET2, tmp2, sizeof(tmp2));\r
+\r
+               if (StrCmp(tmp1, tmp2) != 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (IsEmpty(hWnd, E_HOSTNAME))\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               p = GetInt(hWnd, E_PORT);\r
+\r
+               if (p == 0 || p >= 65536)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               m = GetInt(hWnd, E_RADIUS_RETRY_INTERVAL);\r
+               if (m > RADIUS_RETRY_TIMEOUT || m < RADIUS_RETRY_INTERVAL)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK ボタン\r
+void SmRadiusDlgOnOk(HWND hWnd, SM_HUB *s)\r
+{\r
+       RPC_RADIUS t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+\r
+       if (IsChecked(hWnd, R_USE_RADIUS))\r
+       {\r
+               GetTxtA(hWnd, E_HOSTNAME, t.RadiusServerName, sizeof(t.RadiusServerName));\r
+               t.RadiusPort = GetInt(hWnd, E_PORT);\r
+               GetTxtA(hWnd, E_SECRET1,t.RadiusSecret, sizeof(t.RadiusSecret));\r
+               t.RadiusRetryInterval = GetInt(hWnd, E_RADIUS_RETRY_INTERVAL);\r
+       }\r
+\r
+       if (CALL(hWnd, ScSetHubRadius(s->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+\r
+// Radius ダイアログ プロシージャ\r
+UINT SmRadiusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmRadiusDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_HOSTNAME:\r
+               case E_PORT:\r
+               case E_SECRET1:\r
+               case E_SECRET2:\r
+               case E_RADIUS_RETRY_INTERVAL:\r
+               case R_USE_RADIUS:\r
+                       SmRadiusDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmRadiusDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_USE_RADIUS:\r
+                       if (IsChecked(hWnd, R_USE_RADIUS))\r
+                       {\r
+                               FocusEx(hWnd, E_HOSTNAME);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// Radius 設定ダイアログ\r
+void SmRadiusDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_RADIUS, SmRadiusDlgProc, s);\r
+}\r
+\r
+\r
+// 初期化\r
+void SmEditAccessInit(HWND hWnd, SM_EDIT_ACCESS *s)\r
+{\r
+       ACCESS *a;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_PASS);\r
+\r
+       GetTxt(hWnd, 0, tmp, sizeof(tmp));\r
+\r
+       UniStrCat(tmp, sizeof(tmp), s->Access->IsIPv6 ? L" (IPv6)" : L" (IPv4)");\r
+\r
+       SetText(hWnd, 0, tmp);\r
+\r
+       s->Inited = false;\r
+       a = s->Access;\r
+\r
+       SetText(hWnd, E_NOTE, a->Note);\r
+\r
+       Check(hWnd, R_DISCARD, a->Discard);\r
+       Check(hWnd, R_PASS, a->Discard == false);\r
+       SetIntEx(hWnd, E_PRIORITY, a->Priority);\r
+\r
+       if (a->IsIPv6 == false)\r
+       {\r
+               // IPv4\r
+               if (a->SrcIpAddress == 0 && a->SrcSubnetMask == 0)\r
+               {\r
+                       Check(hWnd, R_SRC_ALL, true);\r
+               }\r
+               else\r
+               {\r
+                       IpSet(hWnd, E_SRC_IP, a->SrcIpAddress);\r
+                       IpSet(hWnd, E_SRC_MASK, a->SrcSubnetMask);\r
+               }\r
+\r
+               if (a->DestIpAddress == 0 && a->DestSubnetMask == 0)\r
+               {\r
+                       Check(hWnd, R_DST_ALL, true);\r
+               }\r
+               else\r
+               {\r
+                       IpSet(hWnd, E_DST_IP, a->DestIpAddress);\r
+                       IpSet(hWnd, E_DST_MASK, a->DestSubnetMask);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               // IPv6\r
+               if (IsZeroIP6Addr(&a->SrcIpAddress6) && IsZeroIP6Addr(&a->SrcSubnetMask6))\r
+               {\r
+                       Check(hWnd, R_SRC_ALL, true);\r
+               }\r
+               else\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+\r
+                       IP6AddrToStr(tmp, sizeof(tmp), &a->SrcIpAddress6);\r
+                       SetTextA(hWnd, E_SRC_IP_V6, tmp);\r
+\r
+                       Mask6AddrToStrEx(tmp, sizeof(tmp), &a->SrcSubnetMask6, false);\r
+\r
+                       if (IsNum(tmp))\r
+                       {\r
+                               StrCatLeft(tmp, sizeof(tmp), "/");\r
+                       }\r
+\r
+                       SetTextA(hWnd, E_SRC_MASK_V6, tmp);\r
+               }\r
+\r
+               if (IsZeroIP6Addr(&a->DestIpAddress6) && IsZeroIP6Addr(&a->DestSubnetMask6))\r
+               {\r
+                       Check(hWnd, R_DST_ALL, true);\r
+               }\r
+               else\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+\r
+                       IP6AddrToStr(tmp, sizeof(tmp), &a->DestIpAddress6);\r
+                       SetTextA(hWnd, E_DST_IP_V6, tmp);\r
+\r
+                       Mask6AddrToStrEx(tmp, sizeof(tmp), &a->DestSubnetMask6, false);\r
+\r
+                       if (IsNum(tmp))\r
+                       {\r
+                               StrCatLeft(tmp, sizeof(tmp), "/");\r
+                       }\r
+\r
+                       SetTextA(hWnd, E_DST_MASK_V6, tmp);\r
+               }\r
+       }\r
+\r
+       CbSetHeight(hWnd, C_PROTOCOL, 18);\r
+       CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_1"), 0);\r
+       CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_2"), 0);\r
+       CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_3"), 0);\r
+       CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_4"), 0);\r
+       CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_5"), 0);\r
+       CbAddStr(hWnd, C_PROTOCOL, _UU("SM_ACCESS_PROTO_6"), 0);\r
+\r
+       switch (a->Protocol)\r
+       {\r
+       case 0:\r
+               CbSelectIndex(hWnd, C_PROTOCOL, 0);\r
+               break;\r
+       case 6:\r
+               CbSelectIndex(hWnd, C_PROTOCOL, 1);\r
+               break;\r
+       case 17:\r
+               CbSelectIndex(hWnd, C_PROTOCOL, 2);\r
+               break;\r
+       case 1:\r
+               CbSelectIndex(hWnd, C_PROTOCOL, 3);\r
+               break;\r
+       case 58:\r
+               CbSelectIndex(hWnd, C_PROTOCOL, 4);\r
+               break;\r
+       default:\r
+               CbSelectIndex(hWnd, C_PROTOCOL, 5);\r
+               break;\r
+       }\r
+\r
+       Check(hWnd, R_DISABLE, a->Active ? false : true);\r
+\r
+       SetIntEx(hWnd, E_IP_PROTO, a->Protocol);\r
+\r
+       SetIntEx(hWnd, E_SRC_PORT_1, a->SrcPortStart);\r
+       SetIntEx(hWnd, E_SRC_PORT_2, a->SrcPortEnd);\r
+       SetIntEx(hWnd, E_DST_PORT_1, a->DestPortStart);\r
+       SetIntEx(hWnd, E_DST_PORT_2, a->DestPortEnd);\r
+\r
+       SetTextA(hWnd, E_USERNAME1, a->SrcUsername);\r
+       SetTextA(hWnd, E_USERNAME2, a->DestUsername);\r
+\r
+       if(a->CheckSrcMac != false)\r
+       {\r
+               char mac[MAX_SIZE], mask[MAX_SIZE];\r
+               MacToStr(mac, sizeof(mac), a->SrcMacAddress);\r
+               MacToStr(mask, sizeof(mask), a->SrcMacMask);\r
+               SetTextA(hWnd, E_SRC_MAC, mac); \r
+               SetTextA(hWnd, E_SRC_MAC_MASK, mask);\r
+       }\r
+       if(a->CheckDstMac != false)\r
+       {\r
+               char mac[MAX_SIZE], mask[MAX_SIZE];\r
+               MacToStr(mac, sizeof(mac), a->DstMacAddress);\r
+               MacToStr(mask, sizeof(mask), a->DstMacMask);\r
+               SetTextA(hWnd, E_DST_MAC, mac); \r
+               SetTextA(hWnd, E_DST_MAC_MASK, mask);\r
+       }\r
+       Check(hWnd, R_CHECK_SRC_MAC, !a->CheckSrcMac);\r
+       Check(hWnd, R_CHECK_DST_MAC, !a->CheckDstMac);\r
+\r
+       Check(hWnd, R_CHECK_TCP_STATE, a->CheckTcpState);\r
+       if(a->CheckTcpState != false)\r
+       {\r
+               Check(hWnd, R_ESTABLISHED, a->Established);\r
+               Check(hWnd, R_UNESTABLISHED, !a->Established);\r
+       }\r
+\r
+       if (GetCapsBool(s->Hub->p->CapsList, "b_support_acl_group") == false)\r
+       {\r
+               SetText(hWnd, S_STATIC11, _UU("D_SM_EDIT_ACCESS@STATIC11_OLD"));\r
+               SetText(hWnd, S_STATIC12, _UU("D_SM_EDIT_ACCESS@STATIC12_OLD"));\r
+               SetText(hWnd, S_STATIC15, _UU("D_SM_EDIT_ACCESS@STATIC15_OLD"));\r
+       }\r
+\r
+       s->Inited = true;\r
+\r
+       SmEditAccessUpdate(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmEditAccessUpdate(HWND hWnd, SM_EDIT_ACCESS *s)\r
+{\r
+       bool ok = true;\r
+       bool tcp;\r
+       bool b;\r
+       bool check_srcmac, check_dstmac, support_mac;\r
+       bool check_state, support_check_state;\r
+       char srcmac[MAX_SIZE], srcmac_mask[MAX_SIZE], dstmac[MAX_SIZE], dstmac_mask[MAX_SIZE];\r
+       char tmp[MAX_SIZE];\r
+       wchar_t unitmp[MAX_SIZE];\r
+       ACCESS *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (s->Inited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       a = s->Access;\r
+\r
+       GetTxt(hWnd, E_NOTE, a->Note, sizeof(a->Note));\r
+\r
+       a->Discard = IsChecked(hWnd, R_DISCARD);\r
+\r
+       a->Priority = GetInt(hWnd, E_PRIORITY);\r
+       if (a->Priority == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+\r
+       b = IsChecked(hWnd, R_SRC_ALL) ? false : true;\r
+       if (b == false)\r
+       {\r
+               if (a->IsIPv6 == false)\r
+               {\r
+                       a->SrcIpAddress = 0;\r
+                       a->SrcSubnetMask = 0;\r
+               }\r
+               else\r
+               {\r
+                       Zero(&a->SrcIpAddress6, sizeof(IPV6_ADDR));\r
+                       Zero(&a->SrcSubnetMask6, sizeof(IPV6_ADDR));\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (a->IsIPv6 == false)\r
+               {\r
+                       if (IpIsFilled(hWnd, E_SRC_IP) == false || IpIsFilled(hWnd, E_SRC_MASK) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               a->SrcIpAddress = IpGet(hWnd, E_SRC_IP);\r
+                               a->SrcSubnetMask = IpGet(hWnd, E_SRC_MASK);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       char tmp1[MAX_SIZE];\r
+                       char tmp2[MAX_SIZE];\r
+\r
+                       GetTxtA(hWnd, E_SRC_IP_V6, tmp1, sizeof(tmp1));\r
+                       GetTxtA(hWnd, E_SRC_MASK_V6, tmp2, sizeof(tmp2));\r
+\r
+                       if (StrToIP6Addr(&a->SrcIpAddress6, tmp1) == false ||\r
+                               StrToMask6Addr(&a->SrcSubnetMask6, tmp2) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+       }\r
+       SetEnable(hWnd, S_SRC_IP_1, b);\r
+       SetEnable(hWnd, S_SRC_IP_2, b);\r
+       SetEnable(hWnd, S_SRC_IP_3, b);\r
+       SetEnable(hWnd, E_SRC_IP, b);\r
+       SetEnable(hWnd, E_SRC_MASK, b);\r
+       SetEnable(hWnd, E_SRC_IP_V6, b);\r
+       SetEnable(hWnd, E_SRC_MASK_V6, b);\r
+\r
+       b = IsChecked(hWnd, R_DST_ALL) ? false : true;\r
+       if (b == false)\r
+       {\r
+               if (a->IsIPv6 == false)\r
+               {\r
+                       a->DestIpAddress = 0;\r
+                       a->DestSubnetMask = 0;\r
+               }\r
+               else\r
+               {\r
+                       Zero(&a->DestIpAddress6, sizeof(IPV6_ADDR));\r
+                       Zero(&a->DestSubnetMask6, sizeof(IPV6_ADDR));\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (a->IsIPv6 == false)\r
+               {\r
+                       if (IpIsFilled(hWnd, E_DST_IP) == false || IpIsFilled(hWnd, E_DST_MASK) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               a->DestIpAddress = IpGet(hWnd, E_DST_IP);\r
+                               a->DestSubnetMask = IpGet(hWnd, E_DST_MASK);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       char tmp1[MAX_SIZE];\r
+                       char tmp2[MAX_SIZE];\r
+\r
+                       GetTxtA(hWnd, E_DST_IP_V6, tmp1, sizeof(tmp1));\r
+                       GetTxtA(hWnd, E_DST_MASK_V6, tmp2, sizeof(tmp2));\r
+\r
+                       if (StrToIP6Addr(&a->DestIpAddress6, tmp1) == false ||\r
+                               StrToMask6Addr(&a->DestSubnetMask6, tmp2) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+       }\r
+       SetEnable(hWnd, S_IP_DST_1, b);\r
+       SetEnable(hWnd, S_IP_DST_2, b);\r
+       SetEnable(hWnd, S_IP_DST_3, b);\r
+       SetEnable(hWnd, E_DST_IP, b);\r
+       SetEnable(hWnd, E_DST_MASK, b);\r
+       SetEnable(hWnd, E_DST_IP_V6, b);\r
+       SetEnable(hWnd, E_DST_MASK_V6, b);\r
+\r
+       a->Protocol = GetInt(hWnd, C_PROTOCOL);\r
+\r
+       GetTxtA(hWnd, C_PROTOCOL, tmp, sizeof(tmp));\r
+       GetTxt(hWnd, C_PROTOCOL, unitmp, sizeof(unitmp));\r
+\r
+       if (UniStrCmpi(unitmp, _UU("SM_ACCESS_PROTO_6")) == 0 || StrCmpi(tmp, _SS("SM_ACCESS_PROTO_6")) == 0)\r
+       {\r
+               a->Protocol = GetInt(hWnd, E_IP_PROTO);\r
+\r
+               if (IsEmpty(hWnd, E_IP_PROTO))\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               Enable(hWnd, S_PROTOID);\r
+               Enable(hWnd, E_IP_PROTO);\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, E_IP_PROTO);\r
+               Disable(hWnd, S_PROTOID);\r
+       }\r
+\r
+       tcp = false;\r
+       if (a->Protocol == 17 || a->Protocol == 6)\r
+       {\r
+               tcp = true;\r
+       }\r
+\r
+       SetEnable(hWnd, S_TCP_1, tcp);\r
+       SetEnable(hWnd, S_TCP_2, tcp);\r
+       SetEnable(hWnd, S_TCP_3, tcp);\r
+       SetEnable(hWnd, S_TCP_4, tcp);\r
+       SetEnable(hWnd, S_TCP_5, tcp);\r
+       SetEnable(hWnd, S_TCP_6, tcp);\r
+       SetEnable(hWnd, S_TCP_7, tcp);\r
+       SetEnable(hWnd, E_SRC_PORT_1, tcp);\r
+       SetEnable(hWnd, E_SRC_PORT_2, tcp);\r
+       SetEnable(hWnd, E_DST_PORT_1, tcp);\r
+       SetEnable(hWnd, E_DST_PORT_2, tcp);\r
+\r
+       if (tcp == false)\r
+       {\r
+               a->SrcPortEnd = a->SrcPortStart = a->DestPortEnd = a->DestPortStart = 0;\r
+       }\r
+       else\r
+       {\r
+               a->SrcPortStart = GetInt(hWnd, E_SRC_PORT_1);\r
+               a->SrcPortEnd = GetInt(hWnd, E_SRC_PORT_2);\r
+               a->DestPortStart = GetInt(hWnd, E_DST_PORT_1);\r
+               a->DestPortEnd = GetInt(hWnd, E_DST_PORT_2);\r
+\r
+               if (a->SrcPortStart != 0)\r
+               {\r
+                       if (a->SrcPortEnd != 0)\r
+                       {\r
+                               if (a->SrcPortStart > a->SrcPortEnd)\r
+                               {\r
+                                       ok = false;\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       if (a->SrcPortEnd != 0)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+\r
+               if (a->DestPortStart != 0)\r
+               {\r
+                       if (a->DestPortEnd != 0)\r
+                       {\r
+                               if (a->DestPortStart > a->DestPortEnd)\r
+                               {\r
+                                       ok = false;\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       if (a->DestPortEnd != 0)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+\r
+               if (a->DestPortEnd < a->DestPortStart)\r
+               {\r
+                       a->DestPortEnd = a->DestPortStart;\r
+               }\r
+\r
+               if (a->SrcPortEnd < a->SrcPortStart)\r
+               {\r
+                       a->SrcPortEnd = a->SrcPortStart;\r
+               }\r
+       }\r
+\r
+       a->SrcUsernameHash = a->DestUsernameHash = 0;\r
+       GetTxtA(hWnd, E_USERNAME1, a->SrcUsername, sizeof(a->SrcUsername));\r
+       GetTxtA(hWnd, E_USERNAME2, a->DestUsername, sizeof(a->DestUsername));\r
+\r
+       Trim(a->SrcUsername);\r
+       /*\r
+       if (StrLen(a->SrcUsername) != 0)\r
+       {\r
+               if (IsUserName(a->SrcUsername) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }*/\r
+\r
+       Trim(a->DestUsername);\r
+       /*\r
+       if (StrLen(a->DestUsername) != 0)\r
+       {\r
+               if (IsUserName(a->DestUsername) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }*/\r
+\r
+       support_mac = GetCapsBool(s->Hub->p->CapsList, "b_support_check_mac");\r
+\r
+       // 送信元 MAC アドレスの設定\r
+       check_srcmac = a->CheckSrcMac = support_mac && (IsChecked(hWnd, R_CHECK_SRC_MAC) ? false : true);\r
+       if(check_srcmac == false)\r
+       {\r
+               Zero(a->SrcMacAddress, sizeof(a->SrcMacAddress));\r
+               Zero(a->SrcMacMask, sizeof(a->SrcMacMask));\r
+       }\r
+       else\r
+       {\r
+               GetTxtA(hWnd, E_SRC_MAC, srcmac, sizeof(srcmac));\r
+               GetTxtA(hWnd, E_SRC_MAC_MASK, srcmac_mask, sizeof(srcmac_mask));\r
+               Trim(srcmac);\r
+               Trim(srcmac_mask);\r
+               if(StrLen(srcmac) != 0 && StrLen(srcmac_mask) != 0)\r
+               {\r
+                       UCHAR mac[6], mask[6];\r
+                       if(StrToMac(mac, srcmac) && StrToMac(mask, srcmac_mask))\r
+                       {\r
+                               Copy(a->SrcMacAddress, mac, 6);\r
+                               Copy(a->SrcMacMask, mask, 6);\r
+                       }\r
+                       else\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       SetEnable(hWnd, S_CHECK_SRC_MAC, support_mac);\r
+       SetEnable(hWnd, R_CHECK_SRC_MAC, support_mac);\r
+       SetEnable(hWnd, S_SRC_MAC, check_srcmac);\r
+       SetEnable(hWnd, S_SRC_MAC_MASK, check_srcmac);\r
+       SetEnable(hWnd, E_SRC_MAC, check_srcmac);\r
+       SetEnable(hWnd, E_SRC_MAC_MASK, check_srcmac);\r
+\r
+       // 宛先 MAC アドレスの設定\r
+       check_dstmac = a->CheckDstMac = support_mac && (IsChecked(hWnd, R_CHECK_DST_MAC) ? false : true);\r
+       if(check_dstmac == false)\r
+       {\r
+               Zero(a->DstMacAddress, sizeof(a->DstMacAddress));\r
+               Zero(a->DstMacMask, sizeof(a->DstMacMask));\r
+       }\r
+       else\r
+       {\r
+               GetTxtA(hWnd, E_DST_MAC, dstmac, sizeof(dstmac));\r
+               GetTxtA(hWnd, E_DST_MAC_MASK, dstmac_mask, sizeof(dstmac_mask));\r
+               Trim(dstmac);\r
+               Trim(dstmac_mask);\r
+               if(StrLen(dstmac) != 0 && StrLen(dstmac_mask) != 0)\r
+               {\r
+                       UCHAR mac[6], mask[6];\r
+                       if(StrToMac(mac, dstmac) && StrToMac(mask, dstmac_mask))\r
+                       {\r
+                               Copy(a->DstMacAddress, mac, 6);\r
+                               Copy(a->DstMacMask, mask, 6);\r
+                       }\r
+                       else\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       SetEnable(hWnd, S_CHECK_DST_MAC, support_mac);\r
+       SetEnable(hWnd, R_CHECK_DST_MAC, support_mac);\r
+       SetEnable(hWnd, S_DST_MAC, check_dstmac);\r
+       SetEnable(hWnd, S_DST_MAC_MASK, check_dstmac);\r
+       SetEnable(hWnd, E_DST_MAC, check_dstmac);\r
+       SetEnable(hWnd, E_DST_MAC_MASK, check_dstmac);\r
+\r
+       SetEnable(hWnd, S_MAC_NOTE, check_srcmac || check_dstmac);\r
+\r
+       // TCP コネクションの状態\r
+       support_check_state = GetCapsBool(s->Hub->p->CapsList, "b_support_check_tcp_state") && a->Protocol == 6;\r
+       SetEnable(hWnd, R_CHECK_TCP_STATE, support_check_state);\r
+       check_state = a->CheckTcpState = support_check_state && IsChecked(hWnd, R_CHECK_TCP_STATE);\r
+\r
+       a->Established = IsChecked(hWnd, R_ESTABLISHED) && check_state;\r
+       SetEnable(hWnd, R_ESTABLISHED, check_state);\r
+       SetEnable(hWnd, R_UNESTABLISHED, check_state);\r
+       if(check_state != false && IsChecked(hWnd, R_ESTABLISHED) == false && IsChecked(hWnd, R_UNESTABLISHED) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       a->Active = IsChecked(hWnd, R_DISABLE) ? false : true;\r
+\r
+       SetEnable(hWnd, B_SIMULATION, a->Discard == false && GetCapsBool(s->Hub->p->CapsList, "b_support_ex_acl"));\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK クリック\r
+void SmEditAccessOnOk(HWND hWnd, SM_EDIT_ACCESS *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmEditAccessUpdate(hWnd, s);\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+\r
+// アクセスリスト編集ダイアログ\r
+UINT SmEditAccessDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_ACCESS *s = (SM_EDIT_ACCESS *)param;\r
+       UINT ico;\r
+       ACCESS *a;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmEditAccessInit(hWnd, s);\r
+\r
+               goto REFRESH_ICON;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_PASS:\r
+               case R_DISCARD:\r
+               case E_PRIORITY:\r
+               case R_SRC_ALL:\r
+               case E_SRC_IP:\r
+               case E_SRC_MASK:\r
+               case R_DST_ALL:\r
+               case E_DST_MASK:\r
+               case E_SRC_IP_V6:\r
+               case E_SRC_MASK_V6:\r
+               case E_DST_MASK_V6:\r
+               case E_DST_IP_V6:\r
+               case C_PROTOCOL:\r
+               case E_SRC_PORT_1:\r
+               case E_SRC_PORT_2:\r
+               case E_DST_PORT_1:\r
+               case E_DST_PORT_2:\r
+               case E_USERNAME1:\r
+               case E_USERNAME2:\r
+               case R_DISABLE:\r
+               case E_IP_PROTO:\r
+               case R_CHECK_SRC_MAC:\r
+               case E_SRC_MAC:\r
+               case E_SRC_MAC_MASK:\r
+               case R_CHECK_DST_MAC:\r
+               case E_DST_MAC:\r
+               case E_DST_MAC_MASK:\r
+               case R_CHECK_TCP_STATE:\r
+               case R_ESTABLISHED:\r
+               case R_UNESTABLISHED:\r
+                       SmEditAccessUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case B_USER1:\r
+                       if (GetTxtA(hWnd, E_USERNAME1, tmp, sizeof(tmp)))\r
+                       {\r
+                               char *ret = SmSelectUserDlgEx(hWnd, s->Hub, tmp, GetCapsBool(s->Hub->p->CapsList, "b_support_acl_group"));\r
+                               if (ret == NULL)\r
+                               {\r
+                                       SetTextA(hWnd, E_USERNAME1, "");\r
+                               }\r
+                               else\r
+                               {\r
+                                       SetTextA(hWnd, E_USERNAME1, ret);\r
+                                       Free(ret);\r
+                               }\r
+                               FocusEx(hWnd, E_USERNAME1);\r
+                       }\r
+                       break;\r
+\r
+               case B_USER2:\r
+                       if (GetTxtA(hWnd, E_USERNAME2, tmp, sizeof(tmp)))\r
+                       {\r
+                               char *ret = SmSelectUserDlgEx(hWnd, s->Hub, tmp, GetCapsBool(s->Hub->p->CapsList, "b_support_acl_group"));\r
+                               if (ret == NULL)\r
+                               {\r
+                                       SetTextA(hWnd, E_USERNAME2, "");\r
+                               }\r
+                               else\r
+                               {\r
+                                       SetTextA(hWnd, E_USERNAME2, ret);\r
+                                       Free(ret);\r
+                               }\r
+                               FocusEx(hWnd, E_USERNAME2);\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmEditAccessOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_SRC_ALL:\r
+                       if (IsChecked(hWnd, R_SRC_ALL) == false)\r
+                       {\r
+                               if (s->Access->IsIPv6)\r
+                               {\r
+                                       FocusEx(hWnd, E_SRC_IP_V6);\r
+                               }\r
+                               else\r
+                               {\r
+                                       Focus(hWnd, E_SRC_IP);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case R_DST_ALL:\r
+                       if (IsChecked(hWnd, R_DST_ALL) == false)\r
+                       {\r
+                               if (s->Access->IsIPv6)\r
+                               {\r
+                                       FocusEx(hWnd, E_DST_IP_V6);\r
+                               }\r
+                               else\r
+                               {\r
+                                       Focus(hWnd, E_DST_IP);\r
+                               }\r
+                       }\r
+                       break;\r
+               case R_CHECK_SRC_MAC:\r
+                       if(IsChecked(hWnd, R_CHECK_SRC_MAC) == false)\r
+                       {\r
+                               Focus(hWnd, E_SRC_MAC);\r
+                       }\r
+                       break;\r
+               case R_CHECK_DST_MAC:\r
+                       if(IsChecked(hWnd, R_CHECK_DST_MAC) == false)\r
+                       {\r
+                               Focus(hWnd, E_DST_MAC);\r
+                       }\r
+                       break;\r
+\r
+               case R_PASS:\r
+               case R_DISCARD:\r
+               case R_DISABLE:\r
+REFRESH_ICON:\r
+                       a = s->Access;\r
+                       if (a->Discard == false && a->Active == false)\r
+                       {\r
+                               ico = ICO_PASS_DISABLE;\r
+                       }\r
+                       else if (a->Discard == false && a->Active)\r
+                       {\r
+                               ico = ICO_PASS;\r
+                       }\r
+                       else if (a->Discard && a->Active == false)\r
+                       {\r
+                               ico = ICO_DISCARD_DISABLE;\r
+                       }\r
+                       else\r
+                       {\r
+                               ico = ICO_DISCARD;\r
+                       }\r
+\r
+                       SetIcon(hWnd, S_ICON, ico);\r
+                       break;\r
+\r
+               case B_SIMULATION:\r
+                       // シミュレーション\r
+                       Dialog(hWnd, D_SM_SIMULATION, SmSimulationDlg, s);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 遅延・ジッタ・パケットロスダイアログ\r
+UINT SmSimulationDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_ACCESS *s = (SM_EDIT_ACCESS *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmSimulationInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_DELAY:\r
+               case E_JITTER:\r
+               case E_LOSS:\r
+                       SmSimulationUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       SmSimulationOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case C_DELAY:\r
+                       SmSimulationUpdate(hWnd, s);\r
+                       if (IsChecked(hWnd, C_DELAY))\r
+                       {\r
+                               FocusEx(hWnd, E_DELAY);\r
+                       }\r
+                       break;\r
+\r
+               case C_JITTER:\r
+                       SmSimulationUpdate(hWnd, s);\r
+                       if (IsChecked(hWnd, C_JITTER))\r
+                       {\r
+                               FocusEx(hWnd, E_JITTER);\r
+                       }\r
+                       break;\r
+\r
+               case C_LOSS:\r
+                       SmSimulationUpdate(hWnd, s);\r
+                       if (IsChecked(hWnd, C_LOSS))\r
+                       {\r
+                               FocusEx(hWnd, E_LOSS);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 遅延・ジッタ・パケットロスダイアログの更新\r
+void SmSimulationUpdate(HWND hWnd, SM_EDIT_ACCESS *s)\r
+{\r
+       bool b1, b2, b3;\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b1 = IsChecked(hWnd, C_DELAY);\r
+       b2 = IsChecked(hWnd, C_JITTER);\r
+       b3 = IsChecked(hWnd, C_LOSS);\r
+\r
+       SetEnable(hWnd, S_DELAY, b1);\r
+       SetEnable(hWnd, S_DELAY2, b1);\r
+       SetEnable(hWnd, E_DELAY, b1);\r
+\r
+       SetEnable(hWnd, C_JITTER, b1);\r
+\r
+       if (b1 == false)\r
+       {\r
+               b2 = false;\r
+       }\r
+\r
+       SetEnable(hWnd, S_JITTER, b2);\r
+       SetEnable(hWnd, S_JITTER2, b2);\r
+       SetEnable(hWnd, E_JITTER, b2);\r
+\r
+       SetEnable(hWnd, S_LOSS, b3);\r
+       SetEnable(hWnd, S_LOSS2, b3);\r
+       SetEnable(hWnd, E_LOSS, b3);\r
+\r
+       if (b1)\r
+       {\r
+               UINT i = GetInt(hWnd, E_DELAY);\r
+               if (i == 0 || i > HUB_ACCESSLIST_DELAY_MAX)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (b2)\r
+       {\r
+               UINT i = GetInt(hWnd, E_JITTER);\r
+               if (i == 0 || i > HUB_ACCESSLIST_JITTER_MAX)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (b3)\r
+       {\r
+               UINT i = GetInt(hWnd, E_LOSS);\r
+               if (i == 0 || i > HUB_ACCESSLIST_LOSS_MAX)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// 遅延・ジッタ・パケットロスダイアログの初期化\r
+void SmSimulationInit(HWND hWnd, SM_EDIT_ACCESS *s)\r
+{\r
+       ACCESS *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       a = s->Access;\r
+\r
+       Check(hWnd, C_DELAY, a->Delay != 0);\r
+       Check(hWnd, C_JITTER, a->Jitter != 0);\r
+       Check(hWnd, C_LOSS, a->Loss != 0);\r
+\r
+       SetIntEx(hWnd, E_DELAY, a->Delay);\r
+       if (a->Delay != 0)\r
+       {\r
+               SetIntEx(hWnd, E_JITTER, a->Jitter);\r
+       }\r
+       SetIntEx(hWnd, E_LOSS, a->Loss);\r
+\r
+       SmSimulationUpdate(hWnd, s);\r
+\r
+       if (a->Delay != 0)\r
+       {\r
+               FocusEx(hWnd, E_DELAY);\r
+       }\r
+       else\r
+       {\r
+               Focus(hWnd, C_DELAY);\r
+       }\r
+}\r
+\r
+// 遅延・ジッタ・パケットロスダイアログの保存\r
+void SmSimulationOnOk(HWND hWnd, SM_EDIT_ACCESS *s)\r
+{\r
+       ACCESS *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       a = s->Access;\r
+\r
+       a->Jitter = a->Loss = a->Delay = 0;\r
+\r
+       if (IsChecked(hWnd, C_DELAY))\r
+       {\r
+               a->Delay = GetInt(hWnd, E_DELAY);\r
+       }\r
+\r
+       if (IsChecked(hWnd, C_JITTER))\r
+       {\r
+               a->Jitter = GetInt(hWnd, E_JITTER);\r
+       }\r
+\r
+       if (IsChecked(hWnd, C_LOSS))\r
+       {\r
+               a->Loss = GetInt(hWnd, E_LOSS);\r
+       }\r
+\r
+       EndDialog(hWnd, 1);\r
+}\r
+\r
+// アクセスリストの編集\r
+bool SmEditAccess(HWND hWnd, SM_ACCESS_LIST *s, ACCESS *a)\r
+{\r
+       SM_EDIT_ACCESS edit;\r
+       bool ret;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&edit, sizeof(edit));\r
+       edit.AccessList = s;\r
+       edit.EditMode = true;\r
+       edit.Access = ZeroMalloc(sizeof(ACCESS));\r
+       edit.Hub = s->Hub;\r
+       Copy(edit.Access, a, sizeof(ACCESS));\r
+\r
+       if (edit.Access->IsIPv6 == false)\r
+       {\r
+               ret = Dialog(hWnd, D_SM_EDIT_ACCESS, SmEditAccessDlg, &edit);\r
+       }\r
+       else\r
+       {\r
+               ret = Dialog(hWnd, D_SM_EDIT_ACCESS_V6, SmEditAccessDlg, &edit);\r
+       }\r
+\r
+       if (ret)\r
+       {\r
+               Copy(a, edit.Access, sizeof(ACCESS));\r
+               Free(edit.Access);\r
+               Sort(s->AccessList);\r
+\r
+               // ID を振り直す\r
+               for (i = 0;i < LIST_NUM(s->AccessList);i++)\r
+               {\r
+                       ACCESS *a = LIST_DATA(s->AccessList, i);\r
+                       a->Id = (i + 1);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Free(edit.Access);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// アクセスリストの追加\r
+bool SmAddAccess(HWND hWnd, SM_ACCESS_LIST *s, bool ipv6)\r
+{\r
+       SM_EDIT_ACCESS edit;\r
+       bool ret;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&edit, sizeof(edit));\r
+       edit.AccessList = s;\r
+       edit.Access = ZeroMalloc(sizeof(ACCESS));\r
+       edit.Access->Active = true;\r
+       edit.Access->Priority = 0;\r
+       edit.Access->IsIPv6 = ipv6;\r
+       edit.Hub = s->Hub;\r
+\r
+       // 新しい優先順位の取得\r
+       for (i = 0;i < LIST_NUM(s->AccessList);i++)\r
+       {\r
+               ACCESS *a = LIST_DATA(s->AccessList, i);\r
+               edit.Access->Priority = MAX(edit.Access->Priority, a->Priority);\r
+       }\r
+\r
+       if (edit.Access->Priority == 0)\r
+       {\r
+               edit.Access->Priority = 900;\r
+       }\r
+\r
+       edit.Access->Priority += 100;\r
+\r
+       if (edit.Access->IsIPv6 == false)\r
+       {\r
+               ret = Dialog(hWnd, D_SM_EDIT_ACCESS, SmEditAccessDlg, &edit);\r
+       }\r
+       else\r
+       {\r
+               ret = Dialog(hWnd, D_SM_EDIT_ACCESS_V6, SmEditAccessDlg, &edit);\r
+       }\r
+\r
+       if (ret)\r
+       {\r
+               Insert(s->AccessList, edit.Access);\r
+\r
+               // ID を振り直す\r
+               for (i = 0;i < LIST_NUM(s->AccessList);i++)\r
+               {\r
+                       ACCESS *a = LIST_DATA(s->AccessList, i);\r
+                       a->Id = (i + 1);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Free(edit.Access);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// 初期化\r
+void SmAccessListInit(HWND hWnd, SM_ACCESS_LIST *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_PASS);\r
+       FormatText(hWnd, S_TITLE, s->Hub->HubName);\r
+\r
+       LvInit(hWnd, L_ACCESS_LIST);\r
+       LvInsertColumn(hWnd, L_ACCESS_LIST, 0, _UU("SM_ACCESS_COLUMN_0"), 60);\r
+       LvInsertColumn(hWnd, L_ACCESS_LIST, 1, _UU("SM_ACCESS_COLUMN_1"), 60);\r
+       LvInsertColumn(hWnd, L_ACCESS_LIST, 2, _UU("SM_ACCESS_COLUMN_2"), 60);\r
+       LvInsertColumn(hWnd, L_ACCESS_LIST, 3, _UU("SM_ACCESS_COLUMN_3"), 70);\r
+       LvInsertColumn(hWnd, L_ACCESS_LIST, 4, _UU("SM_ACCESS_COLUMN_4"), 150);\r
+       LvInsertColumn(hWnd, L_ACCESS_LIST, 5, _UU("SM_ACCESS_COLUMN_5"), 600);\r
+\r
+       LvSetStyle(hWnd, L_ACCESS_LIST, LVS_EX_GRIDLINES);\r
+\r
+       SetEnable(hWnd, B_ADD_V6, GetCapsBool(s->Hub->p->CapsList, "b_support_ipv6_acl"));\r
+\r
+       SmAccessListRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmAccessListUpdate(HWND hWnd, SM_ACCESS_LIST *s)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_ACCESS_LIST) == false || LvIsMultiMasked(hWnd, L_ACCESS_LIST))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+       SetEnable(hWnd, B_DELETE, ok);\r
+\r
+       SetEnable(hWnd, B_CREATE, LIST_NUM(s->AccessList) < MAX_ACCESSLISTS);\r
+}\r
+\r
+// 内容更新\r
+void SmAccessListRefresh(HWND hWnd, SM_ACCESS_LIST *s)\r
+{\r
+       LVB *b;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       Sort(s->AccessList);\r
+\r
+       for (i = 0;i < LIST_NUM(s->AccessList);i++)\r
+       {\r
+               ACCESS *a = LIST_DATA(s->AccessList, i);\r
+               char tmp[MAX_SIZE];\r
+               UINT ico = ICO_PASS;\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               GetAccessListStr(tmp, sizeof(tmp), a);\r
+               UniToStru(tmp1, a->Priority);\r
+               StrToUni(tmp2, sizeof(tmp2), tmp);\r
+\r
+               if (a->Discard == false && a->Active == false)\r
+               {\r
+                       ico = ICO_PASS_DISABLE;\r
+               }\r
+               else if (a->Discard == false && a->Active)\r
+               {\r
+                       ico = ICO_PASS;\r
+               }\r
+               else if (a->Discard && a->Active == false)\r
+               {\r
+                       ico = ICO_DISCARD_DISABLE;\r
+               }\r
+               else\r
+               {\r
+                       ico = ICO_DISCARD;\r
+               }\r
+\r
+               UniToStru(tmp3, a->Id);\r
+\r
+               LvInsertAdd(b, ico, (void *)a, 6,\r
+                       tmp3,\r
+                       a->Discard ? _UU("SM_ACCESS_DISCARD") : _UU("SM_ACCESS_PASS"),\r
+                       a->Active ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"),\r
+                       tmp1,\r
+                       a->Note,\r
+                       tmp2);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_ACCESS_LIST);\r
+       LvSortEx(hWnd, L_ACCESS_LIST, 0, false, true);\r
+\r
+       SmAccessListUpdate(hWnd, s);\r
+}\r
+\r
+// アクセスリストダイアログプロシージャ\r
+UINT SmAccessListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_ACCESS_LIST *s = (SM_ACCESS_LIST *)param;\r
+       NMHDR *n;\r
+       ACCESS *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmAccessListInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_ADD:\r
+                       // 追加 (IPv4)\r
+                       if (SmAddAccess(hWnd, s, false))\r
+                       {\r
+                               SmAccessListRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_ADD_V6:\r
+                       // 追加 (IPv6)\r
+                       if (SmAddAccess(hWnd, s, true))\r
+                       {\r
+                               SmAccessListRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // 編集\r
+                       a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));\r
+                       if (a != NULL)\r
+                       {\r
+                               if (SmEditAccess(hWnd, s, a))\r
+                               {\r
+                                       SmAccessListRefresh(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       a = LvGetParam(hWnd, L_ACCESS_LIST, LvGetSelected(hWnd, L_ACCESS_LIST));\r
+                       if (a != NULL)\r
+                       {\r
+                               UINT i;\r
+                               if (IsInList(s->AccessList, a))\r
+                               {\r
+                                       Delete(s->AccessList, a);\r
+                                       Free(a);\r
+                                       // ID を振り直す\r
+                                       for (i = 0;i < LIST_NUM(s->AccessList);i++)\r
+                                       {\r
+                                               ACCESS *a = LIST_DATA(s->AccessList, i);\r
+                                               a->Id = (i + 1);\r
+                                       }\r
+                                       SmAccessListRefresh(hWnd, s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_SAVE:\r
+                       // 保存\r
+                       {\r
+                               UINT i;\r
+                               bool ok;\r
+                               // アクセスリストを保存する\r
+                               RPC_ENUM_ACCESS_LIST t;\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+                               t.NumAccess = LIST_NUM(s->AccessList);\r
+                               t.Accesses = ZeroMalloc(sizeof(ACCESS) * t.NumAccess);\r
+                               for (i = 0;i < LIST_NUM(s->AccessList);i++)\r
+                               {\r
+                                       ACCESS *access = LIST_DATA(s->AccessList, i);\r
+                                       Copy(&t.Accesses[i], access, sizeof(ACCESS));\r
+                               }\r
+\r
+                               ok = CALL(hWnd, ScSetAccessList(s->Rpc, &t));\r
+                               FreeRpcEnumAccessList(&t);\r
+                               if (ok)\r
+                               {\r
+                                       EndDialog(hWnd, true);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_ACCESS_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmAccessListUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_ACCESS_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+// アクセスリストダイアログ\r
+void SmAccessListDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       SM_ACCESS_LIST a;\r
+       UINT i;\r
+       RPC_ENUM_ACCESS_LIST t;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       a.Hub = s;\r
+       a.Rpc = s->Rpc;\r
+\r
+       // アクセスリストの取得\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       if (CALL(hWnd, ScEnumAccess(s->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       a.AccessList = NewListFast(CmpAccessList);\r
+       // リストに追加\r
+       for (i = 0;i < t.NumAccess;i++)\r
+       {\r
+               ACCESS *access = ZeroMalloc(sizeof(ACCESS));\r
+               Copy(access, &t.Accesses[i], sizeof(ACCESS));\r
+\r
+               Add(a.AccessList, access);\r
+       }\r
+\r
+       // ソート\r
+       Sort(a.AccessList);\r
+       FreeRpcEnumAccessList(&t);\r
+\r
+       // ダイアログ表示\r
+       ret = Dialog(hWnd, D_SM_ACCESS_LIST, SmAccessListProc, &a);\r
+\r
+       for (i = 0;i < LIST_NUM(a.AccessList);i++)\r
+       {\r
+               ACCESS *access = LIST_DATA(a.AccessList, i);\r
+               Free(access);\r
+       }\r
+       ReleaseList(a.AccessList);\r
+}\r
+\r
+// 初期化\r
+void SmEditGroupDlgInit(HWND hWnd, SM_EDIT_GROUP *g)\r
+{\r
+       RPC_SET_GROUP *group;\r
+       LVB *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || g == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_GROUP);\r
+\r
+       group = &g->SetGroup;\r
+\r
+       if (g->EditMode == false)\r
+       {\r
+               SetText(hWnd, 0, _UU("SM_EDIT_GROUP_CAPTION_1"));\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_GROUP_CAPTION_2"), group->Name);\r
+               SetText(hWnd, 0, tmp);\r
+       }\r
+\r
+       SetTextA(hWnd, E_GROUPNAME, group->Name);\r
+       SetText(hWnd, E_REALNAME, group->Realname);\r
+       SetText(hWnd, E_NOTE, group->Note);\r
+\r
+       g->Inited = true;\r
+\r
+       if (g->EditMode == false)\r
+       {\r
+               Disable(hWnd, L_STATUS);\r
+       }\r
+       else\r
+       {\r
+               LvInit(hWnd, L_STATUS);\r
+               LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 0);\r
+               LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 0);\r
+               LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);\r
+\r
+               b = LvInsertStart();\r
+\r
+               SmInsertTrafficInfo(b, &group->Traffic);\r
+\r
+               LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+               LvAutoSize(hWnd, L_STATUS);\r
+       }\r
+\r
+       Check(hWnd, R_POLICY, group->Policy != NULL);\r
+\r
+       if (g->EditMode)\r
+       {\r
+               Disable(hWnd, E_GROUPNAME);\r
+               FocusEx(hWnd, E_REALNAME);\r
+       }\r
+\r
+       SmEditGroupDlgUpdate(hWnd, g);\r
+}\r
+\r
+// 更新\r
+void SmEditGroupDlgUpdate(HWND hWnd, SM_EDIT_GROUP *g)\r
+{\r
+       bool ok = true;\r
+       RPC_SET_GROUP *group;\r
+       // 引数チェック\r
+       if (hWnd == NULL || g == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (g->Inited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       group = &g->SetGroup;\r
+\r
+       GetTxtA(hWnd, E_GROUPNAME, group->Name, sizeof(group->Name));\r
+       Trim(group->Name);\r
+\r
+       if (IsUserName(group->Name) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       GetTxt(hWnd, E_REALNAME, group->Realname, sizeof(group->Realname));\r
+       UniTrim(group->Realname);\r
+\r
+       GetTxt(hWnd, E_NOTE, group->Note, sizeof(group->Note));\r
+       UniTrim(group->Note);\r
+\r
+       SetEnable(hWnd, B_POLICY, IsChecked(hWnd, R_POLICY));\r
+\r
+       if (IsChecked(hWnd, R_POLICY))\r
+       {\r
+               if (group->Policy == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK\r
+void SmEditGroupDlgOnOk(HWND hWnd, SM_EDIT_GROUP *g)\r
+{\r
+       RPC_SET_GROUP *group;\r
+       RPC_SET_GROUP t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || g == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmEditGroupDlgUpdate(hWnd, g);\r
+\r
+       group = &g->SetGroup;\r
+\r
+       if (IsChecked(hWnd, R_POLICY) == false)\r
+       {\r
+               if (group->Policy != NULL)\r
+               {\r
+                       Free(group->Policy);\r
+                       group->Policy = NULL;\r
+               }\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       Copy(&t, group, sizeof(RPC_SET_GROUP));\r
+\r
+       t.Policy = ClonePolicy(group->Policy);\r
+\r
+       if (g->EditMode == false)\r
+       {\r
+               if (CALL(hWnd, ScCreateGroup(g->Rpc, &t)) == false)\r
+               {\r
+                       FocusEx(hWnd, E_GROUPNAME);\r
+                       return;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (CALL(hWnd, ScSetGroup(g->Rpc, &t)) == false)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       FreeRpcSetGroup(&t);\r
+\r
+       if (g->EditMode == false)\r
+       {\r
+               MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_GROUP_CREATED"), group->Name);\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// グループ編集ダイアログプロシージャ\r
+UINT SmEditGroupDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_GROUP *g = (SM_EDIT_GROUP *)param;\r
+       wchar_t tmp[MAX_SIZE];\r
+       NMHDR *n;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmEditGroupDlgInit(hWnd, g);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_GROUPNAME:\r
+               case E_REALNAME:\r
+               case E_NOTE:\r
+               case R_POLICY:\r
+                       SmEditGroupDlgUpdate(hWnd, g);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmEditGroupDlgOnOk(hWnd, g);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_POLICY:\r
+                       if (IsChecked(hWnd, R_POLICY))\r
+                       {\r
+                               Focus(hWnd, B_POLICY);\r
+                       }\r
+                       break;\r
+\r
+               case B_POLICY:\r
+                       // セキュリティ ポリシー\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_GROUP_POLICY_CAPTION"), g->SetGroup.Name);\r
+                       if (g->SetGroup.Policy == NULL)\r
+                       {\r
+                               POLICY *p = ClonePolicy(GetDefaultPolicy());\r
+                               if (SmPolicyDlgEx2(hWnd, p, tmp, false, g->p->PolicyVer))\r
+                               {\r
+                                       g->SetGroup.Policy = p;\r
+                                       SmEditGroupDlgUpdate(hWnd, g);\r
+                               }\r
+                               else\r
+                               {\r
+                                       Free(p);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               SmPolicyDlgEx2(hWnd, g->SetGroup.Policy, tmp, false, g->p->PolicyVer);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_STATUS:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmEditGroupDlgUpdate(hWnd, g);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// グループ編集ダイアログ\r
+bool SmEditGroupDlg(HWND hWnd, SM_GROUP *s, char *name)\r
+{\r
+       SM_EDIT_GROUP g;\r
+       RPC_SET_GROUP *group;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&g, sizeof(g));\r
+       g.EditMode = true;\r
+       g.Hub = s->Hub;\r
+       g.p = s->p;\r
+       g.Rpc = s->Rpc;\r
+\r
+       group = &g.SetGroup;\r
+\r
+       StrCpy(group->Name, sizeof(group->Name), name);\r
+       StrCpy(group->HubName, sizeof(group->HubName), s->Hub->HubName);\r
+\r
+       if (CALL(hWnd, ScGetGroup(s->Rpc, group)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       ret = Dialog(hWnd, D_SM_EDIT_GROUP, SmEditGroupDlgProc, &g);\r
+\r
+       FreeRpcSetGroup(group);\r
+\r
+       return ret;\r
+}\r
+\r
+// グループ作成ダイアログ\r
+bool SmCreateGroupDlg(HWND hWnd, SM_GROUP *s)\r
+{\r
+       SM_EDIT_GROUP g;\r
+       RPC_SET_GROUP *group;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&g, sizeof(g));\r
+       g.EditMode = false;\r
+       g.Hub = s->Hub;\r
+       g.p = s->p;\r
+       g.Rpc = s->Rpc;\r
+\r
+       group = &g.SetGroup;\r
+\r
+       StrCpy(group->HubName, sizeof(group->HubName), s->Hub->HubName);\r
+\r
+       ret = Dialog(hWnd, D_SM_EDIT_GROUP, SmEditGroupDlgProc, &g);\r
+\r
+       FreeRpcSetGroup(group);\r
+\r
+       return ret;\r
+}\r
+\r
+// 初期化\r
+void SmGroupListDlgInit(HWND hWnd, SM_GROUP *s)\r
+{\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_GROUP);\r
+\r
+       // カラム初期化\r
+       LvInit(hWnd, L_GROUP);\r
+       LvInsertColumn(hWnd, L_GROUP, 0, _UU("SM_GROUPLIST_NAME"), 130);\r
+       LvInsertColumn(hWnd, L_GROUP, 1, _UU("SM_GROUPLIST_REALNAME"), 130);\r
+       LvInsertColumn(hWnd, L_GROUP, 2, _UU("SM_GROUPLIST_NOTE"), 170);\r
+       LvInsertColumn(hWnd, L_GROUP, 3, _UU("SM_GROUPLIST_NUMUSERS"), 80);\r
+       LvSetStyle(hWnd, L_GROUP, LVS_EX_GRIDLINES);\r
+\r
+       FormatText(hWnd, S_TITLE, s->Hub->HubName);\r
+\r
+       SmGroupListDlgRefresh(hWnd, s);\r
+\r
+       if (s->SelectMode)\r
+       {\r
+               SetStyle(hWnd, L_GROUP, LVS_SINGLESEL);\r
+       }\r
+\r
+       if (s->SelectMode)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               SetText(hWnd, IDOK, _UU("SM_SELECT_GROUP"));\r
+\r
+               if (s->SelectedGroupName != NULL)\r
+               {\r
+                       UINT i;\r
+                       StrToUni(tmp, sizeof(tmp), s->SelectedGroupName);\r
+                       i = LvSearchStr(hWnd, L_GROUP, 0, tmp);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               LvSelect(hWnd, L_GROUP, i);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+// コントロール更新\r
+void SmGroupListDlgUpdate(HWND hWnd, SM_GROUP *s)\r
+{\r
+       bool ok = true;\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_GROUP) == false || LvIsMultiMasked(hWnd, L_GROUP))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+       SetEnable(hWnd, B_USER, ok);\r
+       SetEnable(hWnd, B_STATUS, ok);\r
+\r
+       if (s->SelectMode == false)\r
+       {\r
+               SetEnable(hWnd, B_DELETE, ok);\r
+       }\r
+       else\r
+       {\r
+               SetEnable(hWnd, B_DELETE, false);\r
+               SetEnable(hWnd, B_USER, false);\r
+               SetText(hWnd, IDCANCEL, _UU("SM_SELECT_NO_GROUP"));\r
+       }\r
+}\r
+\r
+// 内容更新\r
+void SmGroupListDlgRefresh(HWND hWnd, SM_GROUP *s)\r
+{\r
+       RPC_ENUM_GROUP t;\r
+       UINT i;\r
+       LVB *b;\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumGroup(s->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumGroup;i++)\r
+       {\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               RPC_ENUM_GROUP_ITEM *e = &t.Groups[i];\r
+\r
+               StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+               UniToStru(tmp2, e->NumUsers);\r
+\r
+               LvInsertAdd(b, e->DenyAccess == false ? ICO_GROUP : ICO_GROUP_DENY,\r
+                       NULL, 4, tmp1, e->Realname, e->Note, tmp2);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_GROUP);\r
+\r
+       SmGroupListDlgUpdate(hWnd, s);\r
+\r
+       FreeRpcEnumGroup(&t);\r
+}\r
+\r
+// グループリストダイアログプロシージャ\r
+UINT SmGroupListDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_GROUP *s = (SM_GROUP *)param;\r
+       NMHDR *n;\r
+       wchar_t *tmp;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmGroupListDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_CREATE:\r
+                       // 新規作成\r
+                       if (SmCreateGroupDlg(hWnd, s))\r
+                       {\r
+                               SmGroupListDlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case IDOK:\r
+                       // 編集\r
+                       tmp = LvGetSelectedStr(hWnd, L_GROUP, 0);\r
+                       if (tmp != NULL)\r
+                       {\r
+                               char name[MAX_SIZE];\r
+                               UniToStr(name, sizeof(name), tmp);\r
+\r
+                               if (s->SelectMode == false)\r
+                               {\r
+                                       if (SmEditGroupDlg(hWnd, s, name))\r
+                                       {\r
+                                               SmGroupListDlgRefresh(hWnd, s);\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       s->SelectedGroupName = CopyStr(name);\r
+                                       EndDialog(hWnd, true);\r
+                               }\r
+                               Free(tmp);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       tmp = LvGetSelectedStr(hWnd, L_GROUP, 0);\r
+                       if (tmp != NULL)\r
+                       {\r
+                               char name[MAX_SIZE];\r
+                               RPC_DELETE_USER t;\r
+                               UniToStr(name, sizeof(name), tmp);\r
+\r
+                               if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                                       _UU("SM_GROUP_DELETE_MSG"), name) == IDYES)\r
+                               {\r
+                                       Zero(&t, sizeof(t));\r
+                                       StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+                                       StrCpy(t.Name, sizeof(t.Name), name);\r
+\r
+                                       if (CALL(hWnd, ScDeleteGroup(s->Rpc, &t)))\r
+                                       {\r
+                                               SmGroupListDlgRefresh(hWnd, s);\r
+                                       }\r
+                               }\r
+\r
+                               Free(tmp);\r
+                       }\r
+                       break;\r
+\r
+               case B_USER:\r
+                       // メンバ一覧\r
+                       tmp = LvGetSelectedStr(hWnd, L_GROUP, 0);\r
+                       if (tmp != NULL)\r
+                       {\r
+                               char name[MAX_SIZE];\r
+                               UniToStr(name, sizeof(name), tmp);\r
+                               SmUserListDlgEx(hWnd, s->Hub, name, false);\r
+                               Free(tmp);\r
+                       }\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 最新情報に更新\r
+                       SmGroupListDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_GROUP:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmGroupListDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_GROUP);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループリストダイアログ (選択モード)\r
+char *SmSelectGroupDlg(HWND hWnd, SM_HUB *s, char *default_name)\r
+{\r
+       SM_GROUP g;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&g, sizeof(g));\r
+       g.Hub = s;\r
+       g.p = s->p;\r
+       g.Rpc = s->Rpc;\r
+       g.SelectMode = true;\r
+       g.SelectedGroupName = default_name;\r
+\r
+       if (Dialog(hWnd, D_SM_GROUP, SmGroupListDlgProc, &g) == false)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       return g.SelectedGroupName;\r
+}\r
+\r
+// グループリストダイアログ\r
+void SmGroupListDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       SM_GROUP g;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&g, sizeof(g));\r
+       g.Hub = s;\r
+       g.p = s->p;\r
+       g.Rpc = s->Rpc;\r
+       g.SelectMode = false;\r
+\r
+       Dialog(hWnd, D_SM_GROUP, SmGroupListDlgProc, &g);\r
+}\r
+\r
+// ユーザー情報の更新\r
+bool SmRefreshUserInfo(HWND hWnd, SM_SERVER *s, void *param)\r
+{\r
+       RPC_SET_USER t;\r
+       SM_USER_INFO *p = (SM_USER_INFO *)param;\r
+       LVB *b;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char *username;\r
+\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL || param == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       username = p->Username;\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), p->Hub->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), username);\r
+\r
+       if (CALL(hWnd, ScGetUser(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.Name);\r
+       LvInsertAdd(b, ICO_USER, NULL, 2, _UU("SM_USERINFO_NAME"), tmp);\r
+\r
+       if (StrLen(t.GroupName) != 0)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), t.GroupName);\r
+               LvInsertAdd(b, ICO_GROUP, NULL, 2, _UU("SM_USERINFO_GROUP"), tmp);\r
+       }\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime), NULL);\r
+       LvInsertAdd(b, ICO_USER_ADMIN, NULL, 2, _UU("SM_USERINFO_CREATE"), tmp);\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.UpdatedTime), NULL);\r
+       LvInsertAdd(b, ICO_USER_ADMIN, NULL, 2, _UU("SM_USERINFO_UPDATE"), tmp);\r
+\r
+       if (t.ExpireTime != 0)\r
+       {\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ExpireTime), NULL);\r
+               LvInsertAdd(b, ICO_WARNING, NULL, 2, _UU("SM_USERINFO_EXPIRE"), tmp);\r
+       }\r
+\r
+       SmInsertTrafficInfo(b, &t.Traffic);\r
+\r
+       UniToStru(tmp, t.NumLogin);\r
+       LvInsertAdd(b, ICO_LINK, NULL, 2, _UU("SM_USERINFO_NUMLOGIN"), tmp);\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// 初期化\r
+void SmPolicyDlgInit(HWND hWnd, SM_POLICY *s)\r
+{\r
+       CM_POLICY cp;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_MACHINE);\r
+       SetText(hWnd, 0, s->Caption);\r
+       SetText(hWnd, S_TITLE, s->Caption);\r
+       DlgFont(hWnd, S_BOLD, 10, true);\r
+       DlgFont(hWnd, S_BOLD2, 10, true);\r
+\r
+       DlgFont(hWnd, S_POLICY_TITLE, 11, false);\r
+       DlgFont(hWnd, E_POLICY_DESCRIPTION, 10, false);\r
+\r
+       Zero(&cp, sizeof(cp));\r
+       cp.Policy = s->Policy;\r
+       cp.Extension = true;\r
+\r
+       LvInit(hWnd, L_POLICY);\r
+       LvInsertColumn(hWnd, L_POLICY, 0, _UU("POL_TITLE_STR"), 250);\r
+       LvInsertColumn(hWnd, L_POLICY, 1, _UU("POL_VALUE_STR"), 150);\r
+       LvSetStyle(hWnd, L_POLICY, LVS_EX_GRIDLINES);\r
+\r
+       CmPolicyDlgPrintEx2(hWnd, &cp, s->CascadeMode, s->Ver);\r
+\r
+       LvSelect(hWnd, L_POLICY, 0);\r
+\r
+       s->Inited = true;\r
+       SmPolicyDlgUpdate(hWnd, s);\r
+}\r
+\r
+// 更新\r
+void SmPolicyDlgUpdate(HWND hWnd, SM_POLICY *s)\r
+{\r
+       bool ok = true;\r
+       bool value_changed = false;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (s->Inited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       i = LvGetSelected(hWnd, L_POLICY);\r
+       if (i != INFINITE)\r
+       {\r
+               i = (UINT)LvGetParam(hWnd, L_POLICY, i);\r
+       }\r
+       if (i == INFINITE || i >= NUM_POLICY_ITEM)\r
+       {\r
+               SetText(hWnd, S_POLICY_TITLE, _UU("SM_POLICY_INIT_TITLE"));\r
+               SetText(hWnd, E_POLICY_DESCRIPTION, L"");\r
+               Disable(hWnd, S_POLICY_TITLE);\r
+               Disable(hWnd, S_BOLD);\r
+               Hide(hWnd, S_BOLD2);\r
+               Hide(hWnd, R_ENABLE);\r
+               Hide(hWnd, R_DISABLE);\r
+               Hide(hWnd, R_DEFINE);\r
+               Hide(hWnd, E_VALUE);\r
+               Hide(hWnd, S_TANI);\r
+               Hide(hWnd, S_LIMIT);\r
+       }\r
+       else\r
+       {\r
+               POLICY_ITEM *item = &policy_item[i];\r
+               bool changed = false;\r
+               wchar_t *tmp = GetText(hWnd, S_POLICY_TITLE);\r
+               if (UniStrCmp(tmp, GetPolicyTitle(i)) != 0)\r
+               {\r
+                       changed = true;\r
+               }\r
+               Free(tmp);\r
+               SetText(hWnd, S_POLICY_TITLE, GetPolicyTitle(i));\r
+               SetText(hWnd, E_POLICY_DESCRIPTION, GetPolicyDescription(i));\r
+               Enable(hWnd, S_POLICY_TITLE);\r
+               Enable(hWnd, S_BOLD);\r
+               Show(hWnd, S_BOLD2);\r
+\r
+               if (item->TypeInt == false)\r
+               {\r
+                       Show(hWnd, R_ENABLE);\r
+                       Show(hWnd, R_DISABLE);\r
+                       Hide(hWnd, R_DEFINE);\r
+                       Hide(hWnd, E_VALUE);\r
+                       Hide(hWnd, S_TANI);\r
+                       Hide(hWnd, S_LIMIT);\r
+\r
+                       if (changed)\r
+                       {\r
+                               if (POLICY_BOOL(s->Policy, i))\r
+                               {\r
+                                       Check(hWnd, R_ENABLE, true);\r
+                                       Check(hWnd, R_DISABLE, false);\r
+                               }\r
+                               else\r
+                               {\r
+                                       Check(hWnd, R_ENABLE, false);\r
+                                       Check(hWnd, R_DISABLE, true);\r
+                               }\r
+                       }\r
+\r
+                       if ((!(POLICY_BOOL(s->Policy, i))) != (!(IsChecked(hWnd, R_ENABLE))))\r
+                       {\r
+                               POLICY_BOOL(s->Policy, i) = IsChecked(hWnd, R_ENABLE);\r
+                               value_changed = true;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       UINT value;\r
+                       if (item->AllowZero)\r
+                       {\r
+                               if (changed)\r
+                               {\r
+                                       Check(hWnd, R_DEFINE, POLICY_INT(s->Policy, i) != 0);\r
+                                       Enable(hWnd, R_DEFINE);\r
+                                       SetIntEx(hWnd, E_VALUE, POLICY_INT(s->Policy, i));\r
+                               }\r
+\r
+                               SetEnable(hWnd, E_VALUE, IsChecked(hWnd, R_DEFINE));\r
+                               SetEnable(hWnd, S_TANI, IsChecked(hWnd, R_DEFINE));\r
+                               SetEnable(hWnd, S_LIMIT, IsChecked(hWnd, R_DEFINE));\r
+                       }\r
+                       else\r
+                       {\r
+                               if (changed)\r
+                               {\r
+                                       Check(hWnd, R_DEFINE, true);\r
+                                       Disable(hWnd, R_DEFINE);\r
+                                       SetInt(hWnd, E_VALUE, POLICY_INT(s->Policy, i));\r
+                               }\r
+\r
+                               SetEnable(hWnd, E_VALUE, IsChecked(hWnd, R_DEFINE));\r
+                               SetEnable(hWnd, S_TANI, IsChecked(hWnd, R_DEFINE));\r
+                               SetEnable(hWnd, S_LIMIT, IsChecked(hWnd, R_DEFINE));\r
+                       }\r
+\r
+                       UniReplaceStrEx(tmp, sizeof(tmp), _UU(policy_item[i].FormatStr),\r
+                               L"%u ", L"", false);\r
+                       UniReplaceStrEx(tmp, sizeof(tmp), tmp,\r
+                               L"%u", L"", false);\r
+\r
+                       SetText(hWnd, S_TANI, tmp);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_LIMIT_STR"), policy_item[i].MinValue, policy_item[i].MaxValue);\r
+                       SetText(hWnd, S_LIMIT, tmp);\r
+\r
+                       Hide(hWnd, R_ENABLE);\r
+                       Hide(hWnd, R_DISABLE);\r
+                       Show(hWnd, E_VALUE);\r
+                       Show(hWnd, R_DEFINE);\r
+                       Show(hWnd, S_TANI);\r
+                       Show(hWnd, S_LIMIT);\r
+\r
+                       value = GetInt(hWnd, E_VALUE);\r
+\r
+                       if (item->AllowZero && (IsChecked(hWnd, R_DEFINE) == false))\r
+                       {\r
+                               value = 0;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (value < policy_item[i].MinValue || value > policy_item[i].MaxValue)\r
+                               {\r
+                                       ok = false;\r
+                               }\r
+                       }\r
+\r
+                       if (ok)\r
+                       {\r
+                               if (POLICY_INT(s->Policy, i) != value)\r
+                               {\r
+                                       POLICY_INT(s->Policy, i) = value;\r
+                                       value_changed = true;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+       SetEnable(hWnd, L_POLICY, ok);\r
+\r
+       if (value_changed)\r
+       {\r
+               CM_POLICY cp;\r
+               Zero(&cp, sizeof(cp));\r
+               cp.Policy = s->Policy;\r
+               cp.Extension = true;\r
+\r
+               CmPolicyDlgPrintEx(hWnd, &cp, s->CascadeMode);\r
+       }\r
+}\r
+\r
+// 確定\r
+void SmPolicyDlgOk(HWND hWnd, SM_POLICY *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// ポリシー ダイアログ ボックス プロシージャ\r
+UINT SmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_POLICY *s = (SM_POLICY *)param;\r
+       NMHDR *n;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmPolicyDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_DEFINE:\r
+               case R_ENABLE:\r
+               case R_DISABLE:\r
+               case E_VALUE:\r
+                       SmPolicyDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmPolicyDlgOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_DEFINE:\r
+                       if (IsChecked(hWnd, R_DEFINE))\r
+                       {\r
+                               FocusEx(hWnd, E_VALUE);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_POLICY:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmPolicyDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ポリシー ダイアログ ボックスの表示\r
+bool SmPolicyDlg(HWND hWnd, POLICY *p, wchar_t *caption)\r
+{\r
+       return SmPolicyDlgEx(hWnd, p, caption, false);\r
+}\r
+bool SmPolicyDlgEx(HWND hWnd, POLICY *p, wchar_t *caption, bool cascade_mode)\r
+{\r
+       return SmPolicyDlgEx2(hWnd, p, caption, cascade_mode, POLICY_CURRENT_VERSION);\r
+}\r
+bool SmPolicyDlgEx2(HWND hWnd, POLICY *p, wchar_t *caption, bool cascade_mode, UINT ver)\r
+{\r
+       SM_POLICY s;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (caption == NULL)\r
+       {\r
+               caption = _UU("SM_POLICY_DEF_CAPTION");\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       s.Caption = caption;\r
+       s.Policy = ClonePolicy(p);\r
+       s.CascadeMode = cascade_mode;\r
+       s.Ver = ver;\r
+\r
+       ret = Dialog(hWnd, D_SM_POLICY, SmPolicyDlgProc, &s);\r
+\r
+       if (ret)\r
+       {\r
+               Copy(p, s.Policy, sizeof(POLICY));\r
+       }\r
+\r
+       Free(s.Policy);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザー編集確定\r
+void SmEditUserDlgOk(HWND hWnd, SM_EDIT_USER *s)\r
+{\r
+       RPC_SET_USER t;\r
+       RPC_SET_USER *u;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmEditUserDlgUpdate(hWnd, s);\r
+\r
+       Zero(&t, sizeof(t));\r
+       u = &s->SetUser;\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), u->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), u->Name);\r
+       StrCpy(t.GroupName, sizeof(t.GroupName), u->GroupName);\r
+       UniStrCpy(t.Realname, sizeof(t.Realname), u->Realname);\r
+       UniStrCpy(t.Note, sizeof(t.Note), u->Note);\r
+       t.ExpireTime = u->ExpireTime;\r
+       t.AuthType = u->AuthType;\r
+       t.AuthData = CopyAuthData(u->AuthData, t.AuthType);\r
+\r
+       if (IsChecked(hWnd, R_POLICY))\r
+       {\r
+               t.Policy = ClonePolicy(u->Policy);\r
+       }\r
+       else\r
+       {\r
+               t.Policy = NULL;\r
+       }\r
+\r
+       if (s->EditMode == false)\r
+       {\r
+               if (CALL(hWnd, ScCreateUser(s->Rpc, &t)) == false)\r
+               {\r
+                       FocusEx(hWnd, E_USERNAME);\r
+                       return;\r
+               }\r
+               FreeRpcSetUser(&t);\r
+\r
+               MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_USER_CREEATE_OK"), u->Name);\r
+       }\r
+       else\r
+       {\r
+               if (CALL(hWnd, ScSetUser(s->Rpc, &t)) == false)\r
+               {\r
+                       FocusEx(hWnd, E_REALNAME);\r
+                       return;\r
+               }\r
+               FreeRpcSetUser(&t);\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// ユーザー編集初期化\r
+void SmEditUserDlgInit(HWND hWnd, SM_EDIT_USER *s)\r
+{\r
+       RPC_SET_USER *u;\r
+       wchar_t tmp[MAX_SIZE];\r
+       UINT i;\r
+       UINT icons[6] = {ICO_PASS, ICO_KEY, ICO_CERT, ICO_SERVER_CERT,\r
+               ICO_TOWER, ICO_LINK};\r
+       RECT rect;\r
+\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_USER);\r
+\r
+       u = &s->SetUser;\r
+\r
+       // カラム初期化\r
+       LvInit(hWnd, L_AUTH);\r
+       LvSetStyle(hWnd, L_AUTH, LVS_EX_GRIDLINES);\r
+\r
+       GetClientRect(DlgItem(hWnd, L_AUTH), &rect);\r
+       LvInsertColumn(hWnd, L_AUTH, 0, L"Name", rect.right - rect.left);\r
+\r
+       for (i = 0;i < 6;i++)\r
+       {\r
+               LvInsert(hWnd, L_AUTH, icons[i], (void *)i, 1, SmGetAuthTypeStr(i));\r
+       }\r
+\r
+       // ユーザー名など\r
+       SetTextA(hWnd, E_USERNAME, u->Name);\r
+       SetText(hWnd, E_REALNAME, u->Realname);\r
+       SetText(hWnd, E_NOTE, u->Note);\r
+\r
+\r
+       // 有効期限\r
+       if (u->ExpireTime == 0)\r
+       {\r
+               SYSTEMTIME st;\r
+               Check(hWnd, R_EXPIRES, false);\r
+               GetLocalTime(&st);\r
+               UINT64ToSystem(&st, SystemToUINT64(&st) + (60 * 60 * 24 * 1000));\r
+               st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;\r
+               DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_DATE), GDT_VALID, &st);\r
+               DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_TIME), GDT_VALID, &st);\r
+       }\r
+       else\r
+       {\r
+               SYSTEMTIME st;\r
+               UINT64ToSystem(&st, SystemToLocal64(u->ExpireTime));\r
+               Check(hWnd, R_EXPIRES, true);\r
+               DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_DATE), GDT_VALID, &st);\r
+               DateTime_SetSystemtime(DlgItem(hWnd, E_EXPIRES_TIME), GDT_VALID, &st);\r
+       }\r
+\r
+       SetStyle(hWnd, E_EXPIRES_DATE, DTS_LONGDATEFORMAT);\r
+       SetWindowLong(DlgItem(hWnd, E_EXPIRES_TIME), GWL_STYLE, WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | DTS_RIGHTALIGN | DTS_TIMEFORMAT | DTS_UPDOWN);\r
+\r
+       // グループ名\r
+       SetTextA(hWnd, E_GROUP, u->GroupName);\r
+\r
+       // 認証方法\r
+       LvSelect(hWnd, L_AUTH, u->AuthType);\r
+\r
+       SetText(hWnd, S_CERT_INFO, _UU("SM_EDIT_USER_CERT_INFO"));\r
+\r
+       switch (u->AuthType)\r
+       {\r
+       case AUTHTYPE_PASSWORD:\r
+               if (s->EditMode)\r
+               {\r
+                       SetTextA(hWnd, E_PASSWORD1, HIDDEN_PASSWORD);\r
+                       SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_USERCERT:\r
+               SmGetCertInfoStr(tmp, sizeof(tmp), ((AUTHUSERCERT *)u->AuthData)->UserX);\r
+               break;\r
+\r
+       case AUTHTYPE_ROOTCERT:\r
+               if (u->AuthData != NULL)\r
+               {\r
+                       AUTHROOTCERT *c = (AUTHROOTCERT *)u->AuthData;\r
+                       if (c->CommonName != NULL && UniStrLen(c->CommonName) != 0)\r
+                       {\r
+                               Check(hWnd, R_CN, true);\r
+                               SetText(hWnd, E_CN, c->CommonName);\r
+                       }\r
+                       else\r
+                       {\r
+                               Check(hWnd, R_CN, false);\r
+                       }\r
+                       if (c->Serial != NULL && c->Serial->size != 0)\r
+                       {\r
+                               X_SERIAL *s = c->Serial;\r
+                               char *tmp;\r
+                               UINT tmp_size = s->size * 3 + 1;\r
+                               tmp = ZeroMalloc(tmp_size);\r
+                               BinToStrEx(tmp, tmp_size, s->data, s->size);\r
+                               SetTextA(hWnd, E_SERIAL, tmp);\r
+                               Free(tmp);\r
+                               Check(hWnd, R_SERIAL, true);\r
+                       }\r
+                       else\r
+                       {\r
+                               Check(hWnd, R_SERIAL, false);\r
+                       }\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_RADIUS:\r
+               if (u->AuthData != NULL)\r
+               {\r
+                       AUTHRADIUS *r = (AUTHRADIUS *)u->AuthData;\r
+                       if (UniStrLen(r->RadiusUsername) != 0)\r
+                       {\r
+                               Check(hWnd, R_SET_RADIUS_USERNAME, true);\r
+                               SetText(hWnd, E_RADIUS_USERNAME, r->RadiusUsername);\r
+                       }\r
+                       else\r
+                       {\r
+                               Check(hWnd, R_SET_RADIUS_USERNAME, false);\r
+                       }\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_NT:\r
+               if (u->AuthData != NULL)\r
+               {\r
+                       AUTHNT *n = (AUTHNT *)u->AuthData;\r
+                       if (UniStrLen(n->NtUsername) != 0)\r
+                       {\r
+                               Check(hWnd, R_SET_RADIUS_USERNAME, true);\r
+                               SetText(hWnd, E_RADIUS_USERNAME, n->NtUsername);\r
+                       }\r
+                       else\r
+                       {\r
+                               Check(hWnd, R_SET_RADIUS_USERNAME, false);\r
+                       }\r
+               }\r
+               break;\r
+       }\r
+\r
+       if (u->Policy != NULL)\r
+       {\r
+               Check(hWnd, R_POLICY, true);\r
+       }\r
+\r
+       s->Inited = true;\r
+\r
+       SmEditUserDlgUpdate(hWnd, s);\r
+\r
+       if (s->EditMode == false)\r
+       {\r
+               Focus(hWnd, E_USERNAME);\r
+               SetText(hWnd, 0, _UU("SM_EDIT_USER_CAPTION_1"));\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_USER_CAPTION_2"), s->SetUser.Name);\r
+               SetText(hWnd, 0, tmp);\r
+\r
+               Disable(hWnd, E_USERNAME);\r
+               FocusEx(hWnd, E_REALNAME);\r
+       }\r
+}\r
+\r
+// ユーザー編集コントロール更新\r
+void SmEditUserDlgUpdate(HWND hWnd, SM_EDIT_USER *s)\r
+{\r
+       RPC_SET_USER *u;\r
+       bool ok = true;\r
+       UINT old_authtype;\r
+       char tmp1[MAX_SIZE];\r
+       char tmp2[MAX_SIZE];\r
+       bool authtype_changed = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (s->Inited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       u = &s->SetUser;\r
+\r
+       // ユーザー名\r
+       GetTxtA(hWnd, E_USERNAME, u->Name, sizeof(u->Name));\r
+       Trim(u->Name);\r
+       if (StrLen(u->Name) == 0 || IsUserName(u->Name) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       // 本名\r
+       GetTxt(hWnd, E_REALNAME, u->Realname, sizeof(u->Realname));\r
+       UniTrim(u->Realname);\r
+\r
+       // メモ\r
+       GetTxt(hWnd, E_NOTE, u->Note, sizeof(u->Note));\r
+       UniTrim(u->Realname);\r
+\r
+       // グループ\r
+       GetTxtA(hWnd, E_GROUP, u->GroupName, sizeof(u->GroupName));\r
+       Trim(u->GroupName);\r
+\r
+       // 有効期限\r
+       if (IsChecked(hWnd, R_EXPIRES) == false)\r
+       {\r
+               u->ExpireTime = 0;\r
+               Disable(hWnd, E_EXPIRES_DATE);\r
+               Disable(hWnd, E_EXPIRES_TIME);\r
+       }\r
+       else\r
+       {\r
+               SYSTEMTIME st1, st2;\r
+               Enable(hWnd, E_EXPIRES_DATE);\r
+               Enable(hWnd, E_EXPIRES_TIME);\r
+               DateTime_GetSystemtime(DlgItem(hWnd, E_EXPIRES_DATE), &st1);\r
+               DateTime_GetSystemtime(DlgItem(hWnd, E_EXPIRES_TIME), &st2);\r
+               st1.wHour = st2.wHour;\r
+               st1.wMinute = st2.wMinute;\r
+               st1.wSecond = st2.wSecond;\r
+               st1.wMilliseconds = st2.wMilliseconds;\r
+               u->ExpireTime = LocalToSystem64(SystemToUINT64(&st1));\r
+       }\r
+\r
+       // 認証方法\r
+       old_authtype = u->AuthType;\r
+       u->AuthType = LvGetSelected(hWnd, L_AUTH);\r
+\r
+       if (StrCmpi(u->Name, "*") == 0)\r
+       {\r
+               if (u->AuthType != AUTHTYPE_RADIUS && u->AuthType != AUTHTYPE_NT)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (u->AuthType == INFINITE)\r
+       {\r
+               ok = false;\r
+               u->AuthType = 0;\r
+       }\r
+       if (old_authtype != u->AuthType)\r
+       {\r
+               authtype_changed = true;\r
+       }\r
+\r
+       if (authtype_changed)\r
+       {\r
+               FreeAuthData(old_authtype, u->AuthData);\r
+               u->AuthData = NULL;\r
+               switch (u->AuthType)\r
+               {\r
+               case AUTHTYPE_ANONYMOUS:\r
+                       u->AuthData = NULL;\r
+                       break;\r
+\r
+               case AUTHTYPE_PASSWORD:\r
+                       u->AuthData = NewPasswordAuthData("", "");\r
+                       GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));\r
+                       if (StrCmp(tmp1, HIDDEN_PASSWORD) == 0)\r
+                       {\r
+                               SetTextA(hWnd, E_PASSWORD1, "");\r
+                       }\r
+                       GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+                       if (StrCmp(tmp2, HIDDEN_PASSWORD) == 0)\r
+                       {\r
+                               SetTextA(hWnd, E_PASSWORD2, "");\r
+                       }\r
+                       break;\r
+\r
+               case AUTHTYPE_USERCERT:\r
+                       u->AuthData = NewUserCertAuthData(NULL);\r
+                       SetText(hWnd, S_CERT_INFO, _UU("SM_EDIT_USER_CERT_INFO"));\r
+                       break;\r
+\r
+               case AUTHTYPE_ROOTCERT:\r
+                       u->AuthData = NewRootCertAuthData(NULL, NULL);\r
+                       break;\r
+\r
+               case AUTHTYPE_NT:\r
+                       u->AuthData = NewNTAuthData(L"");\r
+                       break;\r
+\r
+               case AUTHTYPE_RADIUS:\r
+                       u->AuthData = NewRadiusAuthData(L"");\r
+                       break;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, S_RADIUS_3, (u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT));\r
+       SetEnable(hWnd, R_SET_RADIUS_USERNAME, (u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT));\r
+       SetEnable(hWnd, S_RADIUS_1, (u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT));\r
+\r
+       if (StrCmp(u->Name, "*") == 0)\r
+       {\r
+               Check(hWnd, R_SET_RADIUS_USERNAME, false);\r
+               Disable(hWnd, R_SET_RADIUS_USERNAME);\r
+       }\r
+\r
+       if ((u->AuthType == AUTHTYPE_RADIUS) || (u->AuthType == AUTHTYPE_NT))\r
+       {\r
+               SetEnable(hWnd, E_RADIUS_USERNAME, IsChecked(hWnd, R_SET_RADIUS_USERNAME));\r
+               SetEnable(hWnd, S_RADIUS_2, IsChecked(hWnd, R_SET_RADIUS_USERNAME));\r
+       }\r
+       else\r
+       {\r
+               SetEnable(hWnd, E_RADIUS_USERNAME, false);\r
+               SetEnable(hWnd, S_RADIUS_2, false);\r
+       }\r
+\r
+       SetEnable(hWnd, S_PASSWORD_1, u->AuthType == AUTHTYPE_PASSWORD);\r
+       SetEnable(hWnd, S_PASSWORD_2, u->AuthType == AUTHTYPE_PASSWORD);\r
+       SetEnable(hWnd, S_PASSWORD_3, u->AuthType == AUTHTYPE_PASSWORD);\r
+       SetEnable(hWnd, E_PASSWORD1, u->AuthType == AUTHTYPE_PASSWORD);\r
+       SetEnable(hWnd, E_PASSWORD2, u->AuthType == AUTHTYPE_PASSWORD);\r
+\r
+       SetEnable(hWnd, S_USER_CERT_1, u->AuthType == AUTHTYPE_USERCERT);\r
+       SetEnable(hWnd, S_CERT_INFO, u->AuthType == AUTHTYPE_USERCERT);\r
+       SetEnable(hWnd, B_LOAD_CERT, u->AuthType == AUTHTYPE_USERCERT);\r
+\r
+       if (u->AuthType == AUTHTYPE_USERCERT)\r
+       {\r
+               SetEnable(hWnd, B_VIEW_CERT, ((AUTHUSERCERT *)u->AuthData)->UserX != NULL);\r
+       }\r
+       else\r
+       {\r
+               SetEnable(hWnd, B_VIEW_CERT, false);\r
+       }\r
+\r
+       SetEnable(hWnd, S_ROOT_CERT_1, u->AuthType == AUTHTYPE_ROOTCERT);\r
+       SetEnable(hWnd, S_ROOT_CERT_2, u->AuthType == AUTHTYPE_ROOTCERT);\r
+       SetEnable(hWnd, S_ROOT_CERT_3, u->AuthType == AUTHTYPE_ROOTCERT);\r
+       SetEnable(hWnd, R_CN, u->AuthType == AUTHTYPE_ROOTCERT);\r
+       SetEnable(hWnd, R_SERIAL, u->AuthType == AUTHTYPE_ROOTCERT);\r
+\r
+       if (u->AuthType == AUTHTYPE_ROOTCERT)\r
+       {\r
+               SetEnable(hWnd, E_CN, IsChecked(hWnd, R_CN));\r
+               SetEnable(hWnd, E_SERIAL, IsChecked(hWnd, R_SERIAL));\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, E_CN);\r
+               Disable(hWnd, E_SERIAL);\r
+       }\r
+\r
+       switch (u->AuthType)\r
+       {\r
+       case AUTHTYPE_PASSWORD:\r
+               GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));\r
+               GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+               if (StrCmp(tmp1, tmp2) != 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+               else\r
+               {\r
+                       if (StrCmp(tmp1, HIDDEN_PASSWORD) != 0)\r
+                       {\r
+                               HashPassword(((AUTHPASSWORD *)u->AuthData)->HashedKey, u->Name, tmp1);\r
+                       }\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_USERCERT:\r
+               if (((AUTHUSERCERT *)u->AuthData)->UserX == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_ROOTCERT:\r
+               Free(((AUTHROOTCERT *)u->AuthData)->CommonName);\r
+               ((AUTHROOTCERT *)u->AuthData)->CommonName = NULL;\r
+               if (IsChecked(hWnd, R_CN) && (IsEmpty(hWnd, E_CN) == false))\r
+               {\r
+                       ((AUTHROOTCERT *)u->AuthData)->CommonName = GetText(hWnd, E_CN);\r
+                       UniTrim(((AUTHROOTCERT *)u->AuthData)->CommonName);\r
+               }\r
+               if (IsChecked(hWnd, R_CN) && ((AUTHROOTCERT *)u->AuthData)->CommonName == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+               FreeXSerial(((AUTHROOTCERT *)u->AuthData)->Serial);\r
+               ((AUTHROOTCERT *)u->AuthData)->Serial = NULL;\r
+               if (IsChecked(hWnd, R_SERIAL))\r
+               {\r
+                       char *serial_str = GetTextA(hWnd, E_SERIAL);\r
+                       if (serial_str != NULL)\r
+                       {\r
+                               BUF *b = StrToBin(serial_str);\r
+                               if (b->Size >= 1)\r
+                               {\r
+                                       ((AUTHROOTCERT *)u->AuthData)->Serial = NewXSerial(b->Buf, b->Size);\r
+                               }\r
+                               FreeBuf(b);\r
+                               Free(serial_str);\r
+                       }\r
+               }\r
+               if (IsChecked(hWnd, R_SERIAL) && ((AUTHROOTCERT *)u->AuthData)->Serial == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_RADIUS:\r
+               Free(((AUTHRADIUS *)u->AuthData)->RadiusUsername);\r
+               ((AUTHRADIUS *)u->AuthData)->RadiusUsername = NULL;\r
+               if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && (IsEmpty(hWnd, E_RADIUS_USERNAME) == false))\r
+               {\r
+                       ((AUTHRADIUS *)u->AuthData)->RadiusUsername = GetText(hWnd, E_RADIUS_USERNAME);\r
+               }\r
+               if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && ((AUTHRADIUS *)u->AuthData)->RadiusUsername == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_NT:\r
+               Free(((AUTHNT *)u->AuthData)->NtUsername);\r
+               ((AUTHNT *)u->AuthData)->NtUsername = NULL;\r
+               if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && (IsEmpty(hWnd, E_RADIUS_USERNAME) == false))\r
+               {\r
+                       ((AUTHNT *)u->AuthData)->NtUsername = GetText(hWnd, E_RADIUS_USERNAME);\r
+               }\r
+               if (IsChecked(hWnd, R_SET_RADIUS_USERNAME) && ((AUTHNT *)u->AuthData)->NtUsername == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+               break;\r
+       }\r
+\r
+       SetEnable(hWnd, B_POLICY, IsChecked(hWnd, R_POLICY));\r
+       if (IsChecked(hWnd, R_POLICY))\r
+       {\r
+               if (u->Policy == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// ユーザー編集ダイアログプロシージャ\r
+UINT SmEditUserDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_USER *s = (SM_EDIT_USER *)param;\r
+       NMHDR *n;\r
+       POLICY *policy;\r
+       X *x = NULL;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char name[MAX_SIZE];\r
+       char *ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmEditUserDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_USERNAME:\r
+               case E_REALNAME:\r
+               case E_NOTE:\r
+               case R_EXPIRES:\r
+               case E_EXPIRES_DATE:\r
+               case E_EXPIRES_TIME:\r
+               case E_GROUP:\r
+               case L_AUTH:\r
+               case R_SET_RADIUS_USERNAME:\r
+               case E_RADIUS_USERNAME:\r
+               case R_POLICY:\r
+               case E_PASSWORD1:\r
+               case E_PASSWORD2:\r
+               case R_CN:\r
+               case E_CN:\r
+               case R_SERIAL:\r
+               case E_SERIAL:\r
+                       SmEditUserDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmEditUserDlgOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_POLICY:\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_USER_POL_DLG"), s->SetUser.Name);\r
+                       // ポリシー\r
+                       if (s->SetUser.Policy == NULL)\r
+                       {\r
+                               policy = ClonePolicy(GetDefaultPolicy());\r
+                               if (SmPolicyDlgEx2(hWnd, policy, tmp, false, s->p->PolicyVer))\r
+                               {\r
+                                       s->SetUser.Policy = policy;\r
+                                       SmEditUserDlgUpdate(hWnd, s);\r
+                               }\r
+                               else\r
+                               {\r
+                                       Free(policy);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               SmPolicyDlgEx2(hWnd, s->SetUser.Policy, tmp, false, s->p->PolicyVer);\r
+                       }\r
+                       break;\r
+\r
+               case B_GROUP:\r
+                       // グループの参照\r
+                       GetTxtA(hWnd, E_GROUP, name, sizeof(name));\r
+                       Trim(name);\r
+                       ret = SmSelectGroupDlg(hWnd, s->Hub, StrLen(name) == 0 ? NULL : name);\r
+                       if (ret != NULL)\r
+                       {\r
+                               SetTextA(hWnd, E_GROUP, ret);\r
+                               Free(ret);\r
+                       }\r
+                       else\r
+                       {\r
+                               SetTextA(hWnd, E_GROUP, "");\r
+                       }\r
+                       FocusEx(hWnd, E_GROUP);\r
+                       break;\r
+\r
+               case B_LOAD_CERT:\r
+                       // 証明書の指定\r
+                       if (CmLoadXFromFileOrSecureCard(hWnd, &x))\r
+                       {\r
+UPDATE_CERT:\r
+                               if (s->SetUser.AuthType == AUTHTYPE_USERCERT)\r
+                               {\r
+                                       wchar_t tmp[MAX_SIZE];\r
+                                       FreeX(((AUTHUSERCERT *)s->SetUser.AuthData)->UserX);\r
+                                       ((AUTHUSERCERT *)s->SetUser.AuthData)->UserX = x;\r
+                                       SmGetCertInfoStr(tmp, sizeof(tmp), x);\r
+                                       SetText(hWnd, S_CERT_INFO, tmp);\r
+                                       SmEditUserDlgUpdate(hWnd, s);\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (x != NULL)\r
+                                       {\r
+                                               FreeX(x);\r
+                                               x = NULL;\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_VIEW_CERT:\r
+                       // 証明書の表示\r
+                       if (s->SetUser.AuthType == AUTHTYPE_USERCERT)\r
+                       {\r
+                               CertDlg(hWnd, ((AUTHUSERCERT *)s->SetUser.AuthData)->UserX, NULL, true);\r
+                       }\r
+                       break;\r
+\r
+               case B_CREATE:\r
+                       // 作成\r
+                       GetTxtA(hWnd, E_USERNAME, name, sizeof(name));\r
+                       Trim(name);\r
+                       if (SmCreateCert(hWnd, &x, NULL, false, name))\r
+                       {\r
+                               if (s->SetUser.AuthType != AUTHTYPE_USERCERT)\r
+                               {\r
+                                       LvSelect(hWnd, L_AUTH, 2);\r
+                               }\r
+                               goto UPDATE_CERT;\r
+                       }\r
+                       break;\r
+\r
+               case R_SET_RADIUS_USERNAME:\r
+                       if (IsChecked(hWnd, R_SET_RADIUS_USERNAME))\r
+                       {\r
+                               FocusEx(hWnd, E_RADIUS_USERNAME);\r
+                       }\r
+                       break;\r
+\r
+               case R_EXPIRES:\r
+                       if (IsChecked(hWnd, R_EXPIRES))\r
+                       {\r
+                               Focus(hWnd, E_EXPIRES_DATE);\r
+                       }\r
+                       break;\r
+\r
+               case R_POLICY:\r
+                       if (IsChecked(hWnd, R_POLICY))\r
+                       {\r
+                               Focus(hWnd, B_POLICY);\r
+                       }\r
+                       break;\r
+\r
+               case R_CN:\r
+                       if (IsChecked(hWnd, R_CN))\r
+                       {\r
+                               Focus(hWnd, E_CN);\r
+                       }\r
+                       break;\r
+\r
+               case R_SERIAL:\r
+                       if (IsChecked(hWnd, R_SERIAL))\r
+                       {\r
+                               Focus(hWnd, E_SERIAL);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_AUTH:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmEditUserDlgUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの編集ダイアログ\r
+bool SmEditUserDlg(HWND hWnd, SM_HUB *s, char *username)\r
+{\r
+       SM_EDIT_USER e;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL || username == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&e, sizeof(e));\r
+       e.p = s->p;\r
+       e.Rpc = s->Rpc;\r
+       e.Hub = s;\r
+\r
+       // ユーザーの取得\r
+       StrCpy(e.SetUser.HubName, sizeof(e.SetUser.HubName), e.Hub->HubName);\r
+       StrCpy(e.SetUser.Name, sizeof(e.SetUser.Name), username);\r
+\r
+       if (CALL(hWnd, ScGetUser(s->Rpc, &e.SetUser)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       e.EditMode = true;\r
+\r
+       ret = Dialog(hWnd, D_SM_EDIT_USER, SmEditUserDlgProc, &e);\r
+\r
+       FreeRpcSetUser(&e.SetUser);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーの新規作成ダイアログ\r
+bool SmCreateUserDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       SM_EDIT_USER e;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&e, sizeof(e));\r
+       e.EditMode = false;\r
+       e.p = s->p;\r
+       e.Rpc = s->Rpc;\r
+       e.Hub = s;\r
+\r
+       // 新しいユーザーの設定\r
+       StrCpy(e.SetUser.HubName, sizeof(e.SetUser.HubName), e.Hub->HubName);\r
+       e.SetUser.AuthType = CLIENT_AUTHTYPE_PASSWORD;\r
+       e.SetUser.AuthData = NewPasswordAuthData("", "");\r
+\r
+       ret = Dialog(hWnd, D_SM_EDIT_USER, SmEditUserDlgProc, &e);\r
+\r
+       FreeRpcSetUser(&e.SetUser);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザー認証方法の文字列の取得\r
+wchar_t *SmGetAuthTypeStr(UINT id)\r
+{\r
+       return GetAuthTypeStr(id);\r
+}\r
+\r
+// ユーザーリスト初期化\r
+void SmUserListInit(HWND hWnd, SM_USER *s)\r
+{\r
+       wchar_t tmp1[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_USER);\r
+\r
+       // カラム初期化\r
+       LvInit(hWnd, L_USER);\r
+       LvSetStyle(hWnd, L_USER, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_USER, 0, _UU("SM_USER_COLUMN_1"), 120);\r
+       LvInsertColumn(hWnd, L_USER, 1, _UU("SM_USER_COLUMN_2"), 100);\r
+       LvInsertColumn(hWnd, L_USER, 2, _UU("SM_USER_COLUMN_3"), 100);\r
+       LvInsertColumn(hWnd, L_USER, 3, _UU("SM_USER_COLUMN_4"), 130);\r
+       LvInsertColumn(hWnd, L_USER, 4, _UU("SM_USER_COLUMN_5"), 100);\r
+       LvInsertColumn(hWnd, L_USER, 5, _UU("SM_USER_COLUMN_6"), 90);\r
+       LvInsertColumn(hWnd, L_USER, 6, _UU("SM_USER_COLUMN_7"), 120);\r
+\r
+       FormatText(hWnd, S_TITLE, s->Hub->HubName);\r
+\r
+       if (s->GroupName != NULL)\r
+       {\r
+               GetTxt(hWnd, 0, tmp1, sizeof(tmp1));\r
+               UniFormat(tmp2, sizeof(tmp2), _UU("SM_GROUP_MEMBER_STR"), s->GroupName);\r
+               UniStrCat(tmp1, sizeof(tmp1), tmp2);\r
+               SetText(hWnd, S_TITLE, tmp1);\r
+               Disable(hWnd, B_CREATE);\r
+       }\r
+\r
+       if (s->SelectMode)\r
+       {\r
+               SetStyle(hWnd, L_USER, LVS_SINGLESEL);\r
+       }\r
+\r
+       SmUserListRefresh(hWnd, s);\r
+\r
+       if (s->SelectMode)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               UINT i;\r
+               StrToUni(tmp, sizeof(tmp), s->SelectedName);\r
+               i = LvSearchStr(hWnd, L_USER, 0, tmp);\r
+               if (i != INFINITE)\r
+               {\r
+                       LvSelect(hWnd, L_USER, i);\r
+               }\r
+\r
+               if (s->AllowGroup)\r
+               {\r
+                       SetText(hWnd, B_DELETE, _UU("SM_SELECT_ALT_GROUP"));\r
+               }\r
+       }\r
+}\r
+\r
+// ユーザーリスト更新\r
+void SmUserListRefresh(HWND hWnd, SM_USER *s)\r
+{\r
+       LVB *b;\r
+       RPC_ENUM_USER t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+       if (CALL(hWnd, ScEnumUser(s->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumUser;i++)\r
+       {\r
+               RPC_ENUM_USER_ITEM *e = &t.Users[i];\r
+               wchar_t name[MAX_SIZE];\r
+               wchar_t group[MAX_SIZE];\r
+               wchar_t num[MAX_SIZE];\r
+               wchar_t time[MAX_SIZE];\r
+\r
+               if (s->GroupName != NULL)\r
+               {\r
+                       if (StrCmpi(s->GroupName, e->GroupName) != 0)\r
+                       {\r
+                               continue;\r
+                       }\r
+               }\r
+\r
+               StrToUni(name, sizeof(name), e->Name);\r
+\r
+               if (StrLen(e->GroupName) != 0)\r
+               {\r
+                       StrToUni(group, sizeof(group), e->GroupName);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(group, sizeof(group), _UU("SM_NO_GROUP"));\r
+               }\r
+\r
+               UniToStru(num, e->NumLogin);\r
+\r
+               GetDateTimeStrEx64(time, sizeof(time), SystemToLocal64(e->LastLoginTime), NULL);\r
+\r
+               LvInsertAdd(b, e->DenyAccess ? ICO_USER_DENY : ICO_USER, NULL, 7,\r
+                       name, e->Realname, group, e->Note, SmGetAuthTypeStr(e->AuthType),\r
+                       num, time);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_USER);\r
+\r
+       FreeRpcEnumUser(&t);\r
+\r
+       SmUserListUpdate(hWnd, s);\r
+}\r
+\r
+// ユーザーリストコントロール更新\r
+void SmUserListUpdate(HWND hWnd, SM_USER *s)\r
+{\r
+       bool b = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_USER) == false || LvIsMultiMasked(hWnd, L_USER))\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (s->SelectMode)\r
+       {\r
+               SetText(hWnd, IDOK, _UU("SM_SELECT_USER"));\r
+               SetText(hWnd, IDCANCEL, _UU("SM_SELECT_NO"));\r
+               SetText(hWnd, S_TITLE, _UU("SM_PLEASE_SELECT"));\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+\r
+       SetEnable(hWnd, B_STATUS, b);\r
+       SetEnable(hWnd, B_DELETE, (b && s->SelectedName == false) || s->AllowGroup);\r
+       SetEnable(hWnd, B_CREATE, s->SelectedName == false);\r
+}\r
+\r
+// ユーザーリストダイアログプロシージャ\r
+UINT SmUserListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_USER *s = (SM_USER *)param;\r
+       NMHDR *n;\r
+       wchar_t *str;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmUserListInit(hWnd, s);\r
+\r
+               if (s->CreateNow)\r
+               {\r
+                       // すぐに作成\r
+                       if (IsEnable(hWnd, B_CREATE))\r
+                       {\r
+                               Command(hWnd, B_CREATE);\r
+                       }\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (s->SelectMode == false)\r
+                       {\r
+                               // プロパティ\r
+                               str = LvGetSelectedStr(hWnd, L_USER, 0);\r
+                               if (str != NULL)\r
+                               {\r
+                                       char name[MAX_SIZE];\r
+                                       UniToStr(name, sizeof(name), str);\r
+\r
+                                       if (SmEditUserDlg(hWnd, s->Hub, name))\r
+                                       {\r
+                                               SmUserListRefresh(hWnd, s);\r
+                                       }\r
+\r
+                                       Free(str);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               // ユーザーを選択した\r
+                               str = LvGetSelectedStr(hWnd, L_USER, 0);\r
+                               if (str != NULL)\r
+                               {\r
+                                       char name[MAX_SIZE];\r
+                                       UniToStr(name, sizeof(name), str);\r
+\r
+                                       s->SelectedName = CopyStr(name);\r
+\r
+                                       EndDialog(hWnd, true);\r
+\r
+                                       Free(str);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_CREATE:\r
+                       // 新規作成\r
+                       if (SmCreateUserDlg(hWnd, s->Hub))\r
+                       {\r
+                               SmUserListRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       if (s->AllowGroup)\r
+                       {\r
+                               // グループ選択\r
+                               EndDialog(hWnd, INFINITE);\r
+                       }\r
+                       else\r
+                       {\r
+                               // 削除\r
+                               str = LvGetSelectedStr(hWnd, L_USER, 0);\r
+                               if (str != NULL)\r
+                               {\r
+                                       RPC_DELETE_USER t;\r
+                                       char name[MAX_SIZE];\r
+                                       UniToStr(name, sizeof(name), str);\r
+\r
+                                       Zero(&t, sizeof(t));\r
+                                       StrCpy(t.HubName, sizeof(t.HubName), s->Hub->HubName);\r
+                                       StrCpy(t.Name, sizeof(t.Name), name);\r
+\r
+                                       if (MsgBoxEx(hWnd, MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION,\r
+                                               _UU("SM_USER_DELETE_MSG"), str) == IDYES)\r
+                                       {\r
+                                               if (CALL(hWnd, ScDeleteUser(s->Rpc, &t)))\r
+                                               {\r
+                                                       SmUserListRefresh(hWnd, s);\r
+                                               }\r
+                                       }\r
+\r
+                                       Free(str);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_STATUS:\r
+                       // ユーザー情報表示\r
+                       str = LvGetSelectedStr(hWnd, L_USER, 0);\r
+                       if (str != NULL)\r
+                       {\r
+                               char name[MAX_SIZE];\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               SM_USER_INFO info;\r
+                               UniToStr(name, sizeof(name), str);\r
+\r
+                               UniFormat(tmp, sizeof(tmp), _UU("SM_USERINFO_CAPTION"), name);\r
+\r
+                               Zero(&info, sizeof(info));\r
+                               info.p = s->p;\r
+                               info.Rpc = s->Rpc;\r
+                               info.Hub = s->Hub;\r
+                               info.Username = name;\r
+\r
+                               SmStatusDlg(hWnd, s->p, &info, false, true, tmp, ICO_USER, NULL, SmRefreshUserInfo);\r
+\r
+                               Free(str);\r
+                       }\r
+                       break;\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmUserListRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_USER:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               // コントロール更新\r
+                               SmUserListUpdate(hWnd, s);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_USER);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーリストダイアログ (選択)\r
+char *SmSelectUserDlg(HWND hWnd, SM_HUB *s, char *default_name)\r
+{\r
+       return SmSelectUserDlgEx(hWnd, s, default_name, false);\r
+}\r
+char *SmSelectUserDlgEx(HWND hWnd, SM_HUB *s, char *default_name, bool allow_group)\r
+{\r
+       UINT ret;\r
+       SM_USER user;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&user, sizeof(user));\r
+       user.Hub = s;\r
+       user.p = s->p;\r
+       user.Rpc = s->Rpc;\r
+       user.GroupName = NULL;\r
+       user.SelectedName = default_name;\r
+       user.SelectMode = true;\r
+       user.AllowGroup = allow_group;\r
+\r
+       ret = Dialog(hWnd, D_SM_USER, SmUserListProc, &user);\r
+\r
+       if (ret == 0)\r
+       {\r
+               return NULL;\r
+       }\r
+       else if (ret == INFINITE)\r
+       {\r
+               // グループの選択\r
+               return SmSelectGroupDlg(hWnd, s, default_name);\r
+       }\r
+       else\r
+       {\r
+               return user.SelectedName;\r
+       }\r
+}\r
+\r
+// ユーザーリストダイアログ (グループ名でフィルタ)\r
+void SmUserListDlgEx(HWND hWnd, SM_HUB *s, char *groupname, bool create)\r
+{\r
+       SM_USER user;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&user, sizeof(user));\r
+       user.Hub = s;\r
+       user.p = s->p;\r
+       user.Rpc = s->Rpc;\r
+       user.GroupName = groupname;\r
+       user.CreateNow = create;\r
+\r
+       Dialog(hWnd, D_SM_USER, SmUserListProc, &user);\r
+}\r
+\r
+// ユーザーリストダイアログ\r
+void SmUserListDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       SmUserListDlgEx(hWnd, s, NULL, false);\r
+}\r
+\r
+// 初期化\r
+void SmHubDlgInit(HWND hWnd, SM_HUB *s)\r
+{\r
+       CAPSLIST *caps;\r
+       bool support_user, support_group, support_accesslist, support_cascade,\r
+               support_log, support_config_hub, support_secure_nat, support_config_radius;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FormatText(hWnd, 0, s->HubName);\r
+       FormatText(hWnd, S_TITLE, s->HubName);\r
+       SetIcon(hWnd, 0, ICO_HUB);\r
+       DlgFont(hWnd, S_TITLE, 15, true);\r
+\r
+       LvInit(hWnd, L_STATUS);\r
+       LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 0);\r
+       LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 0);\r
+\r
+       caps = s->p->CapsList;\r
+\r
+       support_user = GetCapsInt(caps, "i_max_users_per_hub") == 0 ? false : true;\r
+       support_group = GetCapsInt(caps, "i_max_groups_per_hub") == 0 ? false : true;\r
+       support_accesslist = GetCapsInt(caps, "i_max_access_lists") == 0 ? false : true;\r
+       support_cascade = GetCapsBool(caps, "b_support_cascade");\r
+       support_log = GetCapsBool(caps, "b_support_config_log");\r
+       support_config_hub = GetCapsBool(caps, "b_support_config_hub");\r
+       support_secure_nat = GetCapsBool(caps, "b_support_securenat");\r
+       support_config_radius = GetCapsBool(caps, "b_support_radius");\r
+\r
+       SetEnable(hWnd, B_USER, support_user);\r
+       SetEnable(hWnd, S_USER, support_user);\r
+\r
+       SetEnable(hWnd, B_GROUP, support_group);\r
+       SetEnable(hWnd, S_GROUP, support_group);\r
+\r
+       SetEnable(hWnd, B_ACCESS, support_accesslist);\r
+       SetEnable(hWnd, S_ACCESS, support_accesslist);\r
+\r
+       SetEnable(hWnd, B_PROPERTY, s->p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+       SetEnable(hWnd, S_PROPERTY, s->p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+\r
+       SetEnable(hWnd, B_RADIUS, support_config_radius);\r
+       SetEnable(hWnd, S_RADIUS, support_config_radius);\r
+\r
+       SetEnable(hWnd, B_LINK, support_cascade);\r
+       SetEnable(hWnd, S_LINK, support_cascade);\r
+\r
+       SetEnable(hWnd, B_LOG, support_log);\r
+       SetEnable(hWnd, S_LOG, support_log);\r
+\r
+       SetEnable(hWnd, B_CA, support_config_hub);\r
+       SetEnable(hWnd, S_CA, support_config_hub);\r
+\r
+       SetEnable(hWnd, B_SNAT, support_secure_nat);\r
+       SetEnable(hWnd, S_SNAT, support_secure_nat);\r
+\r
+       SetEnable(hWnd, B_CRL, GetCapsBool(caps, "b_support_crl"));\r
+\r
+       SetEnable(hWnd, B_LOG_FILE, GetCapsBool(caps, "b_support_read_log"));\r
+\r
+       SmHubDlgRefresh(hWnd, s);\r
+}\r
+\r
+// コントロール更新\r
+void SmHubDlgUpdate(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+}\r
+\r
+// 内容更新\r
+void SmHubDlgRefresh(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SmRefreshHubStatus(hWnd, s->p, (void *)s->HubName);\r
+       LvAutoSize(hWnd, L_STATUS);\r
+\r
+       SmHubDlgUpdate(hWnd, s);\r
+}\r
+\r
+// HUB 管理ダイアログ\r
+UINT SmHubDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *s = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmHubDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_USER:\r
+                       // ユーザー\r
+                       SmUserListDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_GROUP:\r
+                       // グループ\r
+                       SmGroupListDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_ACCESS:\r
+                       // アクセスリスト\r
+                       SmAccessListDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_PROPERTY:\r
+                       // プロパティ\r
+                       if (SmEditHubDlg(hWnd, s->p, s->HubName))\r
+                       {\r
+                               SmHubDlgRefresh(hWnd, s);\r
+                       }\r
+                       break;\r
+\r
+               case B_RADIUS:\r
+                       // Radius\r
+                       SmRadiusDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_LINK:\r
+                       // カスケード\r
+                       SmLinkDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_SESSION:\r
+                       // セッション\r
+                       SmSessionDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_LOG:\r
+                       // ログ\r
+                       Dialog(hWnd, D_SM_LOG, SmLogDlg, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_CA:\r
+                       // CA\r
+                       SmCaDlg(hWnd, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_SNAT:\r
+                       // SecureNAT\r
+                       Dialog(hWnd, D_SM_SNAT, SmSNATDlgProc, s);\r
+                       SmHubDlgRefresh(hWnd, s);\r
+                       break;\r
+\r
+               case B_CRL:\r
+                       // 無効な証明書の一覧\r
+                       Dialog(hWnd, D_SM_CRL, SmCrlDlgProc, s);\r
+                       break;\r
+\r
+               case B_LOG_FILE:\r
+                       // ログファイル\r
+                       Dialog(hWnd, D_SM_LOG_FILE, SmLogFileDlgProc, s->p);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// HUB の管理\r
+void SmHubDlg(HWND hWnd, SM_HUB *s)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_HUB, SmHubDlgProc, s);\r
+}\r
+\r
+// サーバー パスワードの変更\r
+UINT SmChangeServerPasswordDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       char tmp1[MAX_SIZE];\r
+       char tmp2[MAX_SIZE];\r
+       UCHAR hash[SHA1_SIZE];\r
+       RPC_SET_PASSWORD t;\r
+       SETTING *setting;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SetIcon(hWnd, 0, ICO_USER_ADMIN);\r
+               FormatText(hWnd, 0, p->ServerName);\r
+               FormatText(hWnd, S_TITLE, p->ServerName);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));\r
+                       GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+                       if (StrCmp(tmp1, tmp2) != 0)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONSTOP, _UU("SM_CHANGE_PASSWORD_1"));\r
+                               FocusEx(hWnd, E_PASSWORD2);\r
+                               break;\r
+                       }\r
+                       if (StrLen(tmp1) == 0)\r
+                       {\r
+                               if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SM_CHANGE_PASSWORD_2")) == IDNO)\r
+                               {\r
+                                       Focus(hWnd, E_PASSWORD1);\r
+                                       break;\r
+                               }\r
+                       }\r
+                       Zero(&t, sizeof(t));\r
+                       Hash(t.HashedPassword, tmp1, StrLen(tmp1), true);\r
+                       Copy(hash, t.HashedPassword, sizeof(hash));\r
+                       if (CALL(hWnd, ScSetServerPassword(p->Rpc, &t)) == false)\r
+                       {\r
+                               break;\r
+                       }\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SM_CHANGE_PASSWORD_3"));\r
+\r
+                       // 接続設定のパスワードを変更する\r
+                       setting = SmGetSetting(p->CurrentSetting->Title);\r
+                       if (setting != NULL && sm->TempSetting == NULL)\r
+                       {\r
+                               if (IsZero(setting->HashedPassword, SHA1_SIZE) == false)\r
+                               {\r
+                                       Copy(setting->HashedPassword, hash, SHA1_SIZE);\r
+                                       SmWriteSettingList();\r
+                               }\r
+                       }\r
+\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// サーバー ファーム コントローラへの接続状況更新\r
+bool SmRefreshFarmConnectionInfo(HWND hWnd, SM_SERVER *p, void *param)\r
+{\r
+       RPC_FARM_CONNECTION_STATUS t;\r
+       LVB *b;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScGetFarmConnectionStatus(p->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       if (t.Online == false)\r
+       {\r
+               LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_FC_IP"), _UU("SM_FC_NOT_CONNECTED"));\r
+\r
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_PORT"), _UU("SM_FC_NOT_CONNECTED"));\r
+       }\r
+       else\r
+       {\r
+               IPToStr32(str, sizeof(str), t.Ip);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_FC_IP"), tmp);\r
+\r
+               UniToStru(tmp, t.Port);\r
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_PORT"), tmp);\r
+       }\r
+\r
+       LvInsertAdd(b,\r
+               t.Online ? ICO_SERVER_ONLINE_EX : ICO_PROTOCOL_X, NULL, 2,\r
+               _UU("SM_FC_STATUS"),\r
+               t.Online ? _UU("SM_FC_ONLINE") : _UU("SM_FC_OFFLINE"));\r
+\r
+       if (t.Online == false)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_FC_ERROR_TAG"), _E(t.LastError), t.LastError);\r
+               LvInsertAdd(b, ICO_STOP, NULL, 2,\r
+                       _UU("SM_FC_LAST_ERROR"), tmp);\r
+       }\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartedTime), NULL);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FC_START_TIME"), tmp);\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.FirstConnectedTime), NULL);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FC_FIRST_TIME"), tmp);\r
+\r
+       //if (t.Online == false)\r
+       {\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CurrentConnectedTime), NULL);\r
+               LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FC_CURRENT_TIME"), tmp);\r
+       }\r
+\r
+       UniToStru(tmp, t.NumTry);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_NUM_TRY"), tmp);\r
+\r
+       UniToStru(tmp, t.NumConnected);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_NUM_CONNECTED"), tmp);\r
+\r
+       UniToStru(tmp, t.NumFailed);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FC_NUM_FAILED"), tmp);\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       return true;\r
+}\r
+\r
+// 初期化\r
+void SmFarmMemberDlgInit(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_FARM);\r
+\r
+       FormatText(hWnd, S_TITLE, p->ServerName);\r
+\r
+       // カラム初期化\r
+       LvInit(hWnd, L_FARM_MEMBER);\r
+       LvSetStyle(hWnd, L_FARM_MEMBER, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 0, _UU("SM_FM_COLUMN_1"), 90);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 1, _UU("SM_FM_COLUMN_2"), 150);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 2, _UU("SM_FM_COLUMN_3"), 140);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 3, _UU("SM_FM_COLUMN_4"), 60);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 4, _UU("SM_FM_COLUMN_5"), 80);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 5, _UU("SM_FM_COLUMN_6"), 80);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 6, _UU("SM_FM_COLUMN_7"), 80);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 7, _UU("SM_FM_COLUMN_8"), 160);\r
+       LvInsertColumn(hWnd, L_FARM_MEMBER, 8, _UU("SM_FM_COLUMN_9"), 160);\r
+\r
+       SmFarmMemberDlgRefresh(hWnd, p);\r
+}\r
+\r
+// 更新\r
+void SmFarmMemberDlgUpdate(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_FARM_MEMBER) && (LvIsMultiMasked(hWnd, L_FARM_MEMBER) == false));\r
+       SetEnable(hWnd, B_CERT, LvIsSelected(hWnd, L_FARM_MEMBER) && (LvIsMultiMasked(hWnd, L_FARM_MEMBER) == false));\r
+}\r
+\r
+// 内容更新\r
+void SmFarmMemberDlgRefresh(HWND hWnd, SM_SERVER *p)\r
+{\r
+       RPC_ENUM_FARM t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumFarmMember(p->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       LvReset(hWnd, L_FARM_MEMBER);\r
+\r
+       for (i = 0;i < t.NumFarm;i++)\r
+       {\r
+               RPC_ENUM_FARM_ITEM *e = &t.Farms[i];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp3[64];\r
+               wchar_t tmp4[64];\r
+               wchar_t tmp5[64];\r
+               wchar_t tmp6[64];\r
+               wchar_t tmp7[64];\r
+               wchar_t tmp8[64];\r
+\r
+               GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);\r
+               StrToUni(tmp2, sizeof(tmp2), e->Hostname);\r
+               UniToStru(tmp3, e->Point);\r
+               UniToStru(tmp4, e->NumSessions);\r
+               UniToStru(tmp5, e->NumTcpConnections);\r
+               UniToStru(tmp6, e->NumHubs);\r
+               UniToStru(tmp7, e->AssignedClientLicense);\r
+               UniToStru(tmp8, e->AssignedBridgeLicense);\r
+\r
+               LvInsert(hWnd, L_FARM_MEMBER, e->Controller ? ICO_FARM : ICO_TOWER, (void *)e->Id, 9,\r
+                       e->Controller ? _UU("SM_FM_CONTROLLER") : _UU("SM_FM_MEMBER"),\r
+                       tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8);\r
+       }\r
+\r
+       FreeRpcEnumFarm(&t);\r
+\r
+       SmFarmMemberDlgUpdate(hWnd, p);\r
+}\r
+\r
+// OK ボタン\r
+void SmFarmMemberDlgOnOk(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+}\r
+\r
+// ファーム メンバ証明書の表示\r
+void SmFarmMemberCert(HWND hWnd, SM_SERVER *p, UINT id)\r
+{\r
+       RPC_FARM_INFO t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Id = id;\r
+\r
+       if (CALL(hWnd, ScGetFarmInfo(p->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CertDlg(hWnd, t.ServerCert, NULL, true);\r
+\r
+       FreeRpcFarmInfo(&t);\r
+}\r
+\r
+// ファームメンバ情報の更新\r
+bool SmRefreshFarmMemberInfo(HWND hWnd, SM_SERVER *p, void *param)\r
+{\r
+       RPC_FARM_INFO t;\r
+       UINT id = (UINT)param;\r
+       LVB *b;\r
+       UINT i;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL || id == 0)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Id = id;\r
+\r
+       if (CALL(hWnd, ScGetFarmInfo(p->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_FMINFO_TYPE"),\r
+               t.Controller ? _UU("SM_FARM_CONTROLLER") : _UU("SM_FARM_MEMBER"));\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_FMINFO_CONNECT_TIME"), tmp);\r
+\r
+       IPToStr32(str, sizeof(str), t.Ip);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FMINFO_IP"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.Hostname);\r
+       LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("SM_FMINFO_HOSTNAME"), tmp);\r
+\r
+       UniToStru(tmp, t.Point);\r
+       LvInsertAdd(b, ICO_TEST, NULL, 2, _UU("SM_FMINFO_POINT"), tmp);\r
+\r
+       UniToStru(tmp, t.Weight);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_FMINFO_WEIGHT"), tmp);\r
+\r
+       UniToStru(tmp, t.NumPort);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FMINFO_NUM_PORT"), tmp);\r
+\r
+       for (i = 0;i < t.NumPort;i++)\r
+       {\r
+               wchar_t tmp2[MAX_SIZE];\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_PORT"), i + 1);\r
+               UniToStru(tmp2, t.Ports[i]);\r
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, tmp, tmp2);\r
+       }\r
+\r
+       UniToStru(tmp, t.NumFarmHub);\r
+       LvInsertAdd(b, ICO_HUB_OFFLINE, NULL, 2, _UU("SM_FMINFO_NUM_HUB"), tmp);\r
+\r
+       for (i = 0;i < t.NumFarmHub;i++)\r
+       {\r
+               wchar_t tmp2[MAX_SIZE];\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_HUB"), i + 1);\r
+               UniFormat(tmp2, sizeof(tmp2),\r
+                       t.FarmHubs[i].DynamicHub ? _UU("SM_FMINFO_HUB_TAG_2") : _UU("SM_FMINFO_HUB_TAG_1"),\r
+                       t.FarmHubs[i].HubName);\r
+               LvInsertAdd(b, ICO_HUB, NULL, 2, tmp, tmp2);\r
+       }\r
+\r
+       UniToStru(tmp, t.NumSessions);\r
+       LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_FMINFO_NUM_SESSION"), tmp);\r
+\r
+       UniToStru(tmp, t.NumTcpConnections);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_FMINFO_NUN_CONNECTION"), tmp);\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcFarmInfo(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// ファームメンバ一覧ダイアログ\r
+UINT SmFarmMemberDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       NMHDR *n;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmFarmMemberDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // ファーム メンバの情報を表示\r
+                       i = LvGetSelected(hWnd, L_FARM_MEMBER);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               SmStatusDlg(hWnd, p, LvGetParam(hWnd, L_FARM_MEMBER, i), false, true,\r
+                                       _UU("SM_FMINFO_CAPTION"), ICO_FARM, NULL, SmRefreshFarmMemberInfo);\r
+                       }\r
+                       break;\r
+\r
+               case B_CERT:\r
+                       // サーバー証明書の表示\r
+                       i = LvGetSelected(hWnd, L_FARM_MEMBER);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               SmFarmMemberCert(hWnd, p, (UINT)LvGetParam(hWnd, L_FARM_MEMBER, i));\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       SmFarmMemberDlgRefresh(hWnd, p);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       switch (n->idFrom)\r
+                       {\r
+                       case L_FARM_MEMBER:\r
+                               SmFarmMemberDlgUpdate(hWnd, p);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_FARM_MEMBER);\r
+\r
+       return 0;\r
+}\r
+\r
+// 文字列をポートリストに変換\r
+LIST *SmStrToPortList(char *str)\r
+{\r
+       return StrToPortList(str);\r
+}\r
+\r
+// ダイアログ初期化\r
+void SmFarmDlgInit(HWND hWnd, SM_SERVER *p)\r
+{\r
+       RPC_FARM t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_FARM);\r
+\r
+       // 現在の設定を取得\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScGetFarmSetting(p->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       if (t.Weight == 0)\r
+       {\r
+               t.Weight = FARM_DEFAULT_WEIGHT;\r
+       }\r
+\r
+       FormatText(hWnd, S_TITLE, p->ServerName);\r
+       DlgFont(hWnd, S_CURRENT, 11, true);\r
+\r
+       SetText(hWnd, S_CURRENT, GetServerTypeStr(t.ServerType));\r
+\r
+       switch (t.ServerType)\r
+       {\r
+       case SERVER_TYPE_FARM_CONTROLLER:\r
+               Check(hWnd, R_CONTROLLER, true);\r
+               break;\r
+\r
+       case SERVER_TYPE_FARM_MEMBER:\r
+               Check(hWnd, R_MEMBER, true);\r
+               break;\r
+\r
+       default:\r
+               Check(hWnd, R_STANDALONE, true);\r
+               break;\r
+       }\r
+\r
+       SetInt(hWnd, E_WEIGHT, t.Weight);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               Check(hWnd, R_CONTROLLER_ONLY, t.ControllerOnly);\r
+       }\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               char tmp[MAX_PUBLIC_PORT_NUM * 8];\r
+               UINT i;\r
+               if (t.PublicIp != 0)\r
+               {\r
+                       IpSet(hWnd, E_IP, t.PublicIp);\r
+               }\r
+               StrCpy(tmp, sizeof(tmp), "");\r
+               if (t.NumPort != 0)\r
+               {\r
+                       for (i = 0;i < t.NumPort;i++)\r
+                       {\r
+                               Format(tmp, sizeof(tmp), "%s%u", tmp, t.Ports[i]);\r
+                               if (i != (t.NumPort - 1))\r
+                               {\r
+                                       StrCat(tmp, sizeof(tmp), ", ");\r
+                               }\r
+                       }\r
+                       SetTextA(hWnd, E_PORT, tmp);\r
+               }\r
+               SetTextA(hWnd, E_CONTROLLER, t.ControllerName);\r
+               SetIntEx(hWnd, E_CONTROLLER_PORT, t.ControllerPort);\r
+               SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);\r
+       }\r
+       else\r
+       {\r
+               // ポート一覧を書き込む\r
+               RPC_LISTENER_LIST t;\r
+               char tmp[MAX_PUBLIC_PORT_NUM * 8];\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(tmp, sizeof(tmp), "");\r
+               if (CALL(hWnd, ScEnumListener(p->Rpc, &t)))\r
+               {\r
+                       UINT i;\r
+                       if (t.NumPort != 0)\r
+                       {\r
+                               for (i = 0;i < t.NumPort;i++)\r
+                               {\r
+                                       Format(tmp, sizeof(tmp), "%s%u", tmp, t.Ports[i]);\r
+                                       if (i != (t.NumPort - 1))\r
+                                       {\r
+                                               StrCat(tmp, sizeof(tmp), ", ");\r
+                                       }\r
+                               }\r
+                               SetTextA(hWnd, E_PORT, tmp);\r
+                       }\r
+                       FreeRpcListenerList(&t);\r
+               }\r
+       }\r
+\r
+       SmFarmDlgUpdate(hWnd, p);\r
+\r
+       FreeRpcFarm(&t);\r
+\r
+       Focus(hWnd, IDOK);\r
+}\r
+\r
+// ダイアログ更新\r
+void SmFarmDlgUpdate(HWND hWnd, SM_SERVER *p)\r
+{\r
+       bool ok = true;\r
+       bool farm_member_control = false;\r
+       char *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_MEMBER))\r
+       {\r
+               LIST *o;\r
+               UINT i = IpGetFilledNum(hWnd, E_IP);\r
+               if (i != 0 && i != 4)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               s = GetTextA(hWnd, E_PORT);\r
+               o = SmStrToPortList(s);\r
+               if (o == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+               else\r
+               {\r
+                       ReleaseList(o);\r
+               }\r
+               Free(s);\r
+\r
+               if (IsEmpty(hWnd, E_CONTROLLER))\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               i = GetInt(hWnd, E_CONTROLLER_PORT);\r
+               if (i == 0 || i >= 65536)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               farm_member_control = true;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_STANDALONE))\r
+       {\r
+               Disable(hWnd, S_1);\r
+               Disable(hWnd, S_2);\r
+               Disable(hWnd, E_WEIGHT);\r
+       }\r
+       else\r
+       {\r
+               Enable(hWnd, S_1);\r
+               Enable(hWnd, S_2);\r
+               Enable(hWnd, E_WEIGHT);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_CONTROLLER))\r
+       {\r
+               Enable(hWnd, R_CONTROLLER_ONLY);\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, R_CONTROLLER_ONLY);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_CONTROLLER) || IsChecked(hWnd, R_MEMBER))\r
+       {\r
+               if (GetInt(hWnd, E_WEIGHT) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, S_IP_1, farm_member_control);\r
+       SetEnable(hWnd, E_IP, farm_member_control);\r
+       SetEnable(hWnd, S_IP_2, farm_member_control);\r
+       SetEnable(hWnd, S_PORT_1, farm_member_control);\r
+       SetEnable(hWnd, E_PORT, farm_member_control);\r
+       SetEnable(hWnd, S_PORT_2, farm_member_control);\r
+       SetEnable(hWnd, S_PORT_3, farm_member_control);\r
+       SetEnable(hWnd, E_CONTROLLER, farm_member_control);\r
+       SetEnable(hWnd, S_CONTROLLER, farm_member_control);\r
+       SetEnable(hWnd, E_CONTROLLER_PORT, farm_member_control);\r
+       SetEnable(hWnd, S_CONTROLLER_PORT, farm_member_control);\r
+       SetEnable(hWnd, S_PASSWORD, farm_member_control);\r
+       SetEnable(hWnd, E_PASSWORD, farm_member_control);\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK ボタン\r
+void SmFarmDlgOnOk(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // メッセージ表示\r
+       if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_OKCANCEL | MB_DEFBUTTON2,\r
+               _UU("SM_FARM_REBOOT_MSG")) == IDOK)\r
+       {\r
+               RPC_FARM t;\r
+               Zero(&t, sizeof(t));\r
+               t.ServerType = SERVER_TYPE_STANDALONE;\r
+               if (IsChecked(hWnd, R_CONTROLLER))\r
+               {\r
+                       t.ServerType = SERVER_TYPE_FARM_CONTROLLER;\r
+               }\r
+               if (IsChecked(hWnd, R_MEMBER))\r
+               {\r
+                       t.ServerType = SERVER_TYPE_FARM_MEMBER;\r
+               }\r
+\r
+               t.ControllerOnly = IsChecked(hWnd, R_CONTROLLER_ONLY);\r
+               t.Weight = GetInt(hWnd, E_WEIGHT);\r
+\r
+               if (t.ServerType == SERVER_TYPE_FARM_MEMBER)\r
+               {\r
+                       char *s;\r
+                       char pass[MAX_SIZE];\r
+                       t.PublicIp = IpGet(hWnd, E_IP);\r
+                       s = GetTextA(hWnd, E_PORT);\r
+                       if (s != NULL)\r
+                       {\r
+                               LIST *o = SmStrToPortList(s);\r
+                               if (o != NULL)\r
+                               {\r
+                                       UINT i;\r
+                                       t.NumPort = LIST_NUM(o);\r
+                                       t.Ports = ZeroMalloc(sizeof(UINT) * t.NumPort);\r
+                                       for (i = 0;i < t.NumPort;i++)\r
+                                       {\r
+                                               t.Ports[i] = (UINT)LIST_DATA(o, i);\r
+                                       }\r
+                                       ReleaseList(o);\r
+                               }\r
+                               Free(s);\r
+                       }\r
+                       GetTxtA(hWnd, E_CONTROLLER, t.ControllerName, sizeof(t.ControllerName));\r
+                       t.ControllerPort = GetInt(hWnd, E_CONTROLLER_PORT);\r
+                       GetTxtA(hWnd, E_PASSWORD, pass, sizeof(pass));\r
+                       if (StrCmp(pass, HIDDEN_PASSWORD) != 0)\r
+                       {\r
+                               Hash(t.MemberPassword, pass, StrLen(pass), true);\r
+                       }\r
+               }\r
+\r
+               // 設定更新\r
+               if (CALL(hWnd, ScSetFarmSetting(p->Rpc, &t)) == false)\r
+               {\r
+                       return;\r
+               }\r
+\r
+               FreeRpcFarm(&t);\r
+\r
+               EndDialog(hWnd, true);\r
+       }\r
+}\r
+\r
+// サーバー ファーム ダイアログ プロシージャ\r
+UINT SmFarmDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmFarmDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_STANDALONE:\r
+               case R_CONTROLLER:\r
+               case R_MEMBER:\r
+               case E_IP:\r
+               case E_PORT:\r
+               case E_CONTROLLER:\r
+               case E_CONTROLLER_PORT:\r
+               case E_PASSWORD:\r
+               case R_CONTROLLER_ONLY:\r
+               case E_WEIGHT:\r
+                       SmFarmDlgUpdate(hWnd, p);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmFarmDlgOnOk(hWnd, p);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_MEMBER:\r
+                       if (IsChecked(hWnd, R_MEMBER))\r
+                       {\r
+                               Focus(hWnd, E_IP);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// サーバー ファーム構成\r
+bool SmFarmDlg(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return Dialog(hWnd, D_SM_FARM, SmFarmDlgProc, p);\r
+}\r
+\r
+// コネクション情報の更新\r
+bool SmRefreshConnectionStatus(HWND hWnd, SM_SERVER *p, void *param)\r
+{\r
+       RPC_CONNECTION_INFO t;\r
+       SM_CONNECTION_INFO *info = (SM_CONNECTION_INFO *)param;\r
+       LVB *b;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL || param == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.Name, sizeof(t.Name), info->ConnectionName);\r
+       if (CALL(hWnd, ScGetConnectionInfo(p->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.Name);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_CONNINFO_NAME"), tmp);\r
+\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_TYPE"), SmGetConnectionTypeStr(t.Type));\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.Hostname);\r
+       LvInsertAdd(b, ICO_FARM, NULL, 2, _UU("SM_CONNINFO_HOSTNAME"), tmp);\r
+\r
+       UniToStru(tmp, t.Port);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_CONNINFO_PORT"), tmp);\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_CONNINFO_TIME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.ServerStr);\r
+       LvInsertAdd(b, ICO_VPNSERVER, NULL, 2, _UU("SM_CONNINFO_SERVER_STR"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ServerVer / 100, t.ServerVer % 100);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_SERVER_VER"), tmp);\r
+\r
+       UniToStru(tmp, t.ServerBuild);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_SERVER_BUILD"), tmp);\r
+\r
+       if (StrLen(t.ClientStr) != 0)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), t.ClientStr);\r
+               LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_CONNINFO_CLIENT_STR"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ClientVer / 100, t.ClientVer % 100);\r
+               LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_CLIENT_VER"), tmp);\r
+\r
+               UniToStru(tmp, t.ClientBuild);\r
+               LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_CONNINFO_CLIENT_BUILD"), tmp);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       return true;\r
+}\r
+\r
+// 初期化\r
+void SmConnectionDlgInit(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_PROTOCOL);\r
+       FormatText(hWnd, S_TITLE, p->ServerName);\r
+\r
+       // カラム初期化\r
+       LvInit(hWnd, L_LIST);\r
+       LvSetStyle(hWnd, L_LIST, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SM_CONN_COLUMN_1"), 90);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SM_CONN_COLUMN_2"), 150);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SM_CONN_COLUMN_3"), 200);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SM_CONN_COLUMN_4"), 80);\r
+\r
+       SmConnectionDlgRefresh(hWnd, p);\r
+       SmConnectionDlgUpdate(hWnd, p);\r
+}\r
+\r
+// 更新\r
+void SmConnectionDlgRefresh(HWND hWnd, SM_SERVER *p)\r
+{\r
+       LVB *b;\r
+       UINT i;\r
+       RPC_ENUM_CONNECTION t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumConnection(p->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < t.NumConnection;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               wchar_t name[MAX_SIZE];\r
+               wchar_t datetime[MAX_SIZE];\r
+               RPC_ENUM_CONNECTION_ITEM *e = &t.Connections[i];\r
+\r
+               StrToUni(name, sizeof(name), e->Name);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_HOSTNAME_AND_PORT"), e->Hostname, e->Port);\r
+               GetDateTimeStrEx64(datetime, sizeof(datetime), SystemToLocal64(e->ConnectedTime), NULL);\r
+\r
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 4, name, tmp, datetime,\r
+                       SmGetConnectionTypeStr(e->Type));\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_LIST);\r
+\r
+       FreeRpcEnumConnetion(&t);\r
+}\r
+\r
+// コントロール更新\r
+void SmConnectionDlgUpdate(HWND hWnd, SM_SERVER *p)\r
+{\r
+       bool b = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_LIST) && (LvIsMultiMasked(hWnd, L_LIST) == false))\r
+       {\r
+               b = true;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, b);\r
+       SetEnable(hWnd, B_DISCONNECT, b && p->ServerAdminMode);\r
+}\r
+\r
+// コネクション一覧プロシージャ\r
+UINT SmConnectionDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       NMHDR *n;\r
+       wchar_t *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmConnectionDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // コネクション情報を表示\r
+                       s = LvGetSelectedStr(hWnd, L_LIST, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               wchar_t caption[MAX_SIZE];\r
+                               SM_CONNECTION_INFO info;\r
+                               UniFormat(caption, sizeof(caption), _UU("SM_CONNINFO_CAPTION"),\r
+                                       s);\r
+                               Zero(&info, sizeof(info));\r
+                               info.ConnectionName = CopyUniToStr(s);\r
+                               info.p = p;\r
+                               SmStatusDlg(hWnd, p, &info, false, false, caption, ICO_PROTOCOL,\r
+                                       NULL, SmRefreshConnectionStatus);\r
+                               Free(info.ConnectionName);\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DISCONNECT:\r
+                       // 切断\r
+                       s = LvGetSelectedStr(hWnd, L_LIST, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                                       _UU("SM_CONN_DISCONNECT_MSG"), s) == IDYES)\r
+                               {\r
+                                       char tmp[MAX_SIZE];\r
+                                       RPC_DISCONNECT_CONNECTION t;\r
+\r
+                                       UniToStr(tmp, sizeof(tmp), s);\r
+                                       Zero(&t, sizeof(t));\r
+                                       StrCpy(t.Name, sizeof(t.Name), tmp);\r
+\r
+                                       if (CALL(hWnd, ScDisconnectConnection(p->Rpc, &t)))\r
+                                       {\r
+                                               SmConnectionDlgRefresh(hWnd, p);\r
+                                       }\r
+                               }\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 最新の状態に更新\r
+                       SmConnectionDlgRefresh(hWnd, p);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmConnectionDlgUpdate(hWnd, p);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_LIST);\r
+\r
+       return 0;\r
+}\r
+\r
+// コネクション一覧の表示\r
+void SmConnectionDlg(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_SM_CONNECTION, SmConnectionDlgProc, p);\r
+}\r
+\r
+// コネクション種類文字列の取得\r
+wchar_t *SmGetConnectionTypeStr(UINT type)\r
+{\r
+       return GetConnectionTypeStr(type);\r
+}\r
+\r
+// サーバー情報の更新\r
+bool SmRefreshServerInfo(HWND hWnd, SM_SERVER *p, void *param)\r
+{\r
+       RPC_SERVER_INFO t;\r
+       LVB *b;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScGetServerInfo(p->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       // 製品名\r
+       StrToUni(tmp, sizeof(tmp), t.ServerProductName);\r
+       LvInsertAdd(b, ICO_VPNSERVER, NULL, 2, _UU("SM_INFO_PRODUCT_NAME"), tmp);\r
+\r
+       // バージョン\r
+       StrToUni(tmp, sizeof(tmp), t.ServerVersionString);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("SM_INFO_VERSION"), tmp);\r
+\r
+       // ビルド\r
+       StrToUni(tmp, sizeof(tmp), t.ServerBuildInfoString);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_INFO_BUILD"), tmp);\r
+\r
+       // ホスト名\r
+       StrToUni(tmp, sizeof(tmp), t.ServerHostName);\r
+       LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("SM_INFO_HOSTNAME"), tmp);\r
+\r
+       // 種類\r
+       LvInsertAdd(b, t.ServerType == SERVER_TYPE_STANDALONE ? ICO_SERVER_ONLINE : ICO_FARM, 0,\r
+               2, _UU("SM_ST_SERVER_TYPE"),\r
+               GetServerTypeStr(t.ServerType));\r
+\r
+       // OS\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SYSTEM_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_PRODUCT_NAME"), tmp);\r
+\r
+       if (t.OsInfo.OsServicePack != 0)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_OS_SP_TAG"), t.OsInfo.OsServicePack);\r
+               LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SERVICE_PACK"), tmp);\r
+       }\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VENDER_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VERSION"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_VERSION"), tmp);\r
+\r
+       SmAddServerCaps(b, p->CapsList);\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcServerInfo(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// サーバーの Caps を画面に表示する\r
+void SmAddServerCaps(LVB *b, CAPSLIST *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (b == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < LIST_NUM(t->CapsList);i++)\r
+       {\r
+               CAPS *c = LIST_DATA(t->CapsList, i);\r
+               wchar_t title[MAX_SIZE];\r
+               char name[256];\r
+\r
+               Format(name, sizeof(name), "CT_%s", c->Name);\r
+\r
+               UniStrCpy(title, sizeof(title), _UU(name));\r
+\r
+               if (UniIsEmptyStr(title))\r
+               {\r
+                       UniFormat(title, sizeof(title), L"%S", (StrLen(c->Name) >= 2) ? c->Name + 2 : c->Name);\r
+               }\r
+\r
+               if (StartWith(c->Name, "b_"))\r
+               {\r
+                       bool icon_pass = c->Value == 0 ? false : true;\r
+                       if (StrCmpi(c->Name, "b_must_install_pcap") == 0)\r
+                       {\r
+                               // WinPcap の項目のみ反転する\r
+                               icon_pass = !icon_pass;\r
+                       }\r
+                       LvInsertAdd(b, icon_pass == false ? ICO_DISCARD : ICO_PASS,\r
+                               NULL, 2, title, c->Value == 0 ? _UU("CAPS_NO") : _UU("CAPS_YES"));\r
+               }\r
+               else\r
+               {\r
+                       wchar_t str[64];\r
+                       UniToStru(str, c->Value);\r
+                       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, title, str);\r
+               }\r
+       }\r
+}\r
+\r
+// サーバー状態の更新\r
+bool SmRefreshServerStatus(HWND hWnd, SM_SERVER *p, void *param)\r
+{\r
+       RPC_SERVER_STATUS t;\r
+       LVB *b;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScGetServerStatus(p->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       // サーバーの種類\r
+       LvInsertAdd(b, t.ServerType == SERVER_TYPE_STANDALONE ? ICO_SERVER_ONLINE : ICO_FARM, 0,\r
+               2, _UU("SM_ST_SERVER_TYPE"),\r
+               GetServerTypeStr(t.ServerType));\r
+\r
+       // TCP コネクション数\r
+       UniToStru(tmp, t.NumTcpConnections);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_ST_NUM_TCP"), tmp);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // ローカル TCP コネクション数\r
+               UniToStru(tmp, t.NumTcpConnectionsLocal);\r
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_ST_NUM_TCP_LOCAL"), tmp);\r
+\r
+               // リモート TCP コネクション数\r
+               UniToStru(tmp, t.NumTcpConnectionsRemote);\r
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("SM_ST_NUM_TCP_REMOTE"), tmp);\r
+       }\r
+\r
+       // 仮想 HUB 数\r
+       UniToStru(tmp, t.NumHubTotal);\r
+       LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_ST_NUM_HUB_TOTAL"), tmp);\r
+\r
+       if (t.ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               // スタティック HUB 数\r
+               UniToStru(tmp, t.NumHubStatic);\r
+               LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_ST_NUM_HUB_STATIC"), tmp);\r
+\r
+               // ダイナミック HUB 数\r
+               UniToStru(tmp, t.NumHubDynamic);\r
+               LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_ST_NUM_HUB_DYNAMIC"), tmp);\r
+       }\r
+\r
+       // セッション数\r
+       UniToStru(tmp, t.NumSessionsTotal);\r
+       LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_ST_NUM_SESSION_TOTAL"), tmp);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // ローカルセッション数\r
+               UniToStru(tmp, t.NumSessionsLocal);\r
+               LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_ST_NUM_SESSION_LOCAL"), tmp);\r
+\r
+               // ローカルセッション数\r
+               UniToStru(tmp, t.NumSessionsRemote);\r
+               LvInsertAdd(b, ICO_VPN, NULL, 2, _UU("SM_ST_NUM_SESSION_REMOTE"), tmp);\r
+       }\r
+\r
+       // MAC テーブル数\r
+       UniToStru(tmp, t.NumMacTables);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_ST_NUM_MAC_TABLE"), tmp);\r
+\r
+       // IP テーブル数\r
+       UniToStru(tmp, t.NumIpTables);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_ST_NUM_IP_TABLE"), tmp);\r
+\r
+       // ユーザー数\r
+       UniToStru(tmp, t.NumUsers);\r
+       LvInsertAdd(b, ICO_USER, NULL, 2, _UU("SM_ST_NUM_USERS"), tmp);\r
+\r
+       // グループ数\r
+       UniToStru(tmp, t.NumGroups);\r
+       LvInsertAdd(b, ICO_GROUP, NULL, 2, _UU("SM_ST_NUM_GROUPS"), tmp);\r
+\r
+       // 割り当て済みライセンス数\r
+       UniToStru(tmp, t.AssignedClientLicenses);\r
+       LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_CLIENT_LICENSE"), tmp);\r
+       UniToStru(tmp, t.AssignedBridgeLicenses);\r
+       LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_BRIDGE_LICENSE"), tmp);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               UniToStru(tmp, t.AssignedClientLicensesTotal);\r
+               LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_CLIENT_LICENSE_EX"), tmp);\r
+               UniToStru(tmp, t.AssignedBridgeLicensesTotal);\r
+               LvInsertAdd(b, ICO_CERT, NULL, 2, _UU("SM_ST_BRIDGE_LICENSE_EX"), tmp);\r
+       }\r
+\r
+       // トラフィック\r
+       SmInsertTrafficInfo(b, &t.Traffic);\r
+\r
+       // サーバー起動時刻\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartTime), NULL);\r
+       LvInsertAdd(b, ICO_NULL, NULL, 2, _UU("SM_ST_START_TIME"), tmp);\r
+\r
+       // 現在時刻\r
+       GetDateTimeStrMilli64(str, sizeof(str), SystemToLocal64(t.CurrentTime));\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       LvInsertAdd(b, ICO_NULL, NULL, 2, _UU("SM_ST_CURRENT_TIME"), tmp);\r
+\r
+       // Tick 値\r
+       UniFormat(tmp, sizeof(tmp), L"%I64u", t.CurrentTick);\r
+       LvInsertAdd(b, ICO_NULL, NULL, 2, _UU("SM_ST_CURRENT_TICK"), tmp);\r
+\r
+       // メモリ情報\r
+       if (t.MemInfo.TotalMemory != 0)\r
+       {\r
+               char vv[128];\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.TotalMemory);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_MEMORY"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.UsedMemory);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_MEMORY"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.FreeMemory);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_MEMORY"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.TotalPhys);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_PHYS"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.UsedPhys);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_PHYS"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.FreePhys);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_PHYS"), tmp);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       return true;\r
+}\r
+\r
+// 初期化\r
+void SmSaveKeyPairDlgInit(HWND hWnd, SM_SAVE_KEY_PAIR *s)\r
+{\r
+       UINT current;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       current = MsRegReadInt(REG_CURRENT_USER, SM_REG_KEY, "SavePkcs12");\r
+\r
+       if (current == 1)\r
+       {\r
+               Check(hWnd, R_PKCS12, true);\r
+       }\r
+       else if (current == 2)\r
+       {\r
+               Check(hWnd, R_SECURE, true);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_X509_AND_KEY, true);\r
+       }\r
+\r
+       SmSaveKeyPairDlgUpdate(hWnd, s);\r
+}\r
+\r
+// 更新\r
+void SmSaveKeyPairDlgUpdate(HWND hWnd, SM_SAVE_KEY_PAIR *s)\r
+{\r
+       SECURE_DEVICE *dev;\r
+       bool ok = true;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       dev = GetSecureDevice(SmGetCurrentSecureIdFromReg());\r
+       if (dev == NULL)\r
+       {\r
+               UniStrCpy(tmp, sizeof(tmp), _UU("SEC_CURRENT_NO_DEVICE"));\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("SEC_CURRENT_DEVICE"), dev->DeviceName);\r
+       }\r
+\r
+       SetText(hWnd, S_INFO, tmp);\r
+\r
+       if (IsChecked(hWnd, R_USE_PASS))\r
+       {\r
+               char *s1, *s2;\r
+               s1 = GetTextA(hWnd, E_PASS1);\r
+               s2 = GetTextA(hWnd, E_PASS2);\r
+               if (StrCmp(s1, s2) != 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+               Free(s1);\r
+               Free(s2);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_SECURE))\r
+       {\r
+               if (dev == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, B_SELECT, IsChecked(hWnd, R_SECURE));\r
+       SetEnable(hWnd, B_SECURE_MANAGER, IsChecked(hWnd, R_SECURE));\r
+       SetEnable(hWnd, S_INFO, IsChecked(hWnd, R_SECURE));\r
+\r
+       SetEnable(hWnd, E_PASS1, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));\r
+       SetEnable(hWnd, E_PASS2, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));\r
+       SetEnable(hWnd, S_PASS1, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));\r
+       SetEnable(hWnd, S_PASS2, IsChecked(hWnd, R_USE_PASS) && (IsChecked(hWnd, R_SECURE) == false));\r
+       SetEnable(hWnd, R_USE_PASS, (IsChecked(hWnd, R_SECURE) == false));\r
+       SetEnable(hWnd, S_PASS3, (IsChecked(hWnd, R_SECURE) == false));\r
+       SetEnable(hWnd, S_PASS4, (IsChecked(hWnd, R_SECURE) == false));\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK ボタン\r
+void SmSaveKeyPairDlgOnOk(HWND hWnd, SM_SAVE_KEY_PAIR *s)\r
+{\r
+       UINT pkcs12;\r
+       char pass[MAX_SIZE];\r
+       char *password;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       pkcs12 = 0;\r
+\r
+       if (IsChecked(hWnd, R_PKCS12))\r
+       {\r
+               pkcs12 = 1;\r
+       }\r
+       else if (IsChecked(hWnd, R_SECURE))\r
+       {\r
+               pkcs12 = 2;\r
+       }\r
+       MsRegWriteInt(REG_CURRENT_USER, SM_REG_KEY, "SavePkcs12", pkcs12);\r
+\r
+       if (pkcs12 != 2)\r
+       {\r
+               GetTxtA(hWnd, E_PASS1, pass, sizeof(pass));\r
+\r
+               if (StrLen(pass) != 0)\r
+               {\r
+                       password = pass;\r
+               }\r
+               else\r
+               {\r
+                       password = NULL;\r
+               }\r
+\r
+               if (pkcs12 == false)\r
+               {\r
+                       // X509 と KEY に書き込む\r
+                       wchar_t *x509_name, *key_name;\r
+                       x509_name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");\r
+                       if (x509_name == NULL)\r
+                       {\r
+                               // キャンセル\r
+                               return;\r
+                       }\r
+                       else\r
+                       {\r
+                               wchar_t default_key_name[MAX_SIZE];\r
+                               UniReplaceStrEx(default_key_name, sizeof(default_key_name), x509_name,\r
+                                       L".cer", L"", false);\r
+                               UniReplaceStrEx(default_key_name, sizeof(default_key_name), default_key_name,\r
+                                                               L".crt", L"", false);\r
+                               UniStrCat(default_key_name, sizeof(default_key_name), L".key");\r
+                               key_name = SaveDlg(hWnd, _UU("DLG_KEY_FILTER"), _UU("DLG_SAVE_KEY"),\r
+                                       default_key_name, L".key");\r
+                               if (key_name == NULL)\r
+                               {\r
+                                       // キャンセル\r
+                                       Free(x509_name);\r
+                                       return;\r
+                               }\r
+                               else\r
+                               {\r
+                                       bool ok = true;\r
+                                       char filename1[MAX_SIZE];\r
+                                       char filename2[MAX_SIZE];\r
+\r
+                                       UniToStr(filename1, sizeof(filename1), x509_name);\r
+                                       UniToStr(filename2, sizeof(filename2), key_name);\r
+\r
+                                       // 証明書の保存\r
+                                       if (XToFile(s->Cert, filename1, true) == false)\r
+                                       {\r
+                                               MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));\r
+                                               ok = false;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (KToFile(s->Key, filename2, true, password) == false)\r
+                                               {\r
+                                                       MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_KEY_SAVE_ERROR"));\r
+                                                       ok = false;\r
+                                               }\r
+                                       }\r
+\r
+                                       if (ok)\r
+                                       {\r
+                                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_KEY_PAIR_SAVE_OK"));\r
+                                               EndDialog(hWnd, true);\r
+                                       }\r
+\r
+                                       Free(key_name);\r
+                               }\r
+                               Free(x509_name);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // PKCS#12 に書き込む\r
+                       wchar_t *name = SaveDlg(hWnd, _UU("DLG_PKCS12_FILTER"), _UU("DLG_SAVE_P12"), NULL, L".p12");\r
+                       if (name == NULL)\r
+                       {\r
+                               // キャンセル\r
+                               return;\r
+                       }\r
+                       else\r
+                       {\r
+                               P12 *p12;\r
+                               char filename[MAX_SIZE];\r
+                               UniToStr(filename, sizeof(filename), name);\r
+\r
+                               // PKCS#12 に変換\r
+                               p12 = NewP12(s->Cert, s->Key, pass);\r
+                               if (p12 == NULL)\r
+                               {\r
+                                       // 失敗\r
+                                       MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_KEY_PAIR_SAVE_OK"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       // 保存\r
+                                       if (P12ToFile(p12, filename) == false)\r
+                                       {\r
+                                               // 失敗\r
+                                               MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_KEY_PAIR_SAVE_OK"));\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // 成功\r
+                                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_KEY_PAIR_SAVE_OK"));\r
+                                               EndDialog(hWnd, true);\r
+                                       }\r
+                                       FreeP12(p12);\r
+                               }\r
+\r
+                               Free(name);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               char default_name[MAX_SIZE];\r
+               char *object_name;\r
+               bool ok = false;\r
+               X *x;\r
+               K *k;\r
+               WINUI_SECURE_BATCH batch[] =\r
+               {\r
+                       {WINUI_SECURE_WRITE_CERT, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},\r
+                       {WINUI_SECURE_WRITE_KEY, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},\r
+               };\r
+\r
+               x = s->Cert;\r
+               k = s->Key;\r
+\r
+               // デフォルトの名前を生成する\r
+               GetPrintNameFromXA(default_name, sizeof(default_name), x);\r
+               ConvertSafeFileName(default_name, sizeof(default_name), default_name);\r
+\r
+               object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),\r
+                       _UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_CERT, false, false);\r
+\r
+               if (object_name != NULL)\r
+               {\r
+                       // 書き込みと列挙\r
+                       batch[0].InputX = x;\r
+                       batch[0].Name = object_name;\r
+                       batch[1].InputK = k;\r
+                       batch[1].Name = object_name;\r
+\r
+                       if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), SmGetCurrentSecureIdFromReg(), 0) == false)\r
+                       {\r
+                               // 失敗\r
+                       }\r
+                       else\r
+                       {\r
+                               ok = true;\r
+                       }\r
+\r
+                       Free(object_name);\r
+               }\r
+\r
+               if (ok)\r
+               {\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NEW_CERT_IMPORT_OK"));\r
+\r
+                       EndDialog(hWnd, true);\r
+               }\r
+       }\r
+}\r
+\r
+// 証明書と秘密鍵の保存ダイアログ\r
+UINT SmSaveKeyPairDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SAVE_KEY_PAIR *s = (SM_SAVE_KEY_PAIR *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmSaveKeyPairDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_PASS1:\r
+               case E_PASS2:\r
+               case R_USE_PASS:\r
+               case R_SECURE:\r
+               case R_X509_AND_KEY:\r
+               case R_PKCS12:\r
+                       SmSaveKeyPairDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmSaveKeyPairDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_USE_PASS:\r
+                       if (IsChecked(hWnd, R_USE_PASS))\r
+                       {\r
+                               FocusEx(hWnd, E_PASS1);\r
+                       }\r
+                       break;\r
+\r
+               case B_SELECT:\r
+                       SmSelectSecureId(hWnd);\r
+                       SmSaveKeyPairDlgUpdate(hWnd, s);\r
+                       break;\r
+\r
+               case B_SECURE_MANAGER:\r
+                       CmSecureManagerEx(hWnd, SmGetCurrentSecureId(hWnd), true);\r
+                       SmSaveKeyPairDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 証明書と秘密鍵を保存する\r
+bool SmSaveKeyPairDlg(HWND hWnd, X *x, K *k)\r
+{\r
+       SM_SAVE_KEY_PAIR s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || x == NULL || k == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       s.Cert = x;\r
+       s.Key = k;\r
+\r
+       return Dialog(hWnd,     D_SM_SAVE_KEY_PAIR, SmSaveKeyPairDlgProc, &s);\r
+}\r
+\r
+// SSL 関係ダイアログで OK がクリックされた\r
+void SmSslDlgOnOk(HWND hWnd, SM_SSL *s)\r
+{\r
+       char *name;\r
+       RPC_KEEP t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (s->p->ServerAdminMode == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       name = GetTextA(hWnd, C_CIPHER);\r
+       if (name == NULL)\r
+       {\r
+               return;\r
+       }\r
+       else\r
+       {\r
+               RPC_STR t;\r
+               Zero(&t, sizeof(t));\r
+               t.String = name;\r
+\r
+               // 暗号化アルゴリズムの設定\r
+               if (CALL(hWnd, ScSetServerCipher(s->p->Rpc, &t)) == false)\r
+               {\r
+                       Focus(hWnd, C_CIPHER);\r
+                       return;\r
+               }\r
+               FreeRpcStr(&t);\r
+       }\r
+\r
+       if (s->SetCertAndKey)\r
+       {\r
+               // 証明書のセット\r
+               RPC_KEY_PAIR t;\r
+               Zero(&t, sizeof(t));\r
+\r
+               t.Cert = CloneX(s->Cert);\r
+               t.Key = CloneK(s->Key);\r
+\r
+               if (CALL(hWnd, ScSetServerCert(s->p->Rpc, &t)) == false)\r
+               {\r
+                       return;\r
+               }\r
+               FreeRpcKeyPair(&t);\r
+\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_CERT_SET_MSG"));\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.UseKeepConnect = IsChecked(hWnd, R_USE_KEEP_CONNECT);\r
+       GetTxtA(hWnd, E_HOSTNAME, t.KeepConnectHost, sizeof(t.KeepConnectHost));\r
+       t.KeepConnectPort = GetInt(hWnd, E_PORT);\r
+       t.KeepConnectInterval = GetInt(hWnd, E_INTERVAL);\r
+       t.KeepConnectProtocol = IsChecked(hWnd, R_UDP) ? 1 : 0;\r
+\r
+       CALL(hWnd, ScSetKeep(s->p->Rpc, &t));\r
+\r
+       if (GetCapsBool(s->p->CapsList, "b_support_syslog"))\r
+       {\r
+               if (s->p->ServerAdminMode)\r
+               {\r
+                       SYSLOG_SETTING set;\r
+\r
+                       Zero(&set, sizeof(set));\r
+                       GetTxtA(hWnd, E_SYSLOG_HOSTNAME, set.Hostname, sizeof(set.Hostname));\r
+                       set.Port = GetInt(hWnd, E_SYSLOG_PORT);\r
+                       set.SaveType = CbGetSelect(hWnd, C_SYSLOG);\r
+\r
+                       if (CALL(hWnd, ScSetSysLog(s->p->Rpc, &set)) == false)\r
+                       {\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// SSL 関係ダイアログ初期化\r
+void SmSslDlgInit(HWND hWnd, SM_SSL *s)\r
+{\r
+       UINT i;\r
+       TOKEN_LIST *cipher_list;\r
+       RPC_KEEP t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 暗号化アルゴリズム一覧を設定する\r
+       cipher_list = GetCipherList();\r
+       CbSetHeight(hWnd, C_CIPHER, 18);\r
+       for (i = 0;i < cipher_list->NumTokens;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               char *name = cipher_list->Token[i];\r
+               StrToUni(tmp, sizeof(tmp), name);\r
+               CbAddStr(hWnd, C_CIPHER, tmp, 0);\r
+       }\r
+\r
+       if (s->p != NULL)\r
+       {\r
+               // サーバーから暗号化アルゴリズム名を取得する\r
+               RPC_STR t;\r
+               Zero(&t, sizeof(t));\r
+               if (CALL(hWnd, ScGetServerCipher(s->p->Rpc, &t)))\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       StrToUni(tmp, sizeof(tmp), t.String);\r
+                       SetText(hWnd, C_CIPHER, tmp);\r
+                       FreeRpcStr(&t);\r
+               }\r
+               else\r
+               {\r
+                       EndDialog(hWnd, 0);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (s->p != NULL)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               // サーバーから SSL 証明書と秘密鍵を取得する\r
+               RPC_KEY_PAIR t;\r
+               s->SetCertAndKey = false;\r
+               Zero(&t, sizeof(t));\r
+               if (CALL(hWnd, ScGetServerCert(s->p->Rpc, &t)))\r
+               {\r
+                       // 証明書と鍵のコピー\r
+                       s->Cert = CloneX(t.Cert);\r
+                       s->Key = CloneK(t.Key);\r
+                       FreeRpcKeyPair(&t);\r
+               }\r
+               else\r
+               {\r
+                       EndDialog(hWnd, 0);\r
+                       return;\r
+               }\r
+\r
+               // 証明書情報の表示\r
+               SmGetCertInfoStr(tmp, sizeof(tmp), s->Cert);\r
+               SetText(hWnd, S_CERT_INFO, tmp);\r
+       }\r
+\r
+       // パスワード変更\r
+       SetEnable(hWnd, B_PASSWORD, s->p->ServerAdminMode);\r
+\r
+       // ボタンの有効化 / 無効化\r
+       SetEnable(hWnd, B_IMPORT, s->p->ServerAdminMode);\r
+       SetEnable(hWnd, B_EXPORT, s->p->ServerAdminMode);\r
+       SetEnable(hWnd, R_USE_KEEP_CONNECT, s->p->ServerAdminMode);\r
+\r
+       if (s->p->ServerAdminMode == false)\r
+       {\r
+               Disable(hWnd, C_CIPHER);\r
+       }\r
+\r
+       if (CALL(hWnd, ScGetKeep(s->p->Rpc, &t)))\r
+       {\r
+               Check(hWnd, R_USE_KEEP_CONNECT, t.UseKeepConnect);\r
+               SetTextA(hWnd, E_HOSTNAME, t.KeepConnectHost);\r
+               SetIntEx(hWnd, E_PORT, t.KeepConnectPort);\r
+               SetInt(hWnd, E_INTERVAL, t.KeepConnectInterval);\r
+               Check(hWnd, R_TCP, t.KeepConnectProtocol == 0);\r
+               Check(hWnd, R_UDP, t.KeepConnectProtocol != 0);\r
+       }\r
+\r
+       CbSetHeight(hWnd, C_SYSLOG, 18);\r
+       CbReset(hWnd, C_SYSLOG);\r
+       CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_0"), SYSLOG_NONE);\r
+       CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_1"), SYSLOG_SERVER_LOG);\r
+       CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_2"), SYSLOG_SERVER_AND_HUB_SECURITY_LOG);\r
+       CbAddStr(hWnd, C_SYSLOG, _UU("SM_SYSLOG_3"), SYSLOG_SERVER_AND_HUB_ALL_LOG);\r
+\r
+       if (GetCapsBool(s->p->CapsList, "b_support_syslog"))\r
+       {\r
+               SYSLOG_SETTING set;\r
+\r
+               SetEnable(hWnd, C_SYSLOG, s->p->ServerAdminMode);\r
+               SetEnable(hWnd, E_SYSLOG_HOSTNAME, s->p->ServerAdminMode);\r
+               SetEnable(hWnd, E_SYSLOG_PORT, s->p->ServerAdminMode);\r
+               SetEnable(hWnd, S_01, s->p->ServerAdminMode);\r
+               SetEnable(hWnd, S_02, s->p->ServerAdminMode);\r
+\r
+               Zero(&set, sizeof(set));\r
+\r
+               if (CALL(hWnd, ScGetSysLog(s->p->Rpc, &set)))\r
+               {\r
+                       SetTextA(hWnd, E_SYSLOG_HOSTNAME, set.Hostname);\r
+                       SetInt(hWnd, E_SYSLOG_PORT, set.Port == 0 ? SYSLOG_PORT : set.Port);\r
+                       CbSelect(hWnd, C_SYSLOG, set.SaveType);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, C_SYSLOG);\r
+               Disable(hWnd, E_SYSLOG_HOSTNAME);\r
+               Disable(hWnd, E_SYSLOG_PORT);\r
+               Disable(hWnd, S_01);\r
+               Disable(hWnd, S_02);\r
+       }\r
+\r
+       SmSslDlgUpdate(hWnd, s);\r
+}\r
+\r
+// SSL 関係ダイアログコントロール更新\r
+void SmSslDlgUpdate(HWND hWnd, SM_SSL *s)\r
+{\r
+       bool ok = true;\r
+       bool b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_USE_KEEP_CONNECT))\r
+       {\r
+               UINT i;\r
+               b = true;\r
+               if (IsEmpty(hWnd, E_HOSTNAME))\r
+               {\r
+                       ok = false;\r
+               }\r
+               i = GetInt(hWnd, E_PORT);\r
+               if (i == 0 || i >= 65536)\r
+               {\r
+                       ok = false;\r
+               }\r
+               i = GetInt(hWnd, E_INTERVAL);\r
+               if (i < 5 || i > 600)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       if (IsEnable(hWnd, C_SYSLOG))\r
+       {\r
+               UINT i = CbGetSelect(hWnd, C_SYSLOG);\r
+\r
+               SetEnable(hWnd, E_SYSLOG_HOSTNAME, i != SYSLOG_NONE);\r
+               SetEnable(hWnd, E_SYSLOG_PORT, i != SYSLOG_NONE);\r
+               SetEnable(hWnd, S_01, i != SYSLOG_NONE);\r
+               SetEnable(hWnd, S_02, i != SYSLOG_NONE);\r
+       }\r
+\r
+       SetEnable(hWnd, S_HOSTNAME, b);\r
+       SetEnable(hWnd, E_HOSTNAME, b);\r
+       SetEnable(hWnd, S_PORT, b);\r
+       SetEnable(hWnd, E_PORT, b);\r
+       SetEnable(hWnd, S_INTERVAL, b);\r
+       SetEnable(hWnd, E_INTERVAL, b);\r
+       SetEnable(hWnd, S_INTERVAL2, b);\r
+       SetEnable(hWnd, S_PROTOCOL, b);\r
+       SetEnable(hWnd, R_TCP, b);\r
+       SetEnable(hWnd, R_UDP, b);\r
+       SetEnable(hWnd, S_INFO, b);\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// 証明書情報文字列の取得\r
+void SmGetCertInfoStr(wchar_t *str, UINT size, X *x)\r
+{\r
+       wchar_t subject[MAX_SIZE];\r
+       wchar_t issuer[MAX_SIZE];\r
+       wchar_t date[MAX_SIZE];\r
+       // 引数チェック\r
+       if (x == NULL || str == NULL)\r
+       {\r
+               if (str != NULL)\r
+               {\r
+                       str[0] = 0;\r
+               }\r
+               return;\r
+       }\r
+\r
+       GetPrintNameFromName(subject, sizeof(subject), x->subject_name);\r
+       GetPrintNameFromName(issuer, sizeof(issuer), x->issuer_name);\r
+       GetDateStrEx64(date, sizeof(date), x->notAfter, NULL);\r
+\r
+       UniFormat(str, size, _UU("CM_CERT_INFO"), subject, issuer, date);\r
+}\r
+\r
+// SSL 関係ダイアログプロシージャ\r
+UINT SmSslDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SSL *s = (SM_SSL *)param;\r
+       X *x;\r
+       K *k;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               SmSslDlgInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_USE_KEEP_CONNECT:\r
+               case E_HOSTNAME:\r
+               case E_PORT:\r
+               case E_INTERVAL:\r
+               case R_TCP:\r
+               case R_UDP:\r
+               case C_SYSLOG:\r
+               case E_SYSLOG_HOSTNAME:\r
+               case E_SYSLOG_PORT:\r
+                       SmSslDlgUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // OK ボタン\r
+                       SmSslDlgOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       // キャンセルボタン\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_IMPORT:\r
+                       // インポート\r
+                       if (CmLoadXAndK(hWnd, &x, &k))\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               FreeX(s->Cert);\r
+                               FreeK(s->Key);\r
+                               s->Cert = x;\r
+                               s->Key = k;\r
+                               s->SetCertAndKey = true;\r
+                               // 証明書情報の表示\r
+                               SmGetCertInfoStr(tmp, sizeof(tmp), s->Cert);\r
+                               SetText(hWnd, S_CERT_INFO, tmp);\r
+                       }\r
+                       break;\r
+\r
+               case B_EXPORT:\r
+                       // エクスポート\r
+                       SmSaveKeyPairDlg(hWnd, s->Cert, s->Key);\r
+                       break;\r
+\r
+               case B_VIEW:\r
+                       // 証明書の表示\r
+                       CertDlg(hWnd, s->Cert, NULL, true);\r
+                       break;\r
+\r
+               case B_PASSWORD:\r
+                       // パスワード変更\r
+                       Dialog(hWnd, D_SM_CHANGE_PASSWORD, SmChangeServerPasswordDlg, s->p);\r
+                       break;\r
+\r
+               case R_USE_KEEP_CONNECT:\r
+                       if (IsChecked(hWnd, R_USE_KEEP_CONNECT))\r
+                       {\r
+                               FocusEx(hWnd, E_HOSTNAME);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// SSL 関係ダイアログの表示\r
+void SmSslDlg(HWND hWnd, SM_SERVER *p)\r
+{\r
+       SM_SSL s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       s.p = p;\r
+\r
+       Dialog(hWnd, D_SM_SSL, SmSslDlgProc, &s);\r
+\r
+       // クリーンアップ\r
+       FreeX(s.Cert);\r
+       FreeK(s.Key);\r
+}\r
+\r
+// リスナー作成ダイアログプロシージャ\r
+UINT SmCreateListenerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       UINT port;\r
+       RPC_LISTENER t;\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               Focus(hWnd, E_PORT);\r
+               Disable(hWnd, IDOK);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_PORT:\r
+                       port = GetInt(hWnd, E_PORT);\r
+                       if (port == 0 || port >= 65536)\r
+                       {\r
+                               Disable(hWnd, IDOK);\r
+                       }\r
+                       else\r
+                       {\r
+                               Enable(hWnd, IDOK);\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       port = GetInt(hWnd, E_PORT);\r
+                       Zero(&t, sizeof(t));\r
+                       t.Enable = true;\r
+                       t.Port = port;\r
+                       if (CALL(hWnd, ScCreateListener(p->Rpc, &t)))\r
+                       {\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// リスナー作成ダイアログ\r
+bool SmCreateListenerDlg(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return Dialog(hWnd, D_SM_CREATE_LISTENER, SmCreateListenerDlgProc, p);\r
+}\r
+\r
+// HUB 編集 OK ボタン\r
+void SmEditHubOnOk(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       RPC_CREATE_HUB t;\r
+       char pass1[MAX_SIZE];\r
+       char pass2[MAX_SIZE];\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (s->EditMode)\r
+       {\r
+               StrCpy(hubname, sizeof(hubname), s->HubName);\r
+               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+       }\r
+       else\r
+       {\r
+               GetTxtA(hWnd, E_HUBNAME, t.HubName, sizeof(t.HubName));\r
+               StrCpy(hubname, sizeof(hubname), t.HubName);\r
+       }\r
+\r
+       GetTxtA(hWnd, E_PASSWORD1, pass1, sizeof(pass1));\r
+       GetTxtA(hWnd, E_PASSWORD2, pass2, sizeof(pass2));\r
+\r
+       if (s->EditMode == false || StrCmp(pass1, HIDDEN_PASSWORD) != 0)\r
+       {\r
+               Hash(t.HashedPassword, pass1, StrLen(pass1), true);\r
+               HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass1);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_LIMIT_MAX_SESSION))\r
+       {\r
+               t.HubOption.MaxSession = GetInt(hWnd, E_MAX_SESSION);\r
+       }\r
+\r
+       t.Online = IsChecked(hWnd, R_ONLINE);\r
+\r
+       if (s->p->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               t.HubType = HUB_TYPE_FARM_STATIC;\r
+               if (IsChecked(hWnd, R_DYNAMIC))\r
+               {\r
+                       t.HubType = HUB_TYPE_FARM_DYNAMIC;\r
+               }\r
+       }\r
+\r
+       t.HubOption.NoEnum = IsChecked(hWnd, R_NO_ENUM);\r
+\r
+       if (s->EditMode == false)\r
+       {\r
+               if (CALL(hWnd, ScCreateHub(s->p->Rpc, &t)))\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_EDIT_HUB_CREATER"), hubname);\r
+                       EndDialog(hWnd, true);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (CALL(hWnd, ScSetHub(s->p->Rpc, &t)))\r
+               {\r
+                       EndDialog(hWnd, true);\r
+               }\r
+       }\r
+}\r
+\r
+// HUB 編集更新\r
+void SmEditHubUpdate(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       bool ok = true;\r
+       char *s1, *s2;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s1 = GetTextA(hWnd, E_PASSWORD1);\r
+       s2 = GetTextA(hWnd, E_PASSWORD2);\r
+       if (StrCmp(s1, s2) != 0)\r
+       {\r
+               ok = false;\r
+       }\r
+       Free(s1);\r
+       Free(s2);\r
+\r
+       GetTxtA(hWnd, E_HUBNAME, hubname, sizeof(hubname));\r
+       Trim(hubname);\r
+       if (StrLen(hubname) == 0 ||\r
+               IsSafeStr(hubname) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_LIMIT_MAX_SESSION))\r
+       {\r
+               Enable(hWnd, E_MAX_SESSION);\r
+               Enable(hWnd, S_MAX_SESSION_1);\r
+               Enable(hWnd, S_MAX_SESSION_2);\r
+               if (GetInt(hWnd, E_MAX_SESSION) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, E_MAX_SESSION);\r
+               Disable(hWnd, S_MAX_SESSION_1);\r
+               Disable(hWnd, S_MAX_SESSION_2);\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// HUB 編集初期化\r
+void SmEditHubInit(HWND hWnd, SM_EDIT_HUB *s)\r
+{\r
+       RPC_CREATE_HUB t;\r
+       bool b = false;\r
+       bool support_extoption = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_HUB);\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       if (s->EditMode == false)\r
+       {\r
+               // 新規作成\r
+               SetText(hWnd, 0, _UU("CM_EDIT_HUB_1"));\r
+               FocusEx(hWnd, E_HUBNAME);\r
+\r
+               if (s->p->ServerType == SERVER_TYPE_STANDALONE)\r
+               {\r
+                       // スタンドアロン モード\r
+                       Disable(hWnd, R_STATIC);\r
+                       Disable(hWnd, R_DYNAMIC);\r
+                       SetText(hWnd, S_FARM_INFO, _UU("CM_EDIT_HUB_STANDALONE"));\r
+               }\r
+               else\r
+               {\r
+                       Check(hWnd, R_STATIC, true);\r
+               }\r
+\r
+               Check(hWnd, R_ONLINE, true);\r
+\r
+               Hide(hWnd, B_ACL);\r
+               Hide(hWnd, S_ACL);\r
+               Hide(hWnd, S_ACL_2);\r
+               Hide(hWnd, S_ACL_3);\r
+               Hide(hWnd, S_MSG_1);\r
+               Hide(hWnd, S_MSG_4);\r
+               Hide(hWnd, S_MSG_2);\r
+               Hide(hWnd, B_MSG);\r
+       }\r
+       else\r
+       {\r
+               // 編集\r
+               wchar_t tmp[MAX_SIZE];\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_EDIT_HUB_2"), s->HubName);\r
+               SetText(hWnd, 0, tmp);\r
+               SetTextA(hWnd, E_HUBNAME, s->HubName);\r
+               Disable(hWnd, E_HUBNAME);\r
+\r
+               if (s->p->ServerType == SERVER_TYPE_STANDALONE)\r
+               {\r
+                       // スタンドアロン モード\r
+                       Disable(hWnd, R_STATIC);\r
+                       Disable(hWnd, R_DYNAMIC);\r
+                       SetText(hWnd, S_FARM_INFO, _UU("CM_EDIT_HUB_STANDALONE"));\r
+               }\r
+\r
+               if (s->p->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       // コントローラ\r
+                       if (GetCapsBool(s->p->CapsList, "b_cluster_hub_type_fixed"))\r
+                       {\r
+                               Disable(hWnd, R_STATIC);\r
+                               Disable(hWnd, R_DYNAMIC);\r
+                               SetText(hWnd, S_FARM_INFO, _UU("CM_EDIT_HUB_TYPE_FIXED"));\r
+                       }\r
+               }\r
+\r
+               // HUB 情報の取得\r
+               StrCpy(t.HubName, sizeof(t.HubName), s->HubName);\r
+               if (CALL(hWnd, ScGetHub(s->p->Rpc, &t)) == false)\r
+               {\r
+                       EndDialog(hWnd, false);\r
+                       return;\r
+               }\r
+\r
+               SetTextA(hWnd, E_PASSWORD1, HIDDEN_PASSWORD);\r
+               SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);\r
+\r
+               if (t.HubOption.MaxSession == 0)\r
+               {\r
+                       Check(hWnd, R_LIMIT_MAX_SESSION, false);\r
+               }\r
+               else\r
+               {\r
+                       Check(hWnd, R_LIMIT_MAX_SESSION, true);\r
+               }\r
+\r
+               Check(hWnd, R_NO_ENUM, t.HubOption.NoEnum);\r
+\r
+               SetIntEx(hWnd, E_MAX_SESSION, t.HubOption.MaxSession);\r
+\r
+               Check(hWnd, R_ONLINE, t.Online);\r
+               Check(hWnd, R_OFFLINE, t.Online ? false : true);\r
+\r
+               Check(hWnd, R_STATIC, t.HubType == HUB_TYPE_FARM_STATIC);\r
+               Check(hWnd, R_DYNAMIC, t.HubType == HUB_TYPE_FARM_DYNAMIC);\r
+\r
+               SetShow(hWnd, B_ACL, GetCapsBool(s->p->CapsList, "b_support_ac"));\r
+               SetShow(hWnd, S_ACL, GetCapsBool(s->p->CapsList, "b_support_ac"));\r
+               SetShow(hWnd, S_ACL_2, GetCapsBool(s->p->CapsList, "b_support_ac"));\r
+               SetShow(hWnd, S_ACL_3, GetCapsBool(s->p->CapsList, "b_support_ac"));\r
+\r
+               SetShow(hWnd, S_MSG_1, GetCapsBool(s->p->CapsList, "b_support_msg"));\r
+               SetShow(hWnd, S_MSG_4, GetCapsBool(s->p->CapsList, "b_support_msg"));\r
+               SetShow(hWnd, S_MSG_2, GetCapsBool(s->p->CapsList, "b_support_msg"));\r
+               SetShow(hWnd, B_MSG, GetCapsBool(s->p->CapsList, "b_support_msg"));\r
+       }\r
+\r
+       // 拡張オプション\r
+       if (s->EditMode)\r
+       {\r
+               support_extoption = GetCapsBool(s->p->CapsList, "b_support_hub_ext_options");\r
+       }\r
+\r
+       SetEnable(hWnd, S_STATIC, support_extoption);\r
+       SetEnable(hWnd, B_EXTOPTION, support_extoption);\r
+\r
+       SetEnable(hWnd, R_NO_ENUM, GetCapsBool(s->p->CapsList, "b_support_hide_hub"));\r
+\r
+       SmEditHubUpdate(hWnd, s);\r
+\r
+       if (s->EditMode)\r
+       {\r
+               Focus(hWnd, IDOK);\r
+       }\r
+\r
+       if (s->EditMode)\r
+       {\r
+               if (GetCapsBool(s->p->CapsList, "b_support_hub_admin_option"))\r
+               {\r
+                       b = true;\r
+               }\r
+       }\r
+\r
+       SetShow(hWnd, S_AO_1, b);\r
+       SetShow(hWnd, S_AO_2, b);\r
+       SetShow(hWnd, S_AO_3, b);\r
+       SetShow(hWnd, B_ADMINOPTION, b);\r
+}\r
+\r
+// HUB 編集プロシージャ\r
+UINT SmEditHubProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_HUB *s = (SM_EDIT_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmEditHubInit(hWnd, s);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_PASSWORD1:\r
+               case E_PASSWORD2:\r
+               case E_HUBNAME:\r
+               case R_LIMIT_MAX_SESSION:\r
+               case E_MAX_SESSION:\r
+                       SmEditHubUpdate(hWnd, s);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       SmEditHubOnOk(hWnd, s);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_LIMIT_MAX_SESSION:\r
+                       if (IsChecked(hWnd, R_LIMIT_MAX_SESSION))\r
+                       {\r
+                               FocusEx(hWnd, E_MAX_SESSION);\r
+                       }\r
+                       break;\r
+\r
+               case B_ADMINOPTION:\r
+                       SmHubAdminOption(hWnd, s);\r
+                       break;\r
+\r
+               case B_EXTOPTION:\r
+                       SmHubExtOption(hWnd, s);\r
+                       break;\r
+\r
+               case B_ACL:\r
+                       SmHubAc(hWnd, s);\r
+                       break;\r
+\r
+               case B_MSG:\r
+                       SmHubMsg(hWnd, s);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// HUB 編集ダイアログ\r
+bool SmEditHubDlg(HWND hWnd, SM_SERVER *p, char *hubname)\r
+{\r
+       SM_EDIT_HUB s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       s.p = p;\r
+       s.EditMode = true;\r
+       StrCpy(s.HubName, sizeof(s.HubName), hubname);\r
+\r
+       if (p->Bridge == false)\r
+       {\r
+               return Dialog(hWnd, D_SM_EDIT_HUB, SmEditHubProc, &s);\r
+       }\r
+       else\r
+       {\r
+               SmHubExtOption(hWnd, &s);\r
+               return false;\r
+       }\r
+}\r
+\r
+// HUB 作成ダイアログ\r
+bool SmCreateHubDlg(HWND hWnd, SM_SERVER *p)\r
+{\r
+       SM_EDIT_HUB s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       s.p = p;\r
+       s.EditMode = false;\r
+\r
+       return Dialog(hWnd, D_SM_EDIT_HUB, SmEditHubProc, &s);\r
+}\r
+\r
+// 仮想 HUB 状態の表示\r
+bool SmRefreshHubStatus(HWND hWnd, SM_SERVER *p, void *param)\r
+{\r
+       RPC_HUB_STATUS t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL || param == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(RPC_HUB_STATUS));\r
+       StrCpy(t.HubName, sizeof(t.HubName), (char *)param);\r
+       if (CALL(hWnd, ScGetHubStatus(p->Rpc, &t)))\r
+       {\r
+               wchar_t *s;\r
+               wchar_t tmp[MAX_SIZE];\r
+               LVB *b = LvInsertStart();\r
+\r
+               // HUB 名\r
+               s = CopyStrToUni((char *)param);\r
+               LvInsertAdd(b, ICO_HUB, 0, 2, _UU("SM_HUB_STATUS_HUBNAME"), s);\r
+               Free(s);\r
+\r
+               // オンライン\r
+               LvInsertAdd(b, t.Online ? ICO_PROTOCOL : ICO_PROTOCOL_X, 0, 2, _UU("SM_HUB_STATUS_ONLINE"),\r
+                       t.Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"));\r
+\r
+               // HUB の種類\r
+               LvInsertAdd(b, t.HubType == HUB_TYPE_STANDALONE ? ICO_TOWER : ICO_FARM, 0, 2, _UU("SM_HUB_TYPE"),\r
+                       GetHubTypeStr(t.HubType));\r
+\r
+               if (t.HubType == HUB_TYPE_STANDALONE)\r
+               {\r
+                       // SecureNAT の有効/無効\r
+                       LvInsertAdd(b, ICO_ROUTER, NULL, 2, _UU("SM_HUB_SECURE_NAT"),\r
+                               t.SecureNATEnabled ? _UU("SM_HUB_SECURE_NAT_YES") : _UU("SM_HUB_SECURE_NAT_NO"));\r
+               }\r
+\r
+               // その他の値\r
+               UniToStru(tmp, t.NumSessions);\r
+               LvInsertAdd(b, ICO_PROTOCOL, 0, 2, _UU("SM_HUB_NUM_SESSIONS"), tmp);\r
+               if (t.NumSessionsClient != 0 || t.NumSessionsBridge != 0)\r
+               {\r
+                       UniToStru(tmp, t.NumSessionsClient);\r
+                       LvInsertAdd(b, ICO_PROTOCOL, 0, 2, _UU("SM_HUB_NUM_SESSIONS_CLIENT"), tmp);\r
+                       UniToStru(tmp, t.NumSessionsBridge);\r
+                       LvInsertAdd(b, ICO_PROTOCOL, 0, 2, _UU("SM_HUB_NUM_SESSIONS_BRIDGE"), tmp);\r
+               }\r
+\r
+               UniToStru(tmp, t.NumAccessLists);\r
+               LvInsertAdd(b, ICO_DISCARD, 0, 2, _UU("SM_HUB_NUM_ACCESSES"), tmp);\r
+\r
+               if (p->ServerType != SERVER_TYPE_FARM_MEMBER)\r
+               {\r
+                       UniToStru(tmp, t.NumUsers);\r
+                       LvInsertAdd(b, ICO_USER, 0, 2, _UU("SM_HUB_NUM_USERS"), tmp);\r
+                       UniToStru(tmp, t.NumGroups);\r
+                       LvInsertAdd(b, ICO_GROUP, 0, 2, _UU("SM_HUB_NUM_GROUPS"), tmp);\r
+               }\r
+\r
+               UniToStru(tmp, t.NumMacTables);\r
+               LvInsertAdd(b, ICO_MACHINE, 0, 2, _UU("SM_HUB_NUM_MAC_TABLES"), tmp);\r
+               UniToStru(tmp, t.NumIpTables);\r
+               LvInsertAdd(b, ICO_MACHINE, 0, 2, _UU("SM_HUB_NUM_IP_TABLES"), tmp);\r
+\r
+               // 利用状況\r
+               UniToStru(tmp, t.NumLogin);\r
+               LvInsertAdd(b, ICO_KEY, NULL, 2, _UU("SM_HUB_NUM_LOGIN"), tmp);\r
+\r
+               if (t.LastLoginTime != 0)\r
+               {\r
+                       GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastLoginTime));\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));\r
+               }\r
+               LvInsertAdd(b, ICO_DATETIME, NULL, 2, _UU("SM_HUB_LAST_LOGIN_TIME"), tmp);\r
+\r
+               if (t.LastCommTime != 0)\r
+               {\r
+                       GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastCommTime));\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));\r
+               }\r
+               LvInsertAdd(b, ICO_DATETIME, NULL, 2, _UU("SM_HUB_LAST_COMM_TIME"), tmp);\r
+\r
+               if (t.CreatedTime != 0)\r
+               {\r
+                       GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime));\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));\r
+               }\r
+               LvInsertAdd(b, ICO_DATETIME, NULL, 2, _UU("SM_HUB_CREATED_TIME"), tmp);\r
+\r
+               // トラフィック情報\r
+               SmInsertTrafficInfo(b, &t.Traffic);\r
+\r
+               LvInsertEnd(b, hWnd, L_STATUS);\r
+       }\r
+       else\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// トラフィック情報を LVB に追加\r
+void SmInsertTrafficInfo(LVB *b, TRAFFIC *t)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char vv[128];\r
+       // 引数チェック\r
+       if (b == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 送信情報\r
+       ToStr3(vv, sizeof(vv), t->Send.UnicastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_UCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Send.UnicastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_UCAST_SIZE"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Send.BroadcastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_BCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Send.BroadcastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_SEND_BCAST_SIZE"), tmp);\r
+\r
+       // 受信情報\r
+       ToStr3(vv, sizeof(vv), t->Recv.UnicastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_UCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Recv.UnicastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_UCAST_SIZE"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Recv.BroadcastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_BCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Recv.BroadcastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       LvInsertAdd(b, ICO_INFORMATION, 0, 2, _UU("SM_ST_RECV_BCAST_SIZE"), tmp);\r
+}\r
+\r
+// ステータス表示ダイアログプロシージャ\r
+UINT SmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_STATUS *s = (SM_STATUS *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               // 初期化\r
+               LvInitEx(hWnd, L_STATUS, s->NoImage);\r
+               LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);\r
+               SetIcon(hWnd, 0, s->Icon);\r
+               SetIcon(hWnd, S_ICON, s->Icon);\r
+               SetText(hWnd, 0, s->Caption);\r
+               SetText(hWnd, S_TITLE, s->Caption);\r
+               DlgFont(hWnd, S_TITLE, 15, true);\r
+               if (s->InitProc != NULL)\r
+               {\r
+                       s->InitProc(hWnd, s->p, s->Param);\r
+               }\r
+               else\r
+               {\r
+                       // カラム初期化\r
+                       LvInsertColumn(hWnd, L_STATUS, 0, _UU("SM_STATUS_COLUMN_1"), 0);\r
+                       LvInsertColumn(hWnd, L_STATUS, 1, _UU("SM_STATUS_COLUMN_2"), 0);\r
+               }\r
+               if (s->RefreshProc(hWnd, s->p, s->Param) == false)\r
+               {\r
+                       Close(hWnd);\r
+               }\r
+               LvAutoSize(hWnd, L_STATUS);\r
+               Focus(hWnd, L_STATUS);\r
+\r
+               if (s->show_refresh_button == false)\r
+               {\r
+                       Hide(hWnd, IDOK);\r
+               }\r
+\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // 更新\r
+                       if (s->RefreshProc(hWnd, s->p, s->Param) == false)\r
+                       {\r
+                               Close(hWnd);\r
+                       }\r
+                       LvAutoSize(hWnd, L_STATUS);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_STATUS);\r
+\r
+       return 0;\r
+}\r
+\r
+// ステータス表示ダイアログ\r
+void SmStatusDlg(HWND hWnd, SM_SERVER *p, void *param, bool no_image, bool show_refresh_button, wchar_t *caption, UINT icon,\r
+                                SM_STATUS_INIT_PROC *init, SM_STATUS_REFRESH_PROC *refresh)\r
+{\r
+       SM_STATUS s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL || refresh == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (icon == 0)\r
+       {\r
+               icon = ICO_INFORMATION;\r
+       }\r
+       if (caption == NULL)\r
+       {\r
+               caption = _UU("SM_INFORMATION");\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       s.show_refresh_button = show_refresh_button;\r
+       s.p = p;\r
+       s.NoImage = no_image;\r
+       s.Param = param;\r
+       s.Icon = icon;\r
+       s.Caption = caption;\r
+       s.InitProc = init;\r
+       s.RefreshProc = refresh;\r
+\r
+       Dialog(hWnd, D_SM_STATUS, SmStatusDlgProc, &s);\r
+}\r
+\r
+// サーバー管理ダイアログ更新\r
+void SmServerDlgUpdate(HWND hWnd, SM_SERVER *p)\r
+{\r
+       bool hub_selected = false;\r
+       bool hub_selected_online = false;\r
+       bool hub_selected_offline = false;\r
+       bool hub_have_admin_right = false;\r
+       bool listener_selected = false;\r
+       bool listener_selected_enabled = false;\r
+       bool listener_selected_disabled = false;\r
+       bool two_or_more_listener = false;\r
+       bool bridge;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       bridge = GetCapsBool(p->CapsList, "b_bridge");\r
+\r
+       hub_selected = LvIsSelected(hWnd, L_HUB);\r
+\r
+       if (hub_selected)\r
+       {\r
+               if (p->ServerAdminMode)\r
+               {\r
+                       hub_have_admin_right = true;\r
+               }\r
+               i = LvGetSelected(hWnd, L_HUB);\r
+               if (i != INFINITE)\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_HUB, i, 1);\r
+                       if (p->ServerAdminMode == false)\r
+                       {\r
+                               char *hubname = LvGetStrA(hWnd, L_HUB, i, 0);\r
+                               if (hubname != NULL)\r
+                               {\r
+                                       if (StrCmpi(hubname, p->HubName) == 0)\r
+                                       {\r
+                                               hub_have_admin_right = true;\r
+                                       }\r
+                                       Free(hubname);\r
+                               }\r
+                       }\r
+                       hub_selected_online = (UniStrCmpi(s, _UU("SM_HUB_ONLINE")) == 0);\r
+                       hub_selected_offline = hub_selected_online ? false : true;\r
+                       Free(s);\r
+               }\r
+       }\r
+\r
+       listener_selected = LvIsSelected(hWnd, L_LISTENER);\r
+       if (listener_selected)\r
+       {\r
+               wchar_t *s = LvGetSelectedStr(hWnd, L_LISTENER, 1);\r
+               if (UniStrCmpi(s, _UU("CM_LISTENER_OFFLINE")) == 0)\r
+               {\r
+                       listener_selected_disabled = true;\r
+               }\r
+               else\r
+               {\r
+                       listener_selected_enabled = true;\r
+               }\r
+               Free(s);\r
+       }\r
+\r
+       if (LvNum(hWnd, L_LISTENER) >= 2)\r
+       {\r
+               two_or_more_listener = true;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, bridge || (hub_selected && hub_have_admin_right));\r
+       SetEnable(hWnd, B_ONLINE, bridge == false && hub_selected_offline && hub_have_admin_right && p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+       SetEnable(hWnd, B_OFFLINE, bridge == false && hub_selected_online && hub_have_admin_right && p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+       SetEnable(hWnd, B_HUB_STATUS, hub_selected && hub_have_admin_right);\r
+       SetEnable(hWnd, B_DELETE, bridge == false && hub_selected && p->ServerAdminMode && p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+       SetEnable(hWnd, B_EDIT, hub_selected && hub_have_admin_right && p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+       SetEnable(hWnd, B_CREATE, bridge == false && p->ServerAdminMode && p->ServerType != SERVER_TYPE_FARM_MEMBER);\r
+\r
+       SetEnable(hWnd, B_CREATE_LISTENER, p->ServerAdminMode);\r
+       SetEnable(hWnd, B_DELETE_LISTENER, p->ServerAdminMode && listener_selected && two_or_more_listener);\r
+       SetEnable(hWnd, B_START, p->ServerAdminMode && listener_selected_disabled);\r
+       SetEnable(hWnd, B_STOP, p->ServerAdminMode && listener_selected_enabled);\r
+       SetEnable(hWnd, B_FARM, GetCapsBool(p->CapsList, "b_support_cluster") && p->ServerAdminMode);\r
+       SetEnable(hWnd, B_FARM_STATUS, GetCapsBool(p->CapsList, "b_support_cluster") && p->ServerType != SERVER_TYPE_STANDALONE);\r
+}\r
+\r
+// サーバー管理ダイアログ初期化\r
+void SmServerDlgInit(HWND hWnd, SM_SERVER *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // カラム初期化\r
+       LvInit(hWnd, L_HUB);\r
+       LvSetStyle(hWnd, L_HUB, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_HUB, 0, _UU("SM_HUB_COLUMN_1"), 150);\r
+       LvInsertColumn(hWnd, L_HUB, 1, _UU("SM_HUB_COLUMN_2"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 2, _UU("SM_HUB_COLUMN_3"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 3, _UU("SM_HUB_COLUMN_4"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 4, _UU("SM_HUB_COLUMN_5"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 5, _UU("SM_HUB_COLUMN_6"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 6, _UU("SM_HUB_COLUMN_7"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 7, _UU("SM_HUB_COLUMN_8"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 8, _UU("SM_HUB_COLUMN_9"), 80);\r
+       LvInsertColumn(hWnd, L_HUB, 9, _UU("SM_HUB_COLUMN_10"), 120);\r
+       LvInsertColumn(hWnd, L_HUB, 10, _UU("SM_HUB_COLUMN_11"), 120);\r
+\r
+       LvInit(hWnd, L_LISTENER);\r
+       LvSetStyle(hWnd, L_LISTENER, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_LISTENER, 0, _UU("CM_LISTENER_COLUMN_1"), 90);\r
+       LvInsertColumn(hWnd, L_LISTENER, 1, _UU("CM_LISTENER_COLUMN_2"), 80);\r
+\r
+       SmServerDlgRefresh(hWnd, p);\r
+\r
+       if (p->ServerAdminMode == false)\r
+       {\r
+               // 仮想 HUB 管理モードの場合は唯一の HUB を選択する\r
+               wchar_t *s = CopyStrToUni(p->HubName);\r
+               LvSelect(hWnd, L_HUB, LvSearchStr(hWnd, L_HUB, 0, s));\r
+               Free(s);\r
+       }\r
+       else\r
+       {\r
+               // サーバー全体の管理モードの場合\r
+               UINT num_hubs = LvNum(hWnd, L_HUB);\r
+\r
+               if (num_hubs == 1)\r
+               {\r
+                       // 仮想 HUB が 1 個の場合は必ずその仮想 HUB を選択する\r
+                       LvSelect(hWnd, L_HUB, 0);\r
+               }\r
+               else\r
+               {\r
+                       // 仮想 HUB が複数個ある場合は前回最後に選択した仮想 HUB を選択する\r
+                       char tmp[MAX_SIZE];\r
+                       char *hubname;\r
+\r
+                       Format(tmp, sizeof(tmp), "%s:%u:%s", p->CurrentSetting->ClientOption.Hostname,\r
+                               p->CurrentSetting->ClientOption.Port,\r
+                               p->CurrentSetting->ServerAdminMode ? "" : p->CurrentSetting->HubName);\r
+\r
+                       hubname = MsRegReadStr(REG_CURRENT_USER, SM_LASTHUB_REG_KEY, tmp);\r
+\r
+                       if (IsEmptyStr(hubname) == false)\r
+                       {\r
+                               LvSelect(hWnd, L_HUB, LvSearchStrA(hWnd, L_HUB, 0, hubname));\r
+                       }\r
+\r
+                       Free(hubname);\r
+               }\r
+       }\r
+\r
+       Focus(hWnd, L_HUB);\r
+\r
+       SmServerDlgUpdate(hWnd, p);\r
+\r
+       if (GetCapsBool(p->CapsList, "b_bridge"))\r
+       {\r
+               Disable(hWnd, L_HUB);\r
+       }\r
+\r
+       // ローカルブリッジボタン等はサーバーの Admin の場合に有効にする\r
+       SetEnable(hWnd, B_BRIDGE, GetCapsBool(p->CapsList, "b_local_bridge") && p->ServerAdminMode);\r
+       SetEnable(hWnd, B_CONNECTION, p->ServerAdminMode);\r
+\r
+       // Config R/W ボタン\r
+       SetEnable(hWnd, B_CONFIG, GetCapsBool(p->CapsList, "b_support_config_rw") && p->ServerAdminMode);\r
+\r
+       // レイヤ 3 ボタン\r
+       SetEnable(hWnd, B_L3, GetCapsBool(p->CapsList, "b_support_layer3") && p->ServerAdminMode);\r
+\r
+       // ライセンスボタン\r
+       SetShow(hWnd, B_LICENSE, GetCapsBool(p->CapsList, "b_support_license") && p->ServerAdminMode);\r
+       SetShow(hWnd, S_LICENSE, GetCapsBool(p->CapsList, "b_support_license") && p->ServerAdminMode);\r
+       SetShow(hWnd, S_BETA, GetCapsBool(p->CapsList, "b_beta_version") && (IsShow(hWnd, B_LICENSE) == false));\r
+\r
+       DlgFont(hWnd, S_BETA, 12, false);\r
+}\r
+\r
+// サーバー管理ダイアログ更新\r
+void SmServerDlgRefresh(HWND hWnd, SM_SERVER *p)\r
+{\r
+       RPC_ENUM_HUB t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 仮想 HUB リスト更新\r
+       Zero(&t, sizeof(t));\r
+       if (CALL(hWnd, ScEnumHub(p->Rpc, &t)))\r
+       {\r
+               LVB *b = LvInsertStart();\r
+               for (i = 0;i < t.NumHub;i++)\r
+               {\r
+                       RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];\r
+                       wchar_t name[MAX_HUBNAME_LEN + 1];\r
+                       wchar_t s1[64], s2[64], s3[64], s4[64], s5[64];\r
+                       wchar_t s6[64], s7[128], s8[128];\r
+                       UniToStru(s1, e->NumUsers);\r
+                       UniToStru(s2, e->NumGroups);\r
+                       UniToStru(s3, e->NumSessions);\r
+                       UniToStru(s4, e->NumMacTables);\r
+                       UniToStru(s5, e->NumIpTables);\r
+\r
+                       UniToStru(s6, e->NumLogin);\r
+\r
+                       if (e->LastLoginTime != 0)\r
+                       {\r
+                               GetDateTimeStr64Uni(s7, sizeof(s7), SystemToLocal64(e->LastLoginTime));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniStrCpy(s7, sizeof(s7), _UU("COMMON_UNKNOWN"));\r
+                       }\r
+\r
+                       if (e->LastCommTime != 0)\r
+                       {\r
+                               GetDateTimeStr64Uni(s8, sizeof(s8), SystemToLocal64(e->LastCommTime));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniStrCpy(s8, sizeof(s8), _UU("COMMON_UNKNOWN"));\r
+                       }\r
+\r
+                       StrToUni(name, sizeof(name), e->HubName);\r
+\r
+                       LvInsertAdd(b,\r
+                               e->Online ? ICO_HUB : ICO_HUB_OFFLINE,\r
+                               NULL,\r
+                               11,\r
+                               name,\r
+                               e->Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"),\r
+                               GetHubTypeStr(e->HubType),\r
+                               s1, s2, s3, s4, s5, s6, s7, s8);\r
+               }\r
+               LvInsertEnd(b, hWnd, L_HUB);\r
+               FreeRpcEnumHub(&t);\r
+       }\r
+\r
+       // リスナーリスト更新\r
+       if (p != NULL)\r
+       {\r
+               RPC_LISTENER_LIST t;\r
+               Zero(&t, sizeof(RPC_LISTENER_LIST));\r
+               if (CALL(hWnd, ScEnumListener(p->Rpc, &t)))\r
+               {\r
+                       LVB *b = LvInsertStart();\r
+                       for (i = 0;i < t.NumPort;i++)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               wchar_t *status;\r
+                               UINT icon;\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_LISTENER_TCP_PORT"), t.Ports[i]);\r
+\r
+                               status = _UU("CM_LISTENER_ONLINE");\r
+                               icon = ICO_PROTOCOL;\r
+                               if (t.Errors[i])\r
+                               {\r
+                                       status = _UU("CM_LISTENER_ERROR");\r
+                                       icon = ICO_PROTOCOL_X;\r
+                               }\r
+                               else if (t.Enables[i] == false)\r
+                               {\r
+                                       status = _UU("CM_LISTENER_OFFLINE");\r
+                                       icon = ICO_PROTOCOL_OFFLINE;\r
+                               }\r
+\r
+                               LvInsertAdd(b, icon, (void *)t.Ports[i], 2, tmp, status);\r
+                       }\r
+                       LvInsertEnd(b, hWnd, L_LISTENER);\r
+                       FreeRpcListenerList(&t);\r
+               }\r
+       }\r
+\r
+       SmServerDlgUpdate(hWnd, p);\r
+}\r
+\r
+// サーバー管理ダイアログプロシージャ\r
+UINT SmServerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_SERVER *p = (SM_SERVER *)param;\r
+       wchar_t *s;\r
+       wchar_t tmp[MAX_SIZE];\r
+       NMHDR *n;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               FormatText(hWnd, 0, p->Title);\r
+\r
+               if (p->Bridge == false)\r
+               {\r
+                       FormatText(hWnd, S_TITLE, p->ServerName);\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_SERVER_BRIDGE_TITLE"), p->ServerName);\r
+                       SetText(hWnd, S_TITLE, tmp);\r
+\r
+                       SetText(hWnd, S_VHUB_BRIDGE, _UU("SM_S_VHUB_BRIDGE"));\r
+               }\r
+\r
+               DlgFont(hWnd, S_TITLE, 16, 1);\r
+\r
+               SetIcon(hWnd, 0, p->Bridge == false ? ICO_VPNSERVER : ICO_BRIDGE);\r
+\r
+               SmServerDlgInit(hWnd, p);\r
+\r
+               SetTimer(hWnd, 1, 50, NULL);\r
+\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // 管理\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               if (p->Bridge == false)\r
+                               {\r
+                                       s = LvGetSelectedStr(hWnd, L_HUB, 0);\r
+                               }\r
+                               else\r
+                               {\r
+                                       s = CopyUniStr(L"BRIDGE");\r
+                               }\r
+                               if (s != NULL)\r
+                               {\r
+                                       char hubname[MAX_HUBNAME_LEN + 1];\r
+                                       SM_HUB hub;\r
+                                       Zero(&hub, sizeof(hub));\r
+                                       UniToStr(hubname, sizeof(hubname), s);\r
+                                       hub.p = p;\r
+                                       hub.Rpc = p->Rpc;\r
+                                       hub.HubName = hubname;\r
+                                       SmHubDlg(hWnd, &hub);\r
+                                       //SmServerDlgRefresh(hWnd, p);\r
+                                       Free(s);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_ONLINE:\r
+                       // オンラインにする\r
+                       s = LvGetSelectedStr(hWnd, L_HUB, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               RPC_SET_HUB_ONLINE t;\r
+                               Zero(&t, sizeof(t));\r
+                               UniToStr(t.HubName, sizeof(t.HubName), s);\r
+                               t.Online = true;\r
+                               if (CALL(hWnd, ScSetHubOnline(p->Rpc, &t)))\r
+                               {\r
+                                       SmServerDlgRefresh(hWnd, p);\r
+                               }\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_OFFLINE:\r
+                       // オフラインにする\r
+                       s = LvGetSelectedStr(hWnd, L_HUB, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               RPC_SET_HUB_ONLINE t;\r
+                               Zero(&t, sizeof(t));\r
+                               // 確認メッセージ\r
+                               if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                                       _UU("CM_OFFLINE_MSG"), s) == IDYES)\r
+                               {\r
+                                       UniToStr(t.HubName, sizeof(t.HubName), s);\r
+                                       t.Online = false;\r
+                                       if (CALL(hWnd, ScSetHubOnline(p->Rpc, &t)))\r
+                                       {\r
+                                               SmServerDlgRefresh(hWnd, p);\r
+                                       }\r
+                               }\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_HUB_STATUS:\r
+                       // HUB の状態\r
+                       s = LvGetSelectedStr(hWnd, L_HUB, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               char *hubname = CopyUniToStr(s);\r
+                               UniFormat(tmp, sizeof(tmp), _UU("SM_HUB_STATUS_CAPTION"), s);\r
+                               SmStatusDlg(hWnd, p, hubname, false, true, tmp, ICO_HUB,\r
+                                       NULL, SmRefreshHubStatus);\r
+                               Free(hubname);\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_CREATE:\r
+                       // HUB の作成\r
+                       if (SmCreateHubDlg(hWnd, p))\r
+                       {\r
+                               SmServerDlgRefresh(hWnd, p);\r
+                       }\r
+                       break;\r
+\r
+               case B_EDIT:\r
+                       // HUB の編集\r
+                       s = LvGetSelectedStr(hWnd, L_HUB, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               char *name = CopyUniToStr(s);\r
+                               if (SmEditHubDlg(hWnd, p, name))\r
+                               {\r
+                                       SmServerDlgRefresh(hWnd, p);\r
+                               }\r
+                               Free(name);\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // HUB の削除\r
+                       s = LvGetSelectedStr(hWnd, L_HUB, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               char *name = CopyUniToStr(s);\r
+                               RPC_DELETE_HUB t;\r
+                               Zero(&t, sizeof(t));\r
+                               StrCpy(t.HubName, sizeof(t.HubName), name);\r
+                               if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_HUB_MSG"), name) == IDYES)\r
+                               {\r
+                                       if (CALL(hWnd, ScDeleteHub(p->Rpc, &t)))\r
+                                       {\r
+                                               SmServerDlgRefresh(hWnd, p);\r
+                                               MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_HUB_DELETED_MSG"), name);\r
+                                       }\r
+                               }\r
+                               Free(name);\r
+                               Free(s);\r
+                       }\r
+                       break;\r
+\r
+               case B_CREATE_LISTENER:\r
+                       // リスナー作成\r
+                       if (SmCreateListenerDlg(hWnd, p))\r
+                       {\r
+                               SmServerDlgRefresh(hWnd, p);\r
+                       }\r
+                       break;\r
+\r
+               case B_DELETE_LISTENER:\r
+                       // リスナー削除\r
+                       i = LvGetSelected(hWnd, L_LISTENER);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               UINT port = (UINT)LvGetParam(hWnd, L_LISTENER, i);\r
+                               if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_LISTENER_MSG"), port) == IDYES)\r
+                               {\r
+                                       RPC_LISTENER t;\r
+                                       Zero(&t, sizeof(t));\r
+                                       t.Enable = false;\r
+                                       t.Port = port;\r
+\r
+                                       if (CALL(hWnd, ScDeleteListener(p->Rpc, &t)))\r
+                                       {\r
+                                               SmServerDlgRefresh(hWnd, p);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_START:\r
+                       // 開始\r
+                       i = LvGetSelected(hWnd, L_LISTENER);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               UINT port = (UINT)LvGetParam(hWnd, L_LISTENER, i);\r
+                               RPC_LISTENER t;\r
+                               Zero(&t, sizeof(t));\r
+                               t.Enable = true;\r
+                               t.Port = port;\r
+\r
+                               if (CALL(hWnd, ScEnableListener(p->Rpc, &t)))\r
+                               {\r
+                                       SmServerDlgRefresh(hWnd, p);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_STOP:\r
+                       // 停止\r
+                       i = LvGetSelected(hWnd, L_LISTENER);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               UINT port = (UINT)LvGetParam(hWnd, L_LISTENER, i);\r
+                               if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_STOP_LISTENER_MSG"), port) == IDYES)\r
+                               {\r
+                                       RPC_LISTENER t;\r
+                                       Zero(&t, sizeof(t));\r
+                                       t.Enable = false;\r
+                                       t.Port = port;\r
+\r
+                                       if (CALL(hWnd, ScEnableListener(p->Rpc, &t)))\r
+                                       {\r
+                                               SmServerDlgRefresh(hWnd, p);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_SSL:\r
+                       // SSL 関係\r
+                       SmSslDlg(hWnd, p);\r
+                       break;\r
+\r
+               case B_STATUS:\r
+                       // サーバー状態\r
+                       SmStatusDlg(hWnd, p, p, false, true, _UU("SM_SERVER_STATUS"), ICO_VPNSERVER,\r
+                               NULL, SmRefreshServerStatus);\r
+                       break;\r
+\r
+               case B_INFO:\r
+                       // サーバー情報\r
+                       SmStatusDlg(hWnd, p, p, false, false, _UU("SM_INFO_TITLE"), ICO_VPNSERVER,\r
+                               NULL, SmRefreshServerInfo);\r
+                       break;\r
+\r
+               case B_BRIDGE:\r
+                       // ローカルブリッジ設定\r
+                       SmBridgeDlg(hWnd, p);\r
+                       SmServerDlgRefresh(hWnd, p);\r
+                       break;\r
+\r
+               case B_FARM:\r
+                       // サーバーファーム\r
+                       if (SmFarmDlg(hWnd, p))\r
+                       {\r
+                               // サーバー ファーム構成が変更された場合はダイアログを閉じる\r
+                               Close(hWnd);\r
+                       }\r
+                       break;\r
+\r
+               case B_FARM_STATUS:\r
+                       // サーバー ファーム 状態\r
+                       if (p->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+                       {\r
+                               Dialog(hWnd, D_SM_FARM_MEMBER, SmFarmMemberDlgProc, p);\r
+                       }\r
+                       else if (p->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+                       {\r
+                               SmStatusDlg(hWnd, p, NULL, false, true, _UU("SM_FC_STATUS_CAPTION"),\r
+                                       ICO_FARM, NULL, SmRefreshFarmConnectionInfo);\r
+                       }\r
+                       break;\r
+\r
+               case B_CONNECTION:\r
+                       // TCP コネクション一覧\r
+                       SmConnectionDlg(hWnd, p);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 最新の状態に更新\r
+                       SmServerDlgRefresh(hWnd, p);\r
+                       break;\r
+\r
+               case B_CONFIG:\r
+                       // config 編集\r
+                       SmConfig(hWnd, p);\r
+                       break;\r
+\r
+               case B_L3:\r
+                       // L3 スイッチ\r
+                       SmL3(hWnd, p);\r
+                       break;\r
+\r
+               case B_LICENSE:\r
+                       // ライセンスの追加と削除\r
+                       SmLicense(hWnd, p);\r
+                       SmServerDlgUpdate(hWnd, p);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               {\r
+                       // 最後に選択されていた HUB を保存する\r
+                       char *hubname = NULL;\r
+                       char tmp[MAX_SIZE];\r
+\r
+\r
+                       Format(tmp, sizeof(tmp), "%s:%u:%s", p->CurrentSetting->ClientOption.Hostname,\r
+                               p->CurrentSetting->ClientOption.Port,\r
+                               p->CurrentSetting->ServerAdminMode ? "" : p->CurrentSetting->HubName);\r
+\r
+                       if (LvIsSingleSelected(hWnd, L_HUB))\r
+                       {\r
+                               hubname = LvGetSelectedStrA(hWnd, L_HUB, 0);\r
+                       }\r
+\r
+                       if (IsEmptyStr(hubname) == false)\r
+                       {\r
+                               MsRegWriteStr(REG_CURRENT_USER, SM_LASTHUB_REG_KEY, tmp, hubname);\r
+                       }\r
+                       else\r
+                       {\r
+                               MsRegDeleteValue(REG_CURRENT_USER, SM_LASTHUB_REG_KEY, tmp);\r
+                       }\r
+\r
+                       Free(hubname);\r
+\r
+                       EndDialog(hWnd, false);\r
+               }\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_HUB:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmServerDlgUpdate(hWnd, p);\r
+                               break;\r
+                       }\r
+                       break;\r
+               case L_LISTENER:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               SmServerDlgUpdate(hWnd, p);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       if (p->EmptyPassword && p->ServerAdminMode)\r
+                       {\r
+                               // パスワードが空の場合は変更を推奨する\r
+                               if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_PASSWORD_MSG")) == IDYES)\r
+                               {\r
+                                       Dialog(hWnd, D_SM_CHANGE_PASSWORD, SmChangeServerPasswordDlg, p);\r
+                               }\r
+                       }\r
+\r
+                       if (p->ServerAdminMode)\r
+                       {\r
+                               // ライセンスキーが登録されていない場合は登録を促す\r
+                               RPC_LICENSE_STATUS t;\r
+\r
+                               Zero(&t, sizeof(t));\r
+                               if (p->Bridge == false && GetCapsBool(p->CapsList, "b_support_license"))\r
+                               {\r
+                                       if (ScGetLicenseStatus(p->Rpc, &t) == ERR_NO_ERROR)\r
+                                       {\r
+                                               if (t.EditionId == LICENSE_EDITION_VPN3_NO_LICENSE || (t.NeedSubscription && t.SubscriptionExpires == 0))\r
+                                               {\r
+                                                       // 有効なライセンスキーが 1 つも登録されていない\r
+\r
+                                                       if (MsgBox(hWnd, MB_YESNO | MB_ICONINFORMATION,\r
+                                                               _UU("SM_SETUP_NO_LICENSE_KEY")) == IDYES)\r
+                                                       {\r
+                                                               SmLicense(hWnd, p);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       SetTimer(hWnd, 2, 150, NULL);\r
+                       break;\r
+\r
+               case 2:\r
+                       // セットアップ\r
+                       KillTimer(hWnd, 2);\r
+\r
+                       if (SmSetupIsNew(p))\r
+                       {\r
+                               if (SmSetup(hWnd, p))\r
+                               {\r
+                                       SmServerDlgRefresh(hWnd, p);\r
+                               }\r
+                       }\r
+\r
+                       SetTimer(hWnd, 3, 150, NULL);\r
+                       break;\r
+\r
+               case 3:\r
+                       // 管理者向けメッセージ\r
+                       KillTimer(hWnd, 3);\r
+\r
+                       if (UniIsEmptyStr(p->AdminMsg) == false)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+\r
+                               UniFormat(tmp, sizeof(tmp), _UU("SM_SERVER_ADMIN_MSG"), p->ServerName);\r
+                               OnceMsg(hWnd, tmp, p->AdminMsg, true, ICO_VPNSERVER);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_HUB);\r
+\r
+       return 0;\r
+}\r
+\r
+// 接続\r
+void SmConnect(HWND hWnd, SETTING *s)\r
+{\r
+       bool ok;\r
+       RPC *rpc;\r
+       char *pass;\r
+       bool empty_password = false;\r
+       bool first_bad_password = false;\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // コントロールの無効化\r
+       Disable(hWnd, L_SETTING);\r
+       Disable(hWnd, B_NEW_SETTING);\r
+       Disable(hWnd, B_EDIT_SETTING);\r
+       Disable(hWnd, B_DELETE);\r
+       Disable(hWnd, IDOK);\r
+       Disable(hWnd, B_ABOUT);\r
+       Disable(hWnd, IDCANCEL);\r
+       Disable(hWnd, B_SECURE_MANAGER);\r
+       Disable(hWnd, B_SELECT_SECURE);\r
+\r
+       ok = true;\r
+\r
+       if (IsZero(s->HashedPassword, SHA1_SIZE))\r
+       {\r
+               // パスワード入力画面\r
+ENTER_PASSWORD:\r
+               pass = SmPassword(hWnd, s->ClientOption.Hostname);\r
+               if (pass != NULL)\r
+               {\r
+                       Hash(s->HashedPassword, pass, StrLen(pass), true);\r
+                       Free(pass);\r
+                       ok = true;\r
+               }\r
+               else\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               UINT err = ERR_INTERNAL_ERROR;\r
+               // 接続\r
+               rpc = AdminConnectEx2(sm->Cedar, &s->ClientOption, s->ServerAdminMode ? "" : s->HubName, s->HashedPassword, &err, NULL,\r
+                       hWnd);\r
+               if (rpc == NULL)\r
+               {\r
+                       // エラー発生\r
+                       if (err != ERR_ACCESS_DENIED || first_bad_password)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONSTOP, _E(err));\r
+                       }\r
+                       if (err == ERR_ACCESS_DENIED)\r
+                       {\r
+                               // パスワード間違い\r
+                               first_bad_password = true;\r
+                               goto ENTER_PASSWORD;\r
+                       }\r
+                       else\r
+                       {\r
+                               // その他のエラー\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       UCHAR test[SHA1_SIZE];\r
+                       SM_SERVER p;\r
+                       RPC_SERVER_STATUS status;\r
+                       RPC_SERVER_INFO info;\r
+                       SETTING *setting;\r
+                       RPC_MSG msg;\r
+\r
+                       Hash(test, "", 0, true);\r
+\r
+                       if (Cmp(test, s->HashedPassword, SHA1_SIZE) == 0)\r
+                       {\r
+                               empty_password = true;\r
+                       }\r
+\r
+                       if (sm->TempSetting == NULL)\r
+                       {\r
+                               setting = SmGetSetting(s->Title);\r
+                               if (setting != NULL)\r
+                               {\r
+                                       if (IsZero(setting->HashedPassword, SHA1_SIZE) == false)\r
+                                       {\r
+                                               Copy(setting->HashedPassword, s->HashedPassword, SHA1_SIZE);\r
+                                               SmWriteSettingList();\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       rpc->ServerAdminMode = s->ServerAdminMode;\r
+                       if (s->ServerAdminMode == false)\r
+                       {\r
+                               StrCpy(rpc->HubName, sizeof(rpc->HubName), s->HubName);\r
+                       }\r
+\r
+                       Zero(&p, sizeof(p));\r
+                       p.CurrentSetting = s;\r
+                       p.Rpc = rpc;\r
+                       p.EmptyPassword = empty_password;\r
+                       p.ServerAdminMode = rpc->ServerAdminMode;\r
+                       StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption.Hostname);\r
+                       if (p.ServerAdminMode == false)\r
+                       {\r
+                               StrCpy(p.HubName, sizeof(p.HubName), rpc->HubName);\r
+                       }\r
+                       UniStrCpy(p.Title, sizeof(p.Title), s->Title);\r
+\r
+                       // サーバーの種類の取得\r
+                       Zero(&status, sizeof(status));\r
+                       ScGetServerStatus(rpc, &status);\r
+\r
+                       p.ServerType = status.ServerType;\r
+\r
+                       Zero(&info, sizeof(info));\r
+                       ScGetServerInfo(rpc, &info);\r
+\r
+                       Copy(&p.ServerInfo, &info, sizeof(RPC_SERVER_INFO));\r
+                       Copy(&p.ServerStatus, &status, sizeof(RPC_SERVER_STATUS));\r
+\r
+                       // Admin Msg の取得\r
+                       Zero(&msg, sizeof(msg));\r
+                       if (ScGetAdminMsg(rpc, &msg) == ERR_NO_ERROR)\r
+                       {\r
+                               p.AdminMsg = UniCopyStr(msg.Msg);\r
+                               FreeRpcMsg(&msg);\r
+                       }\r
+\r
+                       // Caps の取得\r
+                       p.CapsList = ScGetCapsEx(p.Rpc);\r
+\r
+                       p.Bridge = GetCapsBool(p.CapsList, "b_bridge");\r
+\r
+                       if (GetCapsBool(p.CapsList, "b_support_policy_ver_3"))\r
+                       {\r
+                               p.PolicyVer = 3;\r
+                       }\r
+                       else\r
+                       {\r
+                               p.PolicyVer = 2;\r
+                       }\r
+\r
+                       // サーバー管理画面\r
+                       Dialog(hWnd, D_SM_SERVER, SmServerDlgProc, &p);\r
+\r
+                       // 切断\r
+                       AdminDisconnect(rpc);\r
+\r
+                       // Caps の解放\r
+                       FreeCapsList(p.CapsList);\r
+\r
+                       Free(p.AdminMsg);\r
+                       p.AdminMsg = NULL;\r
+\r
+                       FreeRpcServerInfo(&info);\r
+               }\r
+       }\r
+\r
+       // コントロールの有効化\r
+       Enable(hWnd, L_SETTING);\r
+       Enable(hWnd, B_NEW_SETTING);\r
+       Enable(hWnd, B_EDIT_SETTING);\r
+       Enable(hWnd, B_DELETE);\r
+       Enable(hWnd, IDOK);\r
+       Enable(hWnd, B_ABOUT);\r
+       Enable(hWnd, IDCANCEL);\r
+       Enable(hWnd, B_SECURE_MANAGER);\r
+       Enable(hWnd, B_SELECT_SECURE);\r
+}\r
+\r
+// パスワード入力ダイアログ\r
+char *SmPassword(HWND hWnd, char *server_name)\r
+{\r
+       char *ret;\r
+       UI_PASSWORD_DLG p;\r
+       // 引数チェック\r
+       if (server_name == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       p.AdminMode = true;\r
+       StrCpy(p.ServerName, sizeof(p.ServerName), server_name);\r
+\r
+       if (PasswordDlg(hWnd, &p) == false)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       ret = CopyStr(p.Password);\r
+\r
+       return ret;\r
+}\r
+\r
+// 設定の編集ダイアログ初期化\r
+void SmEditSettingDlgInit(HWND hWnd, SM_EDIT_SETTING *p)\r
+{\r
+       SETTING *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       p->Inited = false;\r
+\r
+       s = p->Setting;\r
+\r
+       // タイトル\r
+       if (p->EditMode == false)\r
+       {\r
+               SetText(hWnd, 0, _UU("SM_EDIT_CAPTION_1"));\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_EDIT_CAPTION_2"), s->Title);\r
+               SetText(hWnd, 0, tmp);\r
+       }\r
+\r
+       // 接続設定名\r
+       SetText(hWnd, E_ACCOUNT_NAME, s->Title);\r
+\r
+       // ホスト名\r
+       SetTextA(hWnd, E_HOSTNAME, s->ClientOption.Hostname);\r
+\r
+       // ポート番号\r
+       CbSetHeight(hWnd, C_PORT, 18);\r
+       CbAddStr(hWnd, C_PORT, _UU("CM_PORT_4"), 0);\r
+       CbAddStr(hWnd, C_PORT, _UU("CM_PORT_1"), 0);\r
+       CbAddStr(hWnd, C_PORT, _UU("CM_PORT_2"), 0);\r
+       CbAddStr(hWnd, C_PORT, _UU("CM_PORT_3"), 0);\r
+       SetIntEx(hWnd, C_PORT, s->ClientOption.Port);\r
+\r
+       // プロキシ設定\r
+       Check(hWnd, R_DIRECT_TCP, s->ClientOption.ProxyType == PROXY_DIRECT);\r
+       Check(hWnd, R_HTTPS, s->ClientOption.ProxyType == PROXY_HTTP);\r
+       Check(hWnd, R_SOCKS, s->ClientOption.ProxyType == PROXY_SOCKS);\r
+\r
+       // 管理モード設定\r
+       Check(hWnd, R_SERVER_ADMIN, s->ServerAdminMode);\r
+       Check(hWnd, R_HUB_ADMIN, s->ServerAdminMode == false ? true : false);\r
+       CbSetHeight(hWnd, C_HUBNAME, 18);\r
+       SetTextA(hWnd, C_HUBNAME, s->HubName);\r
+\r
+       // パスワード\r
+       if (IsZero(s->HashedPassword, SHA1_SIZE))\r
+       {\r
+               Check(hWnd, R_NO_SAVE, true);\r
+       }\r
+       else\r
+       {\r
+               UCHAR test[SHA1_SIZE];\r
+\r
+               Hash(test, "", 0, true);\r
+               if (Cmp(test, s->HashedPassword, SHA1_SIZE) != 0)\r
+               {\r
+                       SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);\r
+               }\r
+       }\r
+\r
+       if (p->EditMode == false)\r
+       {\r
+               FocusEx(hWnd, E_ACCOUNT_NAME);\r
+       }\r
+       else\r
+       {\r
+               FocusEx(hWnd, E_HOSTNAME);\r
+       }\r
+\r
+       p->Inited = true;\r
+\r
+       // 仮想 HUB の列挙を開始\r
+       CmEnumHubStart(hWnd, &s->ClientOption);\r
+\r
+       SmEditSettingDlgUpdate(hWnd, p);\r
+}\r
+\r
+// 設定の編集ダイアログ更新\r
+void SmEditSettingDlgUpdate(HWND hWnd, SM_EDIT_SETTING *p)\r
+{\r
+       bool ok = true;\r
+       UINT delete_hub_list = 0;\r
+       SETTING *s;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL || p->Inited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s = p->Setting;\r
+\r
+       GetTxt(hWnd, E_ACCOUNT_NAME, s->Title, sizeof(s->Title));\r
+       UniTrim(s->Title);\r
+\r
+       if (UniStrLen(s->Title) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_LOCALHOST))\r
+       {\r
+               SetTextA(hWnd, E_HOSTNAME, "localhost");\r
+               Disable(hWnd, E_HOSTNAME);\r
+       }\r
+       else\r
+       {\r
+               Enable(hWnd, E_HOSTNAME);\r
+       }\r
+\r
+       GetTxtA(hWnd, E_HOSTNAME, tmp, sizeof(tmp));\r
+       Trim(tmp);\r
+\r
+       if (StrCmpi(tmp, s->ClientOption.Hostname) != 0)\r
+       {\r
+               delete_hub_list++;\r
+       }\r
+\r
+       StrCpy(s->ClientOption.Hostname, sizeof(s->ClientOption.Hostname), tmp);\r
+\r
+       if (StrLen(s->ClientOption.Hostname) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       s->ClientOption.Port = GetInt(hWnd, C_PORT);\r
+       if (s->ClientOption.Port == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_DIRECT_TCP))\r
+       {\r
+               s->ClientOption.ProxyType = PROXY_DIRECT;\r
+       }\r
+       else if (IsChecked(hWnd, R_HTTPS))\r
+       {\r
+               s->ClientOption.ProxyType = PROXY_HTTP;\r
+       }\r
+       else\r
+       {\r
+               s->ClientOption.ProxyType = PROXY_SOCKS;\r
+       }\r
+\r
+       SetEnable(hWnd, B_PROXY_CONFIG, s->ClientOption.ProxyType != PROXY_DIRECT);\r
+\r
+       if (s->ClientOption.ProxyType != PROXY_DIRECT)\r
+       {\r
+               if (StrLen(s->ClientOption.ProxyName) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+               if (s->ClientOption.ProxyPort == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       s->ServerAdminMode = IsChecked(hWnd, R_SERVER_ADMIN);\r
+\r
+       SetEnable(hWnd, C_HUBNAME, s->ServerAdminMode == false ? true : false);\r
+       SetEnable(hWnd, S_HUBNAME, s->ServerAdminMode == false ? true : false);\r
+\r
+       GetTxtA(hWnd, C_HUBNAME, s->HubName, sizeof(s->HubName));\r
+       Trim(s->HubName);\r
+       if (StrLen(s->HubName) == 0)\r
+       {\r
+               if (s->ServerAdminMode == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_NO_SAVE))\r
+       {\r
+               Zero(s->HashedPassword, SHA1_SIZE);\r
+               SetTextA(hWnd, E_PASSWORD, "");\r
+               Disable(hWnd, E_PASSWORD);\r
+               Disable(hWnd, S_PASSWORD);\r
+       }\r
+       else\r
+       {\r
+               char tmp[MAX_PASSWORD_LEN + 1];\r
+               Enable(hWnd, E_PASSWORD);\r
+               Enable(hWnd, S_PASSWORD);\r
+               GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));\r
+               if (StrCmp(tmp, HIDDEN_PASSWORD) != 0)\r
+               {\r
+                       Hash(s->HashedPassword, tmp, StrLen(tmp), true);\r
+               }\r
+       }\r
+\r
+       if (delete_hub_list)\r
+       {\r
+               CbReset(hWnd, C_HUBNAME);\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// 設定の編集ダイアログ OK ボタン\r
+void SmEditSettingDlgOnOk(HWND hWnd, SM_EDIT_SETTING *p)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (p->EditMode == false)\r
+       {\r
+               // 新規登録\r
+               SETTING *s = ZeroMalloc(sizeof(SETTING));\r
+               Copy(s, p->Setting, sizeof(SETTING));\r
+               if (SmAddSetting(s) == false)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_SETTING_EXISTS"), s->Title);\r
+                       Free(s);\r
+                       FocusEx(hWnd, E_ACCOUNT_NAME);\r
+                       return;\r
+               }\r
+               EndDialog(hWnd, true);\r
+       }\r
+       else\r
+       {\r
+               // 更新登録\r
+               SETTING *t = SmGetSetting(p->Setting->Title);\r
+               if (t != NULL && t != p->OldSetting)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_SETTING_EXISTS"), p->Setting->Title);\r
+                       FocusEx(hWnd, E_ACCOUNT_NAME);\r
+                       return;\r
+               }\r
+\r
+               Copy(p->OldSetting, p->Setting, sizeof(SETTING));\r
+               Sort(sm->SettingList);\r
+               SmWriteSettingList();\r
+\r
+               EndDialog(hWnd, true);\r
+       }\r
+}\r
+\r
+// 設定の追加 / 編集ダイアログ\r
+UINT SmEditSettingDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_EDIT_SETTING *p = (SM_EDIT_SETTING *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SmEditSettingDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_LOCALHOST:\r
+               case E_ACCOUNT_NAME:\r
+               case E_HOSTNAME:\r
+               case C_PORT:\r
+               case R_DIRECT_TCP:\r
+               case R_HTTPS:\r
+               case R_SOCKS:\r
+               case R_SERVER_ADMIN:\r
+               case R_HUB_ADMIN:\r
+               case C_HUBNAME:\r
+               case E_PASSWORD:\r
+               case R_NO_SAVE:\r
+                       SmEditSettingDlgUpdate(hWnd, p);\r
+                       break;\r
+               }\r
+\r
+               if (LOWORD(wParam) == R_LOCALHOST)\r
+               {\r
+                       FocusEx(hWnd, E_HOSTNAME);\r
+               }\r
+\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_HOSTNAME:\r
+                       if (HIWORD(wParam) == EN_KILLFOCUS)\r
+                       {\r
+                               CmEnumHubStart(hWnd, &p->Setting->ClientOption);\r
+                       }\r
+                       break;\r
+               case C_PORT:\r
+                       if (HIWORD(wParam) == CBN_KILLFOCUS)\r
+                       {\r
+                               CmEnumHubStart(hWnd, &p->Setting->ClientOption);\r
+                       }\r
+                       break;\r
+               case R_DIRECT_TCP:\r
+               case R_HTTPS:\r
+               case R_SOCKS:\r
+                       if (HIWORD(wParam) == BN_CLICKED)\r
+                       {\r
+                               CmEnumHubStart(hWnd, &p->Setting->ClientOption);\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       SmEditSettingDlgOnOk(hWnd, p);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_PROXY_CONFIG:\r
+                       // プロキシ設定\r
+                       if (CmProxyDlg(hWnd, &p->Setting->ClientOption))\r
+                       {\r
+                               UINT n = GetInt(hWnd, C_PORT);\r
+                               if (p->Setting->ClientOption.ProxyType == PROXY_HTTP &&\r
+                                       n != 443)\r
+                               {\r
+                                       // HTTP プロキシ経由の設定になっていて接続先が 443 番ポート\r
+                                       // 以外のポートである場合は警告を表示する\r
+                                       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_HTTP_PROXY_WARNING"), n) == IDYES)\r
+                                       {\r
+                                               // ポート番号を 443 に変更する\r
+                                               SetText(hWnd, C_PORT, _UU("CM_PORT_2"));\r
+                                       }\r
+                               }\r
+                               SmEditSettingDlgUpdate(hWnd, p);\r
+                               CmEnumHubStart(hWnd, &p->Setting->ClientOption);\r
+                       }\r
+                       break;\r
+\r
+               case R_NO_SAVE:\r
+                       if (IsChecked(hWnd, R_NO_SAVE) == false)\r
+                       {\r
+                               FocusEx(hWnd, E_PASSWORD);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 設定の追加ダイアログを表示\r
+bool SmAddSettingDlg(HWND hWnd, wchar_t *new_name, UINT new_name_size)\r
+{\r
+       SM_EDIT_SETTING p;\r
+       SETTING s;\r
+       UINT i;\r
+       bool ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL || new_name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       Zero(&s, sizeof(s));\r
+\r
+       s.ClientOption.Port = 443;\r
+\r
+       p.EditMode = false;\r
+       p.Setting = &s;\r
+\r
+       for (i = 1;;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               if (i == 1)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_1"));\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_2"), i);\r
+               }\r
+\r
+               if (SmGetSetting(tmp) == NULL)\r
+               {\r
+                       UniStrCpy(s.Title, sizeof(s.Title), tmp);\r
+                       Hash(s.HashedPassword, "", 0, true);\r
+                       s.ServerAdminMode = true;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       ret = Dialog(hWnd, D_SM_EDIT_SETTING, SmEditSettingDlgProc, &p);\r
+\r
+       if (ret)\r
+       {\r
+               UniStrCpy(new_name, new_name_size, s.Title);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// 設定の編集ダイアログを表示\r
+bool SmEditSettingDlg(HWND hWnd)\r
+{\r
+       SM_EDIT_SETTING p;\r
+       SETTING s, *setting;\r
+       UINT i;\r
+       wchar_t *name;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       i = LvGetSelected(hWnd, L_SETTING);\r
+       if (i == INFINITE)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       name = LvGetStr(hWnd, L_SETTING, i, 0);\r
+\r
+       setting = SmGetSetting(name);\r
+       if (setting == NULL)\r
+       {\r
+               Free(name);\r
+               return false;\r
+       }\r
+\r
+       Free(name);\r
+\r
+       Copy(&s, setting, sizeof(SETTING));\r
+\r
+       Zero(&p, sizeof(p));\r
+\r
+       p.EditMode = true;\r
+       p.OldSetting = setting;\r
+       p.Setting = &s;\r
+\r
+       return Dialog(hWnd, D_SM_EDIT_SETTING, SmEditSettingDlgProc, &p);\r
+}\r
+\r
+// 設定の更新\r
+bool SmCheckNewName(SETTING *s, wchar_t *new_title)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (new_title == NULL)\r
+       {\r
+               return false;\r
+       }\r
+       if (s != NULL)\r
+       {\r
+               if (IsInList(sm->SettingList, s) == false)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       // 他に同一の名前が無いかどうかチェック\r
+       for (i = 0;i < LIST_NUM(sm->SettingList);i++)\r
+       {\r
+               SETTING *t = LIST_DATA(sm->SettingList, i);\r
+\r
+               if (s != t)\r
+               {\r
+                       if (UniStrCmpi(t->Title, new_title) == 0)\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// 設定の削除\r
+void SmDeleteSetting(wchar_t *title)\r
+{\r
+       SETTING *s;\r
+       // 引数チェック\r
+       if (title == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s = SmGetSetting(title);\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Delete(sm->SettingList, s);\r
+       Free(s);\r
+       Sort(sm->SettingList);\r
+\r
+       SmWriteSettingList();\r
+}\r
+\r
+// 設定の追加\r
+bool SmAddSetting(SETTING *s)\r
+{\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (SmGetSetting(s->Title) != NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Insert(sm->SettingList, s);\r
+\r
+       SmWriteSettingList();\r
+\r
+       return true;\r
+}\r
+\r
+// 設定の取得\r
+SETTING *SmGetSetting(wchar_t *title)\r
+{\r
+       SETTING s;\r
+       // 引数チェック\r
+       if (title == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&s, sizeof(SETTING));\r
+       UniStrCpy(s.Title, sizeof(s.Title), title);\r
+\r
+       return (SETTING *)Search(sm->SettingList, &s);\r
+}\r
+\r
+// 接続設定の比較\r
+int SmCompareSetting(void *p1, void *p2)\r
+{\r
+       SETTING *s1, *s2;\r
+       if (p1 == NULL || p2 == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+       s1 = *(SETTING **)p1;\r
+       s2 = *(SETTING **)p2;\r
+       if (s1 == NULL || s2 == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       return UniStrCmpi(s1->Title, s2->Title);\r
+}\r
+\r
+// 設定リストの初期化\r
+void SmInitSettingList()\r
+{\r
+       sm->SettingList = NewList(SmCompareSetting);\r
+\r
+       SmLoadSettingList();\r
+\r
+       SmInitDefaultSettingList();\r
+}\r
+\r
+// 設定リストの解放\r
+void SmFreeSettingList()\r
+{\r
+       UINT i;\r
+\r
+       // 書き込み\r
+       SmWriteSettingList();\r
+\r
+       for (i = 0;i < LIST_NUM(sm->SettingList);i++)\r
+       {\r
+               SETTING *s = LIST_DATA(sm->SettingList, i);\r
+               Free(s);\r
+       }\r
+       ReleaseList(sm->SettingList);\r
+\r
+       sm->SettingList = NULL;\r
+}\r
+\r
+// 設定リストの書き込み\r
+void SmWriteSettingList()\r
+{\r
+       TOKEN_LIST *t;\r
+       UINT i;\r
+\r
+       t = MsRegEnumValue(REG_CURRENT_USER, SM_SETTING_REG_KEY);\r
+       if (t != NULL)\r
+       {\r
+               // 既存のすべての値を削除する\r
+               for (i = 0;i < t->NumTokens;i++)\r
+               {\r
+                       char *name = t->Token[i];\r
+                       MsRegDeleteValue(REG_CURRENT_USER, SM_SETTING_REG_KEY, name);\r
+               }\r
+\r
+               FreeToken(t);\r
+       }\r
+\r
+       for (i = 0;i < LIST_NUM(sm->SettingList);i++)\r
+       {\r
+               char name[MAX_SIZE];\r
+               SETTING *s = LIST_DATA(sm->SettingList, i);\r
+\r
+               // 書き込む\r
+               Format(name, sizeof(name), "Setting%u", i + 1);\r
+               MsRegWriteBin(REG_CURRENT_USER, SM_SETTING_REG_KEY, name, s, sizeof(SETTING));\r
+       }\r
+}\r
+\r
+// 接続リストの読み込み\r
+void SmLoadSettingList()\r
+{\r
+       TOKEN_LIST *t;\r
+       UINT i;\r
+       char *key_name = SM_SETTING_REG_KEY;\r
+\r
+       t = MsRegEnumValue(REG_CURRENT_USER, key_name);\r
+       if (t == NULL)\r
+       {\r
+               key_name = SM_SETTING_REG_KEY_OLD;\r
+               t = MsRegEnumValue(REG_CURRENT_USER, key_name);\r
+               if (t == NULL)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               char *name = t->Token[i];\r
+               BUF *b = MsRegReadBin(REG_CURRENT_USER, key_name, name);\r
+               if (b != NULL)\r
+               {\r
+                       if (b->Size == sizeof(SETTING))\r
+                       {\r
+                               SETTING *s = ZeroMalloc(sizeof(SETTING));\r
+                               Copy(s, b->Buf, sizeof(SETTING));\r
+\r
+                               Add(sm->SettingList, s);\r
+                       }\r
+                       FreeBuf(b);\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       Sort(sm->SettingList);\r
+}\r
+\r
+// デフォルトの設定リストの初期化\r
+void SmInitDefaultSettingList()\r
+{\r
+       if (LIST_NUM(sm->SettingList) == 0)\r
+       {\r
+               bool b = false;\r
+               LIST *pl = MsGetProcessList();\r
+\r
+               if (pl != NULL)\r
+               {\r
+                       UINT i;\r
+                       for (i = 0;i < LIST_NUM(pl);i++)\r
+                       {\r
+                               MS_PROCESS *p = LIST_DATA(pl, i);\r
+\r
+                               if (InStr(p->ExeFilename, "utvpnserver.exe") || InStr(p->ExeFilename, "utvpnserver_x64.exe") ||\r
+                                       InStr(p->ExeFilename, "utvpnserver_ia64.exe") ||\r
+                                       InStr(p->ExeFilename, "utvpnbridge.exe") || InStr(p->ExeFilename, "utvpnbridge_x64.exe") ||\r
+                                       InStr(p->ExeFilename, "utvpnbridge_ia64.exe"))\r
+                               {\r
+                                       b = true;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               MsFreeProcessList(pl);\r
+\r
+               if (b == false)\r
+               {\r
+                       if (MsIsServiceRunning(_SS("SVC_UTVPNSERVER_NAME")))\r
+                       {\r
+                               b = true;\r
+                       }\r
+               }\r
+\r
+               if (b)\r
+               {\r
+                       SETTING *s = ZeroMalloc(sizeof(SETTING));\r
+\r
+                       UniStrCpy(s->Title, sizeof(s->Title), _UU("SM_LOCALHOST"));\r
+                       s->ServerAdminMode = true;\r
+                       Hash(s->HashedPassword, "", 0, true);\r
+                       UniStrCpy(s->ClientOption.AccountName, sizeof(s->ClientOption.AccountName), s->Title);\r
+                       StrCpy(s->ClientOption.Hostname, sizeof(s->ClientOption.Hostname), "localhost");\r
+                       s->ClientOption.Port = 5555;\r
+\r
+                       Add(sm->SettingList, s);\r
+               }\r
+       }\r
+}\r
+\r
+// メインダイアログ初期化\r
+void SmMainDlgInit(HWND hWnd)\r
+{\r
+       wchar_t *last_select;\r
+       UINT i = INFINITE;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_VPNSERVER);\r
+\r
+       LvInit(hWnd, L_SETTING);\r
+       LvSetStyle(hWnd, L_SETTING, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_SETTING, 0, _UU("SM_MAIN_COLUMN_1"), 146);\r
+       LvInsertColumn(hWnd, L_SETTING, 1, _UU("SM_MAIN_COLUMN_2"), 130);\r
+       LvInsertColumn(hWnd, L_SETTING, 2, _UU("SM_MAIN_COLUMN_3"), 130);\r
+\r
+       SmRefreshSetting(hWnd);\r
+\r
+       last_select = MsRegReadStrW(REG_CURRENT_USER, SM_REG_KEY, "Last Select");\r
+       if (UniIsEmptyStr(last_select) == false)\r
+       {\r
+               i = LvSearchStr(hWnd, L_SETTING, 0, last_select);\r
+       }\r
+       Free(last_select);\r
+\r
+       if (i == INFINITE)\r
+       {\r
+               LvSelect(hWnd, L_SETTING, 0);\r
+       }\r
+       else\r
+       {\r
+               LvSelect(hWnd, L_SETTING, i);\r
+       }\r
+\r
+       Focus(hWnd, L_SETTING);\r
+\r
+       SmMainDlgUpdate(hWnd);\r
+}\r
+\r
+// 設定一覧の更新\r
+void SmRefreshSetting(HWND hWnd)\r
+{\r
+       SmRefreshSettingEx(hWnd, NULL);\r
+}\r
+void SmRefreshSettingEx(HWND hWnd, wchar_t *select_name)\r
+{\r
+       LVB *b;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < LIST_NUM(sm->SettingList);i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               SETTING *s = LIST_DATA(sm->SettingList, i);\r
+\r
+               if (s->ServerAdminMode)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_MODE_SERVER"));\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_MODE_HUB"), s->HubName);\r
+               }\r
+\r
+               StrToUni(tmp2, sizeof(tmp2), s->ClientOption.Hostname);\r
+\r
+               LvInsertAdd(b,\r
+                       (s->ServerAdminMode ? ICO_SERVER_ONLINE : ICO_HUB),\r
+                       NULL,\r
+                       3,\r
+                       s->Title,\r
+                       tmp2,\r
+                       tmp);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_SETTING);\r
+\r
+       if (UniIsEmptyStr(select_name) == false)\r
+       {\r
+               LvSelect(hWnd, L_SETTING, LvSearchStr(hWnd, L_SETTING, 0, select_name));\r
+       }\r
+}\r
+\r
+// メインダイアログ更新\r
+void SmMainDlgUpdate(HWND hWnd)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSelected(hWnd, L_SETTING) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+       if (LvIsMultiMasked(hWnd, L_SETTING))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+       SetEnable(hWnd, B_EDIT_SETTING, ok);\r
+       SetEnable(hWnd, B_DELETE, ok);\r
+}\r
+\r
+// メインウインドウプロシージャ\r
+UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       NMLVDISPINFOW *info;\r
+       NMLVKEYDOWN *key;\r
+       wchar_t *tmp;\r
+       UINT i;\r
+       wchar_t new_name[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               ShowSplashEx(hWnd, "UT-VPN Server", 1300, SM_SPLASH_BORDER_COLOR);\r
+               SmMainDlgInit(hWnd);\r
+               SetTimer(hWnd, 4, 100, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 4:\r
+                       KillTimer(hWnd, 4);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       // 接続\r
+                       i = LvGetSelected(hWnd, L_SETTING);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               tmp = LvGetStr(hWnd, L_SETTING, i, 0);\r
+                               if (tmp != NULL)\r
+                               {\r
+                                       SETTING *setting = SmGetSetting(tmp);\r
+                                       if (setting != NULL)\r
+                                       {\r
+                                               SETTING s;\r
+\r
+                                               // レジストリに最後の選択として記録\r
+                                               MsRegWriteStrW(REG_CURRENT_USER, SM_REG_KEY, "Last Select", tmp);\r
+\r
+                                               // 設定コピー\r
+                                               Copy(&s, setting, sizeof(SETTING));\r
+                                               SmConnect(hWnd, &s);\r
+                                       }\r
+                                       Free(tmp);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_NEW_SETTING:\r
+                       // 追加\r
+                       if (SmAddSettingDlg(hWnd, new_name, sizeof(new_name)))\r
+                       {\r
+                               SmRefreshSettingEx(hWnd, new_name);\r
+                       }\r
+                       break;\r
+\r
+               case B_EDIT_SETTING:\r
+                       // 編集\r
+                       if (SmEditSettingDlg(hWnd))\r
+                       {\r
+                               SmWriteSettingList();\r
+                               SmRefreshSetting(hWnd);\r
+                       }\r
+\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       // 削除\r
+                       i = LvGetSelected(hWnd, L_SETTING);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               tmp = LvGetStr(hWnd, L_SETTING, i, 0);\r
+                               if (tmp != NULL)\r
+                               {\r
+                                       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                                               _UU("SM_SETTING_DELETE_MSG"), tmp) == IDYES)\r
+                                       {\r
+                                               SmDeleteSetting(tmp);\r
+                                               SmWriteSettingList();\r
+                                               SmRefreshSetting(hWnd);\r
+                                       }\r
+                                       Free(tmp);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case B_ABOUT:\r
+                       // バージョン情報\r
+                       ShowSplashEx(hWnd, "UT-VPN Server", 0, SM_SPLASH_BORDER_COLOR);\r
+                       break;\r
+\r
+               case B_SECURE_MANAGER:\r
+                       // スマートカードマネージャ\r
+                       SmSecureManager(hWnd);\r
+                       break;\r
+\r
+               case B_SELECT_SECURE:\r
+                       // スマートカード選択\r
+                       SmSelectSecureId(hWnd);\r
+                       break;\r
+               }\r
+\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_SETTING:\r
+                       switch (n->code)\r
+                       {\r
+                       case NM_DBLCLK:\r
+                               Command(hWnd, IDOK);\r
+                               break;\r
+\r
+                       case LVN_KEYDOWN:\r
+                               key = (NMLVKEYDOWN *)n;\r
+                               if (key != NULL)\r
+                               {\r
+                                       UINT code = key->wVKey;\r
+                                       switch (code)\r
+                                       {\r
+                                       case VK_F2:\r
+                                               if (LvIsSelected(hWnd, L_SETTING))\r
+                                               {\r
+                                                       LvRename(hWnd, L_SETTING, LvGetSelected(hWnd, L_SETTING));\r
+                                               }\r
+                                               break;\r
+\r
+                                       case VK_DELETE:\r
+                                               Command(hWnd, B_DELETE);\r
+                                               break;\r
+\r
+                                       case VK_RETURN:\r
+                                               Command(hWnd, IDOK);\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               break;\r
+\r
+                       case LVN_ENDLABELEDITW:\r
+                               // 名前の変更\r
+                               info = (NMLVDISPINFOW *)n;\r
+                               if (info->item.pszText != NULL)\r
+                               {\r
+                                       wchar_t *new_name = info->item.pszText;\r
+                                       wchar_t *old_name = LvGetStr(hWnd, L_SETTING, info->item.iItem, 0);\r
+\r
+                                       if (old_name != NULL)\r
+                                       {\r
+                                               if (UniStrCmp(new_name, old_name) != 0 && UniStrLen(new_name) != 0)\r
+                                               {\r
+                                                       // 名前変更の実行\r
+                                                       SETTING *s = SmGetSetting(old_name);\r
+                                                       if (s != NULL)\r
+                                                       {\r
+                                                               if (SmGetSetting(new_name) != NULL)\r
+                                                               {\r
+                                                                       MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SM_SETTING_EXISTS"),\r
+                                                                               new_name);\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       UniStrCpy(s->Title, sizeof(s->Title), new_name);\r
+                                                                       Sort(sm->SettingList);\r
+                                                                       SmWriteSettingList();\r
+                                                                       LvSetItem(hWnd, L_SETTING, info->item.iItem, 0, new_name);\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+\r
+                                               Free(old_name);\r
+                                       }\r
+                               }\r
+                               break;\r
+\r
+                       case LVN_ITEMCHANGED:\r
+                               SmMainDlgUpdate(hWnd);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       LvSortHander(hWnd, msg, wParam, lParam, L_SETTING);\r
+\r
+       return 0;\r
+}\r
+\r
+// メインウインドウ\r
+void SmMainDlg()\r
+{\r
+       Dialog(NULL, D_SM_MAIN, SmMainDlgProc, NULL);\r
+}\r
+\r
+// Server Manager メイン処理\r
+void MainSM()\r
+{\r
+       if (sm->TempSetting == NULL)\r
+       {\r
+               // メインウインドウを開く\r
+               SmMainDlg();\r
+       }\r
+       else\r
+       {\r
+               SmConnect(sm->hParentWnd, sm->TempSetting);\r
+       }\r
+}\r
+\r
+// 初期化\r
+void InitSM()\r
+{\r
+       if (sm != NULL)\r
+       {\r
+               // すでに初期化されている\r
+               return;\r
+       }\r
+\r
+       sm = ZeroMalloc(sizeof(SM));\r
+\r
+       InitWinUi(_UU("SM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));\r
+\r
+       sm->Cedar = NewCedar(NULL, NULL);\r
+\r
+       SmInitSettingList();\r
+\r
+       InitCM();\r
+\r
+       // コマンドラインを解釈する\r
+       SmParseCommandLine();\r
+}\r
+\r
+// コマンドラインを解釈する\r
+void SmParseCommandLine()\r
+{\r
+       LIST *o;\r
+       CONSOLE *c = NewLocalConsole(NULL, NULL);\r
+       wchar_t *cmdline;\r
+       PARAM args[] =\r
+       {\r
+               {"[vpnserver]", NULL, NULL, NULL, NULL,},\r
+               {"HUB", NULL, NULL, NULL, NULL,},\r
+               {"PASSWORD", NULL, NULL, NULL, NULL,},\r
+               {"TITLE", NULL, NULL, NULL, NULL,},\r
+               {"HWND", NULL, NULL, NULL, NULL,},\r
+       };\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+       \r
+       cmdline = GetCommandLineUniStr();\r
+\r
+       if (UniIsEmptyStr(cmdline) == false)\r
+       {\r
+               o = ParseCommandList(c, "vpnsmgr", cmdline, args, sizeof(args) / sizeof(args[0]));\r
+               if (o != NULL)\r
+               {\r
+                       char *host;\r
+                       UINT port;\r
+\r
+                       if (ParseHostPort(GetParamStr(o, "[vpnserver]"), &host, &port, 443))\r
+                       {\r
+                               char *hub = GetParamStr(o, "HUB");\r
+                               char *password = GetParamStr(o, "PASSWORD");\r
+                               char *title = GetParamStr(o, "TITLE");\r
+                               char *hwndstr = GetParamStr(o, "HWND");\r
+\r
+                               if (hub == NULL || StrCmpi(hub, "\"") == 0)\r
+                               {\r
+                                       hub = CopyStr("");\r
+                               }\r
+                               if (password == NULL)\r
+                               {\r
+                                       password = CopyStr("");\r
+                               }\r
+                               if (title == NULL)\r
+                               {\r
+                                       title = CopyStr(host);\r
+                               }\r
+\r
+                               if (IsEmptyStr(host) == false)\r
+                               {\r
+                                       SETTING *s = ZeroMalloc(sizeof(SETTING));\r
+                                       BUF *b;\r
+                                       CLIENT_OPTION *o;\r
+\r
+                                       StrToUni(s->Title, sizeof(s->Title), title);\r
+\r
+                                       if (IsEmptyStr(hub))\r
+                                       {\r
+                                               s->ServerAdminMode = true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               s->ServerAdminMode = false;\r
+                                               StrCpy(s->HubName, sizeof(s->HubName), hub);\r
+                                       }\r
+\r
+                                       b = StrToBin(password);\r
+                                       if (b == NULL || b->Size != SHA1_SIZE)\r
+                                       {\r
+                                               Hash(s->HashedPassword, password, StrLen(password), true);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               Copy(s->HashedPassword, b->Buf, SHA1_SIZE);\r
+                                       }\r
+                                       FreeBuf(b);\r
+\r
+                                       o = &s->ClientOption;\r
+\r
+                                       UniStrCpy(o->AccountName, sizeof(o->AccountName), s->Title);\r
+                                       StrCpy(o->Hostname, sizeof(o->Hostname), host);\r
+                                       o->Port = port;\r
+                                       o->ProxyType = PROXY_DIRECT;\r
+                                       StrCpy(o->DeviceName, sizeof(o->DeviceName), "DUMMY");\r
+\r
+                                       sm->TempSetting = s;\r
+\r
+                                       if (IsEmptyStr(hwndstr) == false)\r
+                                       {\r
+                                               sm->hParentWnd = (HWND)ToInt64(hwndstr);\r
+                                       }\r
+                               }\r
+\r
+                               Free(hwndstr);\r
+                               Free(title);\r
+                               Free(hub);\r
+                               Free(password);\r
+                               Free(host);\r
+                       }\r
+               }\r
+       }\r
+\r
+       Free(cmdline);\r
+\r
+       c->Free(c);\r
+}\r
+\r
+// 解放\r
+void FreeSM()\r
+{\r
+       if (sm == NULL)\r
+       {\r
+               // 初期化されていない\r
+               return;\r
+       }\r
+\r
+       FreeCM();\r
+\r
+       SmFreeSettingList();\r
+\r
+       ReleaseCedar(sm->Cedar);\r
+\r
+       FreeWinUi();\r
+\r
+       if (sm->TempSetting != NULL)\r
+       {\r
+               Free(sm->TempSetting);\r
+       }\r
+\r
+       Free(sm);\r
+       sm = NULL;\r
+}\r
+\r
+// Server Manager の実行\r
+void SMExec()\r
+{\r
+       InitSM();\r
+       MainSM();\r
+       FreeSM();\r
+}\r
+\r
+#endif // WIN32\r
+\r
+\r