1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Cedar Communication Module
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 // Contributors:
18 // - ELIN (https://github.com/el1n)
19 //
20 // License: The Apache License, Version 2.0
21 // https://www.apache.org/licenses/LICENSE-2.0
22 //
23 // DISCLAIMER
24 // ==========
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 // SOFTWARE.
33 //
34 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
35 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
36 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
37 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
38 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
39 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
40 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
41 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
42 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
43 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
44 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
45 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
46 // LAW OR COURT RULE.
47 //
48 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
49 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
50 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
51 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
52 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
53 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
54 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
55 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
56 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
57 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
58 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
59 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
60 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
61 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
62 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
63 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
64 // STATEMENT FOR WARNING AND DISCLAIMER.
65 //
66 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
67 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
68 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
69 //
70 //
71 // SOURCE CODE CONTRIBUTION
72 // ------------------------
73 //
74 // Your contribution to SoftEther VPN Project is much appreciated.
75 // Please send patches to us through GitHub.
76 // Read the SoftEther VPN Patch Acceptance Policy in advance:
77 // http://www.softether.org/5-download/src/9.patch
78 //
79 //
80 // DEAR SECURITY EXPERTS
81 // ---------------------
82 //
83 // If you find a bug or a security vulnerability please kindly inform us
84 // about the problem immediately so that we can fix the security problem
85 // to protect a lot of users around the world as soon as possible.
86 //
87 // Our e-mail address for security reports is:
88 // softether-vpn-security [at] softether.org
89 //
90 // Please note that the above e-mail address is not a technical support
91 // inquiry address. If you need technical assistance, please visit
92 // http://www.softether.org/ and ask your question on the users forum.
93 //
94 // Thank you for your cooperation.
95 //
96 //
97 // NO MEMORY OR RESOURCE LEAKS
98 // ---------------------------
99 //
100 // The memory-leaks and resource-leaks verification under the stress
101 // test has been passed before release this source code.
102 
103 
104 // CM.c
105 // VPN Client Connection Manager for Win32
106 
107 #include <GlobalConst.h>
108 
109 #ifdef	WIN32
110 
111 #define	CM_C
112 #define	SM_C
113 #define	MICROSOFT_C
114 
115 #define	_WIN32_WINNT		0x0502
116 #define	WINVER				0x0502
117 #include <winsock2.h>
118 #include <windows.h>
119 #include <Iphlpapi.h>
120 #include <tlhelp32.h>
121 #include <shlobj.h>
122 #include <commctrl.h>
123 #include <Dbghelp.h>
124 #include <setupapi.h>
125 #include <regstr.h>
126 #include <process.h>
127 #include <psapi.h>
128 #include <wtsapi32.h>
129 #include <Ntsecapi.h>
130 #include <stdio.h>
131 #include <stdlib.h>
132 #include <string.h>
133 #include <wchar.h>
134 #include <stdarg.h>
135 #include <time.h>
136 #include <errno.h>
137 #include <Mayaqua/Mayaqua.h>
138 #include <Cedar/Cedar.h>
139 #include "CMInner.h"
140 #include "SMInner.h"
141 #include "NMInner.h"
142 #include "EMInner.h"
143 #include "../PenCore/resource.h"
144 
145 
146 // Get the proxy server settings from the registry string of IE
CmGetProxyServerNameAndPortFromIeProxyRegStr(char * name,UINT name_size,UINT * port,char * str,char * server_type)147 bool CmGetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type)
148 {
149 	TOKEN_LIST *t;
150 	UINT i;
151 	bool ret = false;
152 	// Validate arguments
153 	if (name == NULL || port == NULL || str == NULL || server_type == NULL)
154 	{
155 		return false;
156 	}
157 
158 	t = ParseToken(str, ";");
159 
160 	for (i = 0;i < t->NumTokens;i++)
161 	{
162 		char *s = t->Token[i];
163 		UINT i;
164 
165 		Trim(s);
166 
167 		i = SearchStrEx(s, "=", 0, false);
168 		if (i != INFINITE)
169 		{
170 			char tmp[MAX_PATH];
171 
172 			StrCpy(name, name_size, s);
173 			name[i] = 0;
174 
175 			if (StrCmpi(name, server_type) == 0)
176 			{
177 				char *host;
178 				StrCpy(tmp, sizeof(tmp), s + i + 1);
179 
180 				if (ParseHostPort(tmp, &host, port, 0))
181 				{
182 					StrCpy(name, name_size, host);
183 					Free(host);
184 
185 					if (*port != 0)
186 					{
187 						ret = true;
188 					}
189 					break;
190 				}
191 			}
192 		}
193 	}
194 
195 	FreeToken(t);
196 
197 	return ret;
198 }
199 
200 
201 // Reflect the contents of the proxy settings to the connection settings
CmProxyDlgSet(HWND hWnd,CLIENT_OPTION * o,CM_INTERNET_SETTING * setting)202 void CmProxyDlgSet(HWND hWnd, CLIENT_OPTION *o, CM_INTERNET_SETTING *setting)
203 {
204 	// Validate arguments
205 	if(hWnd == NULL || setting == NULL)
206 	{
207 		return;
208 	}
209 
210 	// Make check in check-box
211 	Check(hWnd, R_DIRECT_TCP,	setting->ProxyType == PROXY_DIRECT);
212 	Check(hWnd, R_HTTPS,		setting->ProxyType == PROXY_HTTP);
213 	Check(hWnd, R_SOCKS,		setting->ProxyType == PROXY_SOCKS);
214 
215 	// Proxy Settings
216 	if(setting->ProxyType != PROXY_DIRECT)
217 	{
218 		StrCpy(o->ProxyName, sizeof(setting->ProxyHostName), setting->ProxyHostName);
219 		o->ProxyPort = setting->ProxyPort;
220 	}
221 }
222 
223 // Get the proxy settings of IE
CmGetSystemInternetSetting(CM_INTERNET_SETTING * setting)224 void CmGetSystemInternetSetting(CM_INTERNET_SETTING *setting)
225 {
226 	bool use_proxy;
227 	// Validate arguments
228 	if (setting == NULL)
229 	{
230 		return;
231 	}
232 
233 	Zero(setting, sizeof(CM_INTERNET_SETTING));
234 
235 	use_proxy = MsRegReadInt(REG_CURRENT_USER,
236 		"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
237 		"ProxyEnable");
238 
239 	if (use_proxy)
240 	{
241 		char *str = MsRegReadStr(REG_CURRENT_USER,
242 			"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
243 			"ProxyServer");
244 		if (str != NULL)
245 		{
246 			char name[MAX_HOST_NAME_LEN + 1];
247 			UINT port;
248 
249 			if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
250 				&port, str, "https"))
251 			{
252 				setting->ProxyType = PROXY_HTTP;
253 				StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
254 				setting->ProxyPort = port;
255 			}
256 			else if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
257 				&port, str, "http"))
258 			{
259 				setting->ProxyType = PROXY_HTTP;
260 				StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
261 				setting->ProxyPort = port;
262 			}
263 			else if (CmGetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name),
264 				&port, str, "socks"))
265 			{
266 				setting->ProxyType = PROXY_SOCKS;
267 				StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name);
268 				setting->ProxyPort = port;
269 			}
270 			else
271 			{
272 				if (SearchStrEx(str, "=", 0, false) == INFINITE)
273 				{
274 					char *host;
275 					UINT port;
276 					if (ParseHostPort(str, &host, &port, 0))
277 					{
278 						if (port != 0)
279 						{
280 							setting->ProxyType = PROXY_HTTP;
281 							StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), host);
282 							setting->ProxyPort = port;
283 						}
284 						Free(host);
285 					}
286 				}
287 			}
288 
289 			Free(str);
290 		}
291 	}
292 }
293 
294 // For the proxy settings to go through, use the IE settings
CmProxyDlgUseForIE(HWND hWnd,CLIENT_OPTION * o)295 void CmProxyDlgUseForIE(HWND hWnd, CLIENT_OPTION *o)
296 {
297 	CM_INTERNET_SETTING s;
298 
299 	// Validate arguments
300 	if(hWnd == NULL)
301 	{
302 		return;
303 	}
304 
305 	Zero(&s, sizeof(s));
306 	CmGetSystemInternetSetting(&s);
307 
308 	CmProxyDlgSet(hWnd, o, &s);
309 }
310 
311 // Determine the bitmap ID of the smart card authentication screen
CmGetSecureBitmapId(char * dest_hostname)312 UINT CmGetSecureBitmapId(char *dest_hostname)
313 {
314 	// Validate arguments
315 	if (dest_hostname == NULL)
316 	{
317 		return 0;
318 	}
319 
320 	if (EndWith(dest_hostname, ".cc.tsukuba.ac.jp"))
321 	{
322 		return BMP_TSUKUBA;
323 	}
324 
325 	return 0;
326 }
327 
328 // Activate the window of UAC
CmSetUacWindowActive()329 void CmSetUacWindowActive()
330 {
331 	HWND hWnd;
332 
333 	if (MsIsVista() == false)
334 	{
335 		return;
336 	}
337 
338 	hWnd = FindWindowA("$$$Secure UAP Dummy Window Class For Interim Dialog", NULL);
339 	if (hWnd == NULL)
340 	{
341 		return;
342 	}
343 
344 	SwitchToThisWindow(hWnd, true);
345 }
346 
347 // UAC helper thread
CmUacHelperThread(THREAD * thread,void * param)348 void CmUacHelperThread(THREAD *thread, void *param)
349 {
350 	CM_UAC_HELPER *c = (CM_UAC_HELPER *)param;
351 	// Validate arguments
352 	if (c == NULL)
353 	{
354 		return;
355 	}
356 
357 	while (c->Halt == false)
358 	{
359 		CmSetUacWindowActive();
360 
361 		Wait(c->HaltEvent, 200);
362 	}
363 }
364 
365 // Start the UAC helper
CmStartUacHelper()366 void *CmStartUacHelper()
367 {
368 	CM_UAC_HELPER *c = ZeroMalloc(sizeof(CM_UAC_HELPER));
369 
370 	c->HaltEvent = NewEvent();
371 	c->Thread = NewThread(CmUacHelperThread, c);
372 
373 	return (void *)c;
374 }
375 
376 // Stop the UAC helper
CmStopUacHelper(void * p)377 void CmStopUacHelper(void *p)
378 {
379 	CM_UAC_HELPER *c = (CM_UAC_HELPER *)p;
380 	// Validate arguments
381 	if (c == NULL)
382 	{
383 		return;
384 	}
385 
386 	c->Halt = true;
387 	Set(c->HaltEvent);
388 	WaitThread(c->Thread, INFINITE);
389 	ReleaseEvent(c->HaltEvent);
390 	ReleaseThread(c->Thread);
391 
392 	Free(c);
393 }
394 
395 // Command invocation of the simple connection manager
CmEasyDlgOnCommand(HWND hWnd,CM_EASY_DLG * d,WPARAM wParam,LPARAM lParam)396 void CmEasyDlgOnCommand(HWND hWnd, CM_EASY_DLG *d, WPARAM wParam, LPARAM lParam)
397 {
398 	// Validate arguments
399 	if (hWnd == NULL || d == NULL)
400 	{
401 		return;
402 	}
403 
404 	switch (wParam)
405 	{
406 	case B_MODE:
407 		Command(hWnd, CMD_CM_SETTING);
408 		return;
409 
410 	case B_STATUS:
411 		Command(hWnd, CMD_STATUS);
412 		return;
413 
414 	case IDCANCEL:
415 		Close(hWnd);
416 		return;
417 
418 	}
419 
420 	if (wParam == CMD_CONNECT)
421 	{
422 		cm->ConnectStartedFlag = false;
423 	}
424 
425 	CmMainWindowOnCommandEx(hWnd, wParam, lParam, true);
426 
427 	if (wParam == CMD_CONNECT && cm->ConnectStartedFlag)
428 	{
429 		// Close the window when the connection started successfully
430 		Close(hWnd);
431 	}
432 }
433 
434 // Keyboard pressing of the simple connection manager
CmEasyDlgOnKey(HWND hWnd,CM_EASY_DLG * d,bool ctrl,bool alt,UINT key)435 void CmEasyDlgOnKey(HWND hWnd, CM_EASY_DLG *d, bool ctrl, bool alt, UINT key)
436 {
437 	// Validate arguments
438 	if (hWnd == NULL)
439 	{
440 		return;
441 	}
442 
443 	// Single key
444 	switch (key)
445 	{
446 	case VK_RETURN:
447 		Command(hWnd, IDOK);
448 		break;
449 	case VK_DELETE:
450 		// Delete
451 		if (IsFocus(hWnd, L_ACCOUNT))
452 		{
453 			// Operation on the account list
454 			Command(hWnd, CMD_DELETE);
455 		}
456 		else
457 		{
458 			// Operation on the virtual LAN card list
459 			Command(hWnd, CMD_DELETE_VLAN);
460 		}
461 		break;
462 	case VK_F2:
463 		// Change the name
464 		Command(hWnd, CMD_RENAME);
465 		break;
466 	case VK_F5:
467 		// Update the status
468 		Command(hWnd, CMD_REFRESH);
469 		break;
470 	}
471 
472 	if (alt)
473 	{
474 		switch (key)
475 		{
476 		case 'Q':
477 			// Close
478 			Command(hWnd, CMD_QUIT);
479 			break;
480 		}
481 	}
482 
483 	if (ctrl)
484 	{
485 		switch (key)
486 		{
487 		case 'G':
488 			// Smart Card Manager
489 			Command(hWnd, CMD_SECURE_MANAGER);
490 			break;
491 		case 'S':
492 			// Show the status
493 			Command(hWnd, CMD_STATUS);
494 			break;
495 		case 'I':
496 			// Disconnect all connections
497 			Command(hWnd, CMD_DISCONNECT_ALL);
498 			break;
499 		case 'D':
500 			// Disconnect
501 			Command(hWnd, CMD_DISCONNECT);
502 			break;
503 		case 'N':
504 			// Create a new connection setting
505 			Command(hWnd, CMD_NEW);
506 			break;
507 		case 'C':
508 			// Creating a copy
509 			Command(hWnd, CMD_CLONE);
510 			break;
511 		case 'T':
512 			// Set to start-up connection
513 			Command(hWnd, CMD_STARTUP);
514 			break;
515 		case 'A':
516 			// Select all
517 			Command(hWnd, CMD_SELECT_ALL);
518 			break;
519 		case 'L':
520 			// Create a new virtual LAN card
521 			Command(hWnd, CMD_NEW_VLAN);
522 			break;
523 		case 'P':
524 			// Set the password
525 			Command(hWnd, CMD_PASSWORD);
526 			break;
527 		case 'O':
528 			// Option settings
529 			Command(hWnd, CMD_TRAFFIC);
530 			break;
531 		case 'R':
532 			// Certificate management
533 			Command(hWnd, CMD_TRUST);
534 			break;
535 		case 'Q':
536 			// Throughput
537 			Command(hWnd, CMD_TRAFFIC);
538 			break;
539 		}
540 	}
541 }
542 
543 // Operation on the list view of the simple connection manager
CmEasyDlgOnNotify(HWND hWnd,CM_EASY_DLG * d,NMHDR * n)544 void CmEasyDlgOnNotify(HWND hWnd, CM_EASY_DLG *d, NMHDR *n)
545 {
546 	NMLVDISPINFOW *disp_info;
547 	NMLVKEYDOWN *key;
548 
549 	// Validate arguments
550 	if (hWnd == NULL || n == NULL)
551 	{
552 		return;
553 	}
554 
555 	switch (n->idFrom)
556 	{
557 	case L_ACCOUNT:
558 		switch (n->code)
559 		{
560 		case LVN_ITEMCHANGED:
561 			CmEasyDlgUpdate(hWnd, d);
562 			break;
563 		case NM_DBLCLK:
564 			// Double click
565 			Command(hWnd, CMD_EASY_DBLCLICK);
566 			break;
567 		case NM_RCLICK:
568 			// Right click
569 			CmAccountListRightClick(hWnd);
570 			break;
571 		case LVN_ENDLABELEDITW:
572 			// Change the name
573 			disp_info = (NMLVDISPINFOW *)n;
574 			if (disp_info->item.pszText != NULL)
575 			{
576 				wchar_t *new_name = disp_info->item.pszText;
577 				wchar_t *old_name = LvGetStr(hWnd, L_ACCOUNT, disp_info->item.iItem, 0);
578 
579 				if (old_name != NULL)
580 				{
581 					if (UniStrCmp(new_name, old_name) != 0 && UniIsEmptyStr(new_name) == false)
582 					{
583 						RPC_RENAME_ACCOUNT a;
584 						Zero(&a, sizeof(a));
585 						UniStrCpy(a.OldName, sizeof(a.OldName), old_name);
586 						UniStrCpy(a.NewName, sizeof(a.NewName), new_name);
587 						if (CALL(hWnd, CcRenameAccount(cm->Client, &a)))
588 						{
589 							LvSetItem(hWnd, L_ACCOUNT, disp_info->item.iItem, 0, new_name);
590 						}
591 					}
592 
593 					Free(old_name);
594 				}
595 			}
596 			break;
597 		case LVN_KEYDOWN:
598 			// Key-press
599 			key = (NMLVKEYDOWN *)n;
600 			if (key != NULL)
601 			{
602 				bool ctrl, alt;
603 				UINT code = key->wVKey;
604 				ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
605 				alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
606 				CmEasyDlgOnKey(hWnd, d, ctrl, alt, code);
607 			}
608 			break;
609 		}
610 		break;
611 	}
612 }
613 
614 // Send an update notification to the Simple Connection Manager
CmRefreshEasy()615 void CmRefreshEasy()
616 {
617 	if (cm->hEasyWnd == NULL)
618 	{
619 		return;
620 	}
621 
622 	SendMessage(cm->hEasyWnd, WM_CM_EASY_REFRESH, 0, 0);
623 }
624 
625 // Initialze the Simple Connect Manager
CmEasyDlgInit(HWND hWnd,CM_EASY_DLG * d)626 void CmEasyDlgInit(HWND hWnd, CM_EASY_DLG *d)
627 {
628 	HFONT hFontForList;
629 	HFONT hFontButton;
630 	HFONT hFontTitle;
631 	HFONT hFontInfo;
632 	HFONT hFontOther;
633 	UINT i, num, num2, j;
634 	bool b = false;
635 	char *font_name = NULL;
636 	bool font_bold = true;
637 	// Validate arguments
638 	if (hWnd == NULL || d == NULL)
639 	{
640 		return;
641 	}
642 
643 	SetIcon(hWnd, 0, ICO_VPN);
644 
645 	// Window handle registration
646 	cm->hEasyWnd = hWnd;
647 
648 	// Show in the center
649 	Center(hWnd);
650 
651 	// Update the account list
652 	CmInitAccountListEx(hWnd, true);
653 
654 	// Font settings of the list
655 	if (cm->VistaStyle)
656 	{
657 		if (_GETLANG() == 0)
658 		{
659 			font_name = "Meiryo";
660 			font_bold = false;
661 		}
662 		else if (_GETLANG() == 2)
663 		{
664 			font_name = "Microsoft YaHei";
665 			font_bold = false;
666 		}
667 	}
668 
669 	hFontForList = GetFont(font_name, 14, font_bold, false, false, false);
670 	hFontButton = GetFont(font_name, 13, font_bold, false, false, false);
671 	hFontTitle = GetFont(font_name, 14, font_bold, false, false, false);
672 	hFontInfo = GetFont(font_name, 11, font_bold, false, false, false);
673 	hFontOther = GetDialogDefaultFont();
674 
675 	if (cm->VistaStyle)
676 	{
677 		hFontOther = GetMeiryoFont();
678 	}
679 
680 	SetFont(hWnd, L_ACCOUNT, hFontForList);
681 	SetFont(hWnd, IDOK, hFontButton);
682 	SetFont(hWnd, S_TITLE, hFontTitle);
683 	SetFont(hWnd, S_INFO, hFontInfo);
684 	SetFont(hWnd, B_MODE, hFontOther);
685 	SetFont(hWnd, IDCANCEL, hFontOther);
686 	SetFont(hWnd, B_VGC, hFontOther);
687 
688 	SetShow(hWnd, B_VGC, cm->Client->IsVgcSupported);
689 
690 	CmEasyDlgRefresh(hWnd, d);
691 
692 	num = LvNum(hWnd, L_ACCOUNT);
693 	num2 = 0;
694 	j = 0;
695 	for (i = 0;i < num;i++)
696 	{
697 		wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
698 
699 		if (str != NULL)
700 		{
701 			if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
702 			{
703 				num2++;
704 				j = i;
705 			}
706 			Free(str);
707 		}
708 	}
709 
710 	if (num2 == 1)
711 	{
712 		LvSelect(hWnd, L_ACCOUNT, j);
713 		b = true;
714 	}
715 
716 	if (b == false)
717 	{
718 		if (UniIsEmptyStr(cm->EasyLastSelectedAccountName) == false)
719 		{
720 			i = LvSearchStr(hWnd, L_ACCOUNT, 0, cm->EasyLastSelectedAccountName);
721 			if (i != INFINITE)
722 			{
723 				LvSelect(hWnd, L_ACCOUNT, i);
724 				b = true;
725 			}
726 		}
727 	}
728 
729 	if (b == false)
730 	{
731 		if (LvNum(hWnd, L_ACCOUNT) != 0)
732 		{
733 			LvSelect(hWnd, L_ACCOUNT, 0);
734 		}
735 	}
736 
737 	Focus(hWnd, L_ACCOUNT);
738 
739 	CmEasyDlgUpdate(hWnd, d);
740 }
741 
742 // Update the Simple Connection Manager control
CmEasyDlgUpdate(HWND hWnd,CM_EASY_DLG * d)743 void CmEasyDlgUpdate(HWND hWnd, CM_EASY_DLG *d)
744 {
745 	bool ok = true;
746 	bool show_status = false;
747 	wchar_t *button_str = _UU("CM_EASY_CONNECT_BUTTON_1");
748 	wchar_t *info_str = _UU("CM_EASY_INFO_1");
749 	wchar_t *title_str = _UU("CM_EASY_TITLE");
750 	// Validate arguments
751 	if (hWnd == NULL || d == NULL)
752 	{
753 		return;
754 	}
755 
756 	if (LvIsSingleSelected(hWnd, L_ACCOUNT) == false)
757 	{
758 		ok = false;
759 	}
760 
761 	if (ok)
762 	{
763 		UINT i = LvGetSelected(hWnd, L_ACCOUNT);
764 		wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
765 
766 		info_str = _UU("CM_EASY_INFO_2");
767 
768 		if (str != NULL)
769 		{
770 			if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
771 			{
772 				button_str = _UU("CM_EASY_CONNECT_BUTTON_2");
773 				show_status = true;
774 				info_str = _UU("CM_EASY_INFO_3");
775 
776 				if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0)
777 				{
778 					title_str = _UU("CM_EASY_CONNECTED");
779 				}
780 				else
781 				{
782 					title_str = _UU("CM_EASY_CONNECTING");
783 				}
784 			}
785 			Free(str);
786 		}
787 	}
788 
789 	SetShow(hWnd, B_STATUS, show_status);
790 
791 	SetText(hWnd, IDOK, button_str);
792 	SetText(hWnd, S_INFO, info_str);
793 	SetText(hWnd, S_TITLE, title_str);
794 
795 	SetShow(hWnd, IDOK, ok);
796 }
797 
798 // Update the Simple Connect Manager content
CmEasyDlgRefresh(HWND hWnd,CM_EASY_DLG * d)799 void CmEasyDlgRefresh(HWND hWnd, CM_EASY_DLG *d)
800 {
801 	// Validate arguments
802 	if (hWnd == NULL || d == NULL)
803 	{
804 		return;
805 	}
806 
807 	// Update the account list
808 	CmRefreshAccountListEx(hWnd, true);
809 
810 	CmEasyDlgUpdate(hWnd, d);
811 }
812 
813 // Dialog procedure of the simple connection manager
CmEasyDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)814 UINT CmEasyDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
815 {
816 	CM_EASY_DLG *d = (CM_EASY_DLG *)param;
817 	NMHDR *n;
818 	UINT i;
819 	// Validate arguments
820 	if (hWnd == NULL)
821 	{
822 		return 0;
823 	}
824 
825 	switch (msg)
826 	{
827 	case WM_INITDIALOG:
828 		CmEasyDlgInit(hWnd, d);
829 		SetTimer(hWnd, 1, 10, NULL);
830 		break;
831 
832 	case WM_TIMER:
833 		switch (wParam)
834 		{
835 		case 1:
836 			KillTimer(hWnd, 1);
837 			SetForegroundWindow(hWnd);
838 			SetActiveWindow(hWnd);
839 			break;
840 		}
841 		break;
842 
843 	case WM_CM_EASY_REFRESH:
844 		CmEasyDlgRefresh(hWnd, d);
845 		break;
846 
847 	case WM_COMMAND:
848 		CmEasyDlgOnCommand(hWnd, d, wParam, lParam);
849 		break;
850 
851 	case WM_NOTIFY:
852 		n = (NMHDR *)lParam;
853 		CmEasyDlgOnNotify(hWnd, d, n);
854 		break;
855 
856 	case WM_CLOSE:
857 		i = LvGetSelected(hWnd, L_ACCOUNT);
858 		if (i != INFINITE)
859 		{
860 			wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 0);
861 			if (s != NULL)
862 			{
863 				UniStrCpy(cm->EasyLastSelectedAccountName, sizeof(cm->EasyLastSelectedAccountName),
864 					s);
865 				Free(s);
866 			}
867 		}
868 		else
869 		{
870 			Zero(cm->EasyLastSelectedAccountName, sizeof(cm->EasyLastSelectedAccountName));
871 		}
872 		EndDialog(hWnd, false);
873 		break;
874 	}
875 
876 	return 0;
877 }
878 
879 // Show the window of the simple connection manager (This is called by a delaying timer)
CmMainWindowOnShowEasy(HWND hWnd)880 void CmMainWindowOnShowEasy(HWND hWnd)
881 {
882 	CM_EASY_DLG d;
883 
884 	Zero(&d, sizeof(d));
885 
886 	if (cm->CmSetting.EasyMode == false)
887 	{
888 		// Not in simple mode
889 		return;
890 	}
891 
892 	if (cm->hEasyWnd != NULL)
893 	{
894 		// It is shown already
895 		SetForegroundWindow(cm->hEasyWnd);
896 		SetActiveWindow(cm->hEasyWnd);
897 		return;
898 	}
899 
900 	Dialog(NULL, D_CM_EASY, CmEasyDlg, &d);
901 
902 	cm->hEasyWnd = NULL;
903 }
904 
905 // Show the window of the simple connection manager
CmShowEasy()906 void CmShowEasy()
907 {
908 	SetTimer(cm->hMainWnd, 4, 2, NULL);
909 }
910 
911 // Close the window of the simple connection manager
CmCloseEasy()912 void CmCloseEasy()
913 {
914 	if (cm->hEasyWnd == NULL)
915 	{
916 		return;
917 	}
918 
919 	SendMessage(cm->hEasyWnd, WM_CLOSE, 0, 0);
920 }
921 
922 // Message processing for such as clicking on the tray icon
CmMainWindowOnTrayClicked(HWND hWnd,WPARAM wParam,LPARAM lParam)923 void CmMainWindowOnTrayClicked(HWND hWnd, WPARAM wParam, LPARAM lParam)
924 {
925 	bool easymode = cm->CmSetting.EasyMode;
926 
927 	switch (wParam)
928 	{
929 	case 1:
930 		switch (lParam)
931 		{
932 		case WM_LBUTTONDOWN:
933 		case WM_RBUTTONDOWN:
934 			// Click
935 			if (easymode == false)
936 			{
937 				if (IsEnable(hWnd, 0))
938 				{
939 					CmShowTrayMenu(hWnd);
940 				}
941 				else
942 				{
943 					CmShowOrHideWindow(hWnd);
944 				}
945 			}
946 			else
947 			{
948 				if (cm->hEasyWnd == NULL || IsEnable(cm->hEasyWnd, 0))
949 				{
950 					CmShowTrayMenu(hWnd);
951 				}
952 				else
953 				{
954 					//CmShowOrHideWindow(hWnd);
955 				}
956 			}
957 			break;
958 		case WM_LBUTTONDBLCLK:
959 		case WM_RBUTTONDBLCLK:
960 			// Double click
961 			if (easymode == false)
962 			{
963 				if (IsEnable(hWnd, 0))
964 				{
965 					CmShowOrHideWindow(hWnd);
966 				}
967 			}
968 			else
969 			{
970 				if (cm->hEasyWnd == NULL)
971 				{
972 					CmShowEasy();
973 				}
974 				else
975 				{
976 					SetForegroundWindow(cm->hEasyWnd);
977 					SetActiveWindow(cm->hEasyWnd);
978 				}
979 			}
980 			break;
981 		}
982 		break;
983 	}
984 }
985 
986 // Apply the setting of the operation mode
CmApplyCmSetting()987 void CmApplyCmSetting()
988 {
989 	CM_SETTING a;
990 	bool changed = false;
991 
992 	if (cm->CmSettingSupported == false)
993 	{
994 		return;
995 	}
996 
997 	// Get the configuration of the current vpnclient
998 	Zero(&a, sizeof(a));
999 	CcGetCmSetting(cm->Client, &a);
1000 
1001 	// Check whether there is change point as compared to the previous CM_SETTING
1002 	if (cm->CmSetting.EasyMode != a.EasyMode)
1003 	{
1004 		changed = true;
1005 	}
1006 	if (cm->CmSetting.LockMode != a.LockMode)
1007 	{
1008 		changed = true;
1009 	}
1010 
1011 	Copy(&cm->CmSetting, &a, sizeof(CM_SETTING));
1012 
1013 	if (changed == false)
1014 	{
1015 		return;
1016 	}
1017 
1018 	if (cm->StartupFinished)
1019 	{
1020 		if (IsShow(cm->hMainWnd, 0) && cm->CmSetting.EasyMode)
1021 		{
1022 			// Close the main window if it is shown
1023 			Hide(cm->hMainWnd, 0);
1024 		}
1025 		else
1026 		{
1027 			WINDOWPLACEMENT current_pos;
1028 			if (cm->CmSetting.EasyMode == false && IsShow(cm->hMainWnd, 0) == false)
1029 			{
1030 				// When restored to normal mode, restore the main window
1031 				if (IsZero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement)) == false)
1032 				{
1033 					cm->FakeWindowPlacement.flags = cm->FakeWindowPlacement.flags & ~SW_MINIMIZE;
1034 					SetWindowPlacement(cm->hMainWnd, &cm->FakeWindowPlacement);
1035 					Zero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement));
1036 					Hide(cm->hMainWnd, 0);
1037 				}
1038 				CmShowOrHideWindow(cm->hMainWnd);
1039 			}
1040 
1041 			if (cm->CmSetting.EasyMode == false)
1042 			{
1043 				if (GetWindowPlacement(cm->hMainWnd, &current_pos))
1044 				{
1045 					if (current_pos.rcNormalPosition.right < 0 ||
1046 						current_pos.rcNormalPosition.bottom < 0)
1047 					{
1048 						// If the window is off the screen for some reason,
1049 						// return it in a visible place
1050 						SetWindowPos(cm->hMainWnd, NULL, 0, 0, CM_DEFAULT_WIDTH, CM_DEFAULT_HEIGHT, SWP_NOREDRAW | SWP_SHOWWINDOW);
1051 						Center(cm->hMainWnd);
1052 					}
1053 				}
1054 			}
1055 		}
1056 
1057 		Command(cm->hMainWnd, CMD_REFRESH);
1058 	}
1059 
1060 	if (cm->CmSetting.EasyMode)
1061 	{
1062 		if (cm->StartupFinished == false && cm->StartupMode)
1063 		{
1064 			// Don't show in the case of /startup
1065 		}
1066 		else
1067 		{
1068 			CmShowEasy();
1069 		}
1070 	}
1071 	else
1072 	{
1073 		CmCloseEasy();
1074 	}
1075 }
1076 
1077 // Initialize the operation mode changing dialog
CmSettingDlgInit(HWND hWnd,CM_SETTING_DLG * d)1078 void CmSettingDlgInit(HWND hWnd, CM_SETTING_DLG *d)
1079 {
1080 	CM_SETTING a;
1081 	// Validate arguments
1082 	if (hWnd == NULL || d == NULL)
1083 	{
1084 		return;
1085 	}
1086 
1087 	// Get the configuration of the current vpnclient
1088 	Zero(&a, sizeof(a));
1089 	CcGetCmSetting(cm->Client, &a);
1090 
1091 	Check(hWnd, R_EASY, a.EasyMode);
1092 	Check(hWnd, R_NORMAL, a.EasyMode == false);
1093 
1094 	if (a.EasyMode == false)
1095 	{
1096 		Focus(hWnd, R_NORMAL);
1097 	}
1098 	else
1099 	{
1100 		Focus(hWnd, R_EASY);
1101 	}
1102 
1103 	Check(hWnd, R_LOCK, a.LockMode);
1104 
1105 	SetEnable(hWnd, R_EASY, cm->CmEasyModeSupported);
1106 
1107 	if (a.LockMode)
1108 	{
1109 		if (IsZero(a.HashedPassword, sizeof(a.HashedPassword)) == false)
1110 		{
1111 			// Password is set
1112 			SetText(hWnd, S_PASSWORD1, _UU("CM_SETTING_PASSWORD"));
1113 			Hide(hWnd, S_PASSWORD3);
1114 			Hide(hWnd, E_PASSWORD2);
1115 
1116 			d->CheckPassword = true;
1117 			Copy(d->HashedPassword, a.HashedPassword, sizeof(d->HashedPassword));
1118 		}
1119 	}
1120 
1121 	SetShow(hWnd, S_VGS1, cm->Client->IsVgcSupported);
1122 	SetShow(hWnd, S_VGS2, cm->Client->IsVgcSupported);
1123 	SetShow(hWnd, S_VGS3, cm->Client->IsVgcSupported);
1124 	SetShow(hWnd, B_VGS, cm->Client->IsVgcSupported);
1125 
1126 	CmSettingDlgUpdate(hWnd, d);
1127 }
1128 
1129 // Update the operation mode changing dialog
CmSettingDlgUpdate(HWND hWnd,CM_SETTING_DLG * d)1130 void CmSettingDlgUpdate(HWND hWnd, CM_SETTING_DLG *d)
1131 {
1132 	bool ok = true;
1133 	char tmp1[MAX_SIZE], tmp2[MAX_SIZE];
1134 	// Validate arguments
1135 	if (hWnd == NULL || d == NULL)
1136 	{
1137 		return;
1138 	}
1139 
1140 	GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
1141 	GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
1142 
1143 	if (d->CheckPassword == false)
1144 	{
1145 		if (IsChecked(hWnd, R_LOCK))
1146 		{
1147 			if (StrCmp(tmp1, tmp2) != 0)
1148 			{
1149 				ok = false;
1150 			}
1151 		}
1152 	}
1153 	else
1154 	{
1155 		bool password_ok = false;
1156 		UCHAR hash[SHA1_SIZE];
1157 
1158 		Hash(hash, tmp1, StrLen(tmp1), true);
1159 		if (Cmp(hash, d->HashedPassword, sizeof(hash)) == 0)
1160 		{
1161 			password_ok = true;
1162 		}
1163 
1164 		if (password_ok == false)
1165 		{
1166 			Check(hWnd, R_LOCK, true);
1167 			Disable(hWnd, R_LOCK);
1168 		}
1169 		else
1170 		{
1171 			Enable(hWnd, R_LOCK);
1172 		}
1173 	}
1174 
1175 	SetEnable(hWnd, S_PASSWORD1, IsChecked(hWnd, R_LOCK));
1176 	SetEnable(hWnd, S_PASSWORD2, IsChecked(hWnd, R_LOCK));
1177 	SetEnable(hWnd, S_PASSWORD3, IsChecked(hWnd, R_LOCK));
1178 	SetEnable(hWnd, E_PASSWORD1, IsChecked(hWnd, R_LOCK));
1179 	SetEnable(hWnd, E_PASSWORD2, IsChecked(hWnd, R_LOCK));
1180 
1181 	SetEnable(hWnd, IDOK, ok);
1182 }
1183 
1184 // Operation mode changing dialog OK
CmSettingDlgOnOk(HWND hWnd,CM_SETTING_DLG * d)1185 void CmSettingDlgOnOk(HWND hWnd, CM_SETTING_DLG *d)
1186 {
1187 	CM_SETTING a;
1188 	char tmp1[MAX_SIZE], tmp2[MAX_SIZE];
1189 	// Validate arguments
1190 	if (hWnd == NULL || d == NULL)
1191 	{
1192 		return;
1193 	}
1194 
1195 	GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));
1196 	GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
1197 
1198 	Zero(&a, sizeof(a));
1199 
1200 	a.EasyMode = IsChecked(hWnd, R_EASY);
1201 	a.LockMode = IsChecked(hWnd, R_LOCK);
1202 
1203 	if (a.LockMode)
1204 	{
1205 		if (d->CheckPassword && IsEnable(hWnd, R_LOCK) == false)
1206 		{
1207 			Copy(a.HashedPassword, d->HashedPassword, sizeof(a.HashedPassword));
1208 		}
1209 		else
1210 		{
1211 			if (StrLen(tmp1) >= 1)
1212 			{
1213 				Hash(a.HashedPassword, tmp1, StrLen(tmp1), true);
1214 			}
1215 		}
1216 	}
1217 
1218 	CcSetCmSetting(cm->Client, &a);
1219 
1220 	EndDialog(hWnd, true);
1221 }
1222 
1223 // Operation mode changing dialog
CmSettingDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1224 UINT CmSettingDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1225 {
1226 	CM_SETTING_DLG *d = (CM_SETTING_DLG *)param;
1227 	// Validate arguments
1228 	if (hWnd == NULL)
1229 	{
1230 		return 0;
1231 	}
1232 
1233 	switch (msg)
1234 	{
1235 	case WM_INITDIALOG:
1236 		CmSettingDlgInit(hWnd, d);
1237 		break;
1238 
1239 	case WM_COMMAND:
1240 		switch (LOWORD(wParam))
1241 		{
1242 		case R_EASY:
1243 		case R_NORMAL:
1244 		case R_LOCK:
1245 		case E_PASSWORD1:
1246 		case E_PASSWORD2:
1247 		case IDOK:
1248 		case IDCANCEL:
1249 			CmSettingDlgUpdate(hWnd, d);
1250 			break;
1251 		}
1252 		switch (wParam)
1253 		{
1254 		case IDOK:
1255 			CmSettingDlgOnOk(hWnd, d);
1256 			break;
1257 
1258 		case IDCANCEL:
1259 			Close(hWnd);
1260 			break;
1261 
1262 		case R_LOCK:
1263 			if (IsChecked(hWnd, R_LOCK))
1264 			{
1265 				if (IsEmpty(hWnd, E_PASSWORD1))
1266 				{
1267 					Focus(hWnd, E_PASSWORD1);
1268 				}
1269 			}
1270 			break;
1271 
1272 		}
1273 		break;
1274 
1275 	case WM_CLOSE:
1276 		EndDialog(hWnd, false);
1277 		break;
1278 	}
1279 
1280 	return 0;
1281 }
1282 
1283 
1284 // Change operation mode
CmSetting(HWND hWnd)1285 bool CmSetting(HWND hWnd)
1286 {
1287 	CM_SETTING_DLG d;
1288 
1289 	Zero(&d, sizeof(d));
1290 
1291 	return Dialog(hWnd, D_CM_SETTING, CmSettingDlg, &d);
1292 }
1293 
1294 
1295 // Attempting thread for starting the UI Helper
CmTryToExecUiHelperThread(THREAD * thread,void * param)1296 void CmTryToExecUiHelperThread(THREAD *thread, void *param)
1297 {
1298 	bool first_flag = true;
1299 
1300 	while (cm->TryExecUiHelperHalt == false && cm->WindowsShutdowning == false)
1301 	{
1302 		if (first_flag == false)
1303 		{
1304 			// Wait a little for other than the first time
1305 			Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL * 2);
1306 
1307 			if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)
1308 			{
1309 				break;
1310 			}
1311 		}
1312 		first_flag = false;
1313 
1314 		if (cm->TryExecUiHelperHalt == false && cm->WindowsShutdowning == false)
1315 		{
1316 			if (cm->TryExecUiHelperProcessHandle == NULL)
1317 			{
1318 				CmTryToExecUiHelper();
1319 			}
1320 		}
1321 
1322 		if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)
1323 		{
1324 			break;
1325 		}
1326 
1327 		if (cm->TryExecUiHelperProcessHandle == NULL)
1328 		{
1329 			Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL);
1330 		}
1331 		else
1332 		{
1333 			HANDLE handles[2];
1334 			handles[0] = cm->TryExecUiHelperProcessHandle;
1335 			handles[1] = (HANDLE)cm->TryExecUiHelperHaltEvent->pData;
1336 			WaitForMultipleObjects(2, handles, false, CM_TRY_EXEC_UI_HELPER_INTERVAL);
1337 
1338 			if (WaitForSingleObject(cm->TryExecUiHelperProcessHandle, 0) != WAIT_TIMEOUT)
1339 			{
1340 				CloseHandle(cm->TryExecUiHelperProcessHandle);
1341 				cm->TryExecUiHelperProcessHandle = NULL;
1342 				if (cm->TryExecUiHelperHalt || cm->WindowsShutdowning)
1343 				{
1344 					break;
1345 				}
1346 				Wait(cm->TryExecUiHelperHaltEvent, CM_TRY_EXEC_UI_HELPER_INTERVAL * 2);
1347 			}
1348 		}
1349 	}
1350 }
1351 
1352 // Stop the UI Helper
CmFreeTryToExecUiHelper()1353 void CmFreeTryToExecUiHelper()
1354 {
1355 	cm->TryExecUiHelperHalt = true;
1356 	Set(cm->TryExecUiHelperHaltEvent);
1357 
1358 	WaitThread(cm->TryExecUiHelperThread, INFINITE);
1359 
1360 	ReleaseThread(cm->TryExecUiHelperThread);
1361 	cm->TryExecUiHelperThread = NULL;
1362 
1363 	ReleaseEvent(cm->TryExecUiHelperHaltEvent);
1364 	cm->TryExecUiHelperHaltEvent = NULL;
1365 
1366 	cm->TryExecUiHelperHalt = false;
1367 	cm->TryExecUiHelperProcessHandle = NULL;
1368 }
1369 
1370 // Initialize the UI Helper starting
CmInitTryToExecUiHelper()1371 void CmInitTryToExecUiHelper()
1372 {
1373 	cm->TryExecUiHelperProcessHandle = NULL;
1374 	cm->TryExecUiHelperHalt = false;
1375 	cm->TryExecUiHelperHaltEvent = NewEvent();
1376 	cm->TryExecUiHelperThread = NewThread(CmTryToExecUiHelperThread, NULL);
1377 }
1378 
1379 // Start the UI Helper
CmExecUiHelperMain()1380 void *CmExecUiHelperMain()
1381 {
1382 	HANDLE h;
1383 	wchar_t tmp[MAX_SIZE];
1384 
1385 	UniFormat(tmp, sizeof(tmp), L"%s\\%S", MsGetExeDirNameW(), CiGetVpnClientExeFileName());
1386 
1387 	// Start
1388 	h = Win32RunExW(tmp, SVC_ARG_UIHELP_W, false);
1389 
1390 	return (void *)h;
1391 }
1392 
1393 // Attempt to start the UI Helper
CmTryToExecUiHelper()1394 void CmTryToExecUiHelper()
1395 {
1396 	HANDLE h;
1397 	// Check that it isn't already running
1398 	if (CnCheckAlreadyExists(false))
1399 	{
1400 		// It have already started
1401 		return;
1402 	}
1403 
1404 	h = (HANDLE)CmExecUiHelperMain();
1405 
1406 	if (h != NULL)
1407 	{
1408 		cm->TryExecUiHelperProcessHandle = h;
1409 	}
1410 }
1411 
1412 // Initialize the dialog
CmTrafficResultDlgInit(HWND hWnd,TT_RESULT * res)1413 void CmTrafficResultDlgInit(HWND hWnd, TT_RESULT *res)
1414 {
1415 	LVB *ct;
1416 	wchar_t tmp[MAX_SIZE];
1417 	wchar_t tmp1[MAX_SIZE];
1418 	wchar_t tmp2[MAX_SIZE];
1419 	char str[MAX_SIZE];
1420 	// Validate arguments
1421 	if (hWnd == NULL || res == NULL)
1422 	{
1423 		return;
1424 	}
1425 
1426 	SetIcon(hWnd, 0, ICO_SWITCH);
1427 
1428 	SetFont(hWnd, L_STATUS, GetFont(_SS("DEFAULT_FONT_2"), 10, false, false, false, false));
1429 
1430 	LvInit(hWnd, L_STATUS);
1431 	LvSetStyle(hWnd, L_STATUS, LVS_EX_GRIDLINES);
1432 	LvInsertColumn(hWnd, L_STATUS, 0, _UU("TTC_RES_COLUMN_1"), 100);
1433 	LvInsertColumn(hWnd, L_STATUS, 1, _UU("TTC_RES_COLUMN_2"), 100);
1434 	LvInsertColumn(hWnd, L_STATUS, 2, _UU("TTC_RES_COLUMN_3"), 100);
1435 
1436 	ct = LvInsertStart();
1437 
1438 	// Time that was used to measure
1439 	GetSpanStrMilli(str, sizeof(str), res->Span);
1440 	StrToUni(tmp, sizeof(tmp), str);
1441 	LvInsertAdd(ct, ICO_DATETIME, NULL, 3, _UU("TTC_RES_SPAN"), tmp, L"");
1442 
1443 	// Correct the data for Ethernet frame
1444 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_ETHER"), res->Raw ? _UU("SEC_NO") : _UU("SEC_YES"), L"");
1445 
1446 	// Amount of communication data of download direction
1447 	ToStr3(str, sizeof(str), res->NumBytesDownload);
1448 	UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
1449 	ToStrByte1000(str, sizeof(str), res->NumBytesDownload);
1450 	StrToUni(tmp2, sizeof(tmp2), str);
1451 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_DOWNLOAD"), tmp1, tmp2);
1452 
1453 	// Amount of communication data of upload direction
1454 	ToStr3(str, sizeof(str), res->NumBytesUpload);
1455 	UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
1456 	ToStrByte1000(str, sizeof(str), res->NumBytesUpload);
1457 	StrToUni(tmp2, sizeof(tmp2), str);
1458 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_UPLOAD"), tmp1, tmp2);
1459 
1460 	// Total amount of communication data
1461 	ToStr3(str, sizeof(str), res->NumBytesTotal);
1462 	UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);
1463 	ToStrByte1000(str, sizeof(str), res->NumBytesTotal);
1464 	StrToUni(tmp2, sizeof(tmp2), str);
1465 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BYTES_TOTAL"), tmp1, tmp2);
1466 
1467 	// Calculate the total throughput of input and output of the relay equipment
1468 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_DOUBLE"), (res->Double == false) ? _UU("SEC_NO") : _UU("SEC_YES"), L"");
1469 
1470 	// Average throughput of download direction
1471 	ToStr3(str, sizeof(str), res->BpsDownload);
1472 	UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
1473 	ToStrByte1000(str, sizeof(str), res->BpsDownload);
1474 	ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
1475 	StrToUni(tmp2, sizeof(tmp2), str);
1476 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_DOWNLOAD"), tmp1, tmp2);
1477 
1478 	// Average throughput of upload direction
1479 	ToStr3(str, sizeof(str), res->BpsUpload);
1480 	UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
1481 	ToStrByte1000(str, sizeof(str), res->BpsUpload);
1482 	ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
1483 	StrToUni(tmp2, sizeof(tmp2), str);
1484 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_UPLOAD"), tmp1, tmp2);
1485 
1486 	// Total average throughput
1487 	ToStr3(str, sizeof(str), res->BpsTotal);
1488 	UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);
1489 	ToStrByte1000(str, sizeof(str), res->BpsTotal);
1490 	ReplaceStr(str, sizeof(str), str, "Bytes", "bps");
1491 	StrToUni(tmp2, sizeof(tmp2), str);
1492 	LvInsertAdd(ct, ICO_INFORMATION, NULL, 3, _UU("TTC_RES_BPS_TOTAL"), tmp1, tmp2);
1493 
1494 	LvInsertEnd(ct, hWnd, L_STATUS);
1495 
1496 	LvAutoSize(hWnd, L_STATUS);
1497 }
1498 
1499 // Dialog procedure to display results of traffic measurements
CmTrafficResultDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1500 UINT CmTrafficResultDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1501 {
1502 	TT_RESULT *r = (TT_RESULT *)param;
1503 	// Validate arguments
1504 	if (hWnd == NULL)
1505 	{
1506 		return 0;
1507 	}
1508 
1509 	switch (msg)
1510 	{
1511 	case WM_INITDIALOG:
1512 		CmTrafficResultDlgInit(hWnd, r);
1513 		break;
1514 
1515 	case WM_COMMAND:
1516 		switch (wParam)
1517 		{
1518 		case IDOK:
1519 		case IDCANCEL:
1520 			Close(hWnd);
1521 			break;
1522 		}
1523 		break;
1524 
1525 	case WM_CLOSE:
1526 		EndDialog(hWnd, 0);
1527 		break;
1528 	}
1529 
1530 	return 0;
1531 }
1532 
1533 // Display results of traffic measurement
CmTrafficResult(HWND hWnd,TT_RESULT * r)1534 void CmTrafficResult(HWND hWnd, TT_RESULT *r)
1535 {
1536 	// Validate arguments
1537 	if (r == NULL)
1538 	{
1539 		return;
1540 	}
1541 
1542 	Dialog(hWnd, D_CM_TRAFFIC_RESULT, CmTrafficResultDlg, r);
1543 }
1544 
1545 // Thread to wait for the termination of the client
CmTrafficRunDlgClientWaitThread(THREAD * t,void * param)1546 void CmTrafficRunDlgClientWaitThread(THREAD *t, void *param)
1547 {
1548 	CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
1549 	TT_RESULT result;
1550 	UINT ret;
1551 	// Validate arguments
1552 	if (t == NULL || param == NULL)
1553 	{
1554 		return;
1555 	}
1556 
1557 	Zero(&result, sizeof(result));
1558 	ret = FreeTtc(d->Ttc, &result);
1559 	d->Ttc = NULL;
1560 
1561 	d->RetCode = ret;
1562 	Copy(&d->Result, &result, sizeof(TT_RESULT));
1563 
1564 	PostMessage(d->hWnd, WM_APP + 66, 0, 0);
1565 }
1566 
1567 // Append the string
CmTrafficRunDlgAddStr(HWND hWnd,wchar_t * str)1568 void CmTrafficRunDlgAddStr(HWND hWnd, wchar_t *str)
1569 {
1570 	wchar_t *tmp;
1571 	UINT tmp_size;
1572 
1573 	tmp_size = UniStrSize(str) + 32;
1574 	tmp = Malloc(tmp_size);
1575 	UniStrCpy(tmp, tmp_size, str);
1576 	if (UniEndWith(str, L"\n") == false)
1577 	{
1578 		UniStrCat(tmp, tmp_size, L"\n");
1579 	}
1580 
1581 	UniReplaceStrEx(tmp, tmp_size, tmp, L"\r\n", L"\n", false);
1582 	UniReplaceStrEx(tmp, tmp_size, tmp, L"\n", L"\r\n", false);
1583 
1584 	if (MsIsNt())
1585 	{
1586 		SendMsg(hWnd, E_EDIT, EM_SETSEL, 0x7fffffff, 0x7fffffff);
1587 		SendMsg(hWnd, E_EDIT, EM_REPLACESEL, false, (LPARAM)tmp);
1588 	}
1589 	else
1590 	{
1591 		char *s = CopyUniToStr(tmp);
1592 		UINT len;
1593 
1594 		len = GetWindowTextLength(DlgItem(hWnd, E_EDIT));
1595 		SendMsg(hWnd, E_EDIT, EM_SETSEL, 0x7fffffff, 0x7fffffff);
1596 		SendMsg(hWnd, E_EDIT, EM_SETSEL, len, len);
1597 		SendMsg(hWnd, E_EDIT, EM_REPLACESEL, false, (LPARAM)s);
1598 		Free(s);
1599 	}
1600 
1601 	Free(tmp);
1602 }
1603 
1604 // Show the string
CmTrafficRunDlgPrintProc(void * param,wchar_t * str)1605 void CmTrafficRunDlgPrintProc(void *param, wchar_t *str)
1606 {
1607 	CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
1608 	HWND hWnd;
1609 	// Validate arguments
1610 	if (param == NULL || str == NULL)
1611 	{
1612 		return;
1613 	}
1614 
1615 	hWnd = d->hWnd;
1616 
1617 	PostMessage(hWnd, WM_APP + 64, 0, (LPARAM)UniCopyStr(str));
1618 }
1619 
1620 // Thread for stop the measurement program
CmTrafficRunDlgHaltThread(THREAD * t,void * param)1621 void CmTrafficRunDlgHaltThread(THREAD *t, void *param)
1622 {
1623 	CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
1624 	// Validate arguments
1625 	if (t == NULL || param == NULL)
1626 	{
1627 		return;
1628 	}
1629 
1630 	if (d->Setting->ServerMode)
1631 	{
1632 		// Stop the server
1633 		d->RetCode = FreeTts(d->Tts);
1634 
1635 		PostMessage(d->hWnd, WM_APP + 65, 0, 0);
1636 	}
1637 }
1638 
1639 // Stop the measurement program
CmTrafficRunDlgHalt(HWND hWnd,CM_TRAFFIC_DLG * d)1640 void CmTrafficRunDlgHalt(HWND hWnd, CM_TRAFFIC_DLG *d)
1641 {
1642 	// Validate arguments
1643 	if (hWnd == NULL || d == NULL)
1644 	{
1645 		return;
1646 	}
1647 
1648 	if (d->Started == false)
1649 	{
1650 		return;
1651 	}
1652 
1653 	if (d->Setting->ServerMode)
1654 	{
1655 		if (d->HaltThread == NULL)
1656 		{
1657 			Disable(hWnd, IDCANCEL);
1658 			d->HaltThread = NewThread(CmTrafficRunDlgHaltThread, d);
1659 		}
1660 	}
1661 	else
1662 	{
1663 		if (d->ClientEndWaitThread != NULL)
1664 		{
1665 			StopTtc(d->Ttc);
1666 		}
1667 		else
1668 		{
1669 			EndDialog(hWnd, 0);
1670 		}
1671 	}
1672 }
1673 
1674 // Start the operation of traffic measurement
CmTrafficRunDlgStart(HWND hWnd,CM_TRAFFIC_DLG * d)1675 void CmTrafficRunDlgStart(HWND hWnd, CM_TRAFFIC_DLG *d)
1676 {
1677 	// Validate arguments
1678 	if (hWnd == NULL || d == NULL)
1679 	{
1680 		return;
1681 	}
1682 
1683 	if (d->Setting->ServerMode)
1684 	{
1685 		// Start the measurement server
1686 		d->Tts = NewTts(d->Setting->Port, d, CmTrafficRunDlgPrintProc);
1687 	}
1688 	else
1689 	{
1690 		// Start the measurement client
1691 		d->Ttc = NewTtc(d->Setting->Host, d->Setting->Port,
1692 			d->Setting->NumTcp, d->Setting->Type, d->Setting->Span * 1000ULL,
1693 			d->Setting->Double, d->Setting->Raw, CmTrafficRunDlgPrintProc, d);
1694 
1695 		d->ClientEndWaitThread = NewThread(CmTrafficRunDlgClientWaitThread, d);
1696 	}
1697 
1698 	d->Started = true;
1699 }
1700 
1701 // Traffic measurement operation dialog initialization
CmTrafficRunDlgInit(HWND hWnd,CM_TRAFFIC_DLG * d)1702 void CmTrafficRunDlgInit(HWND hWnd, CM_TRAFFIC_DLG *d)
1703 {
1704 	// Validate arguments
1705 	if (hWnd == NULL || d == NULL)
1706 	{
1707 		return;
1708 	}
1709 
1710 	d->hWnd = hWnd;
1711 
1712 	SetIcon(hWnd, 0, ICO_SWITCH);
1713 	DlgFont(hWnd, S_INFO, 11, false);
1714 	SetFont(hWnd, E_EDIT, GetFont(_SS("DEFAULT_FONT_2"), 0, false, false,
1715 		false, false));
1716 
1717 	Focus(hWnd, IDCANCEL);
1718 }
1719 
1720 // Traffic measurement operation dialog procedure
CmTrafficRunDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1721 UINT CmTrafficRunDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1722 {
1723 	CM_TRAFFIC_DLG *d = (CM_TRAFFIC_DLG *)param;
1724 	wchar_t *s;
1725 	// Validate arguments
1726 	if (hWnd == NULL)
1727 	{
1728 		return 0;
1729 	}
1730 
1731 	switch (msg)
1732 	{
1733 	case WM_INITDIALOG:
1734 		CmTrafficRunDlgInit(hWnd, d);
1735 
1736 		SetTimer(hWnd, 1, 10, NULL);
1737 		break;
1738 
1739 	case WM_APP + 64:
1740 		// Add a string
1741 		s = (wchar_t *)lParam;
1742 		if (s != NULL)
1743 		{
1744 			CmTrafficRunDlgAddStr(hWnd, s);
1745 			Free(s);
1746 		}
1747 		break;
1748 
1749 	case WM_APP + 65:
1750 		// Stopping complete
1751 		if (d->HaltThread != NULL)
1752 		{
1753 			WaitThread(d->HaltThread, INFINITE);
1754 			ReleaseThread(d->HaltThread);
1755 			d->HaltThread = NULL;
1756 			EndDialog(hWnd, 0);
1757 		}
1758 		break;
1759 
1760 	case WM_APP + 66:
1761 		// Show results
1762 		if (d->RetCode == ERR_NO_ERROR)
1763 		{
1764 			CmTrafficResult(hWnd, &d->Result);
1765 		}
1766 
1767 		if (d->ClientEndWaitThread != NULL)
1768 		{
1769 			WaitThread(d->ClientEndWaitThread, INFINITE);
1770 			ReleaseThread(d->ClientEndWaitThread);
1771 			d->ClientEndWaitThread = NULL;
1772 		}
1773 
1774 		if (d->CloseDialogAfter)
1775 		{
1776 			EndDialog(hWnd, 0);
1777 		}
1778 		break;
1779 
1780 	case WM_TIMER:
1781 		switch (wParam)
1782 		{
1783 		case 1:
1784 			KillTimer(hWnd, 1);
1785 
1786 			CmTrafficRunDlgStart(hWnd, d);
1787 			break;
1788 		}
1789 		break;
1790 
1791 	case WM_COMMAND:
1792 		switch (wParam)
1793 		{
1794 		case IDOK:
1795 		case IDCANCEL:
1796 			Close(hWnd);
1797 			break;
1798 		}
1799 		break;
1800 
1801 	case WM_CLOSE:
1802 		d->CloseDialogAfter = true;
1803 		CmTrafficRunDlgHalt(hWnd, d);
1804 		return 1;
1805 	}
1806 
1807 	return 0;
1808 }
1809 
1810 // Execute a traffic measurement
CmExecTraffic(HWND hWnd,CM_TRAFFIC * t)1811 void CmExecTraffic(HWND hWnd, CM_TRAFFIC *t)
1812 {
1813 	CM_TRAFFIC_DLG d;
1814 	// Validate arguments
1815 	if (t == NULL)
1816 	{
1817 		return;
1818 	}
1819 
1820 	Zero(&d, sizeof(d));
1821 	d.Setting = t;
1822 	d.ResultShowEvent = NewEvent();
1823 
1824 	MsSetThreadPriorityHigh();
1825 	Dialog(hWnd, D_CM_TRAFFIC_RUN, CmTrafficRunDlg, &d);
1826 	MsRestoreThreadPriority();
1827 
1828 	ReleaseEvent(d.ResultShowEvent);
1829 }
1830 
1831 // Write the settings to the registry
CmTrafficSaveToReg(CM_TRAFFIC * t)1832 void CmTrafficSaveToReg(CM_TRAFFIC *t)
1833 {
1834 	// Validate arguments
1835 	if (t == NULL)
1836 	{
1837 		return;
1838 	}
1839 
1840 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "ServerMode", t->ServerMode ? 1 : 0);
1841 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Double", t->Double ? 1 : 0);
1842 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Raw", t->Raw ? 1 : 0);
1843 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Port", t->Port);
1844 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "NumTcp", t->NumTcp);
1845 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Type", t->Type);
1846 	MsRegWriteInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Span", t->Span);
1847 	MsRegWriteStr(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Host", t->Host);
1848 }
1849 
1850 // Read the settings from the registry
CmTrafficLoadFromReg(CM_TRAFFIC * t)1851 bool CmTrafficLoadFromReg(CM_TRAFFIC *t)
1852 {
1853 	char *s;
1854 	// Validate arguments
1855 	if (t == NULL)
1856 	{
1857 		return false;
1858 	}
1859 
1860 	Zero(t, sizeof(CM_TRAFFIC));
1861 
1862 	if (MsRegIsKey(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY) == false)
1863 	{
1864 		return false;
1865 	}
1866 
1867 	t->Double = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Double") == 0 ? false : true;
1868 	t->Raw = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Raw") == 0 ? false : true;
1869 	t->Port = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Port");
1870 	if (t->Port == 0)
1871 	{
1872 		t->Port = TRAFFIC_DEFAULT_PORT;
1873 	}
1874 
1875 	s = MsRegReadStr(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Host");
1876 
1877 	if (IsEmptyStr(s) == false)
1878 	{
1879 		Trim(s);
1880 		StrCpy(t->Host, sizeof(t->Host), s);
1881 	}
1882 
1883 	Free(s);
1884 
1885 	t->NumTcp = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "NumTcp");
1886 	t->NumTcp = MAKESURE(t->NumTcp, 1, TRAFFIC_NUMTCP_MAX);
1887 	t->Type = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Type");
1888 
1889 	if (t->Type != TRAFFIC_TYPE_DOWNLOAD && t->Type != TRAFFIC_TYPE_UPLOAD &&
1890 		t->Type != TRAFFIC_TYPE_FULL)
1891 	{
1892 		t->Type = TRAFFIC_TYPE_FULL;
1893 	}
1894 
1895 	t->Span = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "Span");
1896 	if (t->Span == 0)
1897 	{
1898 		t->Span = TRAFFIC_SPAN_DEFAULT;
1899 	}
1900 
1901 	t->ServerMode = MsRegReadInt(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "ServerMode") == 0 ? false : true;
1902 
1903 	return true;
1904 }
1905 
1906 // Get the default settings
CmTrafficGetDefaultSetting(CM_TRAFFIC * t)1907 void CmTrafficGetDefaultSetting(CM_TRAFFIC *t)
1908 {
1909 	// Validate arguments
1910 	if (t == NULL)
1911 	{
1912 		return;
1913 	}
1914 
1915 	Zero(t, sizeof(CM_TRAFFIC));
1916 
1917 	t->Double = false;
1918 	t->Raw = false;
1919 	t->Port = TRAFFIC_DEFAULT_PORT;
1920 	t->NumTcp = TRAFFIC_NUMTCP_DEFAULT;
1921 	t->Type = TRAFFIC_TYPE_FULL;
1922 	t->Span = TRAFFIC_SPAN_DEFAULT;
1923 	t->ServerMode = false;
1924 }
1925 
1926 // Communication throughput measurement tool dialog initialization
CmTrafficDlgInit(HWND hWnd)1927 void CmTrafficDlgInit(HWND hWnd)
1928 {
1929 	CM_TRAFFIC t;
1930 	LIST *c1, *c2;
1931 	UINT i;
1932 	// Validate arguments
1933 	if (hWnd == NULL)
1934 	{
1935 		return;
1936 	}
1937 
1938 	DlgFont(hWnd, S_8, 9, true);
1939 	DlgFont(hWnd, S_3, 9, true);
1940 
1941 	Zero(&t, sizeof(t));
1942 	if (CmTrafficLoadFromReg(&t) == false)
1943 	{
1944 		CmTrafficGetDefaultSetting(&t);
1945 	}
1946 
1947 	// Write the settings to the dialog
1948 	Check(hWnd, R_SERVER, t.ServerMode);
1949 	Check(hWnd, R_CLIENT, t.ServerMode == false);
1950 
1951 	c1 = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "HostCandidate");
1952 	if (c1 != NULL)
1953 	{
1954 		UINT i;
1955 
1956 		CbReset(hWnd, C_HOST);
1957 
1958 		for (i = 0;i < LIST_NUM(c1);i++)
1959 		{
1960 			CANDIDATE *c = LIST_DATA(c1, i);
1961 
1962 			CbAddStr(hWnd, C_HOST, c->Str, 0);
1963 		}
1964 
1965 		FreeCandidateList(c1);
1966 	}
1967 
1968 	if (CbNum(hWnd, C_HOST) == 0)
1969 	{
1970 		CbAddStr(hWnd, C_HOST, L"speed.softether.com", 0);
1971 	}
1972 
1973 	if (IsEmptyStr(t.Host) == false)
1974 	{
1975 		SetTextA(hWnd, C_HOST, t.Host);
1976 	}
1977 
1978 	c2 = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "PortCandidate");
1979 	if (c2 != NULL)
1980 	{
1981 		UINT i;
1982 
1983 		if (t.Port != 0)
1984 		{
1985 			wchar_t tmp[32];
1986 
1987 			UniToStru(tmp, t.Port);
1988 
1989 			AddCandidate(c2, tmp, 0);
1990 		}
1991 
1992 		CbReset(hWnd, C_PORT);
1993 
1994 		for (i = 0;i < LIST_NUM(c2);i++)
1995 		{
1996 			CANDIDATE *c = LIST_DATA(c2, i);
1997 
1998 			CbAddStr(hWnd, C_PORT, c->Str, 0);
1999 		}
2000 
2001 		FreeCandidateList(c2);
2002 	}
2003 
2004 	CbReset(hWnd, C_NUM);
2005 
2006 	for (i = 1;i <= TRAFFIC_NUMTCP_MAX;i++)
2007 	{
2008 		wchar_t tmp[32];
2009 
2010 		UniToStru(tmp, i);
2011 
2012 		CbAddStr(hWnd, C_NUM, tmp, i);
2013 	}
2014 
2015 	CbSelect(hWnd, C_NUM, t.NumTcp);
2016 
2017 	Check(hWnd, R_DOWNLOAD, t.Type == TRAFFIC_TYPE_DOWNLOAD);
2018 	Check(hWnd, R_UPLOAD, t.Type == TRAFFIC_TYPE_UPLOAD);
2019 	Check(hWnd, R_FULL, t.Type == TRAFFIC_TYPE_FULL);
2020 
2021 	Check(hWnd, R_ETHERNET, t.Raw ? false : true);
2022 	Check(hWnd, R_DOUBLE, t.Double);
2023 
2024 	SetIntEx(hWnd, E_SPAN, t.Span);
2025 
2026 	CmTrafficDlgUpdate(hWnd);
2027 }
2028 
2029 // Put the contents of the dialog to structure
CmTrafficDlgToStruct(HWND hWnd,CM_TRAFFIC * t)2030 void CmTrafficDlgToStruct(HWND hWnd, CM_TRAFFIC *t)
2031 {
2032 	// Validate arguments
2033 	if (hWnd == NULL || t == NULL)
2034 	{
2035 		return;
2036 	}
2037 
2038 	Zero(t, sizeof(CM_TRAFFIC));
2039 	t->ServerMode = IsChecked(hWnd, R_SERVER);
2040 	GetTxtA(hWnd, C_HOST, t->Host, sizeof(t->Host));
2041 	Trim(t->Host);
2042 
2043 	t->Port = GetInt(hWnd, C_PORT);
2044 	t->NumTcp = CbGetSelect(hWnd, C_NUM);
2045 	t->Span = GetInt(hWnd, E_SPAN);
2046 	t->Raw = IsChecked(hWnd, R_ETHERNET) ? false : true;
2047 	t->Double = IsChecked(hWnd, R_DOUBLE);
2048 
2049 	if (IsChecked(hWnd, R_DOWNLOAD))
2050 	{
2051 		t->Type = TRAFFIC_TYPE_DOWNLOAD;
2052 	}
2053 	else if (IsChecked(hWnd, R_UPLOAD))
2054 	{
2055 		t->Type = TRAFFIC_TYPE_UPLOAD;
2056 	}
2057 	else
2058 	{
2059 		t->Type = TRAFFIC_TYPE_FULL;
2060 	}
2061 }
2062 
2063 // Communication throughput measurement tool dialog update
CmTrafficDlgUpdate(HWND hWnd)2064 bool CmTrafficDlgUpdate(HWND hWnd)
2065 {
2066 	CM_TRAFFIC t;
2067 	bool ok = true;
2068 	bool client_only;
2069 	// Validate arguments
2070 	if (hWnd == NULL)
2071 	{
2072 		return false;
2073 	}
2074 
2075 	CmTrafficDlgToStruct(hWnd, &t);
2076 
2077 	client_only = t.ServerMode ? false : true;
2078 
2079 	SetEnable(hWnd, C_HOST, client_only);
2080 	SetEnable(hWnd, S_5, client_only);
2081 	SetEnable(hWnd, S_8, client_only);
2082 	SetEnable(hWnd, S_9, client_only);
2083 	SetEnable(hWnd, R_DOWNLOAD, client_only);
2084 	SetEnable(hWnd, R_UPLOAD, client_only);
2085 	SetEnable(hWnd, R_FULL, client_only);
2086 	SetEnable(hWnd, S_10, client_only);
2087 	SetEnable(hWnd, S_11, client_only);
2088 	SetEnable(hWnd, C_NUM, client_only);
2089 	SetEnable(hWnd, S_14, client_only);
2090 	SetEnable(hWnd, S_12, client_only);
2091 	SetEnable(hWnd, E_SPAN, client_only);
2092 	SetEnable(hWnd, S_13, client_only);
2093 	SetEnable(hWnd, R_ETHERNET, client_only);
2094 	SetEnable(hWnd, R_DOUBLE, client_only);
2095 
2096 	if (t.Port == 0 || t.Port >= 65536)
2097 	{
2098 		ok = false;
2099 	}
2100 
2101 	if (t.ServerMode == false)
2102 	{
2103 		if (IsEmptyStr(t.Host))
2104 		{
2105 			ok = false;
2106 		}
2107 
2108 		if (t.NumTcp == 0 || t.NumTcp >= 33)
2109 		{
2110 			ok = false;
2111 		}
2112 
2113 		if (t.Span == 0)
2114 		{
2115 			ok = false;
2116 		}
2117 
2118 		if (t.Type == TRAFFIC_TYPE_FULL && ((t.NumTcp % 2) != 0))
2119 		{
2120 			ok = false;
2121 		}
2122 	}
2123 
2124 	SetEnable(hWnd, IDOK, ok);
2125 
2126 	return ok;
2127 }
2128 
2129 // Communication throughput measurement tool dialog OK button
CmTrafficDlgOnOk(HWND hWnd)2130 void CmTrafficDlgOnOk(HWND hWnd)
2131 {
2132 	CM_TRAFFIC t;
2133 	LIST *c;
2134 	// Validate arguments
2135 	if (hWnd == NULL)
2136 	{
2137 		return;
2138 	}
2139 
2140 	// Get the basic data
2141 	CmTrafficDlgToStruct(hWnd, &t);
2142 
2143 	// Save to registry
2144 	CmTrafficSaveToReg(&t);
2145 
2146 	// Retrieve and save the server name candidate
2147 	if (IsEmptyStr(t.Host) == false)
2148 	{
2149 		c = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "HostCandidate");
2150 		if (c != NULL)
2151 		{
2152 			wchar_t tmp[MAX_SIZE];
2153 
2154 			StrToUni(tmp, sizeof(tmp), t.Host);
2155 			AddCandidate(c, tmp, 0);
2156 
2157 			WriteCandidateToReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, c, "HostCandidate");
2158 
2159 			FreeCandidateList(c);
2160 		}
2161 	}
2162 
2163 	if (t.Port != 0 && t.Port <= 65536)
2164 	{
2165 		// Retrieve and store the port number candidate
2166 		c = ReadCandidateFromReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, "PortCandidate");
2167 		if (c != NULL)
2168 		{
2169 			wchar_t tmp[MAX_SIZE];
2170 
2171 			UniToStru(tmp, t.Port);
2172 			AddCandidate(c, tmp, 0);
2173 
2174 			WriteCandidateToReg(REG_CURRENT_USER, CM_TRAFFIC_REG_KEY, c, "PortCandidate");
2175 
2176 			FreeCandidateList(c);
2177 		}
2178 	}
2179 
2180 	// Execute
2181 	CmExecTraffic(hWnd, &t);
2182 
2183 	// Update the dialog
2184 	CmTrafficDlgInit(hWnd);
2185 }
2186 
2187 // Communication throughput measurement tool dialog procedure
CmTrafficDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2188 UINT CmTrafficDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2189 {
2190 	// Validate arguments
2191 	if (hWnd == NULL)
2192 	{
2193 		return 0;
2194 	}
2195 
2196 	switch (msg)
2197 	{
2198 	case WM_INITDIALOG:
2199 		SetIcon(hWnd, 0, ICO_SWITCH);
2200 		CmTrafficDlgInit(hWnd);
2201 		break;
2202 
2203 	case WM_COMMAND:
2204 		switch (LOWORD(wParam))
2205 		{
2206 		case R_SERVER:
2207 		case R_CLIENT:
2208 		case C_HOST:
2209 		case C_PORT:
2210 		case R_DOWNLOAD:
2211 		case R_UPLOAD:
2212 		case R_FULL:
2213 		case C_NUM:
2214 		case E_SPAN:
2215 		case R_ETHERNET:
2216 		case R_DOUBLE:
2217 			CmTrafficDlgUpdate(hWnd);
2218 			break;
2219 		}
2220 
2221 		switch (wParam)
2222 		{
2223 		case IDOK:
2224 			CmTrafficDlgOnOk(hWnd);
2225 			break;
2226 
2227 		case IDCANCEL:
2228 			Close(hWnd);
2229 			break;
2230 		}
2231 		break;
2232 
2233 	case WM_CLOSE:
2234 		EndDialog(hWnd, 0);
2235 		break;
2236 	}
2237 
2238 	return 0;
2239 }
2240 
2241 // Communication throughput measurement tool
CmTraffic(HWND hWnd)2242 void CmTraffic(HWND hWnd)
2243 {
2244 	Dialog(hWnd, D_CM_TRAFFIC, CmTrafficDlgProc, NULL);
2245 }
2246 
2247 // Delete old startup file
CmDeleteOldStartupTrayFile()2248 void CmDeleteOldStartupTrayFile()
2249 {
2250 	char tmp[MAX_SIZE];
2251 	char *tag = _SS("CM_JAPANESE_ONLY_OLD_STARTUP");
2252 	if (IsEmptyStr(tag))
2253 	{
2254 		return;
2255 	}
2256 
2257 	Format(tmp, sizeof(tmp), tag, MsGetCommonStartupDir());
2258 
2259 	FileDelete(tmp);
2260 }
2261 
2262 // PKCS license confirmation dialog
CmPkcsEulaDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2263 UINT CmPkcsEulaDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2264 {
2265 	UINT id;
2266 	SECURE_DEVICE *dev;
2267 	char *name;
2268 	// Validate arguments
2269 	if (hWnd == NULL)
2270 	{
2271 		return 0;
2272 	}
2273 
2274 	switch (msg)
2275 	{
2276 	case WM_INITDIALOG:
2277 		id = (UINT)param;
2278 		dev = GetSecureDevice(id);
2279 		if (dev == NULL)
2280 		{
2281 			EndDialog(hWnd, 0);
2282 			return 0;
2283 		}
2284 
2285 		name = dev->ModuleName;
2286 
2287 		FormatText(hWnd, S_INFO_1, name);
2288 		FormatText(hWnd, S_INFO_2, name, name);
2289 		FormatText(hWnd, S_INFO_3, name);
2290 
2291 		break;
2292 
2293 	case WM_COMMAND:
2294 		switch (wParam)
2295 		{
2296 		case IDOK:
2297 			EndDialog(hWnd, 1);
2298 			break;
2299 
2300 		case IDCANCEL:
2301 			Close(hWnd);
2302 			break;
2303 		}
2304 		break;
2305 
2306 	case WM_CLOSE:
2307 		EndDialog(hWnd, 0);
2308 		break;
2309 	}
2310 
2311 	return 0;
2312 }
2313 
2314 // Confirmation screen of whether the user accepts the EULA of the PKCS DLL
CmCheckPkcsEula(HWND hWnd,UINT id)2315 bool CmCheckPkcsEula(HWND hWnd, UINT id)
2316 {
2317 	return (Dialog(hWnd, D_CM_PKCSEULA, CmPkcsEulaDlg, (void *)id) == 0) ? false : true;
2318 }
2319 
2320 // Update controls
CmSecurePinDlgUpdate(HWND hWnd)2321 void CmSecurePinDlgUpdate(HWND hWnd)
2322 {
2323 	char *tmp1, *tmp2, *tmp3;
2324 	bool ok = true;
2325 	// Validate arguments
2326 	if (hWnd == NULL)
2327 	{
2328 		return;
2329 	}
2330 
2331 	tmp1 = GetTextA(hWnd, E_PIN1);
2332 	tmp2 = GetTextA(hWnd, E_PIN2);
2333 	tmp3 = GetTextA(hWnd, E_PIN3);
2334 	if (IsEmptyStr(tmp1))
2335 	{
2336 		ok = false;
2337 	}
2338 	if (IsEmptyStr(tmp2))
2339 	{
2340 		ok = false;
2341 	}
2342 	if (IsEmptyStr(tmp3))
2343 	{
2344 		ok = false;
2345 	}
2346 	if (StrCmp(tmp2, tmp3) != 0)
2347 	{
2348 		ok = false;
2349 	}
2350 	Free(tmp1);
2351 	Free(tmp2);
2352 	Free(tmp3);
2353 	SetEnable(hWnd, IDOK, ok);
2354 }
2355 
2356 // PIN code changing dialog
CmSecurePinDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2357 UINT CmSecurePinDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2358 {
2359 	UINT id = (UINT)param;
2360 	char *src, *dst;
2361 	SECURE *s;
2362 	// Validate arguments
2363 	if (hWnd == NULL)
2364 	{
2365 		return 0;
2366 	}
2367 
2368 	switch (msg)
2369 	{
2370 	case WM_INITDIALOG:
2371 		CmSecurePinDlgUpdate(hWnd);
2372 		break;
2373 
2374 	case WM_COMMAND:
2375 		switch (LOWORD(wParam))
2376 		{
2377 		case E_PIN1:
2378 		case E_PIN2:
2379 		case E_PIN3:
2380 			CmSecurePinDlgUpdate(hWnd);
2381 			break;
2382 		}
2383 
2384 		switch (wParam)
2385 		{
2386 		case IDOK:
2387 			src = GetTextA(hWnd, E_PIN1);
2388 			dst = GetTextA(hWnd, E_PIN3);
2389 
2390 			Disable(hWnd, IDOK);
2391 			Disable(hWnd, IDCANCEL);
2392 
2393 			s = OpenSec(id);
2394 			if (s == NULL)
2395 			{
2396 				if (GetSecureDevice(id) != NULL)
2397 				{
2398 					MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
2399 						GetSecureDevice(id)->DeviceName);
2400 				}
2401 				else
2402 				{
2403 					MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
2404 						"Unknown");
2405 				}
2406 			}
2407 			else
2408 			{
2409 				if (OpenSecSession(s, 0) == false)
2410 				{
2411 					if (GetSecureDevice(id) != NULL)
2412 					{
2413 						MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
2414 							GetSecureDevice(id)->DeviceName);
2415 					}
2416 					else
2417 					{
2418 						MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_DEVICE_OPEN_ERR"),
2419 							"Unknown");
2420 					}
2421 				}
2422 				else
2423 				{
2424 					if (LoginSec(s, src) == false)
2425 					{
2426 						MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_CURRENT_BAD"));
2427 						FocusEx(hWnd, E_PIN1);
2428 					}
2429 					else
2430 					{
2431 						if (ChangePin(s, src, dst) == false)
2432 						{
2433 							MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_PIN_CHANGE_FAILED"));
2434 							FocusEx(hWnd, E_PIN1);
2435 						}
2436 						else
2437 						{
2438 							// Clear the cache for PIN code
2439 							cached_pin_code_expires = 0;
2440 							cached_pin_code[0] = 0;
2441 							MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_PIN_OK"));
2442 							EndDialog(hWnd, true);
2443 						}
2444 
2445 						LogoutSec(s);
2446 					}
2447 
2448 					CloseSecSession(s);
2449 				}
2450 				CloseSec(s);
2451 			}
2452 
2453 			Enable(hWnd, IDOK);
2454 			Enable(hWnd, IDCANCEL);
2455 
2456 			Free(src);
2457 			Free(dst);
2458 			break;
2459 
2460 		case IDCANCEL:
2461 			Close(hWnd);
2462 			break;
2463 		}
2464 		break;
2465 
2466 	case WM_CLOSE:
2467 		EndDialog(hWnd, false);
2468 		break;
2469 	}
2470 
2471 	return 0;
2472 }
2473 
2474 // Change the PIN code
CmSecurePin(HWND hWnd,UINT id)2475 void CmSecurePin(HWND hWnd, UINT id)
2476 {
2477 	// Validate arguments
2478 	if (hWnd == NULL || id == 0 || CheckSecureDeviceId(id) == false)
2479 	{
2480 		return;
2481 	}
2482 
2483 	Dialog(hWnd, D_CM_SECURE_PIN, CmSecurePinDlg, (void *)id);
2484 }
2485 
2486 // Object type selection dialog
CmSecureTypeDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2487 UINT CmSecureTypeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2488 {
2489 	UINT type;
2490 	// Validate arguments
2491 	if (hWnd == NULL)
2492 	{
2493 		return 0;
2494 	}
2495 
2496 	switch (msg)
2497 	{
2498 	case WM_INITDIALOG:
2499 		type = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DefaultImportType");
2500 		Check(hWnd, R_DATA, type == SEC_DATA);
2501 		Check(hWnd, R_CERT, type == SEC_X);
2502 		Check(hWnd, R_KEY, type == SEC_K);
2503 		goto UPDATE_CONTROL;
2504 
2505 	case WM_COMMAND:
2506 		switch (wParam)
2507 		{
2508 		case IDOK:
2509 			type = SEC_DATA;
2510 			if (IsChecked(hWnd, R_CERT))
2511 			{
2512 				type = SEC_X;
2513 			}
2514 			else if (IsChecked(hWnd, R_KEY))
2515 			{
2516 				type = SEC_K;
2517 			}
2518 
2519 			MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "DefaultImportType", type);
2520 
2521 			EndDialog(hWnd, type);
2522 			break;
2523 
2524 		case IDCANCEL:
2525 			Close(hWnd);
2526 			break;
2527 		case R_CERT:
2528 		case R_KEY:
2529 		case R_DATA:
2530 UPDATE_CONTROL:
2531 			SetEnable(hWnd, IDOK, IsChecked(hWnd, R_CERT) ||
2532 				IsChecked(hWnd, R_KEY) ||
2533 				IsChecked(hWnd, R_DATA));
2534 			break;
2535 		}
2536 		break;
2537 
2538 	case WM_CLOSE:
2539 		EndDialog(hWnd, INFINITE);
2540 		break;
2541 	}
2542 
2543 	return 0;
2544 }
2545 
2546 // Object type selection
CmSecureType(HWND hWnd)2547 UINT CmSecureType(HWND hWnd)
2548 {
2549 	return Dialog(hWnd, D_CM_SECURE_TYPE, CmSecureTypeDlg, NULL);
2550 }
2551 
2552 // Initialize the dialog
CmSecureManagerDlgInit(HWND hWnd,UINT id)2553 void CmSecureManagerDlgInit(HWND hWnd, UINT id)
2554 {
2555 	SECURE_DEVICE *dev;
2556 	// Validate arguments
2557 	if (hWnd == NULL || id == 0)
2558 	{
2559 		return;
2560 	}
2561 
2562 	SetIcon(hWnd, 0, ICO_SECURE);
2563 
2564 	dev = GetSecureDevice(id);
2565 	if (dev != NULL)
2566 	{
2567 		FormatText(hWnd, S_INFO, dev->DeviceName);
2568 	}
2569 
2570 	SetFont(hWnd, B_BOLD, Font(0, true));
2571 
2572 	LvInit(hWnd, L_LIST);
2573 	LvInsertColumn(hWnd, L_LIST, 0, _UU("SEC_MGR_COLUMN1"), 200);
2574 	LvInsertColumn(hWnd, L_LIST, 1, _UU("SEC_MGR_COLUMN2"), 110);
2575 
2576 	CmSecureManagerDlgUpdate(hWnd, id);
2577 }
2578 
2579 // Update controls
CmSecureManagerDlgUpdate(HWND hWnd,UINT id)2580 void CmSecureManagerDlgUpdate(HWND hWnd, UINT id)
2581 {
2582 	bool b = true;
2583 	bool read_only = IsJPKI(id);
2584 	// Validate arguments
2585 	if (hWnd == NULL)
2586 	{
2587 		return;
2588 	}
2589 
2590 	if (LvIsSingleSelected(hWnd, L_LIST) == false)
2591 	{
2592 		b = false;
2593 	}
2594 
2595 	SetEnable(hWnd, B_EXPORT, b && ((UINT)LvGetParam(hWnd, L_LIST, LvGetSelected(hWnd, L_LIST)) != SEC_K));
2596 	SetEnable(hWnd, B_DELETE, b && (read_only == false));
2597 	SetEnable(hWnd, B_PIN, (read_only == false));
2598 	SetEnable(hWnd, B_IMPORT, (read_only == false));
2599 	SetEnable(hWnd, B_NEW_CERT, (read_only == false));
2600 }
2601 
2602 // Content update
CmSecureManagerDlgRefresh(HWND hWnd,UINT id)2603 void CmSecureManagerDlgRefresh(HWND hWnd, UINT id)
2604 {
2605 	bool ret;
2606 	LIST *o;
2607 	WINUI_SECURE_BATCH batch[] =
2608 	{
2609 		{WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
2610 	};
2611 	// Validate arguments
2612 	if (hWnd == NULL || id == 0)
2613 	{
2614 		return;
2615 	}
2616 
2617 	ret = SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0);
2618 
2619 	if (ret == false)
2620 	{
2621 		return;
2622 	}
2623 
2624 	o = batch[0].EnumList;
2625 	if (o != NULL)
2626 	{
2627 		CmSecureManagerDlgPrintList(hWnd, o);
2628 
2629 		FreeEnumSecObject(o);
2630 	}
2631 
2632 	// update controls
2633 	CmSecureManagerDlgUpdate(hWnd, id);
2634 }
2635 
2636 // Show the list of secure objects
CmSecureManagerDlgPrintList(HWND hWnd,LIST * o)2637 void CmSecureManagerDlgPrintList(HWND hWnd, LIST *o)
2638 {
2639 	CmSecureManagerDlgPrintListEx(hWnd, L_LIST, o, INFINITE);
2640 }
CmSecureManagerDlgPrintListEx(HWND hWnd,UINT id,LIST * o,UINT type)2641 void CmSecureManagerDlgPrintListEx(HWND hWnd, UINT id, LIST *o, UINT type)
2642 {
2643 	UINT i;
2644 	LVB *v;
2645 	// Validate arguments
2646 	if (hWnd == NULL || o == NULL)
2647 	{
2648 		return;
2649 	}
2650 
2651 	LvReset(hWnd, id);
2652 
2653 	v = LvInsertStart();
2654 
2655 	for (i = 0;i < LIST_NUM(o);i++)
2656 	{
2657 		UINT icon = ICO_LOG2;
2658 		wchar_t tmp1[MAX_SIZE], *tmp2, *tmp3;
2659 		SEC_OBJ *obj = LIST_DATA(o, i);
2660 
2661 		if (type == INFINITE || obj->Type == type)
2662 		{
2663 			StrToUni(tmp1, sizeof(tmp1), obj->Name);
2664 			tmp2 = CmSecureObjTypeToStr(obj->Type);
2665 			tmp3 = obj->Private ? _UU("SEC_YES") : _UU("SEC_NO");
2666 
2667 			if (obj->Type == SEC_X)
2668 			{
2669 				icon = ICO_CERT;
2670 			}
2671 			else if (obj->Type == SEC_K || obj->Type == SEC_P)
2672 			{
2673 				icon = ICO_KEY;
2674 			}
2675 
2676 			LvInsertAdd(v, icon, (void *)obj->Type, 2, tmp1, tmp2);
2677 		}
2678 	}
2679 
2680 	LvInsertEnd(v, hWnd, id);
2681 }
2682 
2683 // Convert the type of secure object to a string
CmSecureObjTypeToStr(UINT type)2684 wchar_t *CmSecureObjTypeToStr(UINT type)
2685 {
2686 	wchar_t *ret = _UU("SEC_TYPE_DATA");
2687 
2688 	if (type == SEC_X)
2689 	{
2690 		ret = _UU("SEC_TYPE_CERT");
2691 	}
2692 	else if (type == SEC_K)
2693 	{
2694 		ret = _UU("SEC_TYPE_KEY");
2695 	}
2696 	else if (type == SEC_P)
2697 	{
2698 		ret = _UU("SEC_TYPE_PUB");
2699 	}
2700 
2701 	return ret;
2702 }
2703 
2704 // Write by creating a new certificate
CmSecureManagerDlgNewCert(HWND hWnd,UINT id)2705 void CmSecureManagerDlgNewCert(HWND hWnd, UINT id)
2706 {
2707 	X *x;
2708 	K *k;
2709 	char default_name[MAX_SIZE];
2710 	char *object_name;
2711 	bool ok = false;
2712 	WINUI_SECURE_BATCH batch[] =
2713 	{
2714 		{WINUI_SECURE_WRITE_CERT, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},
2715 		{WINUI_SECURE_WRITE_KEY, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL},
2716 		{WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
2717 	};
2718 	// Validate arguments
2719 	if (hWnd == NULL || id == 0)
2720 	{
2721 		return;
2722 	}
2723 
2724 	// Dialog for creating certificate
2725 	if (SmCreateCert(hWnd, &x, &k, true, NULL, false) == false)
2726 	{
2727 		return;
2728 	}
2729 	// Generate the default name
2730 	GetPrintNameFromXA(default_name, sizeof(default_name), x);
2731 	ConvertSafeFileName(default_name, sizeof(default_name), default_name);
2732 
2733 	object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
2734 		_UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_CERT, false, false);
2735 
2736 	if (object_name != NULL)
2737 	{
2738 		// Enumerate and write
2739 		batch[0].InputX = x;
2740 		batch[0].Name = object_name;
2741 		batch[1].InputK = k;
2742 		batch[1].Name = object_name;
2743 
2744 		if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
2745 		{
2746 			// Failure
2747 		}
2748 		else
2749 		{
2750 			ok = true;
2751 		}
2752 
2753 		Free(object_name);
2754 	}
2755 
2756 	if (ok)
2757 	{
2758 		LIST *o = batch[2].EnumList;
2759 
2760 		CmSecureManagerDlgPrintList(hWnd, o);
2761 
2762 		FreeEnumSecObject(o);
2763 
2764 		MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NEW_CERT_IMPORT_OK"));
2765 	}
2766 
2767 	FreeX(x);
2768 	FreeK(k);
2769 }
2770 
2771 // Import
CmSecureManagerDlgImport(HWND hWnd,UINT id)2772 void CmSecureManagerDlgImport(HWND hWnd, UINT id)
2773 {
2774 	UINT type;
2775 	char name[MAX_SIZE];
2776 	wchar_t tmp2[MAX_SIZE];
2777 	wchar_t *tmp;
2778 	wchar_t *filename;
2779 	BUF *b;
2780 	K *k;
2781 	bool ok = false;
2782 	X *x;
2783 	WINUI_SECURE_BATCH batch[] =
2784 	{
2785 		{WINUI_SECURE_WRITE_DATA, name, true, NULL, NULL, NULL, NULL, NULL, NULL},
2786 		{WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
2787 	};
2788 	// Validate arguments
2789 	if (hWnd == NULL || id == 0)
2790 	{
2791 		return;
2792 	}
2793 
2794 	// Select the type of secure object
2795 	type = CmSecureType(hWnd);
2796 
2797 	switch (type)
2798 	{
2799 	case SEC_DATA:
2800 		// Data
2801 		tmp = OpenDlg(hWnd, _UU("DLG_ALL_FILES"), _UU("SEC_IMPORT_DATA"));
2802 		if (tmp == NULL)
2803 		{
2804 			return;
2805 		}
2806 
2807 		filename = CopyUniStr(tmp);
2808 		Free(tmp);
2809 
2810 		// Read the file
2811 		b = ReadDumpW(filename);
2812 		if (b == NULL)
2813 		{
2814 			// Read failure
2815 			MsgBox(hWnd, MB_ICONSTOP, _UU("SEC_READ_FAILED"));
2816 		}
2817 		else
2818 		{
2819 			if (b->Size > MAX_SEC_DATA_SIZE)
2820 			{
2821 				// File size is too large
2822 				MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_DATA_TOO_BIG"), MAX_SEC_DATA_SIZE);
2823 			}
2824 			else
2825 			{
2826 				// Generate the default name
2827 				char default_name[MAX_SIZE];
2828 				wchar_t default_name_w[MAX_SIZE];
2829 				char *object_name;
2830 				GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), filename);
2831 				UniToStr(default_name, sizeof(default_name), default_name_w);
2832 				ConvertSafeFileName(default_name, sizeof(default_name), default_name);
2833 
2834 				object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
2835 					_UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_LOG2, false, false);
2836 
2837 				if (object_name != NULL)
2838 				{
2839 					// Enumerate and write
2840 					batch[0].InputData = b;
2841 					batch[0].Name = object_name;
2842 
2843 					if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
2844 					{
2845 						// Failure
2846 					}
2847 					else
2848 					{
2849 						ok = true;
2850 					}
2851 
2852 					Free(object_name);
2853 				}
2854 			}
2855 
2856 			FreeBuf(b);
2857 		}
2858 
2859 		Free(filename);
2860 		break;
2861 
2862 	case SEC_X:
2863 		// Read a certificate
2864 		if (CmLoadXExW(hWnd, &x, tmp2, sizeof(tmp2)))
2865 		{
2866 			// Generate the default name
2867 			char default_name[MAX_SIZE];
2868 			wchar_t default_name_w[MAX_PATH];
2869 			char *object_name;
2870 			GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), tmp2);
2871 			UniToStr(default_name, sizeof(default_name), default_name_w);
2872 			ConvertSafeFileName(default_name, sizeof(default_name), default_name);
2873 
2874 			object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
2875 				_UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_CERT, false, false);
2876 
2877 			if (object_name != NULL)
2878 			{
2879 				// Enumerate and write
2880 				batch[0].Type = WINUI_SECURE_WRITE_CERT;
2881 				batch[0].InputX = x;
2882 				batch[0].Name = object_name;
2883 
2884 				if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
2885 				{
2886 					// Failure
2887 				}
2888 				else
2889 				{
2890 					ok = true;
2891 				}
2892 
2893 				Free(object_name);
2894 			}
2895 
2896 			FreeX(x);
2897 		}
2898 
2899 		break;
2900 
2901 	case SEC_K:
2902 		// Secret key
2903 		if (CmLoadKExW(hWnd, &k, tmp2, sizeof(tmp2)))
2904 		{
2905 			// Generate the default name
2906 			char default_name[MAX_SIZE];
2907 			wchar_t default_name_w[MAX_PATH];
2908 			char *object_name;
2909 			GetFileNameFromFilePathW(default_name_w, sizeof(default_name_w), tmp2);
2910 			UniToStr(default_name, sizeof(default_name), default_name_w);
2911 			ConvertSafeFileName(default_name, sizeof(default_name), default_name);
2912 
2913 			object_name = StringDlgA(hWnd, _UU("SEC_OBJECT_NAME_TITLE"),
2914 				_UU("SEC_OBJECT_NAME_INFO"), default_name, ICO_KEY, false, false);
2915 
2916 			if (object_name != NULL)
2917 			{
2918 				// Enumerate and write
2919 				batch[0].Type = WINUI_SECURE_WRITE_KEY;
2920 				batch[0].InputK = k;
2921 				batch[0].Name = object_name;
2922 
2923 				if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
2924 				{
2925 					// Failure
2926 				}
2927 				else
2928 				{
2929 					ok = true;
2930 				}
2931 
2932 				Free(object_name);
2933 			}
2934 
2935 			FreeK(k);
2936 		}
2937 		break;
2938 
2939 	default:
2940 		// Invalid
2941 		return;
2942 	}
2943 
2944 	if (ok)
2945 	{
2946 		LIST *o = batch[1].EnumList;
2947 
2948 		CmSecureManagerDlgPrintList(hWnd, o);
2949 
2950 		FreeEnumSecObject(o);
2951 
2952 		MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_OBJECT_IMPORT_OK"));
2953 	}
2954 }
2955 
2956 // Export the object
CmSecureManagerDlgExport(HWND hWnd,UINT id)2957 void CmSecureManagerDlgExport(HWND hWnd, UINT id)
2958 {
2959 	char name[MAX_SIZE];
2960 	UINT method = WINUI_SECURE_READ_DATA;
2961 	char *tmp;
2962 	UINT type;
2963 	wchar_t filename[MAX_PATH];
2964 	wchar_t *uni_tmp;
2965 	X *x;
2966 	BUF *b;
2967 	wchar_t default_name[128];
2968 	WINUI_SECURE_BATCH batch[] =
2969 	{
2970 		{WINUI_SECURE_READ_DATA, name, true, NULL, NULL, NULL, NULL, NULL, NULL},
2971 	};
2972 	UINT i;
2973 	// Validate arguments
2974 	if (hWnd == NULL || id == 0)
2975 	{
2976 		return;
2977 	}
2978 
2979 	i = LvGetSelected(hWnd, L_LIST);
2980 	if (i == INFINITE)
2981 	{
2982 		return;
2983 	}
2984 
2985 	tmp = LvGetStrA(hWnd, L_LIST, i, 0);
2986 	StrCpy(name, sizeof(name), tmp);
2987 	Free(tmp);
2988 
2989 	type = (UINT)LvGetParam(hWnd, L_LIST, i);
2990 
2991 	switch (type)
2992 	{
2993 	case SEC_X:
2994 		method = WINUI_SECURE_READ_CERT;
2995 		break;
2996 
2997 	default:
2998 		method = WINUI_SECURE_READ_DATA;
2999 		break;
3000 	}
3001 
3002 	batch[0].Type = method;
3003 
3004 	// Operate the smart card
3005 	if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
3006 	{
3007 		return;
3008 	}
3009 
3010 	switch (type)
3011 	{
3012 	case SEC_X:
3013 		// Certificate
3014 		x = batch[0].OutputX;
3015 
3016 		CertDlg(hWnd, x, NULL, true);
3017 
3018 		FreeX(x);
3019 		break;
3020 
3021 	default:
3022 		// File
3023 		b = batch[0].OutputData;
3024 		StrToUni(default_name, sizeof(default_name), name);
3025 		uni_tmp = SaveDlg(hWnd, _UU("DLG_ALL_FILES"), _UU("DLG_SAVE_FILE"), default_name, NULL);
3026 
3027 		if (uni_tmp != NULL)
3028 		{
3029 			UniStrCpy(filename, sizeof(filename), uni_tmp);
3030 
3031 			DumpBufW(b, filename);
3032 
3033 			Free(uni_tmp);
3034 
3035 			MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_OBJECT_EXPORT_OK"));
3036 		}
3037 
3038 
3039 		FreeBuf(b);
3040 		break;
3041 	}
3042 }
3043 
3044 // Delete the object
CmSecureManagerDlgDelete(HWND hWnd,UINT id)3045 void CmSecureManagerDlgDelete(HWND hWnd, UINT id)
3046 {
3047 	char name[MAX_SIZE];
3048 	UINT method = WINUI_SECURE_DELETE_DATA;
3049 	char *tmp;
3050 	UINT type;
3051 	LIST *o;
3052 	WINUI_SECURE_BATCH batch[] =
3053 	{
3054 		{WINUI_SECURE_DELETE_OBJECT, name, false, NULL, NULL, NULL, NULL, NULL, NULL},
3055 		{WINUI_SECURE_ENUM_OBJECTS, NULL, false, NULL, NULL, NULL, NULL, NULL, NULL},
3056 	};
3057 	UINT i;
3058 	// Validate arguments
3059 	if (hWnd == NULL || id == 0)
3060 	{
3061 		return;
3062 	}
3063 
3064 	i = LvGetSelected(hWnd, L_LIST);
3065 	if (i == INFINITE)
3066 	{
3067 		return;
3068 	}
3069 
3070 	tmp = LvGetStrA(hWnd, L_LIST, i, 0);
3071 	StrCpy(name, sizeof(name), tmp);
3072 	Free(tmp);
3073 
3074 	type = (UINT)LvGetParam(hWnd, L_LIST, i);
3075 
3076 	switch (type)
3077 	{
3078 	case SEC_X:
3079 		method = WINUI_SECURE_DELETE_CERT;
3080 		break;
3081 
3082 	case SEC_K:
3083 		method = WINUI_SECURE_DELETE_KEY;
3084 		break;
3085 
3086 	default:
3087 		method = WINUI_SECURE_DELETE_DATA;
3088 		break;
3089 	}
3090 
3091 	batch[0].Type = method;
3092 
3093 	if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), id, 0) == false)
3094 	{
3095 		return;
3096 	}
3097 
3098 	o = batch[1].EnumList;
3099 
3100 	CmSecureManagerDlgPrintList(hWnd, o);
3101 
3102 	FreeEnumSecObject(o);
3103 }
3104 
3105 static bool cm_secure_manager_no_new_cert = false;
3106 
3107 // Smart Card Manager dialog
CmSecureManagerDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3108 UINT CmSecureManagerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3109 {
3110 	NMHDR *n;
3111 	UINT id = (UINT)param;
3112 	// Validate arguments
3113 	if (hWnd == NULL)
3114 	{
3115 		return 0;
3116 	}
3117 
3118 	switch (msg)
3119 	{
3120 	case WM_INITDIALOG:
3121 		CmSecureManagerDlgInit(hWnd, id);
3122 
3123 		if (cm_secure_manager_no_new_cert)
3124 		{
3125 			Hide(hWnd, B_NEW_CERT);
3126 		}
3127 
3128 		SetTimer(hWnd, 1, 1, NULL);
3129 		break;
3130 
3131 	case WM_COMMAND:
3132 		switch (wParam)
3133 		{
3134 		case B_REFRESH:
3135 			CmSecureManagerDlgRefresh(hWnd, id);
3136 			break;
3137 
3138 		case B_IMPORT:
3139 			CmSecureManagerDlgImport(hWnd, id);
3140 			break;
3141 
3142 		case B_EXPORT:
3143 			CmSecureManagerDlgExport(hWnd, id);
3144 			break;
3145 
3146 		case B_DELETE:
3147 			if (MsgBox(hWnd, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2,
3148 				_UU("SEC_DELETE_MSG")) == IDYES)
3149 			{
3150 				CmSecureManagerDlgDelete(hWnd, id);
3151 			}
3152 			break;
3153 
3154 		case B_NEW_CERT:
3155 			CmSecureManagerDlgNewCert(hWnd, id);
3156 			break;
3157 
3158 		case B_PIN:
3159 			CmSecurePin(hWnd, id);
3160 			break;
3161 
3162 		case IDCANCEL:
3163 			Close(hWnd);
3164 			break;
3165 		}
3166 		break;
3167 
3168 	case WM_TIMER:
3169 		switch (wParam)
3170 		{
3171 		case 1:
3172 			KillTimer(hWnd, 1);
3173 
3174 			CmSecureManagerDlgRefresh(hWnd, id);
3175 			break;
3176 		}
3177 		break;
3178 
3179 	case WM_CLOSE:
3180 		EndDialog(hWnd, 0);
3181 		break;
3182 
3183 	case WM_NOTIFY:
3184 		n = (NMHDR *)lParam;
3185 		switch (n->idFrom)
3186 		{
3187 		case L_LIST:
3188 			switch (n->code)
3189 			{
3190 			case LVN_ITEMCHANGED:
3191 				CmSecureManagerDlgUpdate(hWnd, id);
3192 				break;
3193 			}
3194 			break;
3195 		}
3196 		break;
3197 	}
3198 
3199 	return 0;
3200 }
3201 
3202 // Smart Card Manager
CmSecureManager(HWND hWnd,UINT id)3203 void CmSecureManager(HWND hWnd, UINT id)
3204 {
3205 	CmSecureManagerEx(hWnd, id, false);
3206 }
CmSecureManagerEx(HWND hWnd,UINT id,bool no_new_cert)3207 void CmSecureManagerEx(HWND hWnd, UINT id, bool no_new_cert)
3208 {
3209 	// Validate arguments
3210 	if (hWnd == NULL || id == 0)
3211 	{
3212 		return;
3213 	}
3214 
3215 	// ID check
3216 	if (CheckSecureDeviceId(id) == false)
3217 	{
3218 		MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SEC_INVALID_ID"));
3219 		return;
3220 	}
3221 
3222 	if (no_new_cert)
3223 	{
3224 		cm_secure_manager_no_new_cert = true;
3225 	}
3226 	else
3227 	{
3228 		cm_secure_manager_no_new_cert = false;
3229 	}
3230 
3231 	Dialog(hWnd, D_CM_SECURE_MANAGER, CmSecureManagerDlg, (void *)id);
3232 }
3233 
3234 // Smart Card Manager for Client
CmClientSecureManager(HWND hWnd)3235 void CmClientSecureManager(HWND hWnd)
3236 {
3237 	RPC_USE_SECURE t;
3238 	UINT id;
3239 
3240 	Zero(&t, sizeof(t));
3241 	CcGetUseSecure(cm->Client, &t);
3242 
3243 	id = t.DeviceId;
3244 
3245 	if (id == 0 || CheckSecureDeviceId(id) == false)
3246 	{
3247 		id = CmClientSelectSecure(hWnd);
3248 	}
3249 
3250 	if (id == 0)
3251 	{
3252 		return;
3253 	}
3254 
3255 	CmSecureManager(hWnd, id);
3256 }
3257 
3258 // Initialize the dialog
CmSelectSecureDlgInit(HWND hWnd,UINT default_id)3259 void CmSelectSecureDlgInit(HWND hWnd, UINT default_id)
3260 {
3261 	UINT i;
3262 	LIST *o;
3263 	LVB *v;
3264 
3265 	SetIcon(hWnd, 0, ICO_SECURE);
3266 
3267 	o = GetSecureDeviceList();
3268 
3269 	LvInit(hWnd, L_LIST);
3270 	LvInsertColumn(hWnd, L_LIST, 0, _UU("SEC_COLUMN1"), 150);
3271 	LvInsertColumn(hWnd, L_LIST, 1, _UU("SEC_COLUMN2"), 100);
3272 	LvInsertColumn(hWnd, L_LIST, 2, _UU("SEC_COLUMN3"), 130);
3273 	LvInsertColumn(hWnd, L_LIST, 3, _UU("SEC_COLUMN4"), 100);
3274 
3275 	v = LvInsertStart();
3276 
3277 	for (i = 0;i < LIST_NUM(o);i++)
3278 	{
3279 		wchar_t tmp1[MAX_SIZE];
3280 		wchar_t *tmp2;
3281 		wchar_t tmp3[MAX_SIZE];
3282 		wchar_t tmp4[MAX_SIZE];
3283 		SECURE_DEVICE *dev = LIST_DATA(o, i);
3284 
3285 		StrToUni(tmp1, sizeof(tmp1), dev->DeviceName);
3286 		tmp2 = (dev->Type == SECURE_IC_CARD) ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN");
3287 		StrToUni(tmp3, sizeof(tmp3), dev->Manufacturer);
3288 		StrToUni(tmp4, sizeof(tmp4), dev->ModuleName);
3289 
3290 		LvInsertAdd(v, ICO_SECURE, (void *)dev->Id, 4, tmp1, tmp2, tmp3, tmp4);
3291 	}
3292 
3293 	LvInsertEnd(v, hWnd, L_LIST);
3294 
3295 	if (default_id != 0)
3296 	{
3297 		LvSelect(hWnd, L_LIST, LvSearchParam(hWnd, L_LIST, (void *)default_id));
3298 	}
3299 
3300 	ReleaseList(o);
3301 
3302 	// Control update
3303 	CmSelectSecureDlgUpdate(hWnd);
3304 }
3305 
3306 // Update controls of the dialog
CmSelectSecureDlgUpdate(HWND hWnd)3307 void CmSelectSecureDlgUpdate(HWND hWnd)
3308 {
3309 	SetEnable(hWnd, IDOK, LvIsSingleSelected(hWnd, L_LIST));
3310 }
3311 
3312 // Smart card selection dialog
CmSelectSecureDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3313 UINT CmSelectSecureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3314 {
3315 	UINT default_id = (UINT)param;
3316 	NMHDR *n = NULL;
3317 	static UINT old_id;
3318 	// Validate arguments
3319 	if (hWnd == NULL)
3320 	{
3321 		return 0;
3322 	}
3323 
3324 	switch (msg)
3325 	{
3326 	case WM_INITDIALOG:
3327 		old_id = default_id;
3328 		CmSelectSecureDlgInit(hWnd, default_id);
3329 
3330 		if (LvNum(hWnd, L_LIST) == 0)
3331 		{
3332 			// There is no smart card
3333 			SetTimer(hWnd, 1, 100, NULL);
3334 		}
3335 		break;
3336 
3337 	case WM_TIMER:
3338 		switch (wParam)
3339 		{
3340 		case 1:
3341 			KillTimer(hWnd, 1);
3342 
3343 			Disable(hWnd, L_LIST);
3344 			MsgBox(hWnd, MB_ICONINFORMATION, _UU("SEC_NO_SECURE_DEVICE"));
3345 			break;
3346 		}
3347 		break;
3348 
3349 	case WM_COMMAND:
3350 		switch (wParam)
3351 		{
3352 		case IDOK:
3353 			if (IsEnable(hWnd, IDOK))
3354 			{
3355 				UINT i = LvGetSelected(hWnd, L_LIST);
3356 				if (i != INFINITE)
3357 				{
3358 					UINT id = (UINT)LvGetParam(hWnd, L_LIST, i);
3359 
3360 					if (old_id != id)
3361 					{
3362 						if (CmCheckPkcsEula(hWnd, id) == false)
3363 						{
3364 							break;
3365 						}
3366 					}
3367 					EndDialog(hWnd, id);
3368 				}
3369 			}
3370 			break;
3371 
3372 		case IDCANCEL:
3373 			Close(hWnd);
3374 			break;
3375 		}
3376 		break;
3377 
3378 	case WM_CLOSE:
3379 		EndDialog(hWnd, 0);
3380 		break;
3381 
3382 	case WM_NOTIFY:
3383 		n = (NMHDR *)lParam;
3384 		switch (n->idFrom)
3385 		{
3386 		case L_LIST:
3387 			switch (n->code)
3388 			{
3389 			case LVN_ITEMCHANGED:
3390 				CmSelectSecureDlgUpdate(hWnd);
3391 				break;
3392 			case NM_DBLCLK:
3393 				Command(hWnd, IDOK);
3394 				break;
3395 			}
3396 			break;
3397 		}
3398 		break;
3399 	}
3400 
3401 	return 0;
3402 }
3403 
3404 // Select the smart card device to be used
CmSelectSecure(HWND hWnd,UINT current_id)3405 UINT CmSelectSecure(HWND hWnd, UINT current_id)
3406 {
3407 	return Dialog(hWnd, D_CM_SELECT_SECURE, CmSelectSecureDlg, (void *)current_id);
3408 }
3409 
3410 // Select the smart card device to be used (client)
CmClientSelectSecure(HWND hWnd)3411 UINT CmClientSelectSecure(HWND hWnd)
3412 {
3413 	UINT id;
3414 	RPC_USE_SECURE t;
3415 
3416 	if (cm->server_name != NULL)
3417 	{
3418 		MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_SECURE_MUST_LOCAL"));
3419 		return 0;
3420 	}
3421 
3422 	Zero(&t, sizeof(t));
3423 	CcGetUseSecure(cm->Client, &t);
3424 
3425 	id = t.DeviceId;
3426 
3427 	id = CmSelectSecure(hWnd, id);
3428 	if (id != 0)
3429 	{
3430 		Zero(&t, sizeof(t));
3431 		t.DeviceId = id;
3432 
3433 		CALL(hWnd, CcUseSecure(cm->Client, &t));
3434 
3435 		SmWriteSelectSecureIdReg(id);
3436 	}
3437 
3438 	return id;
3439 }
3440 
3441 // Shortcut connection
CmConnectShortcut(UCHAR * key)3442 void CmConnectShortcut(UCHAR *key)
3443 {
3444 	UINT ret;
3445 	// Validate arguments
3446 	if (key == NULL)
3447 	{
3448 		return;
3449 	}
3450 
3451 	// Attempt to connect
3452 	ret = CcShortcut(key);
3453 
3454 	if (ret != ERR_NO_ERROR)
3455 	{
3456 		if (ret == ERR_ACCOUNT_ACTIVE)
3457 		{
3458 			// Because it is currently connected, to query whether or not to disconnect
3459 			if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_SHORTCUT_DISCONNECT")) == IDYES)
3460 			{
3461 				// Try to disconnect
3462 				ret = CcShortcutDisconnect(key);
3463 
3464 				if (ret != ERR_NO_ERROR)
3465 				{
3466 					// Error
3467 					MsgBox(NULL, MB_ICONEXCLAMATION, GetUniErrorStr(ret));
3468 				}
3469 			}
3470 		}
3471 		else
3472 		{
3473 			// Other errors
3474 			MsgBox(NULL, MB_ICONEXCLAMATION, GetUniErrorStr(ret));
3475 		}
3476 	}
3477 }
3478 
3479 // Play the audio guide
CmVoice(char * name)3480 void CmVoice(char *name)
3481 {
3482 	UINT i;
3483 	// Validate arguments
3484 	if (name == NULL)
3485 	{
3486 		return;
3487 	}
3488 
3489 	// Voice guidance features disappeared!!
3490 	return;
3491 
3492 	if (cm->DisableVoice)
3493 	{
3494 		return;
3495 	}
3496 
3497 	for (i = 0;i < sizeof(cm_voice) / sizeof(CM_VOICE);i++)
3498 	{
3499 		if (cm_voice[i].voice_id == cm->VoiceId)
3500 		{
3501 			char tmp[MAX_SIZE];
3502 			Format(tmp, sizeof(tmp), "%s_%s.wav", cm_voice[i].perfix, name);
3503 			MsPlaySound(tmp);
3504 			return;
3505 		}
3506 	}
3507 }
3508 
3509 // Update the password changing dialog
CmChangePasswordUpdate(HWND hWnd,CM_CHANGE_PASSWORD * p)3510 void CmChangePasswordUpdate(HWND hWnd, CM_CHANGE_PASSWORD *p)
3511 {
3512 	bool ok = true;
3513 	char *s1, *s2;
3514 	// Validate arguments
3515 	if (hWnd == NULL || p == NULL)
3516 	{
3517 		return;
3518 	}
3519 
3520 	if (IsEmpty(hWnd, E_USERNAME))
3521 	{
3522 		ok = false;
3523 	}
3524 
3525 	s1 = GetTextA(hWnd, E_NEW_PASSWORD1);
3526 	s2 = GetTextA(hWnd, E_NEW_PASSWORD2);
3527 
3528 	if (StrCmp(s1, s2) != 0)
3529 	{
3530 		ok = false;
3531 	}
3532 
3533 	Free(s1);
3534 	Free(s2);
3535 
3536 	SetEnable(hWnd, IDOK, ok);
3537 }
3538 
3539 // Password changing dialog procedure
CmChangePasswordProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3540 UINT CmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3541 {
3542 	CM_CHANGE_PASSWORD *p = (CM_CHANGE_PASSWORD *)param;
3543 	char username[MAX_USERNAME_LEN + 1];
3544 	char old_pass[MAX_PASSWORD_LEN + 1];
3545 	char new_pass[MAX_PASSWORD_LEN + 1];
3546 	UINT ret;
3547 	// Validate arguments
3548 	if (hWnd == NULL)
3549 	{
3550 		return 0;
3551 	}
3552 
3553 	switch (msg)
3554 	{
3555 	case WM_INITDIALOG:
3556 		SetTextA(hWnd, E_HUBNAME, p->HubName);
3557 		SetTextA(hWnd, E_USERNAME, p->Username);
3558 		FormatText(hWnd, S_TITLE, p->ClientOption->Hostname);
3559 
3560 		if (IsEmpty(hWnd, E_USERNAME))
3561 		{
3562 			FocusEx(hWnd, E_USERNAME);
3563 		}
3564 		else
3565 		{
3566 			FocusEx(hWnd, E_OLD_PASSWORD);
3567 		}
3568 
3569 		CmChangePasswordUpdate(hWnd, p);
3570 		break;
3571 
3572 	case WM_COMMAND:
3573 		switch (LOWORD(wParam))
3574 		{
3575 		case E_USERNAME:
3576 		case E_OLD_PASSWORD:
3577 		case E_NEW_PASSWORD1:
3578 		case E_NEW_PASSWORD2:
3579 			CmChangePasswordUpdate(hWnd, p);
3580 			break;
3581 		}
3582 
3583 		switch (wParam)
3584 		{
3585 		case IDOK:
3586 			GetTxtA(hWnd, E_USERNAME, username, sizeof(username));
3587 			GetTxtA(hWnd, E_OLD_PASSWORD, old_pass, sizeof(old_pass));
3588 			GetTxtA(hWnd, E_NEW_PASSWORD1, new_pass, sizeof(new_pass));
3589 
3590 			Disable(hWnd, E_USERNAME);
3591 			Disable(hWnd, E_OLD_PASSWORD);
3592 			Disable(hWnd, E_NEW_PASSWORD1);
3593 			Disable(hWnd, E_NEW_PASSWORD2);
3594 			Disable(hWnd, IDOK);
3595 			Disable(hWnd, IDCANCEL);
3596 
3597 			ret = ChangePassword(cm->Cedar, p->ClientOption, p->HubName, username, old_pass, new_pass);
3598 
3599 			if (ret == ERR_NO_ERROR)
3600 			{
3601 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_CHANGED"));
3602 				EndDialog(hWnd, true);
3603 			}
3604 			else
3605 			{
3606 				MsgBox(hWnd, MB_ICONSTOP, _E(ret));
3607 				Enable(hWnd, E_USERNAME);
3608 				Enable(hWnd, E_OLD_PASSWORD);
3609 				Enable(hWnd, E_NEW_PASSWORD1);
3610 				Enable(hWnd, E_NEW_PASSWORD2);
3611 				Enable(hWnd, IDOK);
3612 				Enable(hWnd, IDCANCEL);
3613 
3614 				SetTextA(hWnd, E_OLD_PASSWORD, "");
3615 				SetTextA(hWnd, E_NEW_PASSWORD1, "");
3616 				SetTextA(hWnd, E_NEW_PASSWORD2, "");
3617 
3618 				Focus(hWnd, E_OLD_PASSWORD);
3619 			}
3620 
3621 			break;
3622 
3623 		case IDCANCEL:
3624 			Close(hWnd);
3625 			break;
3626 
3627 		}
3628 
3629 		break;
3630 
3631 	case WM_CLOSE:
3632 		EndDialog(hWnd, false);
3633 		break;
3634 	}
3635 
3636 	return 0;
3637 }
3638 
3639 // Show the password changing dialog
CmChangePassword(HWND hWnd,CLIENT_OPTION * o,char * hubname,char * username)3640 void CmChangePassword(HWND hWnd, CLIENT_OPTION *o, char *hubname, char *username)
3641 {
3642 	CM_CHANGE_PASSWORD p;
3643 	// Validate arguments
3644 	if (hWnd == NULL || o == NULL || hubname == NULL || username == NULL)
3645 	{
3646 		return;
3647 	}
3648 
3649 	Zero(&p, sizeof(p));
3650 	StrCpy(p.Username, sizeof(p.Username), username);
3651 	StrCpy(p.HubName, sizeof(p.HubName), hubname);
3652 	p.ClientOption = o;
3653 
3654 	CmVoice("password");
3655 
3656 	Dialog(hWnd, D_CM_CHANGE_PASSWORD, CmChangePasswordProc, &p);
3657 }
3658 
3659 // Prohibit the installation of the virtual LAN card
CmStopInstallVLan(HWND hWnd)3660 bool CmStopInstallVLan(HWND hWnd)
3661 {
3662 	if (cm->Client->Unix)
3663 	{
3664 		// There is no need to be prohibited if the client is an UNIX
3665 		return true;
3666 	}
3667 	if (cm->Client->Win9x)
3668 	{
3669 		// There is no need to prohibit if the client is a Win9x
3670 		return true;
3671 	}
3672 
3673 	return true;
3674 
3675 	if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
3676 	{
3677 		if (MsGetCurrentTerminalSessionId() == 0)
3678 		{
3679 			// There is no need to prohibit
3680 			return true;
3681 		}
3682 		else
3683 		{
3684 			// Prohibit to install the device drivers since
3685 			// the user logged in other than the console session
3686 			wchar_t *user = MsGetSessionUserName(0);
3687 
3688 			if (user == NULL)
3689 			{
3690 				MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CM_STOP_INST_VLAN_2"),
3691 					MsIsTerminalServiceInstalled() ? _UU("CM_DESKTOP_MSG_LOCAL_TS") : _UU("CM_DESKTOP_MSG_LOCAL_SW"),
3692 					MsGetCurrentTerminalSessionId());
3693 			}
3694 			else
3695 			{
3696 				MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CM_STOP_INST_VLAN_1"),
3697 					MsIsTerminalServiceInstalled() ? _UU("CM_DESKTOP_MSG_LOCAL_TS") : _UU("CM_DESKTOP_MSG_LOCAL_SW"),
3698 					MsGetCurrentTerminalSessionId(), 0, user);
3699 			}
3700 
3701 			if (user != NULL)
3702 			{
3703 				Free(user);
3704 			}
3705 			return false;
3706 		}
3707 	}
3708 	else
3709 	{
3710 		// There is no need to prohibit
3711 		return true;
3712 	}
3713 }
3714 
3715 // Desktop difference warning message dialog initialization
CmDesktopDlgInit(HWND hWnd,wchar_t * account_name)3716 void CmDesktopDlgInit(HWND hWnd, wchar_t *account_name)
3717 {
3718 	wchar_t tmp[2048];
3719 	bool remote = false;
3720 	bool user_switching = false;
3721 	bool console_active = false;
3722 	wchar_t *console_user = NULL;
3723 	// Validate arguments
3724 	if (hWnd == NULL)
3725 	{
3726 		return;
3727 	}
3728 
3729 	FormatText(hWnd, 0, account_name);
3730 	FormatText(hWnd, S_TITLE, account_name);
3731 	DlgFont(hWnd, S_TITLE, 11, true);
3732 	DlgFont(hWnd, S_INFO, 11, true);
3733 	if (cm->server_name == NULL)
3734 	{
3735 		UniStrCpy(tmp, sizeof(tmp), _UU("CM_DESKTOP_LOCAL_PC"));
3736 	}
3737 	else
3738 	{
3739 		UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_REMOTE_PC"), cm->server_name);
3740 	}
3741 	FormatText(hWnd, S_WARNING, tmp);
3742 
3743 	if (cm->server_name != NULL)
3744 	{
3745 		remote = true;
3746 	}
3747 	else
3748 	{
3749 		if (MsIsTerminalServiceInstalled())
3750 		{
3751 			user_switching = false;
3752 		}
3753 		else
3754 		{
3755 			user_switching = true;
3756 		}
3757 
3758 		console_user = MsGetSessionUserName(0);
3759 
3760 		if (console_user == NULL)
3761 		{
3762 			console_active = false;
3763 		}
3764 		else
3765 		{
3766 			console_active = true;
3767 		}
3768 	}
3769 
3770 	// MSG1
3771 	if (remote == false)
3772 	{
3773 		UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_1"),
3774 			user_switching ? _UU("CM_DESKTOP_MSG_LOCAL_SW") : _UU("CM_DESKTOP_MSG_LOCAL_TS"));
3775 	}
3776 	else
3777 	{
3778 		UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_1"),
3779 			cm->server_name);
3780 	}
3781 	SetText(hWnd, S_MSG_1, tmp);
3782 
3783 	// MSG2
3784 	if (remote == false)
3785 	{
3786 		if (console_active)
3787 		{
3788 			UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_21"),
3789 				console_user, MsGetCurrentTerminalSessionId());
3790 		}
3791 		else
3792 		{
3793 			UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_22"),
3794 				MsGetCurrentTerminalSessionId());
3795 		}
3796 	}
3797 	else
3798 	{
3799 		UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_2"), cm->server_name);
3800 	}
3801 	SetText(hWnd, S_MSG_2, tmp);
3802 
3803 	// MSG3
3804 	if (remote == false)
3805 	{
3806 		if (console_active)
3807 		{
3808 			UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_31"),
3809 				console_user, account_name);
3810 		}
3811 		else
3812 		{
3813 			UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_LOCAL_32"),
3814 				account_name);
3815 		}
3816 	}
3817 	else
3818 	{
3819 		UniFormat(tmp, sizeof(tmp), _UU("CM_DESKTOP_MSG_REMOTE_3"), cm->server_name,
3820 			account_name);
3821 	}
3822 	SetText(hWnd, S_MSG_3, tmp);
3823 
3824 	if (console_user != NULL)
3825 	{
3826 		Free(console_user);
3827 	}
3828 }
3829 
3830 // Desktop difference warning message dialog
CmDesktopDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3831 UINT CmDesktopDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3832 {
3833 	wchar_t *account_name = (wchar_t *)param;
3834 	// Validate arguments
3835 	if (hWnd == NULL)
3836 	{
3837 		return 0;
3838 	}
3839 
3840 	switch (msg)
3841 	{
3842 	case WM_INITDIALOG:
3843 		CmDesktopDlgInit(hWnd, account_name);
3844 		break;
3845 	case WM_COMMAND:
3846 		switch (wParam)
3847 		{
3848 		case IDOK:
3849 			EndDialog(hWnd, true);
3850 			break;
3851 		case IDCANCEL:
3852 			Close(hWnd);
3853 			break;
3854 		}
3855 		break;
3856 	case WM_CLOSE:
3857 		EndDialog(hWnd, false);
3858 		break;
3859 	}
3860 
3861 	return 0;
3862 }
3863 
3864 // Show a warning message that the desktop is different, if necessary
CmWarningDesktop(HWND hWnd,wchar_t * account_name)3865 bool CmWarningDesktop(HWND hWnd, wchar_t *account_name)
3866 {
3867 	// Validate arguments
3868 	if (hWnd == NULL || account_name == NULL)
3869 	{
3870 		return false;
3871 	}
3872 
3873 	if (cm->Client->Unix)
3874 	{
3875 		//There is no need for warning if the client is an UNIX
3876 		return true;
3877 	}
3878 
3879 	if (/*MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled() ||*/ (cm->server_name != NULL))
3880 	{
3881 		if (cm->server_name == NULL)
3882 		{
3883 			//if (MsGetCurrentTerminalSessionId() == 0)
3884 			{
3885 				// No need for warning
3886 				return true;
3887 			}
3888 		}
3889 		// There is a need for warning
3890 		return Dialog(hWnd, D_CM_DESKTOP, CmDesktopDlgProc, account_name);
3891 	}
3892 	else
3893 	{
3894 		// No need for warning
3895 		return true;
3896 	}
3897 }
3898 
3899 // Update the password setting dialog
CmPasswordRefresh(HWND hWnd)3900 void CmPasswordRefresh(HWND hWnd)
3901 {
3902 	bool ok = true;
3903 	// Validate arguments
3904 	if (hWnd == NULL)
3905 	{
3906 		return;
3907 	}
3908 
3909 	SetEnable(hWnd, E_PASSWORD, IsChecked(hWnd, R_USE_PASSWORD));
3910 	SetEnable(hWnd, E_PASSWORD2, IsChecked(hWnd, R_USE_PASSWORD));
3911 	SetEnable(hWnd, IDC_STATIC1, IsChecked(hWnd, R_USE_PASSWORD));
3912 	SetEnable(hWnd, IDC_STATIC2, IsChecked(hWnd, R_USE_PASSWORD));
3913 	SetEnable(hWnd, R_REMOTE_ONLY, IsChecked(hWnd, R_USE_PASSWORD));
3914 
3915 	if (IsChecked(hWnd, R_USE_PASSWORD))
3916 	{
3917 		char tmp1[MAX_SIZE];
3918 		char tmp2[MAX_SIZE];
3919 		if (IsEmpty(hWnd, E_PASSWORD))
3920 		{
3921 			ok = false;
3922 		}
3923 		GetTxtA(hWnd, E_PASSWORD, tmp1, sizeof(tmp1));
3924 		GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));
3925 		if (StrCmp(tmp1, tmp2) != 0)
3926 		{
3927 			ok = false;
3928 		}
3929 		if (StrCmp(tmp1, HIDDEN_PASSWORD) == 0)
3930 		{
3931 			ok = false;
3932 		}
3933 	}
3934 
3935 	SetEnable(hWnd, IDOK, ok);
3936 }
3937 
3938 // Password setting procedure
CmPasswordProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3939 UINT CmPasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3940 {
3941 	RPC_CLIENT_PASSWORD_SETTING c;
3942 	RPC_CLIENT_PASSWORD p;
3943 	char tmp[MAX_SIZE];
3944 	// Validate arguments
3945 	if (hWnd == NULL)
3946 	{
3947 		return 0;
3948 	}
3949 
3950 	switch (msg)
3951 	{
3952 	case WM_INITDIALOG:
3953 		// Get the password setting
3954 		if (CALL(hWnd, CcGetPasswordSetting(cm->Client, &c)))
3955 		{
3956 			Check(hWnd, R_USE_PASSWORD, c.IsPasswordPresented);
3957 			if (c.IsPasswordPresented)
3958 			{
3959 				SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);
3960 				SetTextA(hWnd, E_PASSWORD2, HIDDEN_PASSWORD);
3961 				FocusEx(hWnd, E_PASSWORD);
3962 				Check(hWnd, R_REMOTE_ONLY, c.PasswordRemoteOnly);
3963 			}
3964 			else
3965 			{
3966 				Focus(hWnd, R_USE_PASSWORD);
3967 			}
3968 		}
3969 		CmPasswordRefresh(hWnd);
3970 		break;
3971 	case WM_COMMAND:
3972 		switch (wParam)
3973 		{
3974 		case R_USE_PASSWORD:
3975 			if (IsChecked(hWnd, R_USE_PASSWORD))
3976 			{
3977 				FocusEx(hWnd, E_PASSWORD);
3978 			}
3979 			break;
3980 		case IDOK:
3981 			GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));
3982 			Zero(&p, sizeof(p));
3983 			if (IsChecked(hWnd, R_USE_PASSWORD))
3984 			{
3985 				StrCpy(p.Password, sizeof(p.Password), tmp);
3986 				p.PasswordRemoteOnly = IsChecked(hWnd, R_REMOTE_ONLY);
3987 			}
3988 
3989 			if (CALL(hWnd, CcSetPassword(cm->Client, &p)))
3990 			{
3991 				if (StrLen(p.Password) > 0)
3992 				{
3993 					MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_SET"));
3994 				}
3995 				else
3996 				{
3997 					MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PASSWORD_REMOVE"));
3998 				}
3999 				EndDialog(hWnd, true);
4000 			}
4001 			break;
4002 		case IDCANCEL:
4003 			Close(hWnd);
4004 			break;
4005 		}
4006 		switch (LOWORD(wParam))
4007 		{
4008 		case R_USE_PASSWORD:
4009 		case R_REMOTE_ONLY:
4010 		case E_PASSWORD:
4011 		case E_PASSWORD2:
4012 			CmPasswordRefresh(hWnd);
4013 			break;
4014 		}
4015 		switch (wParam)
4016 		{
4017 		case R_REMOTE_ONLY:
4018 		case R_USE_PASSWORD:
4019 			if (IsChecked(hWnd, R_USE_PASSWORD))
4020 			{
4021 				FocusEx(hWnd, E_PASSWORD);
4022 			}
4023 			break;
4024 		}
4025 		break;
4026 	case WM_CLOSE:
4027 		EndDialog(hWnd, false);
4028 		break;
4029 	}
4030 
4031 	return 0;
4032 }
4033 
4034 // Set the password
CmPassword(HWND hWnd)4035 void CmPassword(HWND hWnd)
4036 {
4037 	// Validate arguments
4038 	if (hWnd == NULL)
4039 	{
4040 		return;
4041 	}
4042 
4043 	Dialog(hWnd, D_CM_PASSWORD, CmPasswordProc, NULL);
4044 }
4045 
4046 // CA dialog update
CmTrustDlgUpdate(HWND hWnd)4047 void CmTrustDlgUpdate(HWND hWnd)
4048 {
4049 	// Validate arguments
4050 	if (hWnd == NULL)
4051 	{
4052 		return;
4053 	}
4054 
4055 	SetEnable(hWnd, B_EXPORT, LvIsSelected(hWnd, L_CERT));
4056 	SetEnable(hWnd, B_DELETE, LvIsSelected(hWnd, L_CERT) && cm->CmSetting.LockMode == false);
4057 	SetEnable(hWnd, IDOK, LvIsSelected(hWnd, L_CERT));
4058 	SetEnable(hWnd, B_IMPORT, cm->CmSetting.LockMode == false);
4059 }
4060 
4061 // Update the list of certificates
CmTrustDlgRefresh(HWND hWnd)4062 void CmTrustDlgRefresh(HWND hWnd)
4063 {
4064 	RPC_CLIENT_ENUM_CA c;
4065 	// Validate arguments
4066 	if (hWnd == NULL)
4067 	{
4068 		return;
4069 	}
4070 
4071 	if (CALL(hWnd, CcEnumCa(cm->Client, &c)))
4072 	{
4073 		UINT i;
4074 		LVB *b = LvInsertStart();
4075 		for (i = 0;i < c.NumItem;i++)
4076 		{
4077 			RPC_CLIENT_ENUM_CA_ITEM *cert = c.Items[i];
4078 			wchar_t tmp[MAX_SIZE];
4079 
4080 			GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(cert->Expires), NULL);
4081 			LvInsertAdd(b, ICO_CERT, (void *)cert->Key, 3,
4082 				cert->SubjectName, cert->IssuerName, tmp);
4083 		}
4084 		LvInsertEnd(b, hWnd, L_CERT);
4085 		CiFreeClientEnumCa(&c);
4086 	}
4087 
4088 	CmTrustDlgUpdate(hWnd);
4089 }
4090 
4091 // Import
CmTrustImport(HWND hWnd)4092 void CmTrustImport(HWND hWnd)
4093 {
4094 	X *x;
4095 	RPC_CERT c;
4096 	if (CmLoadXFromFileOrSecureCard(hWnd, &x) == false)
4097 	{
4098 		return;
4099 	}
4100 
4101 	Zero(&c, sizeof(c));
4102 	c.x = x;
4103 
4104 	CALL(hWnd, CcAddCa(cm->Client, &c));
4105 	CmVoice("new_cert");
4106 
4107 	FreeX(c.x);
4108 	CmTrustDlgRefresh(hWnd);
4109 }
4110 
4111 // Export
CmTrustExport(HWND hWnd)4112 void CmTrustExport(HWND hWnd)
4113 {
4114 	UINT key;
4115 	// Validate arguments
4116 	if (hWnd == NULL)
4117 	{
4118 		return;
4119 	}
4120 
4121 	key = (UINT)LvGetParam(hWnd, L_CERT, LvGetSelected(hWnd, L_CERT));
4122 	if (key != INFINITE)
4123 	{
4124 		RPC_GET_CA a;
4125 		Zero(&a, sizeof(a));
4126 		a.Key = key;
4127 
4128 		if (CALL(hWnd, CcGetCa(cm->Client, &a)))
4129 		{
4130 			wchar_t *name;
4131 			X *x = CloneX(a.x);
4132 			CiFreeGetCa(&a);
4133 
4134 			// Save
4135 			name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");
4136 			if (name != NULL)
4137 			{
4138 				wchar_t str[MAX_SIZE];
4139 				UniStrCpy(str, sizeof(str), name);
4140 				if (XToFileW(x, str, true))
4141 				{
4142 					MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));
4143 				}
4144 				else
4145 				{
4146 					MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
4147 				}
4148 				Free(name);
4149 			}
4150 			FreeX(x);
4151 		}
4152 	}
4153 }
4154 
4155 // Display
CmTrustView(HWND hWnd)4156 void CmTrustView(HWND hWnd)
4157 {
4158 	UINT key;
4159 	// Validate arguments
4160 	if (hWnd == NULL)
4161 	{
4162 		return;
4163 	}
4164 
4165 	key = (UINT)LvGetParam(hWnd, L_CERT, LvGetSelected(hWnd, L_CERT));
4166 	if (key != INFINITE)
4167 	{
4168 		RPC_GET_CA a;
4169 		Zero(&a, sizeof(a));
4170 		a.Key = key;
4171 
4172 		if (CALL(hWnd, CcGetCa(cm->Client, &a)))
4173 		{
4174 			X *x = CloneX(a.x);
4175 			X *x_issuer;
4176 			CiFreeGetCa(&a);
4177 
4178 			x_issuer = CmGetIssuer(x);
4179 			CertDlg(hWnd, x, x_issuer, true);
4180 			FreeX(x);
4181 			FreeX(x_issuer);
4182 		}
4183 	}
4184 }
4185 
4186 // CA dialog procedure
CmTrustDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)4187 UINT CmTrustDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
4188 {
4189 	NMHDR *n;
4190 	UINT index;
4191 	// Validate arguments
4192 	if (hWnd == NULL)
4193 	{
4194 		return 0;
4195 	}
4196 
4197 	switch (msg)
4198 	{
4199 	case WM_INITDIALOG:
4200 		LvInit(hWnd, L_CERT);
4201 		LvInsertColumn(hWnd, L_CERT, 0, _UU("CM_CERT_COLUMN_1"), 190);
4202 		LvInsertColumn(hWnd, L_CERT, 1, _UU("CM_CERT_COLUMN_2"), 190);
4203 		LvInsertColumn(hWnd, L_CERT, 2, _UU("CM_CERT_COLUMN_3"), 160);
4204 		CmTrustDlgRefresh(hWnd);
4205 		break;
4206 	case WM_COMMAND:
4207 		switch (wParam)
4208 		{
4209 		case B_IMPORT:
4210 			CmTrustImport(hWnd);
4211 			break;
4212 		case B_EXPORT:
4213 			CmTrustExport(hWnd);
4214 			break;
4215 		case B_DELETE:
4216 			index = LvGetSelected(hWnd, L_CERT);
4217 			if (index != INFINITE)
4218 			{
4219 				UINT key = (UINT)LvGetParam(hWnd, L_CERT, index);
4220 				if (key != INFINITE)
4221 				{
4222 					if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_CERT_DELETE_MSG")) == IDYES)
4223 					{
4224 						RPC_CLIENT_DELETE_CA c;
4225 						Zero(&c, sizeof(c));
4226 						c.Key = key;
4227 						if (CALL(hWnd, CcDeleteCa(cm->Client, &c)))
4228 						{
4229 							CmTrustDlgRefresh(hWnd);
4230 						}
4231 					}
4232 				}
4233 			}
4234 			break;
4235 		case IDOK:
4236 			if (IsEnable(hWnd, IDOK))
4237 			{
4238 				CmTrustView(hWnd);
4239 			}
4240 			break;
4241 		case IDCANCEL:
4242 			Close(hWnd);
4243 			break;
4244 		}
4245 		break;
4246 	case WM_CLOSE:
4247 		EndDialog(hWnd, 0);
4248 		break;
4249 	case WM_NOTIFY:
4250 		n = (NMHDR *)lParam;
4251 		switch (n->idFrom)
4252 		{
4253 		case L_CERT:
4254 			switch (n->code)
4255 			{
4256 			case LVN_ITEMCHANGED:
4257 				CmTrustDlgUpdate(hWnd);
4258 				break;
4259 			case NM_DBLCLK:
4260 				Command(hWnd, IDOK);
4261 				break;
4262 			}
4263 			break;
4264 		}
4265 		break;
4266 	}
4267 
4268 	LvSortHander(hWnd, msg, wParam, lParam, L_CERT);
4269 
4270 	return 0;
4271 }
4272 
4273 // Show the CA dialog
CmTrustDlg(HWND hWnd)4274 void CmTrustDlg(HWND hWnd)
4275 {
4276 	Dialog(hWnd, D_CM_TRUST, CmTrustDlgProc, NULL);
4277 }
4278 
4279 // Main window procedure
CmMainWindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)4280 UINT CmMainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
4281 {
4282 	NMHDR *n;
4283 	static UINT taskbar_msg = 0;
4284 	COPYDATASTRUCT *cpy;
4285 	// Validate arguments
4286 	if (hWnd == NULL)
4287 	{
4288 		return 0;
4289 	}
4290 
4291 	if (taskbar_msg != 0 && msg == taskbar_msg)
4292 	{
4293 		// The task-bar is regenerated
4294 		if (cm->TrayInited)
4295 		{
4296 			MsRestoreIconOnTray();
4297 		}
4298 	}
4299 
4300 	// CmSetForegroundProcessToCnService();
4301 
4302 	switch (msg)
4303 	{
4304 	case WM_CM_SETTING_CHANGED_MESSAGE:
4305 		// CM_SETTING has changed
4306 		CmApplyCmSetting();
4307 		break;
4308 	case WM_INITDIALOG:
4309 		CmMainWindowOnInit(hWnd);
4310 		taskbar_msg = RegisterWindowMessage("TaskbarCreated");
4311 		CmEndStartupMutex();
4312 		break;
4313 	case WM_CM_SHOW:
4314 		// Received a display request from another process
4315 		if (cm->CmSetting.EasyMode == false)
4316 		{
4317 			ShowWindow(hWnd, SW_SHOWNORMAL);
4318 		}
4319 		else
4320 		{
4321 			if (cm->hEasyWnd == NULL)
4322 			{
4323 				CmShowEasy();
4324 			}
4325 			else
4326 			{
4327 				SetForegroundWindow(cm->hEasyWnd);
4328 				SetActiveWindow(cm->hEasyWnd);
4329 			}
4330 		}
4331 		break;
4332 	case WM_COMMAND:
4333 		CmMainWindowOnCommand(hWnd, wParam, lParam);
4334 		break;
4335 	case WM_SIZE:
4336 		CmMainWindowOnSize(hWnd);
4337 		break;
4338 	case WM_CLOSE:
4339 		if (cm->CmSetting.EasyMode == false)
4340 		{
4341 			CmShowOrHideWindow(hWnd);
4342 		}
4343 		else
4344 		{
4345 			if (cm->hEasyWnd == NULL)
4346 			{
4347 				CmShowEasy();
4348 			}
4349 			else
4350 			{
4351 				SetForegroundWindow(cm->hEasyWnd);
4352 				SetActiveWindow(cm->hEasyWnd);
4353 			}
4354 		}
4355 		return 1;
4356 	case WM_INITMENUPOPUP:
4357 		if (HIWORD(lParam) == false)
4358 		{
4359 			CmMainWindowOnPopupMenu(hWnd, (HMENU)wParam, LOWORD(lParam));
4360 		}
4361 		break;
4362 	case WM_NOTIFY:
4363 		n = (NMHDR *)lParam;
4364 		if (n->idFrom == L_ACCOUNT && (n->code == LVN_BEGINLABELEDITW || n->code == LVN_BEGINLABELEDITA))
4365 		{
4366 			wchar_t *tmp = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
4367 			if (tmp != NULL)
4368 			{
4369 				if (UniStrCmpi(tmp, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(tmp, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(tmp, _UU("CM_VGC_LINK")) == 0
4370 					)
4371 				{
4372 					SendMsg(hWnd, L_ACCOUNT, LVM_CANCELEDITLABEL, 0, 0);
4373 					Free(tmp);
4374 					return true;
4375 				}
4376 				Free(tmp);
4377 			}
4378 		}
4379 		CmMainWindowOnNotify(hWnd, (NMHDR *)lParam);
4380 		break;
4381 	case WM_CM_NOTIFY:
4382 		CmRefreshVLanList(hWnd);
4383 		CmRefreshAccountList(hWnd);
4384 		CmRefreshStatusBar(hWnd);
4385 		break;
4386 	case WM_TIMER:
4387 		switch (wParam)
4388 		{
4389 		case 1:
4390 			CmSetForegroundProcessToCnService();
4391 			break;
4392 		case 2:
4393 			CmPollingTray(hWnd);
4394 			break;
4395 		case 3:
4396 			KillTimer(hWnd, 3);
4397 			Hide(hWnd, 0);
4398 			break;
4399 		case 4:
4400 			KillTimer(hWnd, 4);
4401 			CmMainWindowOnShowEasy(hWnd);
4402 			break;
4403 		case 6:
4404 			if (cm->Update == NULL)
4405 			{
4406 				if (cm->server_name == NULL)
4407 				{
4408 					if (CmGetNumConnected(hWnd) == 0)
4409 					{
4410 						cm->Update = InitUpdateUi(_UU("PRODUCT_NAME_VPN_CMGR"), NAME_OF_VPN_CLIENT_MANAGER, NULL,
4411 							GetCurrentBuildDate(), CEDAR_BUILD, CEDAR_VER, ((cm->Client == NULL) ? NULL : cm->Client->ClientId),
4412 							true);
4413 					}
4414 				}
4415 			}
4416 			break;
4417 		}
4418 		break;
4419 	case WM_CM_TRAY_MESSAGE:
4420 		// Message from the icon in the task tray
4421 		CmMainWindowOnTrayClicked(hWnd, wParam, lParam);
4422 		break;
4423 	case WM_COPYDATA:
4424 		cpy = (COPYDATASTRUCT *)lParam;
4425 		if (cpy != NULL)
4426 		{
4427 			if (cpy->dwData == CM_IMPORT_FILENAME_MSG || cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE)
4428 			{
4429 				char *filename = (char *)cpy->lpData;
4430 
4431 				if (cm->CmSetting.LockMode == false || cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE)
4432 				{
4433 					wchar_t fullpath[MAX_PATH];
4434 
4435 					if (StrLen(filename) >= 2 && IsFileExists(filename))
4436 					{
4437 						StrToUni(fullpath, sizeof(fullpath), filename);
4438 					}
4439 					else
4440 					{
4441 						UniStrCpy(fullpath, sizeof(fullpath), (wchar_t *)filename);
4442 					}
4443 
4444 					CmImportAccountMainEx(cm->hEasyWnd ? cm->hEasyWnd : hWnd, fullpath, cpy->dwData == CM_IMPORT_FILENAME_MSG_OVERWRITE);
4445 				}
4446 				else
4447 				{
4448 					MsgBox(cm->hEasyWnd ? cm->hEasyWnd : hWnd, MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_TOPMOST, _UU("CM_VPN_FILE_IMPORT_NG"));
4449 				}
4450 			}
4451 		}
4452 		break;
4453 	case WM_QUERYENDSESSION:
4454 		// Windows is about to terminate
4455 		cm->WindowsShutdowning = true;
4456 		CmSaveMainWindowPos(hWnd);
4457 		SleepThread(256);
4458 		break;
4459 	case WM_ENDSESSION:
4460 		// Windows has terminated
4461 		_exit(0);
4462 		break;
4463 	}
4464 
4465 	LvSortHander(hWnd, msg, wParam, lParam, L_ACCOUNT);
4466 	LvSortHander(hWnd, msg, wParam, lParam, L_VLAN);
4467 
4468 	return 0;
4469 }
4470 
4471 // Specify the notification service to the foreground process
CmSetForegroundProcessToCnService()4472 void CmSetForegroundProcessToCnService()
4473 {
4474 	if (cm->MenuPopuping)
4475 	{
4476 		return;
4477 	}
4478 	if (cm->server_name == NULL)
4479 	{
4480 		if (CnCheckAlreadyExists(false))
4481 		{
4482 			AllowFGWindow(MsRegReadInt(REG_CURRENT_USER,
4483 				CM_REG_KEY, "NotifyServerProcessId"));
4484 		}
4485 	}
4486 }
4487 
4488 // Show the [recent destination] sub-menu
CmCreateRecentSubMenu(HWND hWnd,UINT start_id)4489 HMENU CmCreateRecentSubMenu(HWND hWnd, UINT start_id)
4490 {
4491 	HMENU h = NULL;
4492 	UINT i;
4493 	RPC_CLIENT_ENUM_ACCOUNT a;
4494 	LIST *o;
4495 	bool easy;
4496 
4497 	easy = cm->CmSetting.EasyMode;
4498 
4499 	Zero(&a, sizeof(a));
4500 
4501 	if (CcEnumAccount(cm->Client, &a) == ERR_NO_ERROR)
4502 	{
4503 		o = NewListFast(CiCompareClientAccountEnumItemByLastConnectDateTime);
4504 
4505 		for (i = 0;i < a.NumItem;i++)
4506 		{
4507 			RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = a.Items[i];
4508 
4509 			item->tmp1 = i;
4510 
4511 			if (item->LastConnectDateTime != 0)
4512 			{
4513 				Add(o, item);
4514 			}
4515 		}
4516 
4517 		Sort(o);
4518 
4519 		for (i = 0;i < MIN(LIST_NUM(o), CM_NUM_RECENT);i++)
4520 		{
4521 			RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = (RPC_CLIENT_ENUM_ACCOUNT_ITEM *)LIST_DATA(o, i);
4522 			wchar_t tmp[MAX_PATH];
4523 			wchar_t *account_name;
4524 			char *server_name;
4525 			char *hub_name;
4526 			UINT pos;
4527 
4528 			if (h == NULL)
4529 			{
4530 				h = CreatePopupMenu();
4531 			}
4532 
4533 			account_name = item->AccountName;
4534 			server_name = item->ServerName;
4535 			hub_name = item->HubName;
4536 
4537 			UniStrCpy(tmp, sizeof(tmp), account_name);
4538 
4539 			pos = LvSearchStr(hWnd, L_ACCOUNT, 0, account_name);
4540 			if (pos != INFINITE)
4541 			{
4542 				MsAppendMenu(h, MF_STRING, start_id + pos, tmp);
4543 			}
4544 		}
4545 
4546 		ReleaseList(o);
4547 
4548 		CiFreeClientEnumAccount(&a);
4549 	}
4550 
4551 	return h;
4552 }
4553 
4554 // Show the sub-menu of the right-click menu in the task tray
CmCreateTraySubMenu(HWND hWnd,bool flag,UINT start_id)4555 HMENU CmCreateTraySubMenu(HWND hWnd, bool flag, UINT start_id)
4556 {
4557 	HMENU h = NULL;
4558 	UINT i, num;
4559 	bool easy;
4560 	// Validate arguments
4561 	if (hWnd == NULL)
4562 	{
4563 		return NULL;
4564 	}
4565 
4566 	easy = cm->CmSetting.EasyMode;
4567 
4568 	num = LvNum(hWnd, L_ACCOUNT);
4569 
4570 	for (i = 0;i < num;i++)
4571 	{
4572 		wchar_t *status_str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
4573 
4574 		if (status_str != NULL)
4575 		{
4576 			bool b = false;
4577 			bool is_account = false;
4578 
4579 			if (UniStrCmpi(status_str, _UU("CM_ACCOUNT_OFFLINE")) == 0)
4580 			{
4581 				if (flag == false)
4582 				{
4583 					b = true;
4584 				}
4585 
4586 				is_account = true;
4587 			}
4588 
4589 			if (UniStrCmpi(status_str, _UU("CM_ACCOUNT_ONLINE")) == 0 ||
4590 				UniStrCmpi(status_str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
4591 			{
4592 				if (flag == true)
4593 				{
4594 					b = true;
4595 				}
4596 
4597 				is_account = true;
4598 			}
4599 
4600 			if (b)
4601 			{
4602 				wchar_t tmp[MAX_PATH];
4603 				wchar_t *account_name, *server_name;
4604 				wchar_t *hub_name;
4605 				if (h == NULL)
4606 				{
4607 					h = CreatePopupMenu();
4608 				}
4609 
4610 				account_name = LvGetStr(hWnd, L_ACCOUNT, i, 0);
4611 				server_name = LvGetStr(hWnd, L_ACCOUNT, i, 2);
4612 				hub_name = LvGetStr(hWnd, L_ACCOUNT, i, 3);
4613 
4614 				if (easy == false)
4615 				{
4616 					UniFormat(tmp, sizeof(tmp), L"%s\t- %s [%s]", account_name, server_name, hub_name);
4617 				}
4618 				else
4619 				{
4620 					UniStrCpy(tmp, sizeof(tmp), account_name);
4621 				}
4622 
4623 				MsAppendMenu(h, MF_STRING, start_id + i, tmp);
4624 
4625 				Free(account_name);
4626 				Free(server_name);
4627 				Free(hub_name);
4628 			}
4629 
4630 			Free(status_str);
4631 		}
4632 	}
4633 
4634 	return h;
4635 }
4636 
4637 // Display the right-click menu of the task tray
CmShowTrayMenu(HWND hWnd)4638 void CmShowTrayMenu(HWND hWnd)
4639 {
4640 	HMENU h;
4641 	POINT p;
4642 	HMENU sub1, sub2, sub3, sub4;
4643 	bool locked;
4644 	bool easy;
4645 	// Validate arguments
4646 	if (hWnd == NULL)
4647 	{
4648 		return;
4649 	}
4650 
4651 	cm->MenuPopuping = true;
4652 
4653 	locked = cm->CmSetting.LockMode;
4654 	easy = cm->CmSetting.EasyMode;
4655 
4656 	// Create a menu
4657 	h = CreatePopupMenu();
4658 
4659 	// Cancel
4660 	MsAppendMenu(h, MF_ENABLED | MF_STRING, 100007, _UU("CM_TRAY_MENU_CANCEL"));
4661 
4662 	// Separator
4663 	MsAppendMenu(h, MF_SEPARATOR, 10006, NULL);
4664 
4665 	if (locked == false && easy == false)
4666 	{
4667 		// Creating a new connection settings
4668 		MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_NEW, _UU("CM_TRAY_MENU_NEW"));
4669 
4670 		// Separator
4671 		MsAppendMenu(h, MF_SEPARATOR, 10005, NULL);
4672 	}
4673 
4674 	// Connection menu
4675 	sub1 = CmCreateTraySubMenu(hWnd, false, CM_TRAY_MENU_CONNECT_ID_START);
4676 	if (sub1 != NULL)
4677 	{
4678 		MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
4679 			(UINT_PTR)sub1, _UU("CM_TRAY_MENU_CONNECT"));
4680 	}
4681 
4682 	// Disconnection menu
4683 	sub2 = CmCreateTraySubMenu(hWnd, true, CM_TRAY_MENU_DISCONNECT_ID_START);
4684 	if (sub2 != NULL)
4685 	{
4686 		MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
4687 			(UINT_PTR)sub2, _UU("CM_TRAY_MENU_DISCONNECT"));
4688 	}
4689 
4690 	// Status Display menu
4691 	sub3 = CmCreateTraySubMenu(hWnd, true, CM_TRAY_MENU_STATUS_ID_START);
4692 	if (sub3 != NULL)
4693 	{
4694 		MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
4695 			(UINT_PTR)sub3, _UU("CM_TRAY_MENU_STATUS"));
4696 	}
4697 
4698 	if (sub3 != NULL)
4699 	{
4700 		// Disconnect all connections
4701 		MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_DISCONNECT_ALL, _UU("CM_TRAY_MENU_DISCONNECT_ALL"));
4702 	}
4703 
4704 	if (sub1 != NULL || sub2 != NULL || sub3 != NULL)
4705 	{
4706 		// Separator
4707 		MsAppendMenu(h, MF_SEPARATOR, 10003, NULL);
4708 	}
4709 
4710 	// Connect to the recently connected VPN server
4711 	sub4 = CmCreateRecentSubMenu(hWnd, CM_TRAY_MENU_RECENT_ID_START);
4712 	if (sub4 != NULL)
4713 	{
4714 		MsAppendMenu(h, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
4715 			(UINT_PTR)sub4, _UU("CM_TRAY_MENU_RECENT"));
4716 		MsAppendMenu(h, MF_SEPARATOR, 10008, NULL);
4717 	}
4718 
4719 	if (locked == false && easy == false)
4720 	{
4721 		// Communication throughput measurement
4722 		MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_TRAFFIC, _UU("CM_TRAY_MENU_TRAFFIC"));
4723 	}
4724 
4725 	if (easy == false)
4726 	{
4727 		// Network device status
4728 		MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_NETIF, _UU("CM_TRAY_MENU_NETIF"));
4729 	}
4730 
4731 	// Version information
4732 	MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_ABOUT, _UU("CM_TRAY_MENU_ABOUT"));
4733 
4734 	// Separator
4735 	MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);
4736 
4737 	// Change the operating mode
4738 	MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_CM_SETTING, _UU("CM_TRAY_MENU_SETTING"));
4739 
4740 	// Separator
4741 	MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);
4742 
4743 	// Hide the icon
4744 	MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_TRAYICON, _UU("CM_MENU@CMD_TRAYICON"));
4745 
4746 	// Separator
4747 	MsAppendMenu(h, MF_SEPARATOR, 10001, NULL);
4748 
4749 	// Show or hide
4750 	MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_EXIT,
4751 		IsHide(hWnd, 0) ? _UU("CM_TRAY_MENU_1_SHOW") : _UU("CM_TRAY_MENU_1_HIDE"));
4752 
4753 	// Quit
4754 	MsAppendMenu(h, MF_ENABLED | MF_STRING, CMD_QUIT, _UU("CM_TRAY_MENU_2_QUIT"));
4755 
4756 	// Show the menu
4757 	GetCursorPos(&p);
4758 
4759 	SetForegroundWindow(hWnd);
4760 	TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
4761 	PostMessage(hWnd, WM_NULL, 0, 0);
4762 
4763 	if (sub1 != NULL)
4764 	{
4765 		DestroyMenu(sub1);
4766 	}
4767 
4768 	if (sub2 != NULL)
4769 	{
4770 		DestroyMenu(sub2);
4771 	}
4772 
4773 	if (sub3 != NULL)
4774 	{
4775 		DestroyMenu(sub3);
4776 	}
4777 
4778 	DestroyMenu(h);
4779 
4780 	cm->MenuPopuping = false;
4781 }
4782 
4783 // Hide or show the main window
CmShowOrHideWindow(HWND hWnd)4784 void CmShowOrHideWindow(HWND hWnd)
4785 {
4786 	// Validate arguments
4787 	if (hWnd == NULL)
4788 	{
4789 		return;
4790 	}
4791 
4792 	if (IsHide(hWnd, 0))
4793 	{
4794 		Show(hWnd, 0);
4795 		if (IsIconic(hWnd))
4796 		{
4797 			ShowWindow(hWnd, SW_SHOWNORMAL);
4798 		}
4799 		SetForegroundWindow(hWnd);
4800 		SetActiveWindow(hWnd);
4801 	}
4802 	else
4803 	{
4804 		CmSaveMainWindowPos(hWnd);
4805 		Hide(hWnd, 0);
4806 
4807 		if (cm->TrayInited == false)
4808 		{
4809 			Command(hWnd, CMD_QUIT);
4810 			return;
4811 		}
4812 	}
4813 }
4814 
4815 // Right-clicked on the account list
CmAccountListRightClick(HWND hWnd)4816 void CmAccountListRightClick(HWND hWnd)
4817 {
4818 	HMENU h;
4819 	HMENU parent;
4820 	UINT i;
4821 	// Validate arguments
4822 	if (hWnd == NULL)
4823 	{
4824 		return;
4825 	}
4826 
4827 	// Load the menu
4828 	h = LoadSubMenu(M_MAIN, 0, &parent);
4829 	if (h == NULL)
4830 	{
4831 		return;
4832 	}
4833 
4834 	InitMenuInternational(h, "CM_MENU");
4835 
4836 	// Remove the shortcut key
4837 	RemoveShortcutKeyStrFromMenu(h);
4838 
4839 	// Delete the exit menu
4840 	i = GetMenuItemPos(h, CMD_QUIT);
4841 	if (i != INFINITE)
4842 	{
4843 		DeleteMenuItem(h, i);
4844 		DeleteMenuItem(h, i - 1);
4845 		DeleteMenuItem(h, i - 2);
4846 		DeleteMenuItem(h, i - 3);
4847 	}
4848 
4849 	// Set enable / disable
4850 	CmMainWindowOnPopupMenu(hWnd, h, INFINITE);
4851 
4852 	if (h != NULL)
4853 	{
4854 		// Determine whether the selected account is under connecting
4855 		UINT i = LvGetSelected(hWnd, L_ACCOUNT);
4856 		wchar_t *str;
4857 		bool is_connected = false;
4858 		if (i != INFINITE)
4859 		{
4860 			str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
4861 			if (str != NULL)
4862 			{
4863 				if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
4864 				{
4865 					// Connecting
4866 					is_connected = true;
4867 				}
4868 				Free(str);
4869 			}
4870 		}
4871 
4872 		if (i == INFINITE)
4873 		{
4874 			// Bold the New menu
4875 			SetMenuItemBold(h, GetMenuItemPos(h, CMD_NEW), true);
4876 		}
4877 		else
4878 		{
4879 			if (is_connected == false)
4880 			{
4881 				// Bold the connection menu
4882 				SetMenuItemBold(h, GetMenuItemPos(h, CMD_CONNECT), true);
4883 			}
4884 			else
4885 			{
4886 				// Bold the status menu
4887 				SetMenuItemBold(h, GetMenuItemPos(h, CMD_STATUS), true);
4888 			}
4889 		}
4890 	}
4891 
4892 	// Show the menu
4893 	PrintMenu(hWnd, h);
4894 
4895 	DestroyMenu(parent);
4896 }
4897 
4898 // Right-clicked on the virtual LAN card list
CmVLanListRightClick(HWND hWnd)4899 void CmVLanListRightClick(HWND hWnd)
4900 {
4901 	HMENU h;
4902 	HMENU parent;
4903 	// Validate arguments
4904 	if (hWnd == NULL)
4905 	{
4906 		return;
4907 	}
4908 
4909 	// Load the menu
4910 	h = LoadSubMenu(M_MAIN, 3, &parent);
4911 	if (h == NULL)
4912 	{
4913 		return;
4914 	}
4915 
4916 	InitMenuInternational(h, "CM_MENU");
4917 
4918 	// Remove the shortcut key
4919 	RemoveShortcutKeyStrFromMenu(h);
4920 
4921 	// Set enable / disable
4922 	CmMainWindowOnPopupMenu(hWnd, h, INFINITE);
4923 
4924 	if (h != NULL)
4925 	{
4926 		// Examine whether the selected device is enabled
4927 		UINT i = LvGetSelected(hWnd, L_VLAN);
4928 		wchar_t *str;
4929 		bool is_active = false;
4930 		if (i != INFINITE)
4931 		{
4932 			str = LvGetStr(hWnd, L_VLAN, i, 1);
4933 			if (str != NULL)
4934 			{
4935 				if (UniStrCmpi(str, _UU("CM_VLAN_ENABLED")) == 0)
4936 				{
4937 					// Enabled
4938 					is_active = true;
4939 				}
4940 				Free(str);
4941 			}
4942 		}
4943 
4944 		if (i == INFINITE)
4945 		{
4946 			// Bold the New menu
4947 			SetMenuItemBold(h, GetMenuItemPos(h, CMD_NEW_VLAN), true);
4948 		}
4949 		else
4950 		{
4951 			if (is_active == false)
4952 			{
4953 				// Bold the enable menu
4954 				SetMenuItemBold(h, GetMenuItemPos(h, CMD_ENABLE_VLAN), true);
4955 			}
4956 			else
4957 			{
4958 				// Bold the Windows Network Setup menu
4959 				SetMenuItemBold(h, GetMenuItemPos(h, CMD_WINNET), true);
4960 			}
4961 		}
4962 	}
4963 
4964 	// Show the menu
4965 	PrintMenu(hWnd, h);
4966 
4967 	DestroyMenu(parent);
4968 }
4969 
4970 // Notify to the main window
CmMainWindowOnNotify(HWND hWnd,NMHDR * n)4971 void CmMainWindowOnNotify(HWND hWnd, NMHDR *n)
4972 {
4973 	bool item_vlan;
4974 	NMLVDISPINFOW *disp_info;
4975 	NMLVKEYDOWN *key;
4976 
4977 	// Validate arguments
4978 	if (hWnd == NULL || n == NULL)
4979 	{
4980 		return;
4981 	}
4982 
4983 	switch (n->idFrom)
4984 	{
4985 	case L_ACCOUNT:
4986 	case L_VLAN:
4987 		if (n->idFrom == L_ACCOUNT)
4988 		{
4989 			item_vlan = false;
4990 		}
4991 		else
4992 		{
4993 			item_vlan = true;
4994 		}
4995 
4996 		switch (n->code)
4997 		{
4998 		case NM_DBLCLK:
4999 			// Double click
5000 			CmOnKey(hWnd, false, false, VK_RETURN);
5001 			break;
5002 		case NM_RCLICK:
5003 			// Right click
5004 			if (item_vlan == false)
5005 			{
5006 				CmAccountListRightClick(hWnd);
5007 			}
5008 			else
5009 			{
5010 				CmVLanListRightClick(hWnd);
5011 			}
5012 			break;
5013 		case LVN_ENDLABELEDITW:
5014 			// Change the name
5015 			disp_info = (NMLVDISPINFOW *)n;
5016 			if (disp_info->item.pszText != NULL)
5017 			{
5018 				wchar_t *new_name = disp_info->item.pszText;
5019 				wchar_t *old_name = LvGetStr(hWnd, L_ACCOUNT, disp_info->item.iItem, 0);
5020 
5021 				if (old_name != NULL)
5022 				{
5023 					if (UniStrCmp(new_name, old_name) != 0 && UniIsEmptyStr(new_name) == false)
5024 					{
5025 						RPC_RENAME_ACCOUNT a;
5026 						Zero(&a, sizeof(a));
5027 						UniStrCpy(a.OldName, sizeof(a.OldName), old_name);
5028 						UniStrCpy(a.NewName, sizeof(a.NewName), new_name);
5029 						if (CALL(hWnd, CcRenameAccount(cm->Client, &a)))
5030 						{
5031 							LvSetItem(hWnd, L_ACCOUNT, disp_info->item.iItem, 0, new_name);
5032 						}
5033 					}
5034 
5035 					Free(old_name);
5036 				}
5037 			}
5038 			break;
5039 		case LVN_KEYDOWN:
5040 			// Key pressed
5041 			key = (NMLVKEYDOWN *)n;
5042 			if (key != NULL)
5043 			{
5044 				bool ctrl, alt;
5045 				UINT code = key->wVKey;
5046 				ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
5047 				alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
5048 				CmOnKey(hWnd, ctrl, alt, code);
5049 			}
5050 			break;
5051 		}
5052 		break;
5053 	}
5054 }
5055 
5056 // Keyboard pressed
CmOnKey(HWND hWnd,bool ctrl,bool alt,UINT key)5057 void CmOnKey(HWND hWnd, bool ctrl, bool alt, UINT key)
5058 {
5059 	// Validate arguments
5060 	if (hWnd == NULL)
5061 	{
5062 		return;
5063 	}
5064 
5065 	// Single key
5066 	switch (key)
5067 	{
5068 	case VK_RETURN:
5069 		Command(hWnd, IDOK);
5070 		break;
5071 	case VK_DELETE:
5072 		// Delete
5073 		if (IsFocus(hWnd, L_ACCOUNT))
5074 		{
5075 			// Operation on the account list
5076 			Command(hWnd, CMD_DELETE);
5077 		}
5078 		else
5079 		{
5080 			// Operation on the virtual LAN card list
5081 			Command(hWnd, CMD_DELETE_VLAN);
5082 		}
5083 		break;
5084 	case VK_F2:
5085 		// Change the name
5086 		Command(hWnd, CMD_RENAME);
5087 		break;
5088 	case VK_F5:
5089 		// Update the status
5090 		Command(hWnd, CMD_REFRESH);
5091 		break;
5092 	}
5093 
5094 	if (alt)
5095 	{
5096 		switch (key)
5097 		{
5098 		case 'Q':
5099 			// Close
5100 			Command(hWnd, CMD_QUIT);
5101 			break;
5102 		}
5103 	}
5104 
5105 	if (ctrl)
5106 	{
5107 		switch (key)
5108 		{
5109 		case 'G':
5110 			// Smart Card Manager
5111 			Command(hWnd, CMD_SECURE_MANAGER);
5112 			break;
5113 		case 'S':
5114 			// Show the state
5115 			Command(hWnd, CMD_STATUS);
5116 			break;
5117 		case 'I':
5118 			// Disconnect all connections
5119 			Command(hWnd, CMD_DISCONNECT_ALL);
5120 			break;
5121 		case 'D':
5122 			// Disconnect
5123 			Command(hWnd, CMD_DISCONNECT);
5124 			break;
5125 		case 'N':
5126 			// Create a new connection settings
5127 			Command(hWnd, CMD_NEW);
5128 			break;
5129 		case 'C':
5130 			// Creating a copy
5131 			Command(hWnd, CMD_CLONE);
5132 			break;
5133 		case 'T':
5134 			// Set to start-up connection
5135 			Command(hWnd, CMD_STARTUP);
5136 			break;
5137 		case 'A':
5138 			// Select all
5139 			Command(hWnd, CMD_SELECT_ALL);
5140 			break;
5141 		case 'L':
5142 			// Create a new virtual LAN card
5143 			Command(hWnd, CMD_NEW_VLAN);
5144 			break;
5145 		case 'E':
5146 			// Enable the virtual LAN card
5147 			Command(hWnd, CMD_ENABLE_VLAN);
5148 			break;
5149 		case 'B':
5150 			// Disable the virtual LAN card
5151 			Command(hWnd, CMD_DISABLE_VLAN);
5152 			break;
5153 		case 'U':
5154 			// Reinstall the driver
5155 			Command(hWnd, CMD_REINSTALL);
5156 			break;
5157 		case 'W':
5158 			// Configure Windows network connection
5159 			Command(hWnd, CMD_WINNET);
5160 			break;
5161 		case 'P':
5162 			// Set the password
5163 			Command(hWnd, CMD_PASSWORD);
5164 			break;
5165 		case 'O':
5166 			// Option settings
5167 			Command(hWnd, CMD_TRAFFIC);
5168 			break;
5169 		case 'R':
5170 			// Certificate management
5171 			Command(hWnd, CMD_TRUST);
5172 			break;
5173 		case 'Q':
5174 			// Throughput
5175 			Command(hWnd, CMD_TRAFFIC);
5176 			break;
5177 		}
5178 	}
5179 }
5180 
5181 // Command of the main window
CmMainWindowOnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)5182 void CmMainWindowOnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
5183 {
5184 	CmMainWindowOnCommandEx(hWnd, wParam, lParam, false);
5185 }
CmMainWindowOnCommandEx(HWND hWnd,WPARAM wParam,LPARAM lParam,bool easy)5186 void CmMainWindowOnCommandEx(HWND hWnd, WPARAM wParam, LPARAM lParam, bool easy)
5187 {
5188 	wchar_t *tmp;
5189 	char *name;
5190 	UINT index;
5191 	UINT id;
5192 	bool ctrl, alt;
5193 	UINT flag = 0;
5194 	// Validate arguments
5195 	wchar_t *selected_name = NULL;
5196 	UINT starter_id = 0;
5197 	if (hWnd == NULL)
5198 	{
5199 		return;
5200 	}
5201 
5202 	ctrl = (GetKeyState(VK_CONTROL) & 0x8000) == 0 ? false : true;
5203 	alt = (GetKeyState(VK_MENU) & 0x8000) == 0 ? false : true;
5204 
5205 	if (wParam == IDOK)
5206 	{
5207 		tmp = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
5208 		if (tmp != NULL)
5209 		{
5210 			if (UniStrCmpi(tmp, _UU("CM_NEW_ICON")) == 0)
5211 			{
5212 				Free(tmp);
5213 				Command(hWnd, CMD_NEW);
5214 				return;
5215 			}
5216 			if (UniStrCmpi(tmp, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(tmp, _UU("CM_VGC_LINK")) == 0)
5217 			{
5218 				Free(tmp);
5219 				Command(hWnd, CMD_VGC_CONNECT);
5220 				return;
5221 			}
5222 			Free(tmp);
5223 		}
5224 	}
5225 
5226 	if (CmIsEnabled(hWnd, (UINT)wParam) == false)
5227 	{
5228 		return;
5229 	}
5230 
5231 	if (CM_TRAY_IS_CONNECT_ID(wParam))
5232 	{
5233 		// Connection request
5234 		starter_id = CM_TRAY_MENU_CONNECT_ID_START;
5235 		flag = 1;
5236 	}
5237 
5238 	if (CM_TRAY_IS_STATUS_ID(wParam))
5239 	{
5240 		// Information display request
5241 		starter_id = CM_TRAY_MENU_STATUS_ID_START;
5242 		flag = 2;
5243 	}
5244 
5245 	if (CM_TRAY_IS_DISCONNECT_ID(wParam))
5246 	{
5247 		// Disconnect request
5248 		starter_id = CM_TRAY_MENU_DISCONNECT_ID_START;
5249 		flag = 3;
5250 	}
5251 
5252 	if (CM_TRAY_IS_RECENT_ID(wParam))
5253 	{
5254 		// Recent destinations
5255 		starter_id = CM_TRAY_MENU_RECENT_ID_START;
5256 		flag = 1;
5257 	}
5258 
5259 	if (starter_id != 0)
5260 	{
5261 		UINT num;
5262 
5263 		id = (UINT)wParam - starter_id;
5264 
5265 		num = LvNum(hWnd, L_ACCOUNT);
5266 
5267 		if (id < num)
5268 		{
5269 			selected_name = LvGetStr(hWnd, L_ACCOUNT, id, 0);
5270 
5271 			if (selected_name != NULL)
5272 			{
5273 				if (UniStrCmpi(selected_name, _UU("CM_NEW_ICON")) != 0 &&
5274 					UniStrCmpi(selected_name, _UU("CM_VGC_ICON")) != 0 &&
5275 					UniStrCmpi(selected_name, _UU("CM_VGC_LINK")) != 0)
5276 				{
5277 					switch (flag)
5278 					{
5279 					case 1:
5280 						CmConnect(hWnd, selected_name);
5281 						break;
5282 
5283 					case 2:
5284 						CmStatus(hWnd, selected_name);
5285 						break;
5286 
5287 					case 3:
5288 						CmDisconnect(hWnd, selected_name);
5289 						break;
5290 					}
5291 				}
5292 			}
5293 
5294 			Free(selected_name);
5295 		}
5296 	}
5297 
5298 	switch (wParam)
5299 	{
5300 	case IDOK:
5301 	case CMD_EASY_DBLCLICK:
5302 		// Property or connection
5303 		if (IsFocus(hWnd, L_ACCOUNT) || (hWnd == cm->hEasyWnd))
5304 		{
5305 			// Operation about the account list
5306 			if (alt == false)
5307 			{
5308 				UINT index = LvGetSelected(hWnd, L_ACCOUNT);
5309 				bool b = false;
5310 				if (index != INFINITE)
5311 				{
5312 					wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, index, 1);
5313 					if (s != NULL)
5314 					{
5315 						if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)
5316 						{
5317 							b = true;
5318 						}
5319 						Free(s);
5320 					}
5321 				}
5322 
5323 				if (b == false)
5324 				{
5325 					// Connection
5326 					Command(hWnd, CMD_CONNECT);
5327 				}
5328 				else
5329 				{
5330 					if (hWnd != cm->hEasyWnd || wParam == CMD_EASY_DBLCLICK)
5331 					{
5332 						// Display status
5333 						Command(hWnd, CMD_STATUS);
5334 					}
5335 					else
5336 					{
5337 						// Disconnect
5338 						Command(hWnd, CMD_DISCONNECT);
5339 					}
5340 				}
5341 			}
5342 			else
5343 			{
5344 				// Property
5345 				Command(hWnd, CMD_PROPERTY);
5346 			}
5347 		}
5348 		else
5349 		{
5350 			// Configure Windows network connection
5351 			Command(hWnd, CMD_WINNET);
5352 		}
5353 		break;
5354 	case CMD_CONNECT:
5355 		// Connection
5356 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5357 		if (tmp != NULL)
5358 		{
5359 			CmConnect(hWnd, tmp);
5360 			Free(tmp);
5361 		}
5362 		break;
5363 	case CMD_STATUS:
5364 		// Show the status
5365 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5366 		if (tmp != NULL)
5367 		{
5368 			CmStatus(hWnd, tmp);
5369 			Free(tmp);
5370 		}
5371 		break;
5372 	case CMD_DISCONNECT_ALL:
5373 		// Disconnect all connections
5374 		CmDisconnectAll(hWnd);
5375 		break;
5376 	case CMD_DISCONNECT:
5377 		// Disconnect
5378 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5379 		if (tmp != NULL)
5380 		{
5381 			CmDisconnect(hWnd, tmp);
5382 			Free(tmp);
5383 		}
5384 		break;
5385 	case CMD_NEW:
5386 		// Create new
5387 		CmNewAccount(hWnd);
5388 		break;
5389 
5390 
5391 	case CMD_CLONE:
5392 		// Copy
5393 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5394 		if (tmp != NULL)
5395 		{
5396 			CmCopyAccount(hWnd, tmp);
5397 			Free(tmp);
5398 		}
5399 		break;
5400 	case CMD_SHORTCUT:
5401 		// Create a shortcut
5402 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5403 		if (tmp != NULL)
5404 		{
5405 			CmSortcut(hWnd, tmp);
5406 			Free(tmp);
5407 		}
5408 		break;
5409 	case CMD_EXPORT_ACCOUNT:
5410 		// Export settings
5411 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5412 		if (tmp != NULL)
5413 		{
5414 			CmExportAccount(hWnd, tmp);
5415 			Free(tmp);
5416 		}
5417 		break;
5418 	case CMD_IMPORT_ACCOUNT:
5419 		// Import settings
5420 		CmImportAccount(hWnd);
5421 		break;
5422 	case CMD_STARTUP:
5423 		// Set to start-up connection
5424 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5425 		if (tmp != NULL)
5426 		{
5427 			RPC_CLIENT_DELETE_ACCOUNT c;
5428 			Zero(&c, sizeof(c));
5429 			UniStrCpy(c.AccountName, sizeof(c.AccountName), tmp);
5430 			CALL(hWnd, CcSetStartupAccount(cm->Client, &c));
5431 			CmVoice("set_startup");
5432 			MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_SET_STARTUP"), tmp);
5433 			Free(tmp);
5434 		}
5435 		break;
5436 	case CMD_NOSTARTUP:
5437 		// Unset the start-up connection
5438 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5439 		if (tmp != NULL)
5440 		{
5441 			if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
5442 				_UU("CM_REMOVE_STARTUP"), tmp) == IDYES)
5443 			{
5444 				RPC_CLIENT_DELETE_ACCOUNT c;
5445 				Zero(&c, sizeof(c));
5446 				UniStrCpy(c.AccountName, sizeof(c.AccountName), tmp);
5447 				CALL(hWnd, CcRemoveStartupAccount(cm->Client, &c));
5448 				CmVoice("remove_startup");
5449 			}
5450 			Free(tmp);
5451 		}
5452 		break;
5453 	case CMD_DELETE:
5454 		// Delete
5455 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5456 		if (tmp != NULL)
5457 		{
5458 			CmDeleteAccount(hWnd, tmp);
5459 			Free(tmp);
5460 		}
5461 		break;
5462 	case CMD_RENAME:
5463 		// Change the name
5464 		Focus(hWnd, L_ACCOUNT);
5465 		LvRename(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT));
5466 		break;
5467 	case CMD_PROPERTY:
5468 		// Property
5469 		tmp = LvGetStr(hWnd, L_ACCOUNT, LvGetSelected(hWnd, L_ACCOUNT), 0);
5470 		if (tmp != NULL)
5471 		{
5472 			CmEditAccount(hWnd, tmp);
5473 			Free(tmp);
5474 		}
5475 		break;
5476 	case IDCANCEL:
5477 	case CMD_EXIT:
5478 		// Close
5479 		Close(hWnd);
5480 		break;
5481 	case CMD_QUIT:
5482 		// Exit
5483 		CmMainWindowOnQuit(hWnd);
5484 		break;
5485 	case CMD_SELECT_ALL:
5486 		// Select all
5487 		LvSelectAll(hWnd, L_ACCOUNT);
5488 		LvSelectAll(hWnd, L_VLAN);
5489 		break;
5490 	case CMD_SWITCH_SELECT:
5491 		// Invert selection
5492 		LvSwitchSelect(hWnd, L_ACCOUNT);
5493 		LvSwitchSelect(hWnd, L_VLAN);
5494 		break;
5495 	case CMD_GRID:
5496 		// Show grid
5497 		cm->ShowGrid = !cm->ShowGrid;
5498 		CmRefreshVLanListEx(hWnd, true);
5499 		CmRefreshAccountListEx2(hWnd, false, true);
5500 		break;
5501 	case CMD_STATUSBAR:
5502 		// Show the status bar
5503 		if (cm->HideStatusBar == false)
5504 		{
5505 			cm->HideStatusBar = true;
5506 			Hide(hWnd, S_STATUSBAR);
5507 			CmMainWindowOnSize(hWnd);
5508 		}
5509 		else
5510 		{
5511 			cm->HideStatusBar = false;
5512 			Show(hWnd, S_STATUSBAR);
5513 			CmMainWindowOnSize(hWnd);
5514 		}
5515 		CmSaveMainWindowPos(hWnd);
5516 		break;
5517 	case CMD_VISTASTYLE:
5518 		cm->VistaStyle = !cm->VistaStyle;
5519 		CmRefreshEx(hWnd, true);
5520 		CmSaveMainWindowPos(hWnd);
5521 		break;
5522 	case CMD_TRAYICON:
5523 		// Tray icon display
5524 		if (cm->HideTrayIcon == false)
5525 		{
5526 			cm->HideTrayIcon = true;
5527 			CmFreeTray(hWnd);
5528 
5529 			if (IsHide(hWnd, 0))
5530 			{
5531 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_TRAY_ICON_RESTORE"));
5532 			}
5533 		}
5534 		else
5535 		{
5536 			cm->HideTrayIcon = false;
5537 			if (cm->server_name == NULL)
5538 			{
5539 				CmInitTray(hWnd);
5540 			}
5541 		}
5542 		break;
5543 	case CMD_SHOWPORT:
5544 		// Show the port number
5545 		cm->ShowPort = !cm->ShowPort;
5546 		CmRefresh(hWnd);
5547 		break;
5548 	case CMD_ICON:
5549 		// Show the icon
5550 		if (cm->IconView == false)
5551 		{
5552 			cm->IconView = true;
5553 			CmRefresh(hWnd);
5554 		}
5555 		break;
5556 	case CMD_DETAIL:
5557 		// Show details
5558 		if (cm->IconView)
5559 		{
5560 			cm->IconView = false;
5561 			CmRefresh(hWnd);
5562 		}
5563 		break;
5564 	case CMD_REFRESH:
5565 		if (easy == false)
5566 		{
5567 			// Display update
5568 			LvReset(hWnd, L_ACCOUNT);
5569 			LvReset(hWnd, L_VLAN);
5570 			CmRefresh(hWnd);
5571 		}
5572 		break;
5573 	case CMD_NEW_VLAN:
5574 		// Create a Virtual LAN card
5575 		if (CmStopInstallVLan(hWnd) == false)
5576 		{
5577 			// Installation is prohibited
5578 			break;
5579 		}
5580 		name = CmNewVLanDlg(hWnd);
5581 		if (name != NULL)
5582 		{
5583 			wchar_t tmp[MAX_SIZE];
5584 			void *helper = NULL;
5585 			RPC_CLIENT_CREATE_VLAN c;
5586 			Zero(&c, sizeof(c));
5587 			StrCpy(c.DeviceName, sizeof(c.DeviceName), name);
5588 			if (MsIsNt() == false)
5589 			{
5590 				// Change the title of the window
5591 				GetTxt(hWnd, 0, tmp, sizeof(tmp));
5592 				SetText(hWnd, 0, _UU("CM_VLAN_INSTALLING"));
5593 			}
5594 			// Minimize
5595 			if (MsIsVista() == false)
5596 			{
5597 				ShowWindow(hWnd, SW_SHOWMINIMIZED);
5598 			}
5599 
5600 			if (MsIsVista())
5601 			{
5602 				helper = CmStartUacHelper();
5603 			}
5604 
5605 			if (CALL(hWnd, CcCreateVLan(cm->Client, &c)))
5606 			{
5607 				CmVoice("new_vlan");
5608 			}
5609 
5610 			CmStopUacHelper(helper);
5611 
5612 			if (MsIsNt() == false)
5613 			{
5614 				// Restore the title of the window
5615 				SetText(hWnd, 0, tmp);
5616 			}
5617 			// Restore
5618 			if (MsIsVista() == false)
5619 			{
5620 				ShowWindow(hWnd, SW_SHOWNORMAL);
5621 			}
5622 			Free(name);
5623 		}
5624 		break;
5625 	case CMD_DELETE_VLAN:
5626 		// Delete the Virtual LAN card
5627 		index = LvGetSelected(hWnd, L_VLAN);
5628 		if (index != INFINITE)
5629 		{
5630 			if (cm->Client->Win9x == false)
5631 			{
5632 				// Windows 2000 or later
5633 				wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
5634 				if (s != NULL)
5635 				{
5636 					RPC_CLIENT_CREATE_VLAN c;
5637 					char str[MAX_SIZE];
5638 					CmVoice("delete_vlan_1");
5639 					if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_VLAN"), s) == IDYES)
5640 					{
5641 						Zero(&c, sizeof(c));
5642 						UniToStr(str, sizeof(str), s);
5643 						if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
5644 						{
5645 							if (CALL(hWnd, CcDeleteVLan(cm->Client, &c)))
5646 							{
5647 								CmVoice("delete_vlan_2");
5648 							}
5649 						}
5650 					}
5651 					Free(s);
5652 				}
5653 			}
5654 			else
5655 			{
5656 				// Windows 9x
5657 				if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_9X_VLAN_UNINSTALL")) == IDYES)
5658 				{
5659 					Run("rundll32.exe", "shell32.dll,Control_RunDLL NETCPL.CPL",
5660 						false, false);
5661 				}
5662 			}
5663 		}
5664 		break;
5665 	case CMD_ENABLE_VLAN:
5666 		// Enable the virtual LAN card
5667 		index = LvGetSelected(hWnd, L_VLAN);
5668 		if (index != INFINITE)
5669 		{
5670 			wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
5671 			if (s != NULL)
5672 			{
5673 				RPC_CLIENT_CREATE_VLAN c;
5674 				char str[MAX_SIZE];
5675 				Zero(&c, sizeof(c));
5676 				UniToStr(str, sizeof(str), s);
5677 				if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
5678 				{
5679 					CALL(hWnd, CcEnableVLan(cm->Client, &c));
5680 				}
5681 				Free(s);
5682 			}
5683 		}
5684 		break;
5685 	case CMD_DISABLE_VLAN:
5686 		// Disable the virtual LAN card
5687 		index = LvGetSelected(hWnd, L_VLAN);
5688 		if (index != INFINITE)
5689 		{
5690 			wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
5691 			if (s != NULL)
5692 			{
5693 				RPC_CLIENT_CREATE_VLAN c;
5694 				char str[MAX_SIZE];
5695 				Zero(&c, sizeof(c));
5696 				UniToStr(str, sizeof(str), s);
5697 				if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
5698 				{
5699 					CALL(hWnd, CcDisableVLan(cm->Client, &c));
5700 				}
5701 				Free(s);
5702 			}
5703 		}
5704 		break;
5705 	case CMD_REINSTALL:
5706 		// Reinstall the virtual LAN card
5707 		if (CmStopInstallVLan(hWnd) == false)
5708 		{
5709 			// Installation is prohibited
5710 			break;
5711 		}
5712 		// Warning message
5713 		if (MsgBox(hWnd, MB_ICONINFORMATION | MB_OKCANCEL, _UU("CM_VLAN_REINSTALL_MSG")) == IDCANCEL)
5714 		{
5715 			// Cancel
5716 			break;
5717 		}
5718 		index = LvGetSelected(hWnd, L_VLAN);
5719 		if (index != INFINITE)
5720 		{
5721 			wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 0);
5722 			if (s != NULL)
5723 			{
5724 				RPC_CLIENT_CREATE_VLAN c;
5725 				char str[MAX_SIZE];
5726 				Zero(&c, sizeof(c));
5727 				UniToStr(str, sizeof(str), s);
5728 				if (CmPrintNameToVLanName(c.DeviceName, sizeof(c.DeviceName), str))
5729 				{
5730 					void *helper = NULL;
5731 
5732 					if (MsIsVista() == false)
5733 					{
5734 						ShowWindow(hWnd, SW_SHOWMINIMIZED);
5735 					}
5736 
5737 					if (MsIsVista())
5738 					{
5739 						helper = CmStartUacHelper();
5740 					}
5741 
5742 					CALL(hWnd, CcUpgradeVLan(cm->Client, &c));
5743 
5744 					CmStopUacHelper(helper);
5745 
5746 					if (MsIsVista() == false)
5747 					{
5748 						ShowWindow(hWnd, SW_SHOWNORMAL);
5749 					}
5750 				}
5751 				Free(s);
5752 			}
5753 		}
5754 		break;
5755 	case CMD_PASSWORD:
5756 		// Password setting
5757 		CmPassword(hWnd);
5758 		break;
5759 	case CMD_OPTION:
5760 		// Option
5761 		CmConfigDlg(hWnd);
5762 		break;
5763 	case CMD_LANGUAGE:
5764 		// Language settings
5765 		if (true)
5766 		{
5767 			wchar_t path[MAX_SIZE];
5768 
5769 			CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"vpnsetup.exe");
5770 
5771 			if (MsExecuteW(path, L"/language:yes") == false)
5772 			{
5773 				MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
5774 			}
5775 		}
5776 		break;
5777 	case CMD_TRUST:
5778 		// Certificate management
5779 		CmTrustDlg(hWnd);
5780 		break;
5781 	case CMD_ABOUT:
5782 		// Version information
5783 		if (IsEnable(hWnd, 0))
5784 		{
5785 			AboutEx(hWnd, cm->Cedar, _UU("PRODUCT_NAME_VPN_CMGR"), cm->Update);
5786 		}
5787 		break;
5788 	case CMD_VOIDE_NONE:
5789 		cm->DisableVoice = true;
5790 		break;
5791 	case CMD_VOICE_NORMAL:
5792 		cm->DisableVoice = false;
5793 		cm->VoiceId = VOICE_SSK;
5794 		break;
5795 	case CMD_VOICE_ODD:
5796 		if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_EXT_VOICE_MSG")) == IDYES)
5797 		{
5798 			cm->DisableVoice = false;
5799 			cm->VoiceId = VOICE_AHO;
5800 		}
5801 		break;
5802 	case CMD_SECURE_MANAGER:
5803 		// Smart Card Manager
5804 		CmClientSecureManager(hWnd);
5805 		break;
5806 	case CMD_SECURE_SELECT:
5807 		// Select a smart card
5808 		CmClientSelectSecure(hWnd);
5809 		break;
5810 	case CMD_NETIF:
5811 		// State of the network device
5812 		if (IsEnable(hWnd, 0))
5813 		{
5814 			UtSpeedMeterEx(hWnd);
5815 		}
5816 		break;
5817 	case CMD_MMCSS:
5818 		// Optimization utility for Windows Vista
5819 		if (MsIsVista() == false)
5820 		{
5821 			MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_4"));
5822 		}
5823 		else
5824 		{
5825 			if (MsIsAdmin() == false)
5826 			{
5827 				MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("VISTA_MMCSS_MSG_4"));
5828 			}
5829 			else
5830 			{
5831 				if (MsIsMMCSSNetworkThrottlingEnabled())
5832 				{
5833 					if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("VISTA_MMCSS_MSG")) == IDYES)
5834 					{
5835 						MsSetMMCSSNetworkThrottlingEnable(false);
5836 						MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_5"));
5837 					}
5838 				}
5839 				else
5840 				{
5841 					if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("VISTA_MMCSS_MSG_2")) == IDYES)
5842 					{
5843 						MsSetMMCSSNetworkThrottlingEnable(true);
5844 						MsgBox(hWnd, MB_ICONINFORMATION, _UU("VISTA_MMCSS_MSG_6"));
5845 					}
5846 				}
5847 			}
5848 		}
5849 		break;
5850 	case CMD_TRAFFIC:
5851 		// Communication traffic measurement
5852 		if (IsEnable(hWnd, 0))
5853 		{
5854 			CmTraffic(hWnd);
5855 		}
5856 		break;
5857 	case CMD_CM_SETTING:
5858 		// Operation mode setting
5859 		if (IsEnable(hWnd, 0))
5860 		{
5861 			if (CmSetting(hWnd))
5862 			{
5863 				CmApplyCmSetting();
5864 			}
5865 		}
5866 		break;
5867 	case CMD_WINNET:
5868 		// Windows network settings
5869 		ShowWindowsNetworkConnectionDialog();
5870 		break;
5871 	}
5872 }
5873 
5874 // Option dialog
CmConfigDlg(HWND hWnd)5875 void CmConfigDlg(HWND hWnd)
5876 {
5877 	// Validate arguments
5878 	if (hWnd == NULL)
5879 	{
5880 		return;
5881 	}
5882 
5883 	Dialog(hWnd, D_CM_CONFIG, CmConfigDlgProc, NULL);
5884 }
5885 
5886 // Initialize the option dialog
CmConfigDlgInit(HWND hWnd)5887 void CmConfigDlgInit(HWND hWnd)
5888 {
5889 	bool use_alpha;
5890 	UINT alpha_value;
5891 	UINT os;
5892 	CLIENT_CONFIG c;
5893 	// Validate arguments
5894 	if (hWnd == NULL)
5895 	{
5896 		return;
5897 	}
5898 
5899 	DlgFont(hWnd, S_WARNING, 10, true);
5900 	DlgFont(hWnd, S_INFO, 10, false);
5901 
5902 	Zero(&c, sizeof(c));
5903 	if (CALL(hWnd, CcGetClientConfig(cm->Client, &c)) == false)
5904 	{
5905 		EndDialog(hWnd, 0);
5906 		return;
5907 	}
5908 
5909 	Check(hWnd, R_ALLOW_REMOTE_CONFIG, c.AllowRemoteConfig);
5910 
5911 	Check(hWnd, R_USE_KEEP_CONNECT, c.UseKeepConnect);
5912 	SetTextA(hWnd, E_HOSTNAME, c.KeepConnectHost);
5913 	SetIntEx(hWnd, E_PORT, c.KeepConnectPort);
5914 	SetIntEx(hWnd, E_INTERVAL, c.KeepConnectInterval);
5915 
5916 	Check(hWnd, R_TCP, c.KeepConnectProtocol == CONNECTION_TCP);
5917 	Check(hWnd, R_UDP, c.KeepConnectProtocol == CONNECTION_UDP);
5918 
5919 	use_alpha = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha") == 0 ? false : true;
5920 	alpha_value = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue");
5921 	alpha_value = MAKESURE(alpha_value, 0, 100);
5922 
5923 	SetInt(hWnd, E_ALPHA_VALUE, alpha_value == 0 ? 50 : alpha_value);
5924 	Check(hWnd, R_ALPHA, use_alpha);
5925 
5926 	os = GetOsInfo()->OsType;
5927 	if (OS_IS_WINDOWS_NT(os) && GET_KETA(os, 100) >= 2)
5928 	{
5929 		Enable(hWnd, R_ALPHA);
5930 	}
5931 	else
5932 	{
5933 		Disable(hWnd, R_ALPHA);
5934 	}
5935 
5936 	CmConfigDlgRefresh(hWnd);
5937 }
5938 
5939 // Update the option dialog
CmConfigDlgRefresh(HWND hWnd)5940 void CmConfigDlgRefresh(HWND hWnd)
5941 {
5942 	bool ok = true;
5943 	bool use_keep_connect;
5944 	// Validate arguments
5945 	if (hWnd == NULL)
5946 	{
5947 		return;
5948 	}
5949 
5950 	use_keep_connect = IsChecked(hWnd, R_USE_KEEP_CONNECT);
5951 	SetEnable(hWnd, S_HOSTNAME, use_keep_connect);
5952 	SetEnable(hWnd, S_PORT, use_keep_connect);
5953 	SetEnable(hWnd, S_INTERVAL, use_keep_connect);
5954 	SetEnable(hWnd, S_INTERVAL2, use_keep_connect);
5955 	SetEnable(hWnd, S_PROTOCOL, use_keep_connect);
5956 	SetEnable(hWnd, S_INFO, use_keep_connect);
5957 	SetEnable(hWnd, S_INFO2, use_keep_connect);
5958 	SetEnable(hWnd, E_HOSTNAME, use_keep_connect);
5959 	SetEnable(hWnd, E_PORT, use_keep_connect);
5960 	SetEnable(hWnd, E_INTERVAL, use_keep_connect);
5961 	SetEnable(hWnd, R_TCP, use_keep_connect);
5962 	SetEnable(hWnd, R_UDP, use_keep_connect);
5963 
5964 	SetEnable(hWnd, S_WARNING, IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG));
5965 
5966 	if (IsChecked(hWnd, R_USE_KEEP_CONNECT))
5967 	{
5968 		if (IsEmpty(hWnd, E_HOSTNAME))
5969 		{
5970 			ok = false;
5971 		}
5972 		if (IsChecked(hWnd, R_TCP) == false && IsChecked(hWnd, R_UDP) == false)
5973 		{
5974 			ok = false;
5975 		}
5976 		if (GetInt(hWnd, E_PORT) == 0 || GetInt(hWnd, E_PORT) >= 65536)
5977 		{
5978 			ok = false;
5979 		}
5980 		if (GetInt(hWnd, E_INTERVAL) == 0)
5981 		{
5982 			ok = false;
5983 		}
5984 	}
5985 
5986 	if (IsChecked(hWnd, R_ALPHA))
5987 	{
5988 		UINT i = GetInt(hWnd, E_ALPHA_VALUE);
5989 		if (i < 20 || i >= 100)
5990 		{
5991 			ok = false;
5992 		}
5993 		Enable(hWnd, E_ALPHA_VALUE);
5994 	}
5995 	else
5996 	{
5997 		Disable(hWnd, E_ALPHA_VALUE);
5998 	}
5999 
6000 	SetEnable(hWnd, IDOK, ok);
6001 }
6002 
6003 // Save the setting of the option dialog
CmConfigDlgOnOk(HWND hWnd)6004 void CmConfigDlgOnOk(HWND hWnd)
6005 {
6006 	CLIENT_CONFIG c;
6007 	// Validate arguments
6008 	if (hWnd == NULL)
6009 	{
6010 		return;
6011 	}
6012 
6013 	Zero(&c, sizeof(c));
6014 	c.AllowRemoteConfig = IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG);
6015 	c.UseKeepConnect = IsChecked(hWnd, R_USE_KEEP_CONNECT);
6016 	GetTxtA(hWnd, E_HOSTNAME, c.KeepConnectHost, sizeof(c.KeepConnectHost));
6017 	c.KeepConnectPort = GetInt(hWnd, E_PORT);
6018 	c.KeepConnectInterval = GetInt(hWnd, E_INTERVAL);
6019 	if (IsChecked(hWnd, R_TCP))
6020 	{
6021 		c.KeepConnectProtocol = CONNECTION_TCP;
6022 	}
6023 	else if (IsChecked(hWnd, R_UDP))
6024 	{
6025 		c.KeepConnectProtocol = CONNECTION_UDP;
6026 	}
6027 	else
6028 	{
6029 		return;
6030 	}
6031 
6032 	if (c.UseKeepConnect)
6033 	{
6034 		if (c.KeepConnectInterval < KEEP_INTERVAL_MIN || c.KeepConnectInterval > KEEP_INTERVAL_MAX)
6035 		{
6036 			MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_KEEP_INTERVAL_MSG"),
6037 				KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);
6038 			FocusEx(hWnd, E_INTERVAL);
6039 			return;
6040 		}
6041 	}
6042 
6043 	if (CALL(hWnd, CcSetClientConfig(cm->Client, &c)) == false)
6044 	{
6045 		return;
6046 	}
6047 
6048 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue", GetInt(hWnd, E_ALPHA_VALUE));
6049 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha", IsChecked(hWnd, R_ALPHA));
6050 
6051 	EndDialog(hWnd, true);
6052 }
6053 
6054 // Option setting dialog procedure
CmConfigDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)6055 UINT CmConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
6056 {
6057 	// Validate arguments
6058 	if (hWnd == NULL)
6059 	{
6060 		return 0;
6061 	}
6062 
6063 	switch (msg)
6064 	{
6065 	case WM_INITDIALOG:
6066 		CmConfigDlgInit(hWnd);
6067 		break;
6068 	case WM_COMMAND:
6069 		switch (LOWORD(wParam))
6070 		{
6071 		case R_ALLOW_REMOTE_CONFIG:
6072 		case R_USE_KEEP_CONNECT:
6073 		case E_HOSTNAME:
6074 		case E_PORT:
6075 		case E_INTERVAL:
6076 		case R_ALPHA:
6077 		case E_ALPHA_VALUE:
6078 			CmConfigDlgRefresh(hWnd);
6079 			break;
6080 		}
6081 
6082 		switch (wParam)
6083 		{
6084 		case IDOK:
6085 			CmConfigDlgRefresh(hWnd);
6086 			CmConfigDlgOnOk(hWnd);
6087 			break;
6088 		case IDCANCEL:
6089 			Close(hWnd);
6090 			break;
6091 		case R_ALLOW_REMOTE_CONFIG:
6092 			if (IsChecked(hWnd, R_ALLOW_REMOTE_CONFIG) == false)
6093 			{
6094 				if (cm->server_name != NULL)
6095 				{
6096 					// If the current user is remotely connected, show a warning
6097 					// when the user choose to disable the remote management
6098 					if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_DEFBUTTON2 | MB_YESNO, _UU("CM_REMOTE_WARNING"),
6099 						cm->server_name, cm->server_name) == IDNO)
6100 					{
6101 						Check(hWnd, R_ALLOW_REMOTE_CONFIG, true);
6102 					}
6103 				}
6104 			}
6105 			break;
6106 		case R_USE_KEEP_CONNECT:
6107 			if (IsChecked(hWnd, R_USE_KEEP_CONNECT))
6108 			{
6109 				FocusEx(hWnd, E_HOSTNAME);
6110 			}
6111 			break;
6112 		case R_ALPHA:
6113 			if (IsChecked(hWnd, R_ALPHA))
6114 			{
6115 				FocusEx(hWnd, E_ALPHA_VALUE);
6116 			}
6117 			break;
6118 		}
6119 		break;
6120 	case WM_CLOSE:
6121 		EndDialog(hWnd, false);
6122 		break;
6123 	}
6124 
6125 	return 0;
6126 }
6127 
6128 // Create a shortcut
CmSortcut(HWND hWnd,wchar_t * account_name)6129 void CmSortcut(HWND hWnd, wchar_t *account_name)
6130 {
6131 	wchar_t tmp[MAX_SIZE];
6132 	CM_ACCOUNT *a;
6133 	wchar_t *filename;
6134 	UCHAR key[SHA1_SIZE];
6135 	// Validate arguments
6136 	if (hWnd == NULL || account_name == NULL)
6137 	{
6138 		return;
6139 	}
6140 
6141 	// Get the account information
6142 	a = CmGetExistAccountObject(hWnd, account_name);
6143 	if (a == NULL)
6144 	{
6145 		return;
6146 	}
6147 
6148 	Copy(key, a->ShortcutKey, SHA1_SIZE);
6149 
6150 	if (IsZero(key, SHA1_SIZE))
6151 	{
6152 		MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_SHORTCUT_UNSUPPORTED"));
6153 	}
6154 	else
6155 	{
6156 		// Determine the file name
6157 		UniFormat(tmp, sizeof(tmp), L"%s.lnk", account_name);
6158 		UniSafeFileName(tmp);
6159 
6160 		filename = SaveDlg(hWnd, _UU("CM_SHORTCUT_FILE"),
6161 			_UU("CM_SHORTCUT_SAVE_TITLE"), tmp, L".vpn");
6162 
6163 		if (filename != NULL)
6164 		{
6165 			char key_str[64];
6166 			wchar_t target[MAX_PATH];
6167 			wchar_t workdir[MAX_PATH];
6168 			wchar_t args[MAX_PATH];
6169 			wchar_t comment[MAX_SIZE];
6170 			wchar_t icon[MAX_PATH];
6171 
6172 			BinToStr(key_str, sizeof(key_str), key, SHA1_SIZE);
6173 
6174 			// Create a shortcut
6175 			UniStrCpy(target, sizeof(target), MsGetExeFileNameW());
6176 			UniStrCpy(workdir, sizeof(workdir), MsGetExeDirNameW());
6177 			StrToUni(args, sizeof(args), key_str);
6178 			UniFormat(comment, sizeof(comment), _UU("CM_SHORTCUT_COMMENT"), account_name);
6179 			UniStrCpy(icon, sizeof(icon), MsGetExeFileNameW());
6180 
6181 			if (CreateLink(filename, target, workdir, args, comment, icon, 1) == false)
6182 			{
6183 				MsgBox(hWnd, MB_ICONSTOP, _UU("CM_SHORTCUT_ERROR"));
6184 			}
6185 
6186 			Free(filename);
6187 		}
6188 	}
6189 
6190 	CmFreeAccountObject(hWnd, a);
6191 }
6192 
6193 // Export the account
CmExportAccount(HWND hWnd,wchar_t * account_name)6194 void CmExportAccount(HWND hWnd, wchar_t *account_name)
6195 {
6196 	wchar_t tmp[MAX_SIZE];
6197 	CM_ACCOUNT *a;
6198 	wchar_t *filename;
6199 	// Validate arguments
6200 	if (hWnd == NULL || account_name == NULL)
6201 	{
6202 		return;
6203 	}
6204 
6205 	// Get the account information
6206 	a = CmGetExistAccountObject(hWnd, account_name);
6207 	if (a == NULL)
6208 	{
6209 		return;
6210 	}
6211 
6212 	// Determine the file name
6213 	UniFormat(tmp, sizeof(tmp), L"%s.vpn", account_name);
6214 	UniSafeFileName(tmp);
6215 
6216 	filename = SaveDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"),
6217 		_UU("CM_ACCOUNT_SAVE_TITLE"), tmp, L".vpn");
6218 
6219 	if (filename != NULL)
6220 	{
6221 		RPC_CLIENT_CREATE_ACCOUNT t;
6222 		BUF *b;
6223 		BUF *b2;
6224 		wchar_t tmp[MAX_SIZE];
6225 		UCHAR *buf;
6226 		UINT buf_size;
6227 		UCHAR bom[] = {0xef, 0xbb, 0xbf, };
6228 
6229 		Zero(&t, sizeof(t));
6230 		t.ClientOption = a->ClientOption;
6231 		t.ClientAuth = a->ClientAuth;
6232 		t.StartupAccount = a->Startup;
6233 		t.CheckServerCert = a->CheckServerCert;
6234 		t.ServerCert = a->ServerCert;
6235 		t.ClientOption->FromAdminPack = false;
6236 
6237 		b = CiAccountToCfg(&t);
6238 
6239 		SeekBuf(b, 0, 0);
6240 
6241 		// Check whether the password is contained
6242 		if (CiHasAccountSensitiveInformation(b))
6243 		{
6244 			SeekBuf(b, 0, 0);
6245 
6246 			// Confirm that the user want to clear the password
6247 			if (MsgBox(hWnd, MB_YESNO | MB_ICONQUESTION, _UU("CM_ACCOUNT_MSG_SENSITIVE")) == IDYES)
6248 			{
6249 				// Erase
6250 				CiEraseSensitiveInAccount(b);
6251 			}
6252 		}
6253 
6254 		UniStrCpy(tmp, sizeof(tmp), filename);
6255 		b2 = NewBuf();
6256 
6257 		WriteBuf(b2, bom, sizeof(bom));
6258 
6259 		// Add a header part
6260 		buf_size = CalcUniToUtf8(_UU("CM_ACCOUNT_FILE_BANNER"));
6261 		buf = ZeroMalloc(buf_size + 32);
6262 		UniToUtf8(buf, buf_size, _UU("CM_ACCOUNT_FILE_BANNER"));
6263 
6264 		WriteBuf(b2, buf, StrLen((char *)buf));
6265 		WriteBuf(b2, b->Buf, b->Size);
6266 		SeekBuf(b2, 0, 0);
6267 
6268 		FreeBuf(b);
6269 
6270 		if (DumpBufW(b2, tmp) == false)
6271 		{
6272 			MsgBox(hWnd, MB_ICONSTOP, _UU("CM_FAILED_TO_SAVE_FILE"));
6273 		}
6274 
6275 		Free(filename);
6276 		FreeBuf(b2);
6277 		Free(buf);
6278 	}
6279 
6280 	CmFreeAccountObject(hWnd, a);
6281 }
6282 
6283 // Main process of importing account
CmImportAccountMain(HWND hWnd,wchar_t * filename)6284 void CmImportAccountMain(HWND hWnd, wchar_t *filename)
6285 {
6286 	CmImportAccountMainEx(hWnd, filename, false);
6287 }
CmImportAccountMainEx(HWND hWnd,wchar_t * filename,bool overwrite)6288 void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite)
6289 {
6290 	wchar_t name[MAX_SIZE];
6291 	wchar_t tmp[MAX_SIZE];
6292 	BUF *b;
6293 	RPC_CLIENT_CREATE_ACCOUNT *t;
6294 	// Validate arguments
6295 	if (hWnd == NULL || filename == NULL)
6296 	{
6297 		return;
6298 	}
6299 
6300 	UniStrCpy(tmp, sizeof(tmp), filename);
6301 
6302 	b = ReadDumpW(tmp);
6303 	if (b == NULL)
6304 	{
6305 		MsgBox(hWnd, MB_ICONSTOP, _UU("CM_FAILED_TO_OPEN_FILE"));
6306 		return;
6307 	}
6308 
6309 	t = CiCfgToAccount(b);
6310 	if (t == NULL)
6311 	{
6312 		FreeBuf(b);
6313 		MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED"));
6314 		return;
6315 	}
6316 
6317 	if (overwrite)
6318 	{
6319 		// If the same name already exists, remove it
6320 		if (LvSearchStr(hWnd, L_ACCOUNT, 0, t->ClientOption->AccountName) != INFINITE)
6321 		{
6322 			RPC_CLIENT_DELETE_ACCOUNT d;
6323 			RPC_CLIENT_GET_ACCOUNT get;
6324 			HWND h = cm->hEasyWnd == NULL ? hWnd : cm->hEasyWnd;
6325 
6326 			Zero(&d, sizeof(d));
6327 			UniStrCpy(d.AccountName, sizeof(d.AccountName), t->ClientOption->AccountName);
6328 
6329 			Zero(&get, sizeof(get));
6330 			UniStrCpy(get.AccountName, sizeof(get.AccountName), t->ClientOption->AccountName);
6331 			if (CcGetAccount(cm->Client, &get) == ERR_NO_ERROR)
6332 			{
6333 				// Inherit the information of some of the client option by getting
6334 				// the account information of the same name that already exists
6335 				if (get.ClientOption != NULL && get.ClientAuth != NULL)
6336 				{
6337 					CLIENT_OPTION *old_option = get.ClientOption;
6338 					CLIENT_AUTH *old_auth = get.ClientAuth;
6339 
6340 					// Inherit the connection parameters
6341 					t->ClientOption->ProxyType = old_option->ProxyType;
6342 					StrCpy(t->ClientOption->ProxyName, sizeof(t->ClientOption->ProxyName),
6343 						old_option->ProxyName);
6344 					t->ClientOption->ProxyPort = old_option->ProxyPort;
6345 					StrCpy(t->ClientOption->ProxyUsername, sizeof(t->ClientOption->ProxyUsername),
6346 						old_option->ProxyUsername);
6347 					StrCpy(t->ClientOption->ProxyPassword, sizeof(t->ClientOption->ProxyPassword),
6348 						old_option->ProxyPassword);
6349 					t->ClientOption->NumRetry = old_option->NumRetry;
6350 					t->ClientOption->RetryInterval = old_option->RetryInterval;
6351 					t->ClientOption->MaxConnection = old_option->MaxConnection;
6352 					t->ClientOption->UseEncrypt = old_option->UseEncrypt;
6353 					t->ClientOption->UseCompress = old_option->UseCompress;
6354 					t->ClientOption->HalfConnection = old_option->HalfConnection;
6355 					t->ClientOption->NoRoutingTracking = old_option->NoRoutingTracking;
6356 					StrCpy(t->ClientOption->DeviceName, sizeof(t->ClientOption->DeviceName),
6357 						old_option->DeviceName);
6358 					t->ClientOption->AdditionalConnectionInterval = old_option->AdditionalConnectionInterval;
6359 					t->ClientOption->ConnectionDisconnectSpan = old_option->ConnectionDisconnectSpan;
6360 					t->ClientOption->HideStatusWindow = old_option->HideStatusWindow;
6361 					t->ClientOption->RequireMonitorMode = old_option->RequireMonitorMode;
6362 					t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode;
6363 					t->ClientOption->DisableQoS = old_option->DisableQoS;
6364 					t->ClientOption->NoTls1 = old_option->NoTls1;
6365 
6366 					// Inherit the authentication data
6367 					CiFreeClientAuth(t->ClientAuth);
6368 					t->ClientAuth = CopyClientAuth(old_auth);
6369 
6370 					// Other Settings
6371 					t->StartupAccount = get.StartupAccount;
6372 					t->CheckServerCert = get.CheckServerCert;
6373 					if (t->ServerCert != NULL)
6374 					{
6375 						FreeX(t->ServerCert);
6376 					}
6377 					t->ServerCert = NULL;
6378 					if (get.ServerCert != NULL)
6379 					{
6380 						t->ServerCert = CloneX(get.ServerCert);
6381 					}
6382 					Copy(t->ShortcutKey, get.ShortcutKey, sizeof(t->ShortcutKey));
6383 				}
6384 
6385 				CiFreeClientGetAccount(&get);
6386 			}
6387 
6388 			if (CALL(h, CcDeleteAccount(cm->Client, &d)) == false)
6389 			{
6390 				CiFreeClientCreateAccount(t);
6391 				Free(t);
6392 				return;
6393 			}
6394 
6395 			CmRefreshAccountList(hWnd);
6396 		}
6397 	}
6398 
6399 	CmGenerateImportName(hWnd, name, sizeof(name), t->ClientOption->AccountName);
6400 	UniStrCpy(t->ClientOption->AccountName, sizeof(t->ClientOption->AccountName), name);
6401 
6402 	if (overwrite)
6403 	{
6404 		t->ClientOption->FromAdminPack = true;
6405 	}
6406 
6407 	CALL(hWnd, CcCreateAccount(cm->Client, t));
6408 
6409 	CiFreeClientCreateAccount(t);
6410 	Free(t);
6411 
6412 	FreeBuf(b);
6413 
6414 	if (overwrite)
6415 	{
6416 		// Start to connect the VPN
6417 		CmConnect(hWnd, name);
6418 	}
6419 
6420 	//MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_IMPORT_MESSAGE"), filename, name);
6421 }
6422 
6423 // Import an account
CmImportAccount(HWND hWnd)6424 void CmImportAccount(HWND hWnd)
6425 {
6426 	wchar_t *filename;
6427 	wchar_t tmp[MAX_SIZE];
6428 	// Validate arguments
6429 	if (hWnd == NULL)
6430 	{
6431 		return;
6432 	}
6433 
6434 	// Open the file
6435 	filename = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE"));
6436 	if (filename == NULL)
6437 	{
6438 		return;
6439 	}
6440 
6441 	UniStrCpy(tmp, sizeof(tmp), filename);
6442 	Free(filename);
6443 
6444 	CmImportAccountMain(hWnd, tmp);
6445 }
6446 
6447 // Create a copy of the account
CmCopyAccount(HWND hWnd,wchar_t * account_name)6448 void CmCopyAccount(HWND hWnd, wchar_t *account_name)
6449 {
6450 	wchar_t tmp[MAX_SIZE];
6451 	CM_ACCOUNT *a;
6452 	RPC_CLIENT_CREATE_ACCOUNT c;
6453 	// Validate arguments
6454 	if (hWnd == NULL || account_name == NULL)
6455 	{
6456 		return;
6457 	}
6458 
6459 	CmGenerateCopyName(hWnd, tmp, sizeof(tmp), account_name);
6460 
6461 	// Get an account information
6462 	a = CmGetExistAccountObject(hWnd, account_name);
6463 	if (a == NULL)
6464 	{
6465 		return;
6466 	}
6467 
6468 	// Change the account name
6469 	UniStrCpy(a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName), tmp);
6470 
6471 	// Write
6472 	Zero(&c, sizeof(c));
6473 	c.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6474 	Copy(c.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
6475 	c.ClientAuth = CopyClientAuth(a->ClientAuth);
6476 	if (a->ServerCert)
6477 	{
6478 		c.ServerCert = CloneX(a->ServerCert);
6479 	}
6480 	c.CheckServerCert = a->CheckServerCert;
6481 	c.StartupAccount = false;		// Don't copy the startup attribute
6482 
6483 	CALL(hWnd, CcCreateAccount(cm->Client, &c));
6484 	CiFreeClientCreateAccount(&c);
6485 
6486 	CmFreeAccountObject(hWnd, a);
6487 }
6488 
6489 // Update the Virtual LAN Card Name dialog
CmNewVLanDlgUpdate(HWND hWnd)6490 void CmNewVLanDlgUpdate(HWND hWnd)
6491 {
6492 	bool ok = true;
6493 	char tmp[MAX_SIZE];
6494 	// Validate arguments
6495 	if (hWnd == NULL)
6496 	{
6497 		return;
6498 	}
6499 
6500 	GetTxtA(hWnd, E_NAME, tmp, sizeof(tmp));
6501 	if (IsSafeStr(tmp) == false)
6502 	{
6503 		ok = false;
6504 	}
6505 	if (SearchStrEx(tmp, " ", 0, false) != INFINITE)
6506 	{
6507 		ok = false;
6508 	}
6509 
6510 	Trim(tmp);
6511 	if (StrLen(tmp) == 0)
6512 	{
6513 		ok = false;
6514 	}
6515 
6516 	SetEnable(hWnd, IDOK, ok);
6517 }
6518 
6519 // Virtual LAN card name decision dialog procedure
CmNewVLanDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)6520 UINT CmNewVLanDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
6521 {
6522 	char *tmp = (char *)param;
6523 	char default_name[MAX_SIZE];
6524 	RPC_CLIENT_VERSION ver;
6525 	// Validate arguments
6526 	if (hWnd == NULL)
6527 	{
6528 		return 0;
6529 	}
6530 
6531 	switch (msg)
6532 	{
6533 	case WM_INITDIALOG:
6534 		LimitText(hWnd, E_NAME, cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN);
6535 		FormatText(hWnd, S_INFO, cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN);
6536 
6537 		Zero(&ver, sizeof(ver));
6538 
6539 		if (CcGetClientVersion(cm->Client, &ver) == ERR_NO_ERROR)
6540 		{
6541 			if (ver.IsVLanNameRegulated)
6542 			{
6543 				Show(hWnd, S_WIN8);
6544 			}
6545 		}
6546 
6547 		if (CiGetNextRecommendedVLanName(cm->Client, default_name, sizeof(default_name)))
6548 		{
6549 			// Show a default virtual LAN card name candidate
6550 			SetTextA(hWnd, E_NAME, default_name);
6551 		}
6552 
6553 		CmNewVLanDlgUpdate(hWnd);
6554 		break;
6555 
6556 	case WM_COMMAND:
6557 		switch (wParam)
6558 		{
6559 		case IDOK:
6560 			if (cm->Client->Win9x)
6561 			{
6562 				// For Windows 9x, show a confirmation message
6563 				if (MsgBox(hWnd, MB_ICONQUESTION | MB_OKCANCEL, _UU("CM_9X_VLAN_INSTALL")) == IDCANCEL)
6564 				{
6565 					break;
6566 				}
6567 			}
6568 			GetTxtA(hWnd, E_NAME, tmp, (cm->Client->Win9x ? MAX_DEVICE_NAME_LEN_9X : MAX_DEVICE_NAME_LEN) + 1);
6569 			Trim(tmp);
6570 
6571 			if (CcGetClientVersion(cm->Client, &ver) == ERR_NO_ERROR)
6572 			{
6573 				if (ver.IsVLanNameRegulated)
6574 				{
6575 					if (CiIsValidVLanRegulatedName(tmp) == false)
6576 					{
6577 						// Virtual LAN card name isn't meeting the format
6578 						MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("D_CM_NEW_VLAN@S_WIN8"));
6579 
6580 						FocusEx(hWnd, E_NAME);
6581 						break;
6582 					}
6583 				}
6584 			}
6585 
6586 			EndDialog(hWnd, true);
6587 			break;
6588 		case IDCANCEL:
6589 			Close(hWnd);
6590 			break;
6591 		}
6592 		switch (LOWORD(wParam))
6593 		{
6594 		case E_NAME:
6595 			CmNewVLanDlgUpdate(hWnd);
6596 			break;
6597 
6598 		case R_USE_DISCONNECT:
6599 			if (IsChecked(hWnd, R_USE_DISCONNECT))
6600 			{
6601 				FocusEx(hWnd, E_DISCONNECT_SPAN);
6602 			}
6603 			break;
6604 		}
6605 		break;
6606 
6607 	case WM_CLOSE:
6608 		EndDialog(hWnd, false);
6609 		break;
6610 	}
6611 
6612 	return 0;
6613 }
6614 
6615 // Dialog to determine the new virtual LAN card name
CmNewVLanDlg(HWND hWnd)6616 char *CmNewVLanDlg(HWND hWnd)
6617 {
6618 	char tmp[MAX_DEVICE_NAME_LEN + 1];
6619 
6620 	if (Dialog(hWnd, D_CM_NEW_VLAN, CmNewVLanDlgProc, tmp) == false)
6621 	{
6622 		return NULL;
6623 	}
6624 
6625 	return CopyStr(tmp);
6626 }
6627 
6628 // Update the advanced settings dialog
CmDetailDlgUpdate(HWND hWnd,CM_ACCOUNT * a)6629 void CmDetailDlgUpdate(HWND hWnd, CM_ACCOUNT *a)
6630 {
6631 	bool ok = true;
6632 	bool locked;
6633 	// Validate arguments
6634 	if (hWnd == NULL || a == NULL)
6635 	{
6636 		return;
6637 	}
6638 
6639 	locked = a->LockMode;
6640 
6641 	if (a->LinkMode || a->NatMode)
6642 	{
6643 		Disable(hWnd, R_NO_ROUTING);
6644 	}
6645 	else
6646 	{
6647 		if (cm->Client->Unix)
6648 		{
6649 			Disable(hWnd, R_NO_ROUTING);
6650 		}
6651 	}
6652 
6653 	SetEnable(hWnd, E_DISCONNECT_SPAN, IsChecked(hWnd, R_USE_DISCONNECT));
6654 
6655 	SetEnable(hWnd, IDOK, ok);
6656 
6657 	if (locked)
6658 	{
6659 		Disable(hWnd, C_NUM_TCP);
6660 		Disable(hWnd, S_STATIC5);
6661 		Disable(hWnd, S_STATIC8);
6662 		Disable(hWnd, E_INTERVAL);
6663 		Disable(hWnd, S_STATIC9);
6664 		Disable(hWnd, E_DISCONNECT_SPAN);
6665 		Disable(hWnd, S_STATIC10);
6666 		Disable(hWnd, S_STATIC11);
6667 		Disable(hWnd, R_USE_DISCONNECT);
6668 		Disable(hWnd, R_USE_HALF_CONNECTION);
6669 		Disable(hWnd, R_DISABLE_QOS);
6670 		Disable(hWnd, R_USE_ENCRYPT);
6671 		Disable(hWnd, R_USE_COMPRESS);
6672 		Disable(hWnd, R_BRIDGE);
6673 		Disable(hWnd, R_MONITOR);
6674 		Disable(hWnd, R_NO_ROUTING);
6675 	}
6676 }
6677 
6678 // Advanced Settings dialog procedure
CmDetailDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)6679 UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
6680 {
6681 	CM_ACCOUNT *a = (CM_ACCOUNT *)param;
6682 	UINT i;
6683 	UINT num;
6684 	wchar_t tmp[MAX_SIZE];
6685 	// Validate arguments
6686 	if (hWnd == NULL)
6687 	{
6688 		return 0;
6689 	}
6690 
6691 	switch (msg)
6692 	{
6693 	case WM_INITDIALOG:
6694 		// Number of TCP connections
6695 		for (i = 1;i <= MAX_TCP_CONNECTION;i++)
6696 		{
6697 			UniFormat(tmp, sizeof(tmp), L"%u", i);
6698 			CbAddStr(hWnd, C_NUM_TCP, tmp, i);
6699 		}
6700 		CbSelect(hWnd, C_NUM_TCP, a->ClientOption->MaxConnection);
6701 
6702 		// Connection establishment interval
6703 		SetInt(hWnd, E_INTERVAL, a->ClientOption->AdditionalConnectionInterval);
6704 
6705 		// Lifetime
6706 		SetIntEx(hWnd, E_DISCONNECT_SPAN, a->ClientOption->ConnectionDisconnectSpan);
6707 		Check(hWnd, R_USE_DISCONNECT, a->ClientOption->ConnectionDisconnectSpan != 0);
6708 		Check(hWnd, R_USE_HALF_CONNECTION, a->ClientOption->HalfConnection);
6709 		Check(hWnd, R_USE_ENCRYPT, a->ClientOption->UseEncrypt);
6710 		Check(hWnd, R_USE_COMPRESS, a->ClientOption->UseCompress);
6711 		Check(hWnd, R_NO_ROUTING, a->ClientOption->NoRoutingTracking);
6712 		Check(hWnd, R_DISABLE_QOS, a->ClientOption->DisableQoS);
6713 		Check(hWnd, R_DISABLE_UDP, a->ClientOption->NoUdpAcceleration);
6714 
6715 		// Select the Connection Mode
6716 		if (a->LinkMode == false)
6717 		{
6718 			Check(hWnd, R_BRIDGE, a->ClientOption->RequireBridgeRoutingMode);
6719 			Check(hWnd, R_MONITOR, a->ClientOption->RequireMonitorMode);
6720 		}
6721 		else
6722 		{
6723 			Check(hWnd, R_BRIDGE, true);
6724 			Check(hWnd, R_MONITOR, false);
6725 
6726 			SetText(hWnd, S_MODE, _UU("CM_DETAIL_MODE_LINK_STR"));
6727 			Disable(hWnd, R_BRIDGE);
6728 			Disable(hWnd, R_MONITOR);
6729 		}
6730 
6731 		CmDetailDlgUpdate(hWnd, a);
6732 		Focus(hWnd, IDOK);
6733 		break;
6734 	case WM_COMMAND:
6735 		switch (wParam)
6736 		{
6737 		case IDOK:
6738 			if (IsChecked(hWnd, R_USE_DISCONNECT) && GetInt(hWnd, E_DISCONNECT_SPAN) == 0)
6739 			{
6740 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_NO_DISCONNECT_SPAN"));
6741 				FocusEx(hWnd, E_DISCONNECT_SPAN);
6742 				break;
6743 			}
6744 			num = GetInt(hWnd, C_NUM_TCP);
6745 			if (num == 0)
6746 			{
6747 				break;
6748 			}
6749 			if (num == 1 && IsChecked(hWnd, R_USE_HALF_CONNECTION))
6750 			{
6751 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_HALF_MSG"));
6752 				Focus(hWnd, C_NUM_TCP);
6753 				break;
6754 			}
6755 			if (GetInt(hWnd, E_INTERVAL) < 1)
6756 			{
6757 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_TOO_SMALL_INTERVAL"));
6758 				Focus(hWnd, E_INTERVAL);
6759 				break;
6760 			}
6761 
6762 			a->ClientOption->MaxConnection = num;
6763 			a->ClientOption->AdditionalConnectionInterval = GetInt(hWnd, E_INTERVAL);
6764 			if (IsChecked(hWnd, R_USE_DISCONNECT) == false)
6765 			{
6766 				a->ClientOption->ConnectionDisconnectSpan = 0;
6767 			}
6768 			else
6769 			{
6770 				a->ClientOption->ConnectionDisconnectSpan = GetInt(hWnd, E_DISCONNECT_SPAN);
6771 			}
6772 			a->ClientOption->HalfConnection = IsChecked(hWnd, R_USE_HALF_CONNECTION);
6773 			a->ClientOption->UseEncrypt = IsChecked(hWnd, R_USE_ENCRYPT);
6774 			a->ClientOption->UseCompress = IsChecked(hWnd, R_USE_COMPRESS);
6775 			a->ClientOption->NoRoutingTracking = IsChecked(hWnd, R_NO_ROUTING);
6776 			a->ClientOption->DisableQoS = IsChecked(hWnd, R_DISABLE_QOS);
6777 			a->ClientOption->NoUdpAcceleration = IsChecked(hWnd, R_DISABLE_UDP);
6778 
6779 			if (a->LinkMode)
6780 			{
6781 				a->ClientOption->RequireBridgeRoutingMode = true;
6782 				a->ClientOption->RequireMonitorMode = false;
6783 			}
6784 			else
6785 			{
6786 				a->ClientOption->RequireBridgeRoutingMode = IsChecked(hWnd, R_BRIDGE);
6787 				a->ClientOption->RequireMonitorMode = IsChecked(hWnd, R_MONITOR);
6788 			}
6789 
6790 			EndDialog(hWnd, true);
6791 
6792 			break;
6793 		case IDCANCEL:
6794 			Close(hWnd);
6795 			break;
6796 		}
6797 		switch (LOWORD(wParam))
6798 		{
6799 		case C_NUM_TCP:
6800 		case E_INTERVAL:
6801 		case E_DISCONNECT_SPAN:
6802 		case R_USE_DISCONNECT:
6803 		case R_USE_HALF_CONNECTION:
6804 			CmDetailDlgUpdate(hWnd, a);
6805 			break;
6806 		}
6807 		switch (wParam)
6808 		{
6809 		case R_USE_DISCONNECT:
6810 			if (IsChecked(hWnd, R_USE_DISCONNECT))
6811 			{
6812 				FocusEx(hWnd, E_DISCONNECT_SPAN);
6813 			}
6814 			break;
6815 		}
6816 		break;
6817 	case WM_CLOSE:
6818 		EndDialog(hWnd, false);
6819 		break;
6820 	}
6821 
6822 	return 0;
6823 }
6824 
6825 // Advanced Settings dialog
CmDetailDlg(HWND hWnd,CM_ACCOUNT * a)6826 bool CmDetailDlg(HWND hWnd, CM_ACCOUNT *a)
6827 {
6828 	// Validate arguments
6829 	if (hWnd == NULL || a == NULL)
6830 	{
6831 		return false;
6832 	}
6833 
6834 	return Dialog(hWnd, D_CM_DETAIL, CmDetailDlgProc, a);
6835 }
6836 
6837 // Update the account editing dialog procedure
CmEditAccountDlgUpdate(HWND hWnd,CM_ACCOUNT * a)6838 void CmEditAccountDlgUpdate(HWND hWnd, CM_ACCOUNT *a)
6839 {
6840 	bool ok = true;
6841 	char str[MAX_SIZE];
6842 	bool locked;
6843 	// Validate arguments
6844 	if (hWnd == NULL || a == NULL)
6845 	{
6846 		return;
6847 	}
6848 
6849 	locked = a->LockMode;
6850 
6851 	if (a->Inited == false)
6852 	{
6853 		return;
6854 	}
6855 
6856 	if (a->EditMode)
6857 	{
6858 		Disable(hWnd, E_ACCOUNT_NAME);
6859 	}
6860 
6861 	// The name of connection settings
6862 	GetTxt(hWnd, E_ACCOUNT_NAME, a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName));
6863 	UniTrim(a->ClientOption->AccountName);
6864 
6865 	// Host name
6866 	GetTxtA(hWnd, E_HOSTNAME, a->ClientOption->Hostname, sizeof(a->ClientOption->Hostname));
6867 	Trim(a->ClientOption->Hostname);
6868 
6869 	if (InStr(a->ClientOption->Hostname, "/tcp"))
6870 	{
6871 		Check(hWnd, R_DISABLE_NATT, true);
6872 	}
6873 	else
6874 	{
6875 		Check(hWnd, R_DISABLE_NATT, false);
6876 	}
6877 
6878 	SetEnable(hWnd, R_DISABLE_NATT, !IsEmptyStr(a->ClientOption->Hostname));
6879 
6880 	// Port number
6881 	a->ClientOption->Port = GetInt(hWnd, C_PORT);
6882 
6883 	// HUB name
6884 	GetTxtA(hWnd,C_HUBNAME, a->ClientOption->HubName, sizeof(a->ClientOption->HubName));
6885 
6886 	// Type of proxy
6887 	a->ClientOption->ProxyType = PROXY_DIRECT;
6888 	if (IsChecked(hWnd, R_HTTPS))
6889 	{
6890 		a->ClientOption->ProxyType = PROXY_HTTP;
6891 	}
6892 	if (IsChecked(hWnd, R_SOCKS))
6893 	{
6894 		a->ClientOption->ProxyType = PROXY_SOCKS;
6895 	}
6896 
6897 	// To validate the server certificate
6898 	a->CheckServerCert = IsChecked(hWnd, R_CHECK_CERT);
6899 
6900 	if (a->NatMode)
6901 	{
6902 		Disable(hWnd, R_CHECK_CERT);
6903 		Disable(hWnd, B_TRUST);
6904 	}
6905 
6906 	if (a->HideTrustCert)
6907 	{
6908 		Disable(hWnd, B_TRUST);
6909 	}
6910 
6911 	// Device name
6912 	StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), "");
6913 	if (LvIsSelected(hWnd, L_VLAN))
6914 	{
6915 		wchar_t *s = LvGetStr(hWnd, L_VLAN, LvGetSelected(hWnd, L_VLAN), 0);
6916 		if (s != NULL)
6917 		{
6918 			char str[MAX_SIZE];
6919 			UniToStr(str, sizeof(str), s);
6920 			CmPrintNameToVLanName(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), str);
6921 			Free(s);
6922 		}
6923 	}
6924 
6925 	// User authentication
6926 	a->ClientAuth->AuthType = CbGetSelect(hWnd, C_TYPE);
6927 	GetTxtA(hWnd, E_USERNAME, a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
6928 	Trim(a->ClientAuth->Username);
6929 	switch (a->ClientAuth->AuthType)
6930 	{
6931 	case CLIENT_AUTHTYPE_PASSWORD:
6932 		// Password authentication
6933 		GetTxtA(hWnd, E_PASSWORD, str, sizeof(str));
6934 		if (StrCmp(str, HIDDEN_PASSWORD) != 0)
6935 		{
6936 			HashPassword(a->ClientAuth->HashedPassword, a->ClientAuth->Username, str);
6937 		}
6938 		break;
6939 	case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
6940 		// Plaintext password authentication
6941 		GetTxtA(hWnd, E_PASSWORD, str, sizeof(str));
6942 		if (StrCmp(str, HIDDEN_PASSWORD) != 0)
6943 		{
6944 			StrCpy(a->ClientAuth->PlainPassword, sizeof(a->ClientAuth->PlainPassword), str);
6945 		}
6946 		break;
6947 	}
6948 
6949 	// Reconnection option
6950 	if ((a->LinkMode || a->NatMode) || a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
6951 	{
6952 		Disable(hWnd, R_RETRY);
6953 	}
6954 	else
6955 	{
6956 		Enable(hWnd, R_RETRY);
6957 	}
6958 
6959 	if (IsChecked(hWnd, R_RETRY) == false)
6960 	{
6961 		a->ClientOption->NumRetry = 0;
6962 	}
6963 	else
6964 	{
6965 		if (IsChecked(hWnd, R_INFINITE))
6966 		{
6967 			a->ClientOption->NumRetry = INFINITE;
6968 		}
6969 		else
6970 		{
6971 			a->ClientOption->NumRetry = GetInt(hWnd, E_RETRY_NUM);
6972 		}
6973 	}
6974 	a->ClientOption->RetryInterval = GetInt(hWnd, E_RETRY_SPAN);
6975 
6976 	a->ClientOption->NoTls1 = IsChecked(hWnd, R_NOTLS1);
6977 
6978 	// Information determining
6979 	if (UniStrLen(a->ClientOption->AccountName) == 0 && a->NatMode == false)
6980 	{
6981 		ok = false;
6982 	}
6983 	if (StrLen(a->ClientOption->Hostname) == 0)
6984 	{
6985 		ok = false;
6986 	}
6987 	if (a->ClientOption->Port == 0 || a->ClientOption->Port >= 65536)
6988 	{
6989 		ok = false;
6990 	}
6991 	if (StrLen(a->ClientOption->HubName) == 0)
6992 	{
6993 		ok = false;
6994 	}
6995 	if (StrLen(a->ClientAuth->Username) == 0)
6996 	{
6997 		ok = false;
6998 	}
6999 	if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
7000 	{
7001 		if (a->ClientAuth->ClientK == NULL || a->ClientAuth->ClientX == NULL)
7002 		{
7003 			ok = false;
7004 		}
7005 	}
7006 	if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
7007 	{
7008 		if (IsEmptyStr(a->ClientAuth->SecurePrivateKeyName) || IsEmptyStr(a->ClientAuth->SecurePublicCertName))
7009 		{
7010 			ok = false;
7011 		}
7012 	}
7013 
7014 	// Display update
7015 	if (IsChecked(hWnd, R_RETRY) && IsEnable(hWnd, R_RETRY))
7016 	{
7017 		if (a->LinkMode == false && a->NatMode == false)
7018 		{
7019 			Enable(hWnd, R_INFINITE);
7020 			Enable(hWnd, E_RETRY_SPAN);
7021 			Enable(hWnd, S_RETRY_SPAN_1);
7022 			Enable(hWnd, S_RETRY_SPAN_2);
7023 		}
7024 		else
7025 		{
7026 			Disable(hWnd, R_INFINITE);
7027 			Disable(hWnd, E_RETRY_SPAN);
7028 			Disable(hWnd, S_RETRY_SPAN_1);
7029 			Disable(hWnd, S_RETRY_SPAN_2);
7030 		}
7031 		if (IsChecked(hWnd, R_INFINITE) == false)
7032 		{
7033 			Enable(hWnd, E_RETRY_NUM);
7034 			Enable(hWnd, S_RETRY_NUM_1);
7035 			Enable(hWnd, S_RETRY_NUM_2);
7036 			if (GetInt(hWnd, E_RETRY_NUM) == 0)
7037 			{
7038 				ok = false;
7039 			}
7040 		}
7041 		else
7042 		{
7043 			Disable(hWnd, E_RETRY_NUM);
7044 			Disable(hWnd, S_RETRY_NUM_1);
7045 			Disable(hWnd, S_RETRY_NUM_2);
7046 		}
7047 	}
7048 	else
7049 	{
7050 		Disable(hWnd, E_RETRY_NUM);
7051 		Disable(hWnd, E_RETRY_SPAN);
7052 		Disable(hWnd, R_INFINITE);
7053 		Disable(hWnd, S_RETRY_NUM_1);
7054 		Disable(hWnd, S_RETRY_NUM_2);
7055 		Disable(hWnd, S_RETRY_SPAN_1);
7056 		Disable(hWnd, S_RETRY_SPAN_2);
7057 	}
7058 
7059 	if (a->NatMode == false)
7060 	{
7061 		if (a->ServerCert == NULL)
7062 		{
7063 			SetText(hWnd, B_SERVER_CERT, _UU("CM_SERVER_CERT_1"));
7064 			Disable(hWnd, B_VIEW_SERVER_CERT);
7065 		}
7066 		else
7067 		{
7068 			SetText(hWnd, B_SERVER_CERT, _UU("CM_SERVER_CERT_2"));
7069 			Enable(hWnd, B_VIEW_SERVER_CERT);
7070 		}
7071 	}
7072 	else
7073 	{
7074 		Disable(hWnd, B_VIEW_SERVER_CERT);
7075 		Disable(hWnd, B_SERVER_CERT);
7076 	}
7077 
7078 	if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT || a->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
7079 	{
7080 		wchar_t tmp[MAX_SIZE * 2];
7081 		wchar_t issuer[MAX_SIZE];
7082 		wchar_t subject[MAX_SIZE];
7083 		wchar_t expires[MAX_SIZE];
7084 
7085 		SetIcon(hWnd, S_CERT, (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT) ? ICO_CERT : ICO_SECURE);
7086 
7087 		Hide(hWnd, S_PASSWORD);
7088 		Hide(hWnd, E_PASSWORD);
7089 		if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
7090 		{
7091 			if (a->ClientAuth->ClientX != NULL)
7092 			{
7093 				Enable(hWnd, B_VIEW_CLIENT_CERT);
7094 				SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_CLIENT_CERT_2"));
7095 				GetPrintNameFromName(issuer, sizeof(issuer), a->ClientAuth->ClientX->issuer_name);
7096 				GetPrintNameFromName(subject, sizeof(subject), a->ClientAuth->ClientX->subject_name);
7097 				GetDateStrEx64(expires, sizeof(expires), SystemToLocal64(a->ClientAuth->ClientX->notAfter), NULL);
7098 				UniFormat(tmp, sizeof(tmp), _UU("CM_CERT_INFO"), subject, issuer, expires);
7099 			}
7100 			else
7101 			{
7102 				Disable(hWnd, B_VIEW_CLIENT_CERT);
7103 				SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_CLIENT_CERT_1"));
7104 				UniStrCpy(tmp, sizeof(tmp), _UU("CM_NO_CERT"));
7105 			}
7106 			SetText(hWnd, B_VIEW_CLIENT_CERT, _UU("CM_VIEW_CLIENT_CERT"));
7107 
7108 			Enable(hWnd, B_REGIST_CLIENT_CERT);
7109 		}
7110 		else
7111 		{
7112 			if (IsEmptyStr(a->ClientAuth->SecurePrivateKeyName) || IsEmptyStr(a->ClientAuth->SecurePublicCertName))
7113 			{
7114 				UniStrCpy(tmp, sizeof(tmp), _UU("CM_NO_SECURE"));
7115 			}
7116 			else
7117 			{
7118 				UniFormat(tmp, sizeof(tmp), _UU("CM_CERT_SECURE_INFO"),
7119 					a->ClientAuth->SecurePublicCertName, a->ClientAuth->SecurePrivateKeyName);
7120 			}
7121 
7122 			SetText(hWnd, B_VIEW_CLIENT_CERT, _UU("CM_SELECT_SECURE_DEVICE"));
7123 			SetText(hWnd, B_REGIST_CLIENT_CERT, _UU("CM_SELECT_CERT_INCARD"));
7124 			Enable(hWnd, B_VIEW_CLIENT_CERT);
7125 
7126 			if (SmGetCurrentSecureIdFromReg() == 0)
7127 			{
7128 				Disable(hWnd, B_REGIST_CLIENT_CERT);
7129 			}
7130 			else
7131 			{
7132 				Enable(hWnd, B_REGIST_CLIENT_CERT);
7133 			}
7134 		}
7135 		SetText(hWnd, S_CERT_INFO, tmp);
7136 		Show(hWnd, S_CERT);
7137 		Show(hWnd, S_CERT_INFO);
7138 		Show(hWnd, B_VIEW_CLIENT_CERT);
7139 		Show(hWnd, B_REGIST_CLIENT_CERT);
7140 	}
7141 	else
7142 	{
7143 		if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_ANONYMOUS)
7144 		{
7145 			Hide(hWnd, S_PASSWORD);
7146 			Hide(hWnd, E_PASSWORD);
7147 		}
7148 		else
7149 		{
7150 			Show(hWnd, S_PASSWORD);
7151 			Show(hWnd, E_PASSWORD);
7152 		}
7153 		Hide(hWnd, S_CERT);
7154 		Hide(hWnd, S_CERT_INFO);
7155 		Hide(hWnd, B_VIEW_CLIENT_CERT);
7156 		Hide(hWnd, B_REGIST_CLIENT_CERT);
7157 	}
7158 
7159 	if (a->ClientOption->ProxyType != PROXY_DIRECT)
7160 	{
7161 		Enable(hWnd, B_PROXY_CONFIG);
7162 		if (StrLen(a->ClientOption->ProxyName) == 0)
7163 		{
7164 			ok = false;
7165 		}
7166 		if (a->ClientOption->ProxyPort == 0)
7167 		{
7168 			ok = false;
7169 		}
7170 	}
7171 	else
7172 	{
7173 		Disable(hWnd, B_PROXY_CONFIG);
7174 	}
7175 
7176 	if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
7177 	{
7178 		bool b = true;
7179 
7180 		if (ok == false)
7181 		{
7182 			b = false;
7183 		}
7184 
7185 		if (a->LinkMode == false && a->NatMode == false)
7186 		{
7187 			SetEnable(hWnd, B_CHANGE_PASSWORD, b);
7188 			SetEnable(hWnd, S_CHANGE_PASSWORD, b);
7189 			Show(hWnd, B_CHANGE_PASSWORD);
7190 			Show(hWnd, S_CHANGE_PASSWORD);
7191 		}
7192 		else
7193 		{
7194 			Hide(hWnd, B_CHANGE_PASSWORD);
7195 			Hide(hWnd, S_CHANGE_PASSWORD);
7196 		}
7197 	}
7198 	else
7199 	{
7200 		Hide(hWnd, B_CHANGE_PASSWORD);
7201 		Hide(hWnd, S_CHANGE_PASSWORD);
7202 	}
7203 
7204 	if ((StrLen(a->ClientOption->DeviceName) == 0) && (a->LinkMode == false && a->NatMode == false))
7205 	{
7206 		ok = false;
7207 	}
7208 
7209 	if (a->LinkMode || a->NatMode)
7210 	{
7211 		Disable(hWnd, L_VLAN);
7212 	}
7213 
7214 	if (a->EditMode == false)
7215 	{
7216 		char tmp[MAX_SIZE];
7217 		GetTxtA(hWnd, E_HOSTNAME, tmp, sizeof(tmp));
7218 		Trim(tmp);
7219 
7220 		if (StartWith(tmp, "127.") || (StrCmpi(tmp, "localhost") == 0))
7221 		{
7222 			if (a->Flag1 == false)
7223 			{
7224 				a->Flag1 = true;
7225 				a->ClientOption->UseEncrypt = a->ClientOption->UseCompress = false;
7226 				a->ClientOption->MaxConnection = 1;
7227 			}
7228 		}
7229 	}
7230 
7231 	a->ClientOption->HideStatusWindow = IsChecked(hWnd, R_HIDE);
7232 	a->ClientOption->HideNicInfoWindow = IsChecked(hWnd, R_HIDE2);
7233 
7234 	if (locked)
7235 	{
7236 		SetEnable(hWnd, E_HOSTNAME, false);
7237 		SetEnable(hWnd, C_PORT, false);
7238 		SetEnable(hWnd, C_HUBNAME, false);
7239 		SetEnable(hWnd, S_STATIC2, false);
7240 		SetEnable(hWnd, S_STATIC3, false);
7241 		SetEnable(hWnd, S_STATIC4, false);
7242 		SetEnable(hWnd, S_STATIC5, false);
7243 		SetEnable(hWnd, S_STATIC66, false);
7244 		SetEnable(hWnd, S_STATIC7, false);
7245 		SetEnable(hWnd, S_STATIC11, false);
7246 		SetEnable(hWnd, R_CHECK_CERT, false);
7247 		SetEnable(hWnd, B_TRUST, false);
7248 		SetEnable(hWnd, B_SERVER_CERT, false);
7249 		SetEnable(hWnd, B_VIEW_SERVER_CERT, false);
7250 		SetEnable(hWnd, R_RETRY, false);
7251 		SetEnable(hWnd, S_RETRY_NUM_1, false);
7252 		SetEnable(hWnd, E_RETRY_NUM, false);
7253 		SetEnable(hWnd, S_RETRY_NUM_2, false);
7254 		SetEnable(hWnd, S_RETRY_SPAN_1, false);
7255 		SetEnable(hWnd, E_RETRY_SPAN, false);
7256 		SetEnable(hWnd, S_RETRY_SPAN_2, false);
7257 		SetEnable(hWnd, R_INFINITE, false);
7258 	}
7259 
7260 	SetEnable(hWnd, IDOK, ok);
7261 }
7262 
7263 // Initialize the account editing dialog
CmEditAccountDlgInit(HWND hWnd,CM_ACCOUNT * a)7264 void CmEditAccountDlgInit(HWND hWnd, CM_ACCOUNT *a)
7265 {
7266 	RPC_CLIENT_ENUM_VLAN v;
7267 	UINT i;
7268 	// Validate arguments
7269 	if (hWnd == NULL || a == NULL)
7270 	{
7271 		return;
7272 	}
7273 
7274 	if (a->LockMode)
7275 	{
7276 		SetText(hWnd, S_STATIC1, _UU("CM_EASY_ACCOUNT_WARNING"));
7277 	}
7278 
7279 	// Connection settings name
7280 	if (a->EditMode || a->NatMode)
7281 	{
7282 		Disable(hWnd, E_ACCOUNT_NAME);
7283 	}
7284 
7285 	if (a->NatMode || a->LinkMode)
7286 	{
7287 		Hide(hWnd, R_HIDE);
7288 		Hide(hWnd, R_HIDE2);
7289 	}
7290 
7291 	Check(hWnd, R_HIDE, a->ClientOption->HideStatusWindow);
7292 	Check(hWnd, R_HIDE2, a->ClientOption->HideNicInfoWindow);
7293 
7294 	if (a->NatMode)
7295 	{
7296 		Hide(hWnd, E_ACCOUNT_NAME);
7297 		Hide(hWnd, S_ACCOUNT_NAME);
7298 	}
7299 
7300 	if ((cm != NULL && cm->server_name != NULL) || a->LinkMode)
7301 	{
7302 		Hide(hWnd, B_IE);
7303 	}
7304 
7305 	SetText(hWnd, E_ACCOUNT_NAME, a->ClientOption->AccountName);
7306 
7307 	// Host name
7308 	SetTextA(hWnd, E_HOSTNAME, a->ClientOption->Hostname);
7309 	StrCpy(a->old_server_name, sizeof(a->old_server_name), a->ClientOption->Hostname);
7310 
7311 	if (InStr(a->ClientOption->Hostname, "/tcp"))
7312 	{
7313 		Check(hWnd, R_DISABLE_NATT, true);
7314 	}
7315 	else
7316 	{
7317 		Check(hWnd, R_DISABLE_NATT, false);
7318 	}
7319 
7320 	// Port number
7321 	CbSetHeight(hWnd, C_PORT, 18);
7322 	CbAddStr(hWnd, C_PORT, _UU("CM_PORT_1"), 0);
7323 	CbAddStr(hWnd, C_PORT, _UU("CM_PORT_2"), 0);
7324 	CbAddStr(hWnd, C_PORT, _UU("CM_PORT_3"), 0);
7325 	CbAddStr(hWnd, C_PORT, _UU("CM_PORT_4"), 0);
7326 	SetInt(hWnd, C_PORT, a->ClientOption->Port);
7327 
7328 	// Virtual HUB name
7329 	CbSetHeight(hWnd, C_HUBNAME, 18);
7330 	SetTextA(hWnd, C_HUBNAME, a->ClientOption->HubName);
7331 
7332 	// Type of proxy
7333 	Check(hWnd, R_DIRECT_TCP, a->ClientOption->ProxyType == PROXY_DIRECT);
7334 	Check(hWnd, R_HTTPS, a->ClientOption->ProxyType == PROXY_HTTP);
7335 	Check(hWnd, R_SOCKS, a->ClientOption->ProxyType == PROXY_SOCKS);
7336 
7337 	// Verify the server certificate
7338 	Check(hWnd, R_CHECK_CERT, a->CheckServerCert);
7339 
7340 	// LAN card list
7341 	if (a->NatMode == false && a->LinkMode == false)
7342 	{
7343 		Zero(&v, sizeof(v));
7344 		CcEnumVLan(cm->Client, &v);
7345 		LvInit(hWnd, L_VLAN);
7346 		LvInsertColumn(hWnd, L_VLAN, 0, L"DeviceName", 345);
7347 		for (i = 0;i < v.NumItem;i++)
7348 		{
7349 			wchar_t tmp[MAX_SIZE];
7350 			char str[MAX_SIZE];
7351 			CmVLanNameToPrintName(str, sizeof(str), v.Items[i]->DeviceName);
7352 			StrToUni(tmp, sizeof(tmp), str);
7353 			LvInsert(hWnd, L_VLAN, ICO_NIC_ONLINE, NULL, 1, tmp);
7354 		}
7355 //		LvAutoSize(hWnd, L_VLAN);
7356 
7357 		if (v.NumItem == 1)
7358 		{
7359 			// If only one virtual LAN card exists, initially select it
7360 			LvSelect(hWnd, L_VLAN, 0);
7361 		}
7362 
7363 		CiFreeClientEnumVLan(&v);
7364 	}
7365 
7366 	// Select the LAN card
7367 	if (StrLen(a->ClientOption->DeviceName) != 0)
7368 	{
7369 		char str[MAX_SIZE];
7370 		wchar_t tmp[MAX_SIZE];
7371 		UINT index;
7372 		CmVLanNameToPrintName(str, sizeof(str), a->ClientOption->DeviceName);
7373 		StrToUni(tmp, sizeof(tmp), str);
7374 		index = LvSearchStr(hWnd, L_VLAN, 0, tmp);
7375 		if (index != INFINITE)
7376 		{
7377 			LvSelect(hWnd, L_VLAN, index);
7378 		}
7379 	}
7380 
7381 	// Authentication type
7382 	CbSetHeight(hWnd, C_TYPE, 18);
7383 	CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_0"), CLIENT_AUTHTYPE_ANONYMOUS);
7384 	CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);
7385 	CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);
7386 
7387 	if (a->HideClientCertAuth == false)
7388 	{
7389 		// Certificate authentication is not available when HideClientCertAuth is true
7390 		CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_3"), CLIENT_AUTHTYPE_CERT);
7391 	}
7392 
7393 	if (a->HideSecureAuth == false)
7394 	{
7395 		// Authentication using a smart card
7396 		CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_4"), CLIENT_AUTHTYPE_SECURE);
7397 	}
7398 
7399 	// Select an authentication
7400 	CbSelect(hWnd, C_TYPE, a->ClientAuth->AuthType);
7401 
7402 	// User name
7403 	SetTextA(hWnd, E_USERNAME, a->ClientAuth->Username);
7404 
7405 	// Password
7406 	if (a->EditMode)
7407 	{
7408 		SetTextA(hWnd, E_PASSWORD, HIDDEN_PASSWORD);
7409 	}
7410 
7411 	// Reconnection times
7412 	if (a->ClientOption->NumRetry == 0)
7413 	{
7414 		Check(hWnd, R_RETRY, false);
7415 	}
7416 	else
7417 	{
7418 		Check(hWnd, R_RETRY, true);
7419 		if (a->ClientOption->NumRetry == INFINITE)
7420 		{
7421 			Check(hWnd, R_INFINITE, true);
7422 		}
7423 		else
7424 		{
7425 			Check(hWnd, R_INFINITE, false);
7426 			SetInt(hWnd, E_RETRY_NUM, a->ClientOption->NumRetry);
7427 		}
7428 	}
7429 	SetIntEx(hWnd, E_RETRY_SPAN, a->ClientOption->RetryInterval);
7430 
7431 	Check(hWnd, R_NOTLS1, a->ClientOption->NoTls1);
7432 
7433 	// Title
7434 	if (a->NatMode == false)
7435 	{
7436 		if (a->EditMode == false)
7437 		{
7438 			SetText(hWnd, 0, _UU("CM_ACCOUNT_TITLE_1"));
7439 			FocusEx(hWnd, E_ACCOUNT_NAME);
7440 		}
7441 		else
7442 		{
7443 			SetText(hWnd, 0, _UU("CM_ACCOUNT_TITLE_2"));
7444 			FormatText(hWnd, 0, a->ClientOption->AccountName);
7445 			FocusEx(hWnd, E_HOSTNAME);
7446 		}
7447 	}
7448 	else
7449 	{
7450 		SetText(hWnd, 0, _UU("NM_ACCOUNT_TITLE"));
7451 		FocusEx(hWnd, E_HOSTNAME);
7452 	}
7453 
7454 	if (a->LinkMode || a->NatMode)
7455 	{
7456 		Hide(hWnd, L_VLAN);
7457 
7458 		if (a->NatMode == false)
7459 		{
7460 			SetText(hWnd, S_VLAN_GROUP, _UU("SM_LINK_POLICY_GROUP"));
7461 			Show(hWnd, S_POLICY_1);
7462 			Show(hWnd, S_POLICY_2);
7463 			Show(hWnd, B_POLICY);
7464 		}
7465 		else
7466 		{
7467 			Hide(hWnd, S_VLAN_GROUP);
7468 			Show(hWnd, S_ROUTER_LOGO);
7469 		}
7470 	}
7471 
7472 	// Display update
7473 	a->Inited = true;
7474 	CmEditAccountDlgUpdate(hWnd, a);
7475 }
7476 
7477 // Account editing dialog procedure
CmEditAccountDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)7478 UINT CmEditAccountDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
7479 {
7480 	CM_ACCOUNT *a = (CM_ACCOUNT *)param;
7481 	NMHDR *n;
7482 	X *x;
7483 	K *k;
7484 	char tmp[MAX_PATH];
7485 	bool no_update_natt_check = false;
7486 	// Validate arguments
7487 	if (hWnd == NULL)
7488 	{
7489 		return 0;
7490 	}
7491 
7492 	switch (msg)
7493 	{
7494 	case WM_INITDIALOG:
7495 		CmEditAccountDlgInit(hWnd, a);
7496 		if (a->EditMode == false && a->LinkMode == false && a->NatMode == false)
7497 		{
7498 			SetTimer(hWnd, 1, 100, NULL);
7499 		}
7500 		break;
7501 	case WM_TIMER:
7502 		switch (wParam)
7503 		{
7504 		case 1:
7505 			{
7506 				CM_INTERNET_SETTING s;
7507 
7508 				KillTimer(hWnd, 1);
7509 
7510 				Zero(&s, sizeof(s));
7511 				CmGetSystemInternetSetting(&s);
7512 
7513 				if (s.ProxyType != PROXY_DIRECT)
7514 				{
7515 					if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO,
7516 						_UU("CM_WOULDYOULOAD_IE_PROXY"),
7517 						s.ProxyHostName) == IDYES)
7518 					{
7519 						Command(hWnd, B_IE);
7520 					}
7521 				}
7522 			}
7523 			break;
7524 		}
7525 		break;
7526 	case WM_COMMAND:
7527 		switch (wParam)
7528 		{
7529 		case R_DISABLE_NATT:
7530 			Zero(tmp, sizeof(tmp));
7531 			GetTxtA(hWnd, E_HOSTNAME, tmp, sizeof(tmp));
7532 
7533 			if (IsChecked(hWnd, R_DISABLE_NATT))
7534 			{
7535 				if (InStr(tmp, "/tcp") == false)
7536 				{
7537 					Trim(tmp);
7538 
7539 					StrCat(tmp, sizeof(tmp), "/tcp");
7540 
7541 					SetTextA(hWnd, E_HOSTNAME, tmp);
7542 				}
7543 			}
7544 			else
7545 			{
7546 				if (InStr(tmp, "/tcp"))
7547 				{
7548 					UINT i = SearchStrEx(tmp, "/tcp", 0, false);
7549 
7550 					if (i != INFINITE)
7551 					{
7552 						tmp[i] = 0;
7553 
7554 						Trim(tmp);
7555 
7556 						SetTextA(hWnd, E_HOSTNAME, tmp);
7557 					}
7558 				}
7559 			}
7560 
7561 			CmEditAccountDlgStartEnumHub(hWnd, a);
7562 			break;
7563 		}
7564 		switch (LOWORD(wParam))
7565 		{
7566 		case E_ACCOUNT_NAME:
7567 		case E_HOSTNAME:
7568 		case C_PORT:
7569 		case C_HUBNAME:
7570 		case R_DIRECT_TCP:
7571 		case R_HTTPS:
7572 		case R_SOCKS:
7573 		case R_CHECK_CERT:
7574 		case C_TYPE:
7575 		case E_USERNAME:
7576 		case E_PASSWORD:
7577 		case R_RETRY:
7578 		case E_RETRY_NUM:
7579 		case E_RETRY_SPAN:
7580 		case R_INFINITE:
7581 			CmEditAccountDlgUpdate(hWnd, a);
7582 			break;
7583 		}
7584 		switch (HIWORD(wParam))
7585 		{
7586 		case EN_KILLFOCUS:
7587 			switch (LOWORD(wParam))
7588 			{
7589 			case E_HOSTNAME:
7590 				CmEditAccountDlgStartEnumHub(hWnd, a);
7591 				break;
7592 			}
7593 			break;
7594 		case BN_KILLFOCUS:
7595 			switch (LOWORD(wParam))
7596 			{
7597 			case R_DIRECT_TCP:
7598 			case R_HTTPS:
7599 			case R_SOCKS:
7600 				CmEditAccountDlgStartEnumHub(hWnd, a);
7601 				break;
7602 			}
7603 			break;
7604 		case CBN_KILLFOCUS:
7605 			switch (LOWORD(wParam))
7606 			{
7607 			case C_PORT:
7608 				CmEditAccountDlgStartEnumHub(hWnd, a);
7609 				break;
7610 			}
7611 			break;
7612 		case BN_PUSHED:
7613 			switch (LOWORD(wParam))
7614 			{
7615 			case R_DISABLE_NATT:
7616 				break;
7617 			}
7618 			break;
7619 		}
7620 		if (HIWORD(wParam) == 0)
7621 		{
7622 			CmEditAccountDlgUpdate(hWnd, a);
7623 		}
7624 		switch (wParam)
7625 		{
7626 		case B_POLICY:
7627 			// Policy
7628 			if (a->LinkMode || a->NatMode)
7629 			{
7630 				a->Policy.Access = true;
7631 				a->Policy.MonitorPort = false;
7632 				SmPolicyDlgEx2(hWnd, &a->Policy, _UU("SM_LINK_POLICY_CAPTION"), true, a->PolicyVer);
7633 				a->Policy.Access = true;
7634 				a->Policy.MonitorPort = false;
7635 			}
7636 			break;
7637 		case IDOK:
7638 			CmEditAccountDlgUpdate(hWnd, a);
7639 			CmEditAccountDlgOnOk(hWnd, a);
7640 			break;
7641 		case IDCANCEL:
7642 			Close(hWnd);
7643 			break;
7644 		case B_PROXY_CONFIG:
7645 			// Proxy Settings
7646 			if (CmProxyDlg(hWnd, a->ClientOption))
7647 			{
7648 				UINT n = GetInt(hWnd, C_PORT);
7649 				if (a->ClientOption->ProxyType == PROXY_HTTP &&
7650 					n != 443)
7651 				{
7652 					// Show a warning message if the destination port is
7653 					// other than 443 and HTTP proxy is used
7654 					if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("CM_HTTP_PROXY_WARNING"), n) == IDYES)
7655 					{
7656 						// Change the port number to 443
7657 						SetText(hWnd, C_PORT, _UU("CM_PORT_2"));
7658 					}
7659 				}
7660 				CmEditAccountDlgStartEnumHub(hWnd, a);
7661 				CmEditAccountDlgUpdate(hWnd, a);
7662 			}
7663 			break;
7664 		case B_IE:
7665 			// Use the IE settings
7666 			if(cm->server_name == NULL)
7667 			{
7668 				CmProxyDlgUseForIE(hWnd, a->ClientOption);
7669 				CmEditAccountDlgUpdate(hWnd, a);
7670 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_PROXY_FROM_IE"));
7671 			}
7672 			break;
7673 		case B_TRUST:
7674 			// CA
7675 			if (a->LinkMode == false)
7676 			{
7677 				CmTrustDlg(hWnd);
7678 			}
7679 			else
7680 			{
7681 				SmCaDlg(hWnd, a->Hub);
7682 			}
7683 			break;
7684 		case B_SERVER_CERT:
7685 			// Server certificate registration / delete
7686 			if (a->ServerCert == NULL)
7687 			{
7688 				if (CmLoadXFromFileOrSecureCard(hWnd, &x))
7689 				{
7690 					a->ServerCert = x;
7691 					CmEditAccountDlgUpdate(hWnd, a);
7692 				}
7693 			}
7694 			else
7695 			{
7696 				if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_SERVER_CERT")) == IDYES)
7697 				{
7698 					FreeX(a->ServerCert);
7699 					a->ServerCert = NULL;
7700 					CmEditAccountDlgUpdate(hWnd, a);
7701 				}
7702 			}
7703 			break;
7704 		case B_VIEW_SERVER_CERT:
7705 			// Show the server certificate
7706 			if (a->ServerCert != NULL)
7707 			{
7708 				X *issuer = CmGetIssuer(a->ServerCert);
7709 				CertDlg(hWnd, a->ServerCert, issuer, true);
7710 				FreeX(issuer);
7711 			}
7712 			break;
7713 		case B_VIEW_CLIENT_CERT:
7714 			if (a->ClientAuth->AuthType != CLIENT_AUTHTYPE_SECURE)
7715 			{
7716 				// Show the client certificate
7717 				if (a->ClientAuth->ClientX != NULL)
7718 				{
7719 					X *issuer = CmGetIssuer(a->ClientAuth->ClientX);
7720 					CertDlg(hWnd, a->ClientAuth->ClientX, issuer, true);
7721 					FreeX(issuer);
7722 				}
7723 			}
7724 			else
7725 			{
7726 				UINT id;
7727 				// Select the type of smart card
7728 				SmSelectSecureId(hWnd);
7729 				id = SmGetCurrentSecureIdFromReg();
7730 				if (id != 0)
7731 				{
7732 					if (cm->server_name == NULL)
7733 					{
7734 						RPC_USE_SECURE t;
7735 
7736 						Zero(&t, sizeof(t));
7737 						t.DeviceId = id;
7738 						CcUseSecure(cm->Client, &t);
7739 					}
7740 				}
7741 				CmEditAccountDlgUpdate(hWnd, a);
7742 			}
7743 			break;
7744 		case B_REGIST_CLIENT_CERT:
7745 			if (a->ClientAuth->AuthType != CLIENT_AUTHTYPE_SECURE)
7746 			{
7747 				// Client certificate registration / deletion
7748 				if (a->ClientAuth->ClientX == NULL)
7749 				{
7750 					if (CmLoadXAndK(hWnd, &x, &k))
7751 					{
7752 						a->ClientAuth->ClientX = x;
7753 						a->ClientAuth->ClientK = k;
7754 						CmEditAccountDlgUpdate(hWnd, a);
7755 					}
7756 				}
7757 				else
7758 				{
7759 					if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_CLIENT_CERT")) == IDYES)
7760 					{
7761 						FreeX(a->ClientAuth->ClientX);
7762 						FreeK(a->ClientAuth->ClientK);
7763 						a->ClientAuth->ClientX = NULL;
7764 						a->ClientAuth->ClientK = NULL;
7765 						CmEditAccountDlgUpdate(hWnd, a);
7766 					}
7767 				}
7768 			}
7769 			else
7770 			{
7771 				char cert[MAX_SECURE_DEVICE_FILE_LEN + 1], priv[MAX_SECURE_DEVICE_FILE_LEN + 1];
7772 
7773 				// Select a certificate in the smart card
7774 				if (SmSelectKeyPairEx(hWnd, cert, sizeof(cert), priv, sizeof(priv), CmGetSecureBitmapId(a->ClientOption->Hostname)))
7775 				{
7776 					StrCpy(a->ClientAuth->SecurePublicCertName, sizeof(a->ClientAuth->SecurePublicCertName), cert);
7777 					StrCpy(a->ClientAuth->SecurePrivateKeyName, sizeof(a->ClientAuth->SecurePrivateKeyName), priv);
7778 					CmEditAccountDlgUpdate(hWnd, a);
7779 				}
7780 			}
7781 			break;
7782 		case B_DETAIL:
7783 			// Advanced communication settings
7784 			if (CmDetailDlg(hWnd, a))
7785 			{
7786 				CmEditAccountDlgUpdate(hWnd, a);
7787 			}
7788 			break;
7789 		case B_CHANGE_PASSWORD:
7790 			// Change the password
7791 			CmChangePassword(hWnd, a->ClientOption, a->ClientOption->HubName,
7792 				a->ClientAuth->Username);
7793 			break;
7794 		}
7795 		break;
7796 	case WM_CLOSE:
7797 		EndDialog(hWnd, false);
7798 		break;
7799 	case WM_NOTIFY:
7800 		n = (NMHDR *)lParam;
7801 		switch (n->idFrom)
7802 		{
7803 		case L_VLAN:
7804 			switch (n->code)
7805 			{
7806 			case LVN_ITEMCHANGED:
7807 				CmEditAccountDlgUpdate(hWnd, a);
7808 				break;
7809 			}
7810 			break;
7811 		}
7812 		break;
7813 	}
7814 
7815 	return 0;
7816 }
7817 
7818 // Update the proxy server settings
CmProxyDlgUpdate(HWND hWnd,CLIENT_OPTION * a)7819 void CmProxyDlgUpdate(HWND hWnd, CLIENT_OPTION *a)
7820 {
7821 	bool ok = true;
7822 	// Validate arguments
7823 	if (hWnd == NULL || a == NULL)
7824 	{
7825 		return;
7826 	}
7827 
7828 	if (IsEmpty(hWnd, E_HOSTNAME))
7829 	{
7830 		ok = false;
7831 	}
7832 	if (GetInt(hWnd, C_PORT) == 0)
7833 	{
7834 		ok = false;
7835 	}
7836 
7837 	SetEnable(hWnd, IDOK, ok);
7838 }
7839 
7840 // Proxy server settings dialog c
CmProxyDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)7841 UINT CmProxyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
7842 {
7843 	CLIENT_OPTION *a = (CLIENT_OPTION *)param;
7844 	// Validate arguments
7845 	if (hWnd == NULL)
7846 	{
7847 		return 0;
7848 	}
7849 
7850 	switch (msg)
7851 	{
7852 	case WM_INITDIALOG:
7853 		SetTextA(hWnd, E_HOSTNAME, a->ProxyName);
7854 		CbSetHeight(hWnd, C_PORT, 18);
7855 		CbAddStr(hWnd, C_PORT, L"8080", 0);
7856 		CbAddStr(hWnd, C_PORT, L"1080", 0);
7857 		CbAddStr(hWnd, C_PORT, L"80", 0);
7858 		CbAddStr(hWnd, C_PORT, L"3128", 0);
7859 		CbAddStr(hWnd, C_PORT, L"443", 0);
7860 		CbAddStr(hWnd, C_PORT, L"9821", 0);
7861 		CbAddStr(hWnd, C_PORT, L"9801", 0);
7862 		SetIntEx(hWnd, C_PORT, a->ProxyPort);
7863 		SetTextA(hWnd, E_USERNAME, a->ProxyUsername);
7864 		SetTextA(hWnd, E_PASSWORD, a->ProxyPassword);
7865 		if (a->ProxyPort == 0)
7866 		{
7867 			if (a->ProxyType == PROXY_HTTP)
7868 			{
7869 				SetInt(hWnd, C_PORT, 8080);
7870 			}
7871 			else
7872 			{
7873 				SetInt(hWnd, C_PORT, 1080);
7874 			}
7875 		}
7876 		CmProxyDlgUpdate(hWnd, a);
7877 		break;
7878 	case WM_COMMAND:
7879 		switch (LOWORD(wParam))
7880 		{
7881 		case E_HOSTNAME:
7882 		case C_PORT:
7883 		case E_USERNAME:
7884 		case E_PASSWORD:
7885 			CmProxyDlgUpdate(hWnd, a);
7886 			break;
7887 		}
7888 
7889 		switch (wParam)
7890 		{
7891 		case IDOK:
7892 			GetTxtA(hWnd, E_HOSTNAME, a->ProxyName, sizeof(a->ProxyName));
7893 			GetTxtA(hWnd, E_USERNAME, a->ProxyUsername, sizeof(a->ProxyUsername));
7894 			GetTxtA(hWnd, E_PASSWORD, a->ProxyPassword, sizeof(a->ProxyPassword));
7895 			a->ProxyPort = GetInt(hWnd, C_PORT);
7896 			EndDialog(hWnd, true);
7897 			break;
7898 		case IDCANCEL:
7899 			Close(hWnd);
7900 			break;
7901 		}
7902 		break;
7903 	case WM_CLOSE:
7904 		EndDialog(hWnd, false);
7905 		break;
7906 	}
7907 
7908 	return 0;
7909 }
7910 
7911 // Proxy server settings
CmProxyDlg(HWND hWnd,CLIENT_OPTION * a)7912 bool CmProxyDlg(HWND hWnd, CLIENT_OPTION *a)
7913 {
7914 	// Validate arguments
7915 	if (a == NULL)
7916 	{
7917 		return false;
7918 	}
7919 
7920 	return Dialog(hWnd, D_CM_PROXY, CmProxyDlgProc, a);
7921 }
7922 
7923 // Get issuer of the specified certificate if it is known
CmGetIssuer(X * x)7924 X *CmGetIssuer(X *x)
7925 {
7926 	RPC_GET_ISSUER a;
7927 	X *ret;
7928 	// Validate arguments
7929 	if (x == NULL)
7930 	{
7931 		return NULL;
7932 	}
7933 
7934 	Zero(&a, sizeof(a));
7935 	a.x = CloneX(x);
7936 	if (CALLEX(cm->hMainWnd, CcGetIssuer(cm->Client, &a)) == 0)
7937 	{
7938 		ret = CloneX(a.issuer_x);
7939 	}
7940 	else
7941 	{
7942 		ret = NULL;
7943 	}
7944 
7945 	CiFreeGetIssuer(&a);
7946 
7947 	return ret;
7948 }
7949 
7950 // Initialize the dialog
CmLoadXFromFileOrSecureCardDlgInit(HWND hWnd,CM_LOADX * p)7951 void CmLoadXFromFileOrSecureCardDlgInit(HWND hWnd, CM_LOADX *p)
7952 {
7953 	UINT current;
7954 	// Validate arguments
7955 	if (hWnd == NULL || p == NULL)
7956 	{
7957 		return;
7958 	}
7959 
7960 	current = MsRegReadInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "CertLoadSource");
7961 
7962 	Check(hWnd, R_FROM_FILE, current == 0);
7963 	Check(hWnd, R_FROM_SECURE, current != 0);
7964 
7965 	SetFont(hWnd, S_INFO, Font(0, true));
7966 
7967 	CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
7968 }
7969 
7970 // Update the dialog control
CmLoadXFromFileOrSecureCardDlgUpdate(HWND hWnd,CM_LOADX * p)7971 void CmLoadXFromFileOrSecureCardDlgUpdate(HWND hWnd, CM_LOADX *p)
7972 {
7973 	SECURE_DEVICE *dev;
7974 	wchar_t tmp[MAX_SIZE];
7975 	bool ok = true;
7976 	// Validate arguments
7977 	if (hWnd == NULL || p == NULL)
7978 	{
7979 		return;
7980 	}
7981 
7982 	dev = GetSecureDevice(SmGetCurrentSecureIdFromReg());
7983 	if (dev == NULL)
7984 	{
7985 		UniStrCpy(tmp, sizeof(tmp), _UU("SEC_CURRENT_NO_DEVICE"));
7986 	}
7987 	else
7988 	{
7989 		UniFormat(tmp, sizeof(tmp), _UU("SEC_CURRENT_DEVICE"), dev->DeviceName);
7990 	}
7991 
7992 	SetText(hWnd, S_INFO, tmp);
7993 
7994 	if (IsChecked(hWnd, R_FROM_SECURE))
7995 	{
7996 		if (dev == NULL)
7997 		{
7998 			ok = false;
7999 		}
8000 	}
8001 
8002 	SetEnable(hWnd, IDOK, ok);
8003 	SetEnable(hWnd, B_SELECT, IsChecked(hWnd, R_FROM_SECURE));
8004 	SetEnable(hWnd, S_CERT, IsChecked(hWnd, R_FROM_SECURE));
8005 	SetEnable(hWnd, S_FILE, IsChecked(hWnd, R_FROM_FILE));
8006 }
8007 
8008 // Certificate reading selection dialog procedure
CmLoadXFromFileOrSecureCardDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)8009 UINT CmLoadXFromFileOrSecureCardDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
8010 {
8011 	CM_LOADX *p = (CM_LOADX *)param;
8012 	X *x;
8013 	UINT current;
8014 	// Validate arguments
8015 	if (hWnd == NULL)
8016 	{
8017 		return 0;
8018 	}
8019 
8020 	switch (msg)
8021 	{
8022 	case WM_INITDIALOG:
8023 		CmLoadXFromFileOrSecureCardDlgInit(hWnd, p);
8024 		break;
8025 
8026 	case WM_COMMAND:
8027 		switch (wParam)
8028 		{
8029 		case IDOK:
8030 			current = (IsChecked(hWnd, R_FROM_FILE)) ? 0 : 1;
8031 			MsRegWriteInt(REG_CURRENT_USER, SECURE_MANAGER_KEY, "CertLoadSource", current);
8032 
8033 			if (current == 0)
8034 			{
8035 				// From file
8036 				if (CmLoadX(hWnd, &x))
8037 				{
8038 					p->x = x;
8039 					EndDialog(hWnd, true);
8040 				}
8041 			}
8042 			else
8043 			{
8044 				// From the smart card
8045 				char name[MAX_SIZE];
8046 
8047 				// Select the certificate name in the card
8048 				if (SmSelectKeyPair(hWnd, name, sizeof(name), NULL, 0))
8049 				{
8050 					// Read
8051 					WINUI_SECURE_BATCH batch[] =
8052 					{
8053 						{WINUI_SECURE_READ_CERT, name, true, NULL, NULL, NULL, NULL, NULL, NULL},
8054 					};
8055 
8056 					// Do reading
8057 					if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), SmGetCurrentSecureIdFromReg(), 0))
8058 					{
8059 						// Success
8060 						p->x = batch[0].OutputX;
8061 						EndDialog(hWnd, true);
8062 					}
8063 				}
8064 			}
8065 			break;
8066 
8067 		case IDCANCEL:
8068 			Close(hWnd);
8069 			break;
8070 
8071 		case R_FROM_FILE:
8072 			CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
8073 			break;
8074 
8075 		case R_FROM_SECURE:
8076 			CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
8077 			break;
8078 
8079 		case B_SELECT:
8080 			SmSelectSecureId(hWnd);
8081 			CmLoadXFromFileOrSecureCardDlgUpdate(hWnd, p);
8082 			break;
8083 		}
8084 		break;
8085 
8086 	case WM_CLOSE:
8087 		EndDialog(hWnd, false);
8088 		break;
8089 	}
8090 
8091 	return 0;
8092 }
8093 
8094 // Read certificate from a file or a smart card
CmLoadXFromFileOrSecureCard(HWND hWnd,X ** x)8095 bool CmLoadXFromFileOrSecureCard(HWND hWnd, X **x)
8096 {
8097 	CM_LOADX p;
8098 	// Validate arguments
8099 	if (x == NULL)
8100 	{
8101 		return false;
8102 	}
8103 
8104 	Zero(&p, sizeof(p));
8105 	if (Dialog(hWnd, D_CM_LOAD_X, CmLoadXFromFileOrSecureCardDlgProc, &p) == false)
8106 	{
8107 		return false;
8108 	}
8109 
8110 	*x = p.x;
8111 
8112 	return true;
8113 }
8114 
8115 // Read the certificate
CmLoadX(HWND hWnd,X ** x)8116 bool CmLoadX(HWND hWnd, X **x)
8117 {
8118 	return CmLoadXEx(hWnd, x, NULL, 0);
8119 }
CmLoadXEx(HWND hWnd,X ** x,char * filename,UINT size)8120 bool CmLoadXEx(HWND hWnd, X **x, char *filename, UINT size)
8121 {
8122 	wchar_t *filename_w = CopyStrToUni(filename);
8123 	bool ret;
8124 
8125 	ret = CmLoadXExW(hWnd, x, filename_w, size);
8126 
8127 	Free(filename_w);
8128 
8129 	return ret;
8130 }
CmLoadXExW(HWND hWnd,X ** x,wchar_t * filename,UINT size)8131 bool CmLoadXExW(HWND hWnd, X **x, wchar_t *filename, UINT size)
8132 {
8133 	wchar_t *s;
8134 	bool is_p12;
8135 	wchar_t tmp[MAX_SIZE];
8136 	K *k;
8137 	// Validate arguments
8138 	if (x == NULL)
8139 	{
8140 		return false;
8141 	}
8142 
8143 	// Read the certificate
8144 	s = OpenDlg(hWnd, _UU("DLG_CERT_OR_P12_FILTER"), _UU("DLG_OPEN_CERT"));
8145 	if (s == NULL)
8146 	{
8147 		return false;
8148 	}
8149 	UniStrCpy(tmp, sizeof(tmp), s);
8150 	if (filename != NULL)
8151 	{
8152 		UniStrCpy(filename, size, tmp);
8153 	}
8154 	Free(s);
8155 	if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))
8156 	{
8157 		is_p12 = true;
8158 	}
8159 	else
8160 	{
8161 		is_p12 = false;
8162 	}
8163 
8164 	if (is_p12)
8165 	{
8166 		// Processing of PKCS#12
8167 		BUF *b = ReadDumpW(tmp);
8168 		P12 *p12;
8169 		if (b == NULL)
8170 		{
8171 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8172 			return false;
8173 		}
8174 		p12 = BufToP12(b);
8175 		if (p12 == NULL)
8176 		{
8177 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8178 			FreeBuf(b);
8179 			return false;
8180 		}
8181 		if (IsEncryptedP12(p12) == false)
8182 		{
8183 			if (ParseP12(p12, x, &k, NULL) == false)
8184 			{
8185 				MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8186 				FreeP12(p12);
8187 				FreeBuf(b);
8188 				return false;
8189 			}
8190 		}
8191 		else
8192 		{
8193 			char password[MAX_SIZE];
8194 			if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)
8195 			{
8196 				FreeP12(p12);
8197 				FreeBuf(b);
8198 				return false;
8199 			}
8200 			else
8201 			{
8202 				if (ParseP12(p12, x, &k, password) == false)
8203 				{
8204 					MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8205 					FreeP12(p12);
8206 					FreeBuf(b);
8207 					return false;
8208 				}
8209 			}
8210 		}
8211 		FreeP12(p12);
8212 		FreeBuf(b);
8213 		FreeK(k);
8214 		return true;
8215 	}
8216 	else
8217 	{
8218 		// Processing of X509
8219 		BUF *b = ReadDumpW(tmp);
8220 		X *x509;
8221 		if (b == NULL)
8222 		{
8223 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8224 			return false;
8225 		}
8226 
8227 		x509 = BufToX(b, IsBase64(b));
8228 		FreeBuf(b);
8229 		if (x509 == NULL)
8230 		{
8231 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);
8232 			return false;
8233 		}
8234 
8235 		*x = x509;
8236 		return true;
8237 	}
8238 }
8239 
8240 // Read the secret key
CmLoadK(HWND hWnd,K ** k)8241 bool CmLoadK(HWND hWnd, K **k)
8242 {
8243 	return CmLoadKEx(hWnd, k, NULL, 0);
8244 }
CmLoadKEx(HWND hWnd,K ** k,char * filename,UINT size)8245 bool CmLoadKEx(HWND hWnd, K **k, char *filename, UINT size)
8246 {
8247 	wchar_t *filename_w = CopyStrToUni(filename);
8248 	bool ret;
8249 
8250 	ret = CmLoadKExW(hWnd, k, filename_w, size);
8251 
8252 	Free(filename_w);
8253 
8254 	return ret;
8255 }
CmLoadKExW(HWND hWnd,K ** k,wchar_t * filename,UINT size)8256 bool CmLoadKExW(HWND hWnd, K **k, wchar_t *filename, UINT size)
8257 {
8258 	wchar_t *s;
8259 	bool is_p12;
8260 	wchar_t tmp[MAX_SIZE];
8261 	// Validate arguments
8262 	if (k == NULL)
8263 	{
8264 		return false;
8265 	}
8266 
8267 	// Read the certificate
8268 	s = OpenDlg(hWnd, _UU("DLG_KEY_OR_P12_FILTER"), _UU("DLG_OPEN_KEY"));
8269 	if (s == NULL)
8270 	{
8271 		return false;
8272 	}
8273 	UniStrCpy(tmp, sizeof(tmp), s);
8274 	Free(s);
8275 	if (filename != NULL)
8276 	{
8277 		UniStrCpy(filename, size, tmp);
8278 	}
8279 	if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))
8280 	{
8281 		is_p12 = true;
8282 	}
8283 	else
8284 	{
8285 		is_p12 = false;
8286 	}
8287 
8288 	if (is_p12)
8289 	{
8290 		// Processing of PKCS#12
8291 		BUF *b = ReadDumpW(tmp);
8292 		P12 *p12;
8293 		if (b == NULL)
8294 		{
8295 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8296 			return false;
8297 		}
8298 		p12 = BufToP12(b);
8299 		if (p12 == NULL)
8300 		{
8301 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8302 			FreeBuf(b);
8303 			return false;
8304 		}
8305 		if (IsEncryptedP12(p12) == false)
8306 		{
8307 			X *x;
8308 			if (ParseP12(p12, &x, k, NULL) == false)
8309 			{
8310 				MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8311 				FreeP12(p12);
8312 				FreeBuf(b);
8313 				return false;
8314 			}
8315 
8316 			FreeX(x);
8317 		}
8318 		else
8319 		{
8320 			char password[MAX_SIZE];
8321 			if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)
8322 			{
8323 				FreeP12(p12);
8324 				FreeBuf(b);
8325 				return false;
8326 			}
8327 			else
8328 			{
8329 				X *x;
8330 				if (ParseP12(p12, &x, k, password) == false)
8331 				{
8332 					MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8333 					FreeP12(p12);
8334 					FreeBuf(b);
8335 					return false;
8336 				}
8337 
8338 				FreeX(x);
8339 			}
8340 		}
8341 		FreeP12(p12);
8342 		FreeBuf(b);
8343 		return true;
8344 	}
8345 	else
8346 	{
8347 		// Processing of private key
8348 		BUF *b = ReadDumpW(tmp);
8349 		K *key;
8350 		if (b == NULL)
8351 		{
8352 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8353 			return false;
8354 		}
8355 
8356 		if (IsEncryptedK(b, true) == false)
8357 		{
8358 			key = BufToK(b, true, IsBase64(b), NULL);
8359 		}
8360 		else
8361 		{
8362 			char pass[MAX_SIZE];
8363 			if (PassphraseDlg(hWnd, pass, sizeof(pass), b, false) == false)
8364 			{
8365 				FreeBuf(b);
8366 				return false;
8367 			}
8368 			key = BufToK(b, true, IsBase64(b), pass);
8369 		}
8370 
8371 		if (key == NULL)
8372 		{
8373 			FreeBuf(b);
8374 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);
8375 			return false;
8376 		}
8377 
8378 		FreeBuf(b);
8379 		*k = key;
8380 		return true;
8381 	}
8382 }
8383 
8384 // Read a set of certificate and private key
CmLoadXAndK(HWND hWnd,X ** x,K ** k)8385 bool CmLoadXAndK(HWND hWnd, X **x, K **k)
8386 {
8387 	wchar_t *s;
8388 	bool is_p12;
8389 	wchar_t tmp[MAX_SIZE];
8390 	// Validate arguments
8391 	if (x == NULL || k == NULL)
8392 	{
8393 		return false;
8394 	}
8395 START_FIRST:
8396 
8397 	// Read the certificate
8398 	s = OpenDlg(hWnd, _UU("DLG_CERT_OR_P12_FILTER"), _UU("DLG_OPEN_CERT"));
8399 	if (s == NULL)
8400 	{
8401 		return false;
8402 	}
8403 	UniStrCpy(tmp, sizeof(tmp), s);
8404 	Free(s);
8405 	if (UniEndWith(tmp, L".p12") || UniEndWith(tmp, L".pfx"))
8406 	{
8407 		is_p12 = true;
8408 	}
8409 	else
8410 	{
8411 		is_p12 = false;
8412 	}
8413 
8414 	if (is_p12)
8415 	{
8416 		// Processing of PKCS#12
8417 		BUF *b = ReadDumpW(tmp);
8418 		P12 *p12;
8419 		if (b == NULL)
8420 		{
8421 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8422 			return false;
8423 		}
8424 		p12 = BufToP12(b);
8425 		if (p12 == NULL)
8426 		{
8427 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8428 			FreeBuf(b);
8429 			return false;
8430 		}
8431 		if (IsEncryptedP12(p12) == false)
8432 		{
8433 			if (ParseP12(p12, x, k, NULL) == false)
8434 			{
8435 				MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8436 				FreeP12(p12);
8437 				FreeBuf(b);
8438 				return false;
8439 			}
8440 		}
8441 		else
8442 		{
8443 			char password[MAX_SIZE];
8444 			if (PassphraseDlg(hWnd, password, sizeof(password), b, true) == false)
8445 			{
8446 				FreeP12(p12);
8447 				FreeBuf(b);
8448 				return false;
8449 			}
8450 			else
8451 			{
8452 				if (ParseP12(p12, x, k, password) == false)
8453 				{
8454 					MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
8455 					FreeP12(p12);
8456 					FreeBuf(b);
8457 					return false;
8458 				}
8459 			}
8460 		}
8461 		if (CheckXandK(*x, *k) == false)
8462 		{
8463 			FreeX(*x);
8464 			FreeK(*k);
8465 			FreeP12(p12);
8466 			FreeBuf(b);
8467 			if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)
8468 			{
8469 				goto START_FIRST;
8470 			}
8471 			return false;
8472 		}
8473 		FreeP12(p12);
8474 		FreeBuf(b);
8475 		return true;
8476 	}
8477 	else
8478 	{
8479 		// Processing of X509
8480 		BUF *b = ReadDumpW(tmp);
8481 		X *x509;
8482 		K *key;
8483 		if (b == NULL)
8484 		{
8485 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8486 			return false;
8487 		}
8488 
8489 		x509 = BufToX(b, IsBase64(b));
8490 		FreeBuf(b);
8491 		if (x509 == NULL)
8492 		{
8493 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);
8494 			return false;
8495 		}
8496 
8497 		// Read the secret key
8498 		s = OpenDlg(hWnd, _UU("DLG_KEY_FILTER"), _UU("DLG_OPEN_KEY_WITH_CERT"));
8499 		if (s == NULL)
8500 		{
8501 			FreeX(x509);
8502 			return false;
8503 		}
8504 		UniStrCpy(tmp, sizeof(tmp), s);
8505 		Free(s);
8506 
8507 		b = ReadDumpW(tmp);
8508 		if (b == NULL)
8509 		{
8510 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
8511 			FreeX(x509);
8512 			return false;
8513 		}
8514 
8515 		if (IsEncryptedK(b, true) == false)
8516 		{
8517 			key = BufToK(b, true, IsBase64(b), NULL);
8518 		}
8519 		else
8520 		{
8521 			char pass[MAX_SIZE];
8522 			if (PassphraseDlg(hWnd, pass, sizeof(pass), b, false) == false)
8523 			{
8524 				FreeBuf(b);
8525 				FreeX(x509);
8526 				return false;
8527 			}
8528 			key = BufToK(b, true, IsBase64(b), pass);
8529 		}
8530 
8531 		if (key == NULL)
8532 		{
8533 			FreeBuf(b);
8534 			FreeX(x509);
8535 			MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);
8536 			return false;
8537 		}
8538 
8539 		if (CheckXandK(x509, key) == false)
8540 		{
8541 			FreeBuf(b);
8542 			FreeX(x509);
8543 			FreeK(key);
8544 			if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)
8545 			{
8546 				goto START_FIRST;
8547 			}
8548 			return false;
8549 		}
8550 
8551 		FreeBuf(b);
8552 		*x = x509;
8553 		*k = key;
8554 		return true;
8555 	}
8556 }
8557 
8558 // Virtual HUB enumeration start
CmEditAccountDlgStartEnumHub(HWND hWnd,CM_ACCOUNT * a)8559 void CmEditAccountDlgStartEnumHub(HWND hWnd, CM_ACCOUNT *a)
8560 {
8561 	char server_name[MAX_HOST_NAME_LEN + 1];
8562 	UINT old_proxy_type;
8563 	// Validate arguments
8564 	if (hWnd == NULL || a == NULL)
8565 	{
8566 		return;
8567 	}
8568 
8569 
8570 	if (StrLen(a->ClientOption->Hostname) == 0)
8571 	{
8572 		return;
8573 	}
8574 	if (a->ClientOption->Port == 0)
8575 	{
8576 		return;
8577 	}
8578 	if (a->ClientOption->ProxyType != PROXY_DIRECT &&
8579 		(StrLen(a->ClientOption->ProxyName) == 0 ||
8580 		a->ClientOption->ProxyPort == 0))
8581 	{
8582 		return;
8583 	}
8584 
8585 	GetTxtA(hWnd, E_HOSTNAME, server_name, sizeof(server_name));
8586 
8587 	if (StrCmpi(server_name, a->old_server_name) == 0)
8588 	{
8589 		if (CbNum(hWnd, C_HUBNAME) != 0)
8590 		{
8591 			return;
8592 		}
8593 	}
8594 	else
8595 	{
8596 		StrCpy(a->old_server_name, sizeof(a->old_server_name), server_name);
8597 		CbReset(hWnd, C_HUBNAME);
8598 	}
8599 
8600 	old_proxy_type = a->ClientOption->ProxyType;
8601 
8602 	if (IsChecked(hWnd, R_DIRECT_TCP))
8603 	{
8604 		a->ClientOption->ProxyType = PROXY_DIRECT;
8605 	}
8606 	if (IsChecked(hWnd, R_HTTPS))
8607 	{
8608 		a->ClientOption->ProxyType = PROXY_HTTP;
8609 	}
8610 	if (IsChecked(hWnd, R_SOCKS))
8611 	{
8612 		a->ClientOption->ProxyType = PROXY_SOCKS;
8613 	}
8614 
8615 	CmEnumHubStart(hWnd, a->ClientOption);
8616 
8617 	a->ClientOption->ProxyType = old_proxy_type;
8618 }
8619 
8620 // [OK] button
CmEditAccountDlgOnOk(HWND hWnd,CM_ACCOUNT * a)8621 void CmEditAccountDlgOnOk(HWND hWnd, CM_ACCOUNT *a)
8622 {
8623 	RPC_CLIENT_CREATE_ACCOUNT c;
8624 	bool b;
8625 	// Validate arguments
8626 	if (hWnd == NULL || a == NULL)
8627 	{
8628 		return;
8629 	}
8630 	if (a->ClientOption->NumRetry != 0 && a->ClientOption->RetryInterval < 5)
8631 	{
8632 		MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_RETRY_INTERVAL_ERROR"));
8633 		FocusEx(hWnd, E_RETRY_SPAN);
8634 		return;
8635 	}
8636 
8637 	CmEditAccountDlgUpdate(hWnd, a);
8638 
8639 	if (a->LinkMode == false && a->NatMode == false)
8640 	{
8641 		// Save the account
8642 		Zero(&c, sizeof(c));
8643 		c.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
8644 		Copy(c.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
8645 		c.ClientAuth = CopyClientAuth(a->ClientAuth);
8646 		c.CheckServerCert = a->CheckServerCert;
8647 		if (a->ServerCert != NULL)
8648 		{
8649 			c.ServerCert = CloneX(a->ServerCert);
8650 		}
8651 		c.StartupAccount = a->Startup;
8652 
8653 		if (a->EditMode == false)
8654 		{
8655 			b = CALL(hWnd, CcCreateAccount(cm->Client, &c));
8656 		}
8657 		else
8658 		{
8659 			b = CALL(hWnd, CcSetAccount(cm->Client, &c));
8660 		}
8661 
8662 		CiFreeClientCreateAccount(&c);
8663 
8664 		// Check whether this account is currently running
8665 		if (b)
8666 		{
8667 			RPC_CLIENT_GET_CONNECTION_STATUS st;
8668 			Zero(&st, sizeof(st));
8669 			UniStrCpy(st.AccountName, sizeof(st.AccountName), a->ClientOption->AccountName);
8670 			if (CALL(hWnd, CcGetAccountStatus(cm->Client, &st)))
8671 			{
8672 				if (st.Active)
8673 				{
8674 					MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("CM_CURRENT_ACTIVE"),
8675 						st.AccountName);
8676 				}
8677 			}
8678 		}
8679 
8680 		if (b)
8681 		{
8682 			EndDialog(hWnd, true);
8683 		}
8684 	}
8685 	else
8686 	{
8687 		if (a->LinkMode)
8688 		{
8689 			// Link mode
8690 			RPC_CREATE_LINK t;
8691 
8692 			Zero(&t, sizeof(t));
8693 			StrCpy(t.HubName, sizeof(t.HubName), a->Hub->HubName);
8694 			t.Online = a->OnlineFlag;
8695 			Copy(&t.Policy, &a->Policy, sizeof(POLICY));
8696 			t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
8697 			Copy(t.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
8698 			t.ClientAuth = CopyClientAuth(a->ClientAuth);
8699 			t.CheckServerCert = a->CheckServerCert;
8700 			t.ServerCert = CloneX(a->ServerCert);
8701 
8702 			// Save the settings for cascade connection
8703 			if (a->EditMode)
8704 			{
8705 				if (CALL(hWnd, ScSetLink(a->Hub->Rpc, &t)))
8706 				{
8707 					if (a->OnlineFlag)
8708 					{
8709 						MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("SM_LINK_SAVE_ONLINE"), a->ClientOption->AccountName);
8710 					}
8711 					EndDialog(hWnd, true);
8712 				}
8713 			}
8714 			else
8715 			{
8716 				if (CALL(hWnd, ScCreateLink(a->Hub->Rpc, &t)))
8717 				{
8718 					if (a->Link_ConnectNow)
8719 					{
8720 						RPC_LINK tt;
8721 
8722 						Zero(&tt, sizeof(tt));
8723 						UniStrCpy(tt.AccountName, sizeof(tt.AccountName), a->ClientOption->AccountName);
8724 						StrCpy(tt.HubName, sizeof(tt.HubName), a->Hub->HubName);
8725 
8726 						CALL(hWnd, ScSetLinkOnline(a->Hub->Rpc, &tt));
8727 					}
8728 					EndDialog(hWnd, true);
8729 				}
8730 			}
8731 
8732 			FreeRpcCreateLink(&t);
8733 		}
8734 		else
8735 		{
8736 			// NAT mode
8737 			RPC_CREATE_LINK t;
8738 			Zero(&t, sizeof(t));
8739 
8740 			t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
8741 			Copy(t.ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
8742 			t.ClientAuth = CopyClientAuth(a->ClientAuth);
8743 
8744 			if (CALL(hWnd, NcSetClientConfig(a->Rpc, &t)))
8745 			{
8746 				EndDialog(hWnd, true);
8747 			}
8748 
8749 			FreeRpcCreateLink(&t);
8750 		}
8751 	}
8752 }
8753 
8754 // Show the account editing dialog
CmEditAccountDlg(HWND hWnd,CM_ACCOUNT * a)8755 bool CmEditAccountDlg(HWND hWnd, CM_ACCOUNT *a)
8756 {
8757 	// Validate arguments
8758 	if (hWnd == NULL || a == NULL)
8759 	{
8760 		return false;
8761 	}
8762 
8763 	return Dialog(hWnd, D_CM_ACCOUNT, CmEditAccountDlgProc, a);
8764 }
8765 
8766 // Edit the account
CmEditAccount(HWND hWnd,wchar_t * account_name)8767 void CmEditAccount(HWND hWnd, wchar_t *account_name)
8768 {
8769 	CM_ACCOUNT *a;
8770 	// Validate arguments
8771 	if (hWnd == NULL || account_name == NULL)
8772 	{
8773 		return;
8774 	}
8775 
8776 	a = CmGetExistAccountObject(hWnd, account_name);
8777 	if (a == NULL)
8778 	{
8779 		return;
8780 	}
8781 
8782 	CmVoice("input_config");
8783 	if (CmEditAccountDlg(hWnd, a))
8784 	{
8785 		CmVoice("set_config");
8786 	}
8787 
8788 	CmFreeAccountObject(hWnd, a);
8789 }
8790 
8791 // Create an account
CmNewAccount(HWND hWnd)8792 void CmNewAccount(HWND hWnd)
8793 {
8794 	CM_ACCOUNT *a;
8795 	RPC_CLIENT_ENUM_VLAN t;
8796 	UINT num_vlan = 0;
8797 	// Validate arguments
8798 	if (hWnd == NULL)
8799 	{
8800 		return;
8801 	}
8802 
8803 	if (IsEnable(hWnd, 0) == false)
8804 	{
8805 		return;
8806 	}
8807 
8808 	Zero(&t, sizeof(t));
8809 	if (CcEnumVLan(cm->Client, &t) == ERR_NO_ERROR)
8810 	{
8811 		num_vlan = t.NumItem;
8812 
8813 		CiFreeClientEnumVLan(&t);
8814 	}
8815 
8816 	if (num_vlan == 0)
8817 	{
8818 		if (MsgBox(hWnd, MB_ICONINFORMATION | MB_YESNO, _UU("CM_NO_VLAN")) == IDNO)
8819 		{
8820 			return;
8821 		}
8822 		else
8823 		{
8824 			if (cm->server_name == NULL || cm->Client->Unix)
8825 			{
8826 				Command(hWnd, CMD_NEW_VLAN);
8827 				return;
8828 			}
8829 			else
8830 			{
8831 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_VLAN_REMOTE_ERROR"));
8832 			}
8833 			return;
8834 		}
8835 	}
8836 
8837 	a = CmCreateNewAccountObject(hWnd);
8838 	if (a == NULL)
8839 	{
8840 		return;
8841 	}
8842 
8843 	CmVoice("input_config");
8844 	if (CmEditAccountDlg(hWnd, a))
8845 	{
8846 		CmVoice("new_config");
8847 	}
8848 
8849 	CmFreeAccountObject(hWnd, a);
8850 }
8851 
8852 // Release the account object
CmFreeAccountObject(HWND hWnd,CM_ACCOUNT * a)8853 void CmFreeAccountObject(HWND hWnd, CM_ACCOUNT *a)
8854 {
8855 	// Validate arguments
8856 	if (hWnd == NULL || a == NULL)
8857 	{
8858 		return;
8859 	}
8860 
8861 	Free(a->ClientOption);
8862 	CiFreeClientAuth(a->ClientAuth);
8863 	if (a->ServerCert != NULL)
8864 	{
8865 		FreeX(a->ServerCert);
8866 	}
8867 	Free(a);
8868 }
8869 
8870 // Get an existing account object
CmGetExistAccountObject(HWND hWnd,wchar_t * account_name)8871 CM_ACCOUNT *CmGetExistAccountObject(HWND hWnd, wchar_t *account_name)
8872 {
8873 	RPC_CLIENT_GET_ACCOUNT c;
8874 	CM_ACCOUNT *a;
8875 	// Validate arguments
8876 	if (hWnd == NULL)
8877 	{
8878 		return NULL;
8879 	}
8880 
8881 	Zero(&c, sizeof(c));
8882 	UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
8883 	if (CALL(hWnd, CcGetAccount(cm->Client, &c)) == false)
8884 	{
8885 		return NULL;
8886 	}
8887 
8888 	a = ZeroMalloc(sizeof(CM_ACCOUNT));
8889 	a->EditMode = true;
8890 	a->CheckServerCert = c.CheckServerCert;
8891 	a->Startup = c.StartupAccount;
8892 	if (c.ServerCert != NULL)
8893 	{
8894 		a->ServerCert = CloneX(c.ServerCert);
8895 	}
8896 	a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
8897 	Copy(a->ClientOption, c.ClientOption, sizeof(CLIENT_OPTION));
8898 	a->ClientAuth = CopyClientAuth(c.ClientAuth);
8899 	Copy(a->ShortcutKey, c.ShortcutKey, SHA1_SIZE);
8900 	CiFreeClientGetAccount(&c);
8901 
8902 	a->LockMode = cm->CmSetting.LockMode;
8903 
8904 	return a;
8905 }
8906 
8907 // Create a new account object
CmCreateNewAccountObject(HWND hWnd)8908 CM_ACCOUNT *CmCreateNewAccountObject(HWND hWnd)
8909 {
8910 	CM_ACCOUNT *a;
8911 	// Validate arguments
8912 	if (hWnd == NULL)
8913 	{
8914 		return NULL;
8915 	}
8916 
8917 	a = ZeroMalloc(sizeof(CM_ACCOUNT));
8918 	a->EditMode = false;
8919 	a->CheckServerCert = false;
8920 	a->Startup = false;
8921 	a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
8922 
8923 	// Initialize the client options
8924 	CmGenerateNewAccountName(hWnd, a->ClientOption->AccountName, sizeof(a->ClientOption->AccountName));
8925 	a->ClientOption->Port = 443;	// Default port number
8926 	a->ClientOption->NumRetry = INFINITE;
8927 	a->ClientOption->RetryInterval = 15;
8928 	a->ClientOption->MaxConnection = 1;
8929 	a->ClientOption->HalfConnection = false;
8930 	a->ClientOption->UseEncrypt = true;
8931 	a->ClientOption->AdditionalConnectionInterval = 1;
8932 
8933 	if (cm->Client->Unix)
8934 	{
8935 		a->ClientOption->NoRoutingTracking = true;
8936 	}
8937 
8938 	a->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
8939 
8940 	// Password authentication
8941 	a->ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;
8942 
8943 	return a;
8944 }
8945 
8946 // Create an imported account name
CmGenerateImportName(HWND hWnd,wchar_t * name,UINT size,wchar_t * old_name)8947 void CmGenerateImportName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name)
8948 {
8949 	UINT i;
8950 	// Validate arguments
8951 	if (name == NULL || hWnd == NULL)
8952 	{
8953 		return;
8954 	}
8955 
8956 	for (i = 1;;i++)
8957 	{
8958 		wchar_t tmp[MAX_SIZE];
8959 		if (i == 1)
8960 		{
8961 			UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_1"), old_name);
8962 		}
8963 		else
8964 		{
8965 			UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_2"), old_name, i);
8966 		}
8967 
8968 		if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)
8969 		{
8970 			UniStrCpy(name, size, tmp);
8971 			return;
8972 		}
8973 	}
8974 }
8975 
8976 // Create a copy name
CmGenerateCopyName(HWND hWnd,wchar_t * name,UINT size,wchar_t * old_name)8977 void CmGenerateCopyName(HWND hWnd, wchar_t *name, UINT size, wchar_t *old_name)
8978 {
8979 	UINT i;
8980 	// Validate arguments
8981 	if (name == NULL || hWnd == NULL)
8982 	{
8983 		return;
8984 	}
8985 
8986 	for (i = 1;;i++)
8987 	{
8988 		wchar_t tmp[MAX_SIZE];
8989 		if (i == 1)
8990 		{
8991 			UniFormat(tmp, sizeof(tmp), _UU("CM_COPY_NAME_1"), old_name);
8992 		}
8993 		else
8994 		{
8995 			UniFormat(tmp, sizeof(tmp), _UU("CM_COPY_NAME_2"), i, old_name);
8996 		}
8997 
8998 		if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)
8999 		{
9000 			UniStrCpy(name, size, tmp);
9001 			return;
9002 		}
9003 	}
9004 }
9005 
9006 // Create a new account name
CmGenerateNewAccountName(HWND hWnd,wchar_t * name,UINT size)9007 void CmGenerateNewAccountName(HWND hWnd, wchar_t *name, UINT size)
9008 {
9009 	UINT i;
9010 	// Validate arguments
9011 	if (name == NULL || hWnd == NULL)
9012 	{
9013 		return;
9014 	}
9015 
9016 	for (i = 1;;i++)
9017 	{
9018 		wchar_t tmp[MAX_SIZE];
9019 		if (i == 1)
9020 		{
9021 			UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_1"));
9022 		}
9023 		else
9024 		{
9025 			UniFormat(tmp, sizeof(tmp), _UU("CM_NEW_ACCOUNT_NAME_2"), i);
9026 		}
9027 
9028 		if (LvSearchStr(hWnd, L_ACCOUNT, 0, tmp) == INFINITE)
9029 		{
9030 			UniStrCpy(name, size, tmp);
9031 			return;
9032 		}
9033 	}
9034 }
9035 
9036 // Show the policy list
CmPolicyDlgPrint(HWND hWnd,CM_POLICY * p)9037 void CmPolicyDlgPrint(HWND hWnd, CM_POLICY *p)
9038 {
9039 	CmPolicyDlgPrintEx(hWnd, p, false);
9040 }
CmPolicyDlgPrintEx(HWND hWnd,CM_POLICY * p,bool cascade_mode)9041 void CmPolicyDlgPrintEx(HWND hWnd, CM_POLICY *p, bool cascade_mode)
9042 {
9043 	CmPolicyDlgPrintEx2(hWnd, p, cascade_mode, POLICY_CURRENT_VERSION);
9044 }
CmPolicyDlgPrintEx2(HWND hWnd,CM_POLICY * p,bool cascade_mode,UINT ver)9045 void CmPolicyDlgPrintEx2(HWND hWnd, CM_POLICY *p, bool cascade_mode, UINT ver)
9046 {
9047 	POLICY *pol;
9048 	UINT i;
9049 	LVB *b;
9050 	// Validate arguments
9051 	if (hWnd == NULL || p == NULL)
9052 	{
9053 		return;
9054 	}
9055 
9056 	pol = p->Policy;
9057 
9058 	b = LvInsertStart();
9059 
9060 	for (i = 0;i < NUM_POLICY_ITEM;i++)
9061 	{
9062 		wchar_t tmp[MAX_SIZE];
9063 
9064 		if (cascade_mode)
9065 		{
9066 			if (PolicyIsSupportedForCascade(i) == false)
9067 			{
9068 				continue;
9069 			}
9070 		}
9071 
9072 		if (IS_POLICY_FOR_CURRENT_VER(i, ver))
9073 		{
9074 			if (policy_item[i].TypeInt == false)
9075 			{
9076 				// bool type
9077 				UniStrCpy(tmp, sizeof(tmp), POLICY_BOOL(pol, i) ? _UU("POL_BOOL_ENABLE") : (p->Extension ? _UU("POL_BOOL_DISABLE_EX") : _UU("POL_BOOL_DISABLE")));
9078 			}
9079 			else
9080 			{
9081 				// int type
9082 				if (policy_item[i].AllowZero && POLICY_INT(pol, i) == 0)
9083 				{
9084 					UniStrCpy(tmp, sizeof(tmp), _UU("POL_INT_ZERO"));
9085 				}
9086 				else
9087 				{
9088 					UniFormat(tmp, sizeof(tmp), _UU(policy_item[i].FormatStr), POLICY_INT(pol, i));
9089 				}
9090 			}
9091 
9092 			LvInsertAdd(b, ICO_MACHINE, (void *)i, 2, GetPolicyTitle(i), tmp);
9093 		}
9094 	}
9095 
9096 	LvInsertEnd(b, hWnd, L_POLICY);
9097 }
9098 
9099 // Policy list dialog box
CmPolicyDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)9100 UINT CmPolicyDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
9101 {
9102 	CM_POLICY *p = (CM_POLICY *)param;
9103 	NMHDR *n;
9104 	// Validate arguments
9105 	if (hWnd == NULL)
9106 	{
9107 		return 0;
9108 	}
9109 
9110 	switch (msg)
9111 	{
9112 	case WM_INITDIALOG:
9113 		FormatText(hWnd, 0, p->AccountName);
9114 		FormatText(hWnd, S_TITLE, p->AccountName);
9115 		p->hWnd = hWnd;
9116 		if (p->CmStatus != NULL)
9117 		{
9118 			p->CmStatus->hWndPolicy = hWnd;
9119 		}
9120 
9121 		// Initialize the column
9122 		LvInit(hWnd, L_POLICY);
9123 		LvInsertColumn(hWnd, L_POLICY, 0, _UU("POL_TITLE_STR"), 375);
9124 		LvInsertColumn(hWnd, L_POLICY, 1, _UU("POL_VALUE_STR"), 100);
9125 
9126 		// Display
9127 		CmPolicyDlgPrint(hWnd, p);
9128 
9129 		// Select the first
9130 		LvSelect(hWnd, L_POLICY, 0);
9131 		break;
9132 
9133 	case WM_COMMAND:
9134 		switch (wParam)
9135 		{
9136 		case IDOK:
9137 		case IDCANCEL:
9138 			Close(hWnd);
9139 			break;
9140 		}
9141 		break;
9142 
9143 	case WM_NOTIFY:
9144 		n = (NMHDR *)lParam;
9145 		switch (n->idFrom)
9146 		{
9147 		case L_POLICY:
9148 			switch (n->code)
9149 			{
9150 			case LVN_ITEMCHANGED:
9151 				// Change selection
9152 				if (LvIsSelected(hWnd, L_POLICY) == false)
9153 				{
9154 					SetText(hWnd, S_DESCRIPTION, L"");
9155 				}
9156 				else
9157 				{
9158 					UINT index = LvGetSelected(hWnd, L_POLICY);
9159 					UINT id = (UINT)LvGetParam(hWnd, L_POLICY, index);
9160 					if (id < NUM_POLICY_ITEM)
9161 					{
9162 						SetText(hWnd, S_DESCRIPTION, GetPolicyDescription(id));
9163 					}
9164 				}
9165 				break;
9166 			}
9167 			break;
9168 		}
9169 		break;
9170 
9171 	case WM_CLOSE:
9172 		EndDialog(hWnd, 0);
9173 		break;
9174 	}
9175 
9176 	LvSortHander(hWnd, msg, wParam, lParam, L_POLICY);
9177 
9178 	return 0;
9179 }
9180 
9181 // Show the policy list dialog
CmPolicyDlg(HWND hWnd,CM_STATUS * st)9182 void CmPolicyDlg(HWND hWnd, CM_STATUS *st)
9183 {
9184 	RPC_CLIENT_GET_CONNECTION_STATUS s;
9185 	POLICY *policy;
9186 	CM_POLICY cp;
9187 	// Validate arguments
9188 	if (hWnd == NULL || st == NULL)
9189 	{
9190 		return;
9191 	}
9192 
9193 	// Get the policy
9194 	Zero(&s, sizeof(s));
9195 	UniStrCpy(s.AccountName, sizeof(s.AccountName), st->AccountName);
9196 	if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)
9197 	{
9198 		return;
9199 	}
9200 	if (s.Active == false)
9201 	{
9202 		return;
9203 	}
9204 
9205 	policy = &s.Policy;
9206 
9207 	Zero(&cp, sizeof(cp));
9208 	UniStrCpy(cp.AccountName, sizeof(cp.AccountName), st->AccountName);
9209 	cp.Policy = policy;
9210 	cp.CmStatus = st;
9211 
9212 	Dialog(hWnd, D_CM_POLICY, CmPolicyDlgProc, &cp);
9213 
9214 	st->hWndPolicy = NULL;
9215 
9216 	CiFreeClientGetConnectionStatus(&s);
9217 }
9218 
9219 // Show the certificate
CmStatusDlgPrintCert(HWND hWnd,CM_STATUS * st,bool server)9220 void CmStatusDlgPrintCert(HWND hWnd, CM_STATUS *st, bool server)
9221 {
9222 	RPC_CLIENT_GET_CONNECTION_STATUS s;
9223 	X *x, *issuer;
9224 	// Validate arguments
9225 	if (hWnd == NULL || st == NULL)
9226 	{
9227 		return;
9228 	}
9229 
9230 	// Get the latest information
9231 	Zero(&s, sizeof(s));
9232 	UniStrCpy(s.AccountName, sizeof(s.AccountName), st->AccountName);
9233 	if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)
9234 	{
9235 		Close(hWnd);
9236 		return;
9237 	}
9238 
9239 	if (s.Active == false)
9240 	{
9241 		// Disconnect
9242 		Close(hWnd);
9243 		return;
9244 	}
9245 
9246 	if (server == false)
9247 	{
9248 		// Show the client certificate
9249 		x = s.ClientX;
9250 	}
9251 	else
9252 	{
9253 		// Show the server certificate
9254 		x = s.ServerX;
9255 	}
9256 
9257 	cm->WindowCount++;
9258 	issuer = CmGetIssuer(x);
9259 	CertDlg(hWnd, x, issuer, true);
9260 	FreeX(issuer);
9261 	cm->WindowCount--;
9262 
9263 	CiFreeClientGetConnectionStatus(&s);
9264 }
9265 
9266 // Show the information of the status dialog
CmStatusDlgPrint(HWND hWnd,CM_STATUS * cmst)9267 void CmStatusDlgPrint(HWND hWnd, CM_STATUS *cmst)
9268 {
9269 	RPC_CLIENT_GET_CONNECTION_STATUS s;
9270 	LVB *b;
9271 	// Validate arguments
9272 	if (hWnd == NULL || cmst == NULL)
9273 	{
9274 		return;
9275 	}
9276 
9277 	// Get the latest information
9278 	Zero(&s, sizeof(s));
9279 	UniStrCpy(s.AccountName, sizeof(s.AccountName), cmst->AccountName);
9280 	if (CALL(hWnd, CcGetAccountStatus(cm->Client, &s)) == false)
9281 	{
9282 		Close(hWnd);
9283 		return;
9284 	}
9285 
9286 	if (s.Active == false)
9287 	{
9288 		// Disconnect
9289 		Close(hWnd);
9290 		return;
9291 	}
9292 
9293 	// Show the status in the list box in the status dialog
9294 	b = LvInsertStart();
9295 	CmPrintStatusToListView(b, &s);
9296 	LvInsertEnd(b, hWnd, L_STATUS);
9297 
9298 	LvAutoSize(hWnd, L_STATUS);
9299 
9300 	SetEnable(hWnd, B_POLICY, s.Connected);
9301 
9302 	SetEnable(hWnd, B_SERVER_CERT, s.ServerX != NULL);
9303 	SetEnable(hWnd, B_CLIENT_CERT, s.ClientX != NULL);
9304 
9305 	CiFreeClientGetConnectionStatus(&s);
9306 }
9307 
9308 // Show the status in the list box in the status dialog
CmPrintStatusToListView(LVB * b,RPC_CLIENT_GET_CONNECTION_STATUS * s)9309 void CmPrintStatusToListView(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s)
9310 {
9311 	CmPrintStatusToListViewEx(b, s, false);
9312 }
CmPrintStatusToListViewEx(LVB * b,RPC_CLIENT_GET_CONNECTION_STATUS * s,bool server_mode)9313 void CmPrintStatusToListViewEx(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode)
9314 {
9315 	wchar_t tmp[MAX_SIZE];
9316 	char str[MAX_SIZE];
9317 	char vv[128];
9318 	// Validate arguments
9319 	if (b == NULL || s == NULL)
9320 	{
9321 		return;
9322 	}
9323 
9324 	if (server_mode == false)
9325 	{
9326 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_ACCOUNT_NAME"), s->AccountName);
9327 
9328 		if (s->Connected == false)
9329 		{
9330 			wchar_t *st = _UU("CM_ST_CONNECTED_FALSE");
9331 			switch (s->SessionStatus)
9332 			{
9333 			case CLIENT_STATUS_CONNECTING:
9334 				st = _UU("CM_ST_CONNECTING");
9335 				break;
9336 			case CLIENT_STATUS_NEGOTIATION:
9337 				st = _UU("CM_ST_NEGOTIATION");
9338 				break;
9339 			case CLIENT_STATUS_AUTH:
9340 				st = _UU("CM_ST_AUTH");
9341 				break;
9342 			case CLIENT_STATUS_ESTABLISHED:
9343 				st = _UU("CM_ST_ESTABLISHED");
9344 				break;
9345 			case CLIENT_STATUS_RETRY:
9346 				st = _UU("CM_ST_RETRY");
9347 				break;
9348 			case CLIENT_STATUS_IDLE:
9349 				st = _UU("CM_ST_IDLE");
9350 				break;
9351 			}
9352 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTED"), st);
9353 		}
9354 		else
9355 		{
9356 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTED"), _UU("CM_ST_CONNECTED_TRUE"));
9357 		}
9358 	}
9359 
9360 	if (s->Connected)
9361 	{
9362 		if (s->VLanId == 0)
9363 		{
9364 			UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_NO_VLAN"));
9365 		}
9366 		else
9367 		{
9368 			UniToStru(tmp, s->VLanId);
9369 		}
9370 
9371 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_VLAN_ID"), tmp);
9372 
9373 		if (server_mode == false)
9374 		{
9375 			StrToUni(tmp, sizeof(tmp), s->ServerName);
9376 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_NAME"), tmp);
9377 
9378 			UniFormat(tmp, sizeof(tmp), _UU("CM_ST_PORT_TCP"), s->ServerPort);
9379 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_PORT"), tmp);
9380 		}
9381 
9382 		StrToUni(tmp, sizeof(tmp), s->ServerProductName);
9383 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_NAME"), tmp);
9384 
9385 		UniFormat(tmp, sizeof(tmp), L"%u.%02u", s->ServerProductVer / 100, s->ServerProductVer % 100);
9386 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_VER"), tmp);
9387 		UniFormat(tmp, sizeof(tmp), L"Build %u", s->ServerProductBuild);
9388 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SERVER_P_BUILD"), tmp);
9389 	}
9390 
9391 	GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->StartTime), NULL);
9392 	LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_START_TIME"), tmp);
9393 	GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->FirstConnectionEstablisiedTime), NULL);
9394 	LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_FIRST_ESTAB_TIME"), s->FirstConnectionEstablisiedTime == 0 ? _UU("CM_ST_NONE") : tmp);
9395 
9396 	if (s->Connected)
9397 	{
9398 		GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->CurrentConnectionEstablishTime), NULL);
9399 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CURR_ESTAB_TIME"), tmp);
9400 	}
9401 
9402 	if (server_mode == false)
9403 	{
9404 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_STR"), s->NumConnectionsEatablished);
9405 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_ESTABLISHED"), tmp);
9406 	}
9407 
9408 	if (s->Connected)
9409 	{
9410 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_HALF_CONNECTION"), s->HalfConnection ? _UU("CM_ST_HALF_TRUE") : _UU("CM_ST_HALF_FALSE"));
9411 
9412 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_QOS"), s->QoS ? _UU("CM_ST_QOS_TRUE") : _UU("CM_ST_QOS_FALSE"));
9413 
9414 		UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnections);
9415 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP"), tmp);
9416 
9417 		if (s->HalfConnection)
9418 		{
9419 			UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsUpload);
9420 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP_UPLOAD"), tmp);
9421 			UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsDownload);
9422 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_NUM_TCP_DOWNLOAD"), tmp);
9423 		}
9424 
9425 		UniFormat(tmp, sizeof(tmp), L"%u", s->MaxTcpConnections);
9426 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_MAX_TCP"), tmp);
9427 
9428 		if (s->UseEncrypt == false)
9429 		{
9430 			UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_FALSE"));
9431 		}
9432 		else
9433 		{
9434 			if (StrLen(s->CipherName) != 0)
9435 			{
9436 				UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE"), s->CipherName);
9437 			}
9438 			else
9439 			{
9440 				UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE2"));
9441 			}
9442 		}
9443 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_USE_ENCRYPT"), tmp);
9444 
9445 		if (s->UseCompress)
9446 		{
9447 			UINT percent = 0;
9448 			if ((s->TotalRecvSize + s->TotalSendSize) > 0)
9449 			{
9450 				percent = (UINT)((UINT64)100 - (UINT64)(s->TotalRecvSizeReal + s->TotalSendSizeReal) * (UINT64)100 /
9451 					(s->TotalRecvSize + s->TotalSendSize));
9452 				percent = MAKESURE(percent, 0, 100);
9453 			}
9454 
9455 			UniFormat(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_TRUE"), percent);
9456 		}
9457 		else
9458 		{
9459 			UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_FALSE"));
9460 		}
9461 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_USE_COMPRESS"), tmp);
9462 
9463 		if (IsEmptyStr(s->UnderlayProtocol) == false)
9464 		{
9465 			StrToUni(tmp, sizeof(tmp), s->UnderlayProtocol);
9466 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UNDERLAY_PROTOCOL"), tmp);
9467 		}
9468 
9469 		if (IsEmptyStr(s->ProtocolDetails) == false)
9470 		{
9471 			StrToUni(tmp, sizeof(tmp), s->ProtocolDetails);
9472 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_PROTOCOL_DETAILS"), tmp);
9473 		}
9474 
9475 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UDP_ACCEL_ENABLED"), (s->IsUdpAccelerationEnabled ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
9476 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UDP_ACCEL_USING"), (s->IsUsingUdpAcceleration ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
9477 
9478 		StrToUni(tmp, sizeof(tmp), s->SessionName);
9479 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SESSION_NAME"), tmp);
9480 
9481 		StrToUni(tmp, sizeof(tmp), s->ConnectionName);
9482 		if (UniStrCmpi(tmp, L"INITING") != 0)
9483 		{
9484 			LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_CONNECTION_NAME"), tmp);
9485 		}
9486 
9487 		BinToStr(str, sizeof(str), s->SessionKey, sizeof(s->SessionKey));
9488 		StrToUni(tmp, sizeof(tmp), str);
9489 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SESSION_KEY"), tmp);
9490 
9491 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_BRIDGE_MODE"), s->IsBridgeMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));
9492 
9493 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_MONITOR_MODE"), s->IsMonitorMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));
9494 
9495 		ToStr3(vv, sizeof(vv), s->TotalSendSize);
9496 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
9497 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_SIZE"), tmp);
9498 
9499 		ToStr3(vv, sizeof(vv), s->TotalRecvSize);
9500 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
9501 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_SIZE"), tmp);
9502 
9503 		ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastCount);
9504 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
9505 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_UCAST_NUM"), tmp);
9506 
9507 		ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastBytes);
9508 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
9509 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_UCAST_SIZE"), tmp);
9510 
9511 		ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastCount);
9512 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
9513 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_BCAST_NUM"), tmp);
9514 
9515 		ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastBytes);
9516 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
9517 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_SEND_BCAST_SIZE"), tmp);
9518 
9519 		ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastCount);
9520 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
9521 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_UCAST_NUM"), tmp);
9522 
9523 		ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastBytes);
9524 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
9525 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_UCAST_SIZE"), tmp);
9526 
9527 		ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastCount);
9528 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);
9529 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_BCAST_NUM"), tmp);
9530 
9531 		ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastBytes);
9532 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);
9533 		LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_RECV_BCAST_SIZE"), tmp);
9534 	}
9535 }
9536 
9537 // Status dialog procedure
CmStatusDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)9538 UINT CmStatusDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
9539 {
9540 	wchar_t tmp[MAX_SIZE];
9541 	CM_STATUS *s = (CM_STATUS *)param;
9542 	// Validate arguments
9543 	if (hWnd == NULL)
9544 	{
9545 		return 0;
9546 	}
9547 
9548 	switch (msg)
9549 	{
9550 	case WM_INITDIALOG:
9551 		SetIcon(hWnd, 0, ICO_TOWER);
9552 		UniFormat(tmp, sizeof(tmp), _UU("CM_ST_TITLE"), s->AccountName);
9553 		SetText(hWnd, 0, tmp);
9554 		FormatText(hWnd, S_TITLE, s->AccountName);
9555 		DlgFont(hWnd, S_TITLE, 0, 1);
9556 
9557 		Add(cm->StatusWindowList, hWnd);
9558 
9559 		SetTimer(hWnd, 1, 500, NULL);
9560 
9561 		LvInitEx(hWnd, L_STATUS, true);
9562 		ListView_SetImageList(DlgItem(hWnd, L_STATUS), NULL, LVSIL_NORMAL);
9563 		ListView_SetImageList(DlgItem(hWnd, L_STATUS), NULL, LVSIL_SMALL);
9564 		LvInsertColumn(hWnd, L_STATUS, 0, _UU("CM_ST_COLUMN_1"), 160);
9565 		LvInsertColumn(hWnd, L_STATUS, 1, _UU("CM_ST_COLUMN_2"), 270);
9566 
9567 		CmStatusDlgPrint(hWnd, s);
9568 
9569 		break;
9570 	case WM_TIMER:
9571 		switch (wParam)
9572 		{
9573 		case 1:
9574 			KillTimer(hWnd, 1);
9575 			CmStatusDlgPrint(hWnd, s);
9576 			SetTimer(hWnd, 1, 500, NULL);
9577 			break;
9578 		}
9579 		break;
9580 	case WM_COMMAND:
9581 		switch (wParam)
9582 		{
9583 		case IDOK:
9584 		case IDCANCEL:
9585 			// Close
9586 			Close(hWnd);
9587 			break;
9588 		case B_POLICY:
9589 			// Show the policy
9590 			CmPolicyDlg(hWnd, s);
9591 			break;
9592 		case B_SERVER_CERT:
9593 			CmStatusDlgPrintCert(hWnd, s, true);
9594 			break;
9595 		case B_CLIENT_CERT:
9596 			CmStatusDlgPrintCert(hWnd, s, false);
9597 			break;
9598 		}
9599 		break;
9600 	case WM_CLOSE:
9601 		Delete(cm->StatusWindowList, hWnd);
9602 		if (s->hWndPolicy != NULL)
9603 		{
9604 			EndDialog(s->hWndPolicy, false);
9605 			s->hWndPolicy = NULL;
9606 		}
9607 		EndDialog(hWnd, false);
9608 		break;
9609 	}
9610 
9611 	return 0;
9612 }
9613 
9614 // Show the status dialog
CmStatusDlg(HWND hWnd,wchar_t * account_name)9615 void CmStatusDlg(HWND hWnd, wchar_t *account_name)
9616 {
9617 	CM_STATUS *s;
9618 	// Validate arguments
9619 	if (hWnd == NULL || account_name == NULL)
9620 	{
9621 		return;
9622 	}
9623 
9624 	s = ZeroMalloc(sizeof(CM_STATUS));
9625 	UniStrCpy(s->AccountName, sizeof(s->AccountName), account_name);
9626 
9627 	Dialog(hWnd, D_CONNECTION_STATUS, CmStatusDlgProc, s);
9628 
9629 	Free(s);
9630 }
9631 
9632 // Show the status
CmStatus(HWND hWnd,wchar_t * account_name)9633 void CmStatus(HWND hWnd, wchar_t *account_name)
9634 {
9635 	UINT i;
9636 	wchar_t tmp[MAX_SIZE];
9637 	// Validate arguments
9638 	if (hWnd == NULL || account_name == NULL)
9639 	{
9640 		return;
9641 	}
9642 
9643 	UniFormat(tmp, sizeof(tmp), _UU("CM_ST_TITLE"), account_name);
9644 
9645 	for (i = 0;i < LIST_NUM(cm->StatusWindowList);i++)
9646 	{
9647 		HWND h = LIST_DATA(cm->StatusWindowList, i);
9648 		if (h != NULL)
9649 		{
9650 			wchar_t tmp2[MAX_SIZE];
9651 			if (GetTxt(h, 0, tmp2, sizeof(tmp2)))
9652 			{
9653 				if (UniStrCmpi(tmp2, tmp) == 0)
9654 				{
9655 					SetActiveWindow(h);
9656 					return;
9657 				}
9658 			}
9659 		}
9660 	}
9661 
9662 	CmStatusDlg(hWnd, account_name);
9663 }
9664 
9665 // Delete
CmDeleteAccount(HWND hWnd,wchar_t * account_name)9666 void CmDeleteAccount(HWND hWnd, wchar_t *account_name)
9667 {
9668 	RPC_CLIENT_DELETE_ACCOUNT c;
9669 	// Validate arguments
9670 	if (hWnd == NULL || account_name == NULL)
9671 	{
9672 		return;
9673 	}
9674 	Zero(&c, sizeof(c));
9675 	UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
9676 
9677 	CmVoice("delete_config_1");
9678 	if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DELETE_ACCOUNT_MSG"), account_name)
9679 		== IDNO)
9680 	{
9681 		return;
9682 	}
9683 
9684 	CALL(hWnd, CcDeleteAccount(cm->Client, &c));
9685 	CmVoice("delete_config_2");
9686 }
9687 
9688 // Disconnect
CmDisconnect(HWND hWnd,wchar_t * account_name)9689 void CmDisconnect(HWND hWnd, wchar_t *account_name)
9690 {
9691 	RPC_CLIENT_CONNECT c;
9692 	// Validate arguments
9693 	if (hWnd == NULL || account_name == NULL)
9694 	{
9695 		return;
9696 	}
9697 
9698 	Zero(&c, sizeof(c));
9699 	UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
9700 
9701 	cm->PositiveDisconnectFlag = true;
9702 
9703 	CALL(hWnd, CcDisconnect(cm->Client, &c));
9704 }
9705 
9706 // Show the promotional window
SmShowPublicVpnServerHtml(HWND hWnd)9707 void SmShowPublicVpnServerHtml(HWND hWnd)
9708 {
9709 	char *langstr = _SS("LANGSTR");
9710 
9711 	if(StrCmpi(langstr, "Japanese") == 0)
9712 	{
9713 		ShowHtml(hWnd, PUBLIC_SERVER_HTML, PUBLIC_SERVER_TAG);
9714 	}
9715 	else
9716 	{
9717 		ShowHtml(hWnd, PUBLIC_SERVER_HTML_EN, PUBLIC_SERVER_TAG);
9718 	}
9719 }
9720 
9721 // Connection
CmConnect(HWND hWnd,wchar_t * account_name)9722 void CmConnect(HWND hWnd, wchar_t *account_name)
9723 {
9724 	RPC_CLIENT_CONNECT c;
9725 	UINT i;
9726 	// Validate arguments
9727 	if (hWnd == NULL || account_name == NULL)
9728 	{
9729 		return;
9730 	}
9731 
9732 	if (IsEnable(hWnd, 0) == false)
9733 	{
9734 		return;
9735 	}
9736 
9737 	if (hWnd == cm->hMainWnd)
9738 	{
9739 		if (LvNum(hWnd, L_VLAN) == 0 && cm->Client->Win9x)
9740 		{
9741 			if (MsgBox(hWnd, MB_ICONINFORMATION | MB_YESNO, _UU("CM_NO_VLAN_2")) == IDNO)
9742 			{
9743 				return;
9744 			}
9745 			else
9746 			{
9747 				if (cm->server_name == NULL || cm->Client->Unix)
9748 				{
9749 					Command(hWnd, CMD_NEW_VLAN);
9750 					return;
9751 				}
9752 				else
9753 				{
9754 					MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_VLAN_REMOTE_ERROR"));
9755 				}
9756 				return;
9757 			}
9758 		}
9759 	}
9760 
9761 	// (If necessary) display a warning
9762 	if (CmWarningDesktop(hWnd, account_name) == false)
9763 	{
9764 		return;
9765 	}
9766 
9767 	if (cm->server_name == NULL)
9768 	{
9769 		if (cm->BadProcessChecked == false)
9770 		{
9771 			cm->BadProcessChecked = true;
9772 
9773 			CheckBadProcesses(hWnd);
9774 		}
9775 	}
9776 
9777 	if (cm->server_name == NULL)
9778 	{
9779 		// Check the Windows version
9780 		RPC_WINVER winver;
9781 		wchar_t winver_msg_client[3800];
9782 
9783 		GetWinVer(&winver);
9784 		Zero(winver_msg_client, sizeof(winver_msg_client));
9785 
9786 		if (IsSupportedWinVer(&winver) == false)
9787 		{
9788 			SYSTEMTIME st;
9789 
9790 			LocalTime(&st);
9791 
9792 			UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
9793 				_UU("WINVER_ERROR_PC_LOCAL"),
9794 				winver.Title,
9795 				_UU("WINVER_ERROR_VPNCLIENT"),
9796 				SUPPORTED_WINDOWS_LIST,
9797 				_UU("WINVER_ERROR_PC_LOCAL"),
9798 				_UU("WINVER_ERROR_VPNCLIENT"),
9799 				_UU("WINVER_ERROR_VPNCLIENT"),
9800 				_UU("WINVER_ERROR_VPNCLIENT"),
9801 				st.wYear, st.wMonth);
9802 		}
9803 
9804 		if (UniIsEmptyStr(winver_msg_client) == false)
9805 		{
9806 			OnceMsgEx(hWnd, _UU("WINVER_TITLE"), winver_msg_client,
9807 				true, ICO_WARNING, NULL);
9808 		}
9809 	}
9810 
9811 	i = LvSearchStr(hWnd, L_ACCOUNT, 0, account_name);
9812 	if (i != INFINITE)
9813 	{
9814 		wchar_t *tmp = LvGetStr(hWnd, L_ACCOUNT, i, 2);
9815 		if (tmp != NULL)
9816 		{
9817 			wchar_t tag[MAX_SIZE];
9818 			StrToUni(tag, sizeof(tag), PUBLIC_SERVER_NAME);
9819 
9820 			if (UniSearchStrEx(tmp, tag, 0, false) != INFINITE)
9821 			{
9822 				SmShowPublicVpnServerHtml(hWnd);
9823 			}
9824 
9825 			Free(tmp);
9826 		}
9827 	}
9828 
9829 	if (cm->CheckedAndShowedAdminPackMessage == false)
9830 	{
9831 		cm->CheckedAndShowedAdminPackMessage = true;
9832 		//CmCheckAndShowAdminPackTrialVersionNoticeMessage(NULL);
9833 	}
9834 
9835 	Zero(&c, sizeof(c));
9836 	UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
9837 
9838 	CmSetForegroundProcessToCnService();
9839 
9840 	if (CALL(hWnd, CcConnect(cm->Client, &c)))
9841 	{
9842 		cm->ConnectStartedFlag = true;
9843 	}
9844 }
9845 
9846 // Determine whether to bold the specified menu item
CmIsBold(UINT id)9847 bool CmIsBold(UINT id)
9848 {
9849 	return false;
9850 }
9851 
9852 // Determine whether to enable the specified menu item
CmIsEnabled(HWND hWnd,UINT id)9853 bool CmIsEnabled(HWND hWnd, UINT id)
9854 {
9855 	UINT index;
9856 	wchar_t *name;
9857 	bool locked = false;
9858 	// Validate arguments
9859 	if (hWnd == NULL)
9860 	{
9861 		return false;
9862 	}
9863 
9864 	locked = cm->CmSetting.LockMode;
9865 
9866 	if (locked)
9867 	{
9868 		switch (id)
9869 		{
9870 		case CMD_NEW:
9871 		case CMD_CLONE:
9872 		case CMD_IMPORT_ACCOUNT:
9873 		case CMD_DELETE:
9874 		case CMD_OPTION:
9875 		case CMD_VOIDE_NONE:
9876 		case CMD_VOICE_NORMAL:
9877 		case CMD_VOICE_ODD:
9878 		case CMD_STARTUP:
9879 		case CMD_NOSTARTUP:
9880 		case CMD_TRAFFIC:
9881 		case CMD_MMCSS:
9882 			return false;
9883 		case CMD_NEW_VLAN:
9884 		case CMD_ENABLE_VLAN:
9885 		case CMD_DISABLE_VLAN:
9886 		case CMD_DELETE_VLAN:
9887 		case CMD_REINSTALL:
9888 		case CMD_WINNET:
9889 			if (cm->CmEasyModeSupported)
9890 			{
9891 				return false;
9892 			}
9893 		}
9894 	}
9895 
9896 	switch (id)
9897 	{
9898 	case CMD_LANGUAGE:
9899 		return MsIsNt();
9900 	case CMD_SHOWPORT:
9901 	case CMD_GRID:
9902 		if (cm->IconView)
9903 		{
9904 			return false;
9905 		}
9906 		return true;
9907 	case CMD_MMCSS:
9908 		if (MsIsVista() == false || IsEmptyStr(cm->server_name) == false)
9909 		{
9910 			return false;
9911 		}
9912 		if (OS_IS_SERVER(GetOsType()))
9913 		{
9914 			return false;
9915 		}
9916 		return true;
9917 	case CMD_TRAYICON:
9918 	case CMD_TRAFFIC:
9919 		return (cm->server_name == NULL);
9920 	case CMD_NETIF:
9921 		if (MsIsNt() == false)
9922 		{
9923 			return false;
9924 		}
9925 		return (cm->server_name == NULL);
9926 	case CMD_CM_SETTING:
9927 		return cm->CmSettingSupported;
9928 	case CMD_CONNECT:
9929 	case CMD_DISCONNECT:
9930 	case CMD_STATUS:
9931 	case CMD_RENAME:
9932 	case CMD_DELETE:
9933 		if (LvIsMultiMasked(hWnd, L_ACCOUNT))
9934 		{
9935 			return false;
9936 		}
9937 		if (LvIsSelected(hWnd, L_ACCOUNT) == false)
9938 		{
9939 			return false;
9940 		}
9941 		else
9942 		{
9943 			// Determine whether the selected account is under connecting
9944 			UINT i = LvGetSelected(hWnd, L_ACCOUNT);
9945 			wchar_t *str = LvGetStr(hWnd, L_ACCOUNT, i, 1);
9946 			wchar_t *name = LvGetStr(hWnd, L_ACCOUNT, i, 0);
9947 			bool is_connected = false;
9948 			if (str != NULL)
9949 			{
9950 				if (UniStrCmpi(str, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(str, _UU("CM_ACCOUNT_CONNECTING")) == 0)
9951 				{
9952 					is_connected = true;
9953 				}
9954 				Free(str);
9955 			}
9956 			if (name != NULL)
9957 			{
9958 				if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0)
9959 				{
9960 					Free(name);
9961 					return false;
9962 				}
9963 				Free(name);
9964 			}
9965 			if (id == CMD_CONNECT || id == CMD_RENAME || id == CMD_DELETE)
9966 			{
9967 				return !is_connected;
9968 			}
9969 			else
9970 			{
9971 				return is_connected;
9972 			}
9973 		}
9974 		break;
9975 	case CMD_DISCONNECT_ALL:
9976 		if (CmGetNumConnected(hWnd) == 0)
9977 		{
9978 			return false;
9979 		}
9980 		else
9981 		{
9982 			return true;
9983 		}
9984 	case CMD_SHORTCUT:
9985 		// Create a shortcut
9986 		if (cm->Client->Rpc->Sock->RemoteIP.addr[0] != 127)
9987 		{
9988 			return false;
9989 		}
9990 	case CMD_EXPORT_ACCOUNT:
9991 		if (LvIsMultiMasked(hWnd, L_ACCOUNT))
9992 		{
9993 			return false;
9994 		}
9995 		name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
9996 		if (name != NULL)
9997 		{
9998 			if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0
9999 				)
10000 			{
10001 				Free(name);
10002 				return false;
10003 			}
10004 			Free(name);
10005 		}
10006 		return LvIsSelected(hWnd, L_ACCOUNT);
10007 	case CMD_CLONE:
10008 		if (LvIsMultiMasked(hWnd, L_ACCOUNT))
10009 		{
10010 			return false;
10011 		}
10012 		name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
10013 		if (name != NULL)
10014 		{
10015 			if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0
10016 				)
10017 			{
10018 				Free(name);
10019 				return false;
10020 			}
10021 			Free(name);
10022 		}
10023 		return LvIsSelected(hWnd, L_ACCOUNT);
10024 	case CMD_STARTUP:
10025 	case CMD_NOSTARTUP:
10026 		name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
10027 		if (name != NULL)
10028 		{
10029 			if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0
10030 				)
10031 			{
10032 				Free(name);
10033 				return false;
10034 			}
10035 			Free(name);
10036 		}
10037 		if (LvIsMultiMasked(hWnd, L_ACCOUNT))
10038 		{
10039 			return false;
10040 		}
10041 		if (LvIsSelected(hWnd, L_ACCOUNT) == false)
10042 		{
10043 			return false;
10044 		}
10045 		else
10046 		{
10047 			// Determine whether the selected account is a startup account
10048 			UINT i = LvGetSelected(hWnd, L_ACCOUNT);
10049 			bool is_startup = (bool)LvGetParam(hWnd, L_ACCOUNT, i);
10050 			if (id == CMD_STARTUP)
10051 			{
10052 				return !is_startup;
10053 			}
10054 			else
10055 			{
10056 				return is_startup;
10057 			}
10058 		}
10059 		break;
10060 	case CMD_NEW_VLAN:
10061 		if (cm->Client->Unix == false && cm->Client->Win9x == false)
10062 		{
10063 			if (cm->server_name != NULL)
10064 			{
10065 				return false;
10066 			}
10067 		}
10068 		if (cm->Client->Win9x)
10069 		{
10070 			if (LvNum(hWnd, L_VLAN) >= 1)
10071 			{
10072 				// You can not install two or more virtual LAN cards in Win9x
10073 				return false;
10074 			}
10075 		}
10076 		break;
10077 	case CMD_PROPERTY:
10078 		name = LvGetSelectedStr(hWnd, L_ACCOUNT, 0);
10079 		if (name != NULL)
10080 		{
10081 			if (UniStrCmpi(name, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(name, _UU("CM_VGC_LINK")) == 0)
10082 			{
10083 				Free(name);
10084 				return false;
10085 			}
10086 			Free(name);
10087 		}
10088 		if (LvIsMultiMasked(hWnd, L_ACCOUNT))
10089 		{
10090 			return false;
10091 		}
10092 		return LvIsSelected(hWnd, L_ACCOUNT);
10093 	case CMD_DELETE_VLAN:
10094 		if (LvIsMultiMasked(hWnd, L_VLAN))
10095 		{
10096 			return false;
10097 		}
10098 		return LvIsSelected(hWnd, L_VLAN);
10099 	case CMD_ENABLE_VLAN:
10100 		if (cm->Client->Win9x)
10101 		{
10102 			return false;
10103 		}
10104 		if (LvIsMultiMasked(hWnd, L_VLAN))
10105 		{
10106 			return false;
10107 		}
10108 		index = LvGetSelected(hWnd, L_VLAN);
10109 		if (index == INFINITE)
10110 		{
10111 			return false;
10112 		}
10113 		else
10114 		{
10115 			wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 1);
10116 			if (s != NULL)
10117 			{
10118 				if (UniStrCmpi(s, _UU("CM_VLAN_DISABLED")) == 0)
10119 				{
10120 					Free(s);
10121 					return true;
10122 				}
10123 				Free(s);
10124 			}
10125 			return false;
10126 		}
10127 		break;
10128 	case CMD_DISABLE_VLAN:
10129 		if (cm->Client->Win9x)
10130 		{
10131 			return false;
10132 		}
10133 		if (LvIsMultiMasked(hWnd, L_VLAN))
10134 		{
10135 			return false;
10136 		}
10137 		index = LvGetSelected(hWnd, L_VLAN);
10138 		if (index == INFINITE)
10139 		{
10140 			return false;
10141 		}
10142 		else
10143 		{
10144 			wchar_t *s = LvGetStr(hWnd, L_VLAN, index, 1);
10145 			if (s != NULL)
10146 			{
10147 				if (UniStrCmpi(s, _UU("CM_VLAN_ENABLED")) == 0)
10148 				{
10149 					Free(s);
10150 					return true;
10151 				}
10152 				Free(s);
10153 			}
10154 			return false;
10155 		}
10156 		break;
10157 	case CMD_REINSTALL:
10158 		if (cm->server_name != NULL)
10159 		{
10160 			return false;
10161 		}
10162 		if (cm->Client->Win9x || cm->Client->Unix)
10163 		{
10164 			// Upgrading the virtual LAN card on a UNIX system or Win9x is unavailable
10165 			return false;
10166 		}
10167 		if (LvIsMultiMasked(hWnd, L_VLAN))
10168 		{
10169 			return false;
10170 		}
10171 		return LvIsSelected(hWnd, L_VLAN);
10172 	case CMD_WINNET:
10173 		{
10174 			UINT os_type = GetOsInfo()->OsType;
10175 
10176 			if (OS_IS_WINDOWS_NT(os_type) && GET_KETA(os_type, 100) >= 2)
10177 			{
10178 				if (cm->server_name != NULL)
10179 				{
10180 					return false;
10181 				}
10182 
10183 				return true;
10184 			}
10185 			else
10186 			{
10187 				return false;
10188 			}
10189 		}
10190 		break;
10191 	case CMD_EXIT:
10192 		return cm->TrayInited;
10193 	}
10194 	return true;
10195 }
10196 
10197 // Convert a VLAN device name to the display name
CmVLanNameToPrintName(char * str,UINT size,char * name)10198 void CmVLanNameToPrintName(char *str, UINT size, char *name)
10199 {
10200 	// Validate arguments
10201 	if (str == NULL || name == NULL)
10202 	{
10203 		return;
10204 	}
10205 
10206 	Format(str, size, VLAN_ADAPTER_NAME_TAG, name);
10207 }
10208 
10209 // Convert a display name to a VLAN device name
CmPrintNameToVLanName(char * name,UINT size,char * str)10210 bool CmPrintNameToVLanName(char *name, UINT size, char *str)
10211 {
10212 	// Validate arguments
10213 	if (name == NULL || str == NULL)
10214 	{
10215 		return false;
10216 	}
10217 
10218 	if (StartWith(str, VLAN_ADAPTER_NAME))
10219 	{
10220 		if (StrLen(str) < (StrLen(VLAN_ADAPTER_NAME) + 3))
10221 		{
10222 			return false;
10223 		}
10224 
10225 		StrCpy(name, size, str + StrLen(VLAN_ADAPTER_NAME) + 3);
10226 
10227 		return true;
10228 	}
10229 
10230 	if (StartWith(str, VLAN_ADAPTER_NAME_OLD))
10231 	{
10232 		if (StrLen(str) < (StrLen(VLAN_ADAPTER_NAME_OLD) + 3))
10233 		{
10234 			return false;
10235 		}
10236 
10237 		StrCpy(name, size, str + StrLen(VLAN_ADAPTER_NAME_OLD) + 3);
10238 
10239 		return true;
10240 	}
10241 
10242 	return false;
10243 }
10244 
10245 // Initialize the account list
CmInitAccountList(HWND hWnd)10246 void CmInitAccountList(HWND hWnd)
10247 {
10248 	CmInitAccountListEx(hWnd, false);
10249 }
CmInitAccountListEx(HWND hWnd,bool easy)10250 void CmInitAccountListEx(HWND hWnd, bool easy)
10251 {
10252 	UINT width[5];
10253 	BUF *b;
10254 	// Validate arguments
10255 	if (hWnd == NULL)
10256 	{
10257 		return;
10258 	}
10259 
10260 	// Read the setting
10261 	b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "AccountListColumnWidth");
10262 	if ((b != NULL) && (b->Size == sizeof(width)))
10263 	{
10264 		Copy(width, b->Buf, sizeof(width));
10265 	}
10266 	else if ((b != NULL) && (b->Size == (sizeof(width) - sizeof(UINT))))
10267 	{
10268 		// Migrating from previous versions
10269 		Zero(width, sizeof(width));
10270 		Copy(width, b->Buf, sizeof(width) - sizeof(UINT));
10271 		width[4] = width[3];
10272 		width[3] = 0;
10273 	}
10274 	else
10275 	{
10276 		Zero(width, sizeof(width));
10277 	}
10278 	FreeBuf(b);
10279 
10280 	LvInitEx2(hWnd, L_ACCOUNT, false, easy);
10281 
10282 //	LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_TRACKSELECT);
10283 
10284 	// Initialize the column
10285 	if (easy == false)
10286 	{
10287 		LvInsertColumn(hWnd, L_ACCOUNT, 0, _UU("CM_ACCOUNT_COLUMN_1"), width[0] == 0 ? 215 : width[0]);
10288 		LvInsertColumn(hWnd, L_ACCOUNT, 1, _UU("CM_ACCOUNT_COLUMN_2"), width[1] == 0 ? 80 : width[1]);
10289 		LvInsertColumn(hWnd, L_ACCOUNT, 2, _UU("CM_ACCOUNT_COLUMN_3"), width[2] == 0 ? 220 : width[2]);
10290 		LvInsertColumn(hWnd, L_ACCOUNT, 3, _UU("CM_ACCOUNT_COLUMN_3_2"), width[3] == 0 ? 90 : width[3]);
10291 		LvInsertColumn(hWnd, L_ACCOUNT, 4, _UU("CM_ACCOUNT_COLUMN_4"), (width[4] == 0 || width[4] == 250) ? 120 : width[4]);
10292 	}
10293 	else
10294 	{
10295 		LvInsertColumn(hWnd, L_ACCOUNT, 0, _UU("CM_ACCOUNT_COLUMN_1"), 345);
10296 		LvInsertColumn(hWnd, L_ACCOUNT, 1, _UU("CM_ACCOUNT_COLUMN_2"), 140);
10297 		LvInsertColumn(hWnd, L_ACCOUNT, 2, _UU("CM_ACCOUNT_COLUMN_3"), 0);
10298 		LvInsertColumn(hWnd, L_ACCOUNT, 3, _UU("CM_ACCOUNT_COLUMN_3_2"), 0);
10299 		LvInsertColumn(hWnd, L_ACCOUNT, 4, _UU("CM_ACCOUNT_COLUMN_4"), 0);
10300 	}
10301 }
10302 
10303 // Release the account list
CmSaveAccountListPos(HWND hWnd)10304 void CmSaveAccountListPos(HWND hWnd)
10305 {
10306 	UINT width[5];
10307 	UINT i;
10308 	// Validate arguments
10309 	if (hWnd == NULL)
10310 	{
10311 		return;
10312 	}
10313 
10314 	for (i = 0;i < 5;i++)
10315 	{
10316 		width[i] = LvGetColumnWidth(hWnd, L_ACCOUNT, i);
10317 	}
10318 
10319 	MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "AccountListColumnWidth", width, sizeof(width));
10320 }
10321 
10322 // Initialize the VLAN list
CmInitVLanList(HWND hWnd)10323 void CmInitVLanList(HWND hWnd)
10324 {
10325 	UINT width[4];
10326 	BUF *b;
10327 	// Validate arguments
10328 	if (hWnd == NULL)
10329 	{
10330 		return;
10331 	}
10332 
10333 	// Read the setting
10334 	b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "VLanListColumnWidth");
10335 	if ((b != NULL) && (b->Size == sizeof(width)))
10336 	{
10337 		Copy(width, b->Buf, sizeof(width));
10338 	}
10339 	else
10340 	{
10341 		Zero(width, sizeof(width));
10342 	}
10343 	FreeBuf(b);
10344 
10345 	LvInit(hWnd, L_VLAN);
10346 
10347 //	LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_TRACKSELECT);
10348 
10349 	// Initialize the column
10350 	LvInsertColumn(hWnd, L_VLAN, 0, _UU("CM_VLAN_COLUMN_1"), width[0] == 0 ? 310 : width[0]);
10351 	LvInsertColumn(hWnd, L_VLAN, 1, _UU("CM_VLAN_COLUMN_2"), width[1] == 0 ? 120 : width[1]);
10352 	LvInsertColumn(hWnd, L_VLAN, 2, _UU("CM_VLAN_COLUMN_3"), width[2] == 0 ? 175 : width[2]);
10353 	LvInsertColumn(hWnd, L_VLAN, 3, _UU("CM_VLAN_COLUMN_4"), width[3] == 0 ? 120 : width[3]);
10354 }
10355 
10356 // Release the VLAN list
CmSaveVLanListPos(HWND hWnd)10357 void CmSaveVLanListPos(HWND hWnd)
10358 {
10359 	UINT width[4];
10360 	UINT i;
10361 	// Validate arguments
10362 	if (hWnd == NULL)
10363 	{
10364 		return;
10365 	}
10366 
10367 	for (i = 0;i < 4;i++)
10368 	{
10369 		width[i] = LvGetColumnWidth(hWnd, L_VLAN, i);
10370 	}
10371 
10372 	MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "VLanListColumnWidth", width, sizeof(width));
10373 }
10374 
10375 // Update the account list
CmRefreshAccountList(HWND hWnd)10376 void CmRefreshAccountList(HWND hWnd)
10377 {
10378 	CmRefreshAccountListEx(hWnd, false);
10379 	CmRefreshEasy();
10380 }
CmRefreshAccountListEx(HWND hWnd,bool easy)10381 void CmRefreshAccountListEx(HWND hWnd, bool easy)
10382 {
10383 	CmRefreshAccountListEx2(hWnd, easy, false);
10384 }
CmRefreshAccountListEx2(HWND hWnd,bool easy,bool style_changed)10385 void CmRefreshAccountListEx2(HWND hWnd, bool easy, bool style_changed)
10386 {
10387 	UINT num = 0;
10388 	RPC_CLIENT_ENUM_ACCOUNT a;
10389 	UINT num_connecting = 0, num_connected = 0;
10390 	wchar_t tmp[MAX_SIZE];
10391 	wchar_t new_inserted_item[MAX_ACCOUNT_NAME_LEN + 1];
10392 	bool select_new_insteted_item = true;
10393 	// Validate arguments
10394 	if (hWnd == NULL)
10395 	{
10396 		return;
10397 	}
10398 
10399 	// Switching of icon / detail view
10400 	LvSetView(hWnd, L_ACCOUNT, cm->IconView == false || easy);
10401 
10402 	// Show grid
10403 	if (cm->ShowGrid || easy)
10404 	{
10405 		LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_GRIDLINES);
10406 	}
10407 	else
10408 	{
10409 		LvRemoveStyle(hWnd, L_ACCOUNT, LVS_EX_GRIDLINES);
10410 	}
10411 
10412 	if (style_changed)
10413 	{
10414 		// Change the font
10415 		if (easy == false)
10416 		{
10417 			if (cm->VistaStyle)
10418 			{
10419 				SetFontMeiryo(hWnd, L_ACCOUNT, 9);
10420 			}
10421 			else
10422 			{
10423 				SetFontDefault(hWnd, L_ACCOUNT);
10424 			}
10425 
10426 			if (cm->VistaStyle && (cm->IconView == false))
10427 			{
10428 				LvSetStyle(hWnd, L_ACCOUNT, LVS_EX_FULLROWSELECT);
10429 			}
10430 			else
10431 			{
10432 				LvRemoveStyle(hWnd, L_ACCOUNT, LVS_EX_FULLROWSELECT);
10433 			}
10434 		}
10435 	}
10436 
10437 	Zero(new_inserted_item, sizeof(new_inserted_item));
10438 
10439 	if (LvNum(hWnd, L_ACCOUNT) == 0)
10440 	{
10441 		select_new_insteted_item = false;
10442 	}
10443 
10444 	// Enumerate the account list
10445 	if (CALL(hWnd, CcEnumAccount(cm->Client, &a)))
10446 	{
10447 		UINT i;
10448 		LVB *b = LvInsertStart();
10449 
10450 		if (cm->CmSetting.LockMode == false && (easy == false))
10451 		{
10452 			// Creating a new connection
10453 			LvInsertAdd(b, ICO_NEW, NULL, 4, _UU("CM_NEW_ICON"), L"", L"", L"");
10454 
10455 			if (cm->Client->IsVgcSupported)
10456 			{
10457 				// VPN Gate
10458 				LvInsertAdd(b, ICO_RESEARCH, NULL, 4, _UU("CM_VGC_ICON"), L"", L"", L"");
10459 			}
10460 			else if (cm->Client->ShowVgcLink)
10461 			{
10462 				// VPN Gate Link
10463 				LvInsertAdd(b, ICO_INTERNET, NULL, 4, _UU("CM_VGC_LINK"), L"", L"", L"");
10464 			}
10465 		}
10466 
10467 		for (i = 0;i < a.NumItem;i++)
10468 		{
10469 			RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = a.Items[i];
10470 			UINT icon;
10471 			wchar_t tmp[MAX_SIZE];
10472 			wchar_t tmp2[MAX_SIZE];
10473 			char tmp3[MAX_SIZE];
10474 			wchar_t tmp4[MAX_SIZE];
10475 			IP ip;
10476 			char ip_str[MAX_SIZE];
10477 
10478 			// Special treatment in the case of IPv6 address
10479 			if (StrToIP6(&ip, t->ServerName) && StartWith(t->ServerName, "[") == false)
10480 			{
10481 				Format(ip_str, sizeof(ip_str),
10482 					"[%s]", t->ServerName);
10483 			}
10484 			else
10485 			{
10486 				StrCpy(ip_str, sizeof(ip_str), t->ServerName);
10487 			}
10488 
10489 			// Determine the icon
10490 			if (t->Active == false)
10491 			{
10492 				if (t->StartupAccount == false)
10493 				{
10494 					icon = ICO_SERVER_OFFLINE;
10495 				}
10496 				else
10497 				{
10498 					icon = ICO_SERVER_OFFLINE_EX;
10499 				}
10500 			}
10501 			else
10502 			{
10503 				num++;
10504 				if (t->StartupAccount == false)
10505 				{
10506 					icon = ICO_SERVER_ONLINE;
10507 				}
10508 				else
10509 				{
10510 					icon = ICO_SERVER_ONLINE_EX;
10511 				}
10512 			}
10513 
10514 			// Adding
10515 			if (easy == false)
10516 			{
10517 				//CmVLanNameToPrintName(tmp3, sizeof(tmp3), t->DeviceName);
10518 				StrCpy(tmp3, sizeof(tmp3), t->DeviceName);
10519 				StrToUni(tmp, sizeof(tmp), tmp3);
10520 			}
10521 			else
10522 			{
10523 				StrToUni(tmp, sizeof(tmp), t->DeviceName);
10524 			}
10525 
10526 			if (t->Port == 0 || cm->ShowPort == false)
10527 			{
10528 				// Port number is unknown
10529 				UniFormat(tmp2, sizeof(tmp2), L"%S (%s)", ip_str, CmGetProtocolName(t->ProxyType));
10530 			}
10531 			else
10532 			{
10533 				// Port number are also shown
10534 				UniFormat(tmp2, sizeof(tmp2), L"%S:%u (%s)", ip_str, t->Port, CmGetProtocolName(t->ProxyType));
10535 			}
10536 
10537 			if (LvSearchStr(hWnd, L_ACCOUNT, 0, t->AccountName) == INFINITE)
10538 			{
10539 				UniStrCpy(new_inserted_item, sizeof(new_inserted_item), t->AccountName);
10540 			}
10541 
10542 			// Virtual HUB name
10543 			StrToUni(tmp4, sizeof(tmp4), t->HubName);
10544 
10545 			if (easy == false)
10546 			{
10547 				LvInsertAdd(b, icon, (void *)t->StartupAccount, 5, t->AccountName,
10548 					t->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :
10549 					(t->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),
10550 					tmp2, tmp4,
10551 					tmp);
10552 			}
10553 			else
10554 			{
10555 				LvInsertAdd(b, icon, (void *)t->StartupAccount, 5, t->AccountName,
10556 					t->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :
10557 					(t->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),
10558 					tmp2, tmp4,
10559 					tmp);
10560 			}
10561 
10562 			if (t->Active)
10563 			{
10564 				if (t->Connected)
10565 				{
10566 					num_connected++;
10567 				}
10568 				else
10569 				{
10570 					num_connecting++;
10571 				}
10572 			}
10573 		}
10574 
10575 		LvInsertEnd(b, hWnd, L_ACCOUNT);
10576 
10577 		CiFreeClientEnumAccount(&a);
10578 
10579 		if (select_new_insteted_item)
10580 		{
10581 			if (UniStrLen(new_inserted_item) >= 1)
10582 			{
10583 				LvSelect(hWnd, L_ACCOUNT, INFINITE);
10584 				LvSelect(hWnd, L_ACCOUNT, LvSearchStr(hWnd, L_ACCOUNT, 0, new_inserted_item));
10585 			}
10586 		}
10587 	}
10588 
10589 	if (easy == false)
10590 	{
10591 		// For voice guidance, detect new connection and connection lost
10592 		if (cm->UpdateConnectedNumFlag == false)
10593 		{
10594 			cm->UpdateConnectedNumFlag = true;
10595 			cm->OldConnectedNum = num;
10596 		}
10597 		else
10598 		{
10599 			if (cm->OldConnectedNum != num)
10600 			{
10601 				if (cm->OldConnectedNum < num)
10602 				{
10603 					CmVoice("connect");
10604 				}
10605 				else
10606 				{
10607 					CmVoice("disconnect");
10608 
10609 					if (cm->CmSetting.EasyMode && cm->PositiveDisconnectFlag == false)
10610 					{
10611 						CmShowEasy();
10612 					}
10613 
10614 					cm->PositiveDisconnectFlag = false;
10615 				}
10616 				cm->OldConnectedNum = num;
10617 			}
10618 		}
10619 
10620 		if (num_connecting == 0 && num_connected == 0)
10621 		{
10622 			// There is no connecting or connected account
10623 			UniStrCpy(tmp, sizeof(tmp), _UU("CM_TRAY_NOT_CONNECTED"));
10624 		}
10625 		else if (num_connected == 0)
10626 		{
10627 			// There is only connecting account
10628 			UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_1"), num_connecting);
10629 		}
10630 		else if (num_connecting == 0)
10631 		{
10632 			// There is only connected account
10633 			UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_2"), num_connected);
10634 		}
10635 		else
10636 		{
10637 			// There are both
10638 			UniFormat(tmp, sizeof(tmp), _UU("CM_TRAY_CONNECTED_0"), num_connected, num_connecting);
10639 		}
10640 
10641 		if (num_connecting == 0 && num_connected == 0)
10642 		{
10643 			cm->TrayAnimation = false;
10644 			cm->TraySpeedAnimation = false;
10645 		}
10646 		else
10647 		{
10648 			cm->TrayAnimation = true;
10649 
10650 			if (num_connecting == 0)
10651 			{
10652 				cm->TraySpeedAnimation = false;
10653 			}
10654 			else
10655 			{
10656 				cm->TraySpeedAnimation = true;
10657 			}
10658 		}
10659 
10660 		CmChangeTrayString(hWnd, tmp);
10661 	}
10662 
10663 	Refresh(hWnd);
10664 
10665 	//Updated the Jump List
10666 	CmUpdateJumpList(0);
10667 }
10668 
10669 // Updating the VLAN list
CmRefreshVLanList(HWND hWnd)10670 void CmRefreshVLanList(HWND hWnd)
10671 {
10672 	CmRefreshVLanListEx(hWnd, false);
10673 }
CmRefreshVLanListEx(HWND hWnd,bool style_changed)10674 void CmRefreshVLanListEx(HWND hWnd, bool style_changed)
10675 {
10676 	RPC_CLIENT_ENUM_VLAN e;
10677 	// Validate arguments
10678 	if (hWnd == NULL)
10679 	{
10680 		return;
10681 	}
10682 
10683 	LvSetView(hWnd, L_VLAN, cm->IconView == false);
10684 
10685 	// Show grid
10686 	if (cm->ShowGrid)
10687 	{
10688 		LvSetStyle(hWnd, L_VLAN, LVS_EX_GRIDLINES);
10689 	}
10690 	else
10691 	{
10692 		LvRemoveStyle(hWnd, L_VLAN, LVS_EX_GRIDLINES);
10693 	}
10694 
10695 	if (style_changed)
10696 	{
10697 		// Change the font
10698 		if (cm->VistaStyle)
10699 		{
10700 			SetFontMeiryo(hWnd, L_VLAN, 9);
10701 		}
10702 		else
10703 		{
10704 			SetFontDefault(hWnd, L_VLAN);
10705 		}
10706 
10707 		if (cm->VistaStyle && (cm->IconView == false))
10708 		{
10709 			LvSetStyle(hWnd, L_VLAN, LVS_EX_FULLROWSELECT);
10710 		}
10711 		else
10712 		{
10713 			LvRemoveStyle(hWnd, L_VLAN, LVS_EX_FULLROWSELECT);
10714 		}
10715 	}
10716 
10717 	// Enumeration
10718 	Zero(&e, sizeof(e));
10719 	if (CALL(hWnd, CcEnumVLan(cm->Client, &e)))
10720 	{
10721 		LVB *b = LvInsertStart();
10722 		UINT i;
10723 		for (i = 0;i < e.NumItem;i++)
10724 		{
10725 			wchar_t name[MAX_SIZE];
10726 			wchar_t mac[MAX_SIZE];
10727 			wchar_t ver[MAX_SIZE];
10728 			char str[MAX_SIZE];
10729 			wchar_t *status;
10730 			RPC_CLIENT_ENUM_VLAN_ITEM *v = e.Items[i];
10731 
10732 			// Device name
10733 			CmVLanNameToPrintName(str, sizeof(str), v->DeviceName);
10734 			StrToUni(name, sizeof(name), str);
10735 
10736 			// Status
10737 			status = v->Enabled ? _UU("CM_VLAN_ENABLED") : _UU("CM_VLAN_DISABLED");
10738 
10739 			// MAC address
10740 			StrToUni(mac, sizeof(mac), v->MacAddress);
10741 
10742 			// Version
10743 			StrToUni(ver, sizeof(ver), v->Version);
10744 
10745 			LvInsertAdd(b, v->Enabled ? ICO_NIC_ONLINE : ICO_NIC_OFFLINE, NULL, 4,
10746 				name, status, mac, ver);
10747 		}
10748 		LvInsertEnd(b, hWnd, L_VLAN);
10749 
10750 		CiFreeClientEnumVLan(&e);
10751 	}
10752 }
10753 
10754 // Get a protocol name string
CmGetProtocolName(UINT n)10755 wchar_t *CmGetProtocolName(UINT n)
10756 {
10757 	return GetProtocolName(n);
10758 }
10759 
10760 // Display update
CmRefresh(HWND hWnd)10761 void CmRefresh(HWND hWnd)
10762 {
10763 	CmRefreshEx(hWnd, false);
10764 }
CmRefreshEx(HWND hWnd,bool style_changed)10765 void CmRefreshEx(HWND hWnd, bool style_changed)
10766 {
10767 	// Validate arguments
10768 	if (hWnd == NULL)
10769 	{
10770 		return;
10771 	}
10772 
10773 	// Update size
10774 	CmMainWindowOnSize(hWnd);
10775 
10776 	// Updating the VLAN list
10777 	CmRefreshVLanListEx(hWnd, style_changed);
10778 
10779 	// Update the account list
10780 	CmRefreshAccountListEx2(hWnd, false, style_changed);
10781 
10782 	// Update the status bar
10783 	CmRefreshStatusBar(hWnd);
10784 }
10785 
10786 // Determine whether to check the specified menu item
CmIsChecked(UINT id)10787 bool CmIsChecked(UINT id)
10788 {
10789 	switch (id)
10790 	{
10791 	case CMD_TRAYICON:
10792 		return cm->HideTrayIcon == false;
10793 	case CMD_STATUSBAR:
10794 		return cm->HideStatusBar == false;
10795 	case CMD_VISTASTYLE:
10796 		return cm->VistaStyle;
10797 	case CMD_ICON:
10798 		return cm->IconView;
10799 	case CMD_DETAIL:
10800 		return cm->IconView == false;
10801 	case CMD_GRID:
10802 		return cm->ShowGrid;
10803 	case CMD_VOIDE_NONE:
10804 		return cm->DisableVoice;
10805 	case CMD_SHOWPORT:
10806 		return cm->ShowPort;
10807 	case CMD_VOICE_NORMAL:
10808 		if (cm->DisableVoice)
10809 		{
10810 			return false;
10811 		}
10812 		else
10813 		{
10814 			return cm->VoiceId == VOICE_SSK;
10815 		}
10816 	case CMD_VOICE_ODD:
10817 		if (cm->DisableVoice)
10818 		{
10819 			return false;
10820 		}
10821 		else
10822 		{
10823 			return cm->VoiceId == VOICE_AHO;
10824 		}
10825 	}
10826 	return false;
10827 }
10828 
10829 // The menu popped-up
CmMainWindowOnPopupMenu(HWND hWnd,HMENU hMenu,UINT pos)10830 void CmMainWindowOnPopupMenu(HWND hWnd, HMENU hMenu, UINT pos)
10831 {
10832 	UINT num_menu, i, id;
10833 	// Validate arguments
10834 	if (hWnd == NULL || hMenu == NULL)
10835 	{
10836 		return;
10837 	}
10838 
10839 	num_menu = GetMenuItemCount(hMenu);
10840 	for (i = 0;i < num_menu;i++)
10841 	{
10842 		id = GetMenuItemID(hMenu, i);
10843 
10844 		if (id != INFINITE)
10845 		{
10846 			bool enable_flag = CmIsEnabled(hWnd, id);
10847 			bool checked_flag = CmIsChecked(id);
10848 			bool bold_flag = CmIsBold(id);
10849 			MENUITEMINFO info;
10850 
10851 			Zero(&info, sizeof(info));
10852 			info.cbSize = sizeof(info);
10853 			info.fMask = MIIM_STATE;
10854 			info.fState = (enable_flag ? MFS_ENABLED : MFS_DISABLED) |
10855 				(checked_flag ? MFS_CHECKED : MFS_UNCHECKED) |
10856 				(bold_flag ? MFS_DEFAULT : 0);
10857 
10858 			if (id == CMD_ICON || id == CMD_DETAIL || id == CMD_VOIDE_NONE ||
10859 				id == CMD_VOICE_NORMAL || id == CMD_VOICE_ODD)
10860 			{
10861 				info.fMask |= MIIM_FTYPE;
10862 				info.fType = MFT_RADIOCHECK;
10863 			}
10864 
10865 			SetMenuItemInfo(hMenu, id, false, &info);
10866 		}
10867 
10868 		if (id == CMD_RECENT)
10869 		{
10870 			HMENU sub = CmCreateRecentSubMenu(hWnd, CM_TRAY_MENU_RECENT_ID_START);
10871 
10872 			if (sub != NULL)
10873 			{
10874 				DeleteMenu(hMenu, i, MF_BYPOSITION);
10875 				MsInsertMenu(hMenu, i, MF_BYPOSITION | MF_ENABLED | MF_POPUP | MF_STRING,
10876 					(UINT_PTR)sub, _UU("CM_TRAY_MENU_RECENT"));
10877 			}
10878 			else
10879 			{
10880 				MENUITEMINFO info;
10881 
10882 				Zero(&info, sizeof(info));
10883 				info.cbSize = sizeof(info);
10884 				info.fMask = MIIM_STATE;
10885 				info.fState = MFS_DISABLED;
10886 
10887 				SetMenuItemInfo(hMenu, id, false, &info);
10888 			}
10889 		}
10890 	}
10891 }
10892 
10893 // Set the main window title
CmGenerateMainWindowTitle()10894 wchar_t *CmGenerateMainWindowTitle()
10895 {
10896 	wchar_t tmp[MAX_SIZE];
10897 	if (cm->server_name == NULL)
10898 	{
10899 		UniFormat(tmp, sizeof(tmp), L"%s", _UU("CM_TITLE"));
10900 	}
10901 	else
10902 	{
10903 		UniFormat(tmp, sizeof(tmp), L"%s - %S", _UU("CM_TITLE"), cm->server_name);
10904 	}
10905 
10906 	return CopyUniStr(tmp);
10907 }
10908 
10909 // Initialize the task tray
CmInitTray(HWND hWnd)10910 void CmInitTray(HWND hWnd)
10911 {
10912 	bool ret;
10913 	// Validate arguments
10914 	if (hWnd == NULL)
10915 	{
10916 		return;
10917 	}
10918 
10919 	if (cm->server_name != NULL)
10920 	{
10921 		return;
10922 	}
10923 
10924 	if (cm->TrayInited)
10925 	{
10926 		return;
10927 	}
10928 
10929 	ret = MsShowIconOnTray(hWnd, LoadSmallIcon(CmGetTrayIconId(false, 0)), _UU("CM_TRAY_INITING"), WM_CM_TRAY_MESSAGE);
10930 
10931 	cm->TrayInited = true;
10932 	cm->TrayAnimation = false;
10933 	cm->TraySucceed = ret;
10934 
10935 	SetTimer(hWnd, 2, CM_TRAY_ANIMATION_INTERVAL / 4, NULL);
10936 }
10937 
10938 // Change the string in the task tray
CmChangeTrayString(HWND hWnd,wchar_t * str)10939 void CmChangeTrayString(HWND hWnd, wchar_t *str)
10940 {
10941 	// Validate arguments
10942 	if (hWnd == NULL || str == NULL)
10943 	{
10944 		return;
10945 	}
10946 	if (cm->TrayInited == false)
10947 	{
10948 		return;
10949 	}
10950 
10951 	MsChangeIconOnTray(NULL, str);
10952 }
10953 
10954 // Release the task tray
CmFreeTray(HWND hWnd)10955 void CmFreeTray(HWND hWnd)
10956 {
10957 	// Validate arguments
10958 	if (hWnd == NULL)
10959 	{
10960 		return;
10961 	}
10962 
10963 	if (cm->TrayInited == false)
10964 	{
10965 		return;
10966 	}
10967 
10968 	MsHideIconOnTray();
10969 
10970 	cm->TrayInited = false;
10971 }
CmFreeTrayExternal(void * hWnd)10972 void CmFreeTrayExternal(void *hWnd)
10973 {
10974 	CmFreeTray((HWND)hWnd);
10975 }
10976 
10977 // Periodical processing to the task tray
CmPollingTray(HWND hWnd)10978 void CmPollingTray(HWND hWnd)
10979 {
10980 	UINT interval;
10981 	bool ret;
10982 	// Validate arguments
10983 	if (hWnd == NULL)
10984 	{
10985 		return;
10986 	}
10987 
10988 	if (cm->TrayInited == false)
10989 	{
10990 		return;
10991 	}
10992 
10993 	ret = MsChangeIconOnTrayEx(LoadSmallIcon(CmGetTrayIconId(cm->TrayAnimation, cm->TrayAnimationCounter)),
10994 		NULL, NULL, NULL, NIIF_NONE, !cm->TraySucceed);
10995 
10996 	if (cm->TraySucceed == false)
10997 	{
10998 		cm->TraySucceed = ret;
10999 	}
11000 
11001 	cm->TrayAnimationCounter++;
11002 
11003 	KillTimer(hWnd, 2);
11004 	interval = CM_TRAY_ANIMATION_INTERVAL / 4;
11005 	if (cm->TraySpeedAnimation)
11006 	{
11007 		interval /= 4;
11008 	}
11009 	SetTimer(hWnd, 2, interval, NULL);
11010 }
11011 
11012 // Get the icon ID of the task tray for animation
CmGetTrayIconId(bool animation,UINT animation_counter)11013 UINT CmGetTrayIconId(bool animation, UINT animation_counter)
11014 {
11015 	if (animation == false)
11016 	{
11017 		return ICO_TRAY0;
11018 	}
11019 	else
11020 	{
11021 		switch (animation_counter % 4)
11022 		{
11023 		case 0:
11024 			return ICO_TRAY1;
11025 
11026 		case 1:
11027 			return ICO_TRAY2;
11028 
11029 		case 2:
11030 			return ICO_TRAY3;
11031 
11032 		default:
11033 			return ICO_TRAY4;
11034 		}
11035 	}
11036 }
11037 
11038 // Initialize the main window
CmMainWindowOnInit(HWND hWnd)11039 void CmMainWindowOnInit(HWND hWnd)
11040 {
11041 	wchar_t *s;
11042 	BUF *b;
11043 	bool startup_mode = cm->StartupMode;
11044 	CM_SETTING a;
11045 	bool fake = false;
11046 	// Validate arguments
11047 	if (hWnd == NULL)
11048 	{
11049 		return;
11050 	}
11051 
11052 	// Font settings of list
11053 	SetFontMeiryo(hWnd, L_ACCOUNT, 9);
11054 	SetFontMeiryo(hWnd, L_VLAN, 9);
11055 
11056 	// Get the configuration of the current vpnclient
11057 	Zero(&a, sizeof(a));
11058 	CcGetCmSetting(cm->Client, &a);
11059 
11060 	if (a.EasyMode)
11061 	{
11062 		fake = true;
11063 	}
11064 
11065 	InitMenuInternational(GetMenu(hWnd), "CM_MENU");
11066 
11067 	cm->HideStatusBar = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "HideStatusBar");
11068 	cm->HideTrayIcon = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "HideTrayIcon");
11069 	cm->IconView = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "IconView");
11070 	cm->ShowGrid = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "ShowGrid");
11071 
11072 	if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle"))
11073 	{
11074 		cm->VistaStyle = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle");
11075 	}
11076 	else
11077 	{
11078 		cm->VistaStyle = MsIsVista();
11079 	}
11080 
11081 	if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "ShowPort"))
11082 	{
11083 		cm->ShowPort = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "ShowPort");
11084 	}
11085 	else
11086 	{
11087 		cm->ShowPort = false;
11088 	}
11089 
11090 	if (MsRegIsValue(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice"))
11091 	{
11092 		cm->DisableVoice = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice");
11093 	}
11094 	else
11095 	{
11096 		cm->DisableVoice = true;
11097 	}
11098 	cm->VoiceId = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "VoiceId");
11099 
11100 	cm->StatusWindowList = NewList(NULL);
11101 
11102 	SetIcon(hWnd, 0, ICO_VPN);
11103 
11104 	s = CmGenerateMainWindowTitle();
11105 	SetText(hWnd, 0, s);
11106 	Free(s);
11107 
11108 	// Initialize the window position
11109 	b = MsRegReadBin(REG_CURRENT_USER, CM_REG_KEY, "WindowPlacement");
11110 	if (b != NULL && b->Size == sizeof(WINDOWPLACEMENT))
11111 	{
11112 		// Restore the window position
11113 		WINDOWPLACEMENT *p;
11114 		p = ZeroMalloc(b->Size);
11115 		Copy(p, b->Buf, b->Size);
11116 
11117 		if (startup_mode)
11118 		{
11119 			p->showCmd = SW_SHOWMINIMIZED;
11120 		}
11121 
11122 		if (fake)
11123 		{
11124 			Copy(&cm->FakeWindowPlacement, p, sizeof(WINDOWPLACEMENT));
11125 		}
11126 		else
11127 		{
11128 			SetWindowPlacement(hWnd, p);
11129 		}
11130 		Free(p);
11131 	}
11132 	else
11133 	{
11134 		// Initialize the window position
11135 		SetWindowPos(hWnd, NULL, 0, 0, CM_DEFAULT_WIDTH, CM_DEFAULT_HEIGHT, SWP_NOREDRAW);
11136 		Center(hWnd);
11137 		if (startup_mode)
11138 		{
11139 			ShowWindow(hWnd, SW_SHOWMINIMIZED);
11140 		}
11141 
11142 		if (fake)
11143 		{
11144 			WINDOWPLACEMENT p;
11145 
11146 			Zero(&p, sizeof(p));
11147 			p.length = sizeof(p);
11148 			GetWindowPlacement(hWnd, &p);
11149 			Copy(&cm->FakeWindowPlacement, &p, sizeof(WINDOWPLACEMENT));
11150 		}
11151 	}
11152 	FreeBuf(b);
11153 
11154 	if (fake)
11155 	{
11156 		SetWindowPos(hWnd, NULL, -200, -200, 100, 100,
11157 			SWP_NOREDRAW | SWP_SHOWWINDOW);
11158 	}
11159 
11160 	// Initialize the status bar related items
11161 	cm->hMainWnd = hWnd;
11162 	cm->hStatusBar = CreateStatusWindowW(WS_CHILD |
11163 		(cm->HideStatusBar == false ? WS_VISIBLE : 0),
11164 		_UU("CM_TITLE"),
11165 		hWnd, S_STATUSBAR);
11166 
11167 	UniStrCpy(cm->StatudBar1, sizeof(cm->StatudBar1), _UU("CM_TITLE"));
11168 	UniStrCpy(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_CONN_NO"));
11169 	UniFormat(cm->StatudBar3, sizeof(cm->StatudBar3), _UU("CM_PRODUCT_NAME"), CEDAR_BUILD);
11170 
11171 	cm->Icon2 = LoadSmallIcon(ICO_SERVER_OFFLINE);
11172 	cm->Icon3 = LoadSmallIcon(ICO_VPN);
11173 
11174 	// Initialize the account list
11175 	CmInitAccountList(hWnd);
11176 
11177 	// Initialize the VLAN list
11178 	CmInitVLanList(hWnd);
11179 
11180 	// Display update
11181 	CmRefreshEx(hWnd, true);
11182 
11183 	// Start a thread of notification client
11184 	CmInitNotifyClientThread();
11185 
11186 	// Timer setting
11187 	SetTimer(hWnd, 1, 128, NULL);
11188 	SetTimer(hWnd, 6, 5000, NULL);
11189 
11190 	// Initialize the task tray
11191 	if (cm->server_name == NULL)
11192 	{
11193 		if (cm->HideTrayIcon == false)
11194 		{
11195 			CmInitTray(hWnd);
11196 		}
11197 	}
11198 
11199 	CmVoice("start");
11200 
11201 	if (startup_mode || a.EasyMode)
11202 	{
11203 		SetTimer(hWnd, 3, 1, NULL);
11204 	}
11205 
11206 	if (cm->import_file_name != NULL)
11207 	{
11208 		// Import a file specified as an argument
11209 		CmSendImportMessage(hWnd, cm->import_file_name, cm->CmSettingInitialFlag == CM_SETTING_INIT_NONE ? CM_IMPORT_FILENAME_MSG : CM_IMPORT_FILENAME_MSG_OVERWRITE);
11210 		/*if (a.LockMode == false)
11211 		{
11212 			CmImportAccountMainEx(hWnd, cm->import_file_name, cm->CmSettingInitialFlag != CM_SETTING_INIT_NONE);
11213 		}
11214 		else
11215 		{
11216 			MsgBox(cm->hEasyWnd ? cm->hEasyWnd : hWnd, MB_ICONEXCLAMATION, _UU("CM_VPN_FILE_IMPORT_NG"));
11217 		}*/
11218 	}
11219 
11220 	// Apply the CM_SETTING
11221 	CmApplyCmSetting();
11222 
11223 	cm->StartupFinished = true;
11224 }
11225 
11226 // Start a thread of notification client
CmInitNotifyClientThread()11227 void CmInitNotifyClientThread()
11228 {
11229 	cm->NotifyClient = CcConnectNotify(cm->Client);
11230 	if (cm->NotifyClient == false)
11231 	{
11232 		Close(cm->hMainWnd);
11233 		exit(0);
11234 	}
11235 	cm->NotifyClientThread = NewThread(CmNotifyClientThread, NULL);
11236 }
11237 
11238 // Notification client thread
CmNotifyClientThread(THREAD * thread,void * param)11239 void CmNotifyClientThread(THREAD *thread, void *param)
11240 {
11241 	NOTIFY_CLIENT *nc;
11242 	// Validate arguments
11243 	if (thread == NULL)
11244 	{
11245 		return;
11246 	}
11247 
11248 	nc = cm->NotifyClient;
11249 
11250 	// Wait for the next notification
11251 	while (cm->Halt == false)
11252 	{
11253 		if (CcWaitNotify(nc))
11254 		{
11255 			// Send a message
11256 			PostMessage(cm->hMainWnd, WM_CM_NOTIFY, 0, 0);
11257 		}
11258 		else
11259 		{
11260 			// Disconnected
11261 			if (cm->Halt == false)
11262 			{
11263 				if (cm != NULL)
11264 				{
11265 					CmFreeTrayExternal((void *)cm->hMainWnd);
11266 				}
11267 				CncExit();
11268 				exit(0);
11269 			}
11270 			break;
11271 		}
11272 	}
11273 }
11274 
11275 // Stop the thread of the notification client
CmFreeNotifyClientThread()11276 void CmFreeNotifyClientThread()
11277 {
11278 	cm->Halt = true;
11279 
11280 	// Disconnect
11281 	CcStopNotify(cm->NotifyClient);
11282 
11283 	// Wait for the termination of the thread
11284 	WaitThread(cm->NotifyClientThread, INFINITE);
11285 
11286 	// Connection termination
11287 	CcDisconnectNotify(cm->NotifyClient);
11288 	ReleaseThread(cm->NotifyClientThread);
11289 }
11290 
11291 // Resize the main window
CmMainWindowOnSize(HWND hWnd)11292 void CmMainWindowOnSize(HWND hWnd)
11293 {
11294 	RECT r;
11295 	UINT client_width, client_height;
11296 	UINT status_height;
11297 	// Validate arguments
11298 	if (hWnd == NULL)
11299 	{
11300 		return;
11301 	}
11302 
11303 	// Get the size of the client area of the main window
11304 	GetClientRect(hWnd, &r);
11305 	client_width = MAX(r.right - r.left, 0);
11306 	client_height = MAX(r.bottom - r.top, 0);
11307 
11308 	SendMsg(hWnd, S_STATUSBAR, WM_SIZE, 0, 0);
11309 
11310 	// Get the size of the status bar
11311 	GetWindowRect(DlgItem(hWnd, S_STATUSBAR), &r);
11312 	status_height = MAX(r.bottom - r.top, 0);
11313 
11314 	if (cm->HideStatusBar == false)
11315 	{
11316 		client_height = MAX(client_height - status_height, 0);
11317 	}
11318 
11319 	MoveWindow(DlgItem(hWnd, L_ACCOUNT), 0, 0, client_width, client_height * 3 / 5 - 3, true);
11320 	MoveWindow(DlgItem(hWnd, L_VLAN), 0, client_height * 3 / 5, client_width, client_height * 2 / 5, true);
11321 
11322 	// Re-draw the status bar
11323 	CmRedrawStatusBar(hWnd);
11324 }
11325 
11326 // Disconnect all accounts currently connected
CmDisconnectAll(HWND hWnd)11327 void CmDisconnectAll(HWND hWnd)
11328 {
11329 	UINT i, num;
11330 	LIST *o;
11331 	// Validate arguments
11332 	if (hWnd == NULL)
11333 	{
11334 		return;
11335 	}
11336 
11337 	// Display a warning
11338 	num = CmGetNumConnected(hWnd);
11339 	if (num == 0)
11340 	{
11341 		return;
11342 	}
11343 
11344 	if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("CM_DISCONNECT_ALL"), num) == IDNO)
11345 	{
11346 		return;
11347 	}
11348 
11349 	cm->PositiveDisconnectFlag = true;
11350 
11351 	// Create a list of connected items
11352 	o = NewListFast(NULL);
11353 
11354 	num = LvNum(hWnd, L_ACCOUNT);
11355 	for (i = 0;i < num;i++)
11356 	{
11357 		wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 1);
11358 		if (s != NULL)
11359 		{
11360 			if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)
11361 			{
11362 				Add(o, LvGetStr(hWnd, L_ACCOUNT, i, 0));
11363 			}
11364 			Free(s);
11365 		}
11366 	}
11367 
11368 	for (i = 0;i < LIST_NUM(o);i++)
11369 	{
11370 		wchar_t *s = LIST_DATA(o, i);
11371 		if (s != NULL)
11372 		{
11373 			CmDisconnect(hWnd, s);
11374 			Free(s);
11375 		}
11376 	}
11377 
11378 	ReleaseList(o);
11379 }
11380 
11381 // Get a number of currently connected connection settings
CmGetNumConnected(HWND hWnd)11382 UINT CmGetNumConnected(HWND hWnd)
11383 {
11384 	UINT i, num, num_active;
11385 	// Validate arguments
11386 	if (hWnd == NULL)
11387 	{
11388 		return 0;
11389 	}
11390 
11391 	num_active = 0;
11392 	num = LvNum(hWnd, L_ACCOUNT);
11393 	for (i = 0;i < num;i++)
11394 	{
11395 		wchar_t *s = LvGetStr(hWnd, L_ACCOUNT, i, 1);
11396 		if (s != NULL)
11397 		{
11398 			if (UniStrCmpi(s, _UU("CM_ACCOUNT_ONLINE")) == 0 || UniStrCmpi(s, _UU("CM_ACCOUNT_CONNECTING")) == 0)
11399 			{
11400 				num_active++;
11401 			}
11402 			Free(s);
11403 		}
11404 	}
11405 
11406 	return num_active;
11407 }
11408 
11409 // Update the status bar information
CmRefreshStatusBar(HWND hWnd)11410 void CmRefreshStatusBar(HWND hWnd)
11411 {
11412 	UINT num_active = CmGetNumConnected(hWnd);
11413 	// Validate arguments
11414 	if (hWnd == NULL)
11415 	{
11416 		return;
11417 	}
11418 
11419 	if (num_active == 0)
11420 	{
11421 		UniStrCpy(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_CONN_NO"));
11422 		cm->Icon2 = LoadSmallIcon(ICO_SERVER_OFFLINE);
11423 	}
11424 	else
11425 	{
11426 		UniFormat(cm->StatudBar2, sizeof(cm->StatudBar2), _UU("CM_NUM_CONN_COUNT"), num_active);
11427 		cm->Icon2 = LoadSmallIcon(ICO_SERVER_ONLINE);
11428 	}
11429 
11430 	CmRedrawStatusBar(hWnd);
11431 }
11432 
11433 // Re-draw the status bar
CmRedrawStatusBar(HWND hWnd)11434 void CmRedrawStatusBar(HWND hWnd)
11435 {
11436 	HWND h;
11437 	RECT r;
11438 	int width;
11439 	int x1, x2, x3;
11440 	int xx[3];
11441 	wchar_t tmp[MAX_SIZE];
11442 	HICON icon;
11443 	// Validate arguments
11444 	if (hWnd == NULL)
11445 	{
11446 		return;
11447 	}
11448 
11449 	h = cm->hStatusBar;
11450 
11451 	// Get the width of the status bar
11452 	GetWindowRect(h, &r);
11453 	width = MAX(r.right - r.left, 0);
11454 	x2 = (UINT)(180.0 * GetTextScalingFactor());
11455 	x3 = (UINT)(245.0 * GetTextScalingFactor());
11456 	x1 = MAX(width - x2 - x3, 0);
11457 
11458 	// Divide into three parts
11459 	xx[0] = x1;
11460 	xx[1] = x2 + x1;
11461 	xx[2] = x3 + x2 + x1;
11462 	SendMsg(h, 0, SB_SETPARTS, 3, (LPARAM)xx);
11463 
11464 	// Set an icon
11465 	icon = (HICON)SendMsg(h, 0, SB_GETICON, 1, 0);
11466 	if (icon != cm->Icon2)
11467 	{
11468 		SendMsg(h, 0, SB_SETICON, 1, (LPARAM)cm->Icon2);
11469 	}
11470 
11471 	icon = (HICON)SendMsg(h, 0, SB_GETICON, 2, 0);
11472 	if (icon != cm->Icon3)
11473 	{
11474 		SendMsg(h, 0, SB_SETICON, 2, (LPARAM)cm->Icon3);
11475 	}
11476 
11477 	// Set a string
11478 	SendMsg(h, 0, SB_GETTEXTW, 0, (LPARAM)tmp);
11479 	if (UniStrCmp(tmp, cm->StatudBar1))
11480 	{
11481 		SendMsg(h, 0, SB_SETTEXTW, 0, (LPARAM)cm->StatudBar1);
11482 	}
11483 
11484 	SendMsg(h, 0, SB_GETTEXTW, 1, (LPARAM)tmp);
11485 	if (UniStrCmp(tmp, cm->StatudBar2))
11486 	{
11487 		SendMsg(h, 0, SB_SETTEXTW, 1, (LPARAM)cm->StatudBar2);
11488 	}
11489 
11490 	SendMsg(h, 0, SB_GETTEXTW, 2, (LPARAM)tmp);
11491 	if (UniStrCmp(tmp, cm->StatudBar3))
11492 	{
11493 		SendMsg(h, 0, SB_SETTEXTW, 2, (LPARAM)cm->StatudBar3);
11494 	}
11495 }
11496 
11497 // Save the position information of the main window
CmSaveMainWindowPos(HWND hWnd)11498 void CmSaveMainWindowPos(HWND hWnd)
11499 {
11500 	WINDOWPLACEMENT p;
11501 	// Validate arguments
11502 	if (hWnd == NULL)
11503 	{
11504 		return;
11505 	}
11506 
11507 	// Save settings
11508 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "HideStatusBar", cm->HideStatusBar);
11509 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "HideTrayIcon", cm->HideTrayIcon);
11510 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "IconView", cm->IconView);
11511 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "ShowGrid", cm->ShowGrid);
11512 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "DisableVoice", cm->DisableVoice);
11513 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "VoiceId", cm->VoiceId);
11514 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "VistaStyle", cm->VistaStyle);
11515 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY, "ShowPort", cm->ShowPort);
11516 
11517 	// Save the window position
11518 	Zero(&p, sizeof(p));
11519 	p.length = sizeof(p);
11520 	GetWindowPlacement(hWnd, &p);
11521 
11522 	if (IsZero(&cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement)) == false)
11523 	{
11524 		Copy(&p, &cm->FakeWindowPlacement, sizeof(cm->FakeWindowPlacement));
11525 	}
11526 
11527 	MsRegWriteBin(REG_CURRENT_USER, CM_REG_KEY, "WindowPlacement", &p, sizeof(p));
11528 
11529 	CmSaveAccountListPos(hWnd);
11530 	CmSaveVLanListPos(hWnd);
11531 }
11532 
11533 // Close the main window
CmMainWindowOnQuit(HWND hWnd)11534 void CmMainWindowOnQuit(HWND hWnd)
11535 {
11536 	UINT i;
11537 	// Validate arguments
11538 	if (hWnd == NULL)
11539 	{
11540 		return;
11541 	}
11542 
11543 	if (cm->TrayInited)
11544 	{
11545 		if (MsgBox(hWnd, MB_YESNO | MB_ICONQUESTION,
11546 			_UU("CM_EXIT_MESSAGE")) == IDNO)
11547 		{
11548 			return;
11549 		}
11550 	}
11551 
11552 	if (cm->OnCloseDispatched)
11553 	{
11554 		return;
11555 	}
11556 	cm->OnCloseDispatched = true;
11557 
11558 	CmCloseEasy();
11559 
11560 	// Release the tray icon
11561 	CmFreeTray(hWnd);
11562 
11563 	// Save the position information of the main window
11564 	CmSaveMainWindowPos(hWnd);
11565 
11566 	// Close the status window
11567 	for (i = 0;i < LIST_NUM(cm->StatusWindowList);i++)
11568 	{
11569 		HWND h = LIST_DATA(cm->StatusWindowList, i);
11570 		//EndDialog(h, 0);
11571 		PostMessage(h, WM_CLOSE, 0, 0);
11572 	}
11573 
11574 	ReleaseList(cm->StatusWindowList);
11575 	cm->StatusWindowList = NULL;
11576 
11577 	if (cm->WindowCount != 0)
11578 	{
11579 		// Abort
11580 		exit(0);
11581 	}
11582 
11583 	// Close
11584 	CmFreeNotifyClientThread();
11585 
11586 	EndDialog(hWnd, false);
11587 }
11588 
11589 // Start the mutex to be used in starting
CmStartStartupMutex()11590 bool CmStartStartupMutex()
11591 {
11592 	INSTANCE *o = NewSingleInstance(STARTUP_MUTEX_NAME);
11593 
11594 	if (o == NULL)
11595 	{
11596 		return false;
11597 	}
11598 
11599 	cm->StartupMutex = o;
11600 
11601 	return true;
11602 }
11603 
11604 // Release the mutex to be used in starting
CmEndStartupMutex()11605 void CmEndStartupMutex()
11606 {
11607 	if (cm->StartupMutex != NULL)
11608 	{
11609 		FreeSingleInstance(cm->StartupMutex);
11610 
11611 		cm->StartupMutex = NULL;
11612 	}
11613 }
11614 
11615 // Main window
MainCMWindow()11616 void MainCMWindow()
11617 {
11618 	HWND h;
11619 	wchar_t *s;
11620 	CM_SETTING a;
11621 
11622 	if (CmStartStartupMutex() == false)
11623 	{
11624 		return;
11625 	}
11626 
11627 	s = CmGenerateMainWindowTitle();
11628 	h = SearchWindow(s);
11629 	Free(s);
11630 
11631 	Zero(&a, sizeof(a));
11632 	CcGetCmSetting(cm->Client, &a);
11633 	if (cm->server_name != NULL && a.EasyMode)
11634 	{
11635 		CmEndStartupMutex();
11636 		MsgBox(NULL, MB_ICONEXCLAMATION, _UU("CM_EASY_MODE_NOT_ON_REMOTE"));
11637 		return;
11638 	}
11639 
11640 	// Change the operating mode
11641 	if (cm->CmSettingSupported)
11642 	{
11643 		if (cm->CmSettingInitialFlag == CM_SETTING_INIT_SELECT)
11644 		{
11645 			if (h != NULL)
11646 			{
11647 				CmEndStartupMutex();
11648 			}
11649 
11650 			// Show the selection screen
11651 			CmSetting(NULL);
11652 
11653 			if (h != NULL)
11654 			{
11655 				goto SEND_MESSAGES;
11656 			}
11657 			else
11658 			{
11659 				return;
11660 			}
11661 		}
11662 		else if ((cm->CmSettingInitialFlag == CM_SETTING_INIT_EASY && cm->CmEasyModeSupported) || cm->CmSettingInitialFlag == CM_SETTING_INIT_NORMAL)
11663 		{
11664 			// State transition
11665 			CM_SETTING a;
11666 
11667 			Zero(&a, sizeof(a));
11668 			CcGetCmSetting(cm->Client, &a);
11669 
11670 			if (cm->CmSettingInitialFlag == CM_SETTING_INIT_EASY)
11671 			{
11672 				a.EasyMode = true;
11673 			}
11674 			else
11675 			{
11676 				a.EasyMode = false;
11677 			}
11678 
11679 			CcSetCmSetting(cm->Client, &a);
11680 		}
11681 	}
11682 
11683 	if (h == NULL)
11684 	{
11685 		// Create a window because there is no window of the same title
11686 		if (cm->server_name == NULL)
11687 		{
11688 			CmInitTryToExecUiHelper();
11689 
11690 			if (IsDebug() == false)
11691 			{
11692 				CnWaitForCnServiceReady();
11693 			}
11694 		}
11695 		Dialog(NULL, D_CM_MAIN, CmMainWindowProc, NULL);
11696 		CmFreeTryToExecUiHelper();
11697 	}
11698 	else
11699 	{
11700 SEND_MESSAGES:
11701 		CmEndStartupMutex();
11702 
11703 		// If a window of the same title already exists, activate it and exit itself
11704 		SetForegroundWindow(h);
11705 		SendMessage(h, WM_CM_SHOW, 0, 0);
11706 		SetForegroundWindow(h);
11707 
11708 		if (cm->CmSettingInitialFlag != CM_SETTING_INIT_NONE && cm->CmSettingInitialFlag != CM_SETTING_INIT_CONNECT)
11709 		{
11710 			// Notify since CM_SETTING has been changed
11711 			SendMessage(h, WM_CM_SETTING_CHANGED_MESSAGE, 0, 0);
11712 		}
11713 
11714 		if (cm->import_file_name != NULL)
11715 		{
11716 			UINT msg;
11717 			if (cm->CmSettingInitialFlag == CM_SETTING_INIT_NONE)
11718 			{
11719 				msg = CM_IMPORT_FILENAME_MSG;
11720 			}
11721 			else
11722 			{
11723 				msg = CM_IMPORT_FILENAME_MSG_OVERWRITE;
11724 			}
11725 
11726 			CmSendImportMessage(h, cm->import_file_name, msg);
11727 		}
11728 	}
11729 
11730 	CmEndStartupMutex();
11731 }
11732 
11733 // Send an import message
CmSendImportMessage(HWND hWnd,wchar_t * filename,UINT msg)11734 void CmSendImportMessage(HWND hWnd, wchar_t *filename, UINT msg)
11735 {
11736 	COPYDATASTRUCT cpy;
11737 	// Validate arguments
11738 	if (hWnd == NULL || filename == NULL)
11739 	{
11740 		return;
11741 	}
11742 
11743 	// Specify the file to be imported
11744 	Zero(&cpy, sizeof(cpy));
11745 
11746 	cpy.cbData = UniStrSize(filename);
11747 	cpy.lpData = filename;
11748 	cpy.dwData = msg;
11749 
11750 	SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cpy);
11751 }
11752 
11753 // Login dialog
CmLoginDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)11754 UINT CmLoginDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
11755 {
11756 	// Validate arguments
11757 	wchar_t server_name[MAX_SIZE];
11758 	char password[MAX_PASSWORD_LEN + 1];
11759 	bool bad_pass;
11760 	if (hWnd == NULL)
11761 	{
11762 		return 0;
11763 	}
11764 
11765 	switch (msg)
11766 	{
11767 	case WM_INITDIALOG:
11768 		if (cm->server_name != NULL)
11769 		{
11770 			StrToUni(server_name, sizeof(server_name), cm->server_name);
11771 		}
11772 		else
11773 		{
11774 			UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));
11775 		}
11776 		FormatText(hWnd, S_TITLE, server_name);
11777 		break;
11778 
11779 	case WM_COMMAND:
11780 		switch (wParam)
11781 		{
11782 		case IDOK:
11783 			if (cm->server_name != NULL)
11784 			{
11785 				StrToUni(server_name, sizeof(server_name), cm->server_name);
11786 			}
11787 			else
11788 			{
11789 				UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));
11790 			}
11791 			GetTxtA(hWnd, E_PASSWORD, password, sizeof(password));
11792 			cm->Client = CcConnectRpc(cm->server_name == NULL ? "127.0.0.1" : cm->server_name,
11793 				password, &bad_pass, NULL, 0);
11794 			if (cm->Client == NULL)
11795 			{
11796 				MsgBox(hWnd, MB_ICONSTOP, _UU("CM_BAD_PASSWORD"));
11797 				FocusEx(hWnd, E_PASSWORD);
11798 			}
11799 			else
11800 			{
11801 				EndDialog(hWnd, true);
11802 			}
11803 			break;
11804 		case IDCANCEL:
11805 			Close(hWnd);
11806 			break;
11807 		}
11808 		break;
11809 
11810 	case WM_CLOSE:
11811 		EndDialog(hWnd, false);
11812 		break;
11813 	}
11814 
11815 	return 0;
11816 }
11817 
11818 // Login
LoginCM()11819 bool LoginCM()
11820 {
11821 	// Try to login with an empty password first
11822 	bool bad_pass, no_remote;
11823 	wchar_t server_name[MAX_SIZE];
11824 	RPC_CLIENT_VERSION a;
11825 
11826 RETRY:
11827 	if (cm->server_name != NULL)
11828 	{
11829 		StrToUni(server_name, sizeof(server_name), cm->server_name);
11830 	}
11831 	else
11832 	{
11833 		UniStrCpy(server_name, sizeof(server_name), _UU("CM_PW_LOCALMACHINE"));
11834 	}
11835 
11836 	// Attempt to connect
11837 	if ((cm->Client = CcConnectRpc(
11838 		cm->server_name == NULL ? "localhost" : cm->server_name,
11839 		cm->password == NULL ? "" : cm->password, &bad_pass, &no_remote, cm->StartupMode == false ? 0 : 60000)) == NULL)
11840 	{
11841 		if (no_remote)
11842 		{
11843 			// Remote connection was denied
11844 			if (MsgBoxEx(NULL, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("CM_NO_REMOTE"), server_name) == IDRETRY)
11845 			{
11846 				// Retry
11847 				goto RETRY;
11848 			}
11849 			else
11850 			{
11851 				return false;
11852 			}
11853 		}
11854 		else if (bad_pass)
11855 		{
11856 			if (Dialog(NULL, D_CM_LOGIN, CmLoginDlgProc, NULL) == false)
11857 			{
11858 				return false;
11859 			}
11860 		}
11861 		else
11862 		{
11863 			// Connection failure
11864 			if (cm->StartupMode == false && MsgBoxEx(NULL, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("CM_CONNECT_FAILED"), server_name) == IDRETRY)
11865 			{
11866 				// Retry
11867 				goto RETRY;
11868 			}
11869 			else
11870 			{
11871 				return false;
11872 			}
11873 		}
11874 	}
11875 
11876 	Zero(&a, sizeof(a));
11877 	CcGetClientVersion(cm->Client, &a);
11878 	if (a.ClientBuildInt >= 5192)
11879 	{
11880 		cm->CmSettingSupported = true;
11881 		cm->CmEasyModeSupported = true;
11882 		if (OS_IS_WINDOWS_9X(a.OsType))
11883 		{
11884 			cm->CmEasyModeSupported = false;
11885 		}
11886 	}
11887 
11888 	return true;
11889 }
11890 
11891 // Main process
MainCM()11892 void MainCM()
11893 {
11894 	// If there is /remote in the argument, show the screen of the remote connection
11895 	TOKEN_LIST *cmdline = GetCommandLineToken();
11896 
11897 	UINT i = 0;
11898 	bool isRemote = false;
11899 
11900 	if (cm->server_name != NULL)
11901 	{
11902 		Free(cm->server_name);
11903 	}
11904 	cm->server_name = NULL;
11905 
11906 	if (cm->password != NULL)
11907 	{
11908 		Free(cm->password);
11909 	}
11910 	cm->password = NULL;
11911 
11912 	for(i = 0; i < cmdline->NumTokens; ++i)
11913 	{
11914 		if (StrCmpi(cmdline->Token[i], "/remote") == 0)
11915 		{
11916 			isRemote = true;
11917 		}
11918 		else if (StrCmpi(cmdline->Token[i], "/hostname") == 0 && i + 1 < cmdline->NumTokens)
11919 		{
11920 			isRemote = true;
11921 			if (cm->server_name != NULL)
11922 			{
11923 				Free(cm->server_name);
11924 			}
11925 			cm->server_name = CopyStr(cmdline->Token[++i]);
11926 		}
11927 		else if (StrCmpi(cmdline->Token[i], "/password") == 0 && i + 1 < cmdline->NumTokens)
11928 		{
11929 			if (cm->password != NULL)
11930 			{
11931 				Free(cm->password);
11932 			}
11933 			cm->password = CopyStr(cmdline->Token[++i]);
11934 		}
11935 		else if (StrCmpi(cmdline->Token[i], "/startup") == 0)
11936 		{
11937 			// Startup mode
11938 			cm->StartupMode = true;
11939 		}
11940 	}
11941 
11942 	if (isRemote && cm->server_name == NULL)
11943 	{
11944 		char *hostname = RemoteDlg(NULL, CM_REG_KEY, ICO_VPN, _UU("CM_TITLE"), _UU("CM_REMOTE_TITLE"), NULL);
11945 		if (hostname == NULL)
11946 		{
11947 			return;
11948 		}
11949 		if (cm->server_name != NULL)
11950 		{
11951 			Free(cm->server_name);
11952 		}
11953 		cm->server_name = NULL;
11954 		if (StrCmpi(hostname, "localhost") != 0 && StrCmpi(hostname, "127.0.0.1") != 0 )
11955 		{
11956 			cm->server_name = hostname;
11957 		}
11958 	}
11959 
11960 	FreeToken(cmdline);
11961 
11962 	if (IsZero(cm->ShortcutKey, SHA1_SIZE) == false)
11963 	{
11964 		//if (MsGetCurrentTerminalSessionId() == 0)
11965 		{
11966 			// Start the shortcut connection
11967 			CmConnectShortcut(cm->ShortcutKey);
11968 		}/*
11969 		else
11970 		{
11971 			MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("CM_SHORTCUT_DESKTOP_MSG"),
11972 				MsGetCurrentTerminalSessionId());
11973 		}*/
11974 		return;
11975 	}
11976 
11977 	// Login
11978 	if (LoginCM() == false)
11979 	{
11980 		return;
11981 	}
11982 
11983 	//Update the jump list
11984 	CmUpdateJumpList(0);
11985 
11986 	// Main window
11987 	MainCMWindow();
11988 
11989 	// Log out
11990 	LogoutCM();
11991 
11992 	if (cm->Update != NULL)
11993 	{
11994 		FreeUpdateUi(cm->Update);
11995 		cm->Update = NULL;
11996 	}
11997 }
11998 
11999 // Log out
LogoutCM()12000 void LogoutCM()
12001 {
12002 	if (cm->Client != NULL)
12003 	{
12004 		CcDisconnectRpc(cm->Client);
12005 	}
12006 }
12007 
12008 // Client Connection Manager start function
CMExec()12009 void CMExec()
12010 {
12011 	// Initialize
12012 	InitCM(true);
12013 
12014 	// Main process
12015 	MainCM();
12016 
12017 	// Release
12018 	FreeCM();
12019 }
12020 
12021 // HUB enumeration thread
CmEnumHubThread(THREAD * t,void * param)12022 void CmEnumHubThread(THREAD *t, void *param)
12023 {
12024 	CM_ENUM_HUB *e = (CM_ENUM_HUB *)param;
12025 	HWND hWnd;
12026 	// Validate arguments
12027 	if (t == NULL || param == NULL)
12028 	{
12029 		return;
12030 	}
12031 
12032 	e->Thread = t;
12033 	hWnd = e->hWnd;
12034 	LockList(cm->EnumHubList);
12035 	{
12036 		Add(cm->EnumHubList, e);
12037 	}
12038 	UnlockList(cm->EnumHubList);
12039 
12040 	// Thread initialization is completed
12041 	NoticeThreadInit(t);
12042 
12043 	// Create a session
12044 	e->Session = NewRpcSession(cm->Cedar, e->ClientOption);
12045 	if (e->Session)
12046 	{
12047 		// Enumeration of HUB
12048 		e->Hub = EnumHub(e->Session);
12049 
12050 		if (e->Hub != NULL)
12051 		{
12052 			// Enumeration completed
12053 			// Add to the combo box
12054 			if (CbNum(hWnd, C_HUBNAME) == 0)
12055 			{
12056 				UINT i;
12057 				wchar_t tmp[MAX_SIZE];
12058 				for (i = 0;i < e->Hub->NumTokens;i++)
12059 				{
12060 					StrToUni(tmp, sizeof(tmp), e->Hub->Token[i]);
12061 					CbAddStr(hWnd, C_HUBNAME, tmp, 0);
12062 				}
12063 			}
12064 
12065 			// Release the memory
12066 			FreeToken(e->Hub);
12067 		}
12068 
12069 		// Release the session
12070 		ReleaseSession(e->Session);
12071 	}
12072 
12073 	LockList(cm->EnumHubList);
12074 	{
12075 		Delete(cm->EnumHubList, e);
12076 	}
12077 	UnlockList(cm->EnumHubList);
12078 
12079 	Free(e->ClientOption);
12080 	Free(e);
12081 }
12082 
12083 // The start of the HUB enumeration
CmEnumHubStart(HWND hWnd,CLIENT_OPTION * o)12084 void CmEnumHubStart(HWND hWnd, CLIENT_OPTION *o)
12085 {
12086 	CM_ENUM_HUB *e;
12087 	THREAD *t;
12088 	// Validate arguments
12089 	if (hWnd == NULL || o == NULL)
12090 	{
12091 		return;
12092 	}
12093 
12094 	if (StrLen(o->Hostname) == 0 ||
12095 		o->Port == 0)
12096 	{
12097 		return;
12098 	}
12099 
12100 	if (o->ProxyType != PROXY_DIRECT)
12101 	{
12102 		if (StrLen(o->ProxyName) == 0 ||
12103 			o->ProxyPort == 0)
12104 		{
12105 			return;
12106 		}
12107 	}
12108 
12109 	if (LvNum(hWnd, C_HUBNAME) != 0)
12110 	{
12111 		return;
12112 	}
12113 
12114 	e = ZeroMalloc(sizeof(CM_ENUM_HUB));
12115 	e->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
12116 	e->hWnd = hWnd;
12117 	Copy(e->ClientOption, o, sizeof(CLIENT_OPTION));
12118 
12119 	t = NewThread(CmEnumHubThread, e);
12120 	WaitThreadInit(t);
12121 	ReleaseThread(t);
12122 }
12123 
12124 // Initialize the HUB enumeration process
CmInitEnumHub()12125 void CmInitEnumHub()
12126 {
12127 	cm->EnumHubList = NewList(NULL);
12128 }
12129 
12130 // Release the HUB enumeration process
CmFreeEnumHub()12131 void CmFreeEnumHub()
12132 {
12133 	LIST *o;
12134 	UINT i;
12135 	if (cm->EnumHubList == NULL)
12136 	{
12137 		return;
12138 	}
12139 
12140 	o = NewList(NULL);
12141 	LockList(cm->EnumHubList);
12142 	{
12143 		UINT i;
12144 		for (i = 0;i < LIST_NUM(cm->EnumHubList);i++)
12145 		{
12146 			CM_ENUM_HUB *e = LIST_DATA(cm->EnumHubList, i);
12147 			Add(o, e->Thread);
12148 			AddRef(e->Thread->ref);
12149 		}
12150 	}
12151 	UnlockList(cm->EnumHubList);
12152 
12153 	for (i = 0;i < LIST_NUM(o);i++)
12154 	{
12155 		THREAD *t = LIST_DATA(o, i);
12156 		WaitThread(t, INFINITE);
12157 		ReleaseThread(t);
12158 	}
12159 	ReleaseList(o);
12160 
12161 	ReleaseList(cm->EnumHubList);
12162 }
12163 
12164 // Initialize the Client Connection Manager
12165 
InitCM(bool set_app_id)12166 void InitCM(bool set_app_id)
12167 {
12168 	UNI_TOKEN_LIST *ut;
12169 	if (cm != NULL)
12170 	{
12171 		return;
12172 	}
12173 
12174 	if (set_app_id)
12175 	{
12176 		if(JL_SetCurrentProcessExplicitAppUserModelID(APPID_CM) != S_OK)
12177 		{
12178 		}
12179 	}
12180 
12181 	CmDeleteOldStartupTrayFile();
12182 
12183 	MsSetShutdownParameters(0x4ff, SHUTDOWN_NORETRY);
12184 
12185 	// Memory allocation
12186 	cm = ZeroMalloc(sizeof(CM));
12187 
12188 	// If the command line argument is set treat it as a server name
12189 	ut = GetCommandLineUniToken();
12190 
12191 	if (ut->NumTokens >= 1)
12192 	{
12193 		if (UniStrLen(ut->Token[0]) != 0)
12194 		{
12195 			if (UniStrCmpi(ut->Token[0], L"cm") != 0 && ut->Token[0][0] != L'/')
12196 			{
12197 				BUF *b = UniStrToBin(ut->Token[0]);
12198 				if (b->Size == SHA1_SIZE)
12199 				{
12200 					// Treated as a shortcut key for the connection settings
12201 					Copy(cm->ShortcutKey, b->Buf, SHA1_SIZE);
12202 				}
12203 				else
12204 				{
12205 					if (UniEndWith(ut->Token[0], L".vpn") == false)
12206 					{
12207 						// Treated as a server name
12208 						cm->server_name = CopyUniToStr(ut->Token[0]);
12209 					}
12210 					else
12211 					{
12212 						// Treated as import file name
12213 						cm->import_file_name = CopyUniStr(ut->Token[0]);
12214 					}
12215 				}
12216 				FreeBuf(b);
12217 			}
12218 			else if (UniStrCmpi(ut->Token[0], L"/easy") == 0)
12219 			{
12220 				// Simple mode
12221 				if (ut->NumTokens >= 2)
12222 				{
12223 					// Connection settings to be imported is specified
12224 					cm->import_file_name = CopyUniStr(ut->Token[1]);
12225 				}
12226 
12227 				cm->CmSettingInitialFlag = CM_SETTING_INIT_EASY;
12228 			}
12229 			else if (UniStrCmpi(ut->Token[0], L"/normal") == 0)
12230 			{
12231 				// Normal mode
12232 				if (ut->NumTokens >= 2)
12233 				{
12234 					// Connection settings to be imported is specified
12235 					cm->import_file_name = CopyUniStr(ut->Token[1]);
12236 				}
12237 
12238 				cm->CmSettingInitialFlag = CM_SETTING_INIT_NORMAL;
12239 			}
12240 			else if (UniStrCmpi(ut->Token[0], L"/connect") == 0)
12241 			{
12242 				// Import process by the simple installer
12243 				if (ut->NumTokens >= 2)
12244 				{
12245 					// Connection settings to be imported is specified
12246 					cm->import_file_name = CopyUniStr(ut->Token[1]);
12247 				}
12248 
12249 				cm->CmSettingInitialFlag = CM_SETTING_INIT_CONNECT;
12250 			}
12251 			else if (UniStrCmpi(ut->Token[0], L"/select") == 0)
12252 			{
12253 				// Selection screen
12254 				cm->CmSettingInitialFlag = CM_SETTING_INIT_SELECT;
12255 			}
12256 		}
12257 	}
12258 
12259 	UniFreeToken(ut);
12260 
12261 	InitWinUi(_UU("CM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
12262 
12263 	// Alpha blending related
12264 	UseAlpha = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "UseAlpha");
12265 	AlphaValue = MsRegReadInt(REG_CURRENT_USER, CM_REG_KEY, "AlphaValue");
12266 
12267 	cm->Cedar = NewCedar(NULL, NULL);
12268 	CmInitEnumHub();
12269 }
12270 
12271 // Stop the Client Connection Manager
FreeCM()12272 void FreeCM()
12273 {
12274 	if (cm == NULL)
12275 	{
12276 		return;
12277 	}
12278 
12279 	CmFreeEnumHub();
12280 	ReleaseCedar(cm->Cedar);
12281 
12282 	FreeWinUi();
12283 
12284 	// Release the memory
12285 	if (cm->server_name != NULL)
12286 	{
12287 		Free(cm->server_name);
12288 	}
12289 	Free(cm);
12290 	cm = NULL;
12291 }
12292 
12293 
12294 
12295 //////////////////////////////////////////////////////////////////////////
12296 //JumpList ToDo
12297 // By Takao Ito
CmUpdateJumpList(UINT start_id)12298 void *CmUpdateJumpList(UINT start_id)
12299 {
12300 	HMENU h = NULL;
12301 	UINT i;
12302 	RPC_CLIENT_ENUM_ACCOUNT a;
12303 	LIST *o;
12304 	bool easy;
12305 
12306 	JL_PCustomDestinationList pcdl;
12307 	JL_PObjectCollection poc;
12308 	JL_PShellLink shell;
12309 	JL_PObjectArray poaRemoved;
12310 
12311 	HRESULT hr;
12312 
12313 	if (cm->server_name != NULL)
12314 	{
12315 		// Is not used in the case of an external PC
12316 		return NULL;
12317 	}
12318 
12319 	//Try to add
12320 	if(SUCCEEDED(JL_CreateCustomDestinationList(&pcdl,APPID_CM)))
12321 	{
12322 
12323 		JL_DeleteJumpList(pcdl,APPID_CM);
12324 
12325 		easy = cm->CmSetting.EasyMode;
12326 
12327 		Zero(&a, sizeof(a));
12328 
12329 
12330 		if (CcEnumAccount(cm->Client, &a) == ERR_NO_ERROR)
12331 		{
12332 			o = NewListFast(CiCompareClientAccountEnumItemByLastConnectDateTime);
12333 
12334 			for (i = 0;i < a.NumItem;i++)
12335 			{
12336 				RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = a.Items[i];
12337 
12338 				item->tmp1 = i;
12339 
12340 				if (item->LastConnectDateTime != 0)
12341 				{
12342 					Add(o, item);
12343 				}
12344 			}
12345 
12346 			Sort(o);
12347 
12348 			if(LIST_NUM(o) > 0)
12349 			{
12350 
12351 				if(SUCCEEDED(JL_BeginList(pcdl, &poaRemoved)))
12352 				{
12353 
12354 
12355 					//Create a collection
12356 					if(SUCCEEDED(JL_CreateObjectCollection(&poc)))
12357 					{
12358 
12359 						for (i = 0;i < MIN(LIST_NUM(o), CM_NUM_RECENT);i++)
12360 						{
12361 
12362 							RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = (RPC_CLIENT_ENUM_ACCOUNT_ITEM *)LIST_DATA(o, i);
12363 //							wchar_t tmp[MAX_PATH];
12364 							wchar_t *account_name;
12365 							char *server_name;
12366 							char *hub_name;
12367 //							CM_ACCOUNT *a;
12368 							UCHAR key[SHA1_SIZE];
12369 							RPC_CLIENT_GET_ACCOUNT c;
12370 
12371 
12372 							account_name = item->AccountName;
12373 							server_name = item->ServerName;
12374 							hub_name = item->HubName;
12375 
12376 
12377 
12378 							//
12379 							//a = CmGetExistAccountObject(hWnd, account_name);
12380 
12381 
12382 							//if (a == NULL)
12383 							//{
12384 							//continue;
12385 							//}
12386 
12387 							//Copy(key, a->ShortcutKey, SHA1_SIZE);
12388 							//
12389 
12390 							Zero(&c, sizeof(c));
12391 							UniStrCpy(c.AccountName, sizeof(c.AccountName), account_name);
12392 							if (CALL(NULL, CcGetAccount(cm->Client, &c)) == false)
12393 							{
12394 								break;
12395 							}
12396 
12397 							Copy(key, c.ShortcutKey, SHA1_SIZE);
12398 
12399 							if (IsZero(key, SHA1_SIZE))
12400 							{
12401 								//MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_SHORTCUT_UNSUPPORTED"));
12402 							}
12403 							else
12404 							{
12405 
12406 								//wchar_t target[MAX_PATH];
12407 								////wchar_t workdir[MAX_PATH];
12408 								//wchar_t args[MAX_PATH];
12409 								////wchar_t comment[MAX_SIZE];
12410 								//wchar_t icon[MAX_PATH];
12411 
12412 								char key_str[64];
12413 								wchar_t target[MAX_PATH];
12414 								//wchar_t workdir[MAX_PATH];
12415 								wchar_t args[MAX_PATH];
12416 								wchar_t commentW[MAX_SIZE];
12417 								wchar_t icon[MAX_PATH];
12418 								int iconNum;
12419 
12420 								//char icon = "C:\\Server.ico";
12421 
12422 								BinToStr(key_str, sizeof(key_str), key, SHA1_SIZE);
12423 								UniStrCpy(target, sizeof(target), MsGetExeFileNameW());
12424 								StrToUni(args, sizeof(args), key_str);
12425 								UniStrCpy(icon, sizeof(icon), MsGetExeFileNameW());
12426 								UniFormat(commentW, sizeof(commentW), _UU("CM_SHORTCUT_COMMENT"), account_name);
12427 
12428 								if(item->Connected)
12429 								{
12430 									iconNum = 1;
12431 								}
12432 								else
12433 								{
12434 									iconNum = 2;
12435 								}
12436 
12437 								hr = JL_CreateShellLink(
12438 									target,
12439 									args,
12440 									account_name,
12441 									icon,iconNum,
12442 									commentW,
12443 									&shell);
12444 
12445 								if(SUCCEEDED(hr))
12446 								{
12447 
12448 									if(SUCCEEDED(JL_ObjectCollectionAddShellLink(poc, shell)))
12449 									{
12450 										//Print("Add JumpList %d c:%s\n",i, comment);
12451 										//wprintf(comment);
12452 									}
12453 									JL_ReleaseShellLink(shell);
12454 								}
12455 							}
12456 
12457 							CiFreeClientGetAccount(&c);
12458 						}
12459 
12460 						hr = JL_AddCategoryToList(pcdl,poc,_UU("CM_JUMPLIST_RCCONNECT"),poaRemoved);
12461 
12462 						if(SUCCEEDED(hr))
12463 						{
12464 							//wprintf(L"AddCategory\n");
12465 
12466 							hr = JL_CommitList(pcdl);
12467 							if(SUCCEEDED(hr))
12468 							{
12469 								//wprintf(L"JumpList Commit\n");
12470 							}
12471 						}
12472 						else
12473 						{
12474 							//wprintf(L"Erro JumpList AddCategory %x\n", hr);
12475 						}
12476 
12477 						//Release
12478 						JL_ReleaseObjectCollection(poc);
12479 					}
12480 				}
12481 
12482 			}
12483 
12484 
12485 			ReleaseList(o);
12486 
12487 			CiFreeClientEnumAccount(&a);
12488 		}
12489 
12490 
12491 
12492 
12493 		/*
12494 			JL_BeginList(pcdl, &poaRemoved);
12495 
12496 			JL_CreateObjectCollection(&poc);
12497 
12498 			// Tesht
12499 			for (i = 0; i < 5; i++)
12500 			{
12501 
12502 				JL_CreateShellLink(
12503 					"",
12504 					"",
12505 					L"Connect",
12506 					NULL,0,
12507 					NULL,
12508 					&shell);
12509 				JL_ObjectCollectionAddShellLink(poc, shell);
12510 
12511 				JL_ReleaseShellLink(shell);
12512 
12513 			}
12514 
12515 			JL_AddCategoryToList(pcdl,poc,_UU("CM_JUMPLIST_RCCONNECT"),poaRemoved);
12516 			JL_CommitList(pcdl);
12517 			JL_ReleaseObjectCollection(poc);
12518 
12519 		JL_ReleaseCustomDestinationList(pcdl);
12520 		*/
12521 
12522 	}
12523 
12524 	return h;
12525 }
12526 
12527 
12528 
12529 #endif	// WIN32
12530 
12531 
12532