* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / CM.c
diff --git a/utvpn/utvpn-unix-v101-7101-public/src/Cedar/CM.c b/utvpn/utvpn-unix-v101-7101-public/src/Cedar/CM.c
new file mode 100644 (file)
index 0000000..0927b25
--- /dev/null
@@ -0,0 +1,12153 @@
+// 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
+// CM.c\r
+// Win32 用 SoftEther UT-VPN クライアント接続マネージャ\r
+\r
+\r
+#ifdef WIN32\r
+\r
+#define        CM_C\r
+#define        SM_C\r
+#define        MICROSOFT_C\r
+\r
+#define        _WIN32_WINNT            0x0502\r
+#define        WINVER                          0x0502\r
+#include <winsock2.h>\r
+#include <windows.h>\r
+#include <Iphlpapi.h>\r
+#include <tlhelp32.h>\r
+#include <shlobj.h>\r
+#include <commctrl.h>\r
+#include <Dbghelp.h>\r
+#include <setupapi.h>\r
+#include <regstr.h>\r
+#include <process.h>\r
+#include <psapi.h>\r
+#include <wtsapi32.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
+// IE のレジストリ文字列からプロキシサーバーの設定を取得する\r
+bool CmGetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type)\r
+{\r
+       TOKEN_LIST *t;\r
+       UINT i;\r
+       bool ret = false;\r
+       // 引数チェック\r
+       if (name == NULL || port == NULL || str == NULL || server_type == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       t = ParseToken(str, ";");\r
+\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               char *s = t->Token[i];\r
+               UINT i;\r
+\r
+               Trim(s);\r
+\r
+               i = SearchStrEx(s, "=", 0, false);\r
+               if (i != INFINITE)\r
+               {\r
+                       char tmp[MAX_PATH];\r
+\r
+                       StrCpy(name, name_size, s);\r
+                       name[i] = 0;\r
+\r
+                       if (StrCmpi(name, server_type) == 0)\r
+                       {\r
+                               char *host;\r
+                               StrCpy(tmp, sizeof(tmp), s + i + 1);\r
+\r
+                               if (ParseHostPort(tmp, &host, port, 0))\r
+                               {\r
+                                       StrCpy(name, name_size, host);\r
+                                       Free(host);\r
+\r
+                                       if (*port != 0)\r
+                                       {\r
+                                               ret = true;\r
+                                       }\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       return ret;\r
+}\r
+\r
+\r
+// 接続設定にプロキシ設定の内容を反映する\r
+void CmProxyDlgSet(HWND hWnd, CLIENT_OPTION *o, CM_INTERNET_SETTING *setting)\r
+{\r
+       // 引数チェック\r
+       if(hWnd == NULL || setting == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // チェックをつける\r
+       Check(hWnd, R_DIRECT_TCP,       setting->ProxyType == PROXY_DIRECT);\r
+       Check(hWnd, R_HTTPS,            setting->ProxyType == PROXY_HTTP);\r
+       Check(hWnd, R_SOCKS,            setting->ProxyType == PROXY_SOCKS);\r
+\r
+       // Proxy 設定\r
+       if(setting->ProxyType != PROXY_DIRECT)\r
+       {\r
+               StrCpy(o->ProxyName, sizeof(setting->ProxyHostName), setting->ProxyHostName);\r
+               o->ProxyPort = setting->ProxyPort;\r
+       }\r
+}\r
+\r
+// IE のプロキシ設定を取得する\r
+void CmGetSystemInternetSetting(CM_INTERNET_SETTING *setting)\r
+{\r
+       bool use_proxy;\r
+       // 引数チェック\r
+       if (setting == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(setting, sizeof(CM_INTERNET_SETTING));\r
+\r
+       use_proxy = MsRegReadInt(REG_CURRENT_USER,\r
+               "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",\r
+               "ProxyEnable");\r
+\r
+       if (use_proxy)\r
+       {\r
+               char *str = MsRegReadStr(REG_CURRENT_USER,\r
+                       "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",\r
+                       "ProxyServer");\r
+               if (str != NULL)\r
+               {\r
+                       char name[MAX_HOST_NAME_LEN + 1];\r
+                       UINT port;\r
+\r
+                       if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),\r
+                               &port, str, "https"))\r
+                       {\r
+                               setting->ProxyType = PROXY_HTTP;\r
+                               StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);\r
+                               setting->ProxyPort = port;\r
+                       }\r
+                       else if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),\r
+                               &port, str, "http"))\r
+                       {\r
+                               setting->ProxyType = PROXY_HTTP;\r
+                               StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);\r
+                               setting->ProxyPort = port;\r
+                       }\r
+                       else if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),\r
+                               &port, str, "socks"))\r
+                       {\r
+                               setting->ProxyType = PROXY_SOCKS;\r
+                               StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);\r
+                               setting->ProxyPort = port;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (SearchStrEx(str, "=", 0, false) == INFINITE)\r
+                               {\r
+                                       char *host;\r
+                                       UINT port;\r
+                                       if (ParseHostPort(str, &host, &port, 0))\r
+                                       {\r
+                                               if (port != 0)\r
+                                               {\r
+                                                       setting->ProxyType = PROXY_HTTP;\r
+                                                       StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), host);\r
+                                                       setting->ProxyPort = port;\r
+                                               }\r
+                                               Free(host);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       Free(str);\r
+               }\r
+       }\r
+}\r
+\r
+// 経由するプロキシ設定で、IE の設定を使用する\r
+void CmProxyDlgUseForIE(HWND hWnd, CLIENT_OPTION *o)\r
+{\r
+       CM_INTERNET_SETTING s;\r
+\r
+       // 引数チェック\r
+       if(hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&s, sizeof(s));\r
+       CmGetSystemInternetSetting(&s);\r
+       \r
+       CmProxyDlgSet(hWnd, o, &s);\r
+}\r
+\r
+// スマートカード認証画面のビットマップ ID を決定する\r
+UINT CmGetSecureBitmapId(char *dest_hostname)\r
+{\r
+       // 引数チェック\r
+       if (dest_hostname == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// UAC のウインドウをアクティブにする\r
+void CmSetUacWindowActive()\r
+{\r
+       HWND hWnd;\r
+\r
+       if (MsIsVista() == false)\r
+       {\r
+               return;\r
+       }\r
+       \r
+       hWnd = FindWindowA("$$$Secure UAP Dummy Window Class For Interim Dialog", NULL);\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SwitchToThisWindow(hWnd, true);\r
+}\r
+\r
+// UAC ヘルパースレッド\r
+void CmUacHelperThread(THREAD *thread, void *param)\r
+{\r
+       CM_UAC_HELPER *c = (CM_UAC_HELPER *)param;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       while (c->Halt == false)\r
+       {\r
+               CmSetUacWindowActive();\r
+\r
+               Wait(c->HaltEvent, 200);\r
+       }\r
+}\r
+\r
+// UAC ヘルパーの開始\r
+void *CmStartUacHelper()\r
+{\r
+       CM_UAC_HELPER *c = ZeroMalloc(sizeof(CM_UAC_HELPER));\r
+\r
+       c->HaltEvent = NewEvent();\r
+       c->Thread = NewThread(CmUacHelperThread, c);\r
+\r
+       return (void *)c;\r
+}\r
+\r
+// UAC ヘルパーの終了\r
+void CmStopUacHelper(void *p)\r
+{\r
+       CM_UAC_HELPER *c = (CM_UAC_HELPER *)p;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       c->Halt = true;\r
+       Set(c->HaltEvent);\r
+       WaitThread(c->Thread, INFINITE);\r
+       ReleaseEvent(c->HaltEvent);\r
+       ReleaseThread(c->Thread);\r
+\r
+       Free(c);\r
+}\r
+\r
+// 簡易接続マネージャのコマンド呼び出し\r
+void CmEasyDlgOnCommand(HWND hWnd, CM_EASY_DLG *d, WPARAM wParam, LPARAM lParam)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       switch (wParam)\r
+       {\r
+       case B_MODE:\r
+               Command(hWnd, CMD_CM_SETTING);\r
+               return;\r
+\r
+       case B_STATUS:\r
+               Command(hWnd, CMD_STATUS);\r
+               return;\r
+\r
+       case IDCANCEL:\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       if (wParam == CMD_CONNECT)\r
+       {\r
+               cm->ConnectStartedFlag = false;\r
+       }\r
+\r
+       CmMainWindowOnCommandEx(hWnd, wParam, lParam, true);\r
+\r
+       if (wParam == CMD_CONNECT && cm->ConnectStartedFlag)\r
+       {\r
+               // 接続を開始することに成功したらウインドウを閉じる\r
+               Close(hWnd);\r
+       }\r
+}\r
+\r
+// 簡易接続マネージャのキーボード押下\r
+void CmEasyDlgOnKey(HWND hWnd, CM_EASY_DLG *d, bool ctrl, bool alt, UINT key)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 単一キー\r
+       switch (key)\r
+       {\r
+       case VK_RETURN:\r
+               Command(hWnd, IDOK);\r
+               break;\r
+       case VK_DELETE:\r
+               // 削除\r
+               if (IsFocus(hWnd, L_ACCOUNT))\r
+               {\r
+                       // アカウントリストに関する操作\r
+                       Command(hWnd, CMD_DELETE);\r
+               }\r
+               else\r
+               {\r
+                       // 仮想 LAN カードリストに関する操作\r
+                       Command(hWnd, CMD_DELETE_VLAN);\r
+               }\r
+               break;\r
+       case VK_F2:\r
+               // 名前変更\r
+               Command(hWnd, CMD_RENAME);\r
+               break;\r
+       case VK_F5:\r
+               // 状態更新\r
+               Command(hWnd, CMD_REFRESH);\r
+               break;\r
+       }\r
+\r
+       if (alt)\r
+       {\r
+               switch (key)\r
+               {\r
+               case 'Q':\r
+                       // 閉じる\r
+                       Command(hWnd, CMD_QUIT);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (ctrl)\r
+       {\r
+               switch (key)\r
+               {\r
+               case 'G':\r
+                       // スマートカードマネージャ\r
+                       Command(hWnd, CMD_SECURE_MANAGER);\r
+                       break;\r
+               case 'S':\r
+                       // 状態の表示\r
+                       Command(hWnd, CMD_STATUS);\r
+                       break;\r
+               case 'I':\r
+                       // すべての接続を切断\r
+                       Command(hWnd, CMD_DISCONNECT_ALL);\r
+                       break;\r
+               case 'D':\r
+                       // 切断\r
+                       Command(hWnd, CMD_DISCONNECT);\r
+                       break;\r
+               case 'N':\r
+                       // 接続設定の新規作成\r
+                       Command(hWnd, CMD_NEW);\r
+                       break;\r
+               case 'C':\r
+                       // コピーの作成\r
+                       Command(hWnd, CMD_CLONE);\r
+                       break;\r
+               case 'T':\r
+                       // スタートアップ接続に設定\r
+                       Command(hWnd, CMD_STARTUP);\r
+                       break;\r
+               case 'A':\r
+                       // すべて選択\r
+                       Command(hWnd, CMD_SELECT_ALL);\r
+                       break;\r
+               case 'L':\r
+                       // 新規仮想 LAN カードの作成\r
+                       Command(hWnd, CMD_NEW_VLAN);\r
+                       break;\r
+               case 'P':\r
+                       // パスワードの設定\r
+                       Command(hWnd, CMD_PASSWORD);\r
+                       break;\r
+               case 'O':\r
+                       // オプション設定\r
+                       Command(hWnd, CMD_TRAFFIC);\r
+                       break;\r
+               case 'R':\r
+                       // 証明書管理\r
+                       Command(hWnd, CMD_TRUST);\r
+                       break;\r
+               case 'Q':\r
+                       // スループット\r
+                       Command(hWnd, CMD_TRAFFIC);\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+// 簡易接続マネージャのリストビューに対する操作\r
+void CmEasyDlgOnNotify(HWND hWnd, CM_EASY_DLG *d, NMHDR *n)\r
+{\r
+       NMLVDISPINFOW *disp_info;\r
+       NMLVKEYDOWN *key;\r
+\r
+       // 引数チェック\r
+       if (hWnd == NULL || n == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       switch (n->idFrom)\r
+       {\r
+       case L_ACCOUNT:\r
+               switch (n->code)\r
+               {\r
+               case LVN_ITEMCHANGED:\r
+                       CmEasyDlgUpdate(hWnd, d);\r
+                       break;\r
+               case NM_DBLCLK:\r
+                       // ダブルクリック\r
+                       Command(hWnd, CMD_EASY_DBLCLICK);\r
+                       break;\r
+               case NM_RCLICK:\r
+                       // 右クリック\r
+                       CmAccountListRightClick(hWnd);\r
+                       break;\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_ACCOUNT, 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_ACCOUNT a;\r
+                                               Zero(&a, sizeof(a));\r
+                                               UniStrCpy(a.OldName, sizeof(a.OldName), old_name);\r
+                                               UniStrCpy(a.NewName, sizeof(a.NewName), new_name);\r
+                                               if (CALL(hWnd, CcRenameAccount(cm->Client, &a)))\r
+                                               {\r
+                                                       LvSetItem(hWnd, L_ACCOUNT, disp_info->item.iItem, 0, new_name);\r
+                                               }\r
+                                       }\r
+\r
+                                       Free(old_name);\r
+                               }\r
+                       }\r
+                       break;\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
+                               CmEasyDlgOnKey(hWnd, d, ctrl, alt, code);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+}\r
+\r
+// 簡易接続マネージャに対して更新通知を送信する\r
+void CmRefreshEasy()\r
+{\r
+       if (cm->hEasyWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SendMessage(cm->hEasyWnd, WM_CM_EASY_REFRESH, 0, 0);\r
+}\r
+\r
+// 簡易接続マネージャ初期化\r
+void CmEasyDlgInit(HWND hWnd, CM_EASY_DLG *d)\r
+{\r
+       HFONT hFontForList;\r
+       HFONT hFontButton;\r
+       HFONT hFontTitle;\r
+       HFONT hFontInfo;\r
+       HFONT hFontOther;\r
+       UINT i, num, num2, j;\r
+       bool b = false;\r
+       char *font_name = NULL;\r
+       bool font_bold = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_VPN);\r
+\r
+       // ウインドウハンドル登録\r
+       cm->hEasyWnd = hWnd;\r
+\r
+       // 中央に表示\r
+       Center(hWnd);\r
+\r
+       // アカウントリストの更新\r
+       CmInitAccountListEx(hWnd, true);\r
+\r
+       // リストのフォント設定\r
+       if (cm->VistaStyle)\r
+       {\r
+               if (_GETLANG() == 0)\r
+               {\r
+                       font_name = "Meiryo";\r
+                       font_bold = false;\r
+               }\r
+               else if (_GETLANG() == 2)\r
+               {\r
+                       font_name = "Microsoft YaHei";\r
+                       font_bold = false;\r
+               }\r
+       }\r
+\r
+       hFontForList = GetFont(font_name, 14, font_bold, false, false, false);\r
+       hFontButton = GetFont(font_name, 13, font_bold, false, false, false);\r
+       hFontTitle = GetFont(font_name, 14, font_bold, false, false, false);\r
+       hFontInfo = GetFont(font_name, 11, font_bold, false, false, false);\r
+       hFontOther = GetDialogDefaultFont();\r
+\r
+       if (cm->VistaStyle)\r
+       {\r
+               hFontOther = GetMeiryoFont();\r
+       }\r
+\r
+       SetFont(hWnd, L_ACCOUNT, hFontForList);\r
+       SetFont(hWnd, IDOK, hFontButton);\r
+       SetFont(hWnd, S_TITLE, hFontTitle);\r
+       SetFont(hWnd, S_INFO, hFontInfo);\r
+       SetFont(hWnd, B_MODE, hFontOther);\r
+       SetFont(hWnd, IDCANCEL, hFontOther);\r
+\r
+       CmEasyDlgRefresh(hWnd, d);\r
+\r
+       num = LvNum(hWnd, L_ACCOUNT);\r
+       num2 = 0;\r
+       j = 0;\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+\r
+               if (str != NULL)\r
+               {\r
+                       if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                       {\r
+                               num2++;\r
+                               j = i;\r
+                       }\r
+                       Free(str);\r
+               }\r
+       }\r
+\r
+       if (num2 == 1)\r
+       {\r
+               LvSelect(hWnd, L_ACCOUNT, j);\r
+               b = true;\r
+       }\r
+\r
+       if (b == false)\r
+       {\r
+               if (UniIsEmptyStr(cm->EasyLastSelectedAccountName) == false)\r
+               {\r
+                       i = LvSearchStr(hWnd, L_ACCOUNT, 0, cm->EasyLastSelectedAccountName);\r
+                       if (i != INFINITE)\r
+                       {\r
+                               LvSelect(hWnd, L_ACCOUNT, i);\r
+                               b = true;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (b == false)\r
+       {\r
+               if (LvNum(hWnd, L_ACCOUNT) != 0)\r
+               {\r
+                       LvSelect(hWnd, L_ACCOUNT, 0);\r
+               }\r
+       }\r
+\r
+       Focus(hWnd, L_ACCOUNT);\r
+\r
+       CmEasyDlgUpdate(hWnd, d);\r
+}\r
+\r
+// 簡易接続マネージャコントロール更新\r
+void CmEasyDlgUpdate(HWND hWnd, CM_EASY_DLG *d)\r
+{\r
+       bool ok = true;\r
+       bool show_status = false;\r
+       wchar_t *button_str = _UU("CM_EASY_CONNECT_BUTTON_1");\r
+       wchar_t *info_str = _UU("CM_EASY_INFO_1");\r
+       wchar_t *title_str = _UU("CM_EASY_TITLE");\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSingleSelected(hWnd, L_ACCOUNT) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               UINT i = LvGetSelected(hWnd, L_ACCOUNT);\r
+               wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+\r
+               info_str = _UU("CM_EASY_INFO_2");\r
+\r
+               if (str != NULL)\r
+               {\r
+                       if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                       {\r
+                               button_str = _UU("CM_EASY_CONNECT_BUTTON_2");\r
+                               show_status = true;\r
+                               info_str = _UU("CM_EASY_INFO_3");\r
+\r
+                               if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0)\r
+                               {\r
+                                       title_str = _UU("CM_EASY_CONNECTED");\r
+                               }\r
+                               else\r
+                               {\r
+                                       title_str = _UU("CM_EASY_CONNECTING");\r
+                               }\r
+                       }\r
+                       Free(str);\r
+               }\r
+       }\r
+\r
+       SetShow(hWnd, B_STATUS, show_status);\r
+\r
+       SetText(hWnd, IDOK, button_str);\r
+       SetText(hWnd, S_INFO, info_str);\r
+       SetText(hWnd, S_TITLE, title_str);\r
+\r
+       SetShow(hWnd, IDOK, ok);\r
+}\r
+\r
+// 簡易接続マネージャ内容更新\r
+void CmEasyDlgRefresh(HWND hWnd, CM_EASY_DLG *d)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // アカウントリスト更新\r
+       CmRefreshAccountListEx(hWnd, true);\r
+\r
+       CmEasyDlgUpdate(hWnd, d);\r
+}\r
+\r
+// 簡易接続マネージャのダイアログプロシージャ\r
+UINT CmEasyDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_EASY_DLG *d = (CM_EASY_DLG *)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
+               CmEasyDlgInit(hWnd, d);\r
+               SetTimer(hWnd, 1, 10, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       SetForegroundWindow(hWnd);\r
+                       SetActiveWindow(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CM_EASY_REFRESH:\r
+               CmEasyDlgRefresh(hWnd, d);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               CmEasyDlgOnCommand(hWnd, d, wParam, lParam);\r
+               break;\r
+\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               CmEasyDlgOnNotify(hWnd, d, n);\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               i = LvGetSelected(hWnd, L_ACCOUNT);\r
+               if (i != INFINITE)\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               UniStrCpy(cm->EasyLastSelectedAccountName, sizeof(cm->EasyLastSelectedAccountName),\r
+                                       s);\r
+                               Free(s);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       Zero(cm->EasyLastSelectedAccountName, sizeof(cm->EasyLastSelectedAccountName));\r
+               }\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 簡易接続マネージャのウインドウを表示する (遅延タイマで呼び出される)\r
+void CmMainWindowOnShowEasy(HWND hWnd)\r
+{\r
+       CM_EASY_DLG d;\r
+\r
+       Zero(&d, sizeof(d));\r
+\r
+       if (cm->CmSetting.EasyMode == false)\r
+       {\r
+               // 簡易モードではない\r
+               return;\r
+       }\r
+\r
+       if (cm->hEasyWnd != NULL)\r
+       {\r
+               // すでに表示されている\r
+               SetForegroundWindow(cm->hEasyWnd);\r
+               SetActiveWindow(cm->hEasyWnd);\r
+               return;\r
+       }\r
+\r
+       Dialog(NULL, D_CM_EASY, CmEasyDlg, &d);\r
+\r
+       cm->hEasyWnd = NULL;\r
+}\r
+\r
+// 簡易接続マネージャのウインドウを表示する\r
+void CmShowEasy()\r
+{\r
+       SetTimer(cm->hMainWnd, 4, 2, NULL);\r
+}\r
+\r
+// 簡易接続マネージャのウインドウを閉じる\r
+void CmCloseEasy()\r
+{\r
+       if (cm->hEasyWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SendMessage(cm->hEasyWnd, WM_CLOSE, 0, 0);\r
+}\r
+\r
+// トレイアイコンのクリック等のメッセージ処理\r
+void CmMainWindowOnTrayClicked(HWND hWnd, WPARAM wParam, LPARAM lParam)\r
+{\r
+       bool easymode = cm->CmSetting.EasyMode;\r
+\r
+       switch (wParam)\r
+       {\r
+       case 1:\r
+               switch (lParam)\r
+               {\r
+               case WM_LBUTTONDOWN:\r
+               case WM_RBUTTONDOWN:\r
+                       // クリック\r
+                       if (easymode == false)\r
+                       {\r
+                               if (IsEnable(hWnd, 0))\r
+                               {\r
+                                       CmShowTrayMenu(hWnd);\r
+                               }\r
+                               else\r
+                               {\r
+                                       CmShowOrHideWindow(hWnd);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (cm->hEasyWnd == NULL || IsEnable(cm->hEasyWnd, 0))\r
+                               {\r
+                                       CmShowTrayMenu(hWnd);\r
+                               }\r
+                               else\r
+                               {\r
+                                       //CmShowOrHideWindow(hWnd);\r
+                               }\r
+                       }\r
+                       break;\r
+               case WM_LBUTTONDBLCLK:\r
+               case WM_RBUTTONDBLCLK:\r
+                       // ダブルクリック\r
+                       if (easymode == false)\r
+                       {\r
+                               if (IsEnable(hWnd, 0))\r
+                               {\r
+                                       CmShowOrHideWindow(hWnd);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (cm->hEasyWnd == NULL)\r
+                               {\r
+                                       CmShowEasy();\r
+                               }\r
+                               else\r
+                               {\r
+                                       SetForegroundWindow(cm->hEasyWnd);\r
+                                       SetActiveWindow(cm->hEasyWnd);\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+}\r
+\r
+// 動作モードの設定の適用\r
+void CmApplyCmSetting()\r
+{\r
+       CM_SETTING a;\r
+       bool changed = false;\r
+\r
+       if (cm->CmSettingSupported == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 現在の vpnclient の設定を取得する\r
+       Zero(&a, sizeof(a));\r
+       CcGetCmSetting(cm->Client, &a);\r
+\r
+       // 以前の CM_SETTING と比較して変化点があるか調べる\r
+       if (cm->CmSetting.EasyMode != a.EasyMode)\r
+       {\r
+               changed = true;\r
+       }\r
+       if (cm->CmSetting.LockMode != a.LockMode)\r
+       {\r
+               changed = true;\r
+       }\r
+\r
+       Copy(&cm->CmSetting, &a, sizeof(CM_SETTING));\r
+\r
+       if (changed == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->StartupFinished)\r
+       {\r
+               if (IsShow(cm->hMainWnd, 0) && cm->CmSetting.EasyMode)\r
+               {\r
+                       // メインウインドウが表示されていれば閉じる\r
+                       Hide(cm->hMainWnd, 0);\r
+               }\r
+               else\r
+               {\r
+                       if (cm->CmSetting.EasyMode == false && IsShow(cm->hMainWnd, 0) == false)\r
+                       {\r
+                               // 通常モードに復帰した際は、メインウインドウを復元する\r
+                               if (IsZero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement)) == false)\r
+                               {\r
+                                       cm->FakeWindowPlacement.flags = cm->FakeWindowPlacement.flags & ~SW_MINIMIZE;\r
+                                       SetWindowPlacement(cm->hMainWnd, &cm->FakeWindowPlacement);\r
+                                       Zero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement));\r
+                                       Hide(cm->hMainWnd, 0);\r
+                               }\r
+                               CmShowOrHideWindow(cm->hMainWnd);\r
+                       }\r
+               }\r
+\r
+               Command(cm->hMainWnd, CMD_REFRESH);\r
+       }\r
+\r
+       if (cm->CmSetting.EasyMode)\r
+       {\r
+               if (cm->StartupFinished == false && cm->StartupMode)\r
+               {\r
+                       // /startup の場合は表示しない\r
+               }\r
+               else\r
+               {\r
+                       CmShowEasy();\r
+               }\r
+       }\r
+       else\r
+       {\r
+               CmCloseEasy();\r
+       }\r
+}\r
+\r
+// 動作モード変更ダイアログ初期化\r
+void CmSettingDlgInit(HWND hWnd, CM_SETTING_DLG *d)\r
+{\r
+       CM_SETTING a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 現在の vpnclient の設定を取得する\r
+       Zero(&a, sizeof(a));\r
+       CcGetCmSetting(cm->Client, &a);\r
+\r
+       Check(hWnd, R_EASY, a.EasyMode);\r
+       Check(hWnd, R_NORMAL, a.EasyMode == false);\r
+\r
+       if (a.EasyMode == false)\r
+       {\r
+               Focus(hWnd, R_NORMAL);\r
+       }\r
+       else\r
+       {\r
+               Focus(hWnd, R_EASY);\r
+       }\r
+\r
+       Check(hWnd, R_LOCK, a.LockMode);\r
+\r
+       SetEnable(hWnd, R_EASY, cm->CmEasyModeSupported);\r
+\r
+       if (a.LockMode)\r
+       {\r
+               if (IsZero(a.HashedPassword, sizeof(a.HashedPassword)) == false)\r
+               {\r
+                       // パスワードが設定されている\r
+                       SetText(hWnd, S_PASSWORD1, _UU("CM_SETTING_PASSWORD"));\r
+                       Hide(hWnd, S_PASSWORD3);\r
+                       Hide(hWnd, E_PASSWORD2);\r
+\r
+                       d->CheckPassword = true;\r
+                       Copy(d->HashedPassword, a.HashedPassword, sizeof(d->HashedPassword));\r
+               }\r
+       }\r
+\r
+       CmSettingDlgUpdate(hWnd, d);\r
+}\r
+\r
+// 動作モード変更ダイアログ更新\r
+void CmSettingDlgUpdate(HWND hWnd, CM_SETTING_DLG *d)\r
+{\r
+       bool ok = true;\r
+       char tmp1[MAX_SIZE], tmp2[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));\r
+       GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+\r
+       if (d->CheckPassword == false)\r
+       {\r
+               if (IsChecked(hWnd, R_LOCK))\r
+               {\r
+                       if (StrCmp(tmp1, tmp2) != 0)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               bool password_ok = false;\r
+               UCHAR hash[SHA1_SIZE];\r
+\r
+               Hash(hash, tmp1, StrLen(tmp1), true);\r
+               if (Cmp(hash, d->HashedPassword, sizeof(hash)) == 0)\r
+               {\r
+                       password_ok = true;\r
+               }\r
+\r
+               if (password_ok == false)\r
+               {\r
+                       Check(hWnd, R_LOCK, true);\r
+                       Disable(hWnd, R_LOCK);\r
+               }\r
+               else\r
+               {\r
+                       Enable(hWnd, R_LOCK);\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, S_PASSWORD1, IsChecked(hWnd, R_LOCK));\r
+       SetEnable(hWnd, S_PASSWORD2, IsChecked(hWnd, R_LOCK));\r
+       SetEnable(hWnd, S_PASSWORD3, IsChecked(hWnd, R_LOCK));\r
+       SetEnable(hWnd, E_PASSWORD1, IsChecked(hWnd, R_LOCK));\r
+       SetEnable(hWnd, E_PASSWORD2, IsChecked(hWnd, R_LOCK));\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// 動作モード変更ダイアログ OK\r
+void CmSettingDlgOnOk(HWND hWnd, CM_SETTING_DLG *d)\r
+{\r
+       CM_SETTING a;\r
+       char tmp1[MAX_SIZE], tmp2[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));\r
+       GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+\r
+       Zero(&a, sizeof(a));\r
+\r
+       a.EasyMode = IsChecked(hWnd, R_EASY);\r
+       a.LockMode = IsChecked(hWnd, R_LOCK);\r
+\r
+       if (a.LockMode)\r
+       {\r
+               if (d->CheckPassword && IsEnable(hWnd, R_LOCK) == false)\r
+               {\r
+                       Copy(a.HashedPassword, d->HashedPassword, sizeof(a.HashedPassword));\r
+               }\r
+               else\r
+               {\r
+                       if (StrLen(tmp1) >= 1)\r
+                       {\r
+                               Hash(a.HashedPassword, tmp1, StrLen(tmp1), true);\r
+                       }\r
+               }\r
+       }\r
+\r
+       CcSetCmSetting(cm->Client, &a);\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// 動作モード変更ダイアログ\r
+UINT CmSettingDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_SETTING_DLG *d = (CM_SETTING_DLG *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmSettingDlgInit(hWnd, d);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_EASY:\r
+               case R_NORMAL:\r
+               case R_LOCK:\r
+               case E_PASSWORD1:\r
+               case E_PASSWORD2:\r
+               case IDOK:\r
+               case IDCANCEL:\r
+                       CmSettingDlgUpdate(hWnd, d);\r
+                       break;\r
+               }\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       CmSettingDlgOnOk(hWnd, d);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_LOCK:\r
+                       if (IsChecked(hWnd, R_LOCK))\r
+                       {\r
+                               if (IsEmpty(hWnd, E_PASSWORD1))\r
+                               {\r
+                                       Focus(hWnd, E_PASSWORD1);\r
+                               }\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 CmSetting(HWND hWnd)\r
+{\r
+       CM_SETTING_DLG d;\r
+\r
+       Zero(&d, sizeof(d));\r
+\r
+       return Dialog(hWnd, D_CM_SETTING, CmSettingDlg, &d);\r
+}\r
+\r
+// UI Helper の起動の試行スレッド\r
+void CmTryToExecUiHelperThread(THREAD *thread, void *param)\r
+{\r
+       // このあたりは急いで実装したのでコードがあまり美しくない。\r
+       bool first_flag = true;\r
+\r
+       while (cm->TryExecUiHelperHalt == false && cm->WindowsShutdowning == false)\r
+       {\r
+               if (first_flag == false)\r
+               {\r
+                       // 初回以外は少し待つ\r
+                       Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL * 2);\r
+\r
+                       if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+               first_flag = false;\r
+\r
+               if (cm->TryExecUiHelperHalt == false && cm->WindowsShutdowning == false)\r
+               {\r
+                       if (cm->TryExecUiHelperProcessHandle == NULL)\r
+                       {\r
+                               CmTryToExecUiHelper();\r
+                       }\r
+               }\r
+\r
+               if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)\r
+               {\r
+                       break;\r
+               }\r
+\r
+               if (cm->TryExecUiHelperProcessHandle == NULL)\r
+               {\r
+                       Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL);\r
+               }\r
+               else\r
+               {\r
+                       HANDLE handles[2];\r
+                       handles[0] = cm->TryExecUiHelperProcessHandle;\r
+                       handles[1] = (HANDLE)cm->TryExecUiHelperHaltEvent->pData;\r
+                       WaitForMultipleObjects(2, handles, false, CM_TRY_EXEC_UI_HELPER_INTERVAL);\r
+\r
+                       if (WaitForSingleObject(cm->TryExecUiHelperProcessHandle, 0) != WAIT_TIMEOUT)\r
+                       {\r
+                               CloseHandle(cm->TryExecUiHelperProcessHandle);\r
+                               cm->TryExecUiHelperProcessHandle = NULL;\r
+                               if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)\r
+                               {\r
+                                       break;\r
+                               }\r
+                               Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL * 2);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+// UI Helper 終了\r
+void CmFreeTryToExecUiHelper()\r
+{\r
+       cm->TryExecUiHelperHalt = true;\r
+       Set(cm->TryExecUiHelperHaltEvent);\r
+\r
+       WaitThread(cm->TryExecUiHelperThread, INFINITE);\r
+\r
+       ReleaseThread(cm->TryExecUiHelperThread);\r
+       cm->TryExecUiHelperThread = NULL;\r
+\r
+       ReleaseEvent(cm->TryExecUiHelperHaltEvent);\r
+       cm->TryExecUiHelperHaltEvent = NULL;\r
+\r
+       cm->TryExecUiHelperHalt = false;\r
+       cm->TryExecUiHelperProcessHandle = NULL;\r
+}\r
+\r
+// UI Helper 起動初期化\r
+void CmInitTryToExecUiHelper()\r
+{\r
+       cm->TryExecUiHelperProcessHandle = NULL;\r
+       cm->TryExecUiHelperHalt = false;\r
+       cm->TryExecUiHelperHaltEvent = NewEvent();\r
+       cm->TryExecUiHelperThread = NewThread(CmTryToExecUiHelperThread, NULL);\r
+}\r
+\r
+// UI Helper の起動\r
+void *CmExecUiHelperMain()\r
+{\r
+       HANDLE h;\r
+       wchar_t tmp[MAX_SIZE];\r
+\r
+       UniFormat(tmp, sizeof(tmp), L"%s\\%S", MsGetExeDirNameW(), CiGetVpnClientExeFileName());\r
+\r
+       // 起動\r
+       h = Win32RunExW(tmp, SVC_ARG_UIHELP_W, false);\r
+\r
+       return (void *)h;\r
+}\r
+\r
+// UI Helper の起動の試行\r
+void CmTryToExecUiHelper()\r
+{\r
+       HANDLE h;\r
+       // 既に起動していないかどうかチェックする\r
+       if (CnCheckAlreadyExists(false))\r
+       {\r
+               // 既に起動している\r
+               return;\r
+       }\r
+\r
+       h = (HANDLE)CmExecUiHelperMain();\r
+\r
+       if (h != NULL)\r
+       {\r
+               cm->TryExecUiHelperProcessHandle = h;\r
+       }\r
+}\r
+\r
+// ダイアログ初期化\r
+void CmTrafficResultDlgInit(HWND hWnd, TT_RESULT *res)\r
+{\r
+       LVB *ct;\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t tmp1[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || res == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_SWITCH);\r
+\r
+       SetFont(hWnd, L_STATUS, GetFont(_SS("DEFAULT_FONT_2"), 10, false, false, false, false));\r
+\r
+       LvInit(hWnd, L_STATUS);\r
+       LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);\r
+       LvInsertColumn(hWnd, L_STATUS, 0, _UU("TTC_RES_COLUMN_1"), 100);\r
+       LvInsertColumn(hWnd, L_STATUS, 1, _UU("TTC_RES_COLUMN_2"), 100);\r
+       LvInsertColumn(hWnd, L_STATUS, 2, _UU("TTC_RES_COLUMN_3"), 100);\r
+\r
+       ct = LvInsertStart();\r
+\r
+       // 測定に使用した時間\r
+       GetSpanStrMilli(str, sizeof(str), res->Span);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       LvInsertAdd(ct, ICO_DATETIME, NULL, 3, _UU("TTC_RES_SPAN"), tmp, L"");\r
+\r
+       // Ethernet フレーム用にデータ補正\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_ETHER"), res->Raw ? _UU("SEC_NO") : _UU("SEC_YES"), L"");\r
+\r
+       // ダウンロード方向の通信データ量\r
+       ToStr3(str, sizeof(str), res->NumBytesDownload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);\r
+       ToStrByte1000(str, sizeof(str), res->NumBytesDownload);\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_DOWNLOAD"), tmp1, tmp2);\r
+\r
+       // アップロード方向の通信データ量\r
+       ToStr3(str, sizeof(str), res->NumBytesUpload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);\r
+       ToStrByte1000(str, sizeof(str), res->NumBytesUpload);\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_UPLOAD"), tmp1, tmp2);\r
+\r
+       // 合計通信データ量\r
+       ToStr3(str, sizeof(str), res->NumBytesTotal);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);\r
+       ToStrByte1000(str, sizeof(str), res->NumBytesTotal);\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_TOTAL"), tmp1, tmp2);\r
+\r
+       // 中継機器入出力合計スループット算出\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_DOUBLE"), (res->Double == false) ? _UU("SEC_NO") : _UU("SEC_YES"), L"");\r
+\r
+       // ダウンロード方向の平均スループット\r
+       ToStr3(str, sizeof(str), res->BpsDownload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);\r
+       ToStrByte1000(str, sizeof(str), res->BpsDownload);\r
+       ReplaceStr(str, sizeof(str), str, "Bytes", "bps");\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_DOWNLOAD"), tmp1, tmp2);\r
+\r
+       // アップロード方向の平均スループット\r
+       ToStr3(str, sizeof(str), res->BpsUpload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);\r
+       ToStrByte1000(str, sizeof(str), res->BpsUpload);\r
+       ReplaceStr(str, sizeof(str), str, "Bytes", "bps");\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_UPLOAD"), tmp1, tmp2);\r
+\r
+       // 合計平均スループット\r
+       ToStr3(str, sizeof(str), res->BpsTotal);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);\r
+       ToStrByte1000(str, sizeof(str), res->BpsTotal);\r
+       ReplaceStr(str, sizeof(str), str, "Bytes", "bps");\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_TOTAL"), tmp1, tmp2);\r
+\r
+       LvInsertEnd(ct, hWnd, L_STATUS);\r
+\r
+       LvAutoSize(hWnd, L_STATUS);\r
+}\r
+\r
+// トラフィック測定結果の表示ダイアログプロシージャ\r
+UINT CmTrafficResultDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       TT_RESULT *r = (TT_RESULT *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmTrafficResultDlgInit(hWnd, 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
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// トラフィック測定結果の表示\r
+void CmTrafficResult(HWND hWnd, TT_RESULT *r)\r
+{\r
+       // 引数チェック\r
+       if (r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_CM_TRAFFIC_RESULT, CmTrafficResultDlg, r);\r
+}\r
+\r
+// クライアントの終了を待機するスレッド\r
+void CmTrafficRunDlgClientWaitThread(THREAD *t, void *param)\r
+{\r
+       CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;\r
+       TT_RESULT result;\r
+       UINT ret;\r
+       // 引数チェック\r
+       if (t == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&result, sizeof(result));\r
+       ret = FreeTtc(d->Ttc, &result);\r
+       d->Ttc = NULL;\r
+\r
+       d->RetCode = ret;\r
+       Copy(&d->Result, &result, sizeof(TT_RESULT));\r
+\r
+       PostMessage(d->hWnd, WM_APP + 66, 0, 0);\r
+}\r
+\r
+// 文字列の追記\r
+void CmTrafficRunDlgAddStr(HWND hWnd, wchar_t *str)\r
+{\r
+       wchar_t *tmp;\r
+       UINT tmp_size;\r
+\r
+       tmp_size = UniStrSize(str) + 32;\r
+       tmp = Malloc(tmp_size);\r
+       UniStrCpy(tmp, tmp_size, str);\r
+       if (UniEndWith(str, L"\n") == false)\r
+       {\r
+               UniStrCat(tmp, tmp_size, L"\n");\r
+       }\r
+\r
+       UniReplaceStrEx(tmp, tmp_size, tmp, L"\r\n", L"\n", false);\r
+       UniReplaceStrEx(tmp, tmp_size, tmp, L"\n", L"\r\n", false);\r
+\r
+       if (MsIsNt())\r
+       {\r
+               SendMsg(hWnd, E_EDIT, EM_SETSEL, 0x7fffffff, 0x7fffffff);\r
+               SendMsg(hWnd, E_EDIT, EM_REPLACESEL, false, (LPARAM)tmp);\r
+       }\r
+       else\r
+       {\r
+               char *s = CopyUniToStr(tmp);\r
+               UINT len;\r
+\r
+               len = GetWindowTextLength(DlgItem(hWnd, E_EDIT));\r
+               SendMsg(hWnd, E_EDIT, EM_SETSEL, 0x7fffffff, 0x7fffffff);\r
+               SendMsg(hWnd, E_EDIT, EM_SETSEL, len, len);\r
+               SendMsg(hWnd, E_EDIT, EM_REPLACESEL, false, (LPARAM)s);\r
+               Free(s);\r
+       }\r
+\r
+       Free(tmp);\r
+}\r
+\r
+// 文字列の表示\r
+void CmTrafficRunDlgPrintProc(void *param, wchar_t *str)\r
+{\r
+       CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;\r
+       HWND hWnd;\r
+       // 引数チェック\r
+       if (param == NULL || str == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       hWnd = d->hWnd;\r
+\r
+       PostMessage(hWnd, WM_APP + 64, 0, (LPARAM)UniCopyStr(str));\r
+}\r
+\r
+// 測定プログラムの停止用スレッド\r
+void CmTrafficRunDlgHaltThread(THREAD *t, void *param)\r
+{\r
+       CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;\r
+       // 引数チェック\r
+       if (t == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (d->Setting->ServerMode)\r
+       {\r
+               // サーバーを停止\r
+               d->RetCode = FreeTts(d->Tts);\r
+\r
+               PostMessage(d->hWnd, WM_APP + 65, 0, 0);\r
+       }\r
+}\r
+\r
+// 測定プログラムを停止する\r
+void CmTrafficRunDlgHalt(HWND hWnd, CM_TRAFFIC_DLG *d)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (d->Started == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (d->Setting->ServerMode)\r
+       {\r
+               if (d->HaltThread == NULL)\r
+               {\r
+                       Disable(hWnd, IDCANCEL);\r
+                       d->HaltThread = NewThread(CmTrafficRunDlgHaltThread, d);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (d->ClientEndWaitThread != NULL)\r
+               {\r
+                       StopTtc(d->Ttc);\r
+               }\r
+               else\r
+               {\r
+                       EndDialog(hWnd, 0);\r
+               }\r
+       }\r
+}\r
+\r
+// トラフィック測定の動作を開始する\r
+void CmTrafficRunDlgStart(HWND hWnd, CM_TRAFFIC_DLG *d)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (d->Setting->ServerMode)\r
+       {\r
+               // 測定サーバーを開始\r
+               d->Tts = NewTts(d->Setting->Port, d, CmTrafficRunDlgPrintProc);\r
+       }\r
+       else\r
+       {\r
+               // 測定クライアントを開始\r
+               d->Ttc = NewTtc(d->Setting->Host, d->Setting->Port,\r
+                       d->Setting->NumTcp, d->Setting->Type, d->Setting->Span * 1000ULL,\r
+                       d->Setting->Double, d->Setting->Raw, CmTrafficRunDlgPrintProc, d);\r
+\r
+               d->ClientEndWaitThread = NewThread(CmTrafficRunDlgClientWaitThread, d);\r
+       }\r
+\r
+       d->Started = true;\r
+}\r
+\r
+// トラフィック測定実行ダイアログ初期化\r
+void CmTrafficRunDlgInit(HWND hWnd, CM_TRAFFIC_DLG *d)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || d == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       d->hWnd = hWnd;\r
+\r
+       SetIcon(hWnd, 0, ICO_SWITCH);\r
+       DlgFont(hWnd, S_INFO, 11, false);\r
+       SetFont(hWnd, E_EDIT, GetFont(_SS("DEFAULT_FONT_2"), 0, false, false,\r
+               false, false));\r
+\r
+       Focus(hWnd, IDCANCEL);\r
+}\r
+\r
+// トラフィック測定実行ダイアログプロシージャ\r
+UINT CmTrafficRunDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;\r
+       wchar_t *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmTrafficRunDlgInit(hWnd, d);\r
+\r
+               SetTimer(hWnd, 1, 10, NULL);\r
+               break;\r
+\r
+       case WM_APP + 64:\r
+               // 文字列追加\r
+               s = (wchar_t *)lParam;\r
+               if (s != NULL)\r
+               {\r
+                       CmTrafficRunDlgAddStr(hWnd, s);\r
+                       Free(s);\r
+               }\r
+               break;\r
+\r
+       case WM_APP + 65:\r
+               // 停止完了\r
+               if (d->HaltThread != NULL)\r
+               {\r
+                       WaitThread(d->HaltThread, INFINITE);\r
+                       ReleaseThread(d->HaltThread);\r
+                       d->HaltThread = NULL;\r
+                       EndDialog(hWnd, 0);\r
+               }\r
+               break;\r
+\r
+       case WM_APP + 66:\r
+               // 結果表示\r
+               if (d->RetCode == ERR_NO_ERROR)\r
+               {\r
+                       CmTrafficResult(hWnd, &d->Result);\r
+               }\r
+\r
+               if (d->ClientEndWaitThread != NULL)\r
+               {\r
+                       WaitThread(d->ClientEndWaitThread, INFINITE);\r
+                       ReleaseThread(d->ClientEndWaitThread);\r
+                       d->ClientEndWaitThread = NULL;\r
+               }\r
+\r
+               if (d->CloseDialogAfter)\r
+               {\r
+                       EndDialog(hWnd, 0);\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       CmTrafficRunDlgStart(hWnd, d);\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
+               break;\r
+\r
+       case WM_CLOSE:\r
+               d->CloseDialogAfter = true;\r
+               CmTrafficRunDlgHalt(hWnd, d);\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// トラフィック測定を実行する\r
+void CmExecTraffic(HWND hWnd, CM_TRAFFIC *t)\r
+{\r
+       CM_TRAFFIC_DLG d;\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&d, sizeof(d));\r
+       d.Setting = t;\r
+       d.ResultShowEvent = NewEvent();\r
+\r
+       MsSetThreadPriorityHigh();\r
+       Dialog(hWnd, D_CM_TRAFFIC_RUN, CmTrafficRunDlg, &d);\r
+       MsRestoreThreadPriority();\r
+\r
+       ReleaseEvent(d.ResultShowEvent);\r
+}\r
+\r
+// レジストリに設定を書き込む\r
+void CmTrafficSaveToReg(CM_TRAFFIC *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "ServerMode", t->ServerMode ? 1 : 0);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Double", t->Double ? 1 : 0);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Raw", t->Raw ? 1 : 0);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Port", t->Port);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "NumTcp", t->NumTcp);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Type", t->Type);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Span", t->Span);\r
+       MsRegWriteStr(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Host", t->Host);\r
+}\r
+\r
+// レジストリから設定を読み込む\r
+bool CmTrafficLoadFromReg(CM_TRAFFIC *t)\r
+{\r
+       char *s;\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(t, sizeof(CM_TRAFFIC));\r
+\r
+       if (MsRegIsKey(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       t->Double = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Double") == 0 ? false : true;\r
+       t->Raw = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Raw") == 0 ? false : true;\r
+       t->Port = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Port");\r
+       if (t->Port == 0)\r
+       {\r
+               t->Port = TRAFFIC_DEFAULT_PORT;\r
+       }\r
+\r
+       s = MsRegReadStr(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Host");\r
+\r
+       if (IsEmptyStr(s) == false)\r
+       {\r
+               Trim(s);\r
+               StrCpy(t->Host, sizeof(t->Host), s);\r
+       }\r
+\r
+       Free(s);\r
+\r
+       t->NumTcp = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "NumTcp");\r
+       t->NumTcp = MAKESURE(t->NumTcp, 1, TRAFFIC_NUMTCP_MAX);\r
+       t->Type = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Type");\r
+\r
+       if (t->Type != TRAFFIC_TYPE_DOWNLOAD && t->Type != TRAFFIC_TYPE_UPLOAD &&\r
+               t->Type != TRAFFIC_TYPE_FULL)\r
+       {\r
+               t->Type = TRAFFIC_TYPE_FULL;\r
+       }\r
+\r
+       t->Span = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Span");\r
+       if (t->Span == 0)\r
+       {\r
+               t->Span = TRAFFIC_SPAN_DEFAULT;\r
+       }\r
+\r
+       t->ServerMode = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "ServerMode") == 0 ? false : true;\r
+\r
+       return true;\r
+}\r
+\r
+// デフォルトの設定を取得する\r
+void CmTrafficGetDefaultSetting(CM_TRAFFIC *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(CM_TRAFFIC));\r
+\r
+       t->Double = false;\r
+       t->Raw = false;\r
+       t->Port = TRAFFIC_DEFAULT_PORT;\r
+       t->NumTcp = TRAFFIC_NUMTCP_DEFAULT;\r
+       t->Type = TRAFFIC_TYPE_FULL;\r
+       t->Span = TRAFFIC_SPAN_DEFAULT;\r
+       t->ServerMode = false;\r
+}\r
+\r
+// 通信スループット測定ツールダイアログ初期化\r
+void CmTrafficDlgInit(HWND hWnd)\r
+{\r
+       CM_TRAFFIC t;\r
+       LIST *c1, *c2;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       DlgFont(hWnd, S_8, 9, true);\r
+       DlgFont(hWnd, S_3, 9, true);\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CmTrafficLoadFromReg(&t) == false)\r
+       {\r
+               CmTrafficGetDefaultSetting(&t);\r
+       }\r
+\r
+       // 設定をダイアログに書き出す\r
+       Check(hWnd, R_SERVER, t.ServerMode);\r
+       Check(hWnd, R_CLIENT, t.ServerMode == false);\r
+\r
+       c1 = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "HostCandidate");\r
+       if (c1 != NULL)\r
+       {\r
+               UINT i;\r
+\r
+               CbReset(hWnd, C_HOST);\r
+\r
+               for (i = 0;i < LIST_NUM(c1);i++)\r
+               {\r
+                       CANDIDATE *c = LIST_DATA(c1, i);\r
+\r
+                       CbAddStr(hWnd, C_HOST, c->Str, 0);\r
+               }\r
+\r
+               FreeCandidateList(c1);\r
+       }\r
+\r
+       if (CbNum(hWnd, C_HOST) == 0)\r
+       {\r
+               CbAddStr(hWnd, C_HOST, L"speed.softether.com", 0);\r
+       }\r
+\r
+       if (IsEmptyStr(t.Host) == false)\r
+       {\r
+               SetTextA(hWnd, C_HOST, t.Host);\r
+       }\r
+\r
+       c2 = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "PortCandidate");\r
+       if (c2 != NULL)\r
+       {\r
+               UINT i;\r
+\r
+               if (t.Port != 0)\r
+               {\r
+                       wchar_t tmp[32];\r
+\r
+                       UniToStru(tmp, t.Port);\r
+\r
+                       AddCandidate(c2, tmp, 0);\r
+               }\r
+\r
+               CbReset(hWnd, C_PORT);\r
+\r
+               for (i = 0;i < LIST_NUM(c2);i++)\r
+               {\r
+                       CANDIDATE *c = LIST_DATA(c2, i);\r
+\r
+                       CbAddStr(hWnd, C_PORT, c->Str, 0);\r
+               }\r
+\r
+               FreeCandidateList(c2);\r
+       }\r
+\r
+       CbReset(hWnd, C_NUM);\r
+\r
+       for (i = 1;i <= TRAFFIC_NUMTCP_MAX;i++)\r
+       {\r
+               wchar_t tmp[32];\r
+\r
+               UniToStru(tmp, i);\r
+\r
+               CbAddStr(hWnd, C_NUM, tmp, i);\r
+       }\r
+\r
+       CbSelect(hWnd, C_NUM, t.NumTcp);\r
+\r
+       Check(hWnd, R_DOWNLOAD, t.Type == TRAFFIC_TYPE_DOWNLOAD);\r
+       Check(hWnd, R_UPLOAD, t.Type == TRAFFIC_TYPE_UPLOAD);\r
+       Check(hWnd, R_FULL, t.Type == TRAFFIC_TYPE_FULL);\r
+\r
+       Check(hWnd, R_ETHERNET, t.Raw ? false : true);\r
+       Check(hWnd, R_DOUBLE, t.Double);\r
+\r
+       SetIntEx(hWnd, E_SPAN, t.Span);\r
+\r
+       CmTrafficDlgUpdate(hWnd);\r
+}\r
+\r
+// ダイアログの内容を構造体に入れる\r
+void CmTrafficDlgToStruct(HWND hWnd, CM_TRAFFIC *t)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(CM_TRAFFIC));\r
+       t->ServerMode = IsChecked(hWnd, R_SERVER);\r
+       GetTxtA(hWnd, C_HOST, t->Host, sizeof(t->Host));\r
+       Trim(t->Host);\r
+\r
+       t->Port = GetInt(hWnd, C_PORT);\r
+       t->NumTcp = CbGetSelect(hWnd, C_NUM);\r
+       t->Span = GetInt(hWnd, E_SPAN);\r
+       t->Raw = IsChecked(hWnd, R_ETHERNET) ? false : true;\r
+       t->Double = IsChecked(hWnd, R_DOUBLE);\r
+\r
+       if (IsChecked(hWnd, R_DOWNLOAD))\r
+       {\r
+               t->Type = TRAFFIC_TYPE_DOWNLOAD;\r
+       }\r
+       else if (IsChecked(hWnd, R_UPLOAD))\r
+       {\r
+               t->Type = TRAFFIC_TYPE_UPLOAD;\r
+       }\r
+       else\r
+       {\r
+               t->Type = TRAFFIC_TYPE_FULL;\r
+       }\r
+}\r
+\r
+// 通信スループット測定ツールダイアログ更新\r
+bool CmTrafficDlgUpdate(HWND hWnd)\r
+{\r
+       CM_TRAFFIC t;\r
+       bool ok = true;\r
+       bool client_only;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       CmTrafficDlgToStruct(hWnd, &t);\r
+\r
+       client_only = t.ServerMode ? false : true;\r
+\r
+       SetEnable(hWnd, C_HOST, client_only);\r
+       SetEnable(hWnd, S_5, client_only);\r
+       SetEnable(hWnd, S_8, client_only);\r
+       SetEnable(hWnd, S_9, client_only);\r
+       SetEnable(hWnd, R_DOWNLOAD, client_only);\r
+       SetEnable(hWnd, R_UPLOAD, client_only);\r
+       SetEnable(hWnd, R_FULL, client_only);\r
+       SetEnable(hWnd, S_10, client_only);\r
+       SetEnable(hWnd, S_11, client_only);\r
+       SetEnable(hWnd, C_NUM, client_only);\r
+       SetEnable(hWnd, S_14, client_only);\r
+       SetEnable(hWnd, S_12, client_only);\r
+       SetEnable(hWnd, E_SPAN, client_only);\r
+       SetEnable(hWnd, S_13, client_only);\r
+       SetEnable(hWnd, R_ETHERNET, client_only);\r
+       SetEnable(hWnd, R_DOUBLE, client_only);\r
+\r
+       if (t.Port == 0 || t.Port >= 65536)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (t.ServerMode == false)\r
+       {\r
+               if (IsEmptyStr(t.Host))\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (t.NumTcp == 0 || t.NumTcp >= 33)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (t.Span == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (t.Type == TRAFFIC_TYPE_FULL && ((t.NumTcp % 2) != 0))\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+\r
+       return ok;\r
+}\r
+\r
+// 通信スループット測定ツールダイアログ OK ボタン\r
+void CmTrafficDlgOnOk(HWND hWnd)\r
+{\r
+       CM_TRAFFIC t;\r
+       LIST *c;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 基本データの取得\r
+       CmTrafficDlgToStruct(hWnd, &t);\r
+\r
+       // レジストリに保存\r
+       CmTrafficSaveToReg(&t);\r
+\r
+       // サーバー名候補の取得と保存\r
+       if (IsEmptyStr(t.Host) == false)\r
+       {\r
+               c = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "HostCandidate");\r
+               if (c != NULL)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       StrToUni(tmp, sizeof(tmp), t.Host);\r
+                       AddCandidate(c, tmp, 0);\r
+\r
+                       WriteCandidateToReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, c, "HostCandidate");\r
+\r
+                       FreeCandidateList(c);\r
+               }\r
+       }\r
+\r
+       if (t.Port != 0 && t.Port <= 65536)\r
+       {\r
+               // ポート番号候補の取得と保存\r
+               c = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "PortCandidate");\r
+               if (c != NULL)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       UniToStru(tmp, t.Port);\r
+                       AddCandidate(c, tmp, 0);\r
+\r
+                       WriteCandidateToReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, c, "PortCandidate");\r
+\r
+                       FreeCandidateList(c);\r
+               }\r
+       }\r
+\r
+       // 実行\r
+       CmExecTraffic(hWnd, &t);\r
+\r
+       // ダイアログを更新\r
+       CmTrafficDlgInit(hWnd);\r
+}\r
+\r
+// 通信スループット測定ツールダイアログプロシージャ\r
+UINT CmTrafficDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SetIcon(hWnd, 0, ICO_SWITCH);\r
+               CmTrafficDlgInit(hWnd);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_SERVER:\r
+               case R_CLIENT:\r
+               case C_HOST:\r
+               case C_PORT:\r
+               case R_DOWNLOAD:\r
+               case R_UPLOAD:\r
+               case R_FULL:\r
+               case C_NUM:\r
+               case E_SPAN:\r
+               case R_ETHERNET:\r
+               case R_DOUBLE:\r
+                       CmTrafficDlgUpdate(hWnd);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       CmTrafficDlgOnOk(hWnd);\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 CmTraffic(HWND hWnd)\r
+{\r
+       Dialog(hWnd, D_CM_TRAFFIC, CmTrafficDlgProc, NULL);\r
+}\r
+\r
+// 古いスタートアップファイルがあれば削除する\r
+void CmDeleteOldStartupTrayFile()\r
+{\r
+       char tmp[MAX_SIZE];\r
+       char *tag = _SS("CM_JAPANESE_ONLY_OLD_STARTUP");\r
+       if (IsEmptyStr(tag))\r
+       {\r
+               return;\r
+       }\r
+\r
+       Format(tmp, sizeof(tmp), tag, MsGetCommonStartupDir());\r
+\r
+       FileDelete(tmp);\r
+}\r
+\r
+// PKCS ライセンス確認ダイアログ\r
+UINT CmPkcsEulaDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       UINT id;\r
+       SECURE_DEVICE *dev;\r
+       char *name;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               id = (UINT)param;\r
+               dev = GetSecureDevice(id);\r
+               if (dev == NULL)\r
+               {\r
+                       EndDialog(hWnd, 0);\r
+                       return 0;\r
+               }\r
+\r
+               name = dev->ModuleName;\r
+\r
+               FormatText(hWnd, S_INFO_1, name);\r
+               FormatText(hWnd, S_INFO_2, name, name);\r
+               FormatText(hWnd, S_INFO_3, name);\r
+\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       EndDialog(hWnd, 1);\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
+// PKCS の DLL の EULA に同意しているかどうかの確認画面\r
+bool CmCheckPkcsEula(HWND hWnd, UINT id)\r
+{\r
+       return (Dialog(hWnd, D_CM_PKCSEULA, CmPkcsEulaDlg, (void *)id) == 0) ? false : true;\r
+}\r
+\r
+// コントロール更新\r
+void CmSecurePinDlgUpdate(HWND hWnd)\r
+{\r
+       char *tmp1, *tmp2, *tmp3;\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       tmp1 = GetTextA(hWnd, E_PIN1);\r
+       tmp2 = GetTextA(hWnd, E_PIN2);\r
+       tmp3 = GetTextA(hWnd, E_PIN3);\r
+       if (IsEmptyStr(tmp1))\r
+       {\r
+               ok = false;\r
+       }\r
+       if (IsEmptyStr(tmp2))\r
+       {\r
+               ok = false;\r
+       }\r
+       if (IsEmptyStr(tmp3))\r
+       {\r
+               ok = false;\r
+       }\r
+       if (StrCmp(tmp2, tmp3) != 0)\r
+       {\r
+               ok = false;\r
+       }\r
+       Free(tmp1);\r
+       Free(tmp2);\r
+       Free(tmp3);\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// PIN コード変更ダイアログ\r
+UINT CmSecurePinDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       UINT id = (UINT)param;\r
+       char *src, *dst;\r
+       SECURE *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmSecurePinDlgUpdate(hWnd);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_PIN1:\r
+               case E_PIN2:\r
+               case E_PIN3:\r
+                       CmSecurePinDlgUpdate(hWnd);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       src = GetTextA(hWnd, E_PIN1);\r
+                       dst = GetTextA(hWnd, E_PIN3);\r
+\r
+                       Disable(hWnd, IDOK);\r
+                       Disable(hWnd, IDCANCEL);\r
+\r
+                       s = OpenSec(id);\r
+                       if (s == NULL)\r
+                       {\r
+                               if (GetSecureDevice(id) != NULL)\r
+                               {\r
+                                       MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),\r
+                                               GetSecureDevice(id)->DeviceName);\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),\r
+                                               "Unknown");\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (OpenSecSession(s, 0) == false)\r
+                               {\r
+                                       if (GetSecureDevice(id) != NULL)\r
+                                       {\r
+                                               MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),\r
+                                                       GetSecureDevice(id)->DeviceName);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),\r
+                                                       "Unknown");\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (LoginSec(s, src) == false)\r
+                                       {\r
+                                               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_CURRENT_BAD"));\r
+                                               FocusEx(hWnd, E_PIN1);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (ChangePin(s, src, dst) == false)\r
+                                               {\r
+                                                       MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_CHANGE_FAILED"));\r
+                                                       FocusEx(hWnd, E_PIN1);\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       // PIN コードのキャッシュの消去\r
+                                                       cached_pin_code_expires = 0;\r
+                                                       cached_pin_code[0] = 0;\r
+                                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_PIN_OK"));\r
+                                                       EndDialog(hWnd, true);\r
+                                               }\r
+\r
+                                               LogoutSec(s);\r
+                                       }\r
+\r
+                                       CloseSecSession(s);\r
+                               }\r
+                               CloseSec(s);\r
+                       }\r
+\r
+                       Enable(hWnd, IDOK);\r
+                       Enable(hWnd, IDCANCEL);\r
+\r
+                       Free(src);\r
+                       Free(dst);\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
+// PIN コードの変更\r
+void CmSecurePin(HWND hWnd, UINT id)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0 || CheckSecureDeviceId(id) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_CM_SECURE_PIN, CmSecurePinDlg, (void *)id);\r
+}\r
+\r
+// オブジェクト種類選択ダイアログ\r
+UINT CmSecureTypeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       UINT type;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               type = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DefaultImportType");\r
+               Check(hWnd, R_DATA, type == SEC_DATA);\r
+               Check(hWnd, R_CERT, type == SEC_X);\r
+               Check(hWnd, R_KEY, type == SEC_K);\r
+               goto UPDATE_CONTROL;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       type = SEC_DATA;\r
+                       if (IsChecked(hWnd, R_CERT))\r
+                       {\r
+                               type = SEC_X;\r
+                       }\r
+                       else if (IsChecked(hWnd, R_KEY))\r
+                       {\r
+                               type = SEC_K;\r
+                       }\r
+\r
+                       MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DefaultImportType", type);\r
+\r
+                       EndDialog(hWnd, type);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               case R_CERT:\r
+               case R_KEY:\r
+               case R_DATA:\r
+UPDATE_CONTROL:\r
+                       SetEnable(hWnd, IDOK, IsChecked(hWnd, R_CERT) || \r
+                               IsChecked(hWnd, R_KEY) || \r
+                               IsChecked(hWnd, R_DATA));\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, INFINITE);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// オブジェクト種類選択\r
+UINT CmSecureType(HWND hWnd)\r
+{\r
+       return Dialog(hWnd, D_CM_SECURE_TYPE, CmSecureTypeDlg, NULL);\r
+}\r
+\r
+// ダイアログ初期化\r
+void CmSecureManagerDlgInit(HWND hWnd, UINT id)\r
+{\r
+       SECURE_DEVICE *dev;\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_SECURE);\r
+\r
+       dev = GetSecureDevice(id);\r
+       if (dev != NULL)\r
+       {\r
+               FormatText(hWnd, S_INFO, dev->DeviceName);\r
+       }\r
+\r
+       SetFont(hWnd, B_BOLD, Font(0, true));\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SEC_MGR_COLUMN1"), 200);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SEC_MGR_COLUMN2"), 110);\r
+\r
+       CmSecureManagerDlgUpdate(hWnd, id);\r
+}\r
+\r
+// コントロール更新\r
+void CmSecureManagerDlgUpdate(HWND hWnd, UINT id)\r
+{\r
+       bool b = true;\r
+       bool read_only = IsJPKI(id);\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (LvIsSingleSelected(hWnd, L_LIST) == false)\r
+       {\r
+               b = false;\r
+       }\r
+\r
+       SetEnable(hWnd, B_EXPORT, b && ((UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST)) != SEC_K));\r
+       SetEnable(hWnd, B_DELETE, b && (read_only == false));\r
+       SetEnable(hWnd, B_PIN, (read_only == false));\r
+       SetEnable(hWnd, B_IMPORT, (read_only == false));\r
+       SetEnable(hWnd, B_NEW_CERT, (read_only == false));\r
+}\r
+\r
+// 内容更新\r
+void CmSecureManagerDlgRefresh(HWND hWnd, UINT id)\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 || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       ret = SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0);\r
+\r
+       if (ret == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       o = batch[0].EnumList;\r
+       if (o != NULL)\r
+       {\r
+               CmSecureManagerDlgPrintList(hWnd, o);\r
+\r
+               FreeEnumSecObject(o);\r
+       }\r
+\r
+       // コントロール更新\r
+       CmSecureManagerDlgUpdate(hWnd, id);\r
+}\r
+\r
+// オブジェクト一覧の表示\r
+void CmSecureManagerDlgPrintList(HWND hWnd, LIST *o)\r
+{\r
+       CmSecureManagerDlgPrintListEx(hWnd, L_LIST, o, INFINITE);\r
+}\r
+void CmSecureManagerDlgPrintListEx(HWND hWnd, UINT id, LIST *o, UINT type)\r
+{\r
+       UINT i;\r
+       LVB *v;\r
+       // 引数チェック\r
+       if (hWnd == NULL || o == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       LvReset(hWnd, id);\r
+\r
+       v = LvInsertStart();\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               UINT icon = ICO_LOG2;\r
+               wchar_t tmp1[MAX_SIZE], *tmp2, *tmp3;\r
+               SEC_OBJ *obj = LIST_DATA(o, i);\r
+\r
+               if (type == INFINITE || obj->Type == type)\r
+               {\r
+                       StrToUni(tmp1, sizeof(tmp1), obj->Name);\r
+                       tmp2 = CmSecureObjTypeToStr(obj->Type);\r
+                       tmp3 = obj->Private ? _UU("SEC_YES") : _UU("SEC_NO");\r
+\r
+                       if (obj->Type == SEC_X)\r
+                       {\r
+                               icon = ICO_CERT;\r
+                       }\r
+                       else if (obj->Type == SEC_K || obj->Type == SEC_P)\r
+                       {\r
+                               icon = ICO_KEY;\r
+                       }\r
+\r
+                       LvInsertAdd(v, icon, (void *)obj->Type, 2, tmp1, tmp2);\r
+               }\r
+       }\r
+\r
+       LvInsertEnd(v, hWnd, id);\r
+}\r
+\r
+// オブジェクトの種類を文字列にする\r
+wchar_t *CmSecureObjTypeToStr(UINT type)\r
+{\r
+       wchar_t *ret = _UU("SEC_TYPE_DATA");\r
+\r
+       if (type == SEC_X)\r
+       {\r
+               ret = _UU("SEC_TYPE_CERT");\r
+       }\r
+       else if (type == SEC_K)\r
+       {\r
+               ret = _UU("SEC_TYPE_KEY");\r
+       }\r
+       else if (type == SEC_P)\r
+       {\r
+               ret = _UU("SEC_TYPE_PUB");\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// 新しい証明書を作成して書き込み\r
+void CmSecureManagerDlgNewCert(HWND hWnd, UINT id)\r
+{\r
+       X *x;\r
+       K *k;\r
+       char default_name[MAX_SIZE];\r
+       char *object_name;\r
+       bool ok = false;\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
+               {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},\r
+       };\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 証明書の作成ダイアログ\r
+       if (SmCreateCert(hWnd, &x, &k, true, NULL) == false)\r
+       {\r
+               return;\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]), id, 0) == false)\r
+               {\r
+                       // 失敗\r
+               }\r
+               else\r
+               {\r
+                       ok = true;\r
+               }\r
+\r
+               Free(object_name);\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               LIST *o = batch[2].EnumList;\r
+\r
+               CmSecureManagerDlgPrintList(hWnd, o);\r
+\r
+               FreeEnumSecObject(o);\r
+\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NEW_CERT_IMPORT_OK"));\r
+       }\r
+\r
+       FreeX(x);\r
+       FreeK(k);\r
+}\r
+\r
+// インポート\r
+void CmSecureManagerDlgImport(HWND hWnd, UINT id)\r
+{\r
+       UINT type;\r
+       char name[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       wchar_t *tmp;\r
+       wchar_t *filename;\r
+       BUF *b;\r
+       K *k;\r
+       bool ok = false;\r
+       X *x;\r
+       WINUI_SECURE_BATCH batch[] =\r
+       {\r
+               {WINUI_SECURE_WRITE_DATA, name, true, NULL, NULL, NULL, NULL, NULL, NULL},\r
+               {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},\r
+       };\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // オブジェクトの種類の選択\r
+       type = CmSecureType(hWnd);\r
+\r
+       switch (type)\r
+       {\r
+       case SEC_DATA:\r
+               // データ\r
+               tmp = OpenDlg(hWnd, _UU("DLG_ALL_FILES"), _UU("SEC_IMPORT_DATA"));\r
+               if (tmp == NULL)\r
+               {\r
+                       return;\r
+               }\r
+\r
+               filename = CopyUniStr(tmp);\r
+               Free(tmp);\r
+\r
+               // ファイル読み込み\r
+               b = ReadDumpW(filename);\r
+               if (b == NULL)\r
+               {\r
+                       // 読み込み失敗\r
+                       MsgBox(hWnd, MB_ICONSTOP, _UU("SEC_READ_FAILED"));\r
+               }\r
+               else\r
+               {\r
+                       if (b->Size > MAX_SEC_DATA_SIZE)\r
+                       {\r
+                               // ファイルサイズが大きすぎる\r
+                               MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_DATA_TOO_BIG"), MAX_SEC_DATA_SIZE);\r
+                       }\r
+                       else\r
+                       {\r
+                               // デフォルトの名前を生成する\r
+                               char default_name[MAX_SIZE];\r
+                               wchar_t default_name_w[MAX_SIZE];\r
+                               char *object_name;\r
+                               GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), filename);\r
+                               UniToStr(default_name, sizeof(default_name), default_name_w);\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_LOG2, false, false);\r
+\r
+                               if (object_name != NULL)\r
+                               {\r
+                                       // 書き込みと列挙\r
+                                       batch[0].InputData = b;\r
+                                       batch[0].Name = object_name;\r
+\r
+                                       if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)\r
+                                       {\r
+                                               // 失敗\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               ok = true;\r
+                                       }\r
+\r
+                                       Free(object_name);\r
+                               }\r
+                       }\r
+\r
+                       FreeBuf(b);\r
+               }\r
+\r
+               Free(filename);\r
+               break;\r
+\r
+       case SEC_X:\r
+               // 証明書読み込み\r
+               if (CmLoadXExW(hWnd, &x, tmp2, sizeof(tmp2)))\r
+               {\r
+                       // デフォルトの名前を生成する\r
+                       char default_name[MAX_SIZE];\r
+                       wchar_t default_name_w[MAX_PATH];\r
+                       char *object_name;\r
+                       GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), tmp2);\r
+                       UniToStr(default_name, sizeof(default_name), default_name_w);\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].Type = WINUI_SECURE_WRITE_CERT;\r
+                               batch[0].InputX = x;\r
+                               batch[0].Name = object_name;\r
+\r
+                               if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)\r
+                               {\r
+                                       // 失敗\r
+                               }\r
+                               else\r
+                               {\r
+                                       ok = true;\r
+                               }\r
+\r
+                               Free(object_name);\r
+                       }\r
+\r
+                       FreeX(x);\r
+               }\r
+\r
+               break;\r
+\r
+       case SEC_K:\r
+               // 秘密鍵\r
+               if (CmLoadKExW(hWnd, &k, tmp2, sizeof(tmp2)))\r
+               {\r
+                       // デフォルトの名前を生成する\r
+                       char default_name[MAX_SIZE];\r
+                       wchar_t default_name_w[MAX_PATH];\r
+                       char *object_name;\r
+                       GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), tmp2);\r
+                       UniToStr(default_name, sizeof(default_name), default_name_w);\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_KEY, false, false);\r
+\r
+                       if (object_name != NULL)\r
+                       {\r
+                               // 書き込みと列挙\r
+                               batch[0].Type = WINUI_SECURE_WRITE_KEY;\r
+                               batch[0].InputK = k;\r
+                               batch[0].Name = object_name;\r
+\r
+                               if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)\r
+                               {\r
+                                       // 失敗\r
+                               }\r
+                               else\r
+                               {\r
+                                       ok = true;\r
+                               }\r
+\r
+                               Free(object_name);\r
+                       }\r
+\r
+                       FreeK(k);\r
+               }\r
+               break;\r
+\r
+       default:\r
+               // 無効\r
+               return;\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               LIST *o = batch[1].EnumList;\r
+\r
+               CmSecureManagerDlgPrintList(hWnd, o);\r
+\r
+               FreeEnumSecObject(o);\r
+\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_OBJECT_IMPORT_OK"));\r
+       }\r
+}\r
+\r
+// オブジェクトのエクスポート\r
+void CmSecureManagerDlgExport(HWND hWnd, UINT id)\r
+{\r
+       char name[MAX_SIZE];\r
+       UINT method = WINUI_SECURE_READ_DATA;\r
+       char *tmp;\r
+       UINT type;\r
+       wchar_t filename[MAX_PATH];\r
+       wchar_t *uni_tmp;\r
+       X *x;\r
+       BUF *b;\r
+       wchar_t default_name[128];\r
+       WINUI_SECURE_BATCH batch[] =\r
+       {\r
+               {WINUI_SECURE_READ_DATA, name, true, NULL, NULL, NULL, NULL, NULL, NULL},\r
+       };\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       i = LvGetSelected(hWnd, L_LIST);\r
+       if (i == INFINITE)\r
+       {\r
+               return;\r
+       }\r
+\r
+       tmp = LvGetStrA(hWnd, L_LIST, i, 0);\r
+       StrCpy(name, sizeof(name), tmp);\r
+       Free(tmp);\r
+\r
+       type = (UINT)LvGetParam(hWnd, L_LIST, i);\r
+\r
+       switch (type)\r
+       {\r
+       case SEC_X:\r
+               method = WINUI_SECURE_READ_CERT;\r
+               break;\r
+\r
+       default:\r
+               method = WINUI_SECURE_READ_DATA;\r
+               break;\r
+       }\r
+\r
+       batch[0].Type = method;\r
+\r
+       // スマートカードの操作を行う\r
+       if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       switch (type)\r
+       {\r
+       case SEC_X:\r
+               // 証明書\r
+               x = batch[0].OutputX;\r
+\r
+               CertDlg(hWnd, x, NULL, true);\r
+\r
+               FreeX(x);\r
+               break;\r
+\r
+       default:\r
+               // ファイル\r
+               b = batch[0].OutputData;\r
+               StrToUni(default_name, sizeof(default_name), name);\r
+               uni_tmp = SaveDlg(hWnd, _UU("DLG_ALL_FILES"), _UU("DLG_SAVE_FILE"), default_name, NULL);\r
+\r
+               if (uni_tmp != NULL)\r
+               {\r
+                       UniStrCpy(filename, sizeof(filename), uni_tmp);\r
+\r
+                       DumpBufW(b, filename);\r
+\r
+                       Free(uni_tmp);\r
+\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_OBJECT_EXPORT_OK"));\r
+               }\r
+\r
+\r
+               FreeBuf(b);\r
+               break;\r
+       }\r
+}\r
+\r
+// オブジェクトの削除\r
+void CmSecureManagerDlgDelete(HWND hWnd, UINT id)\r
+{\r
+       char name[MAX_SIZE];\r
+       UINT method = WINUI_SECURE_DELETE_DATA;\r
+       char *tmp;\r
+       UINT type;\r
+       LIST *o;\r
+       WINUI_SECURE_BATCH batch[] =\r
+       {\r
+               {WINUI_SECURE_DELETE_OBJECT, name, false, NULL, NULL, NULL, NULL, NULL, NULL},\r
+               {WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},\r
+       };\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       i = LvGetSelected(hWnd, L_LIST);\r
+       if (i == INFINITE)\r
+       {\r
+               return;\r
+       }\r
+\r
+       tmp = LvGetStrA(hWnd, L_LIST, i, 0);\r
+       StrCpy(name, sizeof(name), tmp);\r
+       Free(tmp);\r
+\r
+       type = (UINT)LvGetParam(hWnd, L_LIST, i);\r
+\r
+       switch (type)\r
+       {\r
+       case SEC_X:\r
+               method = WINUI_SECURE_DELETE_CERT;\r
+               break;\r
+\r
+       case SEC_K:\r
+               method = WINUI_SECURE_DELETE_KEY;\r
+               break;\r
+\r
+       default:\r
+               method = WINUI_SECURE_DELETE_DATA;\r
+               break;\r
+       }\r
+\r
+       batch[0].Type = method;\r
+\r
+       if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       o = batch[1].EnumList;\r
+\r
+       CmSecureManagerDlgPrintList(hWnd, o);\r
+\r
+       FreeEnumSecObject(o);\r
+}\r
+\r
+static bool cm_secure_manager_no_new_cert = false;\r
+\r
+// スマートカードマネージャダイアログ\r
+UINT CmSecureManagerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       UINT id = (UINT)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmSecureManagerDlgInit(hWnd, id);\r
+\r
+               if (cm_secure_manager_no_new_cert)\r
+               {\r
+                       Hide(hWnd, B_NEW_CERT);\r
+               }\r
+\r
+               SetTimer(hWnd, 1, 1, NULL);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_REFRESH:\r
+                       CmSecureManagerDlgRefresh(hWnd, id);\r
+                       break;\r
+\r
+               case B_IMPORT:\r
+                       CmSecureManagerDlgImport(hWnd, id);\r
+                       break;\r
+\r
+               case B_EXPORT:\r
+                       CmSecureManagerDlgExport(hWnd, id);\r
+                       break;\r
+\r
+               case B_DELETE:\r
+                       if (MsgBox(hWnd, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2,\r
+                               _UU("SEC_DELETE_MSG")) == IDYES)\r
+                       {\r
+                               CmSecureManagerDlgDelete(hWnd, id);\r
+                       }\r
+                       break;\r
+\r
+               case B_NEW_CERT:\r
+                       CmSecureManagerDlgNewCert(hWnd, id);\r
+                       break;\r
+\r
+               case B_PIN:\r
+                       CmSecurePin(hWnd, id);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       CmSecureManagerDlgRefresh(hWnd, id);\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_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               CmSecureManagerDlgUpdate(hWnd, id);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// スマートカードマネージャ\r
+void CmSecureManager(HWND hWnd, UINT id)\r
+{\r
+       CmSecureManagerEx(hWnd, id, false);\r
+}\r
+void CmSecureManagerEx(HWND hWnd, UINT id, bool no_new_cert)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // ID チェック\r
+       if (CheckSecureDeviceId(id) == false)\r
+       {\r
+               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_INVALID_ID"));\r
+               return;\r
+       }\r
+\r
+       if (no_new_cert)\r
+       {\r
+               cm_secure_manager_no_new_cert = true;\r
+       }\r
+       else\r
+       {\r
+               cm_secure_manager_no_new_cert = false;\r
+       }\r
+\r
+       Dialog(hWnd, D_CM_SECURE_MANAGER, CmSecureManagerDlg, (void *)id);\r
+}\r
+\r
+// クライアント用スマートカードマネージャ\r
+void CmClientSecureManager(HWND hWnd)\r
+{\r
+       RPC_USE_SECURE t;\r
+       UINT id;\r
+\r
+       Zero(&t, sizeof(t));\r
+       CcGetUseSecure(cm->Client, &t);\r
+\r
+       id = t.DeviceId;\r
+\r
+       if (id == 0 || CheckSecureDeviceId(id) == false)\r
+       {\r
+               id = CmClientSelectSecure(hWnd);\r
+       }\r
+\r
+       if (id == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CmSecureManager(hWnd, id);\r
+}\r
+\r
+// ダイアログの初期化\r
+void CmSelectSecureDlgInit(HWND hWnd, UINT default_id)\r
+{\r
+       UINT i;\r
+       LIST *o;\r
+       LVB *v;\r
+\r
+       SetIcon(hWnd, 0, ICO_SECURE);\r
+\r
+       o = GetSecureDeviceList();\r
+\r
+       LvInit(hWnd, L_LIST);\r
+       LvInsertColumn(hWnd, L_LIST, 0, _UU("SEC_COLUMN1"), 150);\r
+       LvInsertColumn(hWnd, L_LIST, 1, _UU("SEC_COLUMN2"), 100);\r
+       LvInsertColumn(hWnd, L_LIST, 2, _UU("SEC_COLUMN3"), 130);\r
+       LvInsertColumn(hWnd, L_LIST, 3, _UU("SEC_COLUMN4"), 100);\r
+\r
+       v = LvInsertStart();\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t *tmp2;\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp4[MAX_SIZE];\r
+               SECURE_DEVICE *dev = LIST_DATA(o, i);\r
+\r
+               StrToUni(tmp1, sizeof(tmp1), dev->DeviceName);\r
+               tmp2 = (dev->Type == SECURE_IC_CARD) ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN");\r
+               StrToUni(tmp3, sizeof(tmp3), dev->Manufacturer);\r
+               StrToUni(tmp4, sizeof(tmp4), dev->ModuleName);\r
+\r
+               LvInsertAdd(v, ICO_SECURE, (void *)dev->Id, 4, tmp1, tmp2, tmp3, tmp4);\r
+       }\r
+\r
+       LvInsertEnd(v, hWnd, L_LIST);\r
+\r
+       if (default_id != 0)\r
+       {\r
+               LvSelect(hWnd, L_LIST, LvSearchParam(hWnd, L_LIST, (void *)default_id));\r
+       }\r
+\r
+       ReleaseList(o);\r
+\r
+       // コントロール更新\r
+       CmSelectSecureDlgUpdate(hWnd);\r
+}\r
+\r
+// ダイアログのコントロール更新\r
+void CmSelectSecureDlgUpdate(HWND hWnd)\r
+{\r
+       SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));\r
+}\r
+\r
+// スマートカード選択ダイアログ\r
+UINT CmSelectSecureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       UINT default_id = (UINT)param;\r
+       NMHDR *n = NULL;\r
+       static UINT old_id;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               old_id = default_id;\r
+               CmSelectSecureDlgInit(hWnd, default_id);\r
+\r
+               if (LvNum(hWnd, L_LIST) == 0)\r
+               {\r
+                       // 1 つもスマートカードが無い\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
+                       Disable(hWnd, L_LIST);\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NO_SECURE_DEVICE"));\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
+                               if (i != INFINITE)\r
+                               {\r
+                                       UINT id = (UINT)LvGetParam(hWnd, L_LIST, i);\r
+\r
+                                       if (old_id != id)\r
+                                       {\r
+                                               if (CmCheckPkcsEula(hWnd, id) == false)\r
+                                               {\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       EndDialog(hWnd, id);\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->idFrom)\r
+               {\r
+               case L_LIST:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               CmSelectSecureDlgUpdate(hWnd);\r
+                               break;\r
+                       case NM_DBLCLK:\r
+                               Command(hWnd, IDOK);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 使用するスマートカードデバイスの選択\r
+UINT CmSelectSecure(HWND hWnd, UINT current_id)\r
+{\r
+       return Dialog(hWnd, D_CM_SELECT_SECURE, CmSelectSecureDlg, (void *)current_id);\r
+}\r
+\r
+// 使用するスマートカードデバイスの選択 (クライアント)\r
+UINT CmClientSelectSecure(HWND hWnd)\r
+{\r
+       UINT id;\r
+       RPC_USE_SECURE t;\r
+\r
+       if (cm->server_name != NULL)\r
+       {\r
+               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_SECURE_MUST_LOCAL"));\r
+               return 0;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       CcGetUseSecure(cm->Client, &t);\r
+\r
+       id = t.DeviceId;\r
+\r
+       id = CmSelectSecure(hWnd, id);\r
+       if (id != 0)\r
+       {\r
+               Zero(&t, sizeof(t));\r
+               t.DeviceId = id;\r
+\r
+               CALL(hWnd, CcUseSecure(cm->Client, &t));\r
+\r
+               SmWriteSelectSecureIdReg(id);\r
+       }\r
+\r
+       return id;\r
+}\r
+\r
+// ショートカット接続\r
+void CmConnectShortcut(UCHAR *key)\r
+{\r
+       UINT ret;\r
+       // 引数チェック\r
+       if (key == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 接続を試行する\r
+       ret = CcShortcut(key);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               if (ret == ERR_ACCOUNT_ACTIVE)\r
+               {\r
+                       // 現在接続中なので、切断するかどうか問い合わせる\r
+                       if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_SHORTCUT_DISCONNECT")) == IDYES)\r
+                       {\r
+                               // 切断してみる\r
+                               ret = CcShortcutDisconnect(key);\r
+\r
+                               if (ret != ERR_NO_ERROR)\r
+                               {\r
+                                       // エラー\r
+                                       MsgBox(NULL, MB_ICONEXCLAMATION, GetUniErrorStr(ret));\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // その他のエラー\r
+                       MsgBox(NULL, MB_ICONEXCLAMATION, GetUniErrorStr(ret));\r
+               }\r
+       }\r
+}\r
+\r
+// 音声ガイドを再生する\r
+void CmVoice(char *name)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->DisableVoice)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < sizeof(cm_voice) / sizeof(CM_VOICE);i++)\r
+       {\r
+               if (cm_voice[i].voice_id == cm->VoiceId)\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+                       Format(tmp, sizeof(tmp), "%s_%s.wav", cm_voice[i].perfix, name);\r
+                       MsPlaySound(tmp);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+// パスワード変更画面更新\r
+void CmChangePasswordUpdate(HWND hWnd, CM_CHANGE_PASSWORD *p)\r
+{\r
+       bool ok = true;\r
+       char *s1, *s2;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsEmpty(hWnd, E_USERNAME))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       s1 = GetTextA(hWnd, E_NEW_PASSWORD1);\r
+       s2 = GetTextA(hWnd, E_NEW_PASSWORD2);\r
+\r
+       if (StrCmp(s1, s2) != 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       Free(s1);\r
+       Free(s2);\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// パスワード変更ダイアログプロシージャ\r
+UINT CmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_CHANGE_PASSWORD *p = (CM_CHANGE_PASSWORD *)param;\r
+       char username[MAX_USERNAME_LEN + 1];\r
+       char old_pass[MAX_PASSWORD_LEN + 1];\r
+       char new_pass[MAX_PASSWORD_LEN + 1];\r
+       UINT ret;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SetTextA(hWnd, E_HUBNAME, p->HubName);\r
+               SetTextA(hWnd, E_USERNAME, p->Username);\r
+               FormatText(hWnd, S_TITLE, p->ClientOption->Hostname);\r
+\r
+               if (IsEmpty(hWnd, E_USERNAME))\r
+               {\r
+                       FocusEx(hWnd, E_USERNAME);\r
+               }\r
+               else\r
+               {\r
+                       FocusEx(hWnd, E_OLD_PASSWORD);\r
+               }\r
+\r
+               CmChangePasswordUpdate(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_USERNAME:\r
+               case E_OLD_PASSWORD:\r
+               case E_NEW_PASSWORD1:\r
+               case E_NEW_PASSWORD2:\r
+                       CmChangePasswordUpdate(hWnd, p);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       GetTxtA(hWnd, E_USERNAME, username, sizeof(username));\r
+                       GetTxtA(hWnd, E_OLD_PASSWORD, old_pass, sizeof(old_pass));\r
+                       GetTxtA(hWnd, E_NEW_PASSWORD1, new_pass, sizeof(new_pass));\r
+\r
+                       Disable(hWnd, E_USERNAME);\r
+                       Disable(hWnd, E_OLD_PASSWORD);\r
+                       Disable(hWnd, E_NEW_PASSWORD1);\r
+                       Disable(hWnd, E_NEW_PASSWORD2);\r
+                       Disable(hWnd, IDOK);\r
+                       Disable(hWnd, IDCANCEL);\r
+\r
+                       ret = ChangePassword(cm->Cedar, p->ClientOption, p->HubName, username, old_pass, new_pass);\r
+\r
+                       if (ret == ERR_NO_ERROR)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_CHANGED"));\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+                       else\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONSTOP, _E(ret));\r
+                               Enable(hWnd, E_USERNAME);\r
+                               Enable(hWnd, E_OLD_PASSWORD);\r
+                               Enable(hWnd, E_NEW_PASSWORD1);\r
+                               Enable(hWnd, E_NEW_PASSWORD2);\r
+                               Enable(hWnd, IDOK);\r
+                               Enable(hWnd, IDCANCEL);\r
+\r
+                               SetTextA(hWnd, E_OLD_PASSWORD, "");\r
+                               SetTextA(hWnd, E_NEW_PASSWORD1, "");\r
+                               SetTextA(hWnd, E_NEW_PASSWORD2, "");\r
+\r
+                               Focus(hWnd, E_OLD_PASSWORD);\r
+                       }\r
+\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               }\r
+\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// パスワード変更ダイアログ表示\r
+void CmChangePassword(HWND hWnd, CLIENT_OPTION *o, char *hubname, char *username)\r
+{\r
+       CM_CHANGE_PASSWORD p;\r
+       // 引数チェック\r
+       if (hWnd == NULL || o == NULL || hubname == NULL || username == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       StrCpy(p.Username, sizeof(p.Username), username);\r
+       StrCpy(p.HubName, sizeof(p.HubName), hubname);\r
+       p.ClientOption = o;\r
+\r
+       CmVoice("password");\r
+\r
+       Dialog(hWnd, D_CM_CHANGE_PASSWORD, CmChangePasswordProc, &p);\r
+}\r
+\r
+// デスクトップ相違警告メッセージダイアログ初期化\r
+void CmDesktopDlgInit(HWND hWnd, wchar_t *account_name)\r
+{\r
+       wchar_t tmp[2048];\r
+       bool remote = false;\r
+       bool user_switching = false;\r
+       bool console_active = false;\r
+       wchar_t *console_user = NULL;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FormatText(hWnd, 0, account_name);\r
+       FormatText(hWnd, S_TITLE, account_name);\r
+       DlgFont(hWnd, S_TITLE, 11, true);\r
+       DlgFont(hWnd, S_INFO, 11, true);\r
+       if (cm->server_name == NULL)\r
+       {\r
+               UniStrCpy(tmp, sizeof(tmp), _UU("CM_DESKTOP_LOCAL_PC"));\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_REMOTE_PC"), cm->server_name);\r
+       }\r
+       FormatText(hWnd, S_WARNING, tmp);\r
+\r
+       if (cm->server_name != NULL)\r
+       {\r
+               remote = true;\r
+       }\r
+       else\r
+       {\r
+               if (MsIsTerminalServiceInstalled())\r
+               {\r
+                       user_switching = false;\r
+               }\r
+               else\r
+               {\r
+                       user_switching = true;\r
+               }\r
+\r
+               console_user = MsGetSessionUserName(0);\r
+\r
+               if (console_user == NULL)\r
+               {\r
+                       console_active = false;\r
+               }\r
+               else\r
+               {\r
+                       console_active = true;\r
+               }\r
+       }\r
+\r
+       // MSG1\r
+       if (remote == false)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_1"),\r
+                       user_switching ? _UU("CM_DESKTOP_MSG_LOCAL_SW") : _UU("CM_DESKTOP_MSG_LOCAL_TS"));\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_1"),\r
+                       cm->server_name);\r
+       }\r
+       SetText(hWnd, S_MSG_1, tmp);\r
+\r
+       // MSG2\r
+       if (remote == false)\r
+       {\r
+               if (console_active)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_21"),\r
+                               console_user, MsGetCurrentTerminalSessionId());\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_22"),\r
+                               MsGetCurrentTerminalSessionId());\r
+               }\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_2"), cm->server_name);\r
+       }\r
+       SetText(hWnd, S_MSG_2, tmp);\r
+\r
+       // MSG3\r
+       if (remote == false)\r
+       {\r
+               if (console_active)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_31"),\r
+                               console_user, account_name);\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_32"),\r
+                               account_name);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_3"), cm->server_name,\r
+                       account_name);\r
+       }\r
+       SetText(hWnd, S_MSG_3, tmp);\r
+\r
+       if (console_user != NULL)\r
+       {\r
+               Free(console_user);\r
+       }\r
+}\r
+\r
+// デスクトップ相違警告メッセージダイアログ\r
+UINT CmDesktopDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       wchar_t *account_name = (wchar_t *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmDesktopDlgInit(hWnd, account_name);\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 必要であればデスクトップが異なる旨の警告メッセージを表示する\r
+bool CmWarningDesktop(HWND hWnd, wchar_t *account_name)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (cm->Client->Unix)\r
+       {\r
+               //クライアントが UNIX の場合警告の必要は無い\r
+               return true;\r
+       }\r
+\r
+       if (/*MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled() ||*/ (cm->server_name != NULL))\r
+       {\r
+               if (cm->server_name == NULL)\r
+               {\r
+                       //if (MsGetCurrentTerminalSessionId() == 0)\r
+                       {\r
+                               // 警告の必要は無い\r
+                               return true;\r
+                       }\r
+               }\r
+               // 警告の必要がある\r
+               return Dialog(hWnd, D_CM_DESKTOP, CmDesktopDlgProc, account_name);\r
+       }\r
+       else\r
+       {\r
+               // 警告の必要は無い\r
+               return true;\r
+       }\r
+}\r
+\r
+// パスワード設定ダイアログ更新\r
+void CmPasswordRefresh(HWND hWnd)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, E_PASSWORD, IsChecked(hWnd, R_USE_PASSWORD));\r
+       SetEnable(hWnd, E_PASSWORD2, IsChecked(hWnd, R_USE_PASSWORD));\r
+       SetEnable(hWnd, IDC_STATIC1, IsChecked(hWnd, R_USE_PASSWORD));\r
+       SetEnable(hWnd, IDC_STATIC2, IsChecked(hWnd, R_USE_PASSWORD));\r
+       SetEnable(hWnd, R_REMOTE_ONLY, IsChecked(hWnd, R_USE_PASSWORD));\r
+\r
+       if (IsChecked(hWnd, R_USE_PASSWORD))\r
+       {\r
+               char tmp1[MAX_SIZE];\r
+               char tmp2[MAX_SIZE];\r
+               if (IsEmpty(hWnd, E_PASSWORD))\r
+               {\r
+                       ok = false;\r
+               }\r
+               GetTxtA(hWnd, E_PASSWORD, tmp1, sizeof(tmp1));\r
+               GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+               if (StrCmp(tmp1, tmp2) != 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+               if (StrCmp(tmp1, HIDDEN_PASSWORD) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// パスワード設定プロシージャ\r
+UINT CmPasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       RPC_CLIENT_PASSWORD_SETTING c;\r
+       RPC_CLIENT_PASSWORD p;\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
+               if (CALL(hWnd, CcGetPasswordSetting(cm->Client, &c)))\r
+               {\r
+                       Check(hWnd, R_USE_PASSWORD, c.IsPasswordPresented);\r
+                       if (c.IsPasswordPresented)\r
+                       {\r
+                               SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);\r
+                               SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);\r
+                               FocusEx(hWnd, E_PASSWORD);\r
+                               Check(hWnd, R_REMOTE_ONLY, c.PasswordRemoteOnly);\r
+                       }\r
+                       else\r
+                       {\r
+                               Focus(hWnd, R_USE_PASSWORD);\r
+                       }\r
+               }\r
+               CmPasswordRefresh(hWnd);\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case R_USE_PASSWORD:\r
+                       if (IsChecked(hWnd, R_USE_PASSWORD))\r
+                       {\r
+                               FocusEx(hWnd, E_PASSWORD);\r
+                       }\r
+                       break;\r
+               case IDOK:\r
+                       GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));\r
+                       Zero(&p, sizeof(p));\r
+                       if (IsChecked(hWnd, R_USE_PASSWORD))\r
+                       {\r
+                               StrCpy(p.Password, sizeof(p.Password), tmp);\r
+                               p.PasswordRemoteOnly = IsChecked(hWnd, R_REMOTE_ONLY);\r
+                       }\r
+\r
+                       if (CALL(hWnd, CcSetPassword(cm->Client, &p)))\r
+                       {\r
+                               if (StrLen(p.Password) > 0)\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_SET"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_REMOVE"));\r
+                               }\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_USE_PASSWORD:\r
+               case R_REMOTE_ONLY:\r
+               case E_PASSWORD:\r
+               case E_PASSWORD2:\r
+                       CmPasswordRefresh(hWnd);\r
+                       break;\r
+               }\r
+               switch (wParam)\r
+               {\r
+               case R_REMOTE_ONLY:\r
+               case R_USE_PASSWORD:\r
+                       if (IsChecked(hWnd, R_USE_PASSWORD))\r
+                       {\r
+                               FocusEx(hWnd, E_PASSWORD);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// パスワード設定\r
+void CmPassword(HWND hWnd)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_CM_PASSWORD, CmPasswordProc, NULL);\r
+}\r
+\r
+// CA ダイアログ更新\r
+void CmTrustDlgUpdate(HWND hWnd)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetEnable(hWnd, B_EXPORT, LvIsSelected(hWnd, L_CERT));\r
+       SetEnable(hWnd, B_DELETE, LvIsSelected(hWnd, L_CERT) && cm->CmSetting.LockMode == false);\r
+       SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_CERT));\r
+       SetEnable(hWnd, B_IMPORT, cm->CmSetting.LockMode == false);\r
+}\r
+\r
+// 証明書リストの更新\r
+void CmTrustDlgRefresh(HWND hWnd)\r
+{\r
+       RPC_CLIENT_ENUM_CA c;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (CALL(hWnd, CcEnumCa(cm->Client, &c)))\r
+       {\r
+               UINT i;\r
+               LVB *b = LvInsertStart();\r
+               for (i = 0;i < c.NumItem;i++)\r
+               {\r
+                       RPC_CLIENT_ENUM_CA_ITEM *cert = c.Items[i];\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(cert->Expires), NULL);\r
+                       LvInsertAdd(b, ICO_CERT, (void *)cert->Key, 3,\r
+                               cert->SubjectName, cert->IssuerName, tmp);\r
+               }\r
+               LvInsertEnd(b, hWnd, L_CERT);\r
+               CiFreeClientEnumCa(&c);\r
+       }\r
+\r
+       CmTrustDlgUpdate(hWnd);\r
+}\r
+\r
+// インポート\r
+void CmTrustImport(HWND hWnd)\r
+{\r
+       X *x;\r
+       RPC_CERT c;\r
+       if (CmLoadXFromFileOrSecureCard(hWnd, &x) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&c, sizeof(c));\r
+       c.x = x;\r
+\r
+       CALL(hWnd, CcAddCa(cm->Client, &c));\r
+       CmVoice("new_cert");\r
+\r
+       FreeX(c.x);\r
+       CmTrustDlgRefresh(hWnd);\r
+}\r
+\r
+// エクスポート\r
+void CmTrustExport(HWND hWnd)\r
+{\r
+       UINT key;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       key = (UINT)LvGetParam(hWnd, L_CERT, LvGetSelected(hWnd, L_CERT));\r
+       if (key != INFINITE)\r
+       {\r
+               RPC_GET_CA a;\r
+               Zero(&a, sizeof(a));\r
+               a.Key = key;\r
+\r
+               if (CALL(hWnd, CcGetCa(cm->Client, &a)))\r
+               {\r
+                       wchar_t *name;\r
+                       X *x = CloneX(a.x);\r
+                       CiFreeGetCa(&a);\r
+\r
+                       // 保存\r
+                       name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");\r
+                       if (name != NULL)\r
+                       {\r
+                               wchar_t str[MAX_SIZE];\r
+                               UniStrCpy(str, sizeof(str), name);\r
+                               if (XToFileW(x, str, true))\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));\r
+                               }\r
+                               Free(name);\r
+                       }\r
+                       FreeX(x);\r
+               }\r
+       }\r
+}\r
+\r
+// 表示\r
+void CmTrustView(HWND hWnd)\r
+{\r
+       UINT key;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       key = (UINT)LvGetParam(hWnd, L_CERT, LvGetSelected(hWnd, L_CERT));\r
+       if (key != INFINITE)\r
+       {\r
+               RPC_GET_CA a;\r
+               Zero(&a, sizeof(a));\r
+               a.Key = key;\r
+\r
+               if (CALL(hWnd, CcGetCa(cm->Client, &a)))\r
+               {\r
+                       X *x = CloneX(a.x);\r
+                       X *x_issuer;\r
+                       CiFreeGetCa(&a);\r
+\r
+                       x_issuer = CmGetIssuer(x);\r
+                       CertDlg(hWnd, x, x_issuer, true);\r
+                       FreeX(x);\r
+                       FreeX(x_issuer);\r
+               }\r
+       }\r
+}\r
+\r
+// CA ダイアログプロシージャ\r
+UINT CmTrustDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       UINT index;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\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
+               CmTrustDlgRefresh(hWnd);\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_IMPORT:\r
+                       CmTrustImport(hWnd);\r
+                       break;\r
+               case B_EXPORT:\r
+                       CmTrustExport(hWnd);\r
+                       break;\r
+               case B_DELETE:\r
+                       index = LvGetSelected(hWnd, L_CERT);\r
+                       if (index != INFINITE)\r
+                       {\r
+                               UINT key = (UINT)LvGetParam(hWnd, L_CERT, index);\r
+                               if (key != INFINITE)\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_CERT_DELETE_MSG")) == IDYES)\r
+                                       {\r
+                                               RPC_CLIENT_DELETE_CA c;\r
+                                               Zero(&c, sizeof(c));\r
+                                               c.Key = key;\r
+                                               if (CALL(hWnd, CcDeleteCa(cm->Client, &c)))\r
+                                               {\r
+                                                       CmTrustDlgRefresh(hWnd);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+               case IDOK:\r
+                       if (IsEnable(hWnd, IDOK))\r
+                       {\r
+                               CmTrustView(hWnd);\r
+                       }\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\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
+                               CmTrustDlgUpdate(hWnd);\r
+                               break;\r
+                       case NM_DBLCLK:\r
+                               Command(hWnd, IDOK);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       LvSortHander(hWnd, msg, wParam, lParam, L_CERT);\r
+\r
+       return 0;\r
+}\r
+\r
+// CA ダイアログの表示\r
+void CmTrustDlg(HWND hWnd)\r
+{\r
+       Dialog(hWnd, D_CM_TRUST, CmTrustDlgProc, NULL);\r
+}\r
+\r
+// メインウインドウプロシージャ\r
+UINT CmMainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NMHDR *n;\r
+       static UINT taskbar_msg = 0;\r
+       COPYDATASTRUCT *cpy;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       if (taskbar_msg != 0 && msg == taskbar_msg)\r
+       {\r
+               // タスクバーが再生成された\r
+               if (cm->TrayInited)\r
+               {\r
+                       MsRestoreIconOnTray();\r
+               }\r
+       }\r
+\r
+       // CmSetForegroundProcessToCnService();\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_CM_SETTING_CHANGED_MESSAGE:\r
+               // CM_SETTING が変更された\r
+               CmApplyCmSetting();\r
+               break;\r
+       case WM_INITDIALOG:\r
+               CmMainWindowOnInit(hWnd);\r
+               taskbar_msg = RegisterWindowMessage("TaskbarCreated");\r
+               CmEndStartupMutex();\r
+               break;\r
+       case WM_SHOWWINDOW:\r
+LABEL_SPLASH:\r
+               if (cm->SplashHasBeenShown == false)\r
+               {\r
+                       if ((msg == WM_SHOWWINDOW && wParam) || (msg != WM_SHOWWINDOW && IsShow(hWnd, 0)))\r
+                       {\r
+                               if (IsIconic(hWnd) == false)\r
+                               {\r
+                                       SetTimer(hWnd, 5, 100, NULL);\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       case WM_CM_SHOW:\r
+               // 別のプロセスから表示要求を受けた\r
+               if (cm->CmSetting.EasyMode == false)\r
+               {\r
+                       ShowWindow(hWnd, SW_SHOWNORMAL);\r
+               }\r
+               else\r
+               {\r
+                       if (cm->hEasyWnd == NULL)\r
+                       {\r
+                               CmShowEasy();\r
+                       }\r
+                       else\r
+                       {\r
+                               SetForegroundWindow(cm->hEasyWnd);\r
+                               SetActiveWindow(cm->hEasyWnd);\r
+                       }\r
+               }\r
+               break;\r
+       case WM_COMMAND:\r
+               CmMainWindowOnCommand(hWnd, wParam, lParam);\r
+               break;\r
+       case WM_SIZE:\r
+               CmMainWindowOnSize(hWnd);\r
+               goto LABEL_SPLASH;\r
+       case WM_CLOSE:\r
+               if (cm->CmSetting.EasyMode == false)\r
+               {\r
+                       CmShowOrHideWindow(hWnd);\r
+               }\r
+               else\r
+               {\r
+                       if (cm->hEasyWnd == NULL)\r
+                       {\r
+                               CmShowEasy();\r
+                       }\r
+                       else\r
+                       {\r
+                               SetForegroundWindow(cm->hEasyWnd);\r
+                               SetActiveWindow(cm->hEasyWnd);\r
+                       }\r
+               }\r
+               return 1;\r
+       case WM_INITMENUPOPUP:\r
+               if (HIWORD(lParam) == false)\r
+               {\r
+                       CmMainWindowOnPopupMenu(hWnd, (HMENU)wParam, LOWORD(lParam));\r
+               }\r
+               break;\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               if (n->idFrom == L_ACCOUNT && (n->code == LVN_BEGINLABELEDITW || n->code == LVN_BEGINLABELEDITA))\r
+               {\r
+                       wchar_t *tmp = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);\r
+                       if (tmp != NULL)\r
+                       {\r
+                               if (UniStrCmpi(tmp, _UU("CM_NEW_ICON")) == 0 ||\r
+                                       UniStrCmpi(tmp, _UU("CM_ASP")) == 0)\r
+                               {\r
+                                       SendMsg(hWnd, L_ACCOUNT, LVM_CANCELEDITLABEL, 0, 0);\r
+                                       Free(tmp);\r
+                                       return true;\r
+                               }\r
+                               Free(tmp);\r
+                       }\r
+               }\r
+               CmMainWindowOnNotify(hWnd, (NMHDR *)lParam);\r
+               break;\r
+       case WM_CM_NOTIFY:\r
+               CmRefreshVLanList(hWnd);\r
+               CmRefreshAccountList(hWnd);\r
+               CmRefreshStatusBar(hWnd);\r
+               break;\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       CmSetForegroundProcessToCnService();\r
+                       break;\r
+               case 2:\r
+                       CmPollingTray(hWnd);\r
+                       break;\r
+               case 3:\r
+                       KillTimer(hWnd, 3);\r
+                       Hide(hWnd, 0);\r
+                       break;\r
+               case 4:\r
+                       KillTimer(hWnd, 4);\r
+                       CmMainWindowOnShowEasy(hWnd);\r
+                       break;\r
+               case 5:\r
+                       KillTimer(hWnd, 5);\r
+                       if (cm->SplashHasBeenShown == false)\r
+                       {\r
+                               cm->SplashHasBeenShown = true;\r
+\r
+                               ShowSplashEx(hWnd, "UT-VPN Client", 1300, CM_SPLASH_BORDER_COLOR);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CM_TRAY_MESSAGE:\r
+               // タスクトレイのアイコンからのメッセージ\r
+               CmMainWindowOnTrayClicked(hWnd, wParam, lParam);\r
+               break;\r
+       case WM_COPYDATA:\r
+               cpy = (COPYDATASTRUCT *)lParam;\r
+               if (cpy != NULL)\r
+               {\r
+                       if (cpy->dwData == CM_IMPORT_FILENAME_MSG || cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE)\r
+                       {\r
+                               char *filename = (char *)cpy->lpData;\r
+\r
+                               if (cm->CmSetting.LockMode == false || cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE)\r
+                               {\r
+                                       wchar_t fullpath[MAX_PATH];\r
+\r
+                                       if (StrLen(filename) >= 2 && IsFileExists(filename))\r
+                                       {\r
+                                               StrToUni(fullpath, sizeof(fullpath), filename);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               UniStrCpy(fullpath, sizeof(fullpath), (wchar_t *)filename);\r
+                                       }\r
+\r
+                                       CmImportAccountMainEx(cm->hEasyWnd ? cm->hEasyWnd : hWnd, fullpath, cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE);\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBox(cm->hEasyWnd ? cm->hEasyWnd : hWnd, MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_TOPMOST, _UU("CM_VPN_FILE_IMPORT_NG"));\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       case WM_QUERYENDSESSION:\r
+               // Windows が終了しようとしている\r
+               cm->WindowsShutdowning = true;\r
+               CmSaveMainWindowPos(hWnd);\r
+               SleepThread(256);\r
+               break;\r
+       case WM_ENDSESSION:\r
+               // Windows が終了した\r
+               _exit(0);\r
+               break;\r
+       }\r
+\r
+       LvSortHander(hWnd, msg, wParam, lParam, L_ACCOUNT);\r
+       LvSortHander(hWnd, msg, wParam, lParam, L_VLAN);\r
+\r
+       return 0;\r
+}\r
+\r
+// 通知サービスをフォアグラウンドプロセスに指定する\r
+void CmSetForegroundProcessToCnService()\r
+{\r
+       if (cm->MenuPopuping)\r
+       {\r
+               return;\r
+       }\r
+       if (cm->server_name == NULL)\r
+       {\r
+               if (CnCheckAlreadyExists(false))\r
+               {\r
+                       AllowFGWindow(MsRegReadInt(REG_CURRENT_USER,\r
+                               CM_REG_KEY, "NotifyServerProcessId"));\r
+               }\r
+       }\r
+}\r
+\r
+// [最近の接続先] のサブメニューを表示する\r
+HMENU CmCreateRecentSubMenu(HWND hWnd, UINT start_id)\r
+{\r
+       HMENU h = NULL;\r
+       UINT i;\r
+       RPC_CLIENT_ENUM_ACCOUNT a;\r
+       LIST *o;\r
+       bool easy;\r
+\r
+       easy = cm->CmSetting.EasyMode;\r
+\r
+       Zero(&a, sizeof(a));\r
+\r
+       if (CcEnumAccount(cm->Client, &a) == ERR_NO_ERROR)\r
+       {\r
+               o = NewListFast(CiCompareClientAccountEnumItemByLastConnectDateTime);\r
+\r
+               for (i = 0;i < a.NumItem;i++)\r
+               {\r
+                       RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = a.Items[i];\r
+\r
+                       item->tmp1 = i;\r
+\r
+                       if (item->LastConnectDateTime != 0)\r
+                       {\r
+                               Add(o, item);\r
+                       }\r
+               }\r
+\r
+               Sort(o);\r
+\r
+               for (i = 0;i < MIN(LIST_NUM(o), CM_NUM_RECENT);i++)\r
+               {\r
+                       RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = (RPC_CLIENT_ENUM_ACCOUNT_ITEM *)LIST_DATA(o, i);\r
+                       wchar_t tmp[MAX_PATH];\r
+                       wchar_t *account_name;\r
+                       char *server_name;\r
+                       char *hub_name;\r
+                       UINT pos;\r
+\r
+                       if (h == NULL)\r
+                       {\r
+                               h = CreatePopupMenu();\r
+                       }\r
+\r
+                       account_name = item->AccountName;\r
+                       server_name = item->ServerName;\r
+                       hub_name = item->HubName;\r
+\r
+                       UniStrCpy(tmp, sizeof(tmp), account_name);\r
+\r
+                       pos = LvSearchStr(hWnd, L_ACCOUNT, 0, account_name);\r
+                       if (pos != INFINITE)\r
+                       {\r
+                               MsAppendMenu(h, MF_STRING, start_id + pos, tmp);\r
+                       }\r
+               }\r
+\r
+               ReleaseList(o);\r
+\r
+               CiFreeClientEnumAccount(&a);\r
+       }\r
+\r
+       return h;\r
+}\r
+\r
+// タスクトレイの右クリックメニューのサブメニューを表示する\r
+HMENU CmCreateTraySubMenu(HWND hWnd, bool flag, UINT start_id)\r
+{\r
+       HMENU h = NULL;\r
+       UINT i, num;\r
+       bool easy;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       easy = cm->CmSetting.EasyMode;\r
+\r
+       num = LvNum(hWnd, L_ACCOUNT);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               wchar_t *status_str = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+\r
+               if (status_str != NULL)\r
+               {\r
+                       bool b = false;\r
+                       bool is_account = false;\r
+\r
+                       if (UniStrCmpi(status_str, _UU("CM_ACCOUNT_OFFLINE")) == 0)\r
+                       {\r
+                               if (flag == false)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+\r
+                               is_account = true;\r
+                       }\r
+\r
+                       if (UniStrCmpi(status_str, _UU("CM_ACCOUNT_ONLINE")) == 0 ||\r
+                               UniStrCmpi(status_str, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                       {\r
+                               if (flag == true)\r
+                               {\r
+                                       b = true;\r
+                               }\r
+\r
+                               is_account = true;\r
+                       }\r
+\r
+                       if (b)\r
+                       {\r
+                               wchar_t tmp[MAX_PATH];\r
+                               wchar_t *account_name, *server_name;\r
+                               wchar_t *hub_name;\r
+                               if (h == NULL)\r
+                               {\r
+                                       h = CreatePopupMenu();\r
+                               }\r
+\r
+                               account_name = LvGetStr(hWnd, L_ACCOUNT, i, 0);\r
+                               server_name = LvGetStr(hWnd, L_ACCOUNT, i, 2);\r
+                               hub_name = LvGetStr(hWnd, L_ACCOUNT, i, 3);\r
+\r
+                               if (easy == false)\r
+                               {\r
+                                       UniFormat(tmp, sizeof(tmp), L"%s\t- %s [%s]", account_name, server_name, hub_name);\r
+                               }\r
+                               else\r
+                               {\r
+                                       UniStrCpy(tmp, sizeof(tmp), account_name);\r
+                               }\r
+\r
+                               MsAppendMenu(h, MF_STRING, start_id + i, tmp);\r
+\r
+                               Free(account_name);\r
+                               Free(server_name);\r
+                               Free(hub_name);\r
+                       }\r
+\r
+                       Free(status_str);\r
+               }\r
+       }\r
+\r
+       return h;\r
+}\r
+\r
+// タスクトレイの右クリックメニューを表示する\r
+void CmShowTrayMenu(HWND hWnd)\r
+{\r
+       HMENU h;\r
+       POINT p;\r
+       HMENU sub1, sub2, sub3, sub4;\r
+       bool locked;\r
+       bool easy;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       cm->MenuPopuping = true;\r
+\r
+       locked = cm->CmSetting.LockMode;\r
+       easy = cm->CmSetting.EasyMode;\r
+\r
+       // メニューを作成する\r
+       h = CreatePopupMenu();\r
+\r
+       // キャンセル\r
+       MsAppendMenu(h, MF_ENABLED | MF_STRING, 100007, _UU("CM_TRAY_MENU_CANCEL"));\r
+\r
+       // セパレータ\r
+       MsAppendMenu(h, MF_SEPARATOR, 10006, NULL);\r
+\r
+       if (locked == false && easy == false)\r
+       {\r
+               // 新しい接続設定の作成\r
+               MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_NEW, _UU("CM_TRAY_MENU_NEW"));\r
+\r
+               // セパレータ\r
+               MsAppendMenu(h, MF_SEPARATOR, 10005, NULL);\r
+       }\r
+\r
+       // 接続メニュー\r
+       sub1 = CmCreateTraySubMenu(hWnd, false, CM_TRAY_MENU_CONNECT_ID_START);\r
+       if (sub1 != NULL)\r
+       {\r
+               MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,\r
+                       (UINT_PTR)sub1, _UU("CM_TRAY_MENU_CONNECT"));\r
+       }\r
+\r
+       // 切断メニュー\r
+       sub2 = CmCreateTraySubMenu(hWnd, true, CM_TRAY_MENU_DISCONNECT_ID_START);\r
+       if (sub2 != NULL)\r
+       {\r
+               MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,\r
+                       (UINT_PTR)sub2, _UU("CM_TRAY_MENU_DISCONNECT"));\r
+       }\r
+\r
+       // ステータス表示メニュー\r
+       sub3 = CmCreateTraySubMenu(hWnd, true, CM_TRAY_MENU_STATUS_ID_START);\r
+       if (sub3 != NULL)\r
+       {\r
+               MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,\r
+                       (UINT_PTR)sub3, _UU("CM_TRAY_MENU_STATUS"));\r
+       }\r
+\r
+       if (sub3 != NULL)\r
+       {\r
+               // すべての接続を切断\r
+               MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_DISCONNECT_ALL, _UU("CM_TRAY_MENU_DISCONNECT_ALL"));\r
+       }\r
+\r
+       if (sub1 != NULL || sub2 != NULL || sub3 != NULL)\r
+       {\r
+               // セパレータ\r
+               MsAppendMenu(h, MF_SEPARATOR, 10003, NULL);\r
+       }\r
+\r
+       // 最近接続した VPN サーバーに接続\r
+       sub4 = CmCreateRecentSubMenu(hWnd, CM_TRAY_MENU_RECENT_ID_START);\r
+       if (sub4 != NULL)\r
+       {\r
+               MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,\r
+                       (UINT_PTR)sub4, _UU("CM_TRAY_MENU_RECENT"));\r
+               MsAppendMenu(h, MF_SEPARATOR, 10008, NULL);\r
+       }\r
+\r
+       if (locked == false && easy == false)\r
+       {\r
+               // 通信スループット測定\r
+               MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_TRAFFIC, _UU("CM_TRAY_MENU_TRAFFIC"));\r
+       }\r
+\r
+       if (easy == false)\r
+       {\r
+               // ネットワークデバイス状態\r
+               MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_NETIF, _UU("CM_TRAY_MENU_NETIF"));\r
+       }\r
+\r
+       // バージョン情報\r
+       MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_ABOUT, _UU("CM_TRAY_MENU_ABOUT"));\r
+\r
+       // セパレータ\r
+       MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);\r
+\r
+       // 動作モードの変更\r
+       MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_CM_SETTING, _UU("CM_TRAY_MENU_SETTING"));\r
+\r
+       // セパレータ\r
+       MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);\r
+\r
+       // アイコンを非表示\r
+       MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_TRAYICON, _UU("CM_MENU@CMD_TRAYICON"));\r
+\r
+       // セパレータ\r
+       MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);\r
+\r
+       // 表示または非表示\r
+       MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_EXIT,\r
+               IsHide(hWnd, 0) ? _UU("CM_TRAY_MENU_1_SHOW") : _UU("CM_TRAY_MENU_1_HIDE"));\r
+\r
+       // 終了\r
+       MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_QUIT, _UU("CM_TRAY_MENU_2_QUIT"));\r
+\r
+       // メニューを表示する\r
+       GetCursorPos(&p);\r
+\r
+       SetForegroundWindow(hWnd);\r
+       TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);\r
+       PostMessage(hWnd, WM_NULL, 0, 0);\r
+\r
+       if (sub1 != NULL)\r
+       {\r
+               DestroyMenu(sub1);\r
+       }\r
+\r
+       if (sub2 != NULL)\r
+       {\r
+               DestroyMenu(sub2);\r
+       }\r
+\r
+       if (sub3 != NULL)\r
+       {\r
+               DestroyMenu(sub3);\r
+       }\r
+\r
+       DestroyMenu(h);\r
+\r
+       cm->MenuPopuping = false;\r
+}\r
+\r
+// メインウインドウを表示または隠す\r
+void CmShowOrHideWindow(HWND hWnd)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsHide(hWnd, 0))\r
+       {\r
+               Show(hWnd, 0);\r
+               if (IsIconic(hWnd))\r
+               {\r
+                       ShowWindow(hWnd, SW_SHOWNORMAL);\r
+               }\r
+               SetForegroundWindow(hWnd);\r
+               SetActiveWindow(hWnd);\r
+       }\r
+       else\r
+       {\r
+               CmSaveMainWindowPos(hWnd);\r
+               Hide(hWnd, 0);\r
+\r
+               if (cm->TrayInited == false)\r
+               {\r
+                       Command(hWnd, CMD_QUIT);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+// アカウントリストを右クリックした\r
+void CmAccountListRightClick(HWND hWnd)\r
+{\r
+       HMENU h;\r
+       HMENU parent;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // メニューをロード\r
+       h = LoadSubMenu(M_MAIN, 0, &parent);\r
+       if (h == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       InitMenuInternational(h, "CM_MENU");\r
+\r
+       // ショートカットキーを除去\r
+       RemoveShortcutKeyStrFromMenu(h);\r
+\r
+       // 終了メニューを削除\r
+       i = GetMenuItemPos(h, CMD_QUIT);\r
+       if (i != INFINITE)\r
+       {\r
+               DeleteMenuItem(h, i);\r
+               DeleteMenuItem(h, i - 1);\r
+               DeleteMenuItem(h, i - 2);\r
+               DeleteMenuItem(h, i - 3);\r
+       }\r
+\r
+       // 有効 / 無効の設定\r
+       CmMainWindowOnPopupMenu(hWnd, h, INFINITE);\r
+\r
+       if (h != NULL)\r
+       {\r
+               // 選択されているアカウントが接続中かどうか判別する\r
+               UINT i = LvGetSelected(hWnd, L_ACCOUNT);\r
+               wchar_t *str;\r
+               bool is_connected = false;\r
+               if (i != INFINITE)\r
+               {\r
+                       str = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+                       if (str != NULL)\r
+                       {\r
+                               if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                               {\r
+                                       // 接続中\r
+                                       is_connected = true;\r
+                               }\r
+                               Free(str);\r
+                       }\r
+               }\r
+\r
+               if (i == INFINITE)\r
+               {\r
+                       // 新規作成メニューを太字にする\r
+                       SetMenuItemBold(h, GetMenuItemPos(h, CMD_NEW), true);\r
+               }\r
+               else\r
+               {\r
+                       if (is_connected == false)\r
+                       {\r
+                               // 接続メニューを太字にする\r
+                               SetMenuItemBold(h, GetMenuItemPos(h, CMD_CONNECT), true);\r
+                       }\r
+                       else\r
+                       {\r
+                               // 状況メニューを太字にする\r
+                               SetMenuItemBold(h, GetMenuItemPos(h, CMD_STATUS), true);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // メニューを表示\r
+       PrintMenu(hWnd, h);\r
+\r
+       DestroyMenu(parent);\r
+}\r
+\r
+// 仮想 LAN カードリストを右クリックした\r
+void CmVLanListRightClick(HWND hWnd)\r
+{\r
+       HMENU h;\r
+       HMENU parent;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // メニューをロード\r
+       h = LoadSubMenu(M_MAIN, 3, &parent);\r
+       if (h == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       InitMenuInternational(h, "CM_MENU");\r
+\r
+       // ショートカットキーを除去\r
+       RemoveShortcutKeyStrFromMenu(h);\r
+\r
+       // 有効 / 無効の設定\r
+       CmMainWindowOnPopupMenu(hWnd, h, INFINITE);\r
+\r
+       if (h != NULL)\r
+       {\r
+               // 選択されているデバイスが有効かどうか調べる\r
+               UINT i = LvGetSelected(hWnd, L_VLAN);\r
+               wchar_t *str;\r
+               bool is_active = false;\r
+               if (i != INFINITE)\r
+               {\r
+                       str = LvGetStr(hWnd, L_VLAN, i, 1);\r
+                       if (str != NULL)\r
+                       {\r
+                               if (UniStrCmpi(str, _UU("CM_VLAN_ENABLED")) == 0)\r
+                               {\r
+                                       // 有効\r
+                                       is_active = true;\r
+                               }\r
+                               Free(str);\r
+                       }\r
+               }\r
+\r
+               if (i == INFINITE)\r
+               {\r
+                       // 新規作成メニューを太字にする\r
+                       SetMenuItemBold(h, GetMenuItemPos(h, CMD_NEW_VLAN), true);\r
+               }\r
+               else\r
+               {\r
+                       if (is_active == false)\r
+                       {\r
+                               // 有効化メニューを太字にする\r
+                               SetMenuItemBold(h, GetMenuItemPos(h, CMD_ENABLE_VLAN), true);\r
+                       }\r
+                       else\r
+                       {\r
+                               // Windows ネットワーク設定メニューを太字にする\r
+                               SetMenuItemBold(h, GetMenuItemPos(h, CMD_WINNET), true);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // メニューを表示\r
+       PrintMenu(hWnd, h);\r
+\r
+       DestroyMenu(parent);\r
+}\r
+\r
+// メインウインドウへの通知\r
+void CmMainWindowOnNotify(HWND hWnd, NMHDR *n)\r
+{\r
+       bool item_vlan;\r
+       NMLVDISPINFOW *disp_info;\r
+       NMLVKEYDOWN *key;\r
+\r
+       // 引数チェック\r
+       if (hWnd == NULL || n == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       switch (n->idFrom)\r
+       {\r
+       case L_ACCOUNT:\r
+       case L_VLAN:\r
+               if (n->idFrom == L_ACCOUNT)\r
+               {\r
+                       item_vlan = false;\r
+               }\r
+               else\r
+               {\r
+                       item_vlan = true;\r
+               }\r
+\r
+               switch (n->code)\r
+               {\r
+               case NM_DBLCLK:\r
+                       // ダブルクリック\r
+                       CmOnKey(hWnd, false, false, VK_RETURN);\r
+                       break;\r
+               case NM_RCLICK:\r
+                       // 右クリック\r
+                       if (item_vlan == false)\r
+                       {\r
+                               CmAccountListRightClick(hWnd);\r
+                       }\r
+                       else\r
+                       {\r
+                               CmVLanListRightClick(hWnd);\r
+                       }\r
+                       break;\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_ACCOUNT, 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_ACCOUNT a;\r
+                                               Zero(&a, sizeof(a));\r
+                                               UniStrCpy(a.OldName, sizeof(a.OldName), old_name);\r
+                                               UniStrCpy(a.NewName, sizeof(a.NewName), new_name);\r
+                                               if (CALL(hWnd, CcRenameAccount(cm->Client, &a)))\r
+                                               {\r
+                                                       LvSetItem(hWnd, L_ACCOUNT, disp_info->item.iItem, 0, new_name);\r
+                                               }\r
+                                       }\r
+\r
+                                       Free(old_name);\r
+                               }\r
+                       }\r
+                       break;\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
+                               CmOnKey(hWnd, ctrl, alt, code);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+}\r
+\r
+// キーボード押下\r
+void CmOnKey(HWND hWnd, bool ctrl, bool alt, UINT key)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 単一キー\r
+       switch (key)\r
+       {\r
+       case VK_RETURN:\r
+               Command(hWnd, IDOK);\r
+               break;\r
+       case VK_DELETE:\r
+               // 削除\r
+               if (IsFocus(hWnd, L_ACCOUNT))\r
+               {\r
+                       // アカウントリストに関する操作\r
+                       Command(hWnd, CMD_DELETE);\r
+               }\r
+               else\r
+               {\r
+                       // 仮想 LAN カードリストに関する操作\r
+                       Command(hWnd, CMD_DELETE_VLAN);\r
+               }\r
+               break;\r
+       case VK_F2:\r
+               // 名前変更\r
+               Command(hWnd, CMD_RENAME);\r
+               break;\r
+       case VK_F5:\r
+               // 状態更新\r
+               Command(hWnd, CMD_REFRESH);\r
+               break;\r
+       }\r
+\r
+       if (alt)\r
+       {\r
+               switch (key)\r
+               {\r
+               case 'Q':\r
+                       // 閉じる\r
+                       Command(hWnd, CMD_QUIT);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (ctrl)\r
+       {\r
+               switch (key)\r
+               {\r
+               case 'G':\r
+                       // スマートカードマネージャ\r
+                       Command(hWnd, CMD_SECURE_MANAGER);\r
+                       break;\r
+               case 'S':\r
+                       // 状態の表示\r
+                       Command(hWnd, CMD_STATUS);\r
+                       break;\r
+               case 'I':\r
+                       // すべての接続を切断\r
+                       Command(hWnd, CMD_DISCONNECT_ALL);\r
+                       break;\r
+               case 'D':\r
+                       // 切断\r
+                       Command(hWnd, CMD_DISCONNECT);\r
+                       break;\r
+               case 'N':\r
+                       // 接続設定の新規作成\r
+                       Command(hWnd, CMD_NEW);\r
+                       break;\r
+               case 'C':\r
+                       // コピーの作成\r
+                       Command(hWnd, CMD_CLONE);\r
+                       break;\r
+               case 'T':\r
+                       // スタートアップ接続に設定\r
+                       Command(hWnd, CMD_STARTUP);\r
+                       break;\r
+               case 'A':\r
+                       // すべて選択\r
+                       Command(hWnd, CMD_SELECT_ALL);\r
+                       break;\r
+               case 'L':\r
+                       // 新規仮想 LAN カードの作成\r
+                       Command(hWnd, CMD_NEW_VLAN);\r
+                       break;\r
+               case 'E':\r
+                       // 仮想 LAN カードの有効化\r
+                       Command(hWnd, CMD_ENABLE_VLAN);\r
+                       break;\r
+               case 'B':\r
+                       // 仮想 LAN カードの無効化\r
+                       Command(hWnd, CMD_DISABLE_VLAN);\r
+                       break;\r
+               case 'U':\r
+                       // ドライバの再インストール\r
+                       Command(hWnd, CMD_REINSTALL);\r
+                       break;\r
+               case 'W':\r
+                       // Windows ネットワーク接続の設定\r
+                       Command(hWnd, CMD_WINNET);\r
+                       break;\r
+               case 'P':\r
+                       // パスワードの設定\r
+                       Command(hWnd, CMD_PASSWORD);\r
+                       break;\r
+               case 'O':\r
+                       // オプション設定\r
+                       Command(hWnd, CMD_TRAFFIC);\r
+                       break;\r
+               case 'R':\r
+                       // 証明書管理\r
+                       Command(hWnd, CMD_TRUST);\r
+                       break;\r
+               case 'Q':\r
+                       // スループット\r
+                       Command(hWnd, CMD_TRAFFIC);\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+// メインウインドウのコマンド\r
+void CmMainWindowOnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)\r
+{\r
+       CmMainWindowOnCommandEx(hWnd, wParam, lParam, false);\r
+}\r
+void CmMainWindowOnCommandEx(HWND hWnd, WPARAM wParam, LPARAM lParam, bool easy)\r
+{\r
+       wchar_t *tmp;\r
+       char *name;\r
+       UINT index;\r
+       UINT id;\r
+       bool ctrl, alt;\r
+       UINT flag = 0;\r
+       // 引数チェック\r
+       wchar_t *selected_name = NULL;\r
+       UINT starter_id = 0;\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;\r
+       alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;\r
+\r
+       if (wParam == IDOK)\r
+       {\r
+               tmp = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       if (UniStrCmpi(tmp, _UU("CM_NEW_ICON")) == 0)\r
+                       {\r
+                               Free(tmp);\r
+                               Command(hWnd, CMD_NEW);\r
+                               return;\r
+                       }\r
+                       if (UniStrCmpi(tmp, _UU("CM_ASP")) == 0)\r
+                       {\r
+                               Free(tmp);\r
+                               ShellExecuteA(hWnd, "open", _SS("CM_ASP_URL"), NULL, NULL, SW_SHOW);\r
+                               return;\r
+                       }\r
+                       Free(tmp);\r
+               }\r
+       }\r
+\r
+       if (CmIsEnabled(hWnd, (UINT)wParam) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (CM_TRAY_IS_CONNECT_ID(wParam))\r
+       {\r
+               // 接続要求\r
+               starter_id = CM_TRAY_MENU_CONNECT_ID_START;\r
+               flag = 1;\r
+       }\r
+\r
+       if (CM_TRAY_IS_STATUS_ID(wParam))\r
+       {\r
+               // 情報表示要求\r
+               starter_id = CM_TRAY_MENU_STATUS_ID_START;\r
+               flag = 2;\r
+       }\r
+\r
+       if (CM_TRAY_IS_DISCONNECT_ID(wParam))\r
+       {\r
+               // 切断要求\r
+               starter_id = CM_TRAY_MENU_DISCONNECT_ID_START;\r
+               flag = 3;\r
+       }\r
+\r
+       if (CM_TRAY_IS_RECENT_ID(wParam))\r
+       {\r
+               // 最近の接続先\r
+               starter_id = CM_TRAY_MENU_RECENT_ID_START;\r
+               flag = 1;\r
+       }\r
+\r
+       if (starter_id != 0)\r
+       {\r
+               UINT num;\r
+\r
+               id = (UINT)wParam - starter_id;\r
+\r
+               num = LvNum(hWnd, L_ACCOUNT);\r
+\r
+               if (id < num)\r
+               {\r
+                       selected_name = LvGetStr(hWnd, L_ACCOUNT, id, 0);\r
+\r
+                       if (selected_name != NULL)\r
+                       {\r
+                               if (UniStrCmpi(selected_name, _UU("CM_NEW_ICON")) != 0 &&\r
+                                       UniStrCmpi(selected_name, _UU("CM_ASP")) != 0)\r
+                               {\r
+                                       switch (flag)\r
+                                       {\r
+                                       case 1:\r
+                                               CmConnect(hWnd, selected_name);\r
+                                               break;\r
+\r
+                                       case 2:\r
+                                               CmStatus(hWnd, selected_name);\r
+                                               break;\r
+\r
+                                       case 3:\r
+                                               CmDisconnect(hWnd, selected_name);\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       Free(selected_name);\r
+               }\r
+       }\r
+\r
+       switch (wParam)\r
+       {\r
+       case IDOK:\r
+       case CMD_EASY_DBLCLICK:\r
+               // 接続またはプロパティ\r
+               if (IsFocus(hWnd, L_ACCOUNT) || (hWnd == cm->hEasyWnd))\r
+               {\r
+                       // アカウントリストに関する操作\r
+                       if (alt == false)\r
+                       {\r
+                               UINT index = LvGetSelected(hWnd, L_ACCOUNT);\r
+                               bool b = false;\r
+                               if (index != INFINITE)\r
+                               {\r
+                                       wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, index, 1);\r
+                                       if (s != NULL)\r
+                                       {\r
+                                               if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                                               {\r
+                                                       b = true;\r
+                                               }\r
+                                               Free(s);\r
+                                       }\r
+                               }\r
+\r
+                               if (b == false)\r
+                               {\r
+                                       // 接続\r
+                                       Command(hWnd, CMD_CONNECT);\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (hWnd != cm->hEasyWnd || wParam == CMD_EASY_DBLCLICK)\r
+                                       {\r
+                                               // 状況表示\r
+                                               Command(hWnd, CMD_STATUS);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // 切断\r
+                                               Command(hWnd, CMD_DISCONNECT);\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               // プロパティ\r
+                               Command(hWnd, CMD_PROPERTY);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // Windows ネットワーク接続の設定\r
+                       Command(hWnd, CMD_WINNET);\r
+               }\r
+               break;\r
+       case CMD_CONNECT:\r
+               // 接続\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmConnect(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_STATUS:\r
+               // 状態の表示\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmStatus(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_DISCONNECT_ALL:\r
+               // すべての接続を切断する\r
+               CmDisconnectAll(hWnd);\r
+               break;\r
+       case CMD_DISCONNECT:\r
+               // 切断\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmDisconnect(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_NEW:\r
+               // 新規作成\r
+               CmNewAccount(hWnd);\r
+               break;\r
+       case CMD_CLONE:\r
+               // コピー\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmCopyAccount(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_SHORTCUT:\r
+               // ショートカット作成\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmSortcut(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_EXPORT_ACCOUNT:\r
+               // 設定のエクスポート\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmExportAccount(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_IMPORT_ACCOUNT:\r
+               // 設定のインポート\r
+               CmImportAccount(hWnd);\r
+               break;\r
+       case CMD_STARTUP:\r
+               // スタートアップ接続に設定\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       RPC_CLIENT_DELETE_ACCOUNT c;\r
+                       Zero(&c, sizeof(c));\r
+                       UniStrCpy(c.AccountName, sizeof(c.AccountName), tmp);\r
+                       CALL(hWnd, CcSetStartupAccount(cm->Client, &c));\r
+                       CmVoice("set_startup");\r
+                       MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_SET_STARTUP"), tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_NOSTARTUP:\r
+               // スタートアップ接続を解除\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
+                               _UU("CM_REMOVE_STARTUP"), tmp) == IDYES)\r
+                       {\r
+                               RPC_CLIENT_DELETE_ACCOUNT c;\r
+                               Zero(&c, sizeof(c));\r
+                               UniStrCpy(c.AccountName, sizeof(c.AccountName), tmp);\r
+                               CALL(hWnd, CcRemoveStartupAccount(cm->Client, &c));\r
+                               CmVoice("remove_startup");\r
+                       }\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_DELETE:\r
+               // 削除\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmDeleteAccount(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case CMD_RENAME:\r
+               // 名前の変更\r
+               Focus(hWnd, L_ACCOUNT);\r
+               LvRename(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT));\r
+               break;\r
+       case CMD_PROPERTY:\r
+               // プロパティ\r
+               tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);\r
+               if (tmp != NULL)\r
+               {\r
+                       CmEditAccount(hWnd, tmp);\r
+                       Free(tmp);\r
+               }\r
+               break;\r
+       case IDCANCEL:\r
+       case CMD_EXIT:\r
+               // 閉じる\r
+               Close(hWnd);\r
+               break;\r
+       case CMD_QUIT:\r
+               // 終了\r
+               CmMainWindowOnQuit(hWnd);\r
+               break;\r
+       case CMD_SELECT_ALL:\r
+               // すべて選択\r
+               LvSelectAll(hWnd, L_ACCOUNT);\r
+               LvSelectAll(hWnd, L_VLAN);\r
+               break;\r
+       case CMD_SWITCH_SELECT:\r
+               // 選択反転\r
+               LvSwitchSelect(hWnd, L_ACCOUNT);\r
+               LvSwitchSelect(hWnd, L_VLAN);\r
+               break;\r
+       case CMD_GRID:\r
+               // 罫線表示\r
+               cm->ShowGrid = !cm->ShowGrid;\r
+               CmRefreshVLanListEx(hWnd, true);\r
+               CmRefreshAccountListEx2(hWnd, false, true);\r
+               break;\r
+       case CMD_STATUSBAR:\r
+               // ステータスバー表示\r
+               if (cm->HideStatusBar == false)\r
+               {\r
+                       cm->HideStatusBar = true;\r
+                       Hide(hWnd, S_STATUSBAR);\r
+                       CmMainWindowOnSize(hWnd);\r
+               }\r
+               else\r
+               {\r
+                       cm->HideStatusBar = false;\r
+                       Show(hWnd, S_STATUSBAR);\r
+                       CmMainWindowOnSize(hWnd);\r
+               }\r
+               CmSaveMainWindowPos(hWnd);\r
+               break;\r
+       case CMD_VISTASTYLE:\r
+               cm->VistaStyle = !cm->VistaStyle;\r
+               CmRefreshEx(hWnd, true);\r
+               CmSaveMainWindowPos(hWnd);\r
+               break;\r
+       case CMD_TRAYICON:\r
+               // トレイアイコン表示\r
+               if (cm->HideTrayIcon == false)\r
+               {\r
+                       cm->HideTrayIcon = true;\r
+                       CmFreeTray(hWnd);\r
+\r
+                       if (IsHide(hWnd, 0))\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_TRAY_ICON_RESTORE"));\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       cm->HideTrayIcon = false;\r
+                       if (cm->server_name == NULL)\r
+                       {\r
+                               CmInitTray(hWnd);\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_SHOWPORT:\r
+               // ポート番号を表示\r
+               cm->ShowPort = !cm->ShowPort;\r
+               CmRefresh(hWnd);\r
+               break;\r
+       case CMD_ICON:\r
+               // アイコン表示\r
+               if (cm->IconView == false)\r
+               {\r
+                       cm->IconView = true;\r
+                       CmRefresh(hWnd);\r
+               }\r
+               break;\r
+       case CMD_DETAIL:\r
+               // 詳細表示\r
+               if (cm->IconView)\r
+               {\r
+                       cm->IconView = false;\r
+                       CmRefresh(hWnd);\r
+               }\r
+               break;\r
+       case CMD_REFRESH:\r
+               if (easy == false)\r
+               {\r
+                       // 表示更新\r
+                       LvReset(hWnd, L_ACCOUNT);\r
+                       LvReset(hWnd, L_VLAN);\r
+                       CmRefresh(hWnd);\r
+               }\r
+               break;\r
+       case CMD_NEW_VLAN:\r
+               // 仮想 LAN カード作成\r
+               name = CmNewVLanDlg(hWnd);\r
+               if (name != NULL)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       void *helper = NULL;\r
+                       RPC_CLIENT_CREATE_VLAN c;\r
+                       Zero(&c, sizeof(c));\r
+                       StrCpy(c.DeviceName, sizeof(c.DeviceName), name);\r
+                       if (MsIsNt() == false)\r
+                       {\r
+                               // ウインドウのタイトルを変更する\r
+                               GetTxt(hWnd, 0, tmp, sizeof(tmp));\r
+                               SetText(hWnd, 0, _UU("CM_VLAN_INSTALLING"));\r
+                       }\r
+                       // 最小化\r
+                       if (MsIsVista() == false)\r
+                       {\r
+                               ShowWindow(hWnd, SW_SHOWMINIMIZED);\r
+                       }\r
+\r
+                       if (MsIsVista())\r
+                       {\r
+                               helper = CmStartUacHelper();\r
+                       }\r
+\r
+                       if (CALL(hWnd, CcCreateVLan(cm->Client, &c)))\r
+                       {\r
+                               CmVoice("new_vlan");\r
+                       }\r
+\r
+                       CmStopUacHelper(helper);\r
+\r
+                       if (MsIsNt() == false)\r
+                       {\r
+                               // ウインドウのタイトルを戻す\r
+                               SetText(hWnd, 0, tmp);\r
+                       }\r
+                       // 戻す\r
+                       if (MsIsVista() == false)\r
+                       {\r
+                               ShowWindow(hWnd, SW_SHOWNORMAL);\r
+                       }\r
+                       Free(name);\r
+               }\r
+               break;\r
+       case CMD_DELETE_VLAN:\r
+               // 仮想 LAN カード削除\r
+               index = LvGetSelected(hWnd, L_VLAN);\r
+               if (index != INFINITE)\r
+               {\r
+                       if (cm->Client->Win9x == false)\r
+                       {\r
+                               // Windows 2000 以降\r
+                               wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);\r
+                               if (s != NULL)\r
+                               {\r
+                                       RPC_CLIENT_CREATE_VLAN c;\r
+                                       char str[MAX_SIZE];\r
+                                       CmVoice("delete_vlan_1");\r
+                                       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_VLAN"), s) == IDYES)\r
+                                       {\r
+                                               Zero(&c, sizeof(c));\r
+                                               UniToStr(str, sizeof(str), s);\r
+                                               if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))\r
+                                               {\r
+                                                       if (CALL(hWnd, CcDeleteVLan(cm->Client, &c)))\r
+                                                       {\r
+                                                               CmVoice("delete_vlan_2");\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       Free(s);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               // Windows 9x\r
+                               if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_9X_VLAN_UNINSTALL")) == IDYES)\r
+                               {\r
+                                       Run("rundll32.exe", "shell32.dll,Control_RunDLL NETCPL.CPL",\r
+                                               false, false);\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_ENABLE_VLAN:\r
+               // 仮想 LAN カードの有効化\r
+               index = LvGetSelected(hWnd, L_VLAN);\r
+               if (index != INFINITE)\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               RPC_CLIENT_CREATE_VLAN c;\r
+                               char str[MAX_SIZE];\r
+                               Zero(&c, sizeof(c));\r
+                               UniToStr(str, sizeof(str), s);\r
+                               if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))\r
+                               {\r
+                                       CALL(hWnd, CcEnableVLan(cm->Client, &c));\r
+                               }\r
+                               Free(s);\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_DISABLE_VLAN:\r
+               // 仮想 LAN カードの無効化\r
+               index = LvGetSelected(hWnd, L_VLAN);\r
+               if (index != INFINITE)\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               RPC_CLIENT_CREATE_VLAN c;\r
+                               char str[MAX_SIZE];\r
+                               Zero(&c, sizeof(c));\r
+                               UniToStr(str, sizeof(str), s);\r
+                               if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))\r
+                               {\r
+                                       CALL(hWnd, CcDisableVLan(cm->Client, &c));\r
+                               }\r
+                               Free(s);\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_REINSTALL:\r
+               // 仮想 LAN カードの再インストール\r
+               index = LvGetSelected(hWnd, L_VLAN);\r
+               if (index != INFINITE)\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);\r
+                       if (s != NULL)\r
+                       {\r
+                               RPC_CLIENT_CREATE_VLAN c;\r
+                               char str[MAX_SIZE];\r
+                               Zero(&c, sizeof(c));\r
+                               UniToStr(str, sizeof(str), s);\r
+                               if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))\r
+                               {\r
+                                       void *helper = NULL;\r
+\r
+                                       if (MsIsVista() == false)\r
+                                       {\r
+                                               ShowWindow(hWnd, SW_SHOWMINIMIZED);\r
+                                       }\r
+\r
+                                       if (MsIsVista())\r
+                                       {\r
+                                               helper = CmStartUacHelper();\r
+                                       }\r
+\r
+                                       CALL(hWnd, CcUpgradeVLan(cm->Client, &c));\r
+\r
+                                       CmStopUacHelper(helper);\r
+\r
+                                       if (MsIsVista() == false)\r
+                                       {\r
+                                               ShowWindow(hWnd, SW_SHOWNORMAL);\r
+                                       }\r
+                               }\r
+                               Free(s);\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_PASSWORD:\r
+               // パスワード設定\r
+               CmPassword(hWnd);\r
+               break;\r
+       case CMD_OPTION:\r
+               // オプション\r
+               CmConfigDlg(hWnd);\r
+               break;\r
+       case CMD_TRUST:\r
+               // 証明書管理\r
+               CmTrustDlg(hWnd);\r
+               break;\r
+       case CMD_ABOUT:\r
+               // バージョン情報\r
+               if (IsEnable(hWnd, 0))\r
+               {\r
+                       ShowSplashEx(hWnd, "UT-VPN Client", 0, CM_SPLASH_BORDER_COLOR);\r
+               }\r
+               break;\r
+       case CMD_VOIDE_NONE:\r
+               cm->DisableVoice = true;\r
+               break;\r
+       case CMD_VOICE_NORMAL:\r
+               cm->DisableVoice = false;\r
+               cm->VoiceId = VOICE_SSK;\r
+               break;\r
+       case CMD_VOICE_ODD:\r
+               if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_EXT_VOICE_MSG")) == IDYES)\r
+               {\r
+                       cm->DisableVoice = false;\r
+                       cm->VoiceId = VOICE_AHO;\r
+               }\r
+               break;\r
+       case CMD_SECURE_MANAGER:\r
+               // スマートカードマネージャ\r
+               CmClientSecureManager(hWnd);\r
+               break;\r
+       case CMD_SECURE_SELECT:\r
+               // スマートカードの選択\r
+               CmClientSelectSecure(hWnd);\r
+               break;\r
+       case CMD_NETIF:\r
+               // ネットワークデバイスの状態\r
+               if (IsEnable(hWnd, 0))\r
+               {\r
+                       UtSpeedMeterEx(hWnd);\r
+               }\r
+               break;\r
+       case CMD_TCPIP:\r
+               // TCP/IP 最適化ユーティリティ\r
+               if (IsEnable(hWnd, 0))\r
+               {\r
+                       ShowTcpIpConfigUtil(hWnd, true);\r
+               }\r
+               break;\r
+       case CMD_MMCSS:\r
+               // Windows Vista 用最適化ユーティリティ\r
+               if (MsIsVista() == false)\r
+               {\r
+                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_4"));\r
+               }\r
+               else\r
+               {\r
+                       if (MsIsAdmin() == false)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("VISTA_MMCSS_MSG_4"));\r
+                       }\r
+                       else\r
+                       {\r
+                               if (MsIsMMCSSNetworkThrottlingEnabled())\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("VISTA_MMCSS_MSG")) == IDYES)\r
+                                       {\r
+                                               MsSetMMCSSNetworkThrottlingEnable(false);\r
+                                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_5"));\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("VISTA_MMCSS_MSG_2")) == IDYES)\r
+                                       {\r
+                                               MsSetMMCSSNetworkThrottlingEnable(true);\r
+                                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_6"));\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_TRAFFIC:\r
+               // 通信トラフィック測定\r
+               if (IsEnable(hWnd, 0))\r
+               {\r
+                       CmTraffic(hWnd);\r
+               }\r
+               break;\r
+       case CMD_CM_SETTING:\r
+               // 動作モード設定\r
+               if (IsEnable(hWnd, 0))\r
+               {\r
+                       if (CmSetting(hWnd))\r
+                       {\r
+                               CmApplyCmSetting();\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_WINNET:\r
+               // Windows ネットワークの設定\r
+               ShowWindowsNetworkConnectionDialog();\r
+               break;\r
+       }\r
+}\r
+\r
+// オプション設定ダイアログ\r
+void CmConfigDlg(HWND hWnd)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_CM_CONFIG, CmConfigDlgProc, NULL);\r
+}\r
+\r
+// オプション設定ダイアログの初期化\r
+void CmConfigDlgInit(HWND hWnd)\r
+{\r
+       bool use_alpha;\r
+       UINT alpha_value;\r
+       UINT os;\r
+       CLIENT_CONFIG c;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       DlgFont(hWnd, S_WARNING, 10, true);\r
+       DlgFont(hWnd, S_INFO, 10, false);\r
+\r
+       Zero(&c, sizeof(c));\r
+       if (CALL(hWnd, CcGetClientConfig(cm->Client, &c)) == false)\r
+       {\r
+               EndDialog(hWnd, 0);\r
+               return;\r
+       }\r
+\r
+       Check(hWnd, R_ALLOW_REMOTE_CONFIG, c.AllowRemoteConfig);\r
+\r
+       Check(hWnd, R_USE_KEEP_CONNECT, c.UseKeepConnect);\r
+       SetTextA(hWnd, E_HOSTNAME, c.KeepConnectHost);\r
+       SetIntEx(hWnd, E_PORT, c.KeepConnectPort);\r
+       SetIntEx(hWnd, E_INTERVAL, c.KeepConnectInterval);\r
+\r
+       Check(hWnd, R_TCP, c.KeepConnectProtocol == CONNECTION_TCP);\r
+       Check(hWnd, R_UDP, c.KeepConnectProtocol == CONNECTION_UDP);\r
+\r
+       use_alpha = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha") == 0 ? false : true;\r
+       alpha_value = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue");\r
+       alpha_value = MAKESURE(alpha_value, 0, 100);\r
+\r
+       SetInt(hWnd, E_ALPHA_VALUE, alpha_value == 0 ? 50 : alpha_value);\r
+       Check(hWnd, R_ALPHA, use_alpha);\r
+\r
+       os = GetOsInfo()->OsType;\r
+       if (OS_IS_WINDOWS_NT(os) && GET_KETA(os, 100) >= 2)\r
+       {\r
+               Enable(hWnd, R_ALPHA);\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, R_ALPHA);\r
+       }\r
+\r
+       CmConfigDlgRefresh(hWnd);\r
+}\r
+\r
+// オプション設定ダイアログの更新\r
+void CmConfigDlgRefresh(HWND hWnd)\r
+{\r
+       bool ok = true;\r
+       bool use_keep_connect;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       use_keep_connect = IsChecked(hWnd, R_USE_KEEP_CONNECT);\r
+       SetEnable(hWnd, S_HOSTNAME, use_keep_connect);\r
+       SetEnable(hWnd, S_PORT, use_keep_connect);\r
+       SetEnable(hWnd, S_INTERVAL, use_keep_connect);\r
+       SetEnable(hWnd, S_INTERVAL2, use_keep_connect);\r
+       SetEnable(hWnd, S_PROTOCOL, use_keep_connect);\r
+       SetEnable(hWnd, S_INFO, use_keep_connect);\r
+       SetEnable(hWnd, S_INFO2, use_keep_connect);\r
+       SetEnable(hWnd, E_HOSTNAME, use_keep_connect);\r
+       SetEnable(hWnd, E_PORT, use_keep_connect);\r
+       SetEnable(hWnd, E_INTERVAL, use_keep_connect);\r
+       SetEnable(hWnd, R_TCP, use_keep_connect);\r
+       SetEnable(hWnd, R_UDP, use_keep_connect);\r
+\r
+       SetEnable(hWnd, S_WARNING, IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG));\r
+\r
+       if (IsChecked(hWnd, R_USE_KEEP_CONNECT))\r
+       {\r
+               if (IsEmpty(hWnd, E_HOSTNAME))\r
+               {\r
+                       ok = false;\r
+               }\r
+               if (IsChecked(hWnd, R_TCP) == false && IsChecked(hWnd, R_UDP) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+               if (GetInt(hWnd, E_PORT) == 0 || GetInt(hWnd, E_PORT) >= 65536)\r
+               {\r
+                       ok = false;\r
+               }\r
+               if (GetInt(hWnd, E_INTERVAL) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_ALPHA))\r
+       {\r
+               UINT i = GetInt(hWnd, E_ALPHA_VALUE);\r
+               if (i < 20 || i >= 100)\r
+               {\r
+                       ok = false;\r
+               }\r
+               Enable(hWnd, E_ALPHA_VALUE);\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, E_ALPHA_VALUE);\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// オプション設定ダイアログの設定保存\r
+void CmConfigDlgOnOk(HWND hWnd)\r
+{\r
+       CLIENT_CONFIG c;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&c, sizeof(c));\r
+       c.AllowRemoteConfig = IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG);\r
+       c.UseKeepConnect = IsChecked(hWnd, R_USE_KEEP_CONNECT);\r
+       GetTxtA(hWnd, E_HOSTNAME, c.KeepConnectHost, sizeof(c.KeepConnectHost));\r
+       c.KeepConnectPort = GetInt(hWnd, E_PORT);\r
+       c.KeepConnectInterval = GetInt(hWnd, E_INTERVAL);\r
+       if (IsChecked(hWnd, R_TCP))\r
+       {\r
+               c.KeepConnectProtocol = CONNECTION_TCP;\r
+       }\r
+       else if (IsChecked(hWnd, R_UDP))\r
+       {\r
+               c.KeepConnectProtocol = CONNECTION_UDP;\r
+       }\r
+       else\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (c.UseKeepConnect)\r
+       {\r
+               if (c.KeepConnectInterval < KEEP_INTERVAL_MIN || c.KeepConnectInterval > KEEP_INTERVAL_MAX)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_KEEP_INTERVAL_MSG"),\r
+                               KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);\r
+                       FocusEx(hWnd, E_INTERVAL);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (CALL(hWnd, CcSetClientConfig(cm->Client, &c)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue", GetInt(hWnd, E_ALPHA_VALUE));\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha", IsChecked(hWnd, R_ALPHA));\r
+\r
+       EndDialog(hWnd, true);\r
+}\r
+\r
+// オプション設定ダイアログプロシージャ\r
+UINT CmConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmConfigDlgInit(hWnd);\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case R_ALLOW_REMOTE_CONFIG:\r
+               case R_USE_KEEP_CONNECT:\r
+               case E_HOSTNAME:\r
+               case E_PORT:\r
+               case E_INTERVAL:\r
+               case R_ALPHA:\r
+               case E_ALPHA_VALUE:\r
+                       CmConfigDlgRefresh(hWnd);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       CmConfigDlgRefresh(hWnd);\r
+                       CmConfigDlgOnOk(hWnd);\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               case R_ALLOW_REMOTE_CONFIG:\r
+                       if (IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG) == false)\r
+                       {\r
+                               if (cm->server_name != NULL)\r
+                               {\r
+                                       // 現在リモート接続している場合、リモート管理を無効にするように\r
+                                       // 選択すると警告を表示する\r
+                                       if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_DEFBUTTON2 | MB_YESNO, _UU("CM_REMOTE_WARNING"),\r
+                                               cm->server_name, cm->server_name) == IDNO)\r
+                                       {\r
+                                               Check(hWnd, R_ALLOW_REMOTE_CONFIG, true);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+               case R_USE_KEEP_CONNECT:\r
+                       if (IsChecked(hWnd, R_USE_KEEP_CONNECT))\r
+                       {\r
+                               FocusEx(hWnd, E_HOSTNAME);\r
+                       }\r
+                       break;\r
+               case R_ALPHA:\r
+                       if (IsChecked(hWnd, R_ALPHA))\r
+                       {\r
+                               FocusEx(hWnd, E_ALPHA_VALUE);\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ショートカット作成\r
+void CmSortcut(HWND hWnd, wchar_t *account_name)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       CM_ACCOUNT *a;\r
+       wchar_t *filename;\r
+       UCHAR key[SHA1_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // アカウント情報を取得\r
+       a = CmGetExistAccountObject(hWnd, account_name);\r
+       if (a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Copy(key, a->ShortcutKey, SHA1_SIZE);\r
+\r
+       if (IsZero(key, SHA1_SIZE))\r
+       {\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_SHORTCUT_UNSUPPORTED"));\r
+       }\r
+       else\r
+       {\r
+               // ファイル名を決定\r
+               UniFormat(tmp, sizeof(tmp), L"%s.lnk", account_name);\r
+               UniSafeFileName(tmp);\r
+\r
+               filename = SaveDlg(hWnd, _UU("CM_SHORTCUT_FILE"),\r
+                       _UU("CM_SHORTCUT_SAVE_TITLE"), tmp, L".uvpn");\r
+\r
+               if (filename != NULL)\r
+               {\r
+                       char key_str[64];\r
+                       wchar_t target[MAX_PATH];\r
+                       wchar_t workdir[MAX_PATH];\r
+                       wchar_t args[MAX_PATH];\r
+                       wchar_t comment[MAX_SIZE];\r
+                       wchar_t icon[MAX_PATH];\r
+\r
+                       BinToStr(key_str, sizeof(key_str), key, SHA1_SIZE);\r
+\r
+                       // ショートカットを作成\r
+                       UniStrCpy(target, sizeof(target), MsGetExeFileNameW());\r
+                       UniStrCpy(workdir, sizeof(workdir), MsGetExeDirNameW());\r
+                       StrToUni(args, sizeof(args), key_str);\r
+                       UniFormat(comment, sizeof(comment), _UU("CM_SHORTCUT_COMMENT"), account_name);\r
+                       UniStrCpy(icon, sizeof(icon), MsGetExeFileNameW());\r
+\r
+                       if (CreateLink(tmp, target, workdir, args, comment, icon, 1) == false)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONSTOP, _UU("CM_SHORTCUT_ERROR"));\r
+                       }\r
+\r
+                       Free(filename);\r
+               }\r
+       }\r
+\r
+       CmFreeAccountObject(hWnd, a);\r
+}\r
+\r
+// アカウントのエクスポート\r
+void CmExportAccount(HWND hWnd, wchar_t *account_name)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       CM_ACCOUNT *a;\r
+       wchar_t *filename;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // アカウント情報を取得\r
+       a = CmGetExistAccountObject(hWnd, account_name);\r
+       if (a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // ファイル名を決定\r
+       UniFormat(tmp, sizeof(tmp), L"%s.uvpn", account_name);\r
+       UniSafeFileName(tmp);\r
+\r
+       filename = SaveDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"),\r
+               _UU("CM_ACCOUNT_SAVE_TITLE"), tmp, L".uvpn");\r
+\r
+       if (filename != NULL)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT t;\r
+               BUF *b;\r
+               BUF *b2;\r
+               wchar_t tmp[MAX_SIZE];\r
+               UCHAR *buf;\r
+               UINT buf_size;\r
+               UCHAR bom[] = {0xef, 0xbb, 0xbf, };\r
+\r
+               Zero(&t, sizeof(t));\r
+               t.ClientOption = a->ClientOption;\r
+               t.ClientAuth = a->ClientAuth;\r
+               t.StartupAccount = a->Startup;\r
+               t.CheckServerCert = a->CheckServerCert;\r
+               t.ServerCert = a->ServerCert;\r
+               t.ClientOption->FromAdminPack = false;\r
+\r
+               b = CiAccountToCfg(&t);\r
+\r
+               UniStrCpy(tmp, sizeof(tmp), filename);\r
+               b2 = NewBuf();\r
+\r
+               WriteBuf(b2, bom, sizeof(bom));\r
+\r
+               // ヘッダ部分を付加する\r
+               buf_size = CalcUniToUtf8(_UU("CM_ACCOUNT_FILE_BANNER"));\r
+               buf = ZeroMalloc(buf_size + 32);\r
+               UniToUtf8(buf, buf_size, _UU("CM_ACCOUNT_FILE_BANNER"));\r
+\r
+               WriteBuf(b2, buf, StrLen((char *)buf));\r
+               WriteBuf(b2, b->Buf, b->Size);\r
+               SeekBuf(b2, 0, 0);\r
+\r
+               FreeBuf(b);\r
+\r
+               if (DumpBufW(b2, tmp) == false)\r
+               {\r
+                       MsgBox(hWnd, MB_ICONSTOP, _UU("CM_FAILED_TO_SAVE_FILE"));\r
+               }\r
+\r
+               Free(filename);\r
+               FreeBuf(b2);\r
+               Free(buf);\r
+       }\r
+\r
+       CmFreeAccountObject(hWnd, a);\r
+}\r
+\r
+// アカウントのインポートメイン処理\r
+void CmImportAccountMain(HWND hWnd, wchar_t *filename)\r
+{\r
+       CmImportAccountMainEx(hWnd, filename, false);\r
+}\r
+void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite)\r
+{\r
+       wchar_t name[MAX_SIZE];\r
+       wchar_t tmp[MAX_SIZE];\r
+       BUF *b;\r
+       RPC_CLIENT_CREATE_ACCOUNT *t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || filename == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       UniStrCpy(tmp, sizeof(tmp), filename);\r
+\r
+       b = ReadDumpW(tmp);\r
+       if (b == NULL)\r
+       {\r
+               MsgBox(hWnd, MB_ICONSTOP, _UU("CM_FAILED_TO_OPEN_FILE"));\r
+               return;\r
+       }\r
+\r
+       t = CiCfgToAccount(b);\r
+       if (t == NULL)\r
+       {\r
+               FreeBuf(b);\r
+               MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED"));\r
+               return;\r
+       }\r
+\r
+       if (overwrite)\r
+       {\r
+               // すでに同一名が存在する場合は削除する\r
+               if (LvSearchStr(hWnd, L_ACCOUNT, 0, t->ClientOption->AccountName) != INFINITE)\r
+               {\r
+                       RPC_CLIENT_DELETE_ACCOUNT d;\r
+                       RPC_CLIENT_GET_ACCOUNT get;\r
+                       HWND h = cm->hEasyWnd == NULL ? hWnd : cm->hEasyWnd;\r
+\r
+                       Zero(&d, sizeof(d));\r
+                       UniStrCpy(d.AccountName, sizeof(d.AccountName), t->ClientOption->AccountName);\r
+\r
+                       Zero(&get, sizeof(get));\r
+                       UniStrCpy(get.AccountName, sizeof(get.AccountName), t->ClientOption->AccountName);\r
+                       if (CcGetAccount(cm->Client, &get) == ERR_NO_ERROR)\r
+                       {\r
+                               // すでに存在する同一名のアカウント情報を取得して\r
+                               // クライアントオプションのうちいくつかの情報を継承する\r
+                               if (get.ClientOption != NULL && get.ClientAuth != NULL)\r
+                               {\r
+                                       CLIENT_OPTION *old_option = get.ClientOption;\r
+                                       CLIENT_AUTH *old_auth = get.ClientAuth;\r
+\r
+                                       // 接続パラメータの継承\r
+                                       t->ClientOption->ProxyType = old_option->ProxyType;\r
+                                       StrCpy(t->ClientOption->ProxyName, sizeof(t->ClientOption->ProxyName),\r
+                                               old_option->ProxyName);\r
+                                       t->ClientOption->ProxyPort = old_option->ProxyPort;\r
+                                       StrCpy(t->ClientOption->ProxyUsername, sizeof(t->ClientOption->ProxyUsername),\r
+                                               old_option->ProxyUsername);\r
+                                       StrCpy(t->ClientOption->ProxyPassword, sizeof(t->ClientOption->ProxyPassword),\r
+                                               old_option->ProxyPassword);\r
+                                       t->ClientOption->NumRetry = old_option->NumRetry;\r
+                                       t->ClientOption->RetryInterval = old_option->RetryInterval;\r
+                                       t->ClientOption->MaxConnection = old_option->MaxConnection;\r
+                                       t->ClientOption->UseEncrypt = old_option->UseEncrypt;\r
+                                       t->ClientOption->UseCompress = old_option->UseCompress;\r
+                                       t->ClientOption->HalfConnection = old_option->HalfConnection;\r
+                                       t->ClientOption->NoRoutingTracking = old_option->NoRoutingTracking;\r
+                                       StrCpy(t->ClientOption->DeviceName, sizeof(t->ClientOption->DeviceName),\r
+                                               old_option->DeviceName);\r
+                                       t->ClientOption->AdditionalConnectionInterval = old_option->AdditionalConnectionInterval;\r
+                                       t->ClientOption->ConnectionDisconnectSpan = old_option->ConnectionDisconnectSpan;\r
+                                       t->ClientOption->HideStatusWindow = old_option->HideStatusWindow;\r
+                                       t->ClientOption->RequireMonitorMode = old_option->RequireMonitorMode;\r
+                                       t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode;\r
+                                       t->ClientOption->DisableQoS = old_option->DisableQoS;\r
+                                       t->ClientOption->NoTls1 = old_option->NoTls1;\r
+\r
+                                       // 認証データの継承\r
+                                       CiFreeClientAuth(t->ClientAuth);\r
+                                       t->ClientAuth = CopyClientAuth(old_auth);\r
+\r
+                                       // その他の設定\r
+                                       t->StartupAccount = get.StartupAccount;\r
+                                       t->CheckServerCert = get.CheckServerCert;\r
+                                       if (t->ServerCert != NULL)\r
+                                       {\r
+                                               FreeX(t->ServerCert);\r
+                                       }\r
+                                       t->ServerCert = NULL;\r
+                                       if (get.ServerCert != NULL)\r
+                                       {\r
+                                               t->ServerCert = CloneX(get.ServerCert);\r
+                                       }\r
+                                       Copy(t->ShortcutKey, get.ShortcutKey, sizeof(t->ShortcutKey));\r
+                               }\r
+\r
+                               CiFreeClientGetAccount(&get);\r
+                       }\r
+\r
+                       if (CALL(h, CcDeleteAccount(cm->Client, &d)) == false)\r
+                       {\r
+                               CiFreeClientCreateAccount(t);\r
+                               Free(t);\r
+                               return;\r
+                       }\r
+\r
+                       CmRefreshAccountList(hWnd);\r
+               }\r
+       }\r
+\r
+       CmGenerateImportName(hWnd, name, sizeof(name), t->ClientOption->AccountName);\r
+       UniStrCpy(t->ClientOption->AccountName, sizeof(t->ClientOption->AccountName), name);\r
+\r
+       if (overwrite)\r
+       {\r
+               t->ClientOption->FromAdminPack = true;\r
+       }\r
+\r
+       CALL(hWnd, CcCreateAccount(cm->Client, t));\r
+\r
+       CiFreeClientCreateAccount(t);\r
+       Free(t);\r
+\r
+       FreeBuf(b);\r
+\r
+       if (overwrite)\r
+       {\r
+               // VPN 接続を開始する\r
+               CmConnect(hWnd, name);\r
+       }\r
+\r
+       //MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_IMPORT_MESSAGE"), filename, name);\r
+}\r
+\r
+// アカウントのインポート\r
+void CmImportAccount(HWND hWnd)\r
+{\r
+       wchar_t *filename;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // ファイルを開く\r
+       filename = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE"));\r
+       if (filename == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       UniStrCpy(tmp, sizeof(tmp), filename);\r
+       Free(filename);\r
+\r
+       CmImportAccountMain(hWnd, tmp);\r
+}\r
+\r
+// アカウントのコピーの作成\r
+void CmCopyAccount(HWND hWnd, wchar_t *account_name)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       CM_ACCOUNT *a;\r
+       RPC_CLIENT_CREATE_ACCOUNT c;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CmGenerateCopyName(hWnd, tmp, sizeof(tmp), account_name);\r
+\r
+       // アカウント情報を取得\r
+       a = CmGetExistAccountObject(hWnd, account_name);\r
+       if (a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // アカウント名を変更\r
+       UniStrCpy(a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName), tmp);\r
+\r
+       // 書き込み\r
+       Zero(&c, sizeof(c));\r
+       c.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       Copy(c.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));\r
+       c.ClientAuth = CopyClientAuth(a->ClientAuth);\r
+       if (a->ServerCert)\r
+       {\r
+               c.ServerCert = CloneX(a->ServerCert);\r
+       }\r
+       c.CheckServerCert = a->CheckServerCert;\r
+       c.StartupAccount = false;               // スタートアップ属性はコピーしない\r
+\r
+       CALL(hWnd, CcCreateAccount(cm->Client, &c));\r
+       CiFreeClientCreateAccount(&c);\r
+\r
+       CmFreeAccountObject(hWnd, a);\r
+}\r
+\r
+// 仮想 LAN カード名ダイアログ更新\r
+void CmNewVLanDlgUpdate(HWND hWnd)\r
+{\r
+       bool ok = true;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       GetTxtA(hWnd, E_NAME, tmp, sizeof(tmp));\r
+       if (IsSafeStr(tmp) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+       Trim(tmp);\r
+       if (StrLen(tmp) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// 仮想 LAN カード名決定ダイアログプロシージャ\r
+UINT CmNewVLanDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       char *tmp = (char *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               LimitText(hWnd, E_NAME, cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN);\r
+               FormatText(hWnd, S_INFO, cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN);\r
+               CmNewVLanDlgUpdate(hWnd);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (cm->Client->Win9x)\r
+                       {\r
+                               // Windows 9x の場合、確認メッセージを出す\r
+                               if (MsgBox(hWnd, MB_ICONQUESTION | MB_OKCANCEL, _UU("CM_9X_VLAN_INSTALL")) == IDCANCEL)\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       GetTxtA(hWnd, E_NAME, tmp, (cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN) + 1);\r
+                       Trim(tmp);\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_NAME:\r
+                       CmNewVLanDlgUpdate(hWnd);\r
+                       break;\r
+\r
+               case R_USE_DISCONNECT:\r
+                       if (IsChecked(hWnd, R_USE_DISCONNECT))\r
+                       {\r
+                               FocusEx(hWnd, E_DISCONNECT_SPAN);\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
+// 新しい仮想 LAN カード名を決定するダイアログ\r
+char *CmNewVLanDlg(HWND hWnd)\r
+{\r
+       char tmp[MAX_DEVICE_NAME_LEN + 1];\r
+\r
+       if (Dialog(hWnd, D_CM_NEW_VLAN, CmNewVLanDlgProc, tmp) == false)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       return CopyStr(tmp);\r
+}\r
+\r
+// 詳細設定ダイアログ更新\r
+void CmDetailDlgUpdate(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       bool ok = true;\r
+       bool locked;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       locked = a->LockMode;\r
+\r
+       if (a->LinkMode || a->NatMode)\r
+       {\r
+               Disable(hWnd, R_NO_ROUTING);\r
+       }\r
+       else\r
+       {\r
+               if (cm->Client->Unix)\r
+               {\r
+                       Disable(hWnd, R_NO_ROUTING);\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, E_DISCONNECT_SPAN, IsChecked(hWnd, R_USE_DISCONNECT));\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+\r
+       if (locked)\r
+       {\r
+               Disable(hWnd, C_NUM_TCP);\r
+               Disable(hWnd, S_STATIC5);\r
+               Disable(hWnd, S_STATIC8);\r
+               Disable(hWnd, E_INTERVAL);\r
+               Disable(hWnd, S_STATIC9);\r
+               Disable(hWnd, E_DISCONNECT_SPAN);\r
+               Disable(hWnd, S_STATIC10);\r
+               Disable(hWnd, S_STATIC11);\r
+               Disable(hWnd, R_USE_DISCONNECT);\r
+               Disable(hWnd, R_USE_HALF_CONNECTION);\r
+               Disable(hWnd, R_DISABLE_QOS);\r
+               Disable(hWnd, R_USE_ENCRYPT);\r
+               Disable(hWnd, R_USE_COMPRESS);\r
+               Disable(hWnd, R_BRIDGE);\r
+               Disable(hWnd, R_MONITOR);\r
+               Disable(hWnd, R_NO_ROUTING);\r
+       }\r
+}\r
+\r
+// 詳細設定ダイアログプロシージャ\r
+UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_ACCOUNT *a = (CM_ACCOUNT *)param;\r
+       UINT i;\r
+       UINT num;\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
+               // TCP コネクション本数\r
+               for (i = 1;i <= MAX_TCP_CONNECTION;i++)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), L"%u", i);\r
+                       CbAddStr(hWnd, C_NUM_TCP, tmp, i);\r
+               }\r
+               CbSelect(hWnd, C_NUM_TCP, a->ClientOption->MaxConnection);\r
+\r
+               // コネクション確立間隔\r
+               SetInt(hWnd, E_INTERVAL, a->ClientOption->AdditionalConnectionInterval);\r
+\r
+               // 寿命\r
+               SetIntEx(hWnd, E_DISCONNECT_SPAN, a->ClientOption->ConnectionDisconnectSpan);\r
+               Check(hWnd, R_USE_DISCONNECT, a->ClientOption->ConnectionDisconnectSpan != 0);\r
+               Check(hWnd, R_USE_HALF_CONNECTION, a->ClientOption->HalfConnection);\r
+               Check(hWnd, R_USE_ENCRYPT, a->ClientOption->UseEncrypt);\r
+               Check(hWnd, R_USE_COMPRESS, a->ClientOption->UseCompress);\r
+               Check(hWnd, R_NO_ROUTING, a->ClientOption->NoRoutingTracking);\r
+               Check(hWnd, R_DISABLE_QOS, a->ClientOption->DisableQoS);\r
+\r
+               // 接続モードの選択\r
+               if (a->LinkMode == false)\r
+               {\r
+                       Check(hWnd, R_BRIDGE, a->ClientOption->RequireBridgeRoutingMode);\r
+                       Check(hWnd, R_MONITOR, a->ClientOption->RequireMonitorMode);\r
+               }\r
+               else\r
+               {\r
+                       Check(hWnd, R_BRIDGE, true);\r
+                       Check(hWnd, R_MONITOR, false);\r
+\r
+                       SetText(hWnd, S_MODE, _UU("CM_DETAIL_MODE_LINK_STR"));\r
+                       Disable(hWnd, R_BRIDGE);\r
+                       Disable(hWnd, R_MONITOR);\r
+               }\r
+\r
+               CmDetailDlgUpdate(hWnd, a);\r
+               Focus(hWnd, IDOK);\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (IsChecked(hWnd, R_USE_DISCONNECT) && GetInt(hWnd, E_DISCONNECT_SPAN) == 0)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_NO_DISCONNECT_SPAN"));\r
+                               FocusEx(hWnd, E_DISCONNECT_SPAN);\r
+                               break;\r
+                       }\r
+                       num = GetInt(hWnd, C_NUM_TCP);\r
+                       if (num == 0)\r
+                       {\r
+                               break;\r
+                       }\r
+                       if (num == 1 && IsChecked(hWnd, R_USE_HALF_CONNECTION))\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_HALF_MSG"));\r
+                               Focus(hWnd, C_NUM_TCP);\r
+                               break;\r
+                       }\r
+                       if (GetInt(hWnd, E_INTERVAL) < 1)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_TOO_SMALL_INTERVAL"));\r
+                               Focus(hWnd, E_INTERVAL);\r
+                               break;\r
+                       }\r
+\r
+                       a->ClientOption->MaxConnection = num;\r
+                       a->ClientOption->AdditionalConnectionInterval = GetInt(hWnd, E_INTERVAL);\r
+                       if (IsChecked(hWnd, R_USE_DISCONNECT) == false)\r
+                       {\r
+                               a->ClientOption->ConnectionDisconnectSpan = 0;\r
+                       }\r
+                       else\r
+                       {\r
+                               a->ClientOption->ConnectionDisconnectSpan = GetInt(hWnd, E_DISCONNECT_SPAN);\r
+                       }\r
+                       a->ClientOption->HalfConnection = IsChecked(hWnd, R_USE_HALF_CONNECTION);\r
+                       a->ClientOption->UseEncrypt = IsChecked(hWnd, R_USE_ENCRYPT);\r
+                       a->ClientOption->UseCompress = IsChecked(hWnd, R_USE_COMPRESS);\r
+                       a->ClientOption->NoRoutingTracking = IsChecked(hWnd, R_NO_ROUTING);\r
+                       a->ClientOption->DisableQoS = IsChecked(hWnd, R_DISABLE_QOS);\r
+\r
+                       if (a->LinkMode)\r
+                       {\r
+                               a->ClientOption->RequireBridgeRoutingMode = true;\r
+                               a->ClientOption->RequireMonitorMode = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               a->ClientOption->RequireBridgeRoutingMode = IsChecked(hWnd, R_BRIDGE);\r
+                               a->ClientOption->RequireMonitorMode = IsChecked(hWnd, R_MONITOR);\r
+                       }\r
+\r
+                       EndDialog(hWnd, true);\r
+\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case C_NUM_TCP:\r
+               case E_INTERVAL:\r
+               case E_DISCONNECT_SPAN:\r
+               case R_USE_DISCONNECT:\r
+               case R_USE_HALF_CONNECTION:\r
+                       CmDetailDlgUpdate(hWnd, a);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 詳細設定ダイアログ\r
+bool CmDetailDlg(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return Dialog(hWnd, D_CM_DETAIL, CmDetailDlgProc, a);\r
+}\r
+\r
+// アカウント編集ダイアログプロシージャ更新\r
+void CmEditAccountDlgUpdate(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       bool ok = true;\r
+       char str[MAX_SIZE];\r
+       bool locked;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       locked = a->LockMode;\r
+\r
+       if (a->Inited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (a->EditMode)\r
+       {\r
+               Disable(hWnd, E_ACCOUNT_NAME);\r
+       }\r
+\r
+       // 接続設定名\r
+       GetTxt(hWnd, E_ACCOUNT_NAME, a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName));\r
+       UniTrim(a->ClientOption->AccountName);\r
+\r
+       // ホスト名\r
+       GetTxtA(hWnd, E_HOSTNAME, a->ClientOption->Hostname, sizeof(a->ClientOption->Hostname));\r
+       Trim(a->ClientOption->Hostname);\r
+\r
+       // ポート番号\r
+       a->ClientOption->Port = GetInt(hWnd, C_PORT);\r
+\r
+       // HUB 名\r
+       GetTxtA(hWnd,C_HUBNAME, a->ClientOption->HubName, sizeof(a->ClientOption->HubName));\r
+\r
+       // プロキシの種類\r
+       a->ClientOption->ProxyType = PROXY_DIRECT;\r
+       if (IsChecked(hWnd, R_HTTPS))\r
+       {\r
+               a->ClientOption->ProxyType = PROXY_HTTP;\r
+       }\r
+       if (IsChecked(hWnd, R_SOCKS))\r
+       {\r
+               a->ClientOption->ProxyType = PROXY_SOCKS;\r
+       }\r
+\r
+       // サーバー証明書検証\r
+       a->CheckServerCert = IsChecked(hWnd, R_CHECK_CERT);\r
+\r
+       if (a->NatMode)\r
+       {\r
+               Disable(hWnd, R_CHECK_CERT);\r
+               Disable(hWnd, B_TRUST);\r
+       }\r
+\r
+       if (a->HideTrustCert)\r
+       {\r
+               Disable(hWnd, B_TRUST);\r
+       }\r
+\r
+       // デバイス名\r
+       StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), "");\r
+       if (LvIsSelected(hWnd, L_VLAN))\r
+       {\r
+               wchar_t *s = LvGetStr(hWnd, L_VLAN, LvGetSelected(hWnd, L_VLAN), 0);\r
+               if (s != NULL)\r
+               {\r
+                       char str[MAX_SIZE];\r
+                       UniToStr(str, sizeof(str), s);\r
+                       CmPrintNameToVLanName(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), str);\r
+                       Free(s);\r
+               }\r
+       }\r
+\r
+       // ユーザー認証\r
+       a->ClientAuth->AuthType = CbGetSelect(hWnd, C_TYPE);\r
+       GetTxtA(hWnd, E_USERNAME, a->ClientAuth->Username, sizeof(a->ClientAuth->Username));\r
+       Trim(a->ClientAuth->Username);\r
+       switch (a->ClientAuth->AuthType)\r
+       {\r
+       case CLIENT_AUTHTYPE_PASSWORD:\r
+               // パスワード認証\r
+               GetTxtA(hWnd, E_PASSWORD, str, sizeof(str));\r
+               if (StrCmp(str, HIDDEN_PASSWORD) != 0)\r
+               {\r
+                       HashPassword(a->ClientAuth->HashedPassword, a->ClientAuth->Username, str);\r
+               }\r
+               break;\r
+       case CLIENT_AUTHTYPE_PLAIN_PASSWORD:\r
+               // 平文パスワード認証\r
+               GetTxtA(hWnd, E_PASSWORD, str, sizeof(str));\r
+               if (StrCmp(str, HIDDEN_PASSWORD) != 0)\r
+               {\r
+                       StrCpy(a->ClientAuth->PlainPassword, sizeof(a->ClientAuth->PlainPassword), str);\r
+               }\r
+               break;\r
+       }\r
+\r
+       // 再接続オプション\r
+       if ((a->LinkMode || a->NatMode) || a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)\r
+       {\r
+               Disable(hWnd, R_RETRY);\r
+       }\r
+       else\r
+       {\r
+               Enable(hWnd, R_RETRY);\r
+       }\r
+\r
+       if (IsChecked(hWnd, R_RETRY) == false)\r
+       {\r
+               a->ClientOption->NumRetry = 0;\r
+       }\r
+       else\r
+       {\r
+               if (IsChecked(hWnd, R_INFINITE))\r
+               {\r
+                       a->ClientOption->NumRetry = INFINITE;\r
+               }\r
+               else\r
+               {\r
+                       a->ClientOption->NumRetry = GetInt(hWnd, E_RETRY_NUM);\r
+               }\r
+       }\r
+       a->ClientOption->RetryInterval = GetInt(hWnd, E_RETRY_SPAN);\r
+\r
+       a->ClientOption->NoTls1 = IsChecked(hWnd, R_NOTLS1);\r
+\r
+       // 情報判定\r
+       if (UniStrLen(a->ClientOption->AccountName) == 0 && a->NatMode == false)\r
+       {\r
+               ok = false;\r
+       }\r
+       if (StrLen(a->ClientOption->Hostname) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+       if (a->ClientOption->Port == 0 || a->ClientOption->Port >= 65536)\r
+       {\r
+               ok = false;\r
+       }\r
+       if (StrLen(a->ClientOption->HubName) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+       if (StrLen(a->ClientAuth->Username) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+       if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)\r
+       {\r
+               if (a->ClientAuth->ClientK == NULL || a->ClientAuth->ClientX == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)\r
+       {\r
+               if (IsEmptyStr(a->ClientAuth->SecurePrivateKeyName) || IsEmptyStr(a->ClientAuth->SecurePublicCertName))\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       // 表示更新\r
+       if (IsChecked(hWnd, R_RETRY) && IsEnable(hWnd, R_RETRY))\r
+       {\r
+               if (a->LinkMode == false && a->NatMode == false)\r
+               {\r
+                       Enable(hWnd, R_INFINITE);\r
+                       Enable(hWnd, E_RETRY_SPAN);\r
+                       Enable(hWnd, S_RETRY_SPAN_1);\r
+                       Enable(hWnd, S_RETRY_SPAN_2);\r
+               }\r
+               else\r
+               {\r
+                       Disable(hWnd, R_INFINITE);\r
+                       Disable(hWnd, E_RETRY_SPAN);\r
+                       Disable(hWnd, S_RETRY_SPAN_1);\r
+                       Disable(hWnd, S_RETRY_SPAN_2);\r
+               }\r
+               if (IsChecked(hWnd, R_INFINITE) == false)\r
+               {\r
+                       Enable(hWnd, E_RETRY_NUM);\r
+                       Enable(hWnd, S_RETRY_NUM_1);\r
+                       Enable(hWnd, S_RETRY_NUM_2);\r
+                       if (GetInt(hWnd, E_RETRY_NUM) == 0)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       Disable(hWnd, E_RETRY_NUM);\r
+                       Disable(hWnd, S_RETRY_NUM_1);\r
+                       Disable(hWnd, S_RETRY_NUM_2);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, E_RETRY_NUM);\r
+               Disable(hWnd, E_RETRY_SPAN);\r
+               Disable(hWnd, R_INFINITE);\r
+               Disable(hWnd, S_RETRY_NUM_1);\r
+               Disable(hWnd, S_RETRY_NUM_2);\r
+               Disable(hWnd, S_RETRY_SPAN_1);\r
+               Disable(hWnd, S_RETRY_SPAN_2);\r
+       }\r
+\r
+       if (a->NatMode == false)\r
+       {\r
+               if (a->ServerCert == NULL)\r
+               {\r
+                       SetText(hWnd, B_SERVER_CERT, _UU("CM_SERVER_CERT_1"));\r
+                       Disable(hWnd, B_VIEW_SERVER_CERT);\r
+               }\r
+               else\r
+               {\r
+                       SetText(hWnd, B_SERVER_CERT, _UU("CM_SERVER_CERT_2"));\r
+                       Enable(hWnd, B_VIEW_SERVER_CERT);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, B_VIEW_SERVER_CERT);\r
+               Disable(hWnd, B_SERVER_CERT);\r
+       }\r
+\r
+       if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT || a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)\r
+       {\r
+               wchar_t tmp[MAX_SIZE * 2];\r
+               wchar_t issuer[MAX_SIZE];\r
+               wchar_t subject[MAX_SIZE];\r
+               wchar_t expires[MAX_SIZE];\r
+\r
+               SetIcon(hWnd, S_CERT, (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT) ? ICO_CERT : ICO_SECURE);\r
+\r
+               Hide(hWnd, S_PASSWORD);\r
+               Hide(hWnd, E_PASSWORD);\r
+               if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)\r
+               {\r
+                       if (a->ClientAuth->ClientX != NULL)\r
+                       {\r
+                               Enable(hWnd, B_VIEW_CLIENT_CERT);\r
+                               SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_CLIENT_CERT_2"));\r
+                               GetPrintNameFromName(issuer, sizeof(issuer), a->ClientAuth->ClientX->issuer_name);\r
+                               GetPrintNameFromName(subject, sizeof(subject), a->ClientAuth->ClientX->subject_name);\r
+                               GetDateStrEx64(expires, sizeof(expires), SystemToLocal64(a->ClientAuth->ClientX->notAfter), NULL);\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_CERT_INFO"), subject, issuer, expires);\r
+                       }\r
+                       else\r
+                       {\r
+                               Disable(hWnd, B_VIEW_CLIENT_CERT);\r
+                               SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_CLIENT_CERT_1"));\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("CM_NO_CERT"));\r
+                       }\r
+                       SetText(hWnd, B_VIEW_CLIENT_CERT, _UU("CM_VIEW_CLIENT_CERT"));\r
+\r
+                       Enable(hWnd, B_REGIST_CLIENT_CERT);\r
+               }\r
+               else\r
+               {\r
+                       if (IsEmptyStr(a->ClientAuth->SecurePrivateKeyName) || IsEmptyStr(a->ClientAuth->SecurePublicCertName))\r
+                       {\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("CM_NO_SECURE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_CERT_SECURE_INFO"),\r
+                                       a->ClientAuth->SecurePublicCertName, a->ClientAuth->SecurePrivateKeyName);\r
+                       }\r
+\r
+                       SetText(hWnd, B_VIEW_CLIENT_CERT, _UU("CM_SELECT_SECURE_DEVICE"));\r
+                       SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_SELECT_CERT_INCARD"));\r
+                       Enable(hWnd, B_VIEW_CLIENT_CERT);\r
+\r
+                       if (SmGetCurrentSecureIdFromReg() == 0)\r
+                       {\r
+                               Disable(hWnd, B_REGIST_CLIENT_CERT);\r
+                       }\r
+                       else\r
+                       {\r
+                               Enable(hWnd, B_REGIST_CLIENT_CERT);\r
+                       }\r
+               }\r
+               SetText(hWnd, S_CERT_INFO, tmp);\r
+               Show(hWnd, S_CERT);\r
+               Show(hWnd, S_CERT_INFO);\r
+               Show(hWnd, B_VIEW_CLIENT_CERT);\r
+               Show(hWnd, B_REGIST_CLIENT_CERT);\r
+       }\r
+       else\r
+       {\r
+               if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_ANONYMOUS)\r
+               {\r
+                       Hide(hWnd, S_PASSWORD);\r
+                       Hide(hWnd, E_PASSWORD);\r
+               }\r
+               else\r
+               {\r
+                       Show(hWnd, S_PASSWORD);\r
+                       Show(hWnd, E_PASSWORD);\r
+               }\r
+               Hide(hWnd, S_CERT);\r
+               Hide(hWnd, S_CERT_INFO);\r
+               Hide(hWnd, B_VIEW_CLIENT_CERT);\r
+               Hide(hWnd, B_REGIST_CLIENT_CERT);\r
+       }\r
+\r
+       if (a->ClientOption->ProxyType != PROXY_DIRECT)\r
+       {\r
+               Enable(hWnd, B_PROXY_CONFIG);\r
+               if (StrLen(a->ClientOption->ProxyName) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+               if (a->ClientOption->ProxyPort == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Disable(hWnd, B_PROXY_CONFIG);\r
+       }\r
+\r
+       if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)\r
+       {\r
+               bool b = true;\r
+\r
+               if (ok == false)\r
+               {\r
+                       b = false;\r
+               }\r
+\r
+               if (a->LinkMode == false && a->NatMode == false)\r
+               {\r
+                       SetEnable(hWnd, B_CHANGE_PASSWORD, b);\r
+                       SetEnable(hWnd, S_CHANGE_PASSWORD, b);\r
+                       Show(hWnd, B_CHANGE_PASSWORD);\r
+                       Show(hWnd, S_CHANGE_PASSWORD);\r
+               }\r
+               else\r
+               {\r
+                       Hide(hWnd, B_CHANGE_PASSWORD);\r
+                       Hide(hWnd, S_CHANGE_PASSWORD);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Hide(hWnd, B_CHANGE_PASSWORD);\r
+               Hide(hWnd, S_CHANGE_PASSWORD);\r
+       }\r
+\r
+       if ((StrLen(a->ClientOption->DeviceName) == 0) && (a->LinkMode == false && a->NatMode == false))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (a->LinkMode || a->NatMode)\r
+       {\r
+               Disable(hWnd, L_VLAN);\r
+       }\r
+\r
+       if (a->EditMode == false)\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               GetTxtA(hWnd, E_HOSTNAME, tmp, sizeof(tmp));\r
+               Trim(tmp);\r
+\r
+               if (StartWith(tmp, "127.") || (StrCmpi(tmp, "localhost") == 0))\r
+               {\r
+                       if (a->Flag1 == false)\r
+                       {\r
+                               a->Flag1 = true;\r
+                               a->ClientOption->UseEncrypt = a->ClientOption->UseCompress = false;\r
+                               a->ClientOption->MaxConnection = 1;\r
+                       }\r
+               }\r
+       }\r
+\r
+       a->ClientOption->HideStatusWindow = IsChecked(hWnd, R_HIDE);\r
+       a->ClientOption->HideNicInfoWindow = IsChecked(hWnd, R_HIDE2);\r
+\r
+       if (locked)\r
+       {\r
+               SetEnable(hWnd, E_HOSTNAME, false);\r
+               SetEnable(hWnd, C_PORT, false);\r
+               SetEnable(hWnd, C_HUBNAME, false);\r
+               SetEnable(hWnd, S_STATIC2, false);\r
+               SetEnable(hWnd, S_STATIC3, false);\r
+               SetEnable(hWnd, S_STATIC4, false);\r
+               SetEnable(hWnd, S_STATIC5, false);\r
+               SetEnable(hWnd, S_STATIC66, false);\r
+               SetEnable(hWnd, S_STATIC7, false);\r
+               SetEnable(hWnd, S_STATIC11, false);\r
+               SetEnable(hWnd, R_CHECK_CERT, false);\r
+               SetEnable(hWnd, B_TRUST, false);\r
+               SetEnable(hWnd, B_SERVER_CERT, false);\r
+               SetEnable(hWnd, B_VIEW_SERVER_CERT, false);\r
+               SetEnable(hWnd, R_RETRY, false);\r
+               SetEnable(hWnd, S_RETRY_NUM_1, false);\r
+               SetEnable(hWnd, E_RETRY_NUM, false);\r
+               SetEnable(hWnd, S_RETRY_NUM_2, false);\r
+               SetEnable(hWnd, S_RETRY_SPAN_1, false);\r
+               SetEnable(hWnd, E_RETRY_SPAN, false);\r
+               SetEnable(hWnd, S_RETRY_SPAN_2, false);\r
+               SetEnable(hWnd, R_INFINITE, false);\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// アカウント編集ダイアログ初期化\r
+void CmEditAccountDlgInit(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       RPC_CLIENT_ENUM_VLAN v;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (a->LockMode)\r
+       {\r
+               SetText(hWnd, S_STATIC1, _UU("CM_EASY_ACCOUNT_WARNING"));\r
+       }\r
+\r
+       // 接続設定名\r
+       if (a->EditMode || a->NatMode)\r
+       {\r
+               Disable(hWnd, E_ACCOUNT_NAME);\r
+       }\r
+\r
+       if (a->NatMode || a->LinkMode)\r
+       {\r
+               Hide(hWnd, R_HIDE);\r
+               Hide(hWnd, R_HIDE2);\r
+       }\r
+\r
+       Check(hWnd, R_HIDE, a->ClientOption->HideStatusWindow);\r
+       Check(hWnd, R_HIDE2, a->ClientOption->HideNicInfoWindow);\r
+\r
+       if (a->NatMode)\r
+       {\r
+               Hide(hWnd, E_ACCOUNT_NAME);\r
+               Hide(hWnd, S_ACCOUNT_NAME);\r
+       }\r
+\r
+       if ((cm != NULL && cm->server_name != NULL) || a->LinkMode)\r
+       {\r
+               Hide(hWnd, B_IE);\r
+       }\r
+\r
+       SetText(hWnd, E_ACCOUNT_NAME, a->ClientOption->AccountName);\r
+\r
+       // ホスト名\r
+       SetTextA(hWnd, E_HOSTNAME, a->ClientOption->Hostname);\r
+       StrCpy(a->old_server_name, sizeof(a->old_server_name), a->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
+       SetInt(hWnd, C_PORT, a->ClientOption->Port);\r
+\r
+       // 仮想 HUB 名\r
+       CbSetHeight(hWnd, C_HUBNAME, 18);\r
+       SetTextA(hWnd, C_HUBNAME, a->ClientOption->HubName);\r
+\r
+       // プロキシの種類\r
+       Check(hWnd, R_DIRECT_TCP, a->ClientOption->ProxyType == PROXY_DIRECT);\r
+       Check(hWnd, R_HTTPS, a->ClientOption->ProxyType == PROXY_HTTP);\r
+       Check(hWnd, R_SOCKS, a->ClientOption->ProxyType == PROXY_SOCKS);\r
+\r
+       // サーバー証明書の検証\r
+       Check(hWnd, R_CHECK_CERT, a->CheckServerCert);\r
+\r
+       // LAN カード一覧\r
+       if (a->NatMode == false && a->LinkMode == false)\r
+       {\r
+               Zero(&v, sizeof(v));\r
+               CcEnumVLan(cm->Client, &v);\r
+               LvInit(hWnd, L_VLAN);\r
+               LvInsertColumn(hWnd, L_VLAN, 0, L"DeviceName", 345);\r
+               for (i = 0;i < v.NumItem;i++)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       char str[MAX_SIZE];\r
+                       CmVLanNameToPrintName(str, sizeof(str), v.Items[i]->DeviceName);\r
+                       StrToUni(tmp, sizeof(tmp), str);\r
+                       LvInsert(hWnd, L_VLAN, ICO_NIC_ONLINE, NULL, 1, tmp);\r
+               }\r
+//             LvAutoSize(hWnd, L_VLAN);\r
+\r
+               if (v.NumItem == 1)\r
+               {\r
+                       // 仮想 LAN カードが 1 枚だけのときはそれを最初から選択する\r
+                       LvSelect(hWnd, L_VLAN, 0);\r
+               }\r
+\r
+               CiFreeClientEnumVLan(&v);\r
+       }\r
+\r
+       // LAN カードを選択する\r
+       if (StrLen(a->ClientOption->DeviceName) != 0)\r
+       {\r
+               char str[MAX_SIZE];\r
+               wchar_t tmp[MAX_SIZE];\r
+               UINT index;\r
+               CmVLanNameToPrintName(str, sizeof(str), a->ClientOption->DeviceName);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               index = LvSearchStr(hWnd, L_VLAN, 0, tmp);\r
+               if (index != INFINITE)\r
+               {\r
+                       LvSelect(hWnd, L_VLAN, index);\r
+               }\r
+       }\r
+\r
+       // 認証の種類\r
+       CbSetHeight(hWnd, C_TYPE, 18);\r
+       CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_0"), CLIENT_AUTHTYPE_ANONYMOUS);\r
+       CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);\r
+       CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);\r
+\r
+       if (a->HideClientCertAuth == false)\r
+       {\r
+               // HideClientCertAuth が true の場合は証明書認証は利用できない\r
+               CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_3"), CLIENT_AUTHTYPE_CERT);\r
+       }\r
+\r
+       if (a->HideSecureAuth == false)\r
+       {\r
+               // スマートカードを利用した認証\r
+               CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_4"), CLIENT_AUTHTYPE_SECURE);\r
+       }\r
+\r
+       // 認証の選択\r
+       CbSelect(hWnd, C_TYPE, a->ClientAuth->AuthType);\r
+\r
+       // ユーザー名\r
+       SetTextA(hWnd, E_USERNAME, a->ClientAuth->Username);\r
+\r
+       // パスワード\r
+       if (a->EditMode)\r
+       {\r
+               SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);\r
+       }\r
+\r
+       // 再接続回数\r
+       if (a->ClientOption->NumRetry == 0)\r
+       {\r
+               Check(hWnd, R_RETRY, false);\r
+       }\r
+       else\r
+       {\r
+               Check(hWnd, R_RETRY, true);\r
+               if (a->ClientOption->NumRetry == INFINITE)\r
+               {\r
+                       Check(hWnd, R_INFINITE, true);\r
+               }\r
+               else\r
+               {\r
+                       Check(hWnd, R_INFINITE, false);\r
+                       SetInt(hWnd, E_RETRY_NUM, a->ClientOption->NumRetry);\r
+               }\r
+       }\r
+       SetIntEx(hWnd, E_RETRY_SPAN, a->ClientOption->RetryInterval);\r
+\r
+       Check(hWnd, R_NOTLS1, a->ClientOption->NoTls1);\r
+\r
+       // タイトル\r
+       if (a->NatMode == false)\r
+       {\r
+               if (a->EditMode == false)\r
+               {\r
+                       SetText(hWnd, 0, _UU("CM_ACCOUNT_TITLE_1"));\r
+                       FocusEx(hWnd, E_ACCOUNT_NAME);\r
+               }\r
+               else\r
+               {\r
+                       SetText(hWnd, 0, _UU("CM_ACCOUNT_TITLE_2"));\r
+                       FormatText(hWnd, 0, a->ClientOption->AccountName);\r
+                       FocusEx(hWnd, E_HOSTNAME);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               SetText(hWnd, 0, _UU("NM_ACCOUNT_TITLE"));\r
+               FocusEx(hWnd, E_HOSTNAME);\r
+       }\r
+\r
+       if (a->LinkMode || a->NatMode)\r
+       {\r
+               Hide(hWnd, L_VLAN);\r
+\r
+               if (a->NatMode == false)\r
+               {\r
+                       SetText(hWnd, S_VLAN_GROUP, _UU("SM_LINK_POLICY_GROUP"));\r
+                       Show(hWnd, S_POLICY_1);\r
+                       Show(hWnd, S_POLICY_2);\r
+                       Show(hWnd, B_POLICY);\r
+               }\r
+               else\r
+               {\r
+                       Hide(hWnd, S_VLAN_GROUP);\r
+                       Show(hWnd, S_ROUTER_LOGO);\r
+               }\r
+       }\r
+\r
+       // 表示更新\r
+       a->Inited = true;\r
+       CmEditAccountDlgUpdate(hWnd, a);\r
+}\r
+\r
+// アカウント編集ダイアログプロシージャ\r
+UINT CmEditAccountDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_ACCOUNT *a = (CM_ACCOUNT *)param;\r
+       NMHDR *n;\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
+               CmEditAccountDlgInit(hWnd, a);\r
+               if (a->EditMode == false && a->LinkMode == false && a->NatMode == false)\r
+               {\r
+                       SetTimer(hWnd, 1, 100, NULL);\r
+               }\r
+               break;\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       {\r
+                               CM_INTERNET_SETTING s;\r
+\r
+                               KillTimer(hWnd, 1);\r
+\r
+                               Zero(&s, sizeof(s));\r
+                               CmGetSystemInternetSetting(&s);\r
+\r
+                               if (s.ProxyType != PROXY_DIRECT)\r
+                               {\r
+                                       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO,\r
+                                               _UU("CM_WOULDYOULOAD_IE_PROXY"),\r
+                                               s.ProxyHostName) == IDYES)\r
+                                       {\r
+                                               Command(hWnd, B_IE);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_ACCOUNT_NAME:\r
+               case E_HOSTNAME:\r
+               case C_PORT:\r
+               case C_HUBNAME:\r
+               case R_DIRECT_TCP:\r
+               case R_HTTPS:\r
+               case R_SOCKS:\r
+               case R_CHECK_CERT:\r
+               case C_TYPE:\r
+               case E_USERNAME:\r
+               case E_PASSWORD:\r
+               case R_RETRY:\r
+               case E_RETRY_NUM:\r
+               case E_RETRY_SPAN:\r
+               case R_INFINITE:\r
+                       CmEditAccountDlgUpdate(hWnd, a);\r
+                       break;\r
+               }\r
+               switch (HIWORD(wParam))\r
+               {\r
+               case EN_KILLFOCUS:\r
+                       switch (LOWORD(wParam))\r
+                       {\r
+                       case E_HOSTNAME:\r
+                               CmEditAccountDlgStartEnumHub(hWnd, a);\r
+                               break;\r
+                       }\r
+                       break;\r
+               case BN_KILLFOCUS:\r
+                       switch (LOWORD(wParam))\r
+                       {\r
+                       case R_DIRECT_TCP:\r
+                       case R_HTTPS:\r
+                       case R_SOCKS:\r
+                               CmEditAccountDlgStartEnumHub(hWnd, a);\r
+                               break;\r
+                       }\r
+                       break;\r
+               case CBN_KILLFOCUS:\r
+                       switch (LOWORD(wParam))\r
+                       {\r
+                       case C_PORT:\r
+                               CmEditAccountDlgStartEnumHub(hWnd, a);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               if (HIWORD(wParam) == 0)\r
+               {\r
+                       CmEditAccountDlgUpdate(hWnd, a);\r
+               }\r
+               switch (wParam)\r
+               {\r
+               case B_POLICY:\r
+                       // ポリシー\r
+                       if (a->LinkMode || a->NatMode)\r
+                       {\r
+                               a->Policy.Access = true;\r
+                               a->Policy.MonitorPort = false;\r
+                               SmPolicyDlgEx2(hWnd, &a->Policy, _UU("SM_LINK_POLICY_CAPTION"), true, a->PolicyVer);\r
+                               a->Policy.Access = true;\r
+                               a->Policy.MonitorPort = false;\r
+                       }\r
+                       break;\r
+               case IDOK:\r
+                       CmEditAccountDlgUpdate(hWnd, a);\r
+                       CmEditAccountDlgOnOk(hWnd, a);\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               case B_PROXY_CONFIG:\r
+                       // プロキシ設定\r
+                       if (CmProxyDlg(hWnd, a->ClientOption))\r
+                       {\r
+                               UINT n = GetInt(hWnd, C_PORT);\r
+                               if (a->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
+                               CmEditAccountDlgStartEnumHub(hWnd, a);\r
+                               CmEditAccountDlgUpdate(hWnd, a);\r
+                       }\r
+                       break;\r
+               case B_IE:\r
+                       // IE の設定を使用する\r
+                       if(cm->server_name == NULL)\r
+                       {\r
+                               CmProxyDlgUseForIE(hWnd, a->ClientOption);\r
+                               CmEditAccountDlgUpdate(hWnd, a);\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PROXY_FROM_IE"));\r
+                       }\r
+                       break;\r
+               case B_TRUST:\r
+                       // CA\r
+                       if (a->LinkMode == false)\r
+                       {\r
+                               CmTrustDlg(hWnd);\r
+                       }\r
+                       else\r
+                       {\r
+                               SmCaDlg(hWnd, a->Hub);\r
+                       }\r
+                       break;\r
+               case B_SERVER_CERT:\r
+                       // サーバー証明書登録 / 削除\r
+                       if (a->ServerCert == NULL)\r
+                       {\r
+                               if (CmLoadXFromFileOrSecureCard(hWnd, &x))\r
+                               {\r
+                                       a->ServerCert = x;\r
+                                       CmEditAccountDlgUpdate(hWnd, a);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_SERVER_CERT")) == IDYES)\r
+                               {\r
+                                       FreeX(a->ServerCert);\r
+                                       a->ServerCert = NULL;\r
+                                       CmEditAccountDlgUpdate(hWnd, a);\r
+                               }\r
+                       }\r
+                       break;\r
+               case B_VIEW_SERVER_CERT:\r
+                       // サーバー証明書表示\r
+                       if (a->ServerCert != NULL)\r
+                       {\r
+                               X *issuer = CmGetIssuer(a->ServerCert);\r
+                               CertDlg(hWnd, a->ServerCert, issuer, true);\r
+                               FreeX(issuer);\r
+                       }\r
+                       break;\r
+               case B_VIEW_CLIENT_CERT:\r
+                       if (a->ClientAuth->AuthType != CLIENT_AUTHTYPE_SECURE)\r
+                       {\r
+                               // クライアント証明書表示\r
+                               if (a->ClientAuth->ClientX != NULL)\r
+                               {\r
+                                       X *issuer = CmGetIssuer(a->ClientAuth->ClientX);\r
+                                       CertDlg(hWnd, a->ClientAuth->ClientX, issuer, true);\r
+                                       FreeX(issuer);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               UINT id;\r
+                               // スマートカードの種類の選択\r
+                               SmSelectSecureId(hWnd);\r
+                               id = SmGetCurrentSecureIdFromReg();\r
+                               if (id != 0)\r
+                               {\r
+                                       if (cm->server_name == NULL)\r
+                                       {\r
+                                               RPC_USE_SECURE t;\r
+\r
+                                               Zero(&t, sizeof(t));\r
+                                               t.DeviceId = id;\r
+                                               CcUseSecure(cm->Client, &t);\r
+                                       }\r
+                               }\r
+                               CmEditAccountDlgUpdate(hWnd, a);\r
+                       }\r
+                       break;\r
+               case B_REGIST_CLIENT_CERT:\r
+                       if (a->ClientAuth->AuthType != CLIENT_AUTHTYPE_SECURE)\r
+                       {\r
+                               // クライアント証明書登録 / 削除\r
+                               if (a->ClientAuth->ClientX == NULL)\r
+                               {\r
+                                       if (CmLoadXAndK(hWnd, &x, &k))\r
+                                       {\r
+                                               a->ClientAuth->ClientX = x;\r
+                                               a->ClientAuth->ClientK = k;\r
+                                               CmEditAccountDlgUpdate(hWnd, a);\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_CLIENT_CERT")) == IDYES)\r
+                                       {\r
+                                               FreeX(a->ClientAuth->ClientX);\r
+                                               FreeK(a->ClientAuth->ClientK);\r
+                                               a->ClientAuth->ClientX = NULL;\r
+                                               a->ClientAuth->ClientK = NULL;\r
+                                               CmEditAccountDlgUpdate(hWnd, a);\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               char cert[MAX_SECURE_DEVICE_FILE_LEN + 1], priv[MAX_SECURE_DEVICE_FILE_LEN + 1];\r
+\r
+                               // スマートカード内証明書の選択\r
+                               if (SmSelectKeyPairEx(hWnd, cert, sizeof(cert), priv, sizeof(priv), CmGetSecureBitmapId(a->ClientOption->Hostname)))\r
+                               {\r
+                                       StrCpy(a->ClientAuth->SecurePublicCertName, sizeof(a->ClientAuth->SecurePublicCertName), cert);\r
+                                       StrCpy(a->ClientAuth->SecurePrivateKeyName, sizeof(a->ClientAuth->SecurePrivateKeyName), priv);\r
+                                       CmEditAccountDlgUpdate(hWnd, a);\r
+                               }\r
+                       }\r
+                       break;\r
+               case B_DETAIL:\r
+                       // 高度な通信設定\r
+                       if (CmDetailDlg(hWnd, a))\r
+                       {\r
+                               CmEditAccountDlgUpdate(hWnd, a);\r
+                       }\r
+                       break;\r
+               case B_CHANGE_PASSWORD:\r
+                       // パスワードの変更\r
+                       CmChangePassword(hWnd, a->ClientOption, a->ClientOption->HubName,\r
+                               a->ClientAuth->Username);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       case WM_NOTIFY:\r
+               n = (NMHDR *)lParam;\r
+               switch (n->idFrom)\r
+               {\r
+               case L_VLAN:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               CmEditAccountDlgUpdate(hWnd, a);\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// プロキシサーバー設定更新\r
+void CmProxyDlgUpdate(HWND hWnd, CLIENT_OPTION *a)\r
+{\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsEmpty(hWnd, E_HOSTNAME))\r
+       {\r
+               ok = false;\r
+       }\r
+       if (GetInt(hWnd, C_PORT) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// プロキシサーバー設定ダイアログc\r
+UINT CmProxyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CLIENT_OPTION *a = (CLIENT_OPTION *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SetTextA(hWnd, E_HOSTNAME, a->ProxyName);\r
+               CbSetHeight(hWnd, C_PORT, 18);\r
+               CbAddStr(hWnd, C_PORT, L"8080", 0);\r
+               CbAddStr(hWnd, C_PORT, L"1080", 0);\r
+               CbAddStr(hWnd, C_PORT, L"80", 0);\r
+               CbAddStr(hWnd, C_PORT, L"3128", 0);\r
+               CbAddStr(hWnd, C_PORT, L"443", 0);\r
+               CbAddStr(hWnd, C_PORT, L"9821", 0);\r
+               CbAddStr(hWnd, C_PORT, L"9801", 0);\r
+               SetIntEx(hWnd, C_PORT, a->ProxyPort);\r
+               SetTextA(hWnd, E_USERNAME, a->ProxyUsername);\r
+               SetTextA(hWnd, E_PASSWORD, a->ProxyPassword);\r
+               if (a->ProxyPort == 0)\r
+               {\r
+                       if (a->ProxyType == PROXY_HTTP)\r
+                       {\r
+                               SetInt(hWnd, C_PORT, 8080);\r
+                       }\r
+                       else\r
+                       {\r
+                               SetInt(hWnd, C_PORT, 1080);\r
+                       }\r
+               }\r
+               CmProxyDlgUpdate(hWnd, a);\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_HOSTNAME:\r
+               case C_PORT:\r
+               case E_USERNAME:\r
+               case E_PASSWORD:\r
+                       CmProxyDlgUpdate(hWnd, a);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       GetTxtA(hWnd, E_HOSTNAME, a->ProxyName, sizeof(a->ProxyName));\r
+                       GetTxtA(hWnd, E_USERNAME, a->ProxyUsername, sizeof(a->ProxyUsername));\r
+                       GetTxtA(hWnd, E_PASSWORD, a->ProxyPassword, sizeof(a->ProxyPassword));\r
+                       a->ProxyPort = GetInt(hWnd, C_PORT);\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// プロキシサーバー設定\r
+bool CmProxyDlg(HWND hWnd, CLIENT_OPTION *a)\r
+{\r
+       // 引数チェック\r
+       if (a == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return Dialog(hWnd, D_CM_PROXY, CmProxyDlgProc, a);\r
+}\r
+\r
+// 指定した証明書の署名者がわかれば取得する\r
+X *CmGetIssuer(X *x)\r
+{\r
+       RPC_GET_ISSUER a;\r
+       X *ret;\r
+       // 引数チェック\r
+       if (x == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       a.x = CloneX(x);\r
+       if (CALLEX(cm->hMainWnd, CcGetIssuer(cm->Client, &a)) == 0)\r
+       {\r
+               ret = CloneX(a.issuer_x);\r
+       }\r
+       else\r
+       {\r
+               ret = NULL;\r
+       }\r
+\r
+       CiFreeGetIssuer(&a);\r
+\r
+       return ret;\r
+}\r
+\r
+// ダイアログ初期化\r
+void CmLoadXFromFileOrSecureCardDlgInit(HWND hWnd, CM_LOADX *p)\r
+{\r
+       UINT current;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       current = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "CertLoadSource");\r
+\r
+       Check(hWnd, R_FROM_FILE, current == 0);\r
+       Check(hWnd, R_FROM_SECURE, current != 0);\r
+\r
+       SetFont(hWnd, S_INFO, Font(0, true));\r
+\r
+       CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);\r
+}\r
+\r
+// ダイアログコントロール更新\r
+void CmLoadXFromFileOrSecureCardDlgUpdate(HWND hWnd, CM_LOADX *p)\r
+{\r
+       SECURE_DEVICE *dev;\r
+       wchar_t tmp[MAX_SIZE];\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == 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_FROM_SECURE))\r
+       {\r
+               if (dev == NULL)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+       SetEnable(hWnd, B_SELECT, IsChecked(hWnd, R_FROM_SECURE));\r
+       SetEnable(hWnd, S_CERT, IsChecked(hWnd, R_FROM_SECURE));\r
+       SetEnable(hWnd, S_FILE, IsChecked(hWnd, R_FROM_FILE));\r
+}\r
+\r
+// 証明書読み込み選択ダイアログプロシージャ\r
+UINT CmLoadXFromFileOrSecureCardDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_LOADX *p = (CM_LOADX *)param;\r
+       X *x;\r
+       UINT current;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               CmLoadXFromFileOrSecureCardDlgInit(hWnd, p);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       current = (IsChecked(hWnd, R_FROM_FILE)) ? 0 : 1;\r
+                       MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "CertLoadSource", current);\r
+\r
+                       if (current == 0)\r
+                       {\r
+                               // ファイルから\r
+                               if (CmLoadX(hWnd, &x))\r
+                               {\r
+                                       p->x = x;\r
+                                       EndDialog(hWnd, true);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               // スマートカードから\r
+                               char name[MAX_SIZE];\r
+\r
+                               // カード内の証明書名を選択\r
+                               if (SmSelectKeyPair(hWnd, name, sizeof(name), NULL, 0))\r
+                               {\r
+                                       // 読み込み\r
+                                       WINUI_SECURE_BATCH batch[] =\r
+                                       {\r
+                                               {WINUI_SECURE_READ_CERT, name, true, NULL, NULL, NULL, NULL, NULL, NULL},\r
+                                       };\r
+\r
+                                       // 読み込み実行\r
+                                       if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), SmGetCurrentSecureIdFromReg(), 0))\r
+                                       {\r
+                                               // 成功\r
+                                               p->x = batch[0].OutputX;\r
+                                               EndDialog(hWnd, true);\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case R_FROM_FILE:\r
+                       CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);\r
+                       break;\r
+\r
+               case R_FROM_SECURE:\r
+                       CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);\r
+                       break;\r
+\r
+               case B_SELECT:\r
+                       SmSelectSecureId(hWnd);\r
+                       CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, 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
+// 証明書をスマートカードかファイルから読み込む\r
+bool CmLoadXFromFileOrSecureCard(HWND hWnd, X **x)\r
+{\r
+       CM_LOADX p;\r
+       // 引数チェック\r
+       if (x == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&p, sizeof(p));\r
+       if (Dialog(hWnd, D_CM_LOAD_X, CmLoadXFromFileOrSecureCardDlgProc, &p) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       *x = p.x;\r
+\r
+       return true;\r
+}\r
+\r
+// 証明書を読み込む\r
+bool CmLoadX(HWND hWnd, X **x)\r
+{\r
+       return CmLoadXEx(hWnd, x, NULL, 0);\r
+}\r
+bool CmLoadXEx(HWND hWnd, X **x, char *filename, UINT size)\r
+{\r
+       wchar_t *filename_w = CopyStrToUni(filename);\r
+       bool ret;\r
+\r
+       ret = CmLoadXExW(hWnd, x, filename_w, size);\r
+\r
+       Free(filename_w);\r
+\r
+       return ret;\r
+}\r
+bool CmLoadXExW(HWND hWnd, X **x, wchar_t *filename, UINT size)\r
+{\r
+       wchar_t *s;\r
+       bool is_p12;\r
+       wchar_t tmp[MAX_SIZE];\r
+       K *k;\r
+       // 引数チェック\r
+       if (x == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       // 証明書を読み込む\r
+       s = OpenDlg(hWnd, _UU("DLG_CERT_OR_P12_FILTER"), _UU("DLG_OPEN_CERT"));\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+       UniStrCpy(tmp, sizeof(tmp), s);\r
+       if (filename != NULL)\r
+       {\r
+               UniStrCpy(filename, size, tmp);\r
+       }\r
+       Free(s);\r
+       if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))\r
+       {\r
+               is_p12 = true;\r
+       }\r
+       else\r
+       {\r
+               is_p12 = false;\r
+       }\r
+\r
+       if (is_p12)\r
+       {\r
+               // PKCS#12 の処理\r
+               BUF *b = ReadDumpW(tmp);\r
+               P12 *p12;\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       return false;\r
+               }\r
+               p12 = BufToP12(b);\r
+               if (p12 == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                       FreeBuf(b);\r
+                       return false;\r
+               }\r
+               if (IsEncryptedP12(p12) == false)\r
+               {\r
+                       if (ParseP12(p12, x, &k, NULL) == false)\r
+                       {\r
+                               MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                               FreeP12(p12);\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       char password[MAX_SIZE];\r
+                       if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)\r
+                       {\r
+                               FreeP12(p12);\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (ParseP12(p12, x, &k, password) == false)\r
+                               {\r
+                                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                                       FreeP12(p12);\r
+                                       FreeBuf(b);\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
+               FreeP12(p12);\r
+               FreeBuf(b);\r
+               FreeK(k);\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               // X509 の処理\r
+               BUF *b = ReadDumpW(tmp);\r
+               X *x509;\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               x509 = BufToX(b, IsBase64(b));\r
+               FreeBuf(b);\r
+               if (x509 == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               *x = x509;\r
+               return true;\r
+       }\r
+}\r
+\r
+// 秘密鍵を読み込む\r
+bool CmLoadK(HWND hWnd, K **k)\r
+{\r
+       return CmLoadKEx(hWnd, k, NULL, 0);\r
+}\r
+bool CmLoadKEx(HWND hWnd, K **k, char *filename, UINT size)\r
+{\r
+       wchar_t *filename_w = CopyStrToUni(filename);\r
+       bool ret;\r
+\r
+       ret = CmLoadKExW(hWnd, k, filename_w, size);\r
+\r
+       Free(filename_w);\r
+\r
+       return ret;\r
+}\r
+bool CmLoadKExW(HWND hWnd, K **k, wchar_t *filename, UINT size)\r
+{\r
+       wchar_t *s;\r
+       bool is_p12;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (k == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       // 証明書を読み込む\r
+       s = OpenDlg(hWnd, _UU("DLG_KEY_OR_P12_FILTER"), _UU("DLG_OPEN_KEY"));\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+       UniStrCpy(tmp, sizeof(tmp), s);\r
+       Free(s);\r
+       if (filename != NULL)\r
+       {\r
+               UniStrCpy(filename, size, tmp);\r
+       }\r
+       if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))\r
+       {\r
+               is_p12 = true;\r
+       }\r
+       else\r
+       {\r
+               is_p12 = false;\r
+       }\r
+\r
+       if (is_p12)\r
+       {\r
+               // PKCS#12 の処理\r
+               BUF *b = ReadDumpW(tmp);\r
+               P12 *p12;\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       return false;\r
+               }\r
+               p12 = BufToP12(b);\r
+               if (p12 == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                       FreeBuf(b);\r
+                       return false;\r
+               }\r
+               if (IsEncryptedP12(p12) == false)\r
+               {\r
+                       X *x;\r
+                       if (ParseP12(p12, &x, k, NULL) == false)\r
+                       {\r
+                               MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                               FreeP12(p12);\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+\r
+                       FreeX(x);\r
+               }\r
+               else\r
+               {\r
+                       char password[MAX_SIZE];\r
+                       if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)\r
+                       {\r
+                               FreeP12(p12);\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               X *x;\r
+                               if (ParseP12(p12, &x, k, password) == false)\r
+                               {\r
+                                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                                       FreeP12(p12);\r
+                                       FreeBuf(b);\r
+                                       return false;\r
+                               }\r
+\r
+                               FreeX(x);\r
+                       }\r
+               }\r
+               FreeP12(p12);\r
+               FreeBuf(b);\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               // 秘密鍵の処理\r
+               BUF *b = ReadDumpW(tmp);\r
+               K *key;\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               if (IsEncryptedK(b, true) == false)\r
+               {\r
+                       key = BufToK(b, true, IsBase64(b), NULL);\r
+               }\r
+               else\r
+               {\r
+                       char pass[MAX_SIZE];\r
+                       if (PassphraseDlg(hWnd, pass, sizeof(pass), b, false) == false)\r
+                       {\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+                       key = BufToK(b, true, IsBase64(b), pass);\r
+               }\r
+\r
+               if (key == NULL)\r
+               {\r
+                       FreeBuf(b);\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               FreeBuf(b);\r
+               *k = key;\r
+               return true;\r
+       }\r
+}\r
+\r
+// 証明書と秘密鍵のセットを読み込む\r
+bool CmLoadXAndK(HWND hWnd, X **x, K **k)\r
+{\r
+       wchar_t *s;\r
+       bool is_p12;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (x == NULL || k == NULL)\r
+       {\r
+               return false;\r
+       }\r
+START_FIRST:\r
+\r
+       // 証明書を読み込む\r
+       s = OpenDlg(hWnd, _UU("DLG_CERT_OR_P12_FILTER"), _UU("DLG_OPEN_CERT"));\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+       UniStrCpy(tmp, sizeof(tmp), s);\r
+       Free(s);\r
+       if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))\r
+       {\r
+               is_p12 = true;\r
+       }\r
+       else\r
+       {\r
+               is_p12 = false;\r
+       }\r
+\r
+       if (is_p12)\r
+       {\r
+               // PKCS#12 の処理\r
+               BUF *b = ReadDumpW(tmp);\r
+               P12 *p12;\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       return false;\r
+               }\r
+               p12 = BufToP12(b);\r
+               if (p12 == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                       FreeBuf(b);\r
+                       return false;\r
+               }\r
+               if (IsEncryptedP12(p12) == false)\r
+               {\r
+                       if (ParseP12(p12, x, k, NULL) == false)\r
+                       {\r
+                               MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                               FreeP12(p12);\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       char password[MAX_SIZE];\r
+                       if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)\r
+                       {\r
+                               FreeP12(p12);\r
+                               FreeBuf(b);\r
+                               return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (ParseP12(p12, x, k, password) == false)\r
+                               {\r
+                                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);\r
+                                       FreeP12(p12);\r
+                                       FreeBuf(b);\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
+               if (CheckXandK(*x, *k) == false)\r
+               {\r
+                       FreeX(*x);\r
+                       FreeK(*k);\r
+                       FreeP12(p12);\r
+                       FreeBuf(b);\r
+                       if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)\r
+                       {\r
+                               goto START_FIRST;\r
+                       }\r
+                       return false;\r
+               }\r
+               FreeP12(p12);\r
+               FreeBuf(b);\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               // X509 の処理\r
+               BUF *b = ReadDumpW(tmp);\r
+               X *x509;\r
+               K *key;\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               x509 = BufToX(b, IsBase64(b));\r
+               FreeBuf(b);\r
+               if (x509 == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               // 秘密鍵を読み込む\r
+               s = OpenDlg(hWnd, _UU("DLG_KEY_FILTER"), _UU("DLG_OPEN_KEY_WITH_CERT"));\r
+               if (s == NULL)\r
+               {\r
+                       FreeX(x509);\r
+                       return false;\r
+               }\r
+               UniStrCpy(tmp, sizeof(tmp), s);\r
+               Free(s);\r
+\r
+               b = ReadDumpW(tmp);\r
+               if (b == NULL)\r
+               {\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);\r
+                       FreeX(x509);\r
+                       return false;\r
+               }\r
+\r
+               if (IsEncryptedK(b, true) == false)\r
+               {\r
+                       key = BufToK(b, true, IsBase64(b), NULL);\r
+               }\r
+               else\r
+               {\r
+                       char pass[MAX_SIZE];\r
+                       if (PassphraseDlg(hWnd, pass, sizeof(pass), b, false) == false)\r
+                       {\r
+                               FreeBuf(b);\r
+                               FreeX(x509);\r
+                               return false;\r
+                       }\r
+                       key = BufToK(b, true, IsBase64(b), pass);\r
+               }\r
+\r
+               if (key == NULL)\r
+               {\r
+                       FreeBuf(b);\r
+                       FreeX(x509);\r
+                       MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);\r
+                       return false;\r
+               }\r
+\r
+               if (CheckXandK(x509, key) == false)\r
+               {\r
+                       FreeBuf(b);\r
+                       FreeX(x509);\r
+                       FreeK(key);\r
+                       if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)\r
+                       {\r
+                               goto START_FIRST;\r
+                       }\r
+                       return false;\r
+               }\r
+\r
+               FreeBuf(b);\r
+               *x = x509;\r
+               *k = key;\r
+               return true;\r
+       }\r
+}\r
+\r
+// 仮想 HUB 列挙開始\r
+void CmEditAccountDlgStartEnumHub(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       char server_name[MAX_HOST_NAME_LEN + 1];\r
+       UINT old_proxy_type;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (StrLen(a->ClientOption->Hostname) == 0)\r
+       {\r
+               return;\r
+       }\r
+       if (a->ClientOption->Port == 0)\r
+       {\r
+               return;\r
+       }\r
+       if (a->ClientOption->ProxyType != PROXY_DIRECT &&\r
+               (StrLen(a->ClientOption->ProxyName) == 0 ||\r
+               a->ClientOption->ProxyPort == 0))\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (StrCmpi(server_name, a->old_server_name) == 0)\r
+       {\r
+               if (CbNum(hWnd, C_HUBNAME) != 0)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               StrCpy(a->old_server_name, sizeof(a->old_server_name), server_name);\r
+               CbReset(hWnd, C_HUBNAME);\r
+       }\r
+\r
+       old_proxy_type = a->ClientOption->ProxyType;\r
+\r
+       if (IsChecked(hWnd, R_DIRECT_TCP))\r
+       {\r
+               a->ClientOption->ProxyType = PROXY_DIRECT;\r
+       }\r
+       if (IsChecked(hWnd, R_HTTPS))\r
+       {\r
+               a->ClientOption->ProxyType = PROXY_HTTP;\r
+       }\r
+       if (IsChecked(hWnd, R_SOCKS))\r
+       {\r
+               a->ClientOption->ProxyType = PROXY_SOCKS;\r
+       }\r
+\r
+       CmEnumHubStart(hWnd, a->ClientOption);\r
+\r
+       a->ClientOption->ProxyType = old_proxy_type;\r
+}\r
+\r
+// [OK] ボタン\r
+void CmEditAccountDlgOnOk(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       RPC_CLIENT_CREATE_ACCOUNT c;\r
+       bool b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+       if (a->ClientOption->NumRetry != 0 && a->ClientOption->RetryInterval < 5)\r
+       {\r
+               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_RETRY_INTERVAL_ERROR"));\r
+               FocusEx(hWnd, E_RETRY_SPAN);\r
+               return;\r
+       }\r
+\r
+       CmEditAccountDlgUpdate(hWnd, a);\r
+\r
+       if (a->LinkMode == false && a->NatMode == false)\r
+       {\r
+               // アカウントを保存\r
+               Zero(&c, sizeof(c));\r
+               c.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+               Copy(c.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));\r
+               c.ClientAuth = CopyClientAuth(a->ClientAuth);\r
+               c.CheckServerCert = a->CheckServerCert;\r
+               if (a->ServerCert != NULL)\r
+               {\r
+                       c.ServerCert = CloneX(a->ServerCert);\r
+               }\r
+               c.StartupAccount = a->Startup;\r
+\r
+               if (a->EditMode == false)\r
+               {\r
+                       b = CALL(hWnd, CcCreateAccount(cm->Client, &c));\r
+               }\r
+               else\r
+               {\r
+                       b = CALL(hWnd, CcSetAccount(cm->Client, &c));\r
+               }\r
+\r
+               CiFreeClientCreateAccount(&c);\r
+\r
+               // 現在このアカウントが動作中かどうかチェック\r
+               if (b)\r
+               {\r
+                       RPC_CLIENT_GET_CONNECTION_STATUS st;\r
+                       Zero(&st, sizeof(st));\r
+                       UniStrCpy(st.AccountName, sizeof(st.AccountName), a->ClientOption->AccountName);\r
+                       if (CALL(hWnd, CcGetAccountStatus(cm->Client, &st)))\r
+                       {\r
+                               if (st.Active)\r
+                               {\r
+                                       MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_CURRENT_ACTIVE"),\r
+                                               st.AccountName);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (b)\r
+               {\r
+                       EndDialog(hWnd, true);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (a->LinkMode)\r
+               {\r
+                       // リンクモード\r
+                       RPC_CREATE_LINK t;\r
+\r
+                       Zero(&t, sizeof(t));\r
+                       StrCpy(t.HubName, sizeof(t.HubName), a->Hub->HubName);\r
+                       t.Online = a->OnlineFlag;\r
+                       Copy(&t.Policy, &a->Policy, sizeof(POLICY));\r
+                       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+                       Copy(t.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));\r
+                       t.ClientAuth = CopyClientAuth(a->ClientAuth);\r
+                       t.CheckServerCert = a->CheckServerCert;\r
+                       t.ServerCert = CloneX(a->ServerCert);\r
+\r
+                       // カスケード接続の設定を保存\r
+                       if (a->EditMode)\r
+                       {\r
+                               if (CALL(hWnd, ScSetLink(a->Hub->Rpc, &t)))\r
+                               {\r
+                                       if (a->OnlineFlag)\r
+                                       {\r
+                                               MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_LINK_SAVE_ONLINE"), a->ClientOption->AccountName);\r
+                                       }\r
+                                       EndDialog(hWnd, true);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (CALL(hWnd, ScCreateLink(a->Hub->Rpc, &t)))\r
+                               {\r
+                                       if (a->Link_ConnectNow)\r
+                                       {\r
+                                               RPC_LINK tt;\r
+\r
+                                               Zero(&tt, sizeof(tt));\r
+                                               UniStrCpy(tt.AccountName, sizeof(tt.AccountName), a->ClientOption->AccountName);\r
+                                               StrCpy(tt.HubName, sizeof(tt.HubName), a->Hub->HubName);\r
+\r
+                                               CALL(hWnd, ScSetLinkOnline(a->Hub->Rpc, &tt));\r
+                                       }\r
+                                       EndDialog(hWnd, true);\r
+                               }\r
+                       }\r
+\r
+                       FreeRpcCreateLink(&t);\r
+               }\r
+               else\r
+               {\r
+                       // NAT モード\r
+                       RPC_CREATE_LINK t;\r
+                       Zero(&t, sizeof(t));\r
+\r
+                       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+                       Copy(t.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));\r
+                       t.ClientAuth = CopyClientAuth(a->ClientAuth);\r
+\r
+                       if (CALL(hWnd, NcSetClientConfig(a->Rpc, &t)))\r
+                       {\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+\r
+                       FreeRpcCreateLink(&t);\r
+               }\r
+       }\r
+}\r
+\r
+// アカウント編集ダイアログの表示\r
+bool CmEditAccountDlg(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return Dialog(hWnd, D_CM_ACCOUNT, CmEditAccountDlgProc, a);\r
+}\r
+\r
+// アカウント編集\r
+void CmEditAccount(HWND hWnd, wchar_t *account_name)\r
+{\r
+       CM_ACCOUNT *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       a = CmGetExistAccountObject(hWnd, account_name);\r
+       if (a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CmVoice("input_config");\r
+       if (CmEditAccountDlg(hWnd, a))\r
+       {\r
+               CmVoice("set_config");\r
+       }\r
+\r
+       CmFreeAccountObject(hWnd, a);\r
+}\r
+\r
+// アカウント作成\r
+void CmNewAccount(HWND hWnd)\r
+{\r
+       CM_ACCOUNT *a;\r
+       RPC_CLIENT_ENUM_VLAN t;\r
+       UINT num_vlan = 0;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsEnable(hWnd, 0) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (CcEnumVLan(cm->Client, &t) == ERR_NO_ERROR)\r
+       {\r
+               num_vlan = t.NumItem;\r
+\r
+               CiFreeClientEnumVLan(&t);\r
+       }\r
+\r
+       if (num_vlan == 0)\r
+       {\r
+               if (MsgBox(hWnd, MB_ICONINFORMATION | MB_YESNO, _UU("CM_NO_VLAN")) == IDNO)\r
+               {\r
+                       return;\r
+               }\r
+               else\r
+               {\r
+                       if (cm->server_name == NULL)\r
+                       {\r
+                               Command(hWnd, CMD_NEW_VLAN);\r
+                               return;\r
+                       }\r
+                       else\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_VLAN_REMOTE_ERROR"));\r
+                       }\r
+                       return;\r
+               }\r
+       }\r
+\r
+       a = CmCreateNewAccountObject(hWnd);\r
+       if (a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CmVoice("input_config");\r
+       if (CmEditAccountDlg(hWnd, a))\r
+       {\r
+               CmVoice("new_config");\r
+       }\r
+\r
+       CmFreeAccountObject(hWnd, a);\r
+}\r
+\r
+// アカウントオブジェクトの解放\r
+void CmFreeAccountObject(HWND hWnd, CM_ACCOUNT *a)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(a->ClientOption);\r
+       CiFreeClientAuth(a->ClientAuth);\r
+       if (a->ServerCert != NULL)\r
+       {\r
+               FreeX(a->ServerCert);\r
+       }\r
+       Free(a);\r
+}\r
+\r
+// 既存のアカウントオブジェクトの取得\r
+CM_ACCOUNT *CmGetExistAccountObject(HWND hWnd, wchar_t *account_name)\r
+{\r
+       RPC_CLIENT_GET_ACCOUNT c;\r
+       CM_ACCOUNT *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&c, sizeof(c));\r
+       UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);\r
+       if (CALL(hWnd, CcGetAccount(cm->Client, &c)) == false)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       a = ZeroMalloc(sizeof(CM_ACCOUNT));\r
+       a->EditMode = true;\r
+       a->CheckServerCert = c.CheckServerCert;\r
+       a->Startup = c.StartupAccount;\r
+       if (c.ServerCert != NULL)\r
+       {\r
+               a->ServerCert = CloneX(c.ServerCert);\r
+       }\r
+       a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       Copy(a->ClientOption, c.ClientOption, sizeof(CLIENT_OPTION));\r
+       a->ClientAuth = CopyClientAuth(c.ClientAuth);\r
+       Copy(a->ShortcutKey, c.ShortcutKey, SHA1_SIZE);\r
+       CiFreeClientGetAccount(&c);\r
+\r
+       a->LockMode = cm->CmSetting.LockMode;\r
+\r
+       return a;\r
+}\r
+\r
+// 新しいアカウントオブジェクトの作成\r
+CM_ACCOUNT *CmCreateNewAccountObject(HWND hWnd)\r
+{\r
+       CM_ACCOUNT *a;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       a = ZeroMalloc(sizeof(CM_ACCOUNT));\r
+       a->EditMode = false;\r
+       a->CheckServerCert = false;\r
+       a->Startup = false;\r
+       a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+\r
+       // クライアントオプションの初期化\r
+       CmGenerateNewAccountName(hWnd, a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName));\r
+       a->ClientOption->Port = 443;    // デフォルトポート番号\r
+       a->ClientOption->NumRetry = INFINITE;\r
+       a->ClientOption->RetryInterval = 15;\r
+       a->ClientOption->MaxConnection = 1;\r
+       a->ClientOption->HalfConnection = false;\r
+       a->ClientOption->UseEncrypt = true;\r
+       a->ClientOption->AdditionalConnectionInterval = 1;\r
+\r
+       if (cm->Client->Unix)\r
+       {\r
+               a->ClientOption->NoRoutingTracking = true;\r
+       }\r
+\r
+       a->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
+\r
+       // パスワード認証\r
+       a->ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;\r
+\r
+       return a;\r
+}\r
+\r
+// インポート名の作成\r
+void CmGenerateImportName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (name == NULL || hWnd == NULL)\r
+       {\r
+               return;\r
+       }\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_IMPORT_NAME_1"), old_name);\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_2"), old_name, i);\r
+               }\r
+\r
+               if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)\r
+               {\r
+                       UniStrCpy(name, size, tmp);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+// コピー名の作成\r
+void CmGenerateCopyName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (name == NULL || hWnd == NULL)\r
+       {\r
+               return;\r
+       }\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_COPY_NAME_1"), old_name);\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_COPY_NAME_2"), i, old_name);\r
+               }\r
+\r
+               if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)\r
+               {\r
+                       UniStrCpy(name, size, tmp);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+// 新しいアカウント名の作成\r
+void CmGenerateNewAccountName(HWND hWnd, wchar_t *name, UINT size)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (name == NULL || hWnd == NULL)\r
+       {\r
+               return;\r
+       }\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 (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)\r
+               {\r
+                       UniStrCpy(name, size, tmp);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+// ポリシー一覧を表示する\r
+void CmPolicyDlgPrint(HWND hWnd, CM_POLICY *p)\r
+{\r
+       CmPolicyDlgPrintEx(hWnd, p, false);\r
+}\r
+void CmPolicyDlgPrintEx(HWND hWnd, CM_POLICY *p, bool cascade_mode)\r
+{\r
+       CmPolicyDlgPrintEx2(hWnd, p, cascade_mode, POLICY_CURRENT_VERSION);\r
+}\r
+void CmPolicyDlgPrintEx2(HWND hWnd, CM_POLICY *p, bool cascade_mode, bool ver)\r
+{\r
+       POLICY *pol;\r
+       UINT i;\r
+       LVB *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       pol = p->Policy;\r
+\r
+       b = LvInsertStart();\r
+\r
+       for (i = 0;i < NUM_POLICY_ITEM;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               if (cascade_mode)\r
+               {\r
+                       if (PolicyIsSupportedForCascade(i) == false)\r
+                       {\r
+                               continue;\r
+                       }\r
+               }\r
+\r
+               if (IS_POLICY_FOR_CURRENT_VER(i, ver))\r
+               {\r
+                       if (policy_item[i].TypeInt == false)\r
+                       {\r
+                               // bool 型\r
+                               UniStrCpy(tmp, sizeof(tmp), POLICY_BOOL(pol, i) ? _UU("POL_BOOL_ENABLE") : (p->Extension ? _UU("POL_BOOL_DISABLE_EX") : _UU("POL_BOOL_DISABLE")));\r
+                       }\r
+                       else\r
+                       {\r
+                               // int 型\r
+                               if (policy_item[i].AllowZero && POLICY_INT(pol, i) == 0)\r
+                               {\r
+                                       UniStrCpy(tmp, sizeof(tmp), _UU("POL_INT_ZERO"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       UniFormat(tmp, sizeof(tmp), _UU(policy_item[i].FormatStr), POLICY_INT(pol, i));\r
+                               }\r
+                       }\r
+\r
+                       LvInsertAdd(b, ICO_MACHINE, (void *)i, 2, GetPolicyTitle(i), tmp);\r
+               }\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_POLICY);\r
+}\r
+\r
+// ポリシー一覧ダイアログ\r
+UINT CmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       CM_POLICY *p = (CM_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
+               FormatText(hWnd, 0, p->AccountName);\r
+               FormatText(hWnd, S_TITLE, p->AccountName);\r
+               p->hWnd = hWnd;\r
+               if (p->CmStatus != NULL)\r
+               {\r
+                       p->CmStatus->hWndPolicy = hWnd;\r
+               }\r
+\r
+               // カラム初期化\r
+               LvInit(hWnd, L_POLICY);\r
+               LvInsertColumn(hWnd, L_POLICY, 0, _UU("POL_TITLE_STR"), 375);\r
+               LvInsertColumn(hWnd, L_POLICY, 1, _UU("POL_VALUE_STR"), 100);\r
+\r
+               // 表示\r
+               CmPolicyDlgPrint(hWnd, p);\r
+\r
+               // 1 つ目を選択\r
+               LvSelect(hWnd, L_POLICY, 0);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+               case IDCANCEL:\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_POLICY:\r
+                       switch (n->code)\r
+                       {\r
+                       case LVN_ITEMCHANGED:\r
+                               // 選択変更\r
+                               if (LvIsSelected(hWnd, L_POLICY) == false)\r
+                               {\r
+                                       SetText(hWnd, S_DESCRIPTION, L"");\r
+                               }\r
+                               else\r
+                               {\r
+                                       UINT index = LvGetSelected(hWnd, L_POLICY);\r
+                                       UINT id = (UINT)LvGetParam(hWnd, L_POLICY, index);\r
+                                       if (id < NUM_POLICY_ITEM)\r
+                                       {\r
+                                               SetText(hWnd, S_DESCRIPTION, GetPolicyDescription(id));\r
+                                       }\r
+                               }\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, 0);\r
+               break;\r
+       }\r
+\r
+       LvSortHander(hWnd, msg, wParam, lParam, L_POLICY);\r
+\r
+       return 0;\r
+}\r
+\r
+// ポリシー一覧ダイアログの表示\r
+void CmPolicyDlg(HWND hWnd, CM_STATUS *st)\r
+{\r
+       RPC_CLIENT_GET_CONNECTION_STATUS s;\r
+       POLICY *policy;\r
+       CM_POLICY cp;\r
+       // 引数チェック\r
+       if (hWnd == NULL || st == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // ポリシーの取得\r
+       Zero(&s, sizeof(s));\r
+       UniStrCpy(s.AccountName, sizeof(s.AccountName), st->AccountName);\r
+       if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)\r
+       {\r
+               return;\r
+       }\r
+       if (s.Active == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       policy = &s.Policy;\r
+\r
+       Zero(&cp, sizeof(cp));\r
+       UniStrCpy(cp.AccountName, sizeof(cp.AccountName), st->AccountName);\r
+       cp.Policy = policy;\r
+       cp.CmStatus = st;\r
+\r
+       Dialog(hWnd, D_CM_POLICY, CmPolicyDlgProc, &cp);\r
+\r
+       st->hWndPolicy = NULL;\r
+\r
+       CiFreeClientGetConnectionStatus(&s);\r
+}\r
+\r
+// 証明書の表示\r
+void CmStatusDlgPrintCert(HWND hWnd, CM_STATUS *st, bool server)\r
+{\r
+       RPC_CLIENT_GET_CONNECTION_STATUS s;\r
+       X *x, *issuer;\r
+       // 引数チェック\r
+       if (hWnd == NULL || st == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 最新情報を取得する\r
+       Zero(&s, sizeof(s));\r
+       UniStrCpy(s.AccountName, sizeof(s.AccountName), st->AccountName);\r
+       if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       if (s.Active == false)\r
+       {\r
+               // 接続切断\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       if (server == false)\r
+       {\r
+               // クライアント証明書の表示\r
+               x = s.ClientX;\r
+       }\r
+       else\r
+       {\r
+               // サーバー証明書の表示\r
+               x = s.ServerX;\r
+       }\r
+\r
+       cm->WindowCount++;\r
+       issuer = CmGetIssuer(x);\r
+       CertDlg(hWnd, x, issuer, true);\r
+       FreeX(issuer);\r
+       cm->WindowCount--;\r
+\r
+       CiFreeClientGetConnectionStatus(&s);\r
+}\r
+\r
+// ステータスダイアログの情報を表示\r
+void CmStatusDlgPrint(HWND hWnd, CM_STATUS *cmst)\r
+{\r
+       RPC_CLIENT_GET_CONNECTION_STATUS s;\r
+       LVB *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || cmst == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 最新情報を取得する\r
+       Zero(&s, sizeof(s));\r
+       UniStrCpy(s.AccountName, sizeof(s.AccountName), cmst->AccountName);\r
+       if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       if (s.Active == false)\r
+       {\r
+               // 接続切断\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       // ステータスダイアログのリストボックスにステータスを表示する\r
+       b = LvInsertStart();\r
+       CmPrintStatusToListView(b, &s);\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       LvAutoSize(hWnd, L_STATUS);\r
+\r
+       SetEnable(hWnd, B_POLICY, s.Connected);\r
+\r
+       SetEnable(hWnd, B_SERVER_CERT, s.ServerX != NULL);\r
+       SetEnable(hWnd, B_CLIENT_CERT, s.ClientX != NULL);\r
+\r
+       CiFreeClientGetConnectionStatus(&s);\r
+}\r
+\r
+// ステータスダイアログのリストボックスにステータスを表示する\r
+void CmPrintStatusToListView(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s)\r
+{\r
+       CmPrintStatusToListViewEx(b, s, false);\r
+}\r
+void CmPrintStatusToListViewEx(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       char vv[128];\r
+       // 引数チェック\r
+       if (b == NULL || s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (server_mode == false)\r
+       {\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_ACCOUNT_NAME"), s->AccountName);\r
+\r
+               if (s->Connected == false)\r
+               {\r
+                       wchar_t *st = _UU("CM_ST_CONNECTED_FALSE");\r
+                       switch (s->SessionStatus)\r
+                       {\r
+                       case CLIENT_STATUS_CONNECTING:\r
+                               st = _UU("CM_ST_CONNECTING");\r
+                               break;\r
+                       case CLIENT_STATUS_NEGOTIATION:\r
+                               st = _UU("CM_ST_NEGOTIATION");\r
+                               break;\r
+                       case CLIENT_STATUS_AUTH:\r
+                               st = _UU("CM_ST_AUTH");\r
+                               break;\r
+                       case CLIENT_STATUS_ESTABLISHED:\r
+                               st = _UU("CM_ST_ESTABLISHED");\r
+                               break;\r
+                       case CLIENT_STATUS_RETRY:\r
+                               st = _UU("CM_ST_RETRY");\r
+                               break;\r
+                       case CLIENT_STATUS_IDLE:\r
+                               st = _UU("CM_ST_IDLE");\r
+                               break;\r
+                       }\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTED"), st);\r
+               }\r
+               else\r
+               {\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTED"), _UU("CM_ST_CONNECTED_TRUE"));\r
+               }\r
+       }\r
+\r
+       if (s->Connected)\r
+       {\r
+               if (s->VLanId == 0)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_NO_VLAN"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp, s->VLanId);\r
+               }\r
+\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_VLAN_ID"), tmp);\r
+\r
+               if (server_mode == false)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), s->ServerName);\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_NAME"), tmp);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_ST_PORT_TCP"), s->ServerPort);\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_PORT"), tmp);\r
+               }\r
+\r
+               StrToUni(tmp, sizeof(tmp), s->ServerProductName);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_NAME"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u.%02u", s->ServerProductVer / 100, s->ServerProductVer % 100);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_VER"), tmp);\r
+               UniFormat(tmp, sizeof(tmp), L"Build %u", s->ServerProductBuild);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_BUILD"), tmp);\r
+       }\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->StartTime), NULL);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_START_TIME"), tmp);\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->FirstConnectionEstablisiedTime), NULL);\r
+       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_FIRST_ESTAB_TIME"), s->FirstConnectionEstablisiedTime == 0 ? _UU("CM_ST_NONE") : tmp);\r
+\r
+       if (s->Connected)\r
+       {\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->CurrentConnectionEstablishTime), NULL);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CURR_ESTAB_TIME"), tmp);\r
+       }\r
+\r
+       if (server_mode == false)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_STR"), s->NumConnectionsEatablished);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_ESTABLISHED"), tmp);\r
+       }\r
+\r
+       if (s->Connected)\r
+       {\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_HALF_CONNECTION"), s->HalfConnection ? _UU("CM_ST_HALF_TRUE") : _UU("CM_ST_HALF_FALSE"));\r
+\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_QOS"), s->QoS ? _UU("CM_ST_QOS_TRUE") : _UU("CM_ST_QOS_FALSE"));\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnections);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP"), tmp);\r
+\r
+               if (s->HalfConnection)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsUpload);\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP_UPLOAD"), tmp);\r
+                       UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsDownload);\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP_DOWNLOAD"), tmp);\r
+               }\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u", s->MaxTcpConnections);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_MAX_TCP"), tmp);\r
+\r
+               if (s->UseEncrypt == false)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_FALSE"));\r
+               }\r
+               else\r
+               {\r
+                       if (StrLen(s->CipherName) != 0)\r
+                       {\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE"), s->CipherName);\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE2"));\r
+                       }\r
+               }\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_USE_ENCRYPT"), tmp);\r
+\r
+               if (s->UseCompress)\r
+               {\r
+                       UINT percent = 0;\r
+                       if ((s->TotalRecvSize + s->TotalSendSize) > 0)\r
+                       {\r
+                               percent = (UINT)((UINT64)100 - (UINT64)(s->TotalRecvSizeReal + s->TotalSendSizeReal) * (UINT64)100 /\r
+                                       (s->TotalRecvSize + s->TotalSendSize));\r
+                               percent = MAKESURE(percent, 0, 100);\r
+                       }\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_TRUE"), percent);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_FALSE"));\r
+               }\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_USE_COMPRESS"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), s->SessionName);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SESSION_NAME"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), s->ConnectionName);\r
+               if (UniStrCmpi(tmp, L"INITING") != 0)\r
+               {\r
+                       LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTION_NAME"), tmp);\r
+               }\r
+\r
+               BinToStr(str, sizeof(str), s->SessionKey, sizeof(s->SessionKey));\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SESSION_KEY"), tmp);\r
+\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_BRIDGE_MODE"), s->IsBridgeMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));\r
+\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_MONITOR_MODE"), s->IsMonitorMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));\r
+\r
+               ToStr3(vv, sizeof(vv), s->TotalSendSize);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->TotalRecvSize);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_UCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_UCAST_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_BCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_BCAST_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_UCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_UCAST_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_BCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_BCAST_SIZE"), tmp);\r
+       }\r
+}\r
+\r
+// ステータスダイアログプロシージャ\r
+UINT CmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       CM_STATUS *s = (CM_STATUS *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               SetIcon(hWnd, 0, ICO_TOWER);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_TITLE"), s->AccountName);\r
+               SetText(hWnd, 0, tmp);\r
+               FormatText(hWnd, S_TITLE, s->AccountName);\r
+               DlgFont(hWnd, S_TITLE, 0, 1);\r
+\r
+               Add(cm->StatusWindowList, hWnd);\r
+\r
+               SetTimer(hWnd, 1, 500, NULL);\r
+\r
+               LvInitEx(hWnd, L_STATUS, true);\r
+               ListView_SetImageList(DlgItem(hWnd, L_STATUS), NULL, LVSIL_NORMAL);\r
+               ListView_SetImageList(DlgItem(hWnd, L_STATUS), NULL, LVSIL_SMALL);\r
+               LvInsertColumn(hWnd, L_STATUS, 0, _UU("CM_ST_COLUMN_1"), 160);\r
+               LvInsertColumn(hWnd, L_STATUS, 1, _UU("CM_ST_COLUMN_2"), 270);\r
+\r
+               CmStatusDlgPrint(hWnd, s);\r
+\r
+               break;\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       CmStatusDlgPrint(hWnd, s);\r
+                       SetTimer(hWnd, 1, 500, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+               case IDCANCEL:\r
+                       // 閉じる\r
+                       Close(hWnd);\r
+                       break;\r
+               case B_POLICY:\r
+                       // ポリシー表示\r
+                       CmPolicyDlg(hWnd, s);\r
+                       break;\r
+               case B_SERVER_CERT:\r
+                       CmStatusDlgPrintCert(hWnd, s, true);\r
+                       break;\r
+               case B_CLIENT_CERT:\r
+                       CmStatusDlgPrintCert(hWnd, s, false);\r
+                       break;\r
+               }\r
+               break;\r
+       case WM_CLOSE:\r
+               Delete(cm->StatusWindowList, hWnd);\r
+               if (s->hWndPolicy != NULL)\r
+               {\r
+                       EndDialog(s->hWndPolicy, false);\r
+                       s->hWndPolicy = NULL;\r
+               }\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// ステータスダイアログの表示\r
+void CmStatusDlg(HWND hWnd, wchar_t *account_name)\r
+{\r
+       CM_STATUS *s;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s = ZeroMalloc(sizeof(CM_STATUS));\r
+       UniStrCpy(s->AccountName, sizeof(s->AccountName), account_name);\r
+\r
+       Dialog(hWnd, D_CONNECTION_STATUS, CmStatusDlgProc, s);\r
+\r
+       Free(s);\r
+}\r
+\r
+// ステータスの表示\r
+void CmStatus(HWND hWnd, wchar_t *account_name)\r
+{\r
+       UINT i;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("CM_ST_TITLE"), account_name);\r
+\r
+       for (i = 0;i < LIST_NUM(cm->StatusWindowList);i++)\r
+       {\r
+               HWND h = LIST_DATA(cm->StatusWindowList, i);\r
+               if (h != NULL)\r
+               {\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       if (GetTxt(h, 0, tmp2, sizeof(tmp2)))\r
+                       {\r
+                               if (UniStrCmpi(tmp2, tmp) == 0)\r
+                               {\r
+                                       SetActiveWindow(h);\r
+                                       return;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       CmStatusDlg(hWnd, account_name);\r
+}\r
+\r
+// 削除\r
+void CmDeleteAccount(HWND hWnd, wchar_t *account_name)\r
+{\r
+       RPC_CLIENT_DELETE_ACCOUNT c;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+       Zero(&c, sizeof(c));\r
+       UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);\r
+\r
+       CmVoice("delete_config_1");\r
+       if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_ACCOUNT_MSG"), account_name)\r
+               == IDNO)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CALL(hWnd, CcDeleteAccount(cm->Client, &c));\r
+       CmVoice("delete_config_2");\r
+}\r
+\r
+// 切断\r
+void CmDisconnect(HWND hWnd, wchar_t *account_name)\r
+{\r
+       RPC_CLIENT_CONNECT c;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&c, sizeof(c));\r
+       UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);\r
+\r
+       cm->PositiveDisconnectFlag = true;\r
+\r
+       CALL(hWnd, CcDisconnect(cm->Client, &c));\r
+}\r
+\r
+// 宣伝ウインドウの表示\r
+void SmShowPublicVpnServerHtml(HWND hWnd)\r
+{\r
+       char *langstr = _SS("LANGSTR");\r
+\r
+       if(StrCmpi(langstr, "Japanese") == 0)\r
+       {\r
+               ShowHtml(hWnd, PUBLIC_SERVER_HTML, PUBLIC_SERVER_TAG);\r
+       }\r
+       else\r
+       {\r
+               ShowHtml(hWnd, PUBLIC_SERVER_HTML_EN, PUBLIC_SERVER_TAG);\r
+       }\r
+}\r
+\r
+// 接続\r
+void CmConnect(HWND hWnd, wchar_t *account_name)\r
+{\r
+       RPC_CLIENT_CONNECT c;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || account_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (IsEnable(hWnd, 0) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (hWnd == cm->hMainWnd)\r
+       {\r
+               if (LvNum(hWnd, L_VLAN) == 0 && cm->Client->Win9x)\r
+               {\r
+                       if (MsgBox(hWnd, MB_ICONINFORMATION | MB_YESNO, _UU("CM_NO_VLAN_2")) == IDNO)\r
+                       {\r
+                               return;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (cm->server_name == NULL)\r
+                               {\r
+                                       Command(hWnd, CMD_NEW_VLAN);\r
+                                       return;\r
+                               }\r
+                               else\r
+                               {\r
+                                       MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_VLAN_REMOTE_ERROR"));\r
+                               }\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // 警告を表示 (必要な場合)\r
+       if (CmWarningDesktop(hWnd, account_name) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->server_name == NULL)\r
+       {\r
+               if (cm->BadProcessChecked == false)\r
+               {\r
+                       cm->BadProcessChecked = true;\r
+\r
+                       CheckBadProcesses(hWnd);\r
+               }\r
+       }\r
+\r
+       if (cm->server_name == NULL)\r
+       {\r
+               // Windows バージョンチェック\r
+               RPC_WINVER winver;\r
+               wchar_t winver_msg_client[3800];\r
+\r
+               GetWinVer(&winver);\r
+               Zero(winver_msg_client, sizeof(winver_msg_client));\r
+\r
+               if (IsSupportedWinVer(&winver) == false)\r
+               {\r
+                       SYSTEMTIME st;\r
+\r
+                       LocalTime(&st);\r
+\r
+                       UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),\r
+                               _UU("WINVER_ERROR_PC_LOCAL"),\r
+                               winver.Title,\r
+                               _UU("WINVER_ERROR_VPNCLIENT"),\r
+                               SUPPORTED_WINDOWS_LIST,\r
+                               _UU("WINVER_ERROR_PC_LOCAL"),\r
+                               _UU("WINVER_ERROR_VPNCLIENT"),\r
+                               _UU("WINVER_ERROR_VPNCLIENT"),\r
+                               _UU("WINVER_ERROR_VPNCLIENT"),\r
+                               st.wYear, st.wMonth);\r
+               }\r
+\r
+               if (UniIsEmptyStr(winver_msg_client) == false)\r
+               {\r
+                       OnceMsgEx(hWnd, _UU("WINVER_TITLE"), winver_msg_client,\r
+                               true, ICO_WARNING, NULL);\r
+               }\r
+       }\r
+\r
+       i = LvSearchStr(hWnd, L_ACCOUNT, 0, account_name);\r
+       if (i != INFINITE)\r
+       {\r
+               wchar_t *tmp = LvGetStr(hWnd, L_ACCOUNT, i, 2);\r
+               if (tmp != NULL)\r
+               {\r
+                       wchar_t tag[MAX_SIZE];\r
+                       StrToUni(tag, sizeof(tag), PUBLIC_SERVER_NAME);\r
+\r
+                       if (UniSearchStrEx(tmp, tag, 0, false) != INFINITE)\r
+                       {\r
+                               SmShowPublicVpnServerHtml(hWnd);\r
+                       }\r
+\r
+                       Free(tmp);\r
+               }\r
+       }\r
+\r
+       Zero(&c, sizeof(c));\r
+       UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);\r
+\r
+       CmSetForegroundProcessToCnService();\r
+\r
+       if (CALL(hWnd, CcConnect(cm->Client, &c)))\r
+       {\r
+               cm->ConnectStartedFlag = true;\r
+       }\r
+}\r
+\r
+// 指定されたメニュー項目を太字にするかどうか判断する\r
+bool CmIsBold(UINT id)\r
+{\r
+       return false;\r
+}\r
+\r
+// 指定されたメニュー項目を有効にするかどうか判断する\r
+bool CmIsEnabled(HWND hWnd, UINT id)\r
+{\r
+       UINT index;\r
+       wchar_t *name;\r
+       bool locked = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       locked = cm->CmSetting.LockMode;\r
+\r
+       if (locked)\r
+       {\r
+               switch (id)\r
+               {\r
+               case CMD_NEW:\r
+               case CMD_CLONE:\r
+               case CMD_IMPORT_ACCOUNT:\r
+               case CMD_DELETE:\r
+               case CMD_TCPIP:\r
+               case CMD_OPTION:\r
+               case CMD_VOIDE_NONE:\r
+               case CMD_VOICE_NORMAL:\r
+               case CMD_VOICE_ODD:\r
+               case CMD_STARTUP:\r
+               case CMD_NOSTARTUP:\r
+               case CMD_TRAFFIC:\r
+               case CMD_MMCSS:\r
+                       return false;\r
+               case CMD_NEW_VLAN:\r
+               case CMD_ENABLE_VLAN:\r
+               case CMD_DISABLE_VLAN:\r
+               case CMD_DELETE_VLAN:\r
+               case CMD_REINSTALL:\r
+               case CMD_WINNET:\r
+                       if (cm->CmEasyModeSupported)\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       switch (id)\r
+       {\r
+       case CMD_SHOWPORT:\r
+       case CMD_GRID:\r
+               if (cm->IconView)\r
+               {\r
+                       return false;\r
+               }\r
+               return true;\r
+       case CMD_TCPIP:\r
+               if (MsIsTcpConfigSupported() == false)\r
+               {\r
+                       return false;\r
+               }\r
+               return cm->server_name != NULL ? false : true;\r
+       case CMD_MMCSS:\r
+               if (MsIsVista() == false || IsEmptyStr(cm->server_name) == false)\r
+               {\r
+                       return false;\r
+               }\r
+               if (OS_IS_SERVER(GetOsType()))\r
+               {\r
+                       return false;\r
+               }\r
+               return true;\r
+       case CMD_TRAYICON:\r
+       case CMD_TRAFFIC:\r
+               return (cm->server_name == NULL);\r
+       case CMD_NETIF:\r
+               if (MsIsNt() == false)\r
+               {\r
+                       return false;\r
+               }\r
+               return (cm->server_name == NULL);\r
+       case CMD_CM_SETTING:\r
+               return cm->CmSettingSupported;\r
+       case CMD_CONNECT:\r
+       case CMD_DISCONNECT:\r
+       case CMD_STATUS:\r
+       case CMD_RENAME:\r
+       case CMD_DELETE:\r
+               if (LvIsMultiMasked(hWnd, L_ACCOUNT))\r
+               {\r
+                       return false;\r
+               }\r
+               if (LvIsSelected(hWnd, L_ACCOUNT) == false)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       // 選択されているアカウントが接続中かどうか判別する\r
+                       UINT i = LvGetSelected(hWnd, L_ACCOUNT);\r
+                       wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+                       wchar_t *name = LvGetStr(hWnd, L_ACCOUNT, i, 0);\r
+                       bool is_connected = false;\r
+                       if (str != NULL)\r
+                       {\r
+                               if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                               {\r
+                                       is_connected = true;\r
+                               }\r
+                               Free(str);\r
+                       }\r
+                       if (name != NULL)\r
+                       {\r
+                               if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_ASP")) == 0)\r
+                               {\r
+                                       Free(name);\r
+                                       return false;\r
+                               }\r
+                               Free(name);\r
+                       }\r
+                       if (id == CMD_CONNECT || id == CMD_RENAME || id == CMD_DELETE)\r
+                       {\r
+                               return !is_connected;\r
+                       }\r
+                       else\r
+                       {\r
+                               return is_connected;\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_DISCONNECT_ALL:\r
+               if (CmGetNumConnected(hWnd) == 0)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       return true;\r
+               }\r
+       case CMD_SHORTCUT:\r
+               // ショートカットの作成\r
+               if (cm->Client->Rpc->Sock->RemoteIP.addr[0] != 127)\r
+               {\r
+                       return false;\r
+               }\r
+       case CMD_EXPORT_ACCOUNT:\r
+               if (LvIsMultiMasked(hWnd, L_ACCOUNT))\r
+               {\r
+                       return false;\r
+               }\r
+               name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);\r
+               if (name != NULL)\r
+               {\r
+                       if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_ASP")) == 0)\r
+                       {\r
+                               Free(name);\r
+                               return false;\r
+                       }\r
+                       Free(name);\r
+               }\r
+               return LvIsSelected(hWnd, L_ACCOUNT);\r
+       case CMD_CLONE:\r
+               if (LvIsMultiMasked(hWnd, L_ACCOUNT))\r
+               {\r
+                       return false;\r
+               }\r
+               name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);\r
+               if (name != NULL)\r
+               {\r
+                       if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_ASP")) == 0)\r
+                       {\r
+                               Free(name);\r
+                               return false;\r
+                       }\r
+                       Free(name);\r
+               }\r
+               return LvIsSelected(hWnd, L_ACCOUNT);\r
+       case CMD_STARTUP:\r
+       case CMD_NOSTARTUP:\r
+               name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);\r
+               if (name != NULL)\r
+               {\r
+                       if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_ASP")) == 0)\r
+                       {\r
+                               Free(name);\r
+                               return false;\r
+                       }\r
+                       Free(name);\r
+               }\r
+               if (LvIsMultiMasked(hWnd, L_ACCOUNT))\r
+               {\r
+                       return false;\r
+               }\r
+               if (LvIsSelected(hWnd, L_ACCOUNT) == false)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       // 選択されているアカウントがスタートアップアカウントかどうか判別する\r
+                       UINT i = LvGetSelected(hWnd, L_ACCOUNT);\r
+                       bool is_startup = (bool)LvGetParam(hWnd, L_ACCOUNT, i);\r
+                       if (id == CMD_STARTUP)\r
+                       {\r
+                               return !is_startup;\r
+                       }\r
+                       else\r
+                       {\r
+                               return is_startup;\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_NEW_VLAN:\r
+               if (cm->Client->Unix == false && cm->Client->Win9x == false)\r
+               {\r
+                       if (cm->server_name != NULL)\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+               if (cm->Client->Win9x)\r
+               {\r
+                       if (LvNum(hWnd, L_VLAN) >= 1)\r
+                       {\r
+                               // Win9x では 2 枚以上の仮想 LAN カードをインストールできない\r
+                               return false;\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_PROPERTY:\r
+               name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);\r
+               if (name != NULL)\r
+               {\r
+                       if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_ASP")) == 0)\r
+                       {\r
+                               Free(name);\r
+                               return false;\r
+                       }\r
+                       Free(name);\r
+               }\r
+               if (LvIsMultiMasked(hWnd, L_ACCOUNT))\r
+               {\r
+                       return false;\r
+               }\r
+               return LvIsSelected(hWnd, L_ACCOUNT);\r
+       case CMD_DELETE_VLAN:\r
+               if (LvIsMultiMasked(hWnd, L_VLAN))\r
+               {\r
+                       return false;\r
+               }\r
+               return LvIsSelected(hWnd, L_VLAN);\r
+       case CMD_ENABLE_VLAN:\r
+               if (cm->Client->Win9x)\r
+               {\r
+                       return false;\r
+               }\r
+               if (LvIsMultiMasked(hWnd, L_VLAN))\r
+               {\r
+                       return false;\r
+               }\r
+               index = LvGetSelected(hWnd, L_VLAN);\r
+               if (index == INFINITE)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 1);\r
+                       if (s != NULL)\r
+                       {\r
+                               if (UniStrCmpi(s, _UU("CM_VLAN_DISABLED")) == 0)\r
+                               {\r
+                                       Free(s);\r
+                                       return true;\r
+                               }\r
+                               Free(s);\r
+                       }\r
+                       return false;\r
+               }\r
+               break;\r
+       case CMD_DISABLE_VLAN:\r
+               if (cm->Client->Win9x)\r
+               {\r
+                       return false;\r
+               }\r
+               if (LvIsMultiMasked(hWnd, L_VLAN))\r
+               {\r
+                       return false;\r
+               }\r
+               index = LvGetSelected(hWnd, L_VLAN);\r
+               if (index == INFINITE)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 1);\r
+                       if (s != NULL)\r
+                       {\r
+                               if (UniStrCmpi(s, _UU("CM_VLAN_ENABLED")) == 0)\r
+                               {\r
+                                       Free(s);\r
+                                       return true;\r
+                               }\r
+                               Free(s);\r
+                       }\r
+                       return false;\r
+               }\r
+               break;\r
+       case CMD_REINSTALL:\r
+               if (cm->server_name != NULL)\r
+               {\r
+                       return false;\r
+               }\r
+               if (cm->Client->Win9x || cm->Client->Unix)\r
+               {\r
+                       // Win9x と UNIX 系では仮想 LAN カードのアップグレード不可\r
+                       return false;\r
+               }\r
+               if (LvIsMultiMasked(hWnd, L_VLAN))\r
+               {\r
+                       return false;\r
+               }\r
+               return LvIsSelected(hWnd, L_VLAN);\r
+       case CMD_WINNET:\r
+               {\r
+                       UINT os_type = GetOsInfo()->OsType;\r
+\r
+                       if (OS_IS_WINDOWS_NT(os_type) && GET_KETA(os_type, 100) >= 2)\r
+                       {\r
+                               if (cm->server_name != NULL)\r
+                               {\r
+                                       return false;\r
+                               }\r
+\r
+                               return true;\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_EXIT:\r
+               return cm->TrayInited;\r
+       }\r
+       return true;\r
+}\r
+\r
+// VLAN デバイス名を表示名に変換\r
+void CmVLanNameToPrintName(char *str, UINT size, char *name)\r
+{\r
+       // 引数チェック\r
+       if (str == NULL || name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Format(str, size, VLAN_ADAPTER_NAME_TAG, name);\r
+}\r
+\r
+// 表示名を VLAN デバイス名に変換\r
+bool CmPrintNameToVLanName(char *name, UINT size, char *str)\r
+{\r
+       // 引数チェック\r
+       if (name == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (StartWith(str, VLAN_ADAPTER_NAME))\r
+       {\r
+               if (StrLen(str) < (StrLen(VLAN_ADAPTER_NAME) + 3))\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               StrCpy(name, size, str + StrLen(VLAN_ADAPTER_NAME) + 3);\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+// アカウントリストの初期化\r
+void CmInitAccountList(HWND hWnd)\r
+{\r
+       CmInitAccountListEx(hWnd, false);\r
+}\r
+void CmInitAccountListEx(HWND hWnd, bool easy)\r
+{\r
+       UINT width[5];\r
+       BUF *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 設定読み込み\r
+       b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "AccountListColumnWidth");\r
+       if ((b != NULL) && (b->Size == sizeof(width)))\r
+       {\r
+               Copy(width, b->Buf, sizeof(width));\r
+       }\r
+       else if ((b != NULL) && (b->Size == (sizeof(width) - sizeof(UINT))))\r
+       {\r
+               // 旧バージョンからの移行\r
+               Zero(width, sizeof(width));\r
+               Copy(width, b->Buf, sizeof(width) - sizeof(UINT));\r
+               width[4] = width[3];\r
+               width[3] = 0;\r
+       }\r
+       else\r
+       {\r
+               Zero(width, sizeof(width));\r
+       }\r
+       FreeBuf(b);\r
+\r
+       LvInitEx2(hWnd, L_ACCOUNT, false, easy);\r
+\r
+//     LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_TRACKSELECT);\r
+\r
+       // カラムの初期化\r
+       if (easy == false)\r
+       {\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 0, _UU("CM_ACCOUNT_COLUMN_1"), width[0] == 0 ? 215 : width[0]);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 1, _UU("CM_ACCOUNT_COLUMN_2"), width[1] == 0 ? 80 : width[1]);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 2, _UU("CM_ACCOUNT_COLUMN_3"), width[2] == 0 ? 220 : width[2]);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 3, _UU("CM_ACCOUNT_COLUMN_3_2"), width[3] == 0 ? 90 : width[3]);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 4, _UU("CM_ACCOUNT_COLUMN_4"), (width[4] == 0 || width[4] == 250) ? 120 : width[4]);\r
+\r
+               //LvSetBkImage(hWnd, L_ACCOUNT, "|ClientBack2.bmp");\r
+       }\r
+       else\r
+       {\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 0, _UU("CM_ACCOUNT_COLUMN_1"), 345);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 1, _UU("CM_ACCOUNT_COLUMN_2"), 140);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 2, _UU("CM_ACCOUNT_COLUMN_3"), 0);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 3, _UU("CM_ACCOUNT_COLUMN_3_2"), 0);\r
+               LvInsertColumn(hWnd, L_ACCOUNT, 4, _UU("CM_ACCOUNT_COLUMN_4"), 0);\r
+       }\r
+\r
+}\r
+\r
+// アカウントリストの解放\r
+void CmSaveAccountListPos(HWND hWnd)\r
+{\r
+       UINT width[5];\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < 5;i++)\r
+       {\r
+               width[i] = LvGetColumnWidth(hWnd, L_ACCOUNT, i);\r
+       }\r
+\r
+       MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "AccountListColumnWidth", width, sizeof(width));\r
+}\r
+\r
+// VLAN リストの初期化\r
+void CmInitVLanList(HWND hWnd)\r
+{\r
+       UINT width[4];\r
+       BUF *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 設定読み込み\r
+       b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "VLanListColumnWidth");\r
+       if ((b != NULL) && (b->Size == sizeof(width)))\r
+       {\r
+               Copy(width, b->Buf, sizeof(width));\r
+       }\r
+       else\r
+       {\r
+               Zero(width, sizeof(width));\r
+       }\r
+       FreeBuf(b);\r
+\r
+       LvInit(hWnd, L_VLAN);\r
+\r
+//     LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_TRACKSELECT);\r
+\r
+       // カラムの初期化\r
+       LvInsertColumn(hWnd, L_VLAN, 0, _UU("CM_VLAN_COLUMN_1"), width[0] == 0 ? 310 : width[0]);\r
+       LvInsertColumn(hWnd, L_VLAN, 1, _UU("CM_VLAN_COLUMN_2"), width[1] == 0 ? 120 : width[1]);\r
+       LvInsertColumn(hWnd, L_VLAN, 2, _UU("CM_VLAN_COLUMN_3"), width[2] == 0 ? 175 : width[2]);\r
+       LvInsertColumn(hWnd, L_VLAN, 3, _UU("CM_VLAN_COLUMN_4"), width[3] == 0 ? 120 : width[3]);\r
+\r
+       // 背景イメージ\r
+       LvSetBkImage(hWnd, L_VLAN, "|ClientBack2.bmp");\r
+}\r
+\r
+// VLAN リストの解放\r
+void CmSaveVLanListPos(HWND hWnd)\r
+{\r
+       UINT width[4];\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < 4;i++)\r
+       {\r
+               width[i] = LvGetColumnWidth(hWnd, L_VLAN, i);\r
+       }\r
+\r
+       MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "VLanListColumnWidth", width, sizeof(width));\r
+}\r
+\r
+// アカウントリストの更新\r
+void CmRefreshAccountList(HWND hWnd)\r
+{\r
+       CmRefreshAccountListEx(hWnd, false);\r
+       CmRefreshEasy();\r
+}\r
+void CmRefreshAccountListEx(HWND hWnd, bool easy)\r
+{\r
+       CmRefreshAccountListEx2(hWnd, easy, false);\r
+}\r
+void CmRefreshAccountListEx2(HWND hWnd, bool easy, bool style_changed)\r
+{\r
+       UINT num = 0;\r
+       RPC_CLIENT_ENUM_ACCOUNT a;\r
+       UINT num_connecting = 0, num_connected = 0;\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t new_inserted_item[MAX_ACCOUNT_NAME_LEN + 1];\r
+       bool select_new_insteted_item = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // アイコン / 詳細表示の切り替え\r
+       LvSetView(hWnd, L_ACCOUNT, cm->IconView == false || easy);\r
+\r
+       // グリッド表示\r
+       if (cm->ShowGrid || easy)\r
+       {\r
+               LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_GRIDLINES);\r
+       }\r
+       else\r
+       {\r
+               LvRemoveStyle(hWnd, L_ACCOUNT, LVS_EX_GRIDLINES);\r
+       }\r
+\r
+       if (style_changed)\r
+       {\r
+               // フォントの変更\r
+               if (easy == false)\r
+               {\r
+                       if (cm->VistaStyle)\r
+                       {\r
+                               SetFontMeiryo(hWnd, L_ACCOUNT);\r
+                       }\r
+                       else\r
+                       {\r
+                               SetFontDefault(hWnd, L_ACCOUNT);\r
+                       }\r
+\r
+                       if (cm->VistaStyle && (cm->IconView == false))\r
+                       {\r
+                               LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_FULLROWSELECT);\r
+                       }\r
+                       else\r
+                       {\r
+                               LvRemoveStyle(hWnd, L_ACCOUNT, LVS_EX_FULLROWSELECT);\r
+                       }\r
+               }\r
+       }\r
+\r
+       Zero(new_inserted_item, sizeof(new_inserted_item));\r
+\r
+       if (LvNum(hWnd, L_ACCOUNT) == 0)\r
+       {\r
+               select_new_insteted_item = false;\r
+       }\r
+\r
+       // アカウントリストの列挙\r
+       if (CALL(hWnd, CcEnumAccount(cm->Client, &a)))\r
+       {\r
+               UINT i;\r
+               LVB *b = LvInsertStart();\r
+\r
+               if (cm->CmSetting.LockMode == false && (easy == false))\r
+               {\r
+                       // 特別なアイコン\r
+                       LvInsertAdd(b, ICO_NEW, NULL, 4, _UU("CM_NEW_ICON"), L"", L"", L"");\r
+                       LvInsertAdd(b, ICO_INTERNET, NULL, 4, _UU("CM_ASP"), L"", L"", L"");\r
+               }\r
+\r
+               for (i = 0;i < a.NumItem;i++)\r
+               {\r
+                       RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = a.Items[i];\r
+                       UINT icon;\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       char tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       IP ip;\r
+                       char ip_str[MAX_SIZE];\r
+\r
+                       // IPv6 アドレスの場合の特別処理\r
+                       if (StrToIP6(&ip, t->ServerName) && StartWith(t->ServerName, "[") == false)\r
+                       {\r
+                               Format(ip_str, sizeof(ip_str),\r
+                                       "[%s]", t->ServerName);\r
+                       }\r
+                       else\r
+                       {\r
+                               StrCpy(ip_str, sizeof(ip_str), t->ServerName);\r
+                       }\r
+\r
+                       // アイコンの決定\r
+                       if (t->Active == false)\r
+                       {\r
+                               if (t->StartupAccount == false)\r
+                               {\r
+                                       icon = ICO_SERVER_OFFLINE;\r
+                               }\r
+                               else\r
+                               {\r
+                                       icon = ICO_SERVER_OFFLINE_EX;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               num++;\r
+                               if (t->StartupAccount == false)\r
+                               {\r
+                                       icon = ICO_SERVER_ONLINE;\r
+                               }\r
+                               else\r
+                               {\r
+                                       icon = ICO_SERVER_ONLINE_EX;\r
+                               }\r
+                       }\r
+\r
+                       // 追加\r
+                       if (easy == false)\r
+                       {\r
+                               //CmVLanNameToPrintName(tmp3, sizeof(tmp3), t->DeviceName);\r
+                               StrCpy(tmp3, sizeof(tmp3), t->DeviceName);\r
+                               StrToUni(tmp, sizeof(tmp), tmp3);\r
+                       }\r
+                       else\r
+                       {\r
+                               StrToUni(tmp, sizeof(tmp), t->DeviceName);\r
+                       }\r
+\r
+                       if (t->Port == 0 || cm->ShowPort == false)\r
+                       {\r
+                               // ポート番号不明\r
+                               UniFormat(tmp2, sizeof(tmp2), L"%S (%s)", ip_str, CmGetProtocolName(t->ProxyType));\r
+                       }\r
+                       else\r
+                       {\r
+                               // ポート番号併記\r
+                               UniFormat(tmp2, sizeof(tmp2), L"%S:%u (%s)", ip_str, t->Port, CmGetProtocolName(t->ProxyType));\r
+                       }\r
+\r
+                       if (LvSearchStr(hWnd, L_ACCOUNT, 0, t->AccountName) == INFINITE)\r
+                       {\r
+                               UniStrCpy(new_inserted_item, sizeof(new_inserted_item), t->AccountName);\r
+                       }\r
+\r
+                       // 仮想 HUB 名\r
+                       StrToUni(tmp4, sizeof(tmp4), t->HubName);\r
+\r
+                       if (easy == false)\r
+                       {\r
+                               LvInsertAdd(b, icon, (void *)t->StartupAccount, 5, t->AccountName,\r
+                                       t->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :\r
+                                       (t->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),\r
+                                       tmp2, tmp4,\r
+                                       tmp);\r
+                       }\r
+                       else\r
+                       {\r
+                               LvInsertAdd(b, icon, (void *)t->StartupAccount, 5, t->AccountName,\r
+                                       t->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :\r
+                                       (t->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),\r
+                                       tmp2, tmp4,\r
+                                       tmp);\r
+                       }\r
+\r
+                       if (t->Active)\r
+                       {\r
+                               if (t->Connected)\r
+                               {\r
+                                       num_connected++;\r
+                               }\r
+                               else\r
+                               {\r
+                                       num_connecting++;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               LvInsertEnd(b, hWnd, L_ACCOUNT);\r
+\r
+               CiFreeClientEnumAccount(&a);\r
+\r
+               if (select_new_insteted_item)\r
+               {\r
+                       if (UniStrLen(new_inserted_item) >= 1)\r
+                       {\r
+                               LvSelect(hWnd, L_ACCOUNT, INFINITE);\r
+                               LvSelect(hWnd, L_ACCOUNT, LvSearchStr(hWnd, L_ACCOUNT, 0, new_inserted_item));\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (easy == false)\r
+       {\r
+               // 音声ガイドのため、新しく接続されたり、切断されたりした場合を検出する\r
+               if (cm->UpdateConnectedNumFlag == false)\r
+               {\r
+                       cm->UpdateConnectedNumFlag = true;\r
+                       cm->OldConnectedNum = num;\r
+               }\r
+               else\r
+               {\r
+                       if (cm->OldConnectedNum != num)\r
+                       {\r
+                               if (cm->OldConnectedNum < num)\r
+                               {\r
+                                       CmVoice("connect");\r
+                               }\r
+                               else\r
+                               {\r
+                                       CmVoice("disconnect");\r
+\r
+                                       if (cm->CmSetting.EasyMode && cm->PositiveDisconnectFlag == false)\r
+                                       {\r
+                                               CmShowEasy();\r
+                                       }\r
+\r
+                                       cm->PositiveDisconnectFlag = false;\r
+                               }\r
+                               cm->OldConnectedNum = num;\r
+                       }\r
+               }\r
+\r
+               if (num_connecting == 0 && num_connected == 0)\r
+               {\r
+                       // 接続中も接続完了も無し\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_TRAY_NOT_CONNECTED"));\r
+               }\r
+               else if (num_connected == 0)\r
+               {\r
+                       // 接続中だけ有り\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_1"), num_connecting);\r
+               }\r
+               else if (num_connecting == 0)\r
+               {\r
+                       // 接続完了だけ有り\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_2"), num_connected);\r
+               }\r
+               else\r
+               {\r
+                       // 両方有り\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_0"), num_connected, num_connecting);\r
+               }\r
+\r
+               if (num_connecting == 0 && num_connected == 0)\r
+               {\r
+                       cm->TrayAnimation = false;\r
+                       cm->TraySpeedAnimation = false;\r
+               }\r
+               else\r
+               {\r
+                       cm->TrayAnimation = true;\r
+\r
+                       if (num_connecting == 0)\r
+                       {\r
+                               cm->TraySpeedAnimation = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               cm->TraySpeedAnimation = true;\r
+                       }\r
+               }\r
+\r
+               CmChangeTrayString(hWnd, tmp);\r
+       }\r
+\r
+       Refresh(hWnd);\r
+\r
+       //ジャンプリストを更新\r
+       CmUpdateJumpList(0);\r
+}\r
+\r
+// VLAN リストの更新\r
+void CmRefreshVLanList(HWND hWnd)\r
+{\r
+       CmRefreshVLanListEx(hWnd, false);\r
+}\r
+void CmRefreshVLanListEx(HWND hWnd, bool style_changed)\r
+{\r
+       RPC_CLIENT_ENUM_VLAN e;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       LvSetView(hWnd, L_VLAN, cm->IconView == false);\r
+\r
+       // グリッド表示\r
+       if (cm->ShowGrid)\r
+       {\r
+               LvSetStyle(hWnd, L_VLAN, LVS_EX_GRIDLINES);\r
+       }\r
+       else\r
+       {\r
+               LvRemoveStyle(hWnd, L_VLAN, LVS_EX_GRIDLINES);\r
+       }\r
+\r
+       if (style_changed)\r
+       {\r
+               // フォントの変更\r
+               if (cm->VistaStyle)\r
+               {\r
+                       SetFontMeiryo(hWnd, L_VLAN);\r
+               }\r
+               else\r
+               {\r
+                       SetFontDefault(hWnd, L_VLAN);\r
+               }\r
+\r
+               if (cm->VistaStyle && (cm->IconView == false))\r
+               {\r
+                       LvSetStyle(hWnd, L_VLAN, LVS_EX_FULLROWSELECT);\r
+               }\r
+               else\r
+               {\r
+                       LvRemoveStyle(hWnd, L_VLAN, LVS_EX_FULLROWSELECT);\r
+               }\r
+       }\r
+\r
+       // 列挙\r
+       Zero(&e, sizeof(e));\r
+       if (CALL(hWnd, CcEnumVLan(cm->Client, &e)))\r
+       {\r
+               LVB *b = LvInsertStart();\r
+               UINT i;\r
+               for (i = 0;i < e.NumItem;i++)\r
+               {\r
+                       wchar_t name[MAX_SIZE];\r
+                       wchar_t mac[MAX_SIZE];\r
+                       wchar_t ver[MAX_SIZE];\r
+                       char str[MAX_SIZE];\r
+                       wchar_t *status;\r
+                       RPC_CLIENT_ENUM_VLAN_ITEM *v = e.Items[i];\r
+\r
+                       // デバイス名\r
+                       CmVLanNameToPrintName(str, sizeof(str), v->DeviceName);\r
+                       StrToUni(name, sizeof(name), str);\r
+\r
+                       // 状態\r
+                       status = v->Enabled ? _UU("CM_VLAN_ENABLED") : _UU("CM_VLAN_DISABLED");\r
+\r
+                       // MAC アドレス\r
+                       StrToUni(mac, sizeof(mac), v->MacAddress);\r
+\r
+                       // バージョン\r
+                       StrToUni(ver, sizeof(ver), v->Version);\r
+\r
+                       LvInsertAdd(b, v->Enabled ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE, NULL, 4,\r
+                               name, status, mac, ver);\r
+               }\r
+               LvInsertEnd(b, hWnd, L_VLAN);\r
+\r
+               CiFreeClientEnumVLan(&e);\r
+       }\r
+}\r
+\r
+// プロトコル名文字列を取得\r
+wchar_t *CmGetProtocolName(UINT n)\r
+{\r
+       return GetProtocolName(n);\r
+}\r
+\r
+// 表示更新\r
+void CmRefresh(HWND hWnd)\r
+{\r
+       CmRefreshEx(hWnd, false);\r
+}\r
+void CmRefreshEx(HWND hWnd, bool style_changed)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // サイズ更新\r
+       CmMainWindowOnSize(hWnd);\r
+\r
+       // VLAN リストの更新\r
+       CmRefreshVLanListEx(hWnd, style_changed);\r
+\r
+       // アカウントリストの更新\r
+       CmRefreshAccountListEx2(hWnd, false, style_changed);\r
+\r
+       // ステータスバーの更新\r
+       CmRefreshStatusBar(hWnd);\r
+}\r
+\r
+// 指定されたメニュー項目をチェックするかどうか判断する\r
+bool CmIsChecked(UINT id)\r
+{\r
+       switch (id)\r
+       {\r
+       case CMD_TRAYICON:\r
+               return cm->HideTrayIcon == false;\r
+       case CMD_STATUSBAR:\r
+               return cm->HideStatusBar == false;\r
+       case CMD_VISTASTYLE:\r
+               return cm->VistaStyle;\r
+       case CMD_ICON:\r
+               return cm->IconView;\r
+       case CMD_DETAIL:\r
+               return cm->IconView == false;\r
+       case CMD_GRID:\r
+               return cm->ShowGrid;\r
+       case CMD_VOIDE_NONE:\r
+               return cm->DisableVoice;\r
+       case CMD_SHOWPORT:\r
+               return cm->ShowPort;\r
+       case CMD_VOICE_NORMAL:\r
+               if (cm->DisableVoice)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       return cm->VoiceId == VOICE_SSK;\r
+               }\r
+       case CMD_VOICE_ODD:\r
+               if (cm->DisableVoice)\r
+               {\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       return cm->VoiceId == VOICE_AHO;\r
+               }\r
+       }\r
+       return false;\r
+}\r
+\r
+// メニューがポップアップされた\r
+void CmMainWindowOnPopupMenu(HWND hWnd, HMENU hMenu, UINT pos)\r
+{\r
+       UINT num_menu, i, id;\r
+       // 引数チェック\r
+       if (hWnd == NULL || hMenu == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       num_menu = GetMenuItemCount(hMenu);\r
+       for (i = 0;i < num_menu;i++)\r
+       {\r
+               id = GetMenuItemID(hMenu, i);\r
+\r
+               if (id != INFINITE)\r
+               {\r
+                       bool enable_flag = CmIsEnabled(hWnd, id);\r
+                       bool checked_flag = CmIsChecked(id);\r
+                       bool bold_flag = CmIsBold(id);\r
+                       MENUITEMINFO info;\r
+\r
+                       Zero(&info, sizeof(info));\r
+                       info.cbSize = sizeof(info);\r
+                       info.fMask = MIIM_STATE;\r
+                       info.fState = (enable_flag ? MFS_ENABLED : MFS_DISABLED) |\r
+                               (checked_flag ? MFS_CHECKED : MFS_UNCHECKED) |\r
+                               (bold_flag ? MFS_DEFAULT : 0);\r
+\r
+                       if (id == CMD_ICON || id == CMD_DETAIL || id == CMD_VOIDE_NONE ||\r
+                               id == CMD_VOICE_NORMAL || id == CMD_VOICE_ODD)\r
+                       {\r
+                               info.fMask |= MIIM_FTYPE;\r
+                               info.fType = MFT_RADIOCHECK;\r
+                       }\r
+\r
+                       SetMenuItemInfo(hMenu, id, false, &info);\r
+               }\r
+\r
+               if (id == CMD_RECENT)\r
+               {\r
+                       HMENU sub = CmCreateRecentSubMenu(hWnd, CM_TRAY_MENU_RECENT_ID_START);\r
+\r
+                       if (sub != NULL)\r
+                       {\r
+                               DeleteMenu(hMenu, i, MF_BYPOSITION);\r
+                               MsInsertMenu(hMenu, i, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,\r
+                                       (UINT_PTR)sub, _UU("CM_TRAY_MENU_RECENT"));\r
+                       }\r
+                       else\r
+                       {\r
+                               MENUITEMINFO info;\r
+\r
+                               Zero(&info, sizeof(info));\r
+                               info.cbSize = sizeof(info);\r
+                               info.fMask = MIIM_STATE;\r
+                               info.fState = MFS_DISABLED;\r
+\r
+                               SetMenuItemInfo(hMenu, id, false, &info);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+// メインウインドウタイトルの設定\r
+wchar_t *CmGenerateMainWindowTitle()\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       if (cm->server_name == NULL)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), L"%s", _UU("CM_TITLE"));\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), L"%s - %S", _UU("CM_TITLE"), cm->server_name);\r
+       }\r
+\r
+       return CopyUniStr(tmp);\r
+}\r
+\r
+// タスクトレイの初期化\r
+void CmInitTray(HWND hWnd)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->server_name != NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->TrayInited)\r
+       {\r
+               return;\r
+       }\r
+\r
+       MsShowIconOnTray(hWnd, LoadSmallIcon(CmGetTrayIconId(false, 0)), _UU("CM_TRAY_INITING"), WM_CM_TRAY_MESSAGE);\r
+\r
+       cm->TrayInited = true;\r
+       cm->TrayAnimation = false;\r
+\r
+       SetTimer(hWnd, 2, CM_TRAY_ANIMATION_INTERVAL / 4, NULL);\r
+}\r
+\r
+// タスクトレイの文字列の変更\r
+void CmChangeTrayString(HWND hWnd, wchar_t *str)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || str == NULL)\r
+       {\r
+               return;\r
+       }\r
+       if (cm->TrayInited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       MsChangeIconOnTray(NULL, str);\r
+}\r
+\r
+// タスクトレイの解放\r
+void CmFreeTray(HWND hWnd)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->TrayInited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       MsHideIconOnTray();\r
+\r
+       cm->TrayInited = false;\r
+}\r
+void CmFreeTrayExternal(void *hWnd)\r
+{\r
+       CmFreeTray((HWND)hWnd);\r
+}\r
+\r
+// タスクトレイに対する定期的な処理\r
+void CmPollingTray(HWND hWnd)\r
+{\r
+       UINT interval;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->TrayInited == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       MsChangeIconOnTray(LoadSmallIcon(CmGetTrayIconId(cm->TrayAnimation, cm->TrayAnimationCounter)),\r
+               NULL);\r
+\r
+       cm->TrayAnimationCounter++;\r
+\r
+       KillTimer(hWnd, 2);\r
+       interval = CM_TRAY_ANIMATION_INTERVAL / 4;\r
+       if (cm->TraySpeedAnimation)\r
+       {\r
+               interval /= 4;\r
+       }\r
+       SetTimer(hWnd, 2, interval, NULL);\r
+}\r
+\r
+// アニメーション用のタスクトレイのアイコン ID の取得\r
+UINT CmGetTrayIconId(bool animation, UINT animation_counter)\r
+{\r
+       if (animation == false)\r
+       {\r
+               return ICO_TRAY0;\r
+       }\r
+       else\r
+       {\r
+               switch (animation_counter % 4)\r
+               {\r
+               case 0:\r
+                       return ICO_TRAY1;\r
+\r
+               case 1:\r
+                       return ICO_TRAY2;\r
+\r
+               case 2:\r
+                       return ICO_TRAY3;\r
+\r
+               default:\r
+                       return ICO_TRAY4;\r
+               }\r
+       }\r
+}\r
+\r
+// メインウインドウの初期化\r
+void CmMainWindowOnInit(HWND hWnd)\r
+{\r
+       wchar_t *s;\r
+       BUF *b;\r
+       bool startup_mode = cm->StartupMode;\r
+       CM_SETTING a;\r
+       bool fake = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // リストのフォント設定\r
+       SetFontMeiryo(hWnd, L_ACCOUNT);\r
+       SetFontMeiryo(hWnd, L_VLAN);\r
+\r
+       // 現在の vpnclient の設定を取得する\r
+       Zero(&a, sizeof(a));\r
+       CcGetCmSetting(cm->Client, &a);\r
+\r
+       if (a.EasyMode)\r
+       {\r
+               fake = true;\r
+       }\r
+\r
+       InitMenuInternational(GetMenu(hWnd), "CM_MENU");\r
+\r
+       cm->HideStatusBar = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "HideStatusBar");\r
+       cm->HideTrayIcon = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "HideTrayIcon");\r
+       cm->IconView = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "IconView");\r
+       cm->ShowGrid = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "ShowGrid");\r
+\r
+       if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle"))\r
+       {\r
+               cm->VistaStyle = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle");\r
+       }\r
+       else\r
+       {\r
+               cm->VistaStyle = MsIsVista();\r
+       }\r
+\r
+       if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "ShowPort"))\r
+       {\r
+               cm->ShowPort = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "ShowPort");\r
+       }\r
+       else\r
+       {\r
+               cm->ShowPort = false;\r
+       }\r
+\r
+       if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice"))\r
+       {\r
+               cm->DisableVoice = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice");\r
+       }\r
+       else\r
+       {\r
+               cm->DisableVoice = true;\r
+       }\r
+       cm->VoiceId = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "VoiceId");\r
+\r
+       cm->StatusWindowList = NewList(NULL);\r
+\r
+       SetIcon(hWnd, 0, ICO_VPN);\r
+\r
+       s = CmGenerateMainWindowTitle();\r
+       SetText(hWnd, 0, s);\r
+       Free(s);\r
+\r
+       // ウインドウ位置の初期化\r
+       b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "WindowPlacement");\r
+       if (b != NULL && b->Size == sizeof(WINDOWPLACEMENT))\r
+       {\r
+               // ウインドウ位置を復元\r
+               WINDOWPLACEMENT *p;\r
+               p = ZeroMalloc(b->Size);\r
+               Copy(p, b->Buf, b->Size);\r
+\r
+               if (startup_mode)\r
+               {\r
+                       p->showCmd = SW_SHOWMINIMIZED;\r
+               }\r
+\r
+               if (fake)\r
+               {\r
+                       Copy(&cm->FakeWindowPlacement, p, sizeof(WINDOWPLACEMENT));\r
+               }\r
+               else\r
+               {\r
+                       SetWindowPlacement(hWnd, p);\r
+               }\r
+               Free(p);\r
+       }\r
+       else\r
+       {\r
+               // ウインドウ位置を初期化\r
+               SetWindowPos(hWnd, NULL, 0, 0, CM_DEFAULT_WIDTH, CM_DEFAULT_HEIGHT, SWP_NOREDRAW);\r
+               Center(hWnd);\r
+               if (startup_mode)\r
+               {\r
+                       ShowWindow(hWnd, SW_SHOWMINIMIZED);\r
+               }\r
+\r
+               if (fake)\r
+               {\r
+                       WINDOWPLACEMENT p;\r
+\r
+                       Zero(&p, sizeof(p));\r
+                       p.length = sizeof(p);\r
+                       GetWindowPlacement(hWnd, &p);\r
+                       Copy(&cm->FakeWindowPlacement, &p, sizeof(WINDOWPLACEMENT));\r
+               }\r
+       }\r
+       FreeBuf(b);\r
+\r
+       if (fake)\r
+       {\r
+               SetWindowPos(hWnd, NULL, -200, -200, 100, 100,\r
+                       SWP_NOREDRAW | SWP_SHOWWINDOW);\r
+       }\r
+\r
+       // ステータスバー関係の初期化\r
+       cm->hMainWnd = hWnd;\r
+       cm->hStatusBar = CreateStatusWindowW(WS_CHILD |\r
+               (cm->HideStatusBar == false ? WS_VISIBLE : 0),\r
+               _UU("CM_TITLE"),\r
+               hWnd, S_STATUSBAR);\r
+\r
+       UniStrCpy(cm->StatudBar1, sizeof(cm->StatudBar1), _UU("CM_TITLE"));\r
+       UniStrCpy(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_CONN_NO"));\r
+       UniFormat(cm->StatudBar3, sizeof(cm->StatudBar3), _UU("CM_PRODUCT_NAME"), CEDAR_BUILD);\r
+\r
+       cm->Icon2 = LoadSmallIcon(ICO_SERVER_OFFLINE);\r
+       cm->Icon3 = LoadSmallIcon(ICO_VPN);\r
+\r
+       // アカウントリストの初期化\r
+       CmInitAccountList(hWnd);\r
+\r
+       // VLAN リストの初期化\r
+       CmInitVLanList(hWnd);\r
+\r
+       // 表示更新\r
+       CmRefreshEx(hWnd, true);\r
+\r
+       // 通知クライアントのスレッドを開始\r
+       CmInitNotifyClientThread();\r
+\r
+       // タイマー設定\r
+       SetTimer(hWnd, 1, 128, NULL);\r
+\r
+       // タスクトレイの初期化\r
+       if (cm->server_name == NULL)\r
+       {\r
+               if (cm->HideTrayIcon == false)\r
+               {\r
+                       CmInitTray(hWnd);\r
+               }\r
+       }\r
+\r
+       CmVoice("start");\r
+\r
+       if (startup_mode || a.EasyMode)\r
+       {\r
+               SetTimer(hWnd, 3, 1, NULL);\r
+       }\r
+\r
+       if (cm->import_file_name != NULL)\r
+       {\r
+               // 引数として指定されたファイルをインポートする\r
+               CmSendImportMessage(hWnd, cm->import_file_name, cm->CmSettingInitialFlag == CM_SETTING_INIT_NONE ? CM_IMPORT_FILENAME_MSG : CM_IMPORT_FILENAME_MSG_OVERWRITE);\r
+               /*if (a.LockMode == false)\r
+               {\r
+                       CmImportAccountMainEx(hWnd, cm->import_file_name, cm->CmSettingInitialFlag != CM_SETTING_INIT_NONE);\r
+               }\r
+               else\r
+               {\r
+                       MsgBox(cm->hEasyWnd ? cm->hEasyWnd : hWnd, MB_ICONEXCLAMATION, _UU("CM_VPN_FILE_IMPORT_NG"));\r
+               }*/\r
+       }\r
+\r
+       // CM_SETTING の適用\r
+       CmApplyCmSetting();\r
+\r
+       cm->StartupFinished = true;\r
+}\r
+\r
+// 通知クライアントのスレッドを開始\r
+void CmInitNotifyClientThread()\r
+{\r
+       cm->NotifyClient = CcConnectNotify(cm->Client);\r
+       if (cm->NotifyClient == false)\r
+       {\r
+               Close(cm->hMainWnd);\r
+               exit(0);\r
+       }\r
+       cm->NotifyClientThread = NewThread(CmNotifyClientThread, NULL);\r
+}\r
+\r
+// 通知クライアントスレッド\r
+void CmNotifyClientThread(THREAD *thread, void *param)\r
+{\r
+       NOTIFY_CLIENT *nc;\r
+       // 引数チェック\r
+       if (thread == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       nc = cm->NotifyClient;\r
+\r
+       // 次の通知を待機する\r
+       while (cm->Halt == false)\r
+       {\r
+               if (CcWaitNotify(nc))\r
+               {\r
+                       // メッセージ送信\r
+                       PostMessage(cm->hMainWnd, WM_CM_NOTIFY, 0, 0);\r
+               }\r
+               else\r
+               {\r
+                       // 切断された\r
+                       if (cm->Halt == false)\r
+                       {\r
+                               if (cm != NULL)\r
+                               {\r
+                                       CmFreeTrayExternal((void *)cm->hMainWnd);\r
+                               }\r
+                               CncExit();\r
+                               exit(0);\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+// 通知クライアントのスレッドを終了\r
+void CmFreeNotifyClientThread()\r
+{\r
+       cm->Halt = true;\r
+\r
+       // 切断\r
+       CcStopNotify(cm->NotifyClient);\r
+\r
+       // スレッド終了を待機する\r
+       WaitThread(cm->NotifyClientThread, INFINITE);\r
+\r
+       // コネクション終了\r
+       CcDisconnectNotify(cm->NotifyClient);\r
+       ReleaseThread(cm->NotifyClientThread);\r
+}\r
+\r
+// メインウインドウのサイズ変更\r
+void CmMainWindowOnSize(HWND hWnd)\r
+{\r
+       RECT r;\r
+       UINT client_width, client_height;\r
+       UINT status_height;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // メインウインドウのクライアント領域のサイズを取得する\r
+       GetClientRect(hWnd, &r);\r
+       client_width = MAX(r.right - r.left, 0);\r
+       client_height = MAX(r.bottom - r.top, 0);\r
+\r
+       SendMsg(hWnd, S_STATUSBAR, WM_SIZE, 0, 0);\r
+\r
+       // ステータスバーのサイズを取得する\r
+       GetWindowRect(DlgItem(hWnd, S_STATUSBAR), &r);\r
+       status_height = MAX(r.bottom - r.top, 0);\r
+\r
+       if (cm->HideStatusBar == false)\r
+       {\r
+               client_height = MAX(client_height - status_height, 0);\r
+       }\r
+\r
+       MoveWindow(DlgItem(hWnd, L_ACCOUNT), 0, 0, client_width, client_height * 3 / 5 - 3, true);\r
+       MoveWindow(DlgItem(hWnd, L_VLAN), 0, client_height * 3 / 5, client_width, client_height * 2 / 5, true);\r
+\r
+       // ステータスバーの再描画\r
+       CmRedrawStatusBar(hWnd);\r
+}\r
+\r
+// 現在接続中のアカウントをすべて切断する\r
+void CmDisconnectAll(HWND hWnd)\r
+{\r
+       UINT i, num;\r
+       LIST *o;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 警告を表示する\r
+       num = CmGetNumConnected(hWnd);\r
+       if (num == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DISCONNECT_ALL"), num) == IDNO)\r
+       {\r
+               return;\r
+       }\r
+\r
+       cm->PositiveDisconnectFlag = true;\r
+\r
+       // 接続中のリストを作成する\r
+       o = NewListFast(NULL);\r
+\r
+       num = LvNum(hWnd, L_ACCOUNT);\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+               if (s != NULL)\r
+               {\r
+                       if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                       {\r
+                               Add(o, LvGetStr(hWnd, L_ACCOUNT, i, 0));\r
+                       }\r
+                       Free(s);\r
+               }\r
+       }\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               wchar_t *s = LIST_DATA(o, i);\r
+               if (s != NULL)\r
+               {\r
+                       CmDisconnect(hWnd, s);\r
+                       Free(s);\r
+               }\r
+       }\r
+\r
+       ReleaseList(o);\r
+}\r
+\r
+// 現在接続中の接続設定数を取得する\r
+UINT CmGetNumConnected(HWND hWnd)\r
+{\r
+       UINT i, num, num_active;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       num_active = 0;\r
+       num = LvNum(hWnd, L_ACCOUNT);\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 1);\r
+               if (s != NULL)\r
+               {\r
+                       if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)\r
+                       {\r
+                               num_active++;\r
+                       }\r
+                       Free(s);\r
+               }\r
+       }\r
+\r
+       return num_active;\r
+}\r
+\r
+// ステータスバー情報を更新\r
+void CmRefreshStatusBar(HWND hWnd)\r
+{\r
+       UINT num_active = CmGetNumConnected(hWnd);\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (num_active == 0)\r
+       {\r
+               UniStrCpy(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_CONN_NO"));\r
+               cm->Icon2 = LoadSmallIcon(ICO_SERVER_OFFLINE);\r
+       }\r
+       else\r
+       {\r
+               UniFormat(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_NUM_CONN_COUNT"), num_active);\r
+               cm->Icon2 = LoadSmallIcon(ICO_SERVER_ONLINE);\r
+       }\r
+\r
+       CmRedrawStatusBar(hWnd);\r
+}\r
+\r
+// ステータスバーの再描画\r
+void CmRedrawStatusBar(HWND hWnd)\r
+{\r
+       HWND h;\r
+       RECT r;\r
+       int width;\r
+       int x1, x2, x3;\r
+       int xx[3];\r
+       wchar_t tmp[MAX_SIZE];\r
+       HICON icon;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       h = cm->hStatusBar;\r
+\r
+       // ステータスバーの横幅を取得\r
+       GetWindowRect(h, &r);\r
+       width = MAX(r.right - r.left, 0);\r
+       x2 = 180;\r
+       x3 = 245;\r
+       x1 = MAX(width - x2 - x3, 0);\r
+\r
+       // 3 つの部分に分割する\r
+       xx[0] = x1;\r
+       xx[1] = x2 + x1;\r
+       xx[2] = x3 + x2 + x1;\r
+       SendMsg(h, 0, SB_SETPARTS, 3, (LPARAM)xx);\r
+\r
+       // アイコンを設定\r
+       icon = (HICON)SendMsg(h, 0, SB_GETICON, 1, 0);\r
+       if (icon != cm->Icon2)\r
+       {\r
+               SendMsg(h, 0, SB_SETICON, 1, (LPARAM)cm->Icon2);\r
+       }\r
+\r
+       icon = (HICON)SendMsg(h, 0, SB_GETICON, 2, 0);\r
+       if (icon != cm->Icon3)\r
+       {\r
+               SendMsg(h, 0, SB_SETICON, 2, (LPARAM)cm->Icon3);\r
+       }\r
+\r
+       // 文字列を設定\r
+       SendMsg(h, 0, SB_GETTEXTW, 0, (LPARAM)tmp);\r
+       if (UniStrCmp(tmp, cm->StatudBar1))\r
+       {\r
+               SendMsg(h, 0, SB_SETTEXTW, 0, (LPARAM)cm->StatudBar1);\r
+       }\r
+\r
+       SendMsg(h, 0, SB_GETTEXTW, 1, (LPARAM)tmp);\r
+       if (UniStrCmp(tmp, cm->StatudBar2))\r
+       {\r
+               SendMsg(h, 0, SB_SETTEXTW, 1, (LPARAM)cm->StatudBar2);\r
+       }\r
+\r
+       SendMsg(h, 0, SB_GETTEXTW, 2, (LPARAM)tmp);\r
+       if (UniStrCmp(tmp, cm->StatudBar3))\r
+       {\r
+               SendMsg(h, 0, SB_SETTEXTW, 2, (LPARAM)cm->StatudBar3);\r
+       }\r
+}\r
+\r
+// メインウインドウの位置情報を保存する\r
+void CmSaveMainWindowPos(HWND hWnd)\r
+{\r
+       WINDOWPLACEMENT p;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 設定の保存\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "HideStatusBar", cm->HideStatusBar);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "HideTrayIcon", cm->HideTrayIcon);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "IconView", cm->IconView);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "ShowGrid", cm->ShowGrid);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice", cm->DisableVoice);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "VoiceId", cm->VoiceId);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle", cm->VistaStyle);\r
+       MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "ShowPort", cm->ShowPort);\r
+\r
+       // ウインドウ位置の保存\r
+       Zero(&p, sizeof(p));\r
+       p.length = sizeof(p);\r
+       GetWindowPlacement(hWnd, &p);\r
+\r
+       if (IsZero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement)) == false)\r
+       {\r
+               Copy(&p, &cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement));\r
+       }\r
+\r
+       MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "WindowPlacement", &p, sizeof(p));\r
+\r
+       CmSaveAccountListPos(hWnd);\r
+       CmSaveVLanListPos(hWnd);\r
+}\r
+\r
+// メインウインドウを閉じる\r
+void CmMainWindowOnQuit(HWND hWnd)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (cm->TrayInited)\r
+       {\r
+               if (MsgBox(hWnd, MB_YESNO | MB_ICONQUESTION,\r
+                       _UU("CM_EXIT_MESSAGE")) == IDNO)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (cm->OnCloseDispatched)\r
+       {\r
+               return;\r
+       }\r
+       cm->OnCloseDispatched = true;\r
+\r
+       CmCloseEasy();\r
+\r
+       // トレイを解放\r
+       CmFreeTray(hWnd);\r
+\r
+       // メインウインドウの位置情報を保存する\r
+       CmSaveMainWindowPos(hWnd);\r
+\r
+       // ステータスウインドウを閉じる\r
+       for (i = 0;i < LIST_NUM(cm->StatusWindowList);i++)\r
+       {\r
+               HWND h = LIST_DATA(cm->StatusWindowList, i);\r
+               //EndDialog(h, 0);\r
+               PostMessage(h, WM_CLOSE, 0, 0);\r
+       }\r
+\r
+       ReleaseList(cm->StatusWindowList);\r
+       cm->StatusWindowList = NULL;\r
+\r
+       if (cm->WindowCount != 0)\r
+       {\r
+               // 強制終了\r
+               exit(0);\r
+       }\r
+\r
+       // 閉じる\r
+       CmFreeNotifyClientThread();\r
+\r
+       EndDialog(hWnd, false);\r
+}\r
+\r
+// 起動時に使用する mutex を開始\r
+bool CmStartStartupMutex()\r
+{\r
+       INSTANCE *o = NewSingleInstance(STARTUP_MUTEX_NAME);\r
+\r
+       if (o == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       cm->StartupMutex = o;\r
+\r
+       return true;\r
+}\r
+\r
+// 起動時に使用する mutex を解放\r
+void CmEndStartupMutex()\r
+{\r
+       if (cm->StartupMutex != NULL)\r
+       {\r
+               FreeSingleInstance(cm->StartupMutex);\r
+\r
+               cm->StartupMutex = NULL;\r
+       }\r
+}\r
+\r
+// メインウインドウ\r
+void MainCMWindow()\r
+{\r
+       HWND h;\r
+       wchar_t *s;\r
+       CM_SETTING a;\r
+\r
+       if (CmStartStartupMutex() == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s = CmGenerateMainWindowTitle();\r
+       h = SearchWindow(s);\r
+       Free(s);\r
+\r
+       Zero(&a, sizeof(a));\r
+       CcGetCmSetting(cm->Client, &a);\r
+       if (cm->server_name != NULL && a.EasyMode)\r
+       {\r
+               CmEndStartupMutex();\r
+               MsgBox(NULL, MB_ICONEXCLAMATION, _UU("CM_EASY_MODE_NOT_ON_REMOTE"));\r
+               return;\r
+       }\r
+\r
+       // 動作モードの変更\r
+       if (cm->CmSettingSupported)\r
+       {\r
+               if (cm->CmSettingInitialFlag == CM_SETTING_INIT_SELECT)\r
+               {\r
+                       if (h != NULL)\r
+                       {\r
+                               CmEndStartupMutex();\r
+                       }\r
+\r
+                       // 選択画面を表示\r
+                       CmSetting(NULL);\r
+\r
+                       if (h != NULL)\r
+                       {\r
+                               goto SEND_MESSAGES;\r
+                       }\r
+                       else\r
+                       {\r
+                               return;\r
+                       }\r
+               }\r
+               else if ((cm->CmSettingInitialFlag == CM_SETTING_INIT_EASY && cm->CmEasyModeSupported) || cm->CmSettingInitialFlag == CM_SETTING_INIT_NORMAL)\r
+               {\r
+                       // 状態遷移\r
+                       CM_SETTING a;\r
+\r
+                       Zero(&a, sizeof(a));\r
+                       CcGetCmSetting(cm->Client, &a);\r
+\r
+                       if (cm->CmSettingInitialFlag == CM_SETTING_INIT_EASY)\r
+                       {\r
+                               a.EasyMode = true;\r
+                       }\r
+                       else\r
+                       {\r
+                               a.EasyMode = false;\r
+                       }\r
+\r
+                       CcSetCmSetting(cm->Client, &a);\r
+               }\r
+       }\r
+\r
+       if (h == NULL)\r
+       {\r
+               // 他に同じタイトルのウインドウが無いのでウインドウを作成する\r
+               if (cm->server_name == NULL)\r
+               {\r
+                       CmInitTryToExecUiHelper();\r
+                       CnWaitForCnServiceReady();\r
+               }\r
+               Dialog(NULL, D_CM_MAIN, CmMainWindowProc, NULL);\r
+               CmFreeTryToExecUiHelper();\r
+       }\r
+       else\r
+       {\r
+SEND_MESSAGES:\r
+               CmEndStartupMutex();\r
+\r
+               // すでに同じタイトルのウインドウが存在する場合はそれをアクティブにして\r
+               // 自分自身は終了する\r
+               SetForegroundWindow(h);\r
+               SendMessage(h, WM_CM_SHOW, 0, 0);\r
+               SetForegroundWindow(h);\r
+\r
+               if (cm->CmSettingInitialFlag != CM_SETTING_INIT_NONE)\r
+               {\r
+                       // CM_SETTING が変更されたのでそれを通知する\r
+                       SendMessage(h, WM_CM_SETTING_CHANGED_MESSAGE, 0, 0);\r
+               }\r
+\r
+               if (cm->import_file_name != NULL)\r
+               {\r
+                       UINT msg;\r
+                       if (cm->CmSettingInitialFlag == CM_SETTING_INIT_NONE)\r
+                       {\r
+                               msg = CM_IMPORT_FILENAME_MSG;\r
+                       }\r
+                       else\r
+                       {\r
+                               msg = CM_IMPORT_FILENAME_MSG_OVERWRITE;\r
+                       }\r
+\r
+                       CmSendImportMessage(h, cm->import_file_name, msg);\r
+               }\r
+       }\r
+\r
+       CmEndStartupMutex();\r
+}\r
+\r
+// インポートメッセージの送信\r
+void CmSendImportMessage(HWND hWnd, wchar_t *filename, UINT msg)\r
+{\r
+       COPYDATASTRUCT cpy;\r
+       // 引数チェック\r
+       if (hWnd == NULL || filename == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // インポートすべきファイルを指定する\r
+       Zero(&cpy, sizeof(cpy));\r
+\r
+       cpy.cbData = UniStrSize(filename);\r
+       cpy.lpData = filename;\r
+       cpy.dwData = msg;\r
+\r
+       SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cpy);\r
+}\r
+\r
+// ログインダイアログ\r
+UINT CmLoginDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       // 引数チェック\r
+       wchar_t server_name[MAX_SIZE];\r
+       char password[MAX_PASSWORD_LEN + 1];\r
+       bool bad_pass;\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               if (cm->server_name != NULL)\r
+               {\r
+                       StrToUni(server_name, sizeof(server_name), cm->server_name);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));\r
+               }\r
+               FormatText(hWnd, S_TITLE, server_name);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       if (cm->server_name != NULL)\r
+                       {\r
+                               StrToUni(server_name, sizeof(server_name), cm->server_name);\r
+                       }\r
+                       else\r
+                       {\r
+                               UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));\r
+                       }\r
+                       GetTxtA(hWnd, E_PASSWORD, password, sizeof(password));\r
+                       cm->Client = CcConnectRpc(cm->server_name == NULL ? "127.0.0.1" : cm->server_name,\r
+                               password, &bad_pass, NULL, 0);\r
+                       if (cm->Client == NULL)\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONSTOP, _UU("CM_BAD_PASSWORD"));\r
+                               FocusEx(hWnd, E_PASSWORD);\r
+                       }\r
+                       else\r
+                       {\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+                       break;\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 LoginCM()\r
+{\r
+       // まず空のパスワードでログインを試みる\r
+       bool bad_pass, no_remote;\r
+       wchar_t server_name[MAX_SIZE];\r
+       RPC_CLIENT_VERSION a;\r
+\r
+RETRY:\r
+       if (cm->server_name != NULL)\r
+       {\r
+               StrToUni(server_name, sizeof(server_name), cm->server_name);\r
+       }\r
+       else\r
+       {\r
+               UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));\r
+       }\r
+\r
+       // 接続試行\r
+       if ((cm->Client = CcConnectRpc(\r
+               cm->server_name == NULL ? "localhost" : cm->server_name,\r
+               "", &bad_pass, &no_remote, cm->StartupMode == false ? 0 : 60000)) == NULL)\r
+       {\r
+               if (no_remote)\r
+               {\r
+                       // リモート接続が拒否された\r
+                       if (MsgBoxEx(NULL, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("CM_NO_REMOTE"), server_name) == IDRETRY)\r
+                       {\r
+                               // 再試行\r
+                               goto RETRY;\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+               else if (bad_pass)\r
+               {\r
+                       if (Dialog(NULL, D_CM_LOGIN, CmLoginDlgProc, NULL) == false)\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // 接続失敗\r
+                       if (cm->StartupMode == false && MsgBoxEx(NULL, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("CM_CONNECT_FAILED"), server_name) == IDRETRY)\r
+                       {\r
+                               // 再試行\r
+                               goto RETRY;\r
+                       }\r
+                       else\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       CcGetClientVersion(cm->Client, &a);\r
+       if (a.ClientBuildInt >= 5192)\r
+       {\r
+               cm->CmSettingSupported = true;\r
+               cm->CmEasyModeSupported = true;\r
+               if (OS_IS_WINDOWS_9X(a.OsType))\r
+               {\r
+                       cm->CmEasyModeSupported = false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// メイン処理\r
+void MainCM()\r
+{\r
+       // 引数に /remote があればリモート接続の画面を出す\r
+       char *cmdline = GetCommandLineStr();\r
+\r
+       if (StrCmpi(cmdline, "/remote") == 0)\r
+       {\r
+               char *hostname = RemoteDlg(NULL, CM_REG_KEY, ICO_VPN, _UU("CM_TITLE"), _UU("CM_REMOTE_TITLE"), NULL);\r
+               if (hostname == NULL)\r
+               {\r
+                       return;\r
+               }\r
+               if (cm->server_name != NULL)\r
+               {\r
+                       Free(cm->server_name);\r
+               }\r
+               cm->server_name = NULL;\r
+               if (StrCmpi(hostname, "localhost") != 0 && StrCmpi(hostname, "127.0.0.1") != 0 )\r
+               {\r
+                       cm->server_name = hostname;\r
+               }\r
+       }\r
+\r
+       if (StrCmpi(cmdline, "/startup") == 0)\r
+       {\r
+               // スタートアップモード\r
+               cm->StartupMode = true;\r
+       }\r
+\r
+       Free(cmdline);\r
+\r
+       if (IsZero(cm->ShortcutKey, SHA1_SIZE) == false)\r
+       {\r
+               //if (MsGetCurrentTerminalSessionId() == 0)\r
+               {\r
+                       // ショートカット接続の開始\r
+                       CmConnectShortcut(cm->ShortcutKey);\r
+               }/*\r
+               else\r
+               {\r
+                       MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("CM_SHORTCUT_DESKTOP_MSG"),\r
+                               MsGetCurrentTerminalSessionId());\r
+               }*/\r
+               return;\r
+       }\r
+\r
+       // ログイン\r
+       if (LoginCM() == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       //ジャンプリストの更新\r
+       CmUpdateJumpList(0);\r
+\r
+       // メインウインドウ\r
+       MainCMWindow();\r
+\r
+       // ログアウト\r
+       LogoutCM();\r
+}\r
+\r
+// ログアウト\r
+void LogoutCM()\r
+{\r
+       if (cm->Client != NULL)\r
+       {\r
+               CcDisconnectRpc(cm->Client);\r
+       }\r
+}\r
+\r
+// クライアント接続マネージャ起動関数\r
+void CMExec()\r
+{\r
+       // 初期化\r
+       InitCM();\r
+\r
+       // メイン処理\r
+       MainCM();\r
+\r
+       // 解放\r
+       FreeCM();\r
+}\r
+\r
+// HUB 列挙スレッド\r
+void CmEnumHubThread(THREAD *t, void *param)\r
+{\r
+       CM_ENUM_HUB *e = (CM_ENUM_HUB *)param;\r
+       HWND hWnd;\r
+       // 引数チェック\r
+       if (t == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       e->Thread = t;\r
+       hWnd = e->hWnd;\r
+       LockList(cm->EnumHubList);\r
+       {\r
+               Add(cm->EnumHubList, e);\r
+       }\r
+       UnlockList(cm->EnumHubList);\r
+\r
+       // スレッド初期化完了\r
+       NoticeThreadInit(t);\r
+\r
+       // セッション作成\r
+       e->Session = NewRpcSession(cm->Cedar, e->ClientOption);\r
+       if (e->Session)\r
+       {\r
+               // HUB の列挙\r
+               e->Hub = EnumHub(e->Session);\r
+\r
+               if (e->Hub != NULL)\r
+               {\r
+                       // 列挙完了\r
+                       // コンボボックスに追加する\r
+                       if (CbNum(hWnd, C_HUBNAME) == 0)\r
+                       {\r
+                               UINT i;\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               for (i = 0;i < e->Hub->NumTokens;i++)\r
+                               {\r
+                                       StrToUni(tmp, sizeof(tmp), e->Hub->Token[i]);\r
+                                       CbAddStr(hWnd, C_HUBNAME, tmp, 0);\r
+                               }\r
+                       }\r
+\r
+                       // メモリ解放\r
+                       FreeToken(e->Hub);\r
+               }\r
+\r
+               // セッション解放\r
+               ReleaseSession(e->Session);\r
+       }\r
+\r
+       LockList(cm->EnumHubList);\r
+       {\r
+               Delete(cm->EnumHubList, e);\r
+       }\r
+       UnlockList(cm->EnumHubList);\r
+\r
+       Free(e->ClientOption);\r
+       Free(e);\r
+}\r
+\r
+// HUB 列挙の開始\r
+void CmEnumHubStart(HWND hWnd, CLIENT_OPTION *o)\r
+{\r
+       CM_ENUM_HUB *e;\r
+       THREAD *t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || o == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (StrLen(o->Hostname) == 0 ||\r
+               o->Port == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (o->ProxyType != PROXY_DIRECT)\r
+       {\r
+               if (StrLen(o->ProxyName) == 0 ||\r
+                       o->ProxyPort == 0)\r
+               {\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (LvNum(hWnd, C_HUBNAME) != 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       e = ZeroMalloc(sizeof(CM_ENUM_HUB));\r
+       e->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       e->hWnd = hWnd;\r
+       Copy(e->ClientOption, o, sizeof(CLIENT_OPTION));\r
+\r
+       t = NewThread(CmEnumHubThread, e);\r
+       WaitThreadInit(t);\r
+       ReleaseThread(t);\r
+}\r
+\r
+// HUB 列挙処理の初期化\r
+void CmInitEnumHub()\r
+{\r
+       cm->EnumHubList = NewList(NULL);\r
+}\r
+\r
+// HUB 列挙処理の解放\r
+void CmFreeEnumHub()\r
+{\r
+       LIST *o;\r
+       UINT i;\r
+       if (cm->EnumHubList == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       o = NewList(NULL);\r
+       LockList(cm->EnumHubList);\r
+       {\r
+               UINT i;\r
+               for (i = 0;i < LIST_NUM(cm->EnumHubList);i++)\r
+               {\r
+                       CM_ENUM_HUB *e = LIST_DATA(cm->EnumHubList, i);\r
+                       Add(o, e->Thread);\r
+                       AddRef(e->Thread->ref);\r
+               }\r
+       }\r
+       UnlockList(cm->EnumHubList);\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               THREAD *t = LIST_DATA(o, i);\r
+               WaitThread(t, INFINITE);\r
+               ReleaseThread(t);\r
+       }\r
+       ReleaseList(o);\r
+\r
+       ReleaseList(cm->EnumHubList);\r
+}\r
+\r
+// クライアント接続マネージャの初期化\r
+#define APPID L"SoftEther.SoftEther UT-VPN Client"\r
+\r
+void InitCM()\r
+{\r
+       UNI_TOKEN_LIST *ut;\r
+       if (cm != NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       //Set Application ID\r
+       if(JL_SetCurrentProcessExplicitAppUserModelID(APPID) != S_OK)\r
+       {\r
+       }\r
+\r
+       CmDeleteOldStartupTrayFile();\r
+\r
+       MsSetShutdownParameters(0x4ff, SHUTDOWN_NORETRY);\r
+\r
+       // メモリ確保\r
+       cm = ZeroMalloc(sizeof(CM));\r
+\r
+       // コマンドライン引数が設定されている場合はサーバー名として取り扱う\r
+       ut = GetCommandLineUniToken();\r
+\r
+       if (ut->NumTokens >= 1)\r
+       {\r
+               if (UniStrLen(ut->Token[0]) != 0)\r
+               {\r
+                       if (UniStrCmpi(ut->Token[0], L"cm") != 0 && ut->Token[0][0] != L'/')\r
+                       {\r
+                               BUF *b = UniStrToBin(ut->Token[0]);\r
+                               if (b->Size == SHA1_SIZE)\r
+                               {\r
+                                       // 接続設定のショートカットキーとして扱う\r
+                                       Copy(cm->ShortcutKey, b->Buf, SHA1_SIZE);\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (UniEndWith(ut->Token[0], L".uvpn") == false)\r
+                                       {\r
+                                               // サーバー名として扱う\r
+                                               cm->server_name = CopyUniToStr(ut->Token[0]);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // インポートファイル名として扱う\r
+                                               cm->import_file_name = CopyUniStr(ut->Token[0]);\r
+                                       }\r
+                               }\r
+                               FreeBuf(b);\r
+                       }\r
+                       else if (UniStrCmpi(ut->Token[0], L"/easy") == 0)\r
+                       {\r
+                               // 簡易モード\r
+                               if (ut->NumTokens >= 2)\r
+                               {\r
+                                       // インポートすべき接続設定が指定されている\r
+                                       cm->import_file_name = CopyUniStr(ut->Token[1]);\r
+                               }\r
+\r
+                               cm->CmSettingInitialFlag = CM_SETTING_INIT_EASY;\r
+                       }\r
+                       else if (UniStrCmpi(ut->Token[0], L"/normal") == 0)\r
+                       {\r
+                               // 通常モード\r
+                               if (ut->NumTokens >= 2)\r
+                               {\r
+                                       // インポートすべき接続設定が指定されている\r
+                                       cm->import_file_name = CopyUniStr(ut->Token[1]);\r
+                               }\r
+\r
+                               cm->CmSettingInitialFlag = CM_SETTING_INIT_NORMAL;\r
+                       }\r
+                       else if (UniStrCmpi(ut->Token[0], L"/select") == 0)\r
+                       {\r
+                               // 選択画面\r
+                               cm->CmSettingInitialFlag = CM_SETTING_INIT_SELECT;\r
+                       }\r
+               }\r
+       }\r
+\r
+       UniFreeToken(ut);\r
+\r
+       InitWinUi(_UU("CM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));\r
+\r
+       // アルファブレンディング関係\r
+       UseAlpha = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha");\r
+       AlphaValue = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue");\r
+\r
+       cm->Cedar = NewCedar(NULL, NULL);\r
+       CmInitEnumHub();\r
+}\r
+\r
+// クライアント接続マネージャの終了\r
+void FreeCM()\r
+{\r
+       if (cm == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CmFreeEnumHub();\r
+       ReleaseCedar(cm->Cedar);\r
+\r
+       FreeWinUi();\r
+\r
+       // メモリ解放\r
+       if (cm->server_name != NULL)\r
+       {\r
+               Free(cm->server_name);\r
+       }\r
+       Free(cm);\r
+       cm = NULL;\r
+}\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+//JumpList ToDo\r
+// By Takao Ito\r
+void *CmUpdateJumpList(UINT start_id)\r
+{\r
+       HMENU h = NULL;\r
+       UINT i;\r
+       RPC_CLIENT_ENUM_ACCOUNT a;\r
+       LIST *o;\r
+       bool easy;\r
+\r
+       JL_PCustomDestinationList pcdl;\r
+       JL_PObjectCollection poc;\r
+       JL_PShellLink shell;\r
+       JL_PObjectArray poaRemoved;\r
+\r
+       HRESULT hr;\r
+\r
+       if (cm->server_name != NULL)\r
+       {\r
+               // 外部 PC の場合は利用しない\r
+               return NULL;\r
+       }\r
+\r
+       //試しに追加\r
+       if(SUCCEEDED(JL_CreateCustomDestinationList(&pcdl,APPID)))\r
+       {\r
+\r
+               JL_DeleteJumpList(pcdl,APPID);\r
+\r
+               easy = cm->CmSetting.EasyMode;\r
+\r
+               Zero(&a, sizeof(a));\r
+\r
+               \r
+               if (CcEnumAccount(cm->Client, &a) == ERR_NO_ERROR)\r
+               {\r
+                       o = NewListFast(CiCompareClientAccountEnumItemByLastConnectDateTime);\r
+\r
+                       for (i = 0;i < a.NumItem;i++)\r
+                       {\r
+                               RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = a.Items[i];\r
+\r
+                               item->tmp1 = i;\r
+\r
+                               if (item->LastConnectDateTime != 0)\r
+                               {\r
+                                       Add(o, item);\r
+                               }\r
+                       }\r
+\r
+                       Sort(o);\r
+\r
+                       if(LIST_NUM(o) > 0)\r
+                       {\r
+\r
+                               if(SUCCEEDED(JL_BeginList(pcdl, &poaRemoved)))\r
+                               {\r
+\r
+\r
+                                       //コレクションの作成\r
+                                       if(SUCCEEDED(JL_CreateObjectCollection(&poc)))\r
+                                       {\r
+\r
+                                               for (i = 0;i < MIN(LIST_NUM(o), CM_NUM_RECENT);i++)\r
+                                               {\r
+\r
+                                                       RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = (RPC_CLIENT_ENUM_ACCOUNT_ITEM *)LIST_DATA(o, i);\r
+//                                                     wchar_t tmp[MAX_PATH];\r
+                                                       wchar_t *account_name;\r
+                                                       char *server_name;\r
+                                                       char *hub_name;\r
+//                                                     CM_ACCOUNT *a;\r
+                                                       UCHAR key[SHA1_SIZE];\r
+                                                       RPC_CLIENT_GET_ACCOUNT c;\r
+\r
+\r
+                                                       account_name = item->AccountName;\r
+                                                       server_name = item->ServerName;\r
+                                                       hub_name = item->HubName;\r
+\r
+\r
+\r
+                                                       //\r
+                                                       //a = CmGetExistAccountObject(hWnd, account_name);\r
+\r
+\r
+                                                       //if (a == NULL)\r
+                                                       //{\r
+                                                       //continue;\r
+                                                       //}\r
+\r
+                                                       //Copy(key, a->ShortcutKey, SHA1_SIZE);\r
+                                                       //\r
+\r
+                                                       Zero(&c, sizeof(c));\r
+                                                       UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);\r
+                                                       if (CALL(NULL, CcGetAccount(cm->Client, &c)) == false)\r
+                                                       {\r
+                                                               break;\r
+                                                       }\r
+\r
+                                                       Copy(key, c.ShortcutKey, SHA1_SIZE);\r
+\r
+                                                       if (IsZero(key, SHA1_SIZE))\r
+                                                       {\r
+                                                               //MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_SHORTCUT_UNSUPPORTED"));\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+\r
+                                                               //wchar_t target[MAX_PATH];\r
+                                                               ////wchar_t workdir[MAX_PATH];\r
+                                                               //wchar_t args[MAX_PATH];\r
+                                                               ////wchar_t comment[MAX_SIZE];\r
+                                                               //wchar_t icon[MAX_PATH];\r
+\r
+                                                               char key_str[64];\r
+                                                               wchar_t target[MAX_PATH];\r
+                                                               //wchar_t workdir[MAX_PATH];\r
+                                                               wchar_t args[MAX_PATH];\r
+                                                               wchar_t commentW[MAX_SIZE];\r
+                                                               wchar_t icon[MAX_PATH];\r
+                                                               int iconNum;\r
+\r
+                                                               //char icon = "C:\\Server.ico";\r
+\r
+                                                               BinToStr(key_str, sizeof(key_str), key, SHA1_SIZE);\r
+                                                               UniStrCpy(target, sizeof(target), MsGetExeFileNameW());\r
+                                                               StrToUni(args, sizeof(args), key_str);\r
+                                                               UniStrCpy(icon, sizeof(icon), MsGetExeFileNameW());\r
+                                                               UniFormat(commentW, sizeof(commentW), _UU("CM_SHORTCUT_COMMENT"), account_name);\r
+\r
+                                                               if(item->Connected)\r
+                                                               {\r
+                                                                       iconNum = 1;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       iconNum = 2;\r
+                                                               }\r
+\r
+                                                               hr = JL_CreateShellLink(\r
+                                                                       target,\r
+                                                                       args,\r
+                                                                       account_name,\r
+                                                                       icon,iconNum,\r
+                                                                       commentW,\r
+                                                                       &shell);\r
+\r
+                                                               if(SUCCEEDED(hr))\r
+                                                               {\r
+\r
+                                                                       if(SUCCEEDED(JL_ObjectCollectionAddShellLink(poc, shell)))\r
+                                                                       {\r
+                                                                               //Print("Add JumpList %d c:%s\n",i, comment);\r
+                                                                               //wprintf(comment);\r
+                                                                       }\r
+                                                                       JL_ReleaseShellLink(shell);\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       CiFreeClientGetAccount(&c);\r
+                                               }\r
+\r
+                                               hr = JL_AddCategoryToList(pcdl,poc,_UU("CM_JUMPLIST_RCCONNECT"),poaRemoved);\r
+\r
+                                               if(SUCCEEDED(hr))\r
+                                               {\r
+                                                       //wprintf(L"AddCategory\n");\r
+\r
+                                                       hr = JL_CommitList(pcdl);\r
+                                                       if(SUCCEEDED(hr))\r
+                                                       {\r
+                                                               //wprintf(L"JumpList Commit\n");\r
+                                                       }\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       //wprintf(L"Erro JumpList AddCategory %x\n", hr);\r
+                                               }\r
+\r
+                                               //リリース\r
+                                               JL_ReleaseObjectCollection(poc);\r
+                                       }\r
+                               }\r
+\r
+                       }\r
+\r
+\r
+                       ReleaseList(o);\r
+\r
+                       CiFreeClientEnumAccount(&a);\r
+               }\r
+\r
+               \r
+\r
+\r
+               /*\r
+                       JL_BeginList(pcdl, &poaRemoved);\r
+\r
+                       JL_CreateObjectCollection(&poc);\r
+\r
+                       //てしゅと\r
+                       for (i = 0; i < 5; i++)\r
+                       {\r
+\r
+                               JL_CreateShellLink(\r
+                                       "",\r
+                                       "",\r
+                                       L"せつぞく",\r
+                                       NULL,0,\r
+                                       NULL,\r
+                                       &shell);\r
+                               JL_ObjectCollectionAddShellLink(poc, shell);\r
+\r
+                               JL_ReleaseShellLink(shell);\r
+\r
+                       }\r
+\r
+                       JL_AddCategoryToList(pcdl,poc,_UU("CM_JUMPLIST_RCCONNECT"),poaRemoved);\r
+                       JL_CommitList(pcdl);\r
+                       JL_ReleaseObjectCollection(poc);\r
+\r
+               JL_ReleaseCustomDestinationList(pcdl);\r
+               */\r
+\r
+       }\r
+\r
+       return h;\r
+}\r
+\r
+\r
+\r
+#endif // WIN32\r
+\r
+\r