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