1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3 
4 
5 // WinUi.c
6 // User interface code for Win32
7 
8 #ifdef OS_WIN32
9 
10 #define WINUI_C
11 
12 #include "WinUi.h"
13 
14 #include "Client.h"
15 #include "CM.h"
16 #include "Protocol.h"
17 #include "Session.h"
18 #include "Win32Com.h"
19 
20 #include "Mayaqua/FileIO.h"
21 #include "Mayaqua/Internat.h"
22 #include "Mayaqua/Microsoft.h"
23 #include "Mayaqua/Memory.h"
24 #include "Mayaqua/Object.h"
25 #include "Mayaqua/Pack.h"
26 #include "Mayaqua/Secure.h"
27 #include "Mayaqua/Str.h"
28 #include "Mayaqua/Table.h"
29 #include "Mayaqua/Tick64.h"
30 #include "Mayaqua/Win32.h"
31 
32 #include "../PenCore/resource.h"
33 
34 #include <commdlg.h>
35 #include <shellapi.h>
36 #include <shlobj.h>
37 
38 // Process name list of incompatible anti-virus software
39 static BAD_PROCESS bad_processes[] =
40 {
41 	{"nod32krn.exe", "NOD32 Antivirus"},
42 	{"avp.exe", "Kaspersky"}
43 };
44 
45 static const UINT num_bad_processes = sizeof(bad_processes) / sizeof(bad_processes[0]);
46 
47 char cached_pin_code[MAX_SIZE] = {0};
48 UINT64 cached_pin_code_expires = 0;
49 
50 static HINSTANCE hDll = NULL;
51 static wchar_t *title_bar = NULL;
52 static char *font_name = NULL;
53 static UINT font_size = 9;
54 static HIMAGELIST large_image_list = NULL, small_image_list = NULL;
55 static LIST *icon_list = NULL;
56 static HINSTANCE hMsHtml = NULL;
57 static UINT init_winui_counter = 0;
58 static HDC hCommonDC = NULL;
59 static LOCK *lock_common_dc = NULL;
60 
61 bool UseAlpha = false;
62 UINT AlphaValue = 100;
63 
64 static THREAD *led_thread = NULL;
65 static bool thread_stop = false;
66 static bool g_led_special = false;
67 static bool g_tcpip_topmost = false;
68 static DWORD tls_current_wizard = 0xFFFFFFFF;
69 
70 #define WINUI_PSM_SHOWWIZBUTTONS              (WM_USER + 138)
71 #define WINUI_PropSheet_ShowWizButtons(hDlg, dwFlag, dwButton) \
72 	PSTMSG(hDlg, WINUI_PSM_SHOWWIZBUTTONS, (WPARAM)(dwFlag), (LPARAM)(dwButton))
73 
74 typedef struct _WINUI_SHSTOCKICONINFO
75 {
76 	DWORD cbSize;
77 	HICON hIcon;
78 	int   iSysImageIndex;
79 	int   iIcon;
80 	WCHAR szPath[MAX_PATH];
81 } WINUI_SHSTOCKICONINFO;
82 
83 // Get whether the current process is foreground
IsThisProcessForeground()84 bool IsThisProcessForeground()
85 {
86 	HWND hWnd = GetForegroundWindow();
87 	DWORD proc_id, thread_id;
88 
89 	if (hWnd == NULL)
90 	{
91 		return false;
92 	}
93 
94 	proc_id = 0;
95 	thread_id = GetWindowThreadProcessId(hWnd, &proc_id);
96 
97 	if (proc_id == MsGetCurrentProcessId())
98 	{
99 		return true;
100 	}
101 
102 	return false;
103 }
IsThisProcessForegroundForUpdateUi(UPDATE_CLIENT * c,void * p)104 bool IsThisProcessForegroundForUpdateUi(UPDATE_CLIENT *c, void *p)
105 {
106 	return IsThisProcessForeground();
107 }
108 
109 // Update notification screen dialog procedure
UpdateConfigDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)110 UINT UpdateConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
111 {
112 	WINUI_UPDATE *u = (WINUI_UPDATE *)param;
113 	UPDATE_CLIENT_SETTING s;
114 
115 	switch (msg)
116 	{
117 	case WM_INITDIALOG:
118 		SetTimer(hWnd, 1, 100, NULL);
119 
120 		LoadUpdateUiSetting(u, &s);
121 
122 		Check(hWnd, S_ENABLE, s.DisableCheck == false);
123 		Check(hWnd, S_DISABLE, s.DisableCheck);
124 
125 		DlgFont(hWnd, S_TITLE, 10, true);
126 		FormatText(hWnd, S_TITLE, u->SoftwareTitle);
127 		FormatText(hWnd, S_INFO, u->SoftwareTitle);
128 		break;
129 
130 	case WM_TIMER:
131 		switch (wParam)
132 		{
133 		case 1:
134 			if (u->UpdateClient->HaltFlag)
135 			{
136 				goto LABEL_CLOSE;
137 			}
138 			break;
139 		}
140 		break;
141 
142 	case WM_COMMAND:
143 		switch (wParam)
144 		{
145 		case IDCANCEL:
146 			Close(hWnd);
147 			break;
148 		}
149 		break;
150 
151 	case WM_CLOSE:
152 LABEL_CLOSE:
153 		LoadUpdateUiSetting(u, &s);
154 
155 		s.DisableCheck = IsChecked(hWnd, S_DISABLE);
156 
157 		if (s.DisableCheck)
158 		{
159 			s.LatestIgnoreBuild = 0;
160 		}
161 
162 		SaveUpdateUiSetting(u, &s);
163 
164 		SetUpdateClientSetting(u->UpdateClient, &s);
165 
166 		EndDialog(hWnd, !s.DisableCheck);
167 
168 		break;
169 	}
170 
171 	return 0;
172 }
173 
174 // Show the update notification setting screen
ConfigUpdateUi(WINUI_UPDATE * u,HWND hWnd)175 bool ConfigUpdateUi(WINUI_UPDATE *u, HWND hWnd)
176 {
177 	// Validate arguments
178 	if (u == NULL)
179 	{
180 		return false;
181 	}
182 
183 	return Dialog(hWnd, D_UPDATE_CONFIG, UpdateConfigDlgProc, u);
184 }
185 
186 // Update notification dialog procedure
UpdateNoticeDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)187 UINT UpdateNoticeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
188 {
189 	WINUI_UPDATE_DLG_PARAM *p = (WINUI_UPDATE_DLG_PARAM *)param;
190 	WINUI_UPDATE *u = NULL;
191 	UPDATE_CLIENT_SETTING s;
192 	char date_current[64];
193 	char date_latest[64];
194 	wchar_t date_current_str[128];
195 	wchar_t date_latest_str[128];
196 	char *font_name = NULL;
197 
198 	if (p != NULL)
199 	{
200 		u = p->Update;
201 	}
202 
203 	switch (msg)
204 	{
205 	case WM_INITDIALOG:
206 		Zero(date_current_str, sizeof(date_current_str));
207 		Zero(date_latest_str, sizeof(date_latest_str));
208 
209 		GetDateStr64(date_current, sizeof(date_current), u->CurrentDate);
210 		if (u->CurrentDate != 0)
211 		{
212 			UniFormat(date_current_str, sizeof(date_current_str), _UU("DLG_UPDATE_DATE"), date_current);
213 		}
214 
215 		GetDateStr64(date_latest, sizeof(date_latest), p->LatestDate);
216 		if (p->LatestDate != 0)
217 		{
218 			UniFormat(date_latest_str, sizeof(date_latest_str), _UU("DLG_UPDATE_DATE"), date_latest);
219 		}
220 
221 		FormatText(hWnd, 0, u->UpdateClient->SoftwareTitle);
222 		FormatText(hWnd, S_INFO, u->UpdateClient->SoftwareTitle);
223 		SetText(hWnd, S_PRODUCT_STR, u->UpdateClient->SoftwareTitle);
224 
225 		FormatText(hWnd, S_CURRENT_STR, u->CurrentVer / 100, u->CurrentVer % 100, u->CurrentBuild, date_current_str);
226 		FormatText(hWnd, S_LATEST_STR, p->LatestVer, date_latest_str);
227 
228 		if (MsIsWindows7())
229 		{
230 			if (_GETLANG() == 0)
231 			{
232 				font_name = GetMeiryoFontName();
233 			}
234 			else if (_GETLANG() == 2)
235 			{
236 				font_name = "Microsoft YaHei";
237 			}
238 			else if (_GETLANG() == 3)
239 			{
240 				font_name = "Microsoft JhengHei";
241 			}
242 		}
243 
244 		SetFont(hWnd, S_INFO, GetFont(font_name, 11, false, false, false, false));
245 		SetFont(hWnd, IDOK, GetFont(font_name, 0, true, false, false, false));
246 		SetFont(hWnd, IDCANCEL, GetFont(font_name, 0, false, false, false, false));
247 		SetFont(hWnd, S_PRODUCT_STR, GetFont(font_name, 10, true, false, false, false));
248 		SetFont(hWnd, S_CURRENT_STR, GetFont(font_name, 10, true, false, false, false));
249 		SetFont(hWnd, S_LATEST_STR, GetFont(font_name, 10, true, false, false, false));
250 
251 		SetFont(hWnd, S_PRODUCT, GetFont(font_name, 0, false, false, false, false));
252 		SetFont(hWnd, S_CURRENT, GetFont(font_name, 0, false, false, false, false));
253 		SetFont(hWnd, S_LATEST, GetFont(font_name, 0, false, false, false, false));
254 		SetFont(hWnd, B_CONFIG, GetFont(font_name, 0, false, false, false, false));
255 
256 		SetTimer(hWnd, 1, 100, NULL);
257 
258 		//MessageBeep(MB_ICONASTERISK);
259 		break;
260 
261 	case WM_COMMAND:
262 		switch (wParam)
263 		{
264 		case IDOK:	// Web View
265 			OnceMsgEx(hWnd, NULL, _UU("DLG_UPDATE_HINT"), true, ICO_INTERNET, (bool *)p->halt_flag);
266 
267 			ShellExecuteA(hWnd, "open", p->Url, NULL, NULL, SW_SHOWNORMAL);
268 			SleepThread(250);
269 
270 			// Ignore the update notification of this version for future
271 			LoadUpdateUiSetting(u, &s);
272 			s.LatestIgnoreBuild = p->LatestBuild;
273 			SaveUpdateUiSetting(u, &s);
274 
275 			EndDialog(hWnd, 1);
276 			break;
277 
278 		case IDCANCEL:	// Ignore this version
279 			LoadUpdateUiSetting(u, &s);
280 			s.LatestIgnoreBuild = p->LatestBuild;
281 			SaveUpdateUiSetting(u, &s);
282 			Close(hWnd);
283 			break;
284 
285 		case B_CONFIG:	// Show the notification settings screen
286 			p->IsInConfigDialog = true;
287 
288 			if (ConfigUpdateUi(u, hWnd) == false)
289 			{
290 				// Decided not to notify any more as a result of setting
291 				Close(hWnd);
292 			}
293 
294 			p->IsInConfigDialog = false;
295 			break;
296 		}
297 		break;
298 
299 	case WM_TIMER:
300 		switch (wParam)
301 		{
302 		case 1:
303 			if (p->IsInConfigDialog == false)
304 			{
305 				if (*(p->halt_flag))
306 				{
307 					// Close the screen forcibly
308 					EndDialog(hWnd, 0);
309 				}
310 			}
311 			break;
312 		}
313 		break;
314 
315 	case WM_CLOSE:	// Close
316 		EndDialog(hWnd, 0);
317 		break;
318 	}
319 
320 	return 0;
321 }
322 
323 // Update notification dialog
UpdateNotifyProcUi(UPDATE_CLIENT * c,UINT latest_build,UINT64 latest_date,char * latest_ver,char * url,volatile bool * halt_flag,void * param)324 void UpdateNotifyProcUi(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param)
325 {
326 	WINUI_UPDATE *u = (WINUI_UPDATE *)param;
327 	WINUI_UPDATE_DLG_PARAM p;
328 	// Validate arguments
329 	if (c == NULL || latest_build == 0 || latest_date == 0 || latest_ver == NULL || url == NULL || halt_flag == NULL || param == NULL)
330 	{
331 		return;
332 	}
333 
334 	if (u->UseSuppressFlag)
335 	{
336 		// Check the suppress flag
337 		if (MsRegReadIntEx2(REG_LOCAL_MACHINE, PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGKEY,
338 			PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGVALUE, false, true))
339 		{
340 			// Supress the dialog
341 			return;
342 		}
343 	}
344 
345 	if (u->CurrentlyDisabled)
346 	{
347 		// Hide
348 		return;
349 	}
350 
351 	// Show the update screen
352 	Zero(&p, sizeof(p));
353 
354 	p.Update = u;
355 	p.LatestBuild = latest_build;
356 	p.LatestDate = latest_date;
357 	p.LatestVer = latest_ver;
358 	p.Url = url;
359 	p.halt_flag = halt_flag;
360 
361 	Dialog(NULL, D_UPDATE_NOTICE, UpdateNoticeDlgProc, &p);
362 }
363 
364 // Initialize the update notification
InitUpdateUi(wchar_t * title,char * name,char * family_name,UINT64 current_date,UINT current_build,UINT current_ver,char * client_id,bool use_suppress_flag)365 WINUI_UPDATE *InitUpdateUi(wchar_t *title, char *name, char *family_name, UINT64 current_date, UINT current_build, UINT current_ver, char *client_id, bool use_suppress_flag)
366 {
367 	WINUI_UPDATE *u;
368 	UPDATE_CLIENT_SETTING s;
369 	LANGLIST t;
370 	// Validate arguments
371 	if (title == NULL || name == NULL || current_build == 0 || current_ver == 0)
372 	{
373 	return NULL;
374 	}
375 	if (MsIsWine())
376 	{
377 		return false;
378 	}
379 	if (IsEmptyStr(family_name))
380 	{
381 		family_name = UPDATE_FAMILY_NAME;
382 	}
383 
384 	u = ZeroMalloc(sizeof(WINUI_UPDATE));
385 
386 	StrCpy(u->ClientId, sizeof(u->ClientId), client_id);
387 	UniStrCpy(u->SoftwareTitle, sizeof(u->SoftwareTitle), title);
388 	StrCpy(u->SoftwareName, sizeof(u->SoftwareName), name);
389 	u->CurrentDate = current_date;
390 	u->CurrentBuild = current_build;
391 	u->CurrentVer = current_ver;
392 	u->UseSuppressFlag = use_suppress_flag;
393 
394 	Format(u->RegKey, sizeof(u->RegKey), WINUI_UPDATE_REGKEY, u->SoftwareName);
395 
396 	Zero(&s, sizeof(s));
397 	LoadUpdateUiSetting(u, &s);
398 
399 	Zero(&t, sizeof(t));
400 	GetCurrentLang(&t);
401 
402 	u->UpdateClient = NewUpdateClient(UpdateNotifyProcUi, IsThisProcessForegroundForUpdateUi, u, family_name, u->SoftwareName, u->SoftwareTitle,
403 		u->CurrentBuild, u->CurrentDate, t.Name, &s, client_id);
404 
405 	if (u->UpdateClient == NULL)
406 	{
407 		Free(u);
408 		return NULL;
409 	}
410 
411 	return u;
412 }
413 
414 // Disable the update notification UI
DisableUpdateUi(WINUI_UPDATE * u)415 void DisableUpdateUi(WINUI_UPDATE *u)
416 {
417 	// Validate arguments
418 	if (u == NULL)
419 	{
420 		return;
421 	}
422 
423 	u->CurrentlyDisabled = true;
424 }
425 
426 // Release the update notification
FreeUpdateUi(WINUI_UPDATE * u)427 void FreeUpdateUi(WINUI_UPDATE *u)
428 {
429 	// Validate arguments
430 	if (u == NULL)
431 	{
432 		return;
433 	}
434 
435 	if (u->UpdateClient != NULL)
436 	{
437 		FreeUpdateClient(u->UpdateClient);
438 	}
439 
440 	Free(u);
441 }
442 
443 // Read the current settings from the registry
LoadUpdateUiSetting(WINUI_UPDATE * u,UPDATE_CLIENT_SETTING * s)444 void LoadUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s)
445 {
446 	Zero(s, sizeof(UPDATE_CLIENT_SETTING));
447 	// Validate arguments
448 	if (u == NULL || s == NULL)
449 	{
450 		return;
451 	}
452 
453 	s->DisableCheck = MsRegReadInt(REG_CURRENT_USER, u->RegKey, "DisableCheck");
454 	s->LatestIgnoreBuild = MsRegReadInt(REG_CURRENT_USER, u->RegKey, "LatestIgnoreBuild");
455 }
456 
457 // Write the current settings to the registry
SaveUpdateUiSetting(WINUI_UPDATE * u,UPDATE_CLIENT_SETTING * s)458 void SaveUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s)
459 {
460 	// Validate arguments
461 	if (u == NULL || s == NULL)
462 	{
463 		return;
464 	}
465 
466 	MsRegWriteInt(REG_CURRENT_USER, u->RegKey, "DisableCheck", s->DisableCheck);
467 	MsRegWriteInt(REG_CURRENT_USER, u->RegKey, "LatestIgnoreBuild", s->LatestIgnoreBuild);
468 }
469 
470 // Set the UAC icon to the control in the dialog
SetUacIcon(HWND hWnd,UINT id)471 void SetUacIcon(HWND hWnd, UINT id)
472 {
473 	static HINSTANCE hShell32 = NULL;
474 	static HRESULT (__stdcall *_SHGetStockIconInfo)(UINT siid, UINT uFlags, void *psii) = NULL;
475 	bool ok = false;
476 	// Validate arguments
477 	if (hWnd == NULL)
478 	{
479 		return;
480 	}
481 
482 	if (hShell32 == NULL)
483 	{
484 		hShell32 = LoadLibraryA("shell32.dll");
485 	}
486 
487 	if (hShell32 != NULL)
488 	{
489 		if (_SHGetStockIconInfo == NULL)
490 		{
491 			_SHGetStockIconInfo = (HRESULT (__stdcall *)(UINT,UINT,void *))GetProcAddress(hShell32, "SHGetStockIconInfo");
492 		}
493 	}
494 
495 	if (_SHGetStockIconInfo != NULL)
496 	{
497 		WINUI_SHSTOCKICONINFO sii;
498 
499 		Zero(&sii, sizeof(sii));
500 
501 		sii.cbSize = sizeof(sii);
502 		if (_SHGetStockIconInfo(77, 0x000000100 | 0x000000001, &sii) == S_OK)
503 		{
504 			SendMessage(DlgItem(hWnd, id), STM_SETICON, (WPARAM)sii.hIcon, 0);
505 
506 			ok = true;
507 		}
508 	}
509 
510 	if (!ok)
511 	{
512 		Hide(hWnd, id);
513 	}
514 }
515 
516 // Procedure of the wizard page
WizardPageDefDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)517 UINT CALLBACK WizardPageDefDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
518 {
519 	DIALOG_PARAM *dp = (DIALOG_PARAM *)GetParam(hWnd);
520 	WIZARD_PAGE *wizard_page = NULL;
521 	WIZARD *wizard = NULL;
522 	UINT ret_value = 0;
523 	bool do_not_send_msg = false;
524 
525 	if (dp != NULL)
526 	{
527 		wizard_page = dp->wizard_page;
528 		wizard = wizard_page->Wizard;
529 	}
530 
531 	switch (msg)
532 	{
533 	case WM_INITDIALOG:
534 		{
535 			PROPSHEETPAGEW_V3 *t = (PROPSHEETPAGEW_V3 *)lParam;
536 			dp = (DIALOG_PARAM *)t->lParam;
537 			wizard_page = dp->wizard_page;
538 			wizard = wizard_page->Wizard;
539 
540 			wizard->hWndWizard = GetParent(hWnd);
541 			wizard_page->hWndPage = hWnd;
542 
543 			SetParam(hWnd, dp);
544 
545 			InitDialogInternational(hWnd, dp);
546 		}
547 		break;
548 
549 	case WM_CTLCOLORBTN:
550 	case WM_CTLCOLORDLG:
551 	case WM_CTLCOLOREDIT:
552 	case WM_CTLCOLORLISTBOX:
553 	case WM_CTLCOLORMSGBOX:
554 	case WM_CTLCOLORSCROLLBAR:
555 	case WM_CTLCOLORSTATIC:
556 		return (UINT)GetStockObject(WHITE_BRUSH);
557 		break;
558 
559 	case WM_NOTIFY:
560 		{
561 			NMHDR *pnmh = (NMHDR *)lParam;
562 			UINT ret = 0;
563 			UINT next_page = INFINITE;
564 
565 			switch (pnmh->code)
566 			{
567 			case PSN_SETACTIVE:		// Activate
568 				SetWizardButton(wizard_page, true, true, true, false);
569 				dp->wizard_proc(hWnd, WM_WIZ_SHOW, 0, 0, wizard, wizard_page, wizard->Param);
570 				break;
571 
572 			case PSN_KILLACTIVE:	// Deactivate
573 				dp->wizard_proc(hWnd, WM_WIZ_HIDE, 0, 0, wizard, wizard_page, wizard->Param);
574 				break;
575 
576 			case PSN_WIZNEXT:		// Determine the destination of [Next] button
577 				ret = dp->wizard_proc(hWnd, WM_WIZ_NEXT, 0, 0, wizard, wizard_page, wizard->Param);
578 				do_not_send_msg = true;
579 
580 				if (ret == 0)
581 				{
582 					SetWindowLong(hWnd, DWLP_MSGRESULT, -1);
583 				}
584 				else
585 				{
586 					SetWindowLong(hWnd, DWLP_MSGRESULT, ret);
587 				}
588 
589 				ret_value = 1;
590 				break;
591 
592 			case PSN_WIZBACK:		// Determine the destination of [back] button
593 				ret = dp->wizard_proc(hWnd, WM_WIZ_BACK, 0, 0, wizard, wizard_page, wizard->Param);
594 				do_not_send_msg = true;
595 
596 				if (ret == 0)
597 				{
598 					SetWindowLong(hWnd, DWLP_MSGRESULT, -1);
599 				}
600 				else
601 				{
602 					SetWindowLong(hWnd, DWLP_MSGRESULT, ret);
603 				}
604 
605 				ret_value = 1;
606 				break;
607 
608 			case PSN_QUERYCANCEL:	// Determine the process of the [Cancel] button
609 				if (dp->wizard_page->EnableClose == false)
610 				{
611 					SetWindowLong(hWnd, DWLP_MSGRESULT, 1);
612 				}
613 				else
614 				{
615 
616 					ret = dp->wizard_proc(hWnd, WM_WIZ_CLOSE, 0, 0, wizard, wizard_page, wizard->Param);
617 
618 					if (ret == 0)
619 					{
620 						if (IsEmptyUniStr(wizard->CloseConfirmMsg) == false &&
621 							MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, wizard->CloseConfirmMsg) == IDNO)
622 						{
623 							ret = 1;
624 						}
625 					}
626 
627 					if (ret == 0)
628 					{
629 						SetWindowLong(hWnd, DWLP_MSGRESULT, 0);
630 					}
631 					else
632 					{
633 						SetWindowLong(hWnd, DWLP_MSGRESULT, 1);
634 					}
635 				}
636 				ret_value = 1;
637 				do_not_send_msg = true;
638 				break;
639 			}
640 			break;
641 		}
642 	}
643 
644 	if (do_not_send_msg == false)
645 	{
646 		if (dp != NULL)
647 		{
648 			UINT ret = dp->wizard_proc(hWnd, msg, wParam, lParam, wizard, wizard_page, wizard->Param);
649 
650 			if (ret != 0)
651 			{
652 				ret_value = ret;
653 			}
654 		}
655 	}
656 
657 	if (msg == WM_INITDIALOG)
658 	{
659 		if (wizard->SetCenterFlag == false)
660 		{
661 			wizard->SetCenterFlag = true;
662 
663 			Center(wizard->hWndWizard);
664 		}
665 
666 		SetForegroundWindow(wizard->hWndWizard);
667 		SetActiveWindow(wizard->hWndWizard);
668 	}
669 
670 	return ret_value;
671 }
672 
673 // Button setting of the wizard
SetWizardButton(WIZARD_PAGE * p,bool enable_next,bool enable_back,bool enable_close,bool is_finish)674 void SetWizardButton(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish)
675 {
676 	SetWizardButtonEx(p, enable_next, enable_back, enable_close, is_finish, false);
677 }
SetWizardButtonEx(WIZARD_PAGE * p,bool enable_next,bool enable_back,bool enable_close,bool is_finish,bool shield_icon)678 void SetWizardButtonEx(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish, bool shield_icon)
679 {
680 	DWORD flags = 0;
681 	DWORD flags2 = 0;
682 	DWORD flags3 = 0;
683 	// Validate arguments
684 	if (p == NULL)
685 	{
686 		return;
687 	}
688 
689 	p->EnableNext = enable_next;
690 	p->EnableBack = enable_back;
691 	p->EnableClose = enable_close;
692 	p->IsFinish = is_finish;
693 
694 	if (is_finish == false)
695 	{
696 		if (p->EnableNext)
697 		{
698 			flags |= PSWIZB_NEXT;
699 			flags2 |= PSWIZB_NEXT;
700 
701 			if (shield_icon)
702 			{
703 				if (p->Wizard->IsAreoStyle)
704 				{
705 					if (MsIsAdmin() == false)
706 					{
707 						flags3 |= PSWIZBF_ELEVATIONREQUIRED;
708 					}
709 				}
710 			}
711 		}
712 	}
713 	else
714 	{
715 		if (p->EnableNext)
716 		{
717 			flags |= PSWIZB_FINISH;
718 			flags2 |= PSWIZB_FINISH;
719 		}
720 		else
721 		{
722 			flags |= PSWIZB_DISABLEDFINISH;
723 			flags2 |= PSWIZB_FINISH;
724 		}
725 	}
726 
727 	if (p->EnableBack)
728 	{
729 		flags |= PSWIZB_BACK;
730 		flags2 |= PSWIZB_BACK;
731 	}
732 
733 	if (p->EnableClose)
734 	{
735 		flags2 |= 0x00000010;
736 	}
737 
738 	PostMessage(p->Wizard->hWndWizard, PSM_SETWIZBUTTONS, flags3, flags);
739 
740 	SetEnable(p->Wizard->hWndWizard, IDCANCEL, p->EnableClose);
741 
742 	WINUI_PropSheet_ShowWizButtons(p->Wizard->hWndWizard,
743 		flags2, PSWIZB_BACK | PSWIZB_NEXT | PSWIZB_FINISH | 0x00000010);
744 
745 	if (p->EnableClose)
746 	{
747 		EnableClose(p->Wizard->hWndWizard);
748 	}
749 	else
750 	{
751 		DisableClose(p->Wizard->hWndWizard);
752 	}
753 }
754 
WizardCustomizedWindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)755 LRESULT CALLBACK WizardCustomizedWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
756 {
757 	WIZARD *wizard = (WIZARD *)TlsGetValue(tls_current_wizard);
758 
759 	if (wizard != NULL)
760 	{
761 		switch (msg)
762 		{
763 		case WM_CTLCOLORBTN:
764 		case WM_CTLCOLORDLG:
765 		case WM_CTLCOLOREDIT:
766 		case WM_CTLCOLORLISTBOX:
767 		case WM_CTLCOLORMSGBOX:
768 		case WM_CTLCOLORSCROLLBAR:
769 		case WM_CTLCOLORSTATIC:
770 			return (UINT)GetStockObject(WHITE_BRUSH);
771 			break;
772 		}
773 
774 		return CallWindowProcW(wizard->OriginalWindowProc, hWnd, msg, wParam, lParam);
775 	}
776 	else
777 	{
778 		return 0;
779 	}
780 }
781 
782 // Procedure of the wizard
WizardDlgProc(HWND hWnd,UINT msg,LPARAM lParam)783 UINT CALLBACK WizardDlgProc(HWND hWnd, UINT msg, LPARAM lParam)
784 {
785 	WIZARD *wizard = (WIZARD *)TlsGetValue(tls_current_wizard);
786 	switch (msg)
787 	{
788 	case PSCB_INITIALIZED:
789 		if (wizard != NULL)
790 		{
791 			if (wizard->hWndWizard != NULL)
792 			{
793 				wizard->hWndWizard = hWnd;
794 			}
795 
796 			if (wizard->ReplaceWindowProcFlag == false)
797 			{
798 				wizard->ReplaceWindowProcFlag = true;
799 
800 				wizard->OriginalWindowProc = (void *)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
801 				if (wizard->OriginalWindowProc != NULL)
802 				{
803 					SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)WizardCustomizedWindowProc);
804 				}
805 			}
806 		}
807 		break;
808 	}
809 
810 	return 0;
811 }
812 
813 // Jump to another wizard page
JumpWizard(WIZARD_PAGE * p,UINT next_id)814 void JumpWizard(WIZARD_PAGE *p, UINT next_id)
815 {
816 	// Validate arguments
817 	if (p == NULL || next_id == 0)
818 	{
819 		return;
820 	}
821 
822 	PropSheet_SetCurSelByID(p->Wizard->hWndWizard, next_id);
823 }
824 
825 // Close the wizard
CloseWizard(WIZARD_PAGE * p)826 void CloseWizard(WIZARD_PAGE *p)
827 {
828 	// Validate arguments
829 	if (p == NULL)
830 	{
831 		return;
832 	}
833 
834 	p->Wizard->CloseConfirmMsg = NULL;
835 	SetWizardButton(p, false, false, true, false);
836 
837 	if (p->Wizard->IsAreoStyle)
838 	{
839 		PropSheet_PressButton(p->hWndPage, PSBTN_CANCEL);
840 	}
841 	else
842 	{
843 		Close(p->Wizard->hWndWizard);
844 	}
845 }
846 
847 // Show the wizard
ShowWizard(HWND hWndParent,WIZARD * w,UINT start_id)848 void ShowWizard(HWND hWndParent, WIZARD *w, UINT start_id)
849 {
850 	void **pages_array;
851 	UINT num_pages;
852 	UINT i;
853 	PROPSHEETHEADERW_V2 h;
854 	WIZARD_PAGE *start_page;
855 	// Validate arguments
856 	if (w == NULL)
857 	{
858 		return;
859 	}
860 
861 	num_pages = LIST_NUM(w->Pages);
862 	pages_array = ZeroMalloc(sizeof(void *) * num_pages);
863 
864 	for (i = 0;i < num_pages;i++)
865 	{
866 		WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
867 
868 		pages_array[i] = CreateWizardPageInstance(w, p);
869 
870 		p->Index = i;
871 	}
872 
873 	Zero(&h, sizeof(h));
874 	h.dwSize = sizeof(PROPSHEETHEADERW_V2);
875 	h.dwFlags = PSH_WIZARD97 | PSH_HEADER | PSH_USEICONID | PSH_USECALLBACK;
876 
877 	if (MsIsAeroColor() == false)
878 	{
879 		// Aero Wizard can not be used If the color of Aero is disabled
880 		// even in Vista or later (if the background color is not white)
881 		w->IsAreoStyle = false;
882 	}
883 
884 	if (MsIsWindows10())
885 	{
886 		// Windows 10 Icon Bug: Disable Aero Style!
887 		w->IsAreoStyle = false;
888 	}
889 
890 	if (w->IsAreoStyle)
891 	{
892 		// Aero Wizard
893 		h.dwFlags = PSH_WIZARD | 0x00004000 | PSH_HEADER | PSH_USEICONID | PSH_USECALLBACK;
894 	}
895 
896 	h.hInstance = hDll;
897 	h.pszIcon = MAKEINTRESOURCEW(w->Icon);
898 	h.hwndParent = hWndParent;
899 	h.nPages = num_pages;
900 	h.phpage = (HPROPSHEETPAGE *)pages_array;
901 	h.pszbmHeader = MAKEINTRESOURCEW(w->Bitmap);
902 	h.pszCaption = w->Caption;
903 	h.pfnCallback = WizardDlgProc;
904 
905 	start_page = GetWizardPage(w, start_id);
906 	if (start_page != NULL)
907 	{
908 		h.nStartPage = start_page->Index;
909 	}
910 
911 	w->hWndParent = hWndParent;
912 	w->hWndWizard = NULL;
913 	w->SetCenterFlag = false;
914 
915 	TlsSetValue(tls_current_wizard, w);
916 
917 	PropertySheetW(&h);
918 
919 	TlsSetValue(tls_current_wizard, NULL);
920 
921 	Free(pages_array);
922 }
923 
924 // Create an instance of the wizard page
CreateWizardPageInstance(WIZARD * w,WIZARD_PAGE * p)925 void *CreateWizardPageInstance(WIZARD *w, WIZARD_PAGE *p)
926 {
927 	PROPSHEETPAGEW_V3 t;
928 	// Validate arguments
929 	if (w == NULL || p == NULL)
930 	{
931 		return NULL;
932 	}
933 
934 	Zero(&t, sizeof(t));
935 	t.dwSize = sizeof(PROPSHEETPAGEW_V3);
936 	t.dwFlags = PSP_USETITLE | PSP_USEHEADERTITLE;// | PSP_USEHEADERSUBTITLE;
937 	t.hInstance = hDll;
938 	t.pszTemplate = MAKEINTRESOURCEW(p->Id);
939 	t.pfnDlgProc = (DLGPROC)WizardPageDefDlgProc;
940 	t.pszHeaderTitle = p->Title;
941 	t.pszTitle = w->Caption;
942 
943 	if (p->DialogParam != NULL)
944 	{
945 		FreeBitmapList(p->DialogParam->BitmapList);
946 		Free(p->DialogParam);
947 	}
948 
949 	p->DialogParam = ZeroMalloc(sizeof(DIALOG_PARAM));
950 
951 	p->DialogParam->BitmapList = NewBitmapList();
952 	p->DialogParam->wizard = w;
953 	p->DialogParam->wizard_page = p;
954 	p->DialogParam->wizard_proc = p->Proc;
955 	p->DialogParam->param = w->Param;
956 	p->DialogParam->white = false;
957 	p->DialogParam->meiryo = false;
958 
959 	t.lParam = (LPARAM)p->DialogParam;
960 
961 	return CreatePropertySheetPageW(&t);
962 }
963 
964 // Create a new wizard
NewWizard(UINT icon,UINT bitmap,wchar_t * caption,void * param)965 WIZARD *NewWizard(UINT icon, UINT bitmap, wchar_t *caption, void *param)
966 {
967 	WIZARD *w = ZeroMalloc(sizeof(WIZARD));
968 
969 	w->Icon = icon;
970 	w->Pages = NewList(NULL);
971 	w->Param = param;
972 	w->Bitmap = bitmap;
973 	w->Caption = CopyUniStr(caption);
974 
975 	return w;
976 }
977 
978 // Release the wizard
FreeWizard(WIZARD * w)979 void FreeWizard(WIZARD *w)
980 {
981 	UINT i;
982 	// Validate arguments
983 	if (w == NULL)
984 	{
985 		return;
986 	}
987 
988 	for (i = 0;i < LIST_NUM(w->Pages);i++)
989 	{
990 		WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
991 
992 		FreeWizardPage(p);
993 	}
994 
995 	ReleaseList(w->Pages);
996 
997 	Free(w->Caption);
998 
999 	Free(w);
1000 }
1001 
1002 // Get the wizard page
GetWizardPage(WIZARD * w,UINT id)1003 WIZARD_PAGE *GetWizardPage(WIZARD *w, UINT id)
1004 {
1005 	UINT i;
1006 	// Validate arguments
1007 	if (w == NULL || id == 0)
1008 	{
1009 		return NULL;
1010 	}
1011 
1012 	for (i = 0;i < LIST_NUM(w->Pages);i++)
1013 	{
1014 		WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
1015 
1016 		if (p->Id == id)
1017 		{
1018 			return p;
1019 		}
1020 	}
1021 
1022 	return NULL;
1023 }
1024 
1025 // Add a wizard page
AddWizardPage(WIZARD * w,WIZARD_PAGE * p)1026 void AddWizardPage(WIZARD *w, WIZARD_PAGE *p)
1027 {
1028 	// Validate arguments
1029 	if (w == NULL || p == NULL)
1030 	{
1031 		return;
1032 	}
1033 
1034 	Add(w->Pages, p);
1035 
1036 	p->Wizard = w;
1037 }
1038 
1039 // Create a new wizard page
NewWizardPage(UINT id,WINUI_WIZARD_PROC * proc,wchar_t * title)1040 WIZARD_PAGE *NewWizardPage(UINT id, WINUI_WIZARD_PROC *proc, wchar_t *title)
1041 {
1042 	WIZARD_PAGE *p;
1043 	// Validate arguments
1044 	if (id == 0 || proc == NULL)
1045 	{
1046 		return NULL;
1047 	}
1048 
1049 	p = ZeroMalloc(sizeof(WIZARD_PAGE));
1050 	p->Id = id;
1051 	p->Proc = proc;
1052 	p->Title = CopyUniStr(title);
1053 
1054 	return p;
1055 }
1056 
1057 // Release the wizard page
FreeWizardPage(WIZARD_PAGE * p)1058 void FreeWizardPage(WIZARD_PAGE *p)
1059 {
1060 	// Validate arguments
1061 	if (p == NULL)
1062 	{
1063 		return;
1064 	}
1065 
1066 	if (p->DialogParam != NULL)
1067 	{
1068 		FreeBitmapList(p->DialogParam->BitmapList);
1069 		Free(p->DialogParam);
1070 	}
1071 
1072 	Free(p->Title);
1073 
1074 	Free(p);
1075 }
1076 
1077 // NIC information dialog procedure
NicInfoProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1078 UINT NicInfoProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1079 {
1080 	UI_NICINFO *info = (UI_NICINFO *)param;
1081 
1082 	switch (msg)
1083 	{
1084 	case WM_INITDIALOG:
1085 		NicInfoInit(hWnd, info);
1086 
1087 		SetTimer(hWnd, 1, 50, NULL);
1088 		break;
1089 
1090 	case WM_TIMER:
1091 		switch (wParam)
1092 		{
1093 		case 1:
1094 			KillTimer(hWnd, 1);
1095 
1096 			NicInfoOnTimer(hWnd, info);
1097 
1098 			SetTimer(hWnd, 1, 50, NULL);
1099 			break;
1100 
1101 		case 2:
1102 			KillTimer(hWnd, 2);
1103 			Close(hWnd);
1104 			break;
1105 		}
1106 		break;
1107 
1108 	case WM_COMMAND:
1109 		switch (wParam)
1110 		{
1111 		case IDOK:
1112 		case IDCANCEL:
1113 			Close(hWnd);
1114 			break;
1115 		}
1116 		break;
1117 
1118 	case WM_CLOSE:
1119 		KillTimer(hWnd, 1);
1120 		KillTimer(hWnd, 2);
1121 		EndDialog(hWnd, 0);
1122 		break;
1123 	}
1124 
1125 	return 0;
1126 }
NicInfoCloseAfterTime(HWND hWnd,UI_NICINFO * info,UINT tick)1127 void NicInfoCloseAfterTime(HWND hWnd, UI_NICINFO *info, UINT tick)
1128 {
1129 	UINT64 now;
1130 	UINT64 closetime;
1131 	// Validate arguments
1132 	if (hWnd == NULL || info == NULL)
1133 	{
1134 		return;
1135 	}
1136 
1137 	now = Tick64();
1138 	closetime = now + (UINT64)tick;
1139 
1140 	if (info->CloseAfterTime == 0 || info->CloseAfterTime >= closetime)
1141 	{
1142 		info->CloseAfterTime = closetime;
1143 		KillTimer(hWnd, 2);
1144 		SetTimer(hWnd, 2, tick, NULL);
1145 	}
1146 }
NicInfoShowStatus(HWND hWnd,UI_NICINFO * info,wchar_t * msg1,wchar_t * msg2,UINT icon,bool animate)1147 void NicInfoShowStatus(HWND hWnd, UI_NICINFO *info, wchar_t *msg1, wchar_t *msg2, UINT icon, bool animate)
1148 {
1149 	// Validate arguments
1150 	if (hWnd == NULL || info == NULL)
1151 	{
1152 		return;
1153 	}
1154 	if (icon == 0)
1155 	{
1156 		icon = ICO_TEST;
1157 	}
1158 	if (msg1 == NULL)
1159 	{
1160 		msg1 = L"";
1161 	}
1162 	if (msg2 == NULL)
1163 	{
1164 		msg2 = L"";
1165 	}
1166 
1167 	if (info->CurrentIcon != icon)
1168 	{
1169 		SetIcon(hWnd, S_ICON, icon);
1170 		info->CurrentIcon = icon;
1171 	}
1172 
1173 	SetText(hWnd, S_STATUS1, msg1);
1174 	SetText(hWnd, S_STATUS2, msg2);
1175 
1176 	SetShow(hWnd, P_BAR, animate);
1177 }
NicInfoRefresh(HWND hWnd,UI_NICINFO * info)1178 void NicInfoRefresh(HWND hWnd, UI_NICINFO *info)
1179 {
1180 	MS_ADAPTER *a;
1181 	IP ip;
1182 	char ip_str[MAX_SIZE];
1183 	char title[MAX_SIZE];
1184 	UINT i;
1185 	wchar_t tmp[MAX_SIZE];
1186 	bool has_ip = false;
1187 	// Validate arguments
1188 	if (hWnd == NULL || info == NULL)
1189 	{
1190 		return;
1191 	}
1192 
1193 	Format(title, sizeof(title), VLAN_ADAPTER_NAME_TAG, info->NicName);
1194 
1195 	a = MsGetAdapter(title);
1196 	if (a == NULL)
1197 	{
1198 		Close(hWnd);
1199 		return;
1200 	}
1201 
1202 	// Check whether an IP address is assigned
1203 	Zero(&ip, sizeof(ip));
1204 	for (i = 0;i < MAX_MS_ADAPTER_IP_ADDRESS;i++)
1205 	{
1206 		if (IsZeroIP(&a->IpAddresses[i]) == false)
1207 		{
1208 			Copy(&ip, &a->IpAddresses[i], sizeof(IP));
1209 
1210 			if (!(IPV4(ip.address)[0] == 169 && IPV4(ip.address)[1] == 254))
1211 			{
1212 				has_ip = true;
1213 			}
1214 		}
1215 	}
1216 	IPToStr(ip_str, sizeof(ip_str), &ip);
1217 
1218 	if (has_ip == false)
1219 	{
1220 		if (a->UseDhcp)
1221 		{
1222 			NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_1"), ICO_NIC_OFFLINE, true);
1223 		}
1224 		else
1225 		{
1226 			NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_2"), ICO_NIC_OFFLINE, true);
1227 		}
1228 	}
1229 	else
1230 	{
1231 		if (a->UseDhcp)
1232 		{
1233 			UniFormat(tmp, sizeof(tmp), _UU("NICINFO_2_1"), ip_str);
1234 			NicInfoShowStatus(hWnd, info, _UU("NICINFO_2"), tmp, ICO_NIC_ONLINE, false);
1235 		}
1236 		else
1237 		{
1238 			UniFormat(tmp, sizeof(tmp), _UU("NICINFO_3_1"), ip_str);
1239 			NicInfoShowStatus(hWnd, info, _UU("NICINFO_3"), tmp, ICO_NIC_ONLINE, false);
1240 		}
1241 
1242 		NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_2);
1243 	}
1244 
1245 	MsFreeAdapter(a);
1246 }
NicInfoInit(HWND hWnd,UI_NICINFO * info)1247 void NicInfoInit(HWND hWnd, UI_NICINFO *info)
1248 {
1249 	// Validate arguments
1250 	if (hWnd == NULL || info == NULL)
1251 	{
1252 		return;
1253 	}
1254 
1255 	// Show a progress bar
1256 	SendMsg(hWnd, P_BAR, PBM_SETMARQUEE, TRUE, 150);
1257 	SetStyle(hWnd, P_BAR, PBS_MARQUEE);
1258 
1259 	DlgFont(hWnd, S_STATUS1, 9, false);
1260 	DlgFont(hWnd, S_STATUS2, 11, false);
1261 
1262 	SetIcon(hWnd, 0, ICO_NIC_ONLINE);
1263 
1264 	FormatText(hWnd, 0, info->NicName);
1265 
1266 	NicInfoRefresh(hWnd, info);
1267 
1268 	NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_1);
1269 }
NicInfoOnTimer(HWND hWnd,UI_NICINFO * info)1270 void NicInfoOnTimer(HWND hWnd, UI_NICINFO *info)
1271 {
1272 	// Validate arguments
1273 	if (hWnd == NULL || info == NULL)
1274 	{
1275 		return;
1276 	}
1277 
1278 	if (info->Halt)
1279 	{
1280 		Close(hWnd);
1281 		return;
1282 	}
1283 
1284 	if (info->RouteChange != NULL &&
1285 		IsRouteChanged(info->RouteChange) == false)
1286 	{
1287 		return;
1288 	}
1289 
1290 	NicInfoRefresh(hWnd, info);
1291 }
1292 
1293 // Show the NIC information dialog
NicInfo(UI_NICINFO * info)1294 void NicInfo(UI_NICINFO *info)
1295 {
1296 	// Validate arguments
1297 	if (info == NULL)
1298 	{
1299 		return;
1300 	}
1301 
1302 	info->RouteChange = NewRouteChange();
1303 
1304 	DialogEx2(NULL, D_NICINFO, NicInfoProc, info, true, true);
1305 
1306 	FreeRouteChange(info->RouteChange);
1307 	info->RouteChange = NULL;
1308 }
1309 
1310 // TCP connection thread
WinConnectDlgThread(THREAD * thread,void * param)1311 void WinConnectDlgThread(THREAD *thread, void *param)
1312 {
1313 	SOCK *s;
1314 	WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;
1315 	UINT nat_t_error_code;
1316 	char *nat_t_svc_name = NULL;
1317 	// Validate arguments
1318 	if (d == NULL || thread == NULL)
1319 	{
1320 		return;
1321 	}
1322 
1323 	// Socket connection
1324 	if (IsEmptyStr(d->nat_t_svc_name) == false)
1325 	{
1326 		nat_t_svc_name = d->nat_t_svc_name;
1327 	}
1328 
1329 	s = ConnectEx3(d->hostname, d->port, d->timeout, &d->cancel, nat_t_svc_name, &nat_t_error_code, d->try_start_ssl, false);
1330 
1331 	d->ret_sock = s;
1332 	d->nat_t_error_code = nat_t_error_code;
1333 
1334 	PostMessageA(d->hWnd, WM_APP + 68, 0, 0);
1335 }
1336 
1337 // TCP connection dialog procedure
WinConnectDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1338 UINT WinConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1339 {
1340 	WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;
1341 	// Validate arguments
1342 	if (hWnd == NULL || d == NULL)
1343 	{
1344 		return 0;
1345 	}
1346 
1347 	switch (msg)
1348 	{
1349 	case WM_INITDIALOG:
1350 		// UI setting
1351 		CenterParent(hWnd);
1352 		SetText(hWnd, 0, d->caption);
1353 		SetText(hWnd, S_INFO, d->info);
1354 		SetIcon(hWnd, S_ICON, d->icon_id);
1355 		d->hWnd = hWnd;
1356 
1357 		// Show a progress bar
1358 		SendMsg(hWnd, IDC_PROGRESS1, PBM_SETMARQUEE, TRUE, 100);
1359 		SetStyle(hWnd, IDC_PROGRESS1, PBS_MARQUEE);
1360 
1361 		// Create a thread
1362 		d->thread = NewThread(WinConnectDlgThread, d);
1363 		break;
1364 
1365 	case WM_COMMAND:
1366 		switch (wParam)
1367 		{
1368 		case IDCANCEL:
1369 			Close(hWnd);
1370 			break;
1371 		}
1372 		break;
1373 
1374 	case WM_APP + 68:
1375 	case WM_CLOSE:
1376 		if (d->cancel == false)
1377 		{
1378 			d->cancel = true;
1379 			Disable(hWnd, IDCANCEL);
1380 			if (d->ret_sock == NULL)
1381 			{
1382 				SetText(hWnd, S_INFO, _UU("CONNECTDLG_CANCELING"));
1383 			}
1384 			DoEvents(hWnd);
1385 			Refresh(hWnd);
1386 			WaitThread(d->thread, INFINITE);
1387 			ReleaseThread(d->thread);
1388 			EndDialog(hWnd, 0);
1389 		}
1390 		break;
1391 	}
1392 
1393 	return 0;
1394 }
1395 
1396 // TCP connection with showing the UI
WinConnectEx3(HWND hWnd,char * server,UINT port,UINT timeout,UINT icon_id,wchar_t * caption,wchar_t * info,UINT * nat_t_error_code,char * nat_t_svc_name,bool try_start_ssl)1397 SOCK *WinConnectEx3(HWND hWnd, char *server, UINT port, UINT timeout, UINT icon_id, wchar_t *caption, wchar_t *info, UINT *nat_t_error_code, char *nat_t_svc_name, bool try_start_ssl)
1398 {
1399 	wchar_t tmp[MAX_SIZE];
1400 	wchar_t tmp2[MAX_SIZE];
1401 	WINCONNECT_DLG_DATA d;
1402 	// Validate arguments
1403 	if (server == NULL || port == 0)
1404 	{
1405 		return NULL;
1406 	}
1407 	if (icon_id == 0)
1408 	{
1409 		icon_id = ICO_USER_ADMIN;
1410 	}
1411 	if (caption == NULL)
1412 	{
1413 		if (hWnd == NULL)
1414 		{
1415 			caption = _UU("CONNECTDLG_CAPTION");
1416 		}
1417 		else
1418 		{
1419 			GetTxt(hWnd, 0, tmp2, sizeof(tmp2));
1420 			caption = tmp2;
1421 		}
1422 	}
1423 	if (info == NULL)
1424 	{
1425 		UniFormat(tmp, sizeof(tmp), _UU("CONNECTDLG_MESSAGE"), server, port);
1426 
1427 		info = tmp;
1428 	}
1429 
1430 	Zero(&d, sizeof(d));
1431 
1432 	d.try_start_ssl = try_start_ssl;
1433 	d.cancel = false;
1434 	d.caption = caption;
1435 	d.icon_id = icon_id;
1436 	d.info = info;
1437 	d.timeout = timeout;
1438 	d.hostname = server;
1439 	d.port = port;
1440 	StrCpy(d.nat_t_svc_name, sizeof(d.nat_t_svc_name), nat_t_svc_name);
1441 
1442 	Dialog(hWnd, D_CONNECT, WinConnectDlgProc, &d);
1443 
1444 	if (nat_t_error_code != NULL)
1445 	{
1446 		*nat_t_error_code = d.nat_t_error_code;
1447 	}
1448 
1449 	return d.ret_sock;
1450 }
1451 
1452 // Show the Windows Network Setup screen
ShowWindowsNetworkConnectionDialog()1453 bool ShowWindowsNetworkConnectionDialog()
1454 {
1455 	wchar_t exe_name[MAX_SIZE];
1456 	void *proc;
1457 
1458 	CombinePathW(exe_name, sizeof(exe_name), MsGetSystem32DirW(), L"control.exe");
1459 
1460 	proc = Win32RunEx2W(exe_name, L"netconnections", false, NULL);
1461 
1462 	if (proc == NULL)
1463 	{
1464 		return false;
1465 	}
1466 
1467 	Win32CloseProcess(proc);
1468 
1469 	return true;
1470 }
1471 
1472 // Get the best Meiryo font name for the current OS
GetMeiryoFontName()1473 char *GetMeiryoFontName()
1474 {
1475 	if (MsIsWindows7())
1476 	{
1477 		return "Meiryo UI";
1478 	}
1479 	else
1480 	{
1481 		return "Meiryo";
1482 	}
1483 }
1484 
1485 // Get the Meiryo font
GetMeiryoFont()1486 HFONT GetMeiryoFont()
1487 {
1488 	return GetMeiryoFontEx(0);
1489 }
GetMeiryoFontEx(UINT font_size)1490 HFONT GetMeiryoFontEx(UINT font_size)
1491 {
1492 	return GetMeiryoFontEx2(font_size, false);
1493 }
GetMeiryoFontEx2(UINT font_size,bool bold)1494 HFONT GetMeiryoFontEx2(UINT font_size, bool bold)
1495 {
1496 	if (_GETLANG() == 0)
1497 	{
1498 		return GetFont(GetMeiryoFontName(), font_size, bold, false, false, false);
1499 	}
1500 	else if (_GETLANG() == 2)
1501 	{
1502 		return GetFont("Microsoft YaHei", font_size, bold, false, false, false);
1503 	}
1504 	else if (_GETLANG() == 3)
1505 	{
1506 		return GetFont("Microsoft JhengHei", font_size, bold, false, false, false);
1507 	}
1508 	else
1509 	{
1510 		return GetFont(NULL, font_size, bold, false, false, false);
1511 	}
1512 }
1513 
1514 // Set font to Meiryo
SetFontMeiryo(HWND hWnd,UINT id,UINT font_size)1515 void SetFontMeiryo(HWND hWnd, UINT id, UINT font_size)
1516 {
1517 	SetFont(hWnd, id, GetMeiryoFontEx(font_size));
1518 }
1519 
1520 // Set as the default font
SetFontDefault(HWND hWnd,UINT id)1521 void SetFontDefault(HWND hWnd, UINT id)
1522 {
1523 	SetFont(hWnd, id, GetDialogDefaultFont());
1524 }
1525 
1526 // Display the warning messages about bad process
ShowBadProcessWarning(HWND hWnd,BAD_PROCESS * bad)1527 void ShowBadProcessWarning(HWND hWnd, BAD_PROCESS *bad)
1528 {
1529 	wchar_t title[MAX_SIZE];
1530 	wchar_t message[8192];
1531 	// Validate arguments
1532 	if (bad == NULL)
1533 	{
1534 		return;
1535 	}
1536 
1537 	UniFormat(title, sizeof(title), _UU("BAD_PROCESS_TITLE"), bad->Title);
1538 	UniFormat(message, sizeof(message), _UU("BAD_PROCESS_MESSAGE"),
1539 		bad->Title, bad->Title, bad->Title, bad->Title);
1540 
1541 	OnceMsg(hWnd, title, message, true, ICO_WARNING);
1542 }
1543 
1544 // If there is process which is included in incompatible anti-virus software list, show appropriate
CheckBadProcesses(HWND hWnd)1545 bool CheckBadProcesses(HWND hWnd)
1546 {
1547 	bool ret = true;
1548 	UINT i;
1549 	LIST *o;
1550 
1551 	o = MsGetProcessList();
1552 
1553 	for (i = 0;i < LIST_NUM(o);i++)
1554 	{
1555 		MS_PROCESS *p = LIST_DATA(o, i);
1556 		char exe[MAX_PATH];
1557 		BAD_PROCESS *bad;
1558 
1559 		GetFileNameFromFilePath(exe, sizeof(exe), p->ExeFilename);
1560 
1561 		bad = IsBadProcess(exe);
1562 
1563 		if (bad != NULL)
1564 		{
1565 			// Display the message because a bad process have been found
1566 			ret = false;
1567 
1568 			ShowBadProcessWarning(hWnd, bad);
1569 		}
1570 	}
1571 
1572 	MsFreeProcessList(o);
1573 
1574 	return ret;
1575 }
1576 
1577 // Search whether the specified process name is the appropriate to a bad process
IsBadProcess(char * exe)1578 BAD_PROCESS *IsBadProcess(char *exe)
1579 {
1580 	UINT i;
1581 	// Validate arguments
1582 	if (exe == NULL)
1583 	{
1584 		return NULL;
1585 	}
1586 
1587 	for (i = 0;i < num_bad_processes;i++)
1588 	{
1589 		BAD_PROCESS *bad = &bad_processes[i];
1590 
1591 		if (StrCmpi(bad->ExeName, exe) == 0)
1592 		{
1593 			return bad;
1594 		}
1595 	}
1596 
1597 	return NULL;
1598 }
1599 
1600 // Message display procedure
OnceMsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1601 UINT OnceMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1602 {
1603 	ONCEMSG_DLG *d = (ONCEMSG_DLG *)param;
1604 	// Validate arguments
1605 	if (hWnd == NULL)
1606 	{
1607 		return 0;
1608 	}
1609 
1610 	switch (msg)
1611 	{
1612 	case WM_INITDIALOG:
1613 		SetText(hWnd, 0, d->Title);
1614 		SetText(hWnd, E_TEXT, d->Message);
1615 		SetShow(hWnd, C_DONTSHOWAGAIN, d->ShowCheckbox);
1616 		//DisableClose(hWnd);
1617 		Focus(hWnd, IDCANCEL);
1618 		if (d->Icon != 0)
1619 		{
1620 			SetIcon(hWnd, 0, d->Icon);
1621 		}
1622 
1623 		SetFont(hWnd, E_TEXT, GetMeiryoFont());
1624 
1625 		SetTimer(hWnd, 1, 50, NULL);
1626 		break;
1627 
1628 	case WM_TIMER:
1629 		switch (wParam)
1630 		{
1631 		case 1:
1632 			if (*d->halt)
1633 			{
1634 				Close(hWnd);
1635 			}
1636 			break;
1637 		}
1638 		break;
1639 
1640 	case WM_COMMAND:
1641 		switch (wParam)
1642 		{
1643 		case IDOK:
1644 		case IDCANCEL:
1645 			Close(hWnd);
1646 			break;
1647 		}
1648 		break;
1649 
1650 	case WM_CLOSE:
1651 		KillTimer(hWnd, 1);
1652 		d->Checked = IsChecked(hWnd, C_DONTSHOWAGAIN);
1653 		EndDialog(hWnd, 0);
1654 		break;
1655 	}
1656 
1657 	return 0;
1658 }
1659 
1660 // Show a message
OnceMsg(HWND hWnd,wchar_t * title,wchar_t * message,bool show_checkbox,UINT icon)1661 void OnceMsg(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon)
1662 {
1663 	OnceMsgEx(hWnd, title, message, show_checkbox, icon, NULL);
1664 }
OnceMsgEx(HWND hWnd,wchar_t * title,wchar_t * message,bool show_checkbox,UINT icon,bool * halt)1665 void OnceMsgEx(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon, bool *halt)
1666 {
1667 	ONCEMSG_DLG d;
1668 	UINT hash;
1669 	char valuename[MAX_PATH];
1670 	bool b_dummy = false;
1671 	// Validate arguments
1672 	if (title == NULL)
1673 	{
1674 		title = title_bar;
1675 	}
1676 	if (message == NULL)
1677 	{
1678 		message = L"message";
1679 	}
1680 	if (halt == NULL)
1681 	{
1682 		halt = &b_dummy;
1683 	}
1684 
1685 	Zero(&d, sizeof(d));
1686 	d.Message = message;
1687 	d.Title = title;
1688 	d.ShowCheckbox = show_checkbox;
1689 	d.Icon = icon;
1690 	d.halt = halt;
1691 
1692 	hash = GetOnceMsgHash(title, message);
1693 	Format(valuename, sizeof(valuename), ONCE_MSG_REGVALUE, hash);
1694 
1695 	if (MsRegReadInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename) == 0)
1696 	{
1697 		switch (icon)
1698 		{
1699 		case ICO_WARNING:
1700 			MessageBeep(MB_ICONEXCLAMATION);
1701 			break;
1702 
1703 		case ICO_INFORMATION:
1704 			MessageBeep(MB_ICONASTERISK);
1705 			break;
1706 		}
1707 
1708 		Dialog(hWnd, D_ONCEMSG, OnceMsgProc, &d);
1709 
1710 		if (show_checkbox)
1711 		{
1712 			if (d.Checked)
1713 			{
1714 				MsRegWriteInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename, 1);
1715 			}
1716 		}
1717 	}
1718 }
1719 
1720 // Get the message hash
GetOnceMsgHash(wchar_t * title,wchar_t * message)1721 UINT GetOnceMsgHash(wchar_t *title, wchar_t *message)
1722 {
1723 	BUF *b;
1724 	UCHAR hash[SHA1_SIZE];
1725 	UINT ret;
1726 	// Validate arguments
1727 	if (title == NULL)
1728 	{
1729 		title = title_bar;
1730 	}
1731 	if (message == NULL)
1732 	{
1733 		message = L"message";
1734 	}
1735 
1736 	b = NewBuf();
1737 	// 2013.5.19: Exclude the title from the hash calculation
1738 	//WriteBuf(b, title, UniStrSize(title));
1739 	WriteBuf(b, message, UniStrSize(message));
1740 	Sha1(hash, b->Buf, b->Size);
1741 	FreeBuf(b);
1742 
1743 	Copy(&ret, hash, sizeof(UINT));
1744 
1745 	return ret;
1746 }
1747 
1748 // Set a theme for Windows Vista
InitVistaWindowTheme(HWND hWnd)1749 void InitVistaWindowTheme(HWND hWnd)
1750 {
1751 	static HINSTANCE hInstDll = NULL;
1752 	HRESULT (WINAPI *_SetWindowTheme)(HWND, LPCWSTR, LPCWSTR) = NULL;
1753 
1754 	if (hInstDll == NULL)
1755 	{
1756 		hInstDll = LoadLibraryA("uxtheme.dll");
1757 	}
1758 
1759 	if (hInstDll == NULL)
1760 	{
1761 		return;
1762 	}
1763 
1764 	if (_SetWindowTheme == NULL)
1765 	{
1766 		_SetWindowTheme = (HRESULT (WINAPI *)(HWND,LPCWSTR,LPCWSTR))GetProcAddress(hInstDll, "SetWindowTheme");
1767 	}
1768 
1769 	if (_SetWindowTheme == NULL)
1770 	{
1771 		return;
1772 	}
1773 
1774 	_SetWindowTheme(hWnd, L"explorer", NULL);
1775 }
1776 
1777 // Register all applications to be registered in the Windows firewall
1778 // that may be present in the current directory
RegistWindowsFirewallAll()1779 void RegistWindowsFirewallAll()
1780 {
1781 	char exedir[MAX_SIZE];
1782 
1783 	GetExeDir(exedir, sizeof(exedir));
1784 
1785 	RegistWindowsFirewallAllEx(exedir);
1786 }
RegistWindowsFirewallAllEx(char * dir)1787 void RegistWindowsFirewallAllEx(char *dir)
1788 {
1789 	MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "vpnclient.exe", dir);
1790 	MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "vpncmgr.exe", dir);
1791 	MsRegistWindowsFirewallEx2(CEDAR_MANAGER_STR, "vpnsmgr.exe", dir);
1792 	MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "vpnserver.exe", dir);
1793 	MsRegistWindowsFirewallEx2(CEDAR_BRIDGE_STR, "vpnbridge.exe", dir);
1794 	MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "vpncmd.exe", dir);
1795 	MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "vpntest.exe", dir);
1796 }
1797 
1798 // Check whether the notification service is already running
Win32CnCheckAlreadyExists(bool lock)1799 bool Win32CnCheckAlreadyExists(bool lock)
1800 {
1801 	char tmp[MAX_SIZE];
1802 	HANDLE hMutex;
1803 
1804 	HashInstanceNameLocal(tmp, sizeof(tmp), CLIENT_NOTIFY_SERVICE_INSTANCENAME);
1805 
1806 	hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, tmp);
1807 	if (hMutex != NULL)
1808 	{
1809 		CloseHandle(hMutex);
1810 		return true;
1811 	}
1812 
1813 	if (lock == false)
1814 	{
1815 		return false;
1816 	}
1817 
1818 	hMutex = CreateMutex(NULL, FALSE, tmp);
1819 	if (hMutex == NULL)
1820 	{
1821 		CloseHandle(hMutex);
1822 		return true;
1823 	}
1824 
1825 	return false;
1826 }
1827 
1828 // Show the Easter Egg
ShowEasterEgg(HWND hWnd)1829 void ShowEasterEgg(HWND hWnd)
1830 {
1831 }
1832 
1833 // TCP/IP optimization selection dialog procedure
TcpMsgDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1834 UINT TcpMsgDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1835 {
1836 	UINT ret;
1837 	// Validate arguments
1838 	if (hWnd == NULL)
1839 	{
1840 		return 0;
1841 	}
1842 
1843 	switch (msg)
1844 	{
1845 	case WM_INITDIALOG:
1846 		SetIcon(hWnd, 0, ICO_SETUP);
1847 		//DlgFont(hWnd, R_OPTIMIZE, 0, true);
1848 
1849 		Check(hWnd, R_NO, true);
1850 
1851 		if (g_tcpip_topmost)
1852 		{
1853 			Top(hWnd);
1854 		}
1855 
1856 		break;
1857 
1858 	case WM_COMMAND:
1859 		switch (wParam)
1860 		{
1861 		case IDOK:
1862 			ret = 1;
1863 			if (IsChecked(hWnd, R_MANUAL))
1864 			{
1865 				ret = 2;
1866 			}
1867 			else if (IsChecked(hWnd, R_NO))
1868 			{
1869 				ret = 0;
1870 			}
1871 
1872 			EndDialog(hWnd, ret);
1873 			break;
1874 		}
1875 		break;
1876 
1877 	case WM_CLOSE:
1878 		return 1;
1879 	}
1880 
1881 	return 0;
1882 }
1883 
1884 // Initialize the dialog
TcpIpDlgInit(HWND hWnd)1885 void TcpIpDlgInit(HWND hWnd)
1886 {
1887 	MS_TCP tcp;
1888 
1889 	SetIcon(hWnd, 0, ICO_SETUP);
1890 
1891 	MsGetTcpConfig(&tcp);
1892 
1893 	Check(hWnd, R_RECV_DISABLE, tcp.RecvWindowSize == 0);
1894 	Check(hWnd, R_RECV_ENABLE, tcp.RecvWindowSize != 0);
1895 	SetInt(hWnd, E_RECV, tcp.RecvWindowSize != 0 ? tcp.RecvWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);
1896 
1897 	Check(hWnd, R_SEND_DISABLE, tcp.SendWindowSize == 0);
1898 	Check(hWnd, R_SEND_ENABLE, tcp.SendWindowSize != 0);
1899 	SetInt(hWnd, E_SEND, tcp.SendWindowSize != 0 ? tcp.SendWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);
1900 
1901 	TcpIpDlgUpdate(hWnd);
1902 
1903 	Top(hWnd);
1904 }
1905 
1906 // Update the dialog
TcpIpDlgUpdate(HWND hWnd)1907 void TcpIpDlgUpdate(HWND hWnd)
1908 {
1909 	bool ok = true;
1910 
1911 	SetEnable(hWnd, E_RECV, IsChecked(hWnd, R_RECV_ENABLE));
1912 	SetEnable(hWnd, S_RECV, IsChecked(hWnd, R_RECV_ENABLE));
1913 	SetEnable(hWnd, E_SEND, IsChecked(hWnd, R_SEND_ENABLE));
1914 	SetEnable(hWnd, S_SEND, IsChecked(hWnd, R_SEND_ENABLE));
1915 
1916 	if (IsChecked(hWnd, R_RECV_ENABLE) && GetInt(hWnd, E_RECV) < 1454)
1917 	{
1918 		ok = false;
1919 	}
1920 
1921 	if (IsChecked(hWnd, R_SEND_ENABLE) && GetInt(hWnd, E_SEND) < 1454)
1922 	{
1923 		ok = false;
1924 	}
1925 
1926 	SetEnable(hWnd, IDOK, ok);
1927 }
1928 
1929 // TCP/IP dialog procedure
TcpIpDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)1930 UINT TcpIpDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
1931 {
1932 	MS_TCP tcp, old;
1933 	// Validate arguments
1934 	if (hWnd == NULL)
1935 	{
1936 		return 0;
1937 	}
1938 
1939 	switch (msg)
1940 	{
1941 	case WM_INITDIALOG:
1942 		TcpIpDlgInit(hWnd);
1943 
1944 		if (g_tcpip_topmost)
1945 		{
1946 			Top(hWnd);
1947 		}
1948 
1949 		break;
1950 
1951 	case WM_COMMAND:
1952 		switch (LOWORD(wParam))
1953 		{
1954 		case R_RECV_DISABLE:
1955 		case R_RECV_ENABLE:
1956 		case R_SEND_DISABLE:
1957 		case R_SEND_ENABLE:
1958 		case E_RECV:
1959 		case E_SEND:
1960 			TcpIpDlgUpdate(hWnd);
1961 			break;
1962 		}
1963 
1964 		switch (wParam)
1965 		{
1966 		case IDOK:
1967 			Zero(&tcp, sizeof(tcp));
1968 
1969 			if (IsChecked(hWnd, R_RECV_ENABLE))
1970 			{
1971 				tcp.RecvWindowSize = GetInt(hWnd, E_RECV);
1972 			}
1973 
1974 			if (IsChecked(hWnd, R_SEND_ENABLE))
1975 			{
1976 				tcp.SendWindowSize = GetInt(hWnd, E_SEND);
1977 			}
1978 
1979 			MsGetTcpConfig(&old);
1980 
1981 			MsSetTcpConfig(&tcp);
1982 			MsSaveTcpConfigReg(&tcp);
1983 
1984 			EndDialog(hWnd, true);
1985 			break;
1986 
1987 		case IDCANCEL:
1988 			Close(hWnd);
1989 			break;
1990 
1991 		case R_RECV_ENABLE:
1992 			FocusEx(hWnd, E_RECV);
1993 			break;
1994 
1995 		case R_SEND_ENABLE:
1996 			FocusEx(hWnd, E_SEND);
1997 			break;
1998 
1999 		case B_RECV:
2000 			SetInt(hWnd, E_RECV, DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);
2001 			Check(hWnd, R_RECV_DISABLE, false);
2002 			Check(hWnd, R_RECV_ENABLE, true);
2003 			TcpIpDlgUpdate(hWnd);
2004 			FocusEx(hWnd, E_RECV);
2005 			break;
2006 
2007 		case B_SEND:
2008 			SetInt(hWnd, E_SEND, DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);
2009 			Check(hWnd, R_SEND_DISABLE, false);
2010 			Check(hWnd, R_SEND_ENABLE, true);
2011 			TcpIpDlgUpdate(hWnd);
2012 			FocusEx(hWnd, E_SEND);
2013 			break;
2014 
2015 		case B_DELETE:
2016 			Zero(&tcp, sizeof(tcp));
2017 			MsSetTcpConfig(&tcp);
2018 			MsDeleteTcpConfigReg();
2019 			EndDialog(hWnd, 0);
2020 			break;
2021 		}
2022 		break;
2023 
2024 	case WM_CLOSE:
2025 		EndDialog(hWnd, false);
2026 		break;
2027 	}
2028 
2029 	return 0;
2030 }
2031 
2032 // Warning dialog about 64-bit
Cpu64DlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2033 UINT Cpu64DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2034 {
2035 	switch (msg)
2036 	{
2037 	case WM_INITDIALOG:
2038 		SetIcon(hWnd, 0, ICO_WARNING);
2039 		DlgFont(hWnd, S_BOLD, 9, true);
2040 		SetTimer(hWnd, 1, 30 * 1000, NULL);
2041 		break;
2042 
2043 	case WM_TIMER:
2044 		switch (wParam)
2045 		{
2046 		case 1:
2047 			KillTimer(hWnd, 1);
2048 			Command(hWnd, IDOK);
2049 			break;
2050 		}
2051 
2052 		break;
2053 
2054 	case WM_COMMAND:
2055 		switch (wParam)
2056 		{
2057 		case IDOK:
2058 		case IDCANCEL:
2059 			Close(hWnd);
2060 			break;
2061 		}
2062 		break;
2063 
2064 	case WM_CLOSE:
2065 		EndDialog(hWnd, 0);
2066 		break;
2067 	}
2068 
2069 	return 0;
2070 }
2071 
2072 // Display a warning dialog about 64-bit
ShowCpu64Warning()2073 void ShowCpu64Warning()
2074 {
2075 	Dialog(NULL, D_CPU64_WARNING, Cpu64DlgProc, NULL);
2076 }
2077 
2078 // Show the TCP/IP configuration utility
ShowTcpIpConfigUtil(HWND hWnd,bool util_mode)2079 void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode)
2080 {
2081 	if (MsIsTcpConfigSupported() == false)
2082 	{
2083 		if (util_mode)
2084 		{
2085 			// Show a message that is not supported by the current OS
2086 			if (MsIsAdmin() == false)
2087 			{
2088 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_ADMIN"));
2089 			}
2090 			else
2091 			{
2092 				MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_SUPPORTED"));
2093 			}
2094 		}
2095 		return;
2096 	}
2097 
2098 	if (util_mode == false)
2099 	{
2100 		// Exit immediately by start the vpncmd
2101 		wchar_t tmp[MAX_PATH];
2102 		wchar_t exedir[MAX_PATH];
2103 		HANDLE h;
2104 
2105 		GetExeDirW(exedir, sizeof(exedir));
2106 
2107 		UniFormat(tmp, sizeof(tmp), L"%s\\vpncmd.exe", exedir);
2108 		if (IsFileW(tmp))
2109 		{
2110 			RunW(tmp, L"/tool /cmd:exit", true, false);
2111 		}
2112 
2113 		// Disable the task off-loading by netsh
2114 		if (true)
2115 		{
2116 			DIRLIST *dl;
2117 			UINT i;
2118 			bool b = false;
2119 
2120 			dl = EnumDirW(exedir);
2121 
2122 			for (i = 0;i < dl->NumFiles;i++)
2123 			{
2124 				if (UniInStr(dl->File[i]->FileNameW, L"vpnbridge") ||
2125 					UniInStr(dl->File[i]->FileNameW, L"vpnserver"))
2126 				{
2127 					b = true;
2128 				}
2129 			}
2130 
2131 			FreeDir(dl);
2132 
2133 			if (b)
2134 			{
2135 				// Disable the off-loading
2136 				MsDisableNetworkOffloadingEtc();
2137 			}
2138 		}
2139 
2140 		// Windows Firewall registration
2141 		RegistWindowsFirewallAll();
2142 
2143 		SleepThread(1000);
2144 
2145 		// Start vpnclient.exe /uihelp
2146 		h = CmExecUiHelperMain();
2147 		if (h != NULL)
2148 		{
2149 			CloseHandle(h);
2150 		}
2151 
2152 		if (Is64() == false)
2153 		{
2154 			if (MsIs64BitWindows())
2155 			{
2156 				// Show a warning message if a 32-bit version is used in 64-bit Windows
2157 				ShowCpu64Warning();
2158 			}
2159 		}
2160 
2161 		if (MsIsAdmin())
2162 		{
2163 			// If installing on Windows Vista,
2164 			// dispel the network limitation of MMCSS
2165 			if (MsIsMMCSSNetworkThrottlingEnabled())
2166 			{
2167 				MsSetMMCSSNetworkThrottlingEnable(false);
2168 			}
2169 		}
2170 	}
2171 
2172 	if (util_mode == false && MsIsShouldShowTcpConfigApp() == false)
2173 	{
2174 		return;
2175 	}
2176 
2177 	if (util_mode == false)
2178 	{
2179 		// 2006.07.04 nobori
2180 		// I decided not to show TCP/IP optimization utility in the installer
2181 		return;
2182 	}
2183 
2184 	g_tcpip_topmost = util_mode ? false : true;
2185 
2186 	if (util_mode == false)
2187 	{
2188 		UINT ret = Dialog(hWnd, D_TCP_MSG, TcpMsgDlgProc, NULL);
2189 
2190 		if (ret == 0)
2191 		{
2192 			MS_TCP tcp;
2193 
2194 			Zero(&tcp, sizeof(tcp));
2195 			MsGetTcpConfig(&tcp);
2196 			MsSaveTcpConfigReg(&tcp);
2197 			return;
2198 		}
2199 		else if (ret == 1)
2200 		{
2201 			MS_TCP tcp;
2202 
2203 			Zero(&tcp, sizeof(tcp));
2204 
2205 			tcp.RecvWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_RECV;
2206 			tcp.SendWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_SEND;
2207 			MsSetTcpConfig(&tcp);
2208 			MsSaveTcpConfigReg(&tcp);
2209 
2210 			return;
2211 		}
2212 	}
2213 
2214 	Dialog(hWnd, D_TCP, TcpIpDlgProc, NULL);
2215 }
2216 
2217 // Internationalization of menu (Unicode)
InitMenuInternationalUni(HMENU hMenu,char * prefix)2218 void InitMenuInternationalUni(HMENU hMenu, char *prefix)
2219 {
2220 	UINT i, num;
2221 	// Validate arguments
2222 	if (hMenu == NULL || prefix == NULL)
2223 	{
2224 		return;
2225 	}
2226 
2227 	// Get the number of items in the menu
2228 	num = GetMenuItemCount(hMenu);
2229 
2230 	// Enumerate the menu items
2231 	for (i = 0;i < num;i++)
2232 	{
2233 		HMENU hSubMenu = GetSubMenu(hMenu, i);
2234 		MENUITEMINFOW info;
2235 		wchar_t tmp[MAX_SIZE];
2236 
2237 		if (hSubMenu != NULL)
2238 		{
2239 			// If there is a sub-menu, call it recursively
2240 			InitMenuInternational(hSubMenu, prefix);
2241 		}
2242 
2243 		// Get the menu item
2244 		Zero(&info, sizeof(info));
2245 		info.cbSize = sizeof(info);
2246 		info.cch = sizeof(tmp);
2247 		info.dwTypeData = tmp;
2248 		info.fMask = MIIM_STRING;
2249 		Zero(tmp, sizeof(tmp));
2250 
2251 		if (GetMenuItemInfoW(hMenu, i, true, &info))
2252 		{
2253 			if (tmp[0] == L'@')
2254 			{
2255 				char name[256];
2256 				wchar_t *ret;
2257 
2258 				Format(name, sizeof(name), "%s@%S", prefix, &tmp[1]);
2259 
2260 				ret = _UU(name);
2261 				if (UniIsEmptyStr(ret) == false)
2262 				{
2263 					UniStrCpy(tmp, sizeof(tmp), ret);
2264 					info.cch = UniStrLen(tmp);
2265 
2266 					SetMenuItemInfoW(hMenu, i, true, &info);
2267 				}
2268 			}
2269 		}
2270 	}
2271 }
2272 
2273 // Internationalization of menu
InitMenuInternational(HMENU hMenu,char * prefix)2274 void InitMenuInternational(HMENU hMenu, char *prefix)
2275 {
2276 	// Validate arguments
2277 	if (hMenu == NULL || prefix == NULL)
2278 	{
2279 		return;
2280 	}
2281 
2282 	InitMenuInternationalUni(hMenu, prefix);
2283 }
2284 
2285 // Get the default font for the dialog box
GetDialogDefaultFont()2286 HFONT GetDialogDefaultFont()
2287 {
2288 	return GetDialogDefaultFontEx(false);
2289 }
GetDialogDefaultFontEx(bool meiryo)2290 HFONT GetDialogDefaultFontEx(bool meiryo)
2291 {
2292 	char *default_font_name = _SS("DEFAULT_FONT");
2293 	UINT default_font_size = _II("DEFAULT_FONT_SIZE");
2294 	char *win7_font = _SS("DEFAULT_FONT_WIN7");
2295 
2296 	if (meiryo)
2297 	{
2298 		if (_GETLANG() == 2)
2299 		{
2300 			default_font_name = "Microsoft YaHei";
2301 		}
2302 		if (_GETLANG() == 3)
2303 		{
2304 			default_font_name = "Microsoft JhengHei";
2305 		}
2306 		else
2307 		{
2308 			default_font_name = GetMeiryoFontName();
2309 		}
2310 	}
2311 
2312 	if (MsIsWindows7())
2313 	{
2314 		if (IsEmptyStr(win7_font) == false)
2315 		{
2316 			default_font_name = win7_font;
2317 		}
2318 
2319 		if (GetTextScalingFactor() >= 1.44)
2320 		{
2321 			// Use a substitute font in the case of high-DPI in Windows 7 and later
2322 			char *alternative_font = _SS("DEFAULT_FONT_HIGHDPI");
2323 
2324 			if (IsEmptyStr(alternative_font) == false)
2325 			{
2326 				default_font_name = alternative_font;
2327 			}
2328 		}
2329 	}
2330 
2331 	if (IsEmptyStr(default_font_name))
2332 	{
2333 		default_font_name = font_name;
2334 	}
2335 
2336 	if (default_font_size == 0)
2337 	{
2338 		default_font_size = 9;
2339 	}
2340 
2341 	return GetFont(default_font_name, default_font_size, false, false, false, false);
2342 }
2343 
2344 // Adjust the control size and window size
AdjustWindowAndControlSize(HWND hWnd,bool * need_resize,double * factor_x,double * factor_y)2345 void AdjustWindowAndControlSize(HWND hWnd, bool *need_resize, double *factor_x, double *factor_y)
2346 {
2347 	HFONT hDlgFont;
2348 	UINT dlgfont_x, dlgfont_y;
2349 	// Validate arguments
2350 	if (hWnd == NULL || need_resize == NULL || factor_x == NULL || factor_y == NULL)
2351 	{
2352 		return;
2353 	}
2354 
2355 	*need_resize = true;
2356 
2357 	// Get the font of the current window
2358 	hDlgFont = (HFONT)SendMsg(hWnd, 0, WM_GETFONT, 0, 0);
2359 
2360 	// Get the width and height of the font of the current window
2361 	CalcFontSize(hDlgFont, &dlgfont_x, &dlgfont_y);
2362 
2363 	if ((dlgfont_x == WINUI_DEFAULT_DIALOG_UNIT_X) &&
2364 		(dlgfont_y == WINUI_DEFAULT_DIALOG_UNIT_Y))
2365 	{
2366 		// There is no need to adjust
2367 		*need_resize = false;
2368 		*factor_x = 1.0;
2369 		*factor_y = 1.0;
2370 		//Debug("// There is no need to adjust\n");
2371 		return;
2372 	}
2373 
2374 	// Calculate the adjustment amount
2375 	*factor_x = (double)dlgfont_x / (double)WINUI_DEFAULT_DIALOG_UNIT_X;
2376 	*factor_y = (double)dlgfont_y / (double)WINUI_DEFAULT_DIALOG_UNIT_Y;
2377 	//Debug("Factors: %f %f\n", *factor_x, *factor_y);
2378 }
2379 
2380 // Adjust the values of x and y according to the font
AdjustDialogXY(UINT * x,UINT * y,UINT dlgfont_x,UINT dlgfont_y)2381 void AdjustDialogXY(UINT *x, UINT *y, UINT dlgfont_x, UINT dlgfont_y)
2382 {
2383 	if (x != NULL)
2384 	{
2385 		*x = (UINT)(((double)*x) * (double)WINUI_DEFAULT_DIALOG_UNIT_X / (double)dlgfont_x);
2386 	}
2387 
2388 	if (y != NULL)
2389 	{
2390 		*y = (UINT)(((double)*y) * (double)WINUI_DEFAULT_DIALOG_UNIT_Y / (double)dlgfont_y);
2391 	}
2392 }
2393 
2394 // Internationalizing process for the dialog box
InitDialogInternational(HWND hWnd,void * pparam)2395 void InitDialogInternational(HWND hWnd, void *pparam)
2396 {
2397 	LIST *o;
2398 	UINT i;
2399 	bool is_managed_dialog = false;
2400 	char caption[MAX_PATH];
2401 	char *dialog_name;
2402 	DIALOG_PARAM *param = (DIALOG_PARAM *)pparam;
2403 	HDC hDC;
2404 	bool need_resize = false;
2405 	double factor_x = 0.0, factor_y = 0.0;
2406 	// Validate arguments
2407 	if (hWnd == NULL || param == NULL)
2408 	{
2409 		return;
2410 	}
2411 
2412 	hDC = CreateCompatibleDC(NULL);
2413 
2414 	AdjustWindowAndControlSize(hWnd, &need_resize, &factor_x, &factor_y);
2415 
2416 	GetTxtA(hWnd, 0, caption, sizeof(caption));
2417 	if (caption[0] == '@')
2418 	{
2419 		dialog_name = &caption[1];
2420 
2421 		is_managed_dialog = true;
2422 	}
2423 
2424 	// Enumerate all window handles
2425 	o = EnumAllChildWindow(hWnd);
2426 
2427 	for (i = 0;i < LIST_NUM(o);i++)
2428 	{
2429 		HWND hControl = *((HWND *)LIST_DATA(o, i));
2430 
2431 		if (hControl != NULL)
2432 		{
2433 			bool set_font = true;
2434 			HFONT hFont = GetDialogDefaultFontEx(param && ((DIALOG_PARAM *)param)->meiryo);
2435 
2436 			if (MsIsWine())
2437 			{
2438 				char classname[MAX_PATH];
2439 				char parent_classname[MAX_PATH];
2440 				HWND hParent = GetParent(hControl);
2441 
2442 				Zero(classname, sizeof(classname));
2443 				Zero(parent_classname, sizeof(parent_classname));
2444 
2445 				GetClassNameA(hControl, classname, sizeof(classname));
2446 
2447 				if (hParent != NULL)
2448 				{
2449 					GetClassNameA(hParent, parent_classname, sizeof(parent_classname));
2450 				}
2451 
2452 				if (StrCmpi(classname, "edit") == 0)
2453 				{
2454 					set_font = false;
2455 				}
2456 
2457 				if (StrCmpi(classname, "combobox") == 0)
2458 				{
2459 					set_font = false;
2460 				}
2461 
2462 				if (StrCmpi(classname, "syslistview32") == 0)
2463 				{
2464 					set_font = false;
2465 				}
2466 
2467 				if (StrCmpi(classname, "sysheader32") == 0)
2468 				{
2469 					set_font = false;
2470 				}
2471 
2472 				if (StrCmpi(parent_classname, "SysIPAddress32") == 0 ||
2473 					StrCmpi(classname, "SysIPAddress32") == 0)
2474 				{
2475 					set_font = true;
2476 					hFont = GetFont("Tahoma", 8, false, false, false, false);
2477 				}
2478 			}
2479 
2480 			if (set_font)
2481 			{
2482 				SetFont(hControl, 0, hFont);
2483 			}
2484 
2485 			char classname[MAX_PATH];
2486 			GetClassNameA(hControl, classname, sizeof(classname));
2487 
2488 			if (StrCmpi(classname, "syslistview32") == 0)
2489 			{
2490 				InitVistaWindowTheme(hControl);
2491 			}
2492 
2493 			if (is_managed_dialog)
2494 			{
2495 				char str[MAX_PATH];
2496 
2497 				GetTxtA(hControl, 0, str, sizeof(str));
2498 				if (str[0] == '@')
2499 				{
2500 					char *control_name = &str[1];
2501 					char tmp[MAX_PATH];
2502 					wchar_t *ret;
2503 
2504 					StrCpy(tmp, sizeof(tmp), dialog_name);
2505 					StrCat(tmp, sizeof(tmp), "@");
2506 
2507 					if (hWnd == hControl)
2508 					{
2509 						StrCat(tmp, sizeof(tmp), "CAPTION");
2510 					}
2511 					else
2512 					{
2513 						StrCat(tmp, sizeof(tmp), control_name);
2514 					}
2515 
2516 					ret = _UU(tmp);
2517 
2518 					if (ret != NULL && UniIsEmptyStr(ret) == false)
2519 					{
2520 						SetText(hControl, 0, ret);
2521 					}
2522 				}
2523 			}
2524 		}
2525 	}
2526 
2527 	FreeWindowList(o);
2528 
2529 	if (need_resize)
2530 	{
2531 		// Since the window size is changed automatically by the OS by the dpi setting
2532 		// in Windows Vista or later, a static (bitmap) control needs to be expanded
2533 		// by anticipating the size after changing
2534 
2535 		// Enumerate all child window (not recursive)
2536 		o = EnumAllChildWindowEx(hWnd, true, false, true);
2537 
2538 		for (i = 0;i < LIST_NUM(o);i++)
2539 		{
2540 			HWND hControl = *((HWND *)LIST_DATA(o, i));
2541 
2542 			if (hControl != NULL)
2543 			{
2544 				char class_name[MAX_SIZE];
2545 
2546 				Zero(class_name, sizeof(class_name));
2547 				GetClassNameA(hControl, class_name, sizeof(class_name));
2548 
2549 				if (StrCmpi(class_name, "static") == 0)
2550 				{
2551 					UINT style = GetStyle(hControl, 0);
2552 
2553 					if (style & SS_BITMAP)
2554 					{
2555 						// Get the Bitmap
2556 						HBITMAP hBitmap = (HBITMAP)SendMessage(hControl, STM_GETIMAGE, IMAGE_BITMAP, 0);
2557 
2558 						if (hBitmap != NULL)
2559 						{
2560 							// Get the size of this bitmap
2561 							UINT src_x;
2562 							UINT src_y;
2563 
2564 							if (GetBitmapSize(hBitmap, &src_x, &src_y))
2565 							{
2566 								RECT ctl_rect;
2567 
2568 								Zero(&ctl_rect, sizeof(ctl_rect));
2569 
2570 								if (GetWindowRect(hControl, &ctl_rect))
2571 								{
2572 									// Use the smaller magnification of the height and the width
2573 									//double scale_factor = 1.5;
2574 									double scale_factor = MIN(factor_x, factor_y);
2575 									UINT dst_x = (UINT)((double)src_x * scale_factor);
2576 									UINT dst_y = (UINT)((double)src_y * scale_factor);
2577 
2578 									HBITMAP hDst = ResizeBitmap(hBitmap, src_x, src_y, dst_x, dst_y);
2579 
2580 									if (hDst != NULL)
2581 									{
2582 										Add(param->BitmapList, hDst);
2583 
2584 										SendMessage(hControl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hDst);
2585 									}
2586 								}
2587 							}
2588 						}
2589 					}
2590 				}
2591 			}
2592 		}
2593 
2594 		FreeWindowList(o);
2595 	}
2596 
2597 	DeleteDC(hDC);
2598 }
2599 
2600 // Get the size of the bitmap
GetBitmapSize(void * bmp,UINT * x,UINT * y)2601 bool GetBitmapSize(void *bmp, UINT *x, UINT *y)
2602 {
2603 	BITMAP info;
2604 	// Validate arguments
2605 	if (bmp == NULL || x == NULL || y == NULL)
2606 	{
2607 		return false;
2608 	}
2609 
2610 	Zero(&info, sizeof(info));
2611 	if (GetObject((HANDLE)bmp, sizeof(info), &info) == 0)
2612 	{
2613 		return false;
2614 	}
2615 
2616 	*x = info.bmWidth;
2617 	*y = info.bmHeight;
2618 
2619 	return true;
2620 }
2621 
2622 // Resize the bitmap
ResizeBitmap(HBITMAP hSrc,UINT src_x,UINT src_y,UINT dst_x,UINT dst_y)2623 HBITMAP ResizeBitmap(HBITMAP hSrc, UINT src_x, UINT src_y, UINT dst_x, UINT dst_y)
2624 {
2625 	HDC hMemDC;
2626 	HDC hSrcDC;
2627 	HBITMAP ret = NULL;
2628 	BITMAPINFOHEADER h;
2629 	BITMAPINFO bi;
2630 	UCHAR *data = NULL;
2631 	// Validate arguments
2632 	if (hSrc == NULL)
2633 	{
2634 		return NULL;
2635 	}
2636 
2637 	hSrcDC = CreateCompatibleDC(NULL);
2638 	if (hSrcDC != NULL)
2639 	{
2640 		HBITMAP hOld = SelectObject(hSrcDC, hSrc);
2641 
2642 		if (hOld != NULL)
2643 		{
2644 			hMemDC = CreateCompatibleDC(NULL);
2645 
2646 			if (hMemDC != NULL)
2647 			{
2648 				HBITMAP hOld;
2649 				HBITMAP srcHbitMap;
2650 				UCHAR* srcData;
2651 				CT_RectF_c destRect;
2652 				CT_RectF_c srcRect;
2653 
2654 				Zero(&h, sizeof(h));
2655 				h.biSize = sizeof(h);
2656 				h.biWidth = src_x;
2657 				h.biHeight = src_y;
2658 				h.biPlanes = 1;
2659 				h.biBitCount = 32;
2660 				h.biXPelsPerMeter = 2834;
2661 				h.biYPelsPerMeter = 2834;
2662 				h.biCompression = BI_RGB;
2663 
2664 				// Copy once the transfer source
2665 				Zero(&bi, sizeof(bi));
2666 				Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));
2667 				srcHbitMap = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, &srcData, NULL, 0);
2668 
2669 				hOld = SelectObject(hMemDC, srcHbitMap);
2670 
2671 				BitBlt(hMemDC,0,0,src_x,src_y,hSrcDC,0,0, SRCCOPY);
2672 
2673 				GdiFlush();
2674 
2675 
2676 
2677 				// Generate a resized version
2678 				if(src_x != dst_x || src_y != dst_y)
2679 				{
2680 					h.biWidth = dst_x;
2681 					h.biHeight = dst_y;
2682 					Zero(&bi, sizeof(bi));
2683 					Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));
2684 
2685 					ret = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, &data, NULL, 0);
2686 
2687 					if(srcData != NULL && data != NULL)
2688 					{
2689 						destRect.X = 0; destRect.Y = 0;
2690 						destRect.Width = (float)dst_x; destRect.Height = (float)dst_y;
2691 						srcRect = destRect;
2692 						srcRect.Width = (float)src_x; srcRect.Height = (float)src_y;
2693 
2694 						CT_DrawImage((UCHAR*)data, destRect, dst_x,dst_y,
2695 							(UCHAR*)srcData, srcRect,src_x, src_y);
2696 					}
2697 
2698 					if(srcHbitMap != NULL)
2699 					{
2700 						DeleteObject(srcHbitMap);
2701 					}
2702 				}
2703 				else
2704 				{
2705 					ret = srcHbitMap;
2706 				}
2707 
2708 				SelectObject(hMemDC, hOld);
2709 
2710 				DeleteDC(hMemDC);
2711 			}
2712 
2713 			SelectObject(hSrcDC, hOld);
2714 		}
2715 
2716 		DeleteDC(hSrcDC);
2717 	}
2718 
2719 	return ret;
2720 }
2721 
2722 // Initialize the bitmap list
NewBitmapList()2723 LIST *NewBitmapList()
2724 {
2725 	LIST *o = NewListFast(NULL);
2726 
2727 	return o;
2728 }
2729 
2730 // Release the bitmap list
FreeBitmapList(LIST * o)2731 void FreeBitmapList(LIST *o)
2732 {
2733 	UINT i;
2734 	// Validate arguments
2735 	if (o == NULL)
2736 	{
2737 		return;
2738 	}
2739 
2740 	for (i = 0;i < LIST_NUM(o);i++)
2741 	{
2742 		HBITMAP *h = LIST_DATA(o, i);
2743 
2744 		DeleteObject(h);
2745 	}
2746 
2747 	ReleaseList(o);
2748 }
2749 
2750 // Child window enumeration procedure
2751 // Initialize the dialog
StringDlgInit(HWND hWnd,STRING_DLG * s)2752 void StringDlgInit(HWND hWnd, STRING_DLG *s)
2753 {
2754 	// Validate arguments
2755 	if (hWnd == NULL || s == NULL)
2756 	{
2757 		return;
2758 	}
2759 
2760 	SetText(hWnd, E_STRING, s->String);
2761 
2762 	SetIcon(hWnd, S_ICON, s->Icon);
2763 	SetText(hWnd, S_INFO, s->Info);
2764 	SetText(hWnd, 0, s->Title);
2765 
2766 	FocusEx(hWnd, E_STRING);
2767 
2768 	StringDlgUpdate(hWnd, s);
2769 }
2770 
2771 // Update the dialog control
StringDlgUpdate(HWND hWnd,STRING_DLG * s)2772 void StringDlgUpdate(HWND hWnd, STRING_DLG *s)
2773 {
2774 	wchar_t *tmp;
2775 	bool b = true;
2776 	// Validate arguments
2777 	if (hWnd == NULL || s == NULL)
2778 	{
2779 		return;
2780 	}
2781 
2782 	tmp = GetText(hWnd, E_STRING);
2783 
2784 	if (tmp != NULL)
2785 	{
2786 		if (s->AllowEmpty == false)
2787 		{
2788 			if (UniIsEmptyStr(tmp))
2789 			{
2790 				b = false;
2791 			}
2792 		}
2793 
2794 		if (s->AllowUnsafe == false)
2795 		{
2796 			if (IsSafeUniStr(tmp) == false)
2797 			{
2798 				b = false;
2799 			}
2800 		}
2801 
2802 		Free(tmp);
2803 	}
2804 
2805 	SetEnable(hWnd, IDOK, b);
2806 }
2807 
2808 // String dialog procedure
StringDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2809 UINT StringDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2810 {
2811 	STRING_DLG *s = (STRING_DLG *)param;
2812 	// Validate arguments
2813 	if (hWnd == NULL)
2814 	{
2815 		return 0;
2816 	}
2817 
2818 	switch (msg)
2819 	{
2820 	case WM_INITDIALOG:
2821 		StringDlgInit(hWnd, s);
2822 		break;
2823 
2824 	case WM_COMMAND:
2825 		switch (LOWORD(wParam))
2826 		{
2827 		case E_STRING:
2828 			StringDlgUpdate(hWnd, s);
2829 			break;
2830 		}
2831 
2832 		switch (wParam)
2833 		{
2834 		case IDOK:
2835 			GetTxt(hWnd, E_STRING, s->String, sizeof(s->String));
2836 			EndDialog(hWnd, true);
2837 			break;
2838 
2839 		case IDCANCEL:
2840 			Close(hWnd);
2841 			break;
2842 		}
2843 		break;
2844 
2845 	case WM_CLOSE:
2846 		EndDialog(hWnd, false);
2847 		break;
2848 	}
2849 
2850 	return 0;
2851 }
2852 
2853 // Show the string dialog
StringDlg(HWND hWnd,wchar_t * title,wchar_t * info,wchar_t * def,UINT icon,bool allow_empty,bool allow_unsafe)2854 wchar_t *StringDlg(HWND hWnd, wchar_t *title, wchar_t *info, wchar_t *def, UINT icon, bool allow_empty, bool allow_unsafe)
2855 {
2856 	STRING_DLG s;
2857 	// Validate arguments
2858 	if (title == NULL)
2859 	{
2860 		title = _UU("DLG_STRING_DEFTITLE");
2861 	}
2862 	if (info == NULL)
2863 	{
2864 		info = _UU("DLG_STRING_DEFINFO");
2865 	}
2866 	if (def == NULL)
2867 	{
2868 		def = L"";
2869 	}
2870 	if (icon == 0)
2871 	{
2872 		icon = ICO_NULL;
2873 	}
2874 
2875 	Zero(&s, sizeof(s));
2876 	s.Icon = icon;
2877 	s.Info = info;
2878 	s.Title = title;
2879 	s.Icon = icon;
2880 	UniStrCpy(s.String, sizeof(s.String), def);
2881 	s.AllowEmpty = allow_empty;
2882 	s.AllowUnsafe = allow_unsafe;
2883 
2884 	if (Dialog(hWnd, D_STRING, StringDlgProc, &s) == false)
2885 	{
2886 		return NULL;
2887 	}
2888 	else
2889 	{
2890 		return CopyUniStr(s.String);
2891 	}
2892 }
StringDlgA(HWND hWnd,wchar_t * title,wchar_t * info,char * def,UINT icon,bool allow_empty,bool allow_unsafe)2893 char *StringDlgA(HWND hWnd, wchar_t *title, wchar_t *info, char *def, UINT icon, bool allow_empty, bool allow_unsafe)
2894 {
2895 	wchar_t unidef[MAX_SIZE];
2896 	wchar_t *tmp;
2897 	char *ret;
2898 	if (def == NULL)
2899 	{
2900 		def = "";
2901 	}
2902 
2903 	StrToUni(unidef, sizeof(unidef), def);
2904 
2905 	tmp = StringDlg(hWnd, title, info, unidef, icon, allow_empty, allow_unsafe);
2906 	if (tmp == NULL)
2907 	{
2908 		return NULL;
2909 	}
2910 
2911 	ret = CopyUniToStr(tmp);
2912 	Free(tmp);
2913 
2914 	return ret;
2915 }
2916 
2917 // Show a text file
ShowTextFile(HWND hWnd,char * filename,wchar_t * caption,UINT icon)2918 void ShowTextFile(HWND hWnd, char *filename, wchar_t *caption, UINT icon)
2919 {
2920 	BUF *b;
2921 	wchar_t *str;
2922 	// Validate arguments
2923 	if (filename == NULL || caption == NULL)
2924 	{
2925 		return;
2926 	}
2927 	if (icon == 0)
2928 	{
2929 		icon = ICO_NULL;
2930 	}
2931 
2932 	// Read the text file
2933 	b = ReadDump(filename);
2934 	if (b == NULL)
2935 	{
2936 		return;
2937 	}
2938 
2939 	SeekBufToEnd(b);
2940 	WriteBufChar(b, 0);
2941 
2942 	str = CopyUtfToUni(b->Buf);
2943 
2944 	OnceMsg(hWnd, caption, str, false, icon);
2945 
2946 	FreeBuf(b);
2947 	Free(str);
2948 }
2949 
2950 // Initialize the version information
AboutDlgInit(HWND hWnd,WINUI_ABOUT * a)2951 void AboutDlgInit(HWND hWnd, WINUI_ABOUT *a)
2952 {
2953 	wchar_t tmp[MAX_SIZE];
2954 	// Validate arguments
2955 	if (hWnd == NULL || a == NULL)
2956 	{
2957 		return;
2958 	}
2959 
2960 	SetIcon(hWnd, 0, ICO_INFORMATION);
2961 
2962 	UniFormat(tmp, sizeof(tmp), _UU("ABOUT_CAPTION"), a->ProductName);
2963 	SetText(hWnd, 0, tmp);
2964 
2965 	SetFont(hWnd, S_INFO1, GetFont("Arial", 12, false, false, false, false));
2966 	FormatText(hWnd, S_INFO1, CEDAR_VERSION_MAJOR, CEDAR_VERSION_MAJOR, CEDAR_VERSION_MINOR, CEDAR_VERSION_BUILD);
2967 
2968 	SetFont(hWnd, S_INFO2, GetFont("Arial", 8, false, false, false, false));
2969 	FormatText(hWnd, S_INFO2, BUILD_DATE_Y, a->Cedar->BuildInfo);
2970 
2971 	SetFont(hWnd, S_INFO3, GetFont("Arial", 7, false, false, false, false));
2972 
2973 	if (MsIsWine())
2974 	{
2975 		Disable(hWnd, B_LANGUAGE);
2976 	}
2977 
2978 	//DlgFont(hWnd, S_INFO4, 8, false);
2979 
2980 	SetShow(hWnd, B_UPDATE_CONFIG, (a->Update != NULL));
2981 
2982 	Show(hWnd, B_AUTHORS);
2983 }
2984 
2985 // Version information procedure
AboutDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)2986 UINT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
2987 {
2988 	WINUI_ABOUT *a = (WINUI_ABOUT *)param;
2989 	char tmp[MAX_PATH];
2990 	LANGLIST t;
2991 	// Validate arguments
2992 	if (hWnd == NULL)
2993 	{
2994 		return 0;
2995 	}
2996 
2997 	switch (msg)
2998 	{
2999 	case WM_INITDIALOG:
3000 		AboutDlgInit(hWnd, a);
3001 		break;
3002 
3003 	case WM_COMMAND:
3004 		switch (wParam)
3005 		{
3006 		case IDOK:
3007 		case IDCANCEL:
3008 			if ((GetKeyState(VK_SHIFT) & 0x8000) &&
3009 				(GetKeyState(VK_CONTROL) & 0x8000) &&
3010 				(GetKeyState(VK_MENU) & 0x8000))
3011 			{
3012 				ShowEasterEgg(hWnd);
3013 			}
3014 			EndDialog(hWnd, true);
3015 			break;
3016 		case B_WEB:
3017 			ShellExecute(hWnd, "open", _SS("SE_COMPANY_URL"), NULL, NULL, SW_SHOW);
3018 			break;
3019 		case B_EULA:
3020 			ShowTextFile(hWnd, "|eula.txt", _UU("SW_EULA_TITLE"), ICO_LOG);
3021 			break;
3022 		case B_IMPORTANT:
3023 			GetCurrentLang(&t);
3024 			Format(tmp, sizeof(tmp), "|warning_%s.txt", t.Name);
3025 			ShowTextFile(hWnd, tmp, _UU("SW_WARNING_TITLE"), ICO_LOG);
3026 			break;
3027 		case B_LEGAL:
3028 			ShowTextFile(hWnd, "|legal.txt", _UU("DLG_ABOUT_LEGAL"), ICO_LOG);
3029 			break;
3030 		case B_UPDATE_CONFIG:
3031 			ConfigUpdateUi(a->Update, hWnd);
3032 			break;
3033 		case B_AUTHORS:
3034 			ShowTextFile(hWnd, "|authors.txt", _UU("DLG_ABOUT_AUTHORS"), ICO_ZURUHAM);
3035 			break;
3036 		case B_LANGUAGE:
3037 			// Language settings
3038 			if (true)
3039 			{
3040 				wchar_t path[MAX_SIZE];
3041 
3042 				CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"vpnsetup.exe");
3043 
3044 				if (IsFileExistsW(path))
3045 				{
3046 					// with Installer
3047 					if (MsExecuteW(path, L"/language:yes") == false)
3048 					{
3049 						MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
3050 					}
3051 				}
3052 				else
3053 				{
3054 					// without Installer
3055 					CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"lang.config");
3056 					if (MsExecuteW(path, L"") == false)
3057 					{
3058 						MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
3059 					}
3060 				}
3061 			}
3062 			break;
3063 		}
3064 		break;
3065 
3066 	case WM_CLOSE:
3067 		EndDialog(hWnd, false);
3068 		break;
3069 	}
3070 
3071 	return 0;
3072 }
3073 
3074 // Version information
About(HWND hWnd,CEDAR * cedar,wchar_t * product_name)3075 void About(HWND hWnd, CEDAR *cedar, wchar_t *product_name)
3076 {
3077 	AboutEx(hWnd, cedar, product_name, NULL);
3078 }
AboutEx(HWND hWnd,CEDAR * cedar,wchar_t * product_name,WINUI_UPDATE * u)3079 void AboutEx(HWND hWnd, CEDAR *cedar, wchar_t *product_name, WINUI_UPDATE *u)
3080 {
3081 	WINUI_ABOUT a;
3082 	// Validate arguments
3083 	if (cedar == NULL || product_name == NULL)
3084 	{
3085 		return;
3086 	}
3087 
3088 	Zero(&a, sizeof(a));
3089 	a.Cedar = cedar;
3090 	a.ProductName = product_name;
3091 	a.Update = u;
3092 
3093 	Dialog(hWnd, D_ABOUT, AboutDlgProc, &a);
3094 }
3095 
3096 // Examine the number of fields that an IP address is entered
IpGetFilledNum(HWND hWnd,UINT id)3097 UINT IpGetFilledNum(HWND hWnd, UINT id)
3098 {
3099 	UINT ret;
3100 	DWORD value;
3101 	// Validate arguments
3102 	if (hWnd == NULL)
3103 	{
3104 		return 0;
3105 	}
3106 
3107 	ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
3108 
3109 	return ret;
3110 }
3111 
3112 // Examine whether an IP address has been entered
IpIsFilled(HWND hWnd,UINT id)3113 bool IpIsFilled(HWND hWnd, UINT id)
3114 {
3115 	UINT ret;
3116 	DWORD value;
3117 	// Validate arguments
3118 	if (hWnd == NULL)
3119 	{
3120 		return 0;
3121 	}
3122 
3123 	ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
3124 
3125 	if (ret != 4)
3126 	{
3127 		return false;
3128 	}
3129 	else
3130 	{
3131 		return true;
3132 	}
3133 }
3134 
3135 // Get an IP address
IpGet(HWND hWnd,UINT id)3136 UINT IpGet(HWND hWnd, UINT id)
3137 {
3138 	UINT ret;
3139 	DWORD value;
3140 	// Validate arguments
3141 	if (hWnd == NULL)
3142 	{
3143 		return 0;
3144 	}
3145 
3146 	ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
3147 
3148 	if (ret != 4)
3149 	{
3150 		return 0;
3151 	}
3152 	else
3153 	{
3154 		return Endian32((UINT)value);
3155 	}
3156 }
3157 
3158 // Set the IP addresses
IpSet(HWND hWnd,UINT id,UINT ip)3159 void IpSet(HWND hWnd, UINT id, UINT ip)
3160 {
3161 	// Validate arguments
3162 	if (hWnd == NULL)
3163 	{
3164 		return;
3165 	}
3166 
3167 	SendMsg(hWnd, id, IPM_SETADDRESS, 0, Endian32(ip));
3168 }
3169 
3170 // Write the candidates to the registry
WriteCandidateToReg(UINT root,char * key,LIST * o,char * name)3171 void WriteCandidateToReg(UINT root, char *key, LIST *o, char *name)
3172 {
3173 	BUF *b;
3174 	// Validate arguments
3175 	if (key == NULL || o == NULL || name == NULL)
3176 	{
3177 		return;
3178 	}
3179 
3180 	b = CandidateToBuf(o);
3181 	if (b == NULL)
3182 	{
3183 		return;
3184 	}
3185 
3186 	MsRegWriteBin(root, key, name, b->Buf, b->Size);
3187 
3188 	FreeBuf(b);
3189 }
3190 
3191 // Read the candidates from the registry
ReadCandidateFromReg(UINT root,char * key,char * name)3192 LIST *ReadCandidateFromReg(UINT root, char *key, char *name)
3193 {
3194 	BUF *b;
3195 	// Validate arguments
3196 	if (key == NULL || name == NULL)
3197 	{
3198 		return NULL;
3199 	}
3200 
3201 	b = MsRegReadBin(root, key, name);
3202 	if (b == NULL)
3203 	{
3204 		return NewCandidateList();
3205 	}
3206 	else
3207 	{
3208 		LIST *o = BufToCandidate(b);
3209 		FreeBuf(b);
3210 
3211 		return o;
3212 	}
3213 }
3214 
3215 // initialize the remote connection dialog
RemoteDlgInit(HWND hWnd,WINUI_REMOTE * r)3216 void RemoteDlgInit(HWND hWnd, WINUI_REMOTE *r)
3217 {
3218 	LIST *o;
3219 	UINT i;
3220 	// Validate arguments
3221 	if (hWnd == NULL || r == NULL)
3222 	{
3223 		return;
3224 	}
3225 
3226 	SetIcon(hWnd, 0, r->Icon);
3227 
3228 	SetText(hWnd, 0, r->Caption);
3229 	SetText(hWnd, S_TITLE, r->Title);
3230 	SetIcon(hWnd, S_ICON, r->Icon);
3231 
3232 	// Read candidates
3233 	o = ReadCandidateFromReg(REG_CURRENT_USER, r->RegKeyName, "RemoteHostCandidate");
3234 	r->CandidateList = o;
3235 
3236 	// Show the candidates
3237 	for (i = 0;i < LIST_NUM(o);i++)
3238 	{
3239 		CANDIDATE *c = LIST_DATA(o, i);
3240 		CbAddStr(hWnd, C_HOSTNAME, c->Str, 0);
3241 	}
3242 
3243 	if (r->DefaultHostname != NULL)
3244 	{
3245 		SetTextA(hWnd, C_HOSTNAME, r->DefaultHostname);
3246 	}
3247 
3248 	FocusEx(hWnd, C_HOSTNAME);
3249 
3250 	RemoteDlgRefresh(hWnd, r);
3251 }
3252 
3253 // Remote connection dialog update
RemoteDlgRefresh(HWND hWnd,WINUI_REMOTE * r)3254 void RemoteDlgRefresh(HWND hWnd, WINUI_REMOTE *r)
3255 {
3256 	char *s;
3257 	bool ok = true;
3258 	bool localhost_mode = false;
3259 	// Validate arguments
3260 	if (hWnd == NULL || r == NULL)
3261 	{
3262 		return;
3263 	}
3264 
3265 	s = GetTextA(hWnd, C_HOSTNAME);
3266 	if (s != NULL)
3267 	{
3268 		Trim(s);
3269 		if (StrCmpi(s, "localhost") == 0 || StartWith(s, "127."))
3270 		{
3271 			localhost_mode = true;
3272 		}
3273 		Free(s);
3274 	}
3275 
3276 	if (localhost_mode == false)
3277 	{
3278 		Enable(hWnd, C_HOSTNAME);
3279 		Enable(hWnd, S_HOSTNAME);
3280 		Check(hWnd, R_LOCAL, false);
3281 	}
3282 	else
3283 	{
3284 		if (r->Title != _UU("NM_CONNECT_TITLE"))
3285 		{
3286 			Disable(hWnd, C_HOSTNAME);
3287 			Disable(hWnd, S_HOSTNAME);
3288 		}
3289 		Check(hWnd, R_LOCAL, true);
3290 		SetTextA(hWnd, C_HOSTNAME, "localhost");
3291 
3292 		if (r->flag1 == false)
3293 		{
3294 			Focus(hWnd, IDOK);
3295 		}
3296 	}
3297 
3298 	if (IsEmpty(hWnd, C_HOSTNAME))
3299 	{
3300 		ok = false;
3301 	}
3302 
3303 	SetEnable(hWnd, IDOK, ok);
3304 
3305 	r->flag1 = true;
3306 }
3307 
3308 // Remote connection dialog OK button
RemoteDlgOnOk(HWND hWnd,WINUI_REMOTE * r)3309 void RemoteDlgOnOk(HWND hWnd, WINUI_REMOTE *r)
3310 {
3311 	char *hostname;
3312 	wchar_t *s;
3313 	LIST *o;
3314 	// Validate arguments
3315 	if (hWnd == NULL || r == NULL)
3316 	{
3317 		return;
3318 	}
3319 
3320 	// Get the entered host name
3321 	hostname = GetTextA(hWnd, C_HOSTNAME);
3322 	if (hostname == NULL)
3323 	{
3324 		return;
3325 	}
3326 	Trim(hostname);
3327 
3328 	// Add a candidate
3329 	o = r->CandidateList;
3330 	s = CopyStrToUni(hostname);
3331 	AddCandidate(o, s, 64);
3332 	Free(s);
3333 
3334 	// Write the candidates
3335 	WriteCandidateToReg(REG_CURRENT_USER, r->RegKeyName, o, "RemoteHostCandidate");
3336 	FreeCandidateList(o);
3337 
3338 	r->Hostname = hostname;
3339 
3340 	EndDialog(hWnd, true);
3341 }
3342 
3343 // Remote connection dialog procedure
RemoteDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3344 UINT RemoteDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3345 {
3346 	WINUI_REMOTE *r = (WINUI_REMOTE *)param;
3347 	// Validate arguments
3348 	if (hWnd == NULL)
3349 	{
3350 		return 0;
3351 	}
3352 
3353 	switch (msg)
3354 	{
3355 	case WM_INITDIALOG:
3356 		RemoteDlgInit(hWnd, r);
3357 		SetTimer(hWnd, 1, 100, NULL);
3358 		break;
3359 	case WM_TIMER:
3360 		switch (wParam)
3361 		{
3362 		case 1:
3363 			KillTimer(hWnd, 1);
3364 			RemoteDlgRefresh(hWnd, r);
3365 			SetTimer(hWnd, 1, 100, NULL);
3366 			break;
3367 		}
3368 		break;
3369 	case WM_COMMAND:
3370 		switch (wParam)
3371 		{
3372 		case R_LOCAL:
3373 			if (IsChecked(hWnd, R_LOCAL) == false)
3374 			{
3375 				SetTextA(hWnd, C_HOSTNAME, "");
3376 				RemoteDlgRefresh(hWnd, r);
3377 				FocusEx(hWnd, C_HOSTNAME);
3378 			}
3379 			else
3380 			{
3381 				SetTextA(hWnd, C_HOSTNAME, "localhost");
3382 				RemoteDlgRefresh(hWnd, r);
3383 				Focus(hWnd, IDOK);
3384 			}
3385 			break;
3386 		case IDCANCEL:
3387 			Close(hWnd);
3388 			break;
3389 		case IDOK:
3390 			RemoteDlgOnOk(hWnd, r);
3391 			break;
3392 		}
3393 		switch (LOWORD(wParam))
3394 		{
3395 		case R_LOCAL:
3396 		case C_HOSTNAME:
3397 			RemoteDlgRefresh(hWnd, r);
3398 			break;
3399 		}
3400 		break;
3401 	case WM_CLOSE:
3402 		FreeCandidateList(r->CandidateList);
3403 		EndDialog(hWnd, false);
3404 		break;
3405 	}
3406 
3407 	return 0;
3408 }
3409 
3410 // Remote connection dialog
RemoteDlg(HWND hWnd,char * regkey,UINT icon,wchar_t * caption,wchar_t * title,char * default_host)3411 char *RemoteDlg(HWND hWnd, char *regkey, UINT icon, wchar_t *caption, wchar_t *title, char *default_host)
3412 {
3413 	WINUI_REMOTE r;
3414 	// Validate arguments
3415 	if (regkey == NULL)
3416 	{
3417 		regkey = "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\WinUI Common Module";
3418 	}
3419 	if (caption == NULL)
3420 	{
3421 		caption = _UU("REMOTE_DEF_CAPTION");
3422 	}
3423 	if (title == NULL)
3424 	{
3425 		title = _UU("REMOTE_DEF_TITLE");
3426 	}
3427 	if (icon == 0)
3428 	{
3429 		icon = ICO_INTERNET;
3430 	}
3431 
3432 	Zero(&r, sizeof(r));
3433 	r.RegKeyName = regkey;
3434 	r.Caption = caption;
3435 	r.Title = title;
3436 	r.Icon = icon;
3437 	r.DefaultHostname = default_host;
3438 
3439 	if (Dialog(hWnd, D_REMOTE, RemoteDlgProc, &r) == false)
3440 	{
3441 		return NULL;
3442 	}
3443 
3444 	return r.Hostname;
3445 }
3446 
3447 // Window Searching procedure
SearchWindowEnumProc(HWND hWnd,LPARAM lParam)3448 bool CALLBACK SearchWindowEnumProc(HWND hWnd, LPARAM lParam)
3449 {
3450 	if (hWnd != NULL && lParam != 0)
3451 	{
3452 		wchar_t *s = GetText(hWnd, 0);
3453 		SEARCH_WINDOW_PARAM *p = (SEARCH_WINDOW_PARAM *)lParam;
3454 		if (s != NULL)
3455 		{
3456 			if (UniStrCmpi(p->caption, s) == 0)
3457 			{
3458 				p->hWndFound = hWnd;
3459 			}
3460 			Free(s);
3461 		}
3462 	}
3463 	return true;
3464 }
3465 
3466 // Search for the window
SearchWindow(wchar_t * caption)3467 HWND SearchWindow(wchar_t *caption)
3468 {
3469 	SEARCH_WINDOW_PARAM p;
3470 	// Validate arguments
3471 	if (caption == NULL)
3472 	{
3473 		return NULL;
3474 	}
3475 
3476 	Zero(&p, sizeof(p));
3477 	p.caption = caption;
3478 	p.hWndFound = NULL;
3479 
3480 	EnumWindows(SearchWindowEnumProc, (LPARAM)&p);
3481 
3482 	return p.hWndFound;
3483 }
3484 
3485 // Allow for the specified process to become the foreground window
AllowFGWindow(UINT process_id)3486 void AllowFGWindow(UINT process_id)
3487 {
3488 	if (process_id == 0)
3489 	{
3490 		return;
3491 	}
3492 
3493 	AllowSetForegroundWindow(process_id);
3494 }
3495 
3496 // Rename the item
LvRename(HWND hWnd,UINT id,UINT pos)3497 void LvRename(HWND hWnd, UINT id, UINT pos)
3498 {
3499 	// Validate arguments
3500 	if (hWnd == NULL || pos == INFINITE)
3501 	{
3502 		return;
3503 	}
3504 
3505 	ListView_EditLabel(DlgItem(hWnd, id), pos);
3506 }
3507 
3508 // Enhanced function
LvEnhancedProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)3509 LRESULT CALLBACK LvEnhancedProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
3510 {
3511 	WNDPROC func = (WNDPROC)GetPropW(hWnd, L"ORIGINAL_FUNC");
3512 	if (func == NULL)
3513 	{
3514 		Debug("LvEnhancedProc(): GetProp() returned NULL!\n");
3515 		return 1;
3516 	}
3517 
3518 	switch (msg)
3519 	{
3520 	case WM_HSCROLL:
3521 	case WM_VSCROLL:
3522 	case WM_MOUSEWHEEL:
3523 	{
3524 		// Prevent graphical glitches with the edit box by sending the NM_RETURN signal
3525 		// to the parent dialog (the parent dialog has to delete the edit box on NM_RETURN)
3526 		NMHDR nmh;
3527 		nmh.code = NM_RETURN;
3528 		nmh.idFrom = GetDlgCtrlID(hWnd);
3529 		nmh.hwndFrom = hWnd;
3530 		SendMsg(GetParent(hWnd), 0, WM_NOTIFY, nmh.idFrom, (LPARAM)&nmh);
3531 
3532 		break;
3533 	}
3534 	case WM_CLOSE:
3535 		// Prevent list view from disappearing after pressing ESC in an edit box
3536 		return 0;
3537 	case WM_NCDESTROY:
3538 		// Restore original function during destruction
3539 		LvSetEnhanced(hWnd, 0, false);
3540 	}
3541 
3542 	return CallWindowProcW(func, hWnd, msg, wParam, lParam);
3543 }
3544 
3545 // Toggle enhanced function
LvSetEnhanced(HWND hWnd,UINT id,bool enable)3546 void LvSetEnhanced(HWND hWnd, UINT id, bool enable)
3547 {
3548 	// Validate arguments
3549 	if (hWnd == NULL)
3550 	{
3551 		return;
3552 	}
3553 
3554 	if (enable)
3555 	{
3556 		const HANDLE fn = (HANDLE)SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)LvEnhancedProc);
3557 		SetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC", fn);
3558 	}
3559 	else
3560 	{
3561 		SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)GetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC"));
3562 		RemovePropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC");
3563 	}
3564 }
3565 
3566 // Enhanced function
EditBoxEnhancedProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)3567 LRESULT CALLBACK EditBoxEnhancedProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
3568 {
3569 	WNDPROC func = (WNDPROC)GetPropW(hWnd, L"ORIGINAL_FUNC");
3570 	if (func == NULL)
3571 	{
3572 		Debug("EditBoxEnhancedProc(): GetProp() returned NULL!\n");
3573 		return 1;
3574 	}
3575 
3576 	switch (msg)
3577 	{
3578 	case WM_CHAR:
3579 		switch (wParam)
3580 		{
3581 		// CTRL + A
3582 		case 1:
3583 			SelectEdit(hWnd, 0);
3584 			return 0;
3585 		case VK_RETURN:
3586 			SendMsg(GetParent(hWnd), 0, WM_KEYDOWN, VK_RETURN, 0);
3587 			return 0;
3588 		case VK_ESCAPE:
3589 			DestroyWindow(hWnd);
3590 			return 0;
3591 		}
3592 		break;
3593 	case WM_NCDESTROY:
3594 		// Restore original function during destruction
3595 		EditBoxSetEnhanced(hWnd, 0, false);
3596 	}
3597 
3598 	return CallWindowProcW(func, hWnd, msg, wParam, lParam);
3599 }
3600 
3601 // Toggle enhanced function
EditBoxSetEnhanced(HWND hWnd,UINT id,bool enable)3602 void EditBoxSetEnhanced(HWND hWnd, UINT id, bool enable)
3603 {
3604 	// Validate arguments
3605 	if (hWnd == NULL)
3606 	{
3607 		return;
3608 	}
3609 
3610 	if (enable)
3611 	{
3612 		const HANDLE fn = (HANDLE)SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)EditBoxEnhancedProc);
3613 		SetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC", fn);
3614 	}
3615 	else
3616 	{
3617 		SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)GetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC"));
3618 		RemovePropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC");
3619 	}
3620 }
3621 
3622 // Show the menu
PrintMenu(HWND hWnd,HMENU hMenu)3623 void PrintMenu(HWND hWnd, HMENU hMenu)
3624 {
3625 	POINT p;
3626 	// Validate arguments
3627 	if (hMenu == NULL || hWnd == NULL)
3628 	{
3629 		return;
3630 	}
3631 
3632 	GetCursorPos(&p);
3633 
3634 	TrackPopupMenu(hMenu, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
3635 }
3636 
3637 // Remove a shortcut string from the menu
RemoveShortcutKeyStrFromMenu(HMENU hMenu)3638 void RemoveShortcutKeyStrFromMenu(HMENU hMenu)
3639 {
3640 	UINT i, num;
3641 	// Validate arguments
3642 	if (hMenu == NULL)
3643 	{
3644 		return;
3645 	}
3646 
3647 	num = GetMenuNum(hMenu);
3648 	for (i = 0;i < num;i++)
3649 	{
3650 		wchar_t *str = GetMenuStr(hMenu, i);
3651 		if (str != NULL)
3652 		{
3653 			UINT j, len;
3654 			len = UniStrLen(str);
3655 			for (j = 0;j < len;j++)
3656 			{
3657 				if (str[j] == L'\t')
3658 				{
3659 					str[j] = 0;
3660 				}
3661 			}
3662 			SetMenuStr(hMenu, i, str);
3663 			Free(str);
3664 		}
3665 	}
3666 }
3667 
3668 // Get the number of items in the menu
GetMenuNum(HMENU hMenu)3669 UINT GetMenuNum(HMENU hMenu)
3670 {
3671 	UINT ret;
3672 	// Validate arguments
3673 	if (hMenu == NULL)
3674 	{
3675 		return 0;
3676 	}
3677 
3678 	ret = GetMenuItemCount(hMenu);
3679 	if (ret == INFINITE)
3680 	{
3681 		return 0;
3682 	}
3683 	else
3684 	{
3685 		return ret;
3686 	}
3687 }
3688 
3689 // Set the string into the menu
SetMenuStr(HMENU hMenu,UINT pos,wchar_t * str)3690 void SetMenuStr(HMENU hMenu, UINT pos, wchar_t *str)
3691 {
3692 	MENUITEMINFOW info;
3693 	// Validate arguments
3694 	if (hMenu == NULL || pos == INFINITE || str == NULL)
3695 	{
3696 		return;
3697 	}
3698 
3699 	Zero(&info, sizeof(info));
3700 	info.cbSize = sizeof(info);
3701 	info.fMask = MIIM_STRING;
3702 	info.dwTypeData = str;
3703 	SetMenuItemInfoW(hMenu, pos, true, &info);
3704 }
SetMenuStrA(HMENU hMenu,UINT pos,char * str)3705 void SetMenuStrA(HMENU hMenu, UINT pos, char *str)
3706 {
3707 	MENUITEMINFOA info;
3708 	// Validate arguments
3709 	if (hMenu == NULL || pos == INFINITE || str == NULL)
3710 	{
3711 		return;
3712 	}
3713 
3714 	Zero(&info, sizeof(info));
3715 	info.cbSize = sizeof(info);
3716 	info.fMask = MIIM_STRING;
3717 	info.dwTypeData = str;
3718 	SetMenuItemInfoA(hMenu, pos, true, &info);
3719 }
3720 
3721 // Get a string in the menu
GetMenuStr(HMENU hMenu,UINT pos)3722 wchar_t *GetMenuStr(HMENU hMenu, UINT pos)
3723 {
3724 	wchar_t tmp[MAX_SIZE];
3725 	// Validate arguments
3726 	if (hMenu == NULL || pos == INFINITE)
3727 	{
3728 		return NULL;
3729 	}
3730 
3731 	if (GetMenuStringW(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)
3732 	{
3733 		return NULL;
3734 	}
3735 
3736 	return UniCopyStr(tmp);
3737 }
GetMenuStrA(HMENU hMenu,UINT pos)3738 char *GetMenuStrA(HMENU hMenu, UINT pos)
3739 {
3740 	char tmp[MAX_SIZE];
3741 	// Validate arguments
3742 	if (hMenu == NULL || pos == INFINITE)
3743 	{
3744 		return NULL;
3745 	}
3746 
3747 	if (GetMenuString(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)
3748 	{
3749 		return NULL;
3750 	}
3751 
3752 	return CopyStr(tmp);
3753 }
3754 
3755 // Bold the menu item
SetMenuItemBold(HMENU hMenu,UINT pos,bool bold)3756 void SetMenuItemBold(HMENU hMenu, UINT pos, bool bold)
3757 {
3758 	MENUITEMINFO info;
3759 	// Validate arguments
3760 	if (hMenu == NULL || pos == INFINITE)
3761 	{
3762 		return;
3763 	}
3764 
3765 	Zero(&info, sizeof(info));
3766 	info.cbSize = sizeof(info);
3767 	info.fMask = MIIM_STATE;
3768 
3769 	if (GetMenuItemInfo(hMenu, pos, true, &info) == false)
3770 	{
3771 		return;
3772 	}
3773 
3774 	if (bold)
3775 	{
3776 		info.fState |= MFS_DEFAULT;
3777 	}
3778 	else
3779 	{
3780 		info.fState = info.fState & ~MFS_DEFAULT;
3781 	}
3782 
3783 	SetMenuItemInfo(hMenu, pos, true, &info);
3784 }
3785 
3786 // Remove a menu item
DeleteMenuItem(HMENU hMenu,UINT pos)3787 void DeleteMenuItem(HMENU hMenu, UINT pos)
3788 {
3789 	// Validate arguments
3790 	if (hMenu == NULL || pos == INFINITE)
3791 	{
3792 		return;
3793 	}
3794 
3795 	DeleteMenu(hMenu, pos, MF_BYPOSITION);
3796 }
3797 
3798 // Get the position from the ID in the menu
GetMenuItemPos(HMENU hMenu,UINT id)3799 UINT GetMenuItemPos(HMENU hMenu, UINT id)
3800 {
3801 	UINT num, i;
3802 	// Validate arguments
3803 	if (hMenu == NULL)
3804 	{
3805 		return INFINITE;
3806 	}
3807 
3808 	num = GetMenuItemCount(hMenu);
3809 	if (num == INFINITE)
3810 	{
3811 		return INFINITE;
3812 	}
3813 
3814 	for (i = 0;i < num;i++)
3815 	{
3816 		if (GetMenuItemID(hMenu, i) == id)
3817 		{
3818 			return i;
3819 		}
3820 	}
3821 
3822 	return INFINITE;
3823 }
3824 
3825 // Get a sub-menu
LoadSubMenu(UINT menu_id,UINT pos,HMENU * parent_menu)3826 HMENU LoadSubMenu(UINT menu_id, UINT pos, HMENU *parent_menu)
3827 {
3828 	HMENU h = LoadMenu(hDll, MAKEINTRESOURCE(menu_id));
3829 	HMENU ret;
3830 	if (h == NULL)
3831 	{
3832 		return NULL;
3833 	}
3834 
3835 	ret = GetSubMenu(h, pos);
3836 
3837 	if (parent_menu != NULL)
3838 	{
3839 		*parent_menu = h;
3840 	}
3841 
3842 	return ret;
3843 }
3844 
3845 // Get the DLL of the user interface
GetUiDll()3846 HINSTANCE GetUiDll()
3847 {
3848 	return hDll;
3849 }
3850 
3851 // Connection Error dialog procedure
ConnectErrorDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)3852 UINT ConnectErrorDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
3853 {
3854 	UI_CONNECTERROR_DLG *p = (UI_CONNECTERROR_DLG *)param;
3855 	wchar_t tmp[1024];
3856 	// Validate arguments
3857 	if (hWnd == NULL)
3858 	{
3859 		return 0;
3860 	}
3861 
3862 	switch (msg)
3863 	{
3864 	case WM_INITDIALOG:
3865 		if (p->Err == ERR_DISCONNECTED || p->Err == ERR_SESSION_TIMEOUT)
3866 		{
3867 			// Message indicating that the connection has been disconnected
3868 			SetText(hWnd, S_TITLE, _UU("ERRDLG_DISCONNECTED_MSG"));
3869 		}
3870 		if (p->HideWindow)
3871 		{
3872 			Hide(hWnd, R_HIDE);
3873 		}
3874 		FormatText(hWnd, 0, p->AccountName);
3875 		FormatText(hWnd, S_TITLE, p->ServerName);
3876 		UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_ERRMSG"), p->Err, _E(p->Err));
3877 		SetText(hWnd, E_ERROR, tmp);
3878 
3879 		SetIcon(hWnd, 0, ICO_SERVER_OFFLINE);
3880 
3881 		if (p->RetryIntervalSec == 0)
3882 		{
3883 			SetText(hWnd, S_COUNTDOWN, _UU("ERRDLG_INFORMATION"));
3884 			Hide(hWnd, P_PROGRESS);
3885 			Hide(hWnd, S_RETRYINFO);
3886 		}
3887 		else
3888 		{
3889 			if (p->RetryLimit != INFINITE)
3890 			{
3891 				UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_1"), p->CurrentRetryCount, p->RetryLimit);
3892 			}
3893 			else
3894 			{
3895 				UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_2"), p->CurrentRetryCount);
3896 			}
3897 			SetText(hWnd, S_RETRYINFO, tmp);
3898 			SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec);
3899 			SetPos(hWnd, P_PROGRESS, 0);
3900 			SetTimer(hWnd, 1, 10, NULL);
3901 			p->StartTick = Tick64();
3902 		}
3903 		SetTimer(hWnd, 2, 10, NULL);
3904 		Focus(hWnd, IDOK);
3905 		break;
3906 	case WM_TIMER:
3907 		switch (wParam)
3908 		{
3909 		case 1:
3910 			if (p->RetryIntervalSec != 0)
3911 			{
3912 				UINT64 start, end, now;
3913 				now = Tick64();
3914 				start = p->StartTick;
3915 				end = start + (UINT64)p->RetryIntervalSec;
3916 
3917 				if (end > now)
3918 				{
3919 					SetPos(hWnd, P_PROGRESS, (UINT)(now - start));
3920 					UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRYCOUNT"), ((UINT)(end - now)) / 1000);
3921 					SetText(hWnd, S_COUNTDOWN, tmp);
3922 				}
3923 				else
3924 				{
3925 					Command(hWnd, IDOK);
3926 				}
3927 			}
3928 			break;
3929 		case 2:
3930 			if (p->CancelEvent != NULL)
3931 			{
3932 				if (WaitForSingleObject((HANDLE)p->CancelEvent->pData, 0) != WAIT_TIMEOUT)
3933 				{
3934 					// Forced Cancel
3935 					Close(hWnd);
3936 				}
3937 			}
3938 			break;
3939 		}
3940 		break;
3941 	case WM_COMMAND:
3942 		switch (LOWORD(wParam))
3943 		{
3944 		case R_HIDE:
3945 			p->HideWindow = IsChecked(hWnd, R_HIDE);
3946 			break;
3947 		}
3948 		switch (wParam)
3949 		{
3950 		case IDOK:
3951 			EndDialog(hWnd, true);
3952 			break;
3953 		case IDCANCEL:
3954 			Close(hWnd);
3955 			break;
3956 		}
3957 		break;
3958 	case WM_CLOSE:
3959 		EndDialog(hWnd, false);
3960 		break;
3961 	}
3962 
3963 	return 0;
3964 }
3965 
3966 // Show the connection error dialog
ConnectErrorDlg(UI_CONNECTERROR_DLG * p)3967 bool ConnectErrorDlg(UI_CONNECTERROR_DLG *p)
3968 {
3969 	// Validate arguments
3970 	if (p == NULL)
3971 	{
3972 		return false;
3973 	}
3974 
3975 	return DialogEx2(NULL, D_CONNECTERROR, ConnectErrorDlgProc, p, true, true);
3976 }
3977 
3978 // Display the contents of the certificate
PrintCheckCertInfo(HWND hWnd,UI_CHECKCERT * p)3979 void PrintCheckCertInfo(HWND hWnd, UI_CHECKCERT *p)
3980 {
3981 	wchar_t tmp[MAX_SIZE];
3982 	char tmp2[MAX_SIZE];
3983 	UCHAR md5[MD5_SIZE];
3984 	UCHAR sha1[SHA1_SIZE];
3985 	X *x;
3986 	// Validate arguments
3987 	if (hWnd == NULL || p == NULL)
3988 	{
3989 		return;
3990 	}
3991 
3992 	x = p->x;
3993 
3994 	GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);
3995 	SetText(hWnd, E_SUBJECT, tmp);
3996 
3997 	GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);
3998 	SetText(hWnd, E_ISSUER, tmp);
3999 
4000 	GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
4001 	SetText(hWnd, E_EXPIRES, tmp);
4002 
4003 	GetXDigest(x, md5, false);
4004 	BinToStr(tmp2, sizeof(tmp2), md5, sizeof(md5));
4005 	SetTextA(hWnd, E_MD5, tmp2);
4006 
4007 	GetXDigest(x, sha1, true);
4008 	BinToStr(tmp2, sizeof(tmp2), sha1, sizeof(sha1));
4009 	SetTextA(hWnd, E_SHA1, tmp2);
4010 
4011 	SetFont(hWnd, E_MD5, GetFont("Arial", 8, false, false, false, false));
4012 	SetFont(hWnd, E_SHA1, GetFont("Arial", 8, false, false, false, false));
4013 }
4014 
4015 // Warn that the certificate is different
ShowDlgDiffWarning(HWND hWnd,UI_CHECKCERT * p)4016 void ShowDlgDiffWarning(HWND hWnd, UI_CHECKCERT *p)
4017 {
4018 	UCHAR sha1_new[SHA1_SIZE], sha1_old[SHA1_SIZE];
4019 	UCHAR md5_new[MD5_SIZE], md5_old[MD5_SIZE];
4020 	char sha1_new_str[MAX_SIZE], sha1_old_str[MAX_SIZE];
4021 	char md5_new_str[MAX_SIZE], md5_old_str[MAX_SIZE];
4022 	// Validate arguments
4023 	if (hWnd == NULL || p == NULL || p->x == NULL || p->old_x == NULL)
4024 	{
4025 		return;
4026 	}
4027 
4028 	GetXDigest(p->x, sha1_new, true);
4029 	GetXDigest(p->x, md5_new, false);
4030 
4031 	GetXDigest(p->old_x, sha1_old, true);
4032 	GetXDigest(p->old_x, md5_old, false);
4033 
4034 	BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));
4035 	BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));
4036 	BinToStrEx(sha1_old_str, sizeof(sha1_old_str), sha1_old, sizeof(sha1_old));
4037 	BinToStrEx(md5_old_str, sizeof(md5_old_str), md5_old, sizeof(md5_old));
4038 
4039 	MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CC_DANGEROUS_MSG"),
4040 		p->ServerName, md5_old_str, sha1_old_str, md5_new_str, sha1_new_str);
4041 }
4042 
4043 // [OK] button is pressed
CheckCertDialogOnOk(HWND hWnd,UI_CHECKCERT * p)4044 void CheckCertDialogOnOk(HWND hWnd, UI_CHECKCERT *p)
4045 {
4046 	UCHAR sha1_new[SHA1_SIZE];
4047 	UCHAR md5_new[MD5_SIZE];
4048 	char sha1_new_str[MAX_SIZE];
4049 	char md5_new_str[MAX_SIZE];
4050 	UINT ret;
4051 	// Validate arguments
4052 	if (hWnd == NULL || p == NULL)
4053 	{
4054 		return;
4055 	}
4056 
4057 	GetXDigest(p->x, sha1_new, true);
4058 	GetXDigest(p->x, md5_new, false);
4059 	BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));
4060 	BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));
4061 
4062 	ret = MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON2,
4063 		_UU("CC_WARNING_MSG"),
4064 		p->AccountName, sha1_new_str, md5_new_str);
4065 
4066 	if (ret == IDYES)
4067 	{
4068 		p->SaveServerCert = true;
4069 	}
4070 
4071 	if (ret == IDCANCEL)
4072 	{
4073 		return;
4074 	}
4075 
4076 	p->Ok = true;
4077 	EndDialog(hWnd, true);
4078 }
4079 
4080 // Certificate dialog procedure
CheckCertDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)4081 UINT CheckCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
4082 {
4083 	UI_CHECKCERT *p = (UI_CHECKCERT *)param;
4084 	// Validate arguments
4085 	if (hWnd == NULL || param == NULL)
4086 	{
4087 		return 0;
4088 	}
4089 
4090 	switch (msg)
4091 	{
4092 	case WM_INITDIALOG:
4093 		FormatText(hWnd, 0, p->AccountName);
4094 		FormatText(hWnd, S_TITLE, p->ServerName);
4095 		FormatText(hWnd, S_MSG1, p->ServerName);
4096 
4097 		PrintCheckCertInfo(hWnd, p);
4098 
4099 		Focus(hWnd, IDCANCEL);
4100 
4101 		SetIcon(hWnd, 0, ICO_WARNING);
4102 
4103 		if (p->DiffWarning)
4104 		{
4105 			SetTimer(hWnd, 1, 1, NULL);
4106 		}
4107 
4108 		SetTimer(hWnd, 2, 100, NULL);
4109 
4110 		break;
4111 	case WM_TIMER:
4112 		switch (wParam)
4113 		{
4114 		case 1:
4115 			KillTimer(hWnd, 1);
4116 			ShowDlgDiffWarning(hWnd, p);
4117 			break;
4118 		case 2:
4119 			if ((p->Session != NULL && p->Session->Halt) ||
4120 				(p->Halt))
4121 			{
4122 				p->Ok = false;
4123 				EndDialog(hWnd, false);
4124 			}
4125 			break;
4126 		}
4127 		break;
4128 	case WM_COMMAND:
4129 		switch (wParam)
4130 		{
4131 		case B_SHOW:
4132 			CertDlg(hWnd, p->x, p->parent_x, false);
4133 			break;
4134 		case IDOK:
4135 			CheckCertDialogOnOk(hWnd, p);
4136 			break;
4137 		case IDCANCEL:
4138 			Close(hWnd);
4139 			break;
4140 		}
4141 		break;
4142 	case WM_CLOSE:
4143 		p->Ok = false;
4144 		EndDialog(hWnd, false);
4145 		break;
4146 	}
4147 
4148 	return 0;
4149 }
4150 
4151 // Certificate Check dialog
CheckCertDlg(UI_CHECKCERT * p)4152 void CheckCertDlg(UI_CHECKCERT *p)
4153 {
4154 	// Validate arguments
4155 	if (p == NULL)
4156 	{
4157 		return;
4158 	}
4159 
4160 	Dialog(NULL, D_CHECKCERT, CheckCertDlgProc, p);
4161 }
4162 
4163 // Get the image list ID from the icon ID
GetIcon(UINT icon_id)4164 UINT GetIcon(UINT icon_id)
4165 {
4166 	IMAGELIST_ICON *c, t;
4167 	t.id = icon_id;
4168 
4169 	c = Search(icon_list, &t);
4170 	if (c == NULL)
4171 	{
4172 		if (icon_id != ICO_NULL)
4173 		{
4174 			return GetIcon(ICO_NULL);
4175 		}
4176 		else
4177 		{
4178 			return INFINITE;
4179 		}
4180 	}
4181 	else
4182 	{
4183 		return c->Index;
4184 	}
4185 }
4186 
4187 // Load an icon for the image list
LoadIconForImageList(UINT id)4188 IMAGELIST_ICON *LoadIconForImageList(UINT id)
4189 {
4190 	IMAGELIST_ICON *ret = ZeroMalloc(sizeof(IMAGELIST_ICON));
4191 	HICON small_icon, large_icon;
4192 
4193 	ret->id = id;
4194 
4195 	large_icon = LoadLargeIcon(id);
4196 	if (large_icon == NULL)
4197 	{
4198 		large_icon = LoadSmallIcon(id);
4199 	}
4200 
4201 	small_icon = LoadSmallIcon(id);
4202 	if (small_icon == NULL)
4203 	{
4204 		small_icon = LoadLargeIcon(id);
4205 	}
4206 
4207 	ret->hSmallImage = small_icon;
4208 	ret->hLargeImage = large_icon;
4209 	ret->Index = ImageList_AddIcon(large_image_list, large_icon);
4210 	ImageList_AddIcon(small_image_list, small_icon);
4211 
4212 	return ret;
4213 }
4214 
4215 // Comparison of the image list icons
CompareImageListIcon(void * p1,void * p2)4216 int CompareImageListIcon(void *p1, void *p2)
4217 {
4218 	IMAGELIST_ICON *c1, *c2;
4219 	if (p1 == NULL || p2 == NULL)
4220 	{
4221 		return 0;
4222 	}
4223 	c1 = *(IMAGELIST_ICON **)p1;
4224 	c2 = *(IMAGELIST_ICON **)p2;
4225 	if (c1 == NULL || c2 == NULL)
4226 	{
4227 		return 0;
4228 	}
4229 
4230 	if (c1->id > c2->id)
4231 	{
4232 		return 1;
4233 	}
4234 	else if (c1->id < c2->id)
4235 	{
4236 		return -1;
4237 	}
4238 	else
4239 	{
4240 		return 0;
4241 	}
4242 }
4243 
4244 // Initialize thr image list
InitImageList()4245 void InitImageList()
4246 {
4247 	large_image_list = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 1, 0);
4248 	ImageList_SetBkColor(large_image_list, RGB(255, 255, 255));
4249 	small_image_list = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 0);
4250 	ImageList_SetBkColor(small_image_list, RGB(255, 255, 255));
4251 	icon_list = NewList(CompareImageListIcon);
4252 
4253 	// Enumeration
4254 	EnumResourceNames(hDll, RT_GROUP_ICON, EnumResNameProc, 0);
4255 }
4256 
4257 // Icon resource enumeration procedure
EnumResNameProc(HMODULE hModule,LPCTSTR lpszType,LPTSTR lpszName,LONG_PTR lParam)4258 BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
4259 {
4260 	if (IS_INTRESOURCE(lpszName))
4261 	{
4262 		UINT icon_id = (UINT)lpszName;
4263 		IMAGELIST_ICON *img = LoadIconForImageList(icon_id);
4264 
4265 		Add(icon_list, img);
4266 	}
4267 
4268 	return TRUE;
4269 }
4270 
4271 // Release the image list
FreeImageList()4272 void FreeImageList()
4273 {
4274 	UINT i;
4275 	ImageList_Destroy(large_image_list);
4276 	ImageList_Destroy(small_image_list);
4277 	large_image_list = small_image_list = NULL;
4278 
4279 	for (i = 0;i < LIST_NUM(icon_list);i++)
4280 	{
4281 		IMAGELIST_ICON *c = LIST_DATA(icon_list, i);
4282 		Free(c);
4283 	}
4284 
4285 	ReleaseList(icon_list);
4286 	icon_list = NULL;
4287 }
4288 
4289 // Get the width of the column of the list view
LvGetColumnWidth(HWND hWnd,UINT id,UINT index)4290 UINT LvGetColumnWidth(HWND hWnd, UINT id, UINT index)
4291 {
4292 	return (UINT)((double)ListView_GetColumnWidth(DlgItem(hWnd, id), index) / GetTextScalingFactor());
4293 }
4294 
4295 // Insert the column into the list view
LvInsertColumn(HWND hWnd,UINT id,UINT index,wchar_t * str,UINT width)4296 void LvInsertColumn(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT width)
4297 {
4298 	LVCOLUMNW c;
4299 	// Validate arguments
4300 	if (hWnd == NULL || str == NULL)
4301 	{
4302 		return;
4303 	}
4304 
4305 	width = (UINT)((double)width * GetTextScalingFactor());
4306 
4307 	Zero(&c, sizeof(c));
4308 	c.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
4309 
4310 	c.pszText = str;
4311 	c.iSubItem = index;
4312 	c.cx = width;
4313 
4314 	SendMsg(hWnd, id, LVM_INSERTCOLUMNW, index, (LPARAM)&c);
4315 }
4316 
4317 // Remove all items from list view
LvReset(HWND hWnd,UINT id)4318 void LvReset(HWND hWnd, UINT id)
4319 {
4320 	// Validate arguments
4321 	if (hWnd == NULL)
4322 	{
4323 		return;
4324 	}
4325 
4326 	ListView_DeleteAllItems(DlgItem(hWnd, id));
4327 }
4328 
4329 // Initialize the list view
LvInitEx(HWND hWnd,UINT id,bool no_image)4330 void LvInitEx(HWND hWnd, UINT id, bool no_image)
4331 {
4332 	LvInitEx2(hWnd, id, no_image, false);
4333 }
LvInitEx2(HWND hWnd,UINT id,bool no_image,bool large_icon)4334 void LvInitEx2(HWND hWnd, UINT id, bool no_image, bool large_icon)
4335 {
4336 	// Validate arguments
4337 	if (hWnd == NULL)
4338 	{
4339 		return;
4340 	}
4341 
4342 	ListView_SetUnicodeFormat(DlgItem(hWnd, id), true);
4343 
4344 	if (no_image == false)
4345 	{
4346 		ListView_SetImageList(DlgItem(hWnd, id), large_image_list, LVSIL_NORMAL);
4347 		ListView_SetImageList(DlgItem(hWnd, id), large_icon ? large_image_list : small_image_list, LVSIL_SMALL);
4348 	}
4349 
4350 	ListView_SetExtendedListViewStyle(DlgItem(hWnd, id), LVS_EX_FULLROWSELECT);
4351 
4352 	LvSetStyle(hWnd, id, LVS_EX_DOUBLEBUFFER);
4353 }
LvInit(HWND hWnd,UINT id)4354 void LvInit(HWND hWnd, UINT id)
4355 {
4356 	LvInitEx(hWnd, id, false);
4357 }
4358 
4359 // Adding batch complete (high-speed)
LvInsertEnd(LVB * b,HWND hWnd,UINT id)4360 void LvInsertEnd(LVB *b, HWND hWnd, UINT id)
4361 {
4362 	LvInsertEndEx(b, hWnd, id, false);
4363 }
LvInsertEndEx(LVB * b,HWND hWnd,UINT id,bool force_reset)4364 void LvInsertEndEx(LVB *b, HWND hWnd, UINT id, bool force_reset)
4365 {
4366 	UINT i, num;
4367 	LIST *new_list, *exist_list;
4368 	wchar_t *last_selected = NULL;
4369 	// Validate arguments
4370 	if (b == NULL || hWnd == NULL)
4371 	{
4372 		return;
4373 	}
4374 
4375 	new_list = NewListFast(CompareUniStr);
4376 
4377 	for (i = 0;i < LIST_NUM(b->ItemList);i++)
4378 	{
4379 		LVB_ITEM *t = LIST_DATA(b->ItemList, i);
4380 		Add(new_list, t->Strings[0]);
4381 	}
4382 
4383 	Sort(new_list);
4384 
4385 	if ((LIST_NUM(b->ItemList) >= LV_INSERT_RESET_ALL_ITEM_MIN) || force_reset)
4386 	{
4387 		last_selected = LvGetFocusedStr(hWnd, id, 0);
4388 		LvReset(hWnd, id);
4389 	}
4390 
4391 	exist_list = NewListFast(CompareUniStr);
4392 
4393 	num = LvNum(hWnd, id);
4394 
4395 	// Delete the items which isn't contained in the batch list of existing items
4396 	for (i = 0;i < num;i++)
4397 	{
4398 		bool exists = false;
4399 		wchar_t *s = LvGetStr(hWnd, id, i, 0);
4400 		if (Search(new_list, s) != NULL)
4401 		{
4402 			exists = true;
4403 		}
4404 		if (exists == false)
4405 		{
4406 			// Remove items that don't exist in the batch list of the adding plan from the list view
4407 			LvDeleteItem(hWnd, id, i);
4408 			num = LvNum(hWnd, id);
4409 			i--;
4410 			Free(s);
4411 		}
4412 		else
4413 		{
4414 			Add(exist_list, s);
4415 		}
4416 	}
4417 
4418 	Sort(exist_list);
4419 
4420 	// Add items in the batch one by one
4421 	for (i = 0;i < LIST_NUM(b->ItemList);i++)
4422 	{
4423 		LVB_ITEM *t = LIST_DATA(b->ItemList, i);
4424 		UINT index;
4425 		UINT j;
4426 		bool exists = false;
4427 
4428 		if (Search(exist_list, t->Strings[0]) != NULL)
4429 		{
4430 			index = LvSearchStr(hWnd, id, 0, t->Strings[0]);
4431 		}
4432 		else
4433 		{
4434 			index = INFINITE;
4435 		}
4436 
4437 		if (index != INFINITE)
4438 		{
4439 			UINT j;
4440 			// If an item with the string same to adding item already exists,
4441 			// update instead of adding
4442 			for (j = 0;j < t->NumStrings;j++)
4443 			{
4444 				LvSetItem(hWnd, id, index, j, t->Strings[j]);
4445 			}
4446 			LvSetItemImageByImageListId(hWnd, id, index, t->Image);
4447 			LvSetItemParam(hWnd, id, index, t->Param);
4448 		}
4449 		else
4450 		{
4451 			// Add newly
4452 			UINT index = INFINITE;
4453 			UINT j;
4454 			for (j = 0;j < t->NumStrings;j++)
4455 			{
4456 				if (j == 0)
4457 				{
4458 					index = LvInsertItemByImageListId(hWnd, id, t->Image, t->Param, t->Strings[j]);
4459 				}
4460 				else
4461 				{
4462 					LvSetItem(hWnd, id, index, j, t->Strings[j]);
4463 				}
4464 			}
4465 		}
4466 
4467 		// Release the memory
4468 		for (j = 0;j < t->NumStrings;j++)
4469 		{
4470 			Free(t->Strings[j]);
4471 		}
4472 		Free(t->Strings);
4473 		Free(t);
4474 	}
4475 
4476 	// Release the list
4477 	ReleaseList(b->ItemList);
4478 
4479 	// Release the memory
4480 	Free(b);
4481 
4482 	ReleaseList(new_list);
4483 
4484 	for (i = 0;i < LIST_NUM(exist_list);i++)
4485 	{
4486 		Free(LIST_DATA(exist_list, i));
4487 	}
4488 	ReleaseList(exist_list);
4489 
4490 	if (last_selected != NULL)
4491 	{
4492 		UINT pos = LvSearchStr(hWnd, id, 0, last_selected);
4493 
4494 		if (pos != INFINITE)
4495 		{
4496 			LvSelect(hWnd, id, pos);
4497 		}
4498 
4499 		Free(last_selected);
4500 	}
4501 }
4502 
4503 // Get the number of columns of the list view
LvGetColumnNum(HWND hWnd,UINT id)4504 UINT LvGetColumnNum(HWND hWnd, UINT id)
4505 {
4506 	UINT i;
4507 	LVCOLUMN c;
4508 	if (hWnd == NULL)
4509 	{
4510 		return 0;
4511 	}
4512 
4513 	for (i = 0;;i++)
4514 	{
4515 		Zero(&c, sizeof(c));
4516 		c.mask = LVCF_SUBITEM;
4517 		if (ListView_GetColumn(DlgItem(hWnd, id), i, &c) == false)
4518 		{
4519 			break;
4520 		}
4521 	}
4522 
4523 	return i;
4524 }
4525 
4526 // List-view sort function
LvSortProc(LPARAM param1,LPARAM param2,LPARAM sort_param)4527 int CALLBACK LvSortProc(LPARAM param1, LPARAM param2, LPARAM sort_param)
4528 {
4529 	WINUI_LV_SORT *sort = (WINUI_LV_SORT *)sort_param;
4530 	HWND hWnd;
4531 	UINT id;
4532 	UINT i1, i2;
4533 	int ret = 0;
4534 	wchar_t *s1, *s2;
4535 	if (sort == NULL)
4536 	{
4537 		return 0;
4538 	}
4539 
4540 	hWnd = sort->hWnd;
4541 	id = sort->id;
4542 
4543 	if (hWnd == NULL)
4544 	{
4545 		return 0;
4546 	}
4547 
4548 	i1 = (UINT)param1;
4549 	i2 = (UINT)param2;
4550 
4551 	s1 = LvGetStr(hWnd, id, i1, sort->subitem);
4552 	if (s1 == NULL)
4553 	{
4554 		return 0;
4555 	}
4556 
4557 	s2 = LvGetStr(hWnd, id, i2, sort->subitem);
4558 	if (s2 == NULL)
4559 	{
4560 		Free(s1);
4561 		return 0;
4562 	}
4563 
4564 	if (sort->numeric == false)
4565 	{
4566 		if (UniStrCmpi(s1, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_LINK")) == 0)
4567 		{
4568 			ret = -1;
4569 		}
4570 		else if (UniStrCmpi(s2, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(s2, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_LINK")) == 0)
4571 		{
4572 			ret = 1;
4573 		}
4574 		else
4575 		{
4576 			ret = UniStrCmpi(s1, s2);
4577 		}
4578 	}
4579 	else
4580 	{
4581 		UINT64 v1, v2;
4582 		v1 = UniToInt64(s1);
4583 		v2 = UniToInt64(s2);
4584 		if (v1 > v2)
4585 		{
4586 			ret = 1;
4587 		}
4588 		else if (v1 < v2)
4589 		{
4590 			ret = -1;
4591 		}
4592 		else
4593 		{
4594 			ret = 0;
4595 		}
4596 	}
4597 
4598 	Free(s1);
4599 	Free(s2);
4600 
4601 	if (sort->desc)
4602 	{
4603 		ret = -ret;
4604 	}
4605 
4606 	return ret;
4607 }
4608 
4609 // Standard handler
LvStandardHandler(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,UINT id)4610 void LvStandardHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)
4611 {
4612 	NMHDR *n;
4613 	NMLVKEYDOWN *key;
4614 	// Validate arguments
4615 	if (hWnd == NULL)
4616 	{
4617 		return;
4618 	}
4619 
4620 	LvSortHander(hWnd, msg, wParam, lParam, id);
4621 
4622 	switch (msg)
4623 	{
4624 	case WM_NOTIFY:
4625 		n = (NMHDR *)lParam;
4626 		if (n->idFrom == id)
4627 		{
4628 			switch (n->code)
4629 			{
4630 			case NM_DBLCLK:
4631 				Command(hWnd, IDOK);
4632 				break;
4633 			case LVN_KEYDOWN:
4634 				key = (NMLVKEYDOWN *)n;
4635 				if (key != NULL)
4636 				{
4637 					UINT code = key->wVKey;
4638 					switch (code)
4639 					{
4640 					case VK_DELETE:
4641 						Command(hWnd, B_DELETE);
4642 						break;
4643 
4644 					case VK_RETURN:
4645 						Command(hWnd, IDOK);
4646 						break;
4647 
4648 					case VK_F5:
4649 						Command(hWnd, B_REFRESH);
4650 						break;
4651 					}
4652 				}
4653 				break;
4654 			}
4655 		}
4656 		break;
4657 	}
4658 }
4659 
4660 // Sort header handler
LvSortHander(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,UINT id)4661 void LvSortHander(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)
4662 {
4663 	NMHDR *nmhdr;
4664 	UINT subitem;
4665 	bool desc;
4666 	// Validate arguments
4667 	if (hWnd == NULL)
4668 	{
4669 		return;
4670 	}
4671 
4672 	switch (msg)
4673 	{
4674 	case WM_NOTIFY:
4675 		nmhdr = (NMHDR *)lParam;
4676 
4677 		if (nmhdr != NULL)
4678 		{
4679 			if (nmhdr->idFrom == id)
4680 			{
4681 				NMLISTVIEW *v;
4682 				switch (nmhdr->code)
4683 				{
4684 				case LVN_COLUMNCLICK:
4685 					desc = false;
4686 					v = (NMLISTVIEW *)lParam;
4687 					subitem = v->iSubItem;
4688 
4689 					if ((GetStyle(hWnd, id) & LVS_SORTDESCENDING) == 0)
4690 					{
4691 						desc = true;
4692 						SetStyle(hWnd, id, LVS_SORTDESCENDING);
4693 						RemoveStyle(hWnd, id, LVS_SORTASCENDING);
4694 					}
4695 					else
4696 					{
4697 						SetStyle(hWnd, id, LVS_SORTASCENDING);
4698 						RemoveStyle(hWnd, id, LVS_SORTDESCENDING);
4699 					}
4700 
4701 					LvSort(hWnd, id, subitem, desc);
4702 					break;
4703 				}
4704 			}
4705 		}
4706 		break;
4707 	}
4708 }
4709 
4710 // Do sort
LvSort(HWND hWnd,UINT id,UINT subitem,bool desc)4711 void LvSort(HWND hWnd, UINT id, UINT subitem, bool desc)
4712 {
4713 	UINT i, num;
4714 	bool numeric = true;
4715 	wchar_t na[2] = {0xff0d, 0x0, };
4716 	// Validate arguments
4717 	if (hWnd == NULL)
4718 	{
4719 		return;
4720 	}
4721 
4722 	num = LvNum(hWnd, id);
4723 	for (i = 0;i < num;i++)
4724 	{
4725 		wchar_t *s = LvGetStr(hWnd, id, i, subitem);
4726 		if (s != NULL)
4727 		{
4728 			if (UniIsNum(s) == false && UniStrCmp(s, na) != 0)
4729 			{
4730 				numeric = false;
4731 				Free(s);
4732 				break;
4733 			}
4734 			Free(s);
4735 		}
4736 		else
4737 		{
4738 			numeric = false;
4739 			break;
4740 		}
4741 	}
4742 
4743 	LvSortEx(hWnd, id, subitem, desc, numeric);
4744 }
4745 
LvSortEx(HWND hWnd,UINT id,UINT subitem,bool desc,bool numeric)4746 void LvSortEx(HWND hWnd, UINT id, UINT subitem, bool desc, bool numeric)
4747 {
4748 	WINUI_LV_SORT s;
4749 	// Validate arguments
4750 	if (hWnd == NULL)
4751 	{
4752 		return;
4753 	}
4754 	if (subitem >= LvGetColumnNum(hWnd, id))
4755 	{
4756 		return;
4757 	}
4758 
4759 	Zero(&s, sizeof(s));
4760 	s.desc = desc;
4761 	s.numeric = numeric;
4762 	s.id = id;
4763 	s.hWnd = hWnd;
4764 	s.subitem = subitem;
4765 
4766 	ListView_SortItemsEx(DlgItem(hWnd, id), LvSortProc, (LPARAM)&s);
4767 }
4768 
4769 // Add an item to adding batch
LvInsertAdd(LVB * b,UINT icon,void * param,UINT num_str,...)4770 void LvInsertAdd(LVB *b, UINT icon, void *param, UINT num_str, ...)
4771 {
4772 	UINT i;
4773 	va_list va;
4774 	UINT index = 0;
4775 	LVB_ITEM *t;
4776 	// Validate arguments
4777 	if (b == NULL || num_str == 0)
4778 	{
4779 		return;
4780 	}
4781 
4782 	t = ZeroMalloc(sizeof(LVB_ITEM));
4783 
4784 	va_start(va, num_str);
4785 
4786 	t->Strings = (wchar_t **)ZeroMalloc(sizeof(wchar_t *) * num_str);
4787 	t->NumStrings = num_str;
4788 
4789 	for (i = 0;i < num_str;i++)
4790 	{
4791 		wchar_t *s = va_arg(va, wchar_t *);
4792 
4793 		t->Strings[i] = UniCopyStr(s);
4794 	}
4795 
4796 	t->Param = param;
4797 	t->Image = GetIcon(icon);
4798 
4799 	Add(b->ItemList, t);
4800 
4801 	va_end(va);
4802 }
4803 
4804 // Start the item adding batch
LvInsertStart()4805 LVB *LvInsertStart()
4806 {
4807 	LVB *b = ZeroMalloc(sizeof(LVB));
4808 	b->ItemList = NewListFast(NULL);
4809 
4810 	return b;
4811 }
4812 
4813 // Add items to the list view
LvInsert(HWND hWnd,UINT id,UINT icon,void * param,UINT num_str,...)4814 void LvInsert(HWND hWnd, UINT id, UINT icon, void *param, UINT num_str, ...)
4815 {
4816 	UINT i;
4817 	va_list va;
4818 	UINT index = 0;
4819 	// Validate arguments
4820 	if (hWnd == NULL)
4821 	{
4822 		return;
4823 	}
4824 
4825 	va_start(va, num_str);
4826 
4827 	for (i = 0;i < num_str;i++)
4828 	{
4829 		wchar_t *s = va_arg(va, wchar_t *);
4830 		if (i == 0)
4831 		{
4832 			index = LvInsertItem(hWnd, id, icon, param, s);
4833 		}
4834 		else
4835 		{
4836 			LvSetItem(hWnd, id, index, i, s);
4837 		}
4838 	}
4839 
4840 	va_end(va);
4841 }
4842 
4843 // Adjust the item size automatically
LvAutoSize(HWND hWnd,UINT id)4844 void LvAutoSize(HWND hWnd, UINT id)
4845 {
4846 	UINT i;
4847 	// Validate arguments
4848 	if (hWnd == NULL)
4849 	{
4850 		return;
4851 	}
4852 
4853 	i = 0;
4854 	while (true)
4855 	{
4856 		if (ListView_SetColumnWidth(DlgItem(hWnd, id), i, LVSCW_AUTOSIZE) == false)
4857 		{
4858 			break;
4859 		}
4860 		i++;
4861 	}
4862 }
4863 
4864 // Add an item
LvInsertItem(HWND hWnd,UINT id,UINT icon,void * param,wchar_t * str)4865 UINT LvInsertItem(HWND hWnd, UINT id, UINT icon, void *param, wchar_t *str)
4866 {
4867 	return LvInsertItemByImageListId(hWnd, id, GetIcon(icon), param, str);
4868 }
LvInsertItemByImageListId(HWND hWnd,UINT id,UINT image,void * param,wchar_t * str)4869 UINT LvInsertItemByImageListId(HWND hWnd, UINT id, UINT image, void *param, wchar_t *str)
4870 {
4871 	LVITEMW t;
4872 	// Validate arguments
4873 	if (hWnd == NULL || str == NULL)
4874 	{
4875 		return INFINITE;
4876 	}
4877 
4878 	Zero(&t, sizeof(t));
4879 	t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
4880 	t.pszText = str;
4881 	t.iImage = image;
4882 	t.lParam = (LPARAM)param;
4883 	t.iItem = LvNum(hWnd, id);
4884 
4885 	return SendMsg(hWnd, id, LVM_INSERTITEMW, 0, (LPARAM)&t);
4886 }
LvInsertItemByImageListIdA(HWND hWnd,UINT id,UINT image,void * param,char * str)4887 UINT LvInsertItemByImageListIdA(HWND hWnd, UINT id, UINT image, void *param, char *str)
4888 {
4889 	LVITEM t;
4890 	// Validate arguments
4891 	if (hWnd == NULL || str == NULL)
4892 	{
4893 		return INFINITE;
4894 	}
4895 
4896 	Zero(&t, sizeof(t));
4897 	t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
4898 	t.pszText = str;
4899 	t.iImage = image;
4900 	t.lParam = (LPARAM)param;
4901 	t.iItem = LvNum(hWnd, id);
4902 
4903 	return SendMsg(hWnd, id, LVM_INSERTITEM, 0, (LPARAM)&t);
4904 }
4905 
4906 // Change the image
LvSetItemImageByImageListId(HWND hWnd,UINT id,UINT index,UINT image)4907 void LvSetItemImageByImageListId(HWND hWnd, UINT id, UINT index, UINT image)
4908 {
4909 	LVITEM t;
4910 	// Validate arguments
4911 	if (hWnd == NULL)
4912 	{
4913 		return;
4914 	}
4915 
4916 	Zero(&t, sizeof(t));
4917 	t.mask = LVIF_IMAGE;
4918 	t.iImage = image;
4919 	t.iItem = index;
4920 
4921 	SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
4922 }
4923 
4924 // Set the parameters of the item
LvSetItemParam(HWND hWnd,UINT id,UINT index,void * param)4925 void LvSetItemParam(HWND hWnd, UINT id, UINT index, void *param)
4926 {
4927 	LvSetItemParamEx(hWnd, id, index, 0, param);
4928 }
LvSetItemParamEx(HWND hWnd,UINT id,UINT index,UINT subitem,void * param)4929 void LvSetItemParamEx(HWND hWnd, UINT id, UINT index, UINT subitem, void *param)
4930 {
4931 	LVITEM t;
4932 	// Validate arguments
4933 	if (hWnd == NULL)
4934 	{
4935 		return;
4936 	}
4937 
4938 	Zero(&t, sizeof(t));
4939 	t.mask = LVIF_PARAM;
4940 	t.iItem = index;
4941 	t.iSubItem = subitem;
4942 	t.lParam = (LPARAM)param;
4943 
4944 	SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
4945 }
4946 
4947 // Set the item
LvSetItem(HWND hWnd,UINT id,UINT index,UINT pos,wchar_t * str)4948 void LvSetItem(HWND hWnd, UINT id, UINT index, UINT pos, wchar_t *str)
4949 {
4950 	LVITEMW t;
4951 	wchar_t *old_str;
4952 	// Validate arguments
4953 	if (hWnd == NULL || str == NULL)
4954 	{
4955 		return;
4956 	}
4957 
4958 	Zero(&t, sizeof(t));
4959 	t.mask = LVIF_TEXT;
4960 	t.pszText = str;
4961 	t.iItem = index;
4962 	t.iSubItem = pos;
4963 
4964 	old_str = LvGetStr(hWnd, id, index, pos);
4965 
4966 	if (UniStrCmp(old_str, str) != 0)
4967 	{
4968 		SendMsg(hWnd, id, LVM_SETITEMW, 0, (LPARAM)&t);
4969 	}
4970 
4971 	Free(old_str);
4972 }
LvSetItemA(HWND hWnd,UINT id,UINT index,UINT pos,char * str)4973 void LvSetItemA(HWND hWnd, UINT id, UINT index, UINT pos, char *str)
4974 {
4975 	LVITEM t;
4976 	wchar_t *old_str;
4977 	char *old_str_2;
4978 	// Validate arguments
4979 	if (hWnd == NULL || str == NULL)
4980 	{
4981 		return;
4982 	}
4983 
4984 	Zero(&t, sizeof(t));
4985 	t.mask = LVIF_TEXT;
4986 	t.pszText = str;
4987 	t.iItem = index;
4988 	t.iSubItem = pos;
4989 
4990 	old_str = LvGetStr(hWnd, id, index, pos);
4991 	old_str_2 = CopyUniToStr(old_str);
4992 
4993 	if (StrCmp(old_str_2, str) != 0)
4994 	{
4995 		SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
4996 	}
4997 
4998 	Free(old_str_2);
4999 	Free(old_str);
5000 }
5001 
5002 // Set the view of the list box
LvSetView(HWND hWnd,UINT id,bool details)5003 void LvSetView(HWND hWnd, UINT id, bool details)
5004 {
5005 	// Validate arguments
5006 	if (hWnd == NULL)
5007 	{
5008 		return;
5009 	}
5010 
5011 	if (details)
5012 	{
5013 		RemoveStyle(hWnd, id, LVS_ICON);
5014 		SetStyle(hWnd, id, LVS_REPORT);
5015 	}
5016 	else
5017 	{
5018 		RemoveStyle(hWnd, id, LVS_REPORT);
5019 		SetStyle(hWnd, id, LVS_ICON);
5020 	}
5021 }
5022 
5023 // Get whether there is currently selected item
LvIsSelected(HWND hWnd,UINT id)5024 bool LvIsSelected(HWND hWnd, UINT id)
5025 {
5026 	// Validate arguments
5027 	if (hWnd == NULL)
5028 	{
5029 		return false;
5030 	}
5031 
5032 	if (LvGetSelected(hWnd, id) == INFINITE)
5033 	{
5034 		return false;
5035 	}
5036 
5037 	return true;
5038 }
5039 
5040 // Get the currently selected item
LvGetFocused(HWND hWnd,UINT id)5041 UINT LvGetFocused(HWND hWnd, UINT id)
5042 {
5043 	// Validate arguments
5044 	if (hWnd == NULL)
5045 	{
5046 		return INFINITE;
5047 	}
5048 
5049 	return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED);
5050 }
5051 
5052 // Get the parameter of the currently selected item
LvGetSelectedParam(HWND hWnd,UINT id)5053 void *LvGetSelectedParam(HWND hWnd, UINT id)
5054 {
5055 	UINT index;
5056 	// Validate arguments
5057 	if (hWnd == NULL)
5058 	{
5059 		return NULL;
5060 	}
5061 
5062 	index = LvGetSelected(hWnd, id);
5063 
5064 	if (index == INFINITE)
5065 	{
5066 		return NULL;
5067 	}
5068 
5069 	return LvGetParam(hWnd, id, index);
5070 }
5071 
5072 // Get a string that is currently selected
LvGetFocusedStr(HWND hWnd,UINT id,UINT pos)5073 wchar_t *LvGetFocusedStr(HWND hWnd, UINT id, UINT pos)
5074 {
5075 	UINT i;
5076 	// Validate arguments
5077 	if (hWnd == NULL)
5078 	{
5079 		return NULL;
5080 	}
5081 
5082 	i = LvGetFocused(hWnd, id);
5083 	if (i == INFINITE)
5084 	{
5085 		return NULL;
5086 	}
5087 
5088 	return LvGetStr(hWnd, id, i, pos);
5089 }
5090 
5091 // Get the currently selected item
LvGetSelected(HWND hWnd,UINT id)5092 UINT LvGetSelected(HWND hWnd, UINT id)
5093 {
5094 	// Validate arguments
5095 	if (hWnd == NULL)
5096 	{
5097 		return INFINITE;
5098 	}
5099 
5100 	return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED | LVNI_SELECTED);
5101 }
5102 
5103 // Get a string that is currently selected
LvGetSelectedStr(HWND hWnd,UINT id,UINT pos)5104 wchar_t *LvGetSelectedStr(HWND hWnd, UINT id, UINT pos)
5105 {
5106 	UINT i;
5107 	// Validate arguments
5108 	if (hWnd == NULL)
5109 	{
5110 		return NULL;
5111 	}
5112 
5113 	i = LvGetSelected(hWnd, id);
5114 	if (i == INFINITE)
5115 	{
5116 		return NULL;
5117 	}
5118 
5119 	return LvGetStr(hWnd, id, i, pos);
5120 }
LvGetSelectedStrA(HWND hWnd,UINT id,UINT pos)5121 char *LvGetSelectedStrA(HWND hWnd, UINT id, UINT pos)
5122 {
5123 	char *ret;
5124 	wchar_t *tmp = LvGetSelectedStr(hWnd, id, pos);
5125 	if (tmp == NULL)
5126 	{
5127 		return NULL;
5128 	}
5129 	ret = CopyUniToStr(tmp);
5130 	Free(tmp);
5131 	return ret;
5132 }
5133 
5134 // Get whether two or more items are masked
LvIsMultiMasked(HWND hWnd,UINT id)5135 bool LvIsMultiMasked(HWND hWnd, UINT id)
5136 {
5137 	UINT i;
5138 	// Validate arguments
5139 	if (hWnd == NULL)
5140 	{
5141 		return false;
5142 	}
5143 
5144 	i = INFINITE;
5145 	i = LvGetNextMasked(hWnd, id, i);
5146 	if (i != INFINITE)
5147 	{
5148 		if (LvGetNextMasked(hWnd, id, i) != INFINITE)
5149 		{
5150 			return true;
5151 		}
5152 	}
5153 
5154 	return false;
5155 }
5156 
5157 // Examine whether just only one item is selected
LvIsSingleSelected(HWND hWnd,UINT id)5158 bool LvIsSingleSelected(HWND hWnd, UINT id)
5159 {
5160 	return LvIsSelected(hWnd, id) && (LvIsMultiMasked(hWnd, id) == false);
5161 }
5162 
5163 // Get whether there are items that are currently masked
LvIsMasked(HWND hWnd,UINT id)5164 bool LvIsMasked(HWND hWnd, UINT id)
5165 {
5166 	// Validate arguments
5167 	if (hWnd == NULL)
5168 	{
5169 		return false;
5170 	}
5171 
5172 	if (LvGetNextMasked(hWnd, id, INFINITE) == INFINITE)
5173 	{
5174 		return false;
5175 	}
5176 
5177 	return true;
5178 }
5179 
5180 // Get the items that is currently masked
LvGetNextMasked(HWND hWnd,UINT id,UINT start)5181 UINT LvGetNextMasked(HWND hWnd, UINT id, UINT start)
5182 {
5183 	// Validate arguments
5184 	if (hWnd == NULL)
5185 	{
5186 		return INFINITE;
5187 	}
5188 
5189 	return ListView_GetNextItem(DlgItem(hWnd, id), start, LVNI_SELECTED);
5190 }
5191 
5192 // Search an item with the specified string
LvSearchStr(HWND hWnd,UINT id,UINT pos,wchar_t * str)5193 UINT LvSearchStr(HWND hWnd, UINT id, UINT pos, wchar_t *str)
5194 {
5195 	UINT i, num;
5196 	// Validate arguments
5197 	if (hWnd == NULL || str == NULL)
5198 	{
5199 		return INFINITE;
5200 	}
5201 
5202 	num = LvNum(hWnd, id);
5203 
5204 	for (i = 0;i < num;i++)
5205 	{
5206 		wchar_t *s = LvGetStr(hWnd, id, i, pos);
5207 		if (s != NULL)
5208 		{
5209 			if (UniStrCmpi(s, str) == 0)
5210 			{
5211 				Free(s);
5212 				return i;
5213 			}
5214 			else
5215 			{
5216 				Free(s);
5217 			}
5218 		}
5219 	}
5220 
5221 	return INFINITE;
5222 }
LvSearchStrA(HWND hWnd,UINT id,UINT pos,char * str)5223 UINT LvSearchStrA(HWND hWnd, UINT id, UINT pos, char *str)
5224 {
5225 	wchar_t *tmp = CopyStrToUni(str);
5226 	UINT ret = LvSearchStr(hWnd, id, pos, tmp);
5227 	Free(tmp);
5228 	return ret;
5229 }
5230 
5231 // Search for item that have a specified param
LvSearchParam(HWND hWnd,UINT id,void * param)5232 UINT LvSearchParam(HWND hWnd, UINT id, void *param)
5233 {
5234 	UINT i, num;
5235 	// Validate arguments
5236 	if (hWnd == NULL)
5237 	{
5238 		return INFINITE;
5239 	}
5240 
5241 	num = LvNum(hWnd, id);
5242 
5243 	for (i = 0;i < num;i++)
5244 	{
5245 		if (LvGetParam(hWnd, id, i) == param)
5246 		{
5247 			return i;
5248 		}
5249 	}
5250 
5251 	return INFINITE;
5252 }
5253 
5254 // Get the number of items
LvNum(HWND hWnd,UINT id)5255 UINT LvNum(HWND hWnd, UINT id)
5256 {
5257 	// Validate arguments
5258 	if (hWnd == NULL)
5259 	{
5260 		return 0;
5261 	}
5262 
5263 	return ListView_GetItemCount(DlgItem(hWnd, id));
5264 }
5265 
5266 // Remove an item
LvDeleteItem(HWND hWnd,UINT id,UINT index)5267 void LvDeleteItem(HWND hWnd, UINT id, UINT index)
5268 {
5269 	UINT i;
5270 	// Validate arguments
5271 	if (hWnd == NULL)
5272 	{
5273 		return;
5274 	}
5275 
5276 	ListView_DeleteItem(DlgItem(hWnd, id), index);
5277 
5278 	i = LvGetSelected(hWnd, id);
5279 	if (i != INFINITE)
5280 	{
5281 		LvSelect(hWnd, id, i);
5282 	}
5283 }
5284 
5285 // Get the data from the item
LvGetParam(HWND hWnd,UINT id,UINT index)5286 void *LvGetParam(HWND hWnd, UINT id, UINT index)
5287 {
5288 	return LvGetParamEx(hWnd, id, index, 0);
5289 }
LvGetParamEx(HWND hWnd,UINT id,UINT index,UINT subitem)5290 void *LvGetParamEx(HWND hWnd, UINT id, UINT index, UINT subitem)
5291 {
5292 	LVITEM t;
5293 	// Validate arguments
5294 	if (hWnd == NULL)
5295 	{
5296 		return NULL;
5297 	}
5298 	if (index == INFINITE)
5299 	{
5300 		return NULL;
5301 	}
5302 
5303 	Zero(&t, sizeof(t));
5304 	t.mask = LVIF_PARAM;
5305 	t.iItem = index;
5306 	t.iSubItem = subitem;
5307 
5308 	if (ListView_GetItem(DlgItem(hWnd, id), &t) == false)
5309 	{
5310 		return NULL;
5311 	}
5312 
5313 	return (void *)t.lParam;
5314 }
5315 
5316 // Get the string of item
LvGetStr(HWND hWnd,UINT id,UINT index,UINT pos)5317 wchar_t *LvGetStr(HWND hWnd, UINT id, UINT index, UINT pos)
5318 {
5319 	wchar_t *tmp;
5320 	UINT size;
5321 	LVITEMW t;
5322 	// Validate arguments
5323 	if (hWnd == NULL)
5324 	{
5325 		return NULL;
5326 	}
5327 
5328 	size = 65536;
5329 	tmp = Malloc(size);
5330 
5331 	Zero(&t, sizeof(t));
5332 	t.mask = LVIF_TEXT;
5333 	t.iItem = index;
5334 	t.iSubItem = pos;
5335 	t.pszText = tmp;
5336 	t.cchTextMax = size;
5337 
5338 	if (SendMsg(hWnd, id, LVM_GETITEMTEXTW, index, (LPARAM)&t) <= 0)
5339 	{
5340 		Free(tmp);
5341 		return UniCopyStr(L"");
5342 	}
5343 	else
5344 	{
5345 		wchar_t *ret = UniCopyStr(tmp);
5346 		Free(tmp);
5347 		return ret;
5348 	}
5349 }
LvGetStrA(HWND hWnd,UINT id,UINT index,UINT pos)5350 char *LvGetStrA(HWND hWnd, UINT id, UINT index, UINT pos)
5351 {
5352 	char *tmp;
5353 	UINT size;
5354 	LVITEM t;
5355 	// Validate arguments
5356 	if (hWnd == NULL)
5357 	{
5358 		return NULL;
5359 	}
5360 
5361 	size = 65536;
5362 	tmp = Malloc(size);
5363 
5364 	Zero(&t, sizeof(t));
5365 	t.mask = LVIF_TEXT;
5366 	t.iItem = index;
5367 	t.iSubItem = pos;
5368 	t.pszText = tmp;
5369 	t.cchTextMax = size;
5370 
5371 	if (SendMsg(hWnd, id, LVM_GETITEMTEXT, index, (LPARAM)&t) <= 0)
5372 	{
5373 		Free(tmp);
5374 		return CopyStr("");
5375 	}
5376 	else
5377 	{
5378 		char *ret = CopyStr(tmp);
5379 		Free(tmp);
5380 		return ret;
5381 	}
5382 }
5383 
5384 // Set the style
LvSetStyle(HWND hWnd,UINT id,UINT style)5385 void LvSetStyle(HWND hWnd, UINT id, UINT style)
5386 {
5387 	// Validate arguments
5388 	if (hWnd == NULL)
5389 	{
5390 		return;
5391 	}
5392 
5393 	if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) == 0)
5394 	{
5395 		ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, style);
5396 	}
5397 }
5398 
5399 // Remove the style
LvRemoveStyle(HWND hWnd,UINT id,UINT style)5400 void LvRemoveStyle(HWND hWnd, UINT id, UINT style)
5401 {
5402 	// Validate arguments
5403 	if (hWnd == NULL)
5404 	{
5405 		return;
5406 	}
5407 
5408 	if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) != 0)
5409 	{
5410 		ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, 0);
5411 	}
5412 }
5413 
5414 // Invert the selection of items
LvSwitchSelect(HWND hWnd,UINT id)5415 void LvSwitchSelect(HWND hWnd, UINT id)
5416 {
5417 	UINT i, num;
5418 	bool *states;
5419 	// Validate arguments
5420 	if (hWnd == NULL)
5421 	{
5422 		return;
5423 	}
5424 
5425 	num = LvNum(hWnd, id);
5426 	states = ZeroMalloc(sizeof(bool) * num);
5427 
5428 	i = INFINITE;
5429 	while (true)
5430 	{
5431 		i = LvGetNextMasked(hWnd, id, i);
5432 		if (i == INFINITE)
5433 		{
5434 			break;
5435 		}
5436 
5437 		states[i] = true;
5438 	}
5439 
5440 	for (i = 0;i < num;i++)
5441 	{
5442 		if (states[i] == false)
5443 		{
5444 			ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);
5445 		}
5446 		else
5447 		{
5448 			ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);
5449 		}
5450 	}
5451 
5452 	Free(states);
5453 }
5454 
5455 // Select all items
LvSelectAll(HWND hWnd,UINT id)5456 void LvSelectAll(HWND hWnd, UINT id)
5457 {
5458 	UINT i, num;
5459 	// Validate arguments
5460 	if (hWnd == NULL)
5461 	{
5462 		return;
5463 	}
5464 
5465 	num = LvNum(hWnd, id);
5466 	for (i = 0;i < num;i++)
5467 	{
5468 		ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);
5469 	}
5470 }
5471 
5472 // Select the item by specifying the parameter
LvSelectByParam(HWND hWnd,UINT id,void * param)5473 void LvSelectByParam(HWND hWnd, UINT id, void *param)
5474 {
5475 	UINT index;
5476 	// Validate arguments
5477 	if (hWnd == NULL || param == NULL)
5478 	{
5479 		return;
5480 	}
5481 
5482 	index = LvSearchParam(hWnd, id, param);
5483 	if (index == INFINITE)
5484 	{
5485 		return;
5486 	}
5487 
5488 	LvSelect(hWnd, id, index);
5489 }
5490 
5491 // Select an item
LvSelect(HWND hWnd,UINT id,UINT index)5492 void LvSelect(HWND hWnd, UINT id, UINT index)
5493 {
5494 	// Validate arguments
5495 	if (hWnd == NULL)
5496 	{
5497 		return;
5498 	}
5499 
5500 	if (index == INFINITE)
5501 	{
5502 		UINT i, num;
5503 		// Deselect all
5504 		num = LvNum(hWnd, id);
5505 		for (i = 0;i < num;i++)
5506 		{
5507 			ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);
5508 		}
5509 	}
5510 	else
5511 	{
5512 		// Select
5513 		ListView_SetItemState(DlgItem(hWnd, id), index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
5514 		ListView_EnsureVisible(DlgItem(hWnd, id), index, true);
5515 	}
5516 }
5517 
5518 // Show the certificate information
PrintCertInfo(HWND hWnd,CERT_DLG * p)5519 void PrintCertInfo(HWND hWnd, CERT_DLG *p)
5520 {
5521 	X *x;
5522 	char *serial_tmp;
5523 	UINT serial_size;
5524 	wchar_t *wchar_tmp;
5525 	wchar_t tmp[1024 * 5];
5526 	UCHAR md5[MD5_SIZE];
5527 	UCHAR sha1[SHA1_SIZE];
5528 	char *s_tmp;
5529 	K *k;
5530 	// Validate arguments
5531 	if (p == NULL || hWnd == NULL)
5532 	{
5533 		return;
5534 	}
5535 
5536 	x = p->x;
5537 
5538 	// Serial number
5539 	if (x->serial != NULL)
5540 	{
5541 		serial_size = x->serial->size * 3 + 1;
5542 		serial_tmp = ZeroMalloc(serial_size);
5543 		BinToStrEx(serial_tmp, serial_size, x->serial->data, x->serial->size);
5544 		wchar_tmp = CopyStrToUni(serial_tmp);
5545 		Free(serial_tmp);
5546 	}
5547 	else
5548 	{
5549 		wchar_tmp = CopyUniStr(_UU("CERT_NO_SERIAL"));
5550 	}
5551 	LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SERIAL"), wchar_tmp);
5552 
5553 	// Issuer
5554 	GetAllNameFromName(tmp, sizeof(tmp), x->issuer_name);
5555 	LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_ISSUER"), tmp);
5556 
5557 	// Subject
5558 	GetAllNameFromName(tmp, sizeof(tmp), x->subject_name);
5559 	LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SUBJECT"), tmp);
5560 
5561 	// Not available before
5562 	GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notBefore), NULL);
5563 	LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_BEFORE"), tmp);
5564 
5565 	// Not available after
5566 	GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
5567 	LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_AFTER"), tmp);
5568 
5569 	// Number of bits
5570 	if (x->is_compatible_bit)
5571 	{
5572 		UniFormat(tmp, sizeof(tmp), _UU("CERT_BITS_FORMAT"), x->bits);
5573 		LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_BITS"), tmp);
5574 	}
5575 
5576 	// Public key
5577 	k = GetKFromX(x);
5578 	if (k != NULL)
5579 	{
5580 		BUF *b = KToBuf(k, false, NULL);
5581 		s_tmp = CopyBinToStrEx(b->Buf, b->Size);
5582 		StrToUni(tmp, sizeof(tmp), s_tmp);
5583 		Free(s_tmp);
5584 		LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_PUBLIC_KEY"), tmp);
5585 		FreeBuf(b);
5586 	}
5587 	FreeK(k);
5588 
5589 	GetXDigest(x, md5, false);
5590 	GetXDigest(x, sha1, true);
5591 
5592 	// Digest (MD5)
5593 	s_tmp = CopyBinToStrEx(md5, sizeof(md5));
5594 	StrToUni(tmp, sizeof(tmp), s_tmp);
5595 	Free(s_tmp);
5596 	LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_MD5"), tmp);
5597 
5598 	// Digest (SHA-1)
5599 	s_tmp = CopyBinToStrEx(sha1, sizeof(sha1));
5600 	StrToUni(tmp, sizeof(tmp), s_tmp);
5601 	Free(s_tmp);
5602 	LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_SHA1"), tmp);
5603 
5604 	Free(wchar_tmp);
5605 
5606 	LvSelect(hWnd, L_CERTINFO, 0);
5607 }
5608 
5609 // Update the display
CertDlgUpdate(HWND hWnd,CERT_DLG * p)5610 void CertDlgUpdate(HWND hWnd, CERT_DLG *p)
5611 {
5612 	// Validate arguments
5613 	if (hWnd == NULL || p == NULL)
5614 	{
5615 		return;
5616 	}
5617 
5618 	if (LvIsSelected(hWnd, L_CERTINFO) == false)
5619 	{
5620 		SetText(hWnd, E_DETAIL, L"");
5621 	}
5622 	else
5623 	{
5624 		UINT i = LvGetSelected(hWnd, L_CERTINFO);
5625 		wchar_t *tmp = LvGetStr(hWnd, L_CERTINFO, i, 1);
5626 		SetText(hWnd, E_DETAIL, tmp);
5627 		Free(tmp);
5628 	}
5629 }
5630 
5631 // Save the certificate
CertDlgSave(HWND hWnd,CERT_DLG * p)5632 void CertDlgSave(HWND hWnd, CERT_DLG *p)
5633 {
5634 	wchar_t *name;
5635 	X *x;
5636 	// Validate arguments
5637 	if (hWnd == NULL || p == NULL)
5638 	{
5639 		return;
5640 	}
5641 
5642 	// Save to a file
5643 	name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");
5644 	x = p->x;
5645 	if (name != NULL)
5646 	{
5647 		wchar_t str[MAX_SIZE];
5648 		UniStrCpy(str, sizeof(str), name);
5649 		if (XToFileW(x, str, true))
5650 		{
5651 			MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));
5652 		}
5653 		else
5654 		{
5655 			MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
5656 		}
5657 		Free(name);
5658 	}
5659 }
5660 
5661 // Certificate display dialog procedure
CertDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)5662 UINT CertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
5663 {
5664 	CERT_DLG *p = (CERT_DLG *)param;
5665 	X *x;
5666 	wchar_t tmp[MAX_SIZE];
5667 	NMHDR *n;
5668 	// Validate arguments
5669 	if (hWnd == NULL)
5670 	{
5671 		return 0;
5672 	}
5673 
5674 	switch (msg)
5675 	{
5676 	case WM_INITDIALOG:
5677 		SetIcon(hWnd, 0, ICO_CERT);
5678 		x = p->x;
5679 		GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);
5680 		SetText(hWnd, E_SUBJECT, tmp);
5681 		GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);
5682 		SetText(hWnd, E_ISSUER, tmp);
5683 		GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
5684 		SetText(hWnd, E_EXPIRES, tmp);
5685 		SetFont(hWnd, E_SUBJECT, Font(0, 1));
5686 		SetFont(hWnd, E_ISSUER, Font(0, 1));
5687 		SetFont(hWnd, E_EXPIRES, Font(0, 1));
5688 		SetIcon(hWnd, B_PARENT, ICO_CERT);
5689 		if (x->root_cert)
5690 		{
5691 			// Root certificate
5692 			Hide(hWnd, S_WARNING_ICON);
5693 			SetText(hWnd, S_PARENT, _UU("CERT_ROOT"));
5694 			Hide(hWnd, B_PARENT);
5695 			Hide(hWnd, S_PARENT_BUTTON_STR);
5696 		}
5697 		else if (p->issuer_x != NULL)
5698 		{
5699 			// Parent certificate exists
5700 			Hide(hWnd, S_WARNING_ICON);
5701 		}
5702 		else
5703 		{
5704 			// There is no parent certificate
5705 			Hide(hWnd, S_CERT_ICON);
5706 			Hide(hWnd, B_PARENT);
5707 			Hide(hWnd, S_PARENT_BUTTON_STR);
5708 			SetText(hWnd, S_PARENT, _UU("CERT_NOT_FOUND"));
5709 			if (p->ManagerMode)
5710 			{
5711 				Hide(hWnd, IDC_STATIC1);
5712 				Hide(hWnd, S_PARENT);
5713 				Hide(hWnd, S_WARNING_ICON);
5714 				Hide(hWnd, S_CERT_ICON);
5715 				Hide(hWnd, B_PARENT);
5716 				Hide(hWnd, S_PARENT_BUTTON_STR);
5717 			}
5718 		}
5719 
5720 
5721 		LvInit(hWnd, L_CERTINFO);
5722 		LvInsertColumn(hWnd, L_CERTINFO, 0, _UU("CERT_LV_C1"), 130);
5723 		LvInsertColumn(hWnd, L_CERTINFO, 1, _UU("CERT_LV_C2"), 250);
5724 
5725 		PrintCertInfo(hWnd, p);
5726 		Focus(hWnd, L_CERTINFO);
5727 
5728 		CertDlgUpdate(hWnd, p);
5729 
5730 		if (p->ManagerMode)
5731 		{
5732 			Show(hWnd, B_SAVE);
5733 		}
5734 		else
5735 		{
5736 			// Hide for security
5737 			Hide(hWnd, B_SAVE);
5738 		}
5739 
5740 		break;
5741 	case WM_COMMAND:
5742 		switch (wParam)
5743 		{
5744 		case IDOK:
5745 		case IDCANCEL:
5746 			Close(hWnd);
5747 			break;
5748 		case B_PARENT:
5749 			CertDlg(hWnd, p->issuer_x, NULL, p->ManagerMode);
5750 			break;
5751 		case B_SAVE:
5752 			// Save to the file
5753 			CertDlgSave(hWnd, p);
5754 			break;
5755 		}
5756 		break;
5757 	case WM_CLOSE:
5758 		EndDialog(hWnd, false);
5759 		break;
5760 	case WM_NOTIFY:
5761 		n = (NMHDR *)lParam;
5762 		switch (n->idFrom)
5763 		{
5764 		case L_CERTINFO:
5765 			switch (n->code)
5766 			{
5767 			case LVN_ITEMCHANGED:
5768 				CertDlgUpdate(hWnd, p);
5769 				break;
5770 			}
5771 			break;
5772 		}
5773 		break;
5774 	}
5775 
5776 	LvSortHander(hWnd, msg, wParam, lParam, L_CERTINFO);
5777 
5778 	return 0;
5779 }
5780 
5781 // Certificate display dialog
CertDlg(HWND hWnd,X * x,X * issuer_x,bool manager)5782 void CertDlg(HWND hWnd, X *x, X *issuer_x, bool manager)
5783 {
5784 	CERT_DLG p;
5785 	// Validate arguments
5786 	if (x == NULL)
5787 	{
5788 		return;
5789 	}
5790 
5791 	Zero(&p, sizeof(p));
5792 	p.x = x;
5793 	if (CompareX(x, issuer_x) == false)
5794 	{
5795 		p.issuer_x = issuer_x;
5796 	}
5797 	p.ManagerMode = manager;
5798 	Dialog(hWnd, D_CERT, CertDlgProc, &p);
5799 }
5800 
5801 // Status window dialog
StatusPrinterWindowDlg(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)5802 UINT StatusPrinterWindowDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
5803 {
5804 	STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;
5805 	PACK *pack;
5806 	// Validate arguments
5807 	if (hWnd == NULL)
5808 	{
5809 		return 0;
5810 	}
5811 
5812 	switch (msg)
5813 	{
5814 	case WM_INITDIALOG:
5815 		// Initialize
5816 		SetIcon(hWnd, 0, ICO_SERVER_ONLINE);
5817 		RemoveExStyle(hWnd, 0, WS_EX_APPWINDOW);
5818 		p->hWnd = hWnd;
5819 		NoticeThreadInit(p->Thread);
5820 		FormatText(hWnd, 0, p->AccountName);
5821 		break;
5822 
5823 	case WM_COMMAND:
5824 		switch (wParam)
5825 		{
5826 		case IDOK:
5827 		case IDCANCEL:
5828 			// Cancel button
5829 			Close(hWnd);
5830 			break;
5831 		}
5832 
5833 		break;
5834 
5835 	case WM_APP + 1:
5836 		// Set a string
5837 		SetText(hWnd, S_STATUS, (wchar_t *)lParam);
5838 		break;
5839 
5840 	case WM_APP + 2:
5841 		// Close this window
5842 		EndDialog(hWnd, false);
5843 		break;
5844 
5845 	case WM_CLOSE:
5846 		// End the session
5847 		pack = NewPack();
5848 		SendPack(p->Sock, pack);
5849 		EndDialog(hWnd, false);
5850 		break;
5851 	}
5852 
5853 	return 0;
5854 }
5855 
5856 // Status window control thread
StatusPrinterWindowThread(THREAD * thread,void * param)5857 void StatusPrinterWindowThread(THREAD *thread, void *param)
5858 {
5859 	STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;
5860 	// Validate arguments
5861 	if (thread == NULL || param == NULL)
5862 	{
5863 		return;
5864 	}
5865 
5866 	p->Thread = thread;
5867 	DialogEx2(NULL, D_STATUS, StatusPrinterWindowDlg, p, true, true);
5868 
5869 	Free(p);
5870 }
5871 
5872 // Show a message in the status window
StatusPrinterWindowPrint(STATUS_WINDOW * sw,wchar_t * str)5873 void StatusPrinterWindowPrint(STATUS_WINDOW *sw, wchar_t *str)
5874 {
5875 	// Validate arguments
5876 	if (sw == NULL)
5877 	{
5878 		return;
5879 	}
5880 
5881 	SendMessage(sw->hWnd, WM_APP + 1, 0, (LPARAM)str);
5882 }
5883 
5884 // End and release the status window
StatusPrinterWindowStop(STATUS_WINDOW * sw)5885 void StatusPrinterWindowStop(STATUS_WINDOW *sw)
5886 {
5887 	// Validate arguments
5888 	if (sw == NULL)
5889 	{
5890 		return;
5891 	}
5892 
5893 	// Send stop message
5894 	SendMessage(sw->hWnd, WM_APP + 2, 0, 0);
5895 
5896 	// Wait until the thread terminates
5897 	WaitThread(sw->Thread, INFINITE);
5898 
5899 	// Release the memory
5900 	ReleaseThread(sw->Thread);
5901 	Free(sw);
5902 }
5903 
5904 // Initialize the status window
StatusPrinterWindowStart(SOCK * s,wchar_t * account_name)5905 STATUS_WINDOW *StatusPrinterWindowStart(SOCK *s, wchar_t *account_name)
5906 {
5907 	STATUS_WINDOW_PARAM *p;
5908 	STATUS_WINDOW *sw;
5909 	THREAD *t;
5910 	// Validate arguments
5911 	if (s == NULL || account_name == NULL)
5912 	{
5913 		return NULL;
5914 	}
5915 
5916 	p = ZeroMalloc(sizeof(STATUS_WINDOW_PARAM));
5917 	p->Sock = s;
5918 	UniStrCpy(p->AccountName, sizeof(p->AccountName), account_name);
5919 
5920 	// Create a thread
5921 	t = NewThread(StatusPrinterWindowThread, p);
5922 	WaitThreadInit(t);
5923 
5924 	sw = ZeroMalloc(sizeof(STATUS_WINDOW));
5925 	sw->hWnd = p->hWnd;
5926 	sw->Thread = t;
5927 
5928 	return sw;
5929 }
5930 
5931 // Remove all
LbReset(HWND hWnd,UINT id)5932 void LbReset(HWND hWnd, UINT id)
5933 {
5934 	// Validate arguments
5935 	if (hWnd == NULL)
5936 	{
5937 		return;
5938 	}
5939 
5940 	SendMsg(hWnd, id, LB_RESETCONTENT, 0, 0);
5941 }
5942 
5943 // Password input dialog state change
PasswordDlgProcChange(HWND hWnd,UI_PASSWORD_DLG * p)5944 void PasswordDlgProcChange(HWND hWnd, UI_PASSWORD_DLG *p)
5945 {
5946 	bool b;
5947 	// Validate arguments
5948 	if (hWnd == NULL || p == NULL)
5949 	{
5950 		return;
5951 	}
5952 
5953 	b = true;
5954 	if (IsEmpty(hWnd, E_USERNAME))
5955 	{
5956 		b = false;
5957 	}
5958 
5959 	SetEnable(hWnd, IDOK, b);
5960 
5961 	p->StartTick = Tick64();
5962 	if (p->RetryIntervalSec)
5963 	{
5964 		KillTimer(hWnd, 1);
5965 		Hide(hWnd, P_PROGRESS);
5966 		Hide(hWnd, S_COUNTDOWN);
5967 	}
5968 }
5969 
5970 // Get the string
CbGetStr(HWND hWnd,UINT id)5971 wchar_t *CbGetStr(HWND hWnd, UINT id)
5972 {
5973 	// Validate arguments
5974 	if (hWnd == NULL)
5975 	{
5976 		return NULL;
5977 	}
5978 
5979 	return GetText(hWnd, id);
5980 }
5981 
5982 // String search
CbFindStr(HWND hWnd,UINT id,wchar_t * str)5983 UINT CbFindStr(HWND hWnd, UINT id, wchar_t *str)
5984 {
5985 	UINT ret;
5986 	// Validate arguments
5987 	if (hWnd == NULL || str == NULL)
5988 	{
5989 		return INFINITE;
5990 	}
5991 
5992 	ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);
5993 
5994 	return ret;
5995 }
CbFindStr9xA(HWND hWnd,UINT id,char * str)5996 UINT CbFindStr9xA(HWND hWnd, UINT id, char *str)
5997 {
5998 	UINT ret;
5999 	// Validate arguments
6000 	if (hWnd == NULL || str == NULL)
6001 	{
6002 		return INFINITE;
6003 	}
6004 
6005 	ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);
6006 
6007 	return ret;
6008 }
6009 
6010 // Get the number of items
CbNum(HWND hWnd,UINT id)6011 UINT CbNum(HWND hWnd, UINT id)
6012 {
6013 	// Validate arguments
6014 	if (hWnd == NULL)
6015 	{
6016 		return INFINITE;
6017 	}
6018 
6019 	return SendMsg(hWnd, id, CB_GETCOUNT, 0, 0);
6020 }
6021 
6022 // Add a string
CbAddStrA(HWND hWnd,UINT id,char * str,UINT data)6023 UINT CbAddStrA(HWND hWnd, UINT id, char *str, UINT data)
6024 {
6025 	wchar_t *tmp;
6026 	UINT ret;
6027 	// Validate arguments
6028 	if (hWnd == NULL || str == NULL)
6029 	{
6030 		return INFINITE;
6031 	}
6032 	tmp = CopyStrToUni(str);
6033 	ret = CbAddStr(hWnd, id, tmp, data);
6034 	Free(tmp);
6035 	return ret;
6036 }
CbAddStr(HWND hWnd,UINT id,wchar_t * str,UINT data)6037 UINT CbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data)
6038 {
6039 	UINT ret;
6040 	// Validate arguments
6041 	if (hWnd == NULL || str == NULL)
6042 	{
6043 		return INFINITE;
6044 	}
6045 
6046 	ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);
6047 	SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
6048 
6049 	if (CbNum(hWnd, id) == 1)
6050 	{
6051 		wchar_t tmp[MAX_SIZE];
6052 		GetTxt(hWnd, id, tmp, sizeof(tmp));
6053 		if (UniStrLen(tmp) == 0)
6054 		{
6055 			CbSelectIndex(hWnd, id, 0);
6056 		}
6057 	}
6058 
6059 	return ret;
6060 }
CbAddStr9xA(HWND hWnd,UINT id,char * str,UINT data)6061 UINT CbAddStr9xA(HWND hWnd, UINT id, char *str, UINT data)
6062 {
6063 	UINT ret;
6064 	// Validate arguments
6065 	if (hWnd == NULL || str == NULL)
6066 	{
6067 		return INFINITE;
6068 	}
6069 
6070 	ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);
6071 	SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
6072 
6073 	if (CbNum(hWnd, id) == 1)
6074 	{
6075 		wchar_t tmp[MAX_SIZE];
6076 		GetTxt(hWnd, id, tmp, sizeof(tmp));
6077 		if (UniStrLen(tmp) == 0)
6078 		{
6079 			CbSelectIndex(hWnd, id, 0);
6080 		}
6081 	}
6082 
6083 	return ret;
6084 }
6085 
6086 // Remove all
CbReset(HWND hWnd,UINT id)6087 void CbReset(HWND hWnd, UINT id)
6088 {
6089 	wchar_t *s;
6090 	// Validate arguments
6091 	if (hWnd == NULL)
6092 	{
6093 		return;
6094 	}
6095 
6096 	s = GetText(hWnd, id);
6097 
6098 	SendMsg(hWnd, id, CB_RESETCONTENT, 0, 0);
6099 
6100 	if (s != NULL)
6101 	{
6102 		SetText(hWnd, id, s);
6103 		Free(s);
6104 	}
6105 }
6106 
6107 // Select by specifying the index
CbSelectIndex(HWND hWnd,UINT id,UINT index)6108 void CbSelectIndex(HWND hWnd, UINT id, UINT index)
6109 {
6110 	// Validate arguments
6111 	if (hWnd == NULL)
6112 	{
6113 		return;
6114 	}
6115 
6116 	SendMsg(hWnd, id, CB_SETCURSEL, index, 0);
6117 }
6118 
6119 // Get the data
CbGetData(HWND hWnd,UINT id,UINT index)6120 UINT CbGetData(HWND hWnd, UINT id, UINT index)
6121 {
6122 	// Validate arguments
6123 	if (hWnd == NULL || index == INFINITE)
6124 	{
6125 		return INFINITE;
6126 	}
6127 
6128 	return SendMsg(hWnd, id, CB_GETITEMDATA, index, 0);
6129 }
6130 
6131 // Search for the data
CbFindData(HWND hWnd,UINT id,UINT data)6132 UINT CbFindData(HWND hWnd, UINT id, UINT data)
6133 {
6134 	UINT i, num;
6135 	// Validate arguments
6136 	if (hWnd == NULL)
6137 	{
6138 		return INFINITE;
6139 	}
6140 
6141 	num = CbNum(hWnd, id);
6142 	if (num == INFINITE)
6143 	{
6144 		return INFINITE;
6145 	}
6146 
6147 	for (i = 0;i < num;i++)
6148 	{
6149 		if (CbGetData(hWnd, id, i) == data)
6150 		{
6151 			return i;
6152 		}
6153 	}
6154 
6155 	return INFINITE;
6156 }
6157 
6158 // Set the height of the item
CbSetHeight(HWND hWnd,UINT id,UINT value)6159 void CbSetHeight(HWND hWnd, UINT id, UINT value)
6160 {
6161 	// Validate arguments
6162 	if (hWnd == NULL)
6163 	{
6164 		return;
6165 	}
6166 
6167 	SendMsg(hWnd, id, CB_SETITEMHEIGHT, 0, (UINT)(GetTextScalingFactor() * (double)value));
6168 }
6169 
6170 // Search by specifying the data
CbSelect(HWND hWnd,UINT id,int data)6171 void CbSelect(HWND hWnd, UINT id, int data)
6172 {
6173 	UINT index;
6174 	// Validate arguments
6175 	if (hWnd == NULL)
6176 	{
6177 		return;
6178 	}
6179 
6180 	if (data == INFINITE)
6181 	{
6182 		// Get the first item
6183 		CbSelectIndex(hWnd, id, 0);
6184 		return;
6185 	}
6186 
6187 	index = CbFindData(hWnd, id, data);
6188 	if (index == INFINITE)
6189 	{
6190 		// Can not be found
6191 		return;
6192 	}
6193 
6194 	// Select
6195 	CbSelectIndex(hWnd, id, index);
6196 }
6197 
6198 // Get the currently selected item
CbGetSelectIndex(HWND hWnd,UINT id)6199 UINT CbGetSelectIndex(HWND hWnd, UINT id)
6200 {
6201 	// Validate arguments
6202 	if (hWnd == NULL)
6203 	{
6204 		return INFINITE;
6205 	}
6206 
6207 	return SendMsg(hWnd, id, CB_GETCURSEL, 0, 0);
6208 }
6209 
6210 // Get the value that is currently selected
CbGetSelect(HWND hWnd,UINT id)6211 UINT CbGetSelect(HWND hWnd, UINT id)
6212 {
6213 	UINT index;
6214 	// Validate arguments
6215 	if (hWnd == NULL)
6216 	{
6217 		return INFINITE;
6218 	}
6219 
6220 	index = CbGetSelectIndex(hWnd, id);
6221 	if (index == INFINITE)
6222 	{
6223 		return INFINITE;
6224 	}
6225 
6226 	return CbGetData(hWnd, id, index);
6227 }
6228 
6229 // OK button is pressed
PasswordDlgOnOk(HWND hWnd,UI_PASSWORD_DLG * p)6230 void PasswordDlgOnOk(HWND hWnd, UI_PASSWORD_DLG *p)
6231 {
6232 	// Validate arguments
6233 	if (hWnd == NULL || p == NULL)
6234 	{
6235 		return;
6236 	}
6237 
6238 	GetTxtA(hWnd, E_USERNAME, p->Username, sizeof(p->Username));
6239 	GetTxtA(hWnd, E_PASSWORD, p->Password, sizeof(p->Password));
6240 	p->Type = CbGetSelect(hWnd, C_TYPE);
6241 
6242 	if (p->ShowNoSavePassword)
6243 	{
6244 		p->NoSavePassword = IsChecked(hWnd, R_NO_SAVE_PASSWORD);
6245 	}
6246 
6247 	EndDialog(hWnd, true);
6248 }
6249 
6250 // Password input dialog procedure
PasswordDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)6251 UINT PasswordDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
6252 {
6253 	UI_PASSWORD_DLG *p = (UI_PASSWORD_DLG *)param;
6254 	// Validate arguments
6255 	if (hWnd == NULL)
6256 	{
6257 		return 0;
6258 	}
6259 
6260 	switch (msg)
6261 	{
6262 	case WM_INITDIALOG:
6263 		SetIcon(hWnd, 0, ICO_KEY);
6264 		CbSetHeight(hWnd, C_TYPE, 18);
6265 		if (p->ServerName != NULL)
6266 		{
6267 			FormatText(hWnd, 0, p->ServerName);
6268 		}
6269 		else
6270 		{
6271 			SetText(hWnd, 0, _UU("PW_LOGIN_DLG_TITLE"));
6272 		}
6273 
6274 		if (p->ProxyServer == false)
6275 		{
6276 			FormatText(hWnd, S_TITLE, p->ServerName == NULL ? "" : p->ServerName);
6277 		}
6278 		else
6279 		{
6280 			wchar_t tmp[MAX_SIZE];
6281 			UniFormat(tmp, sizeof(tmp), _UU("PW_MSG_PROXY"), p->ServerName == NULL ? "" : p->ServerName);
6282 			SetText(hWnd, S_TITLE, tmp);
6283 		}
6284 
6285 		// Enumerate the connection methods
6286 		SendMsg(hWnd, C_TYPE, CBEM_SETUNICODEFORMAT, true, 0);
6287 
6288 		if (StrCmpi(p->Username, WINUI_PASSWORD_NULL_USERNAME) != 0)
6289 		{
6290 			SetTextA(hWnd, E_USERNAME, p->Username);
6291 			SetTextA(hWnd, E_PASSWORD, p->Password);
6292 		}
6293 		else
6294 		{
6295 			p->RetryIntervalSec = 0;
6296 			SetTextA(hWnd, E_USERNAME, "");
6297 			SetTextA(hWnd, E_PASSWORD, "");
6298 		}
6299 
6300 		if (p->AdminMode == false)
6301 		{
6302 			if (p->ProxyServer == false)
6303 			{
6304 				CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);
6305 				CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);
6306 			}
6307 			else
6308 			{
6309 				CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_PROXY"), 0);
6310 				Disable(hWnd, C_TYPE);
6311 			}
6312 
6313 			CbSelect(hWnd, C_TYPE, p->Type);
6314 		}
6315 		else
6316 		{
6317 			CbAddStr(hWnd, C_TYPE, _UU("SM_PASSWORD_TYPE_STR"), 0);
6318 			Disable(hWnd, C_TYPE);
6319 			SetTextA(hWnd, E_USERNAME, "Administrator");
6320 			Disable(hWnd, E_USERNAME);
6321 		}
6322 
6323 		if (IsEmpty(hWnd, E_USERNAME))
6324 		{
6325 			FocusEx(hWnd, E_USERNAME);
6326 		}
6327 		else
6328 		{
6329 			FocusEx(hWnd, E_PASSWORD);
6330 		}
6331 		LimitText(hWnd, E_USERNAME, MAX_USERNAME_LEN);
6332 		LimitText(hWnd, E_PASSWORD, MAX_PASSWORD_LEN);
6333 
6334 		PasswordDlgProcChange(hWnd, p);
6335 
6336 		if (p->RetryIntervalSec != 0)
6337 		{
6338 			SetTimer(hWnd, 1, 50, NULL);
6339 			FormatText(hWnd, S_COUNTDOWN, p->RetryIntervalSec);
6340 			Show(hWnd, S_COUNTDOWN);
6341 			Show(hWnd, P_PROGRESS);
6342 			SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec * 1000);
6343 		}
6344 		else
6345 		{
6346 			Hide(hWnd, S_COUNTDOWN);
6347 			Hide(hWnd, P_PROGRESS);
6348 		}
6349 
6350 		if (p->ShowNoSavePassword)
6351 		{
6352 			Show(hWnd, R_NO_SAVE_PASSWORD);
6353 			Check(hWnd, R_NO_SAVE_PASSWORD, p->NoSavePassword);
6354 		}
6355 		else
6356 		{
6357 			Hide(hWnd, R_NO_SAVE_PASSWORD);
6358 		}
6359 
6360 		p->StartTick = Tick64();
6361 
6362 		if (p->CancelEvent != NULL)
6363 		{
6364 			SetTimer(hWnd, 2, 50, NULL);
6365 		}
6366 
6367 		break;
6368 
6369 	case WM_CLOSE:
6370 		EndDialog(hWnd, false);
6371 		break;
6372 
6373 	case WM_TIMER:
6374 		switch (wParam)
6375 		{
6376 		case 1:
6377 			if (p->RetryIntervalSec != 0)
6378 			{
6379 				wchar_t tmp[MAX_SIZE];
6380 				UINT64 end, now, start;
6381 				start = p->StartTick;
6382 				end = p->StartTick + (UINT64)(p->RetryIntervalSec * 1000);
6383 				now = Tick64();
6384 
6385 				if (now <= end)
6386 				{
6387 					UniFormat(tmp, sizeof(tmp), _UU("PW_RETRYCOUNT"), (UINT)((end - now) / 1000));
6388 					SetText(hWnd, S_COUNTDOWN, tmp);
6389 					SetPos(hWnd, P_PROGRESS, (UINT)(now - start));
6390 				}
6391 				else
6392 				{
6393 					EndDialog(hWnd, true);
6394 				}
6395 			}
6396 			break;
6397 
6398 		case 2:
6399 			if (p->CancelEvent != NULL)
6400 			{
6401 				// Wait for the end event
6402 				HANDLE hEvent = (HANDLE)p->CancelEvent->pData;
6403 				UINT ret = WaitForSingleObject(hEvent, 0);
6404 				if (ret != WAIT_TIMEOUT)
6405 				{
6406 					// Forced termination event is set
6407 					Close(hWnd);
6408 				}
6409 			}
6410 			break;
6411 		}
6412 		break;
6413 
6414 	case WM_COMMAND:
6415 		switch (wParam)
6416 		{
6417 		case IDOK:
6418 			PasswordDlgOnOk(hWnd, p);
6419 			break;
6420 		case IDCANCEL:
6421 			Close(hWnd);
6422 			break;
6423 		}
6424 		switch (HIWORD(wParam))
6425 		{
6426 		case EN_CHANGE:
6427 			switch (LOWORD(wParam))
6428 			{
6429 			case E_USERNAME:
6430 			case E_PASSWORD:
6431 				PasswordDlgProcChange(hWnd, p);
6432 				break;
6433 			}
6434 			break;
6435 		case CBN_SELCHANGE:
6436 			switch (LOWORD(wParam))
6437 			{
6438 			case C_TYPE:
6439 				PasswordDlgProcChange(hWnd, p);
6440 				if (IsEmpty(hWnd, E_USERNAME))
6441 				{
6442 					FocusEx(hWnd, E_USERNAME);
6443 				}
6444 				else
6445 				{
6446 					FocusEx(hWnd, E_PASSWORD);
6447 				}
6448 				break;
6449 			}
6450 			break;
6451 		}
6452 		break;
6453 	}
6454 
6455 	return 0;
6456 }
6457 
6458 // Set the position of the progress bar
SetPos(HWND hWnd,UINT id,UINT pos)6459 void SetPos(HWND hWnd, UINT id, UINT pos)
6460 {
6461 	// Validate arguments
6462 	if (hWnd == NULL)
6463 	{
6464 		return;
6465 	}
6466 
6467 	SendMsg(hWnd, id, PBM_SETPOS, pos, 0);
6468 }
6469 
6470 // Set the range of the progress bar
SetRange(HWND hWnd,UINT id,UINT start,UINT end)6471 void SetRange(HWND hWnd, UINT id, UINT start, UINT end)
6472 {
6473 	// Validate arguments
6474 	if (hWnd == NULL)
6475 	{
6476 		return;
6477 	}
6478 
6479 	SendMsg(hWnd, id, PBM_SETRANGE32, start, end);
6480 }
6481 
6482 // Password input dialog
PasswordDlg(HWND hWnd,UI_PASSWORD_DLG * p)6483 bool PasswordDlg(HWND hWnd, UI_PASSWORD_DLG *p)
6484 {
6485 	// Validate arguments
6486 	if (p == NULL)
6487 	{
6488 		return false;
6489 	}
6490 
6491 	p->StartTick = Tick64();
6492 
6493 	return Dialog(hWnd, D_PASSWORD, PasswordDlgProc, p);
6494 }
6495 
6496 // Passphrase input dialog
PassphraseDlg(HWND hWnd,char * pass,UINT pass_size,BUF * buf,bool p12)6497 bool PassphraseDlg(HWND hWnd, char *pass, UINT pass_size, BUF *buf, bool p12)
6498 {
6499 	PASSPHRASE_DLG p;
6500 	// Validate arguments
6501 	if (pass == NULL || buf == NULL)
6502 	{
6503 		return false;
6504 	}
6505 
6506 	Zero(&p, sizeof(PASSPHRASE_DLG));
6507 
6508 	p.buf = buf;
6509 	p.p12 = p12;
6510 
6511 	// Examine whether it is encrypted first
6512 	if (p12 == false)
6513 	{
6514 		// Secret key
6515 		if (IsEncryptedK(buf, true) == false)
6516 		{
6517 			// Unencrypted
6518 			StrCpy(pass, pass_size, "");
6519 			return true;
6520 		}
6521 	}
6522 	else
6523 	{
6524 		// PKCS#12
6525 		P12 *p12 = BufToP12(buf);
6526 		if (p12 == NULL)
6527 		{
6528 			// It is in unknown format, but not encrypted
6529 			StrCpy(pass, pass_size, "");
6530 			return true;
6531 		}
6532 
6533 		if (IsEncryptedP12(p12) == false)
6534 		{
6535 			// Unencrypted
6536 			StrCpy(pass, pass_size, "");
6537 			FreeP12(p12);
6538 			return true;
6539 		}
6540 		FreeP12(p12);
6541 	}
6542 
6543 	// Show the dialog
6544 	if (Dialog(hWnd, D_PASSPHRASE, PassphraseDlgProc, &p) == false)
6545 	{
6546 		// Cancel
6547 		return false;
6548 	}
6549 
6550 	StrCpy(pass, pass_size, p.pass);
6551 
6552 	return true;
6553 }
6554 
6555 // WM_COMMAND handler
PassphraseDlgProcCommand(HWND hWnd,PASSPHRASE_DLG * p)6556 void PassphraseDlgProcCommand(HWND hWnd, PASSPHRASE_DLG *p)
6557 {
6558 	char *pass;
6559 	bool ok;
6560 	// Validate arguments
6561 	if (hWnd == NULL || p == NULL)
6562 	{
6563 		return;
6564 	}
6565 
6566 	pass = GetTextA(hWnd, E_PASSPHRASE);
6567 	if (pass == NULL)
6568 	{
6569 		return;
6570 	}
6571 
6572 	ok = false;
6573 
6574 	if (p->p12 == false)
6575 	{
6576 		K *k;
6577 		k = BufToK(p->buf, true, true, pass);
6578 		if (k != NULL)
6579 		{
6580 			ok = true;
6581 			FreeK(k);
6582 		}
6583 	}
6584 	else
6585 	{
6586 		X *x;
6587 		K *k;
6588 		P12 *p12;
6589 		p12 = BufToP12(p->buf);
6590 		if (p12 != NULL)
6591 		{
6592 			if (ParseP12(p12, &x, &k, pass))
6593 			{
6594 				FreeX(x);
6595 				FreeK(k);
6596 				ok = true;
6597 			}
6598 			FreeP12(p12);
6599 		}
6600 	}
6601 
6602 	Free(pass);
6603 
6604 	SetEnable(hWnd, IDOK, ok);
6605 }
6606 
6607 // Passphrase input dialog procedure
PassphraseDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)6608 UINT PassphraseDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
6609 {
6610 	PASSPHRASE_DLG *p = (PASSPHRASE_DLG *)param;
6611 	// Validate arguments
6612 	if (hWnd == NULL)
6613 	{
6614 		return 0;
6615 	}
6616 
6617 	switch (msg)
6618 	{
6619 	case WM_INITDIALOG:
6620 		PassphraseDlgProcCommand(hWnd, p);
6621 		break;
6622 
6623 	case WM_COMMAND:
6624 		switch (wParam)
6625 		{
6626 		case IDOK:
6627 			GetTxtA(hWnd, E_PASSPHRASE, p->pass, sizeof(p->pass));
6628 			EndDialog(hWnd, true);
6629 			break;
6630 
6631 		case IDCANCEL:
6632 			Close(hWnd);
6633 			break;
6634 		}
6635 
6636 		switch (LOWORD(wParam))
6637 		{
6638 		case E_PASSPHRASE:
6639 			PassphraseDlgProcCommand(hWnd, p);
6640 			break;
6641 		}
6642 		break;
6643 
6644 	case WM_CLOSE:
6645 		EndDialog(hWnd, false);
6646 		break;
6647 	}
6648 
6649 	return 0;
6650 }
6651 
6652 // [Save File] dialog
SaveDlg(HWND hWnd,wchar_t * filter,wchar_t * title,wchar_t * default_name,wchar_t * default_ext)6653 wchar_t *SaveDlg(HWND hWnd, wchar_t *filter, wchar_t *title, wchar_t *default_name, wchar_t *default_ext)
6654 {
6655 	wchar_t *filter_str;
6656 	wchar_t tmp[MAX_SIZE];
6657 	OPENFILENAMEW o;
6658 
6659 	// Validate arguments
6660 	if (filter == NULL)
6661 	{
6662 		filter = _UU("DLG_ALL_FILES");
6663 	}
6664 
6665 	filter_str = MakeFilter(filter);
6666 
6667 	Zero(&o, sizeof(o));
6668 	Zero(tmp, sizeof(tmp));
6669 
6670 	if (default_name != NULL)
6671 	{
6672 		UniStrCpy(tmp, sizeof(tmp), default_name);
6673 	}
6674 
6675 	o.lStructSize = sizeof(o);
6676 	o.hwndOwner = hWnd;
6677 	o.hInstance = GetModuleHandle(NULL);
6678 	o.lpstrFile = tmp;
6679 	o.lpstrTitle = title;
6680 	o.lpstrFilter = filter_str;
6681 	o.nMaxFile = sizeof(tmp);
6682 	o.Flags = OFN_OVERWRITEPROMPT;
6683 	o.lpstrDefExt = default_ext;
6684 
6685 	if (GetSaveFileNameW(&o) == false)
6686 	{
6687 		Free(filter_str);
6688 		return NULL;
6689 	}
6690 
6691 	Free(filter_str);
6692 
6693 	return UniCopyStr(tmp);
6694 }
SaveDlgA(HWND hWnd,char * filter,char * title,char * default_name,char * default_ext)6695 char *SaveDlgA(HWND hWnd, char *filter, char *title, char *default_name, char *default_ext)
6696 {
6697 	char *filter_str;
6698 	char tmp[MAX_SIZE];
6699 	OPENFILENAME o;
6700 	// Validate arguments
6701 	if (filter == NULL)
6702 	{
6703 		filter = _SS("DLG_ALL_FILES");
6704 	}
6705 
6706 	filter_str = MakeFilterA(filter);
6707 
6708 	Zero(&o, sizeof(o));
6709 	Zero(tmp, sizeof(tmp));
6710 
6711 	if (default_name != NULL)
6712 	{
6713 		StrCpy(tmp, sizeof(tmp), default_name);
6714 	}
6715 
6716 	o.lStructSize = sizeof(o);
6717 	o.hwndOwner = hWnd;
6718 	o.hInstance = GetModuleHandle(NULL);
6719 	o.lpstrFile = tmp;
6720 	o.lpstrTitle = title;
6721 	o.lpstrFilter = filter_str;
6722 	o.nMaxFile = sizeof(tmp);
6723 	o.Flags = OFN_OVERWRITEPROMPT;
6724 	o.lpstrDefExt = default_ext;
6725 
6726 	if (GetSaveFileName(&o) == false)
6727 	{
6728 		Free(filter_str);
6729 		return NULL;
6730 	}
6731 
6732 	Free(filter_str);
6733 
6734 	return CopyStr(tmp);
6735 }
6736 
6737 // [Open File] dialog
OpenDlg(HWND hWnd,wchar_t * filter,wchar_t * title)6738 wchar_t *OpenDlg(HWND hWnd, wchar_t *filter, wchar_t *title)
6739 {
6740 	wchar_t *filter_str;
6741 	wchar_t tmp[MAX_SIZE];
6742 	OPENFILENAMEW o;
6743 
6744 	// Validate arguments
6745 	if (filter == NULL)
6746 	{
6747 		filter = _UU("DLG_ALL_FILES");
6748 	}
6749 
6750 	filter_str = MakeFilter(filter);
6751 
6752 	Zero(&o, sizeof(OPENFILENAMEW));
6753 	Zero(tmp, sizeof(tmp));
6754 
6755 	o.lStructSize = sizeof(o);
6756 	o.hwndOwner = hWnd;
6757 	o.hInstance = GetModuleHandle(NULL);
6758 	o.lpstrFilter = filter_str;
6759 	o.lpstrFile = tmp;
6760 	o.nMaxFile = sizeof(tmp);
6761 	o.lpstrTitle = title;
6762 	o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
6763 
6764 	if (GetOpenFileNameW(&o) == false)
6765 	{
6766 		Free(filter_str);
6767 		return NULL;
6768 	}
6769 
6770 	Free(filter_str);
6771 
6772 	return UniCopyStr(tmp);
6773 }
OpenDlgA(HWND hWnd,char * filter,char * title)6774 char *OpenDlgA(HWND hWnd, char *filter, char *title)
6775 {
6776 	char *filter_str;
6777 	char tmp[MAX_SIZE];
6778 	OPENFILENAME o;
6779 	// Validate arguments
6780 	if (filter == NULL)
6781 	{
6782 		filter = _SS("DLG_ALL_FILES");
6783 	}
6784 
6785 	filter_str = MakeFilterA(filter);
6786 
6787 	Zero(&o, sizeof(OPENFILENAME));
6788 	Zero(tmp, sizeof(tmp));
6789 
6790 	o.lStructSize = sizeof(o);
6791 	o.hwndOwner = hWnd;
6792 	o.hInstance = GetModuleHandle(NULL);
6793 	o.lpstrFilter = filter_str;
6794 	o.lpstrFile = tmp;
6795 	o.nMaxFile = sizeof(tmp);
6796 	o.lpstrTitle = title;
6797 	o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
6798 
6799 	if (GetOpenFileName(&o) == false)
6800 	{
6801 		Free(filter_str);
6802 		return NULL;
6803 	}
6804 
6805 	Free(filter_str);
6806 
6807 	return CopyStr(tmp);
6808 }
6809 
6810 // Generate the filter string
MakeFilter(wchar_t * str)6811 wchar_t *MakeFilter(wchar_t *str)
6812 {
6813 	UINT i;
6814 	wchar_t *ret;
6815 	// Validate arguments
6816 	if (str == NULL)
6817 	{
6818 		return NULL;
6819 	}
6820 
6821 	ret = ZeroMalloc(UniStrSize(str) + 32);
6822 
6823 	for (i = 0;i < UniStrLen(str);i++)
6824 	{
6825 		if (str[i] == L'|')
6826 		{
6827 			ret[i] = L'\0';
6828 		}
6829 		else
6830 		{
6831 			ret[i] = str[i];
6832 		}
6833 	}
6834 
6835 	return ret;
6836 }
MakeFilterA(char * str)6837 char *MakeFilterA(char *str)
6838 {
6839 	UINT i;
6840 	char *ret;
6841 	// Validate arguments
6842 	if (str == NULL)
6843 	{
6844 		return NULL;
6845 	}
6846 
6847 	ret = ZeroMalloc(StrSize(str) + 32);
6848 
6849 	for (i = 0;i < StrLen(str);i++)
6850 	{
6851 		if (str[i] == '|')
6852 		{
6853 			ret[i] = '\0';
6854 		}
6855 		else
6856 		{
6857 			ret[i] = str[i];
6858 		}
6859 	}
6860 
6861 	return ret;
6862 }
6863 
6864 // Execution of batch
ExecuteSecureDeviceBatch(HWND hWnd,SECURE * sec,SECURE_DEVICE_THREAD * p,SECURE_DEVICE * dev,WINUI_SECURE_BATCH * batch)6865 bool ExecuteSecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev, WINUI_SECURE_BATCH *batch)
6866 {
6867 	LIST *o;
6868 	void *buf;
6869 	UINT size = 10 * 1024;		// Maximum size of the data
6870 	UINT type = INFINITE;
6871 	// Validate arguments
6872 	if (hWnd == NULL || p == NULL || dev == NULL || batch == NULL || sec == NULL)
6873 	{
6874 		return false;
6875 	}
6876 
6877 	switch (batch->Type)
6878 	{
6879 	case WINUI_SECURE_DELETE_CERT:
6880 		type = SEC_X;
6881 		goto DELETE_OBJECT;
6882 
6883 	case WINUI_SECURE_DELETE_KEY:
6884 		type = SEC_K;
6885 		goto DELETE_OBJECT;
6886 
6887 	case WINUI_SECURE_DELETE_DATA:
6888 		type = SEC_DATA;
6889 		goto DELETE_OBJECT;
6890 
6891 	case WINUI_SECURE_DELETE_OBJECT:
6892 		// Delete the object
6893 DELETE_OBJECT:
6894 		SetText(hWnd, S_STATUS, _UU("SEC_DELETE"));
6895 		if (DeleteSecObjectByName(sec, batch->Name, type) == false)
6896 		{
6897 			p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_DELETE"));
6898 			return false;
6899 		}
6900 		break;
6901 
6902 	case WINUI_SECURE_ENUM_OBJECTS:
6903 		// Enumerate objects
6904 		SetText(hWnd, S_STATUS, _UU("SEC_ENUM"));
6905 		o = EnumSecObject(sec);
6906 		if (o == NULL)
6907 		{
6908 			p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_ENUM"));
6909 			return false;
6910 		}
6911 
6912 		batch->EnumList = o;
6913 		break;
6914 
6915 	case WINUI_SECURE_WRITE_DATA:
6916 		// Write the data
6917 		SetText(hWnd, S_STATUS, _UU("SEC_WRITE_DATA"));
6918 		if (WriteSecData(sec, batch->Private, batch->Name, batch->InputData->Buf, batch->InputData->Size) == false)
6919 		{
6920 			p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
6921 				_UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
6922 			return false;
6923 		}
6924 		break;
6925 
6926 	case WINUI_SECURE_READ_DATA:
6927 		// Read the data
6928 		SetText(hWnd, S_STATUS, _UU("SEC_READ_DATA"));
6929 		buf = MallocEx(size, true);
6930 		size = ReadSecData(sec, batch->Name, buf, size);
6931 		if (size == 0)
6932 		{
6933 			Free(buf);
6934 			p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
6935 				_UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));
6936 			return false;
6937 		}
6938 		batch->OutputData = NewBuf();
6939 		WriteBuf(batch->OutputData, buf, size);
6940 		SeekBuf(batch->OutputData, 0, 0);
6941 		Free(buf);
6942 		break;
6943 
6944 	case WINUI_SECURE_WRITE_CERT:
6945 		// Write the certificate
6946 		SetText(hWnd, S_STATUS, _UU("SEC_WRITE_CERT"));
6947 		if (WriteSecCert(sec, batch->Private, batch->Name, batch->InputX) == false)
6948 		{
6949 			p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
6950 				_UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
6951 			return false;
6952 		}
6953 		break;
6954 
6955 	case WINUI_SECURE_READ_CERT:
6956 		// Read the certificate
6957 		SetText(hWnd, S_STATUS, _UU("SEC_READ_CERT"));
6958 		batch->OutputX = ReadSecCert(sec, batch->Name);
6959 		if (batch->OutputX == NULL)
6960 		{
6961 			p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
6962 				_UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));
6963 			return false;
6964 		}
6965 		break;
6966 
6967 	case WINUI_SECURE_WRITE_KEY:
6968 		// Write the secret key
6969 		SetText(hWnd, S_STATUS, _UU("SEC_WRITE_KEY"));
6970 		if (WriteSecKey(sec, batch->Private, batch->Name, batch->InputK) == false)
6971 		{
6972 			p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
6973 				_UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
6974 			return false;
6975 		}
6976 		break;
6977 
6978 	case WINUI_SECURE_SIGN_WITH_KEY:
6979 		// Signature
6980 		SetText(hWnd, S_STATUS, _UU("SEC_SIGN"));
6981 		if (SignSec(sec, batch->Name, batch->OutputSign, batch->InputData->Buf, batch->InputData->Size) == false)
6982 		{
6983 			p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
6984 				_UU("SEC_ERROR_SIGN_1") : _UU("SEC_ERROR_SIGN_2"));
6985 			return false;
6986 		}
6987 		break;
6988 	}
6989 
6990 	return true;
6991 }
6992 
6993 // Run the secure device operations as a batch job
SecureDeviceBatch(HWND hWnd,SECURE * sec,SECURE_DEVICE_THREAD * p,SECURE_DEVICE * dev)6994 void SecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev)
6995 {
6996 	UINT i;
6997 	// Validate arguments
6998 	if (hWnd == NULL || p == NULL || dev == NULL || sec == NULL)
6999 	{
7000 		return;
7001 	}
7002 
7003 	// Sequential processing
7004 	for (i = 0;i < p->w->num_batch;i++)
7005 	{
7006 		WINUI_SECURE_BATCH *batch = &p->w->batch[i];
7007 
7008 		if (ExecuteSecureDeviceBatch(hWnd, sec, p, dev, batch) == false)
7009 		{
7010 			// If fail even one, abort immediately
7011 			return;
7012 		}
7013 	}
7014 
7015 	// All batch job succeeded
7016 	p->Succeed = true;
7017 }
7018 
7019 // Thread to perform a secure device operation
SecureDeviceThread(THREAD * t,void * param)7020 void SecureDeviceThread(THREAD *t, void *param)
7021 {
7022 	SECURE *sec;
7023 	SECURE_DEVICE_THREAD *p = (SECURE_DEVICE_THREAD *)param;
7024 	SECURE_DEVICE *dev;
7025 	HWND hWnd;
7026 	// Validate arguments
7027 	if (t == NULL || param == NULL)
7028 	{
7029 		return;
7030 	}
7031 
7032 	p->Succeed = false;
7033 	p->ErrorMessage = NULL;
7034 
7035 	hWnd = p->hWnd;
7036 
7037 	// Open the device
7038 	dev = GetSecureDevice(p->w->device_id);
7039 	SetText(hWnd, S_STATUS, _UU("SEC_OPENING"));
7040 	sec = OpenSec(p->w->device_id);
7041 	if (sec == NULL)
7042 	{
7043 		// Device open failure
7044 		if (p->w->device_id != 9)
7045 		{
7046 			p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICE"), dev->DeviceName);
7047 		}
7048 		else
7049 		{
7050 			p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICEEX"), dev->DeviceName);
7051 		}
7052 	}
7053 	else
7054 	{
7055 		// Open the session
7056 		SetText(hWnd, S_STATUS, _UU("SEC_OPEN_SESSION"));
7057 		if (OpenSecSession(sec, 0) == false)
7058 		{
7059 			// Session initialization failure
7060 			p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_SESSION"), dev->DeviceName);
7061 		}
7062 		else
7063 		{
7064 			// Login
7065 			SetText(hWnd, S_STATUS, _UU("SEC_LOGIN"));
7066 			if (LoginSec(sec, p->pin) == false)
7067 			{
7068 				// Login failure
7069 				p->ErrorMessage =UniCopyStr(_UU("SEC_ERROR_LOGIN"));
7070 			}
7071 			else
7072 			{
7073 				// Batch processing main
7074 				SetText(hWnd, S_STATUS, _UU("SEC_INIT_BATCH"));
7075 				SecureDeviceBatch(hWnd, sec, p, dev);
7076 
7077 				// Logout
7078 				SetText(hWnd, S_STATUS, _UU("SEC_LOGOUT"));
7079 				LogoutSec(sec);
7080 			}
7081 
7082 			// Close the session
7083 			SetText(hWnd, S_STATUS, _UU("SEC_CLOSE_SESSION"));
7084 			CloseSecSession(sec);
7085 		}
7086 
7087 		// Close the device
7088 		SetText(hWnd, S_STATUS, _UU("SEC_CLOSING"));
7089 		CloseSec(sec);
7090 	}
7091 
7092 	if (p->Succeed)
7093 	{
7094 		// If successful, show the message for 150ms (service)
7095 		SetText(hWnd, S_STATUS, _UU("SEC_FINISHED"));
7096 		SleepThread(150);
7097 	}
7098 
7099 	SendMessage(p->hWnd, WM_APP + 1, 0, 0);
7100 }
7101 
7102 // Start a secure device operation
StartSecureDevice(HWND hWnd,SECURE_DEVICE_WINDOW * w)7103 void StartSecureDevice(HWND hWnd, SECURE_DEVICE_WINDOW *w)
7104 {
7105 	SECURE_DEVICE_THREAD *p;
7106 	// Validate arguments
7107 	if (hWnd == NULL || w == NULL)
7108 	{
7109 		return;
7110 	}
7111 
7112 	// Disable the control
7113 	EnableSecureDeviceWindowControls(hWnd, false);
7114 
7115 	// Start the thread
7116 	p = ZeroMalloc(sizeof(SECURE_DEVICE_THREAD));
7117 	p->w = w;
7118 	p->hWnd = hWnd;
7119 	w->p = p;
7120 	p->pin = GetTextA(hWnd, E_PIN);
7121 	ReleaseThread(NewThread(SecureDeviceThread, p));
7122 }
7123 
7124 // Enable or disable the control of the secure device operation window
EnableSecureDeviceWindowControls(HWND hWnd,bool enable)7125 void EnableSecureDeviceWindowControls(HWND hWnd, bool enable)
7126 {
7127 	// Validate arguments
7128 	if (hWnd == NULL)
7129 	{
7130 		return;
7131 	}
7132 
7133 	if (enable)
7134 	{
7135 		Show(hWnd, S_PIN_CODE);
7136 		Show(hWnd, E_PIN);
7137 		Show(hWnd, S_WARNING);
7138 	}
7139 	else
7140 	{
7141 		Hide(hWnd, S_PIN_CODE);
7142 		Hide(hWnd, E_PIN);
7143 		Hide(hWnd, S_WARNING);
7144 	}
7145 
7146 	SetEnable(hWnd, IDOK, enable);
7147 	SetEnable(hWnd, IDCANCEL, enable);
7148 	SetEnable(hWnd, S_TITLE, enable);
7149 	SetEnable(hWnd, S_DEVICE_INFO, enable);
7150 	SetEnable(hWnd, S_INSERT_SECURE, enable);
7151 
7152 	if (enable == false)
7153 	{
7154 		DisableClose(hWnd);
7155 		SetText(hWnd, S_STATUS, L"");
7156 		Show(hWnd, S_STATUS);
7157 		PlayAvi(hWnd, A_PROGRESS, true);
7158 	}
7159 	else
7160 	{
7161 		EnableClose(hWnd);
7162 		SetText(hWnd, S_STATUS, L"");
7163 		Hide(hWnd, S_STATUS);
7164 		StopAvi(hWnd, A_PROGRESS);
7165 	}
7166 }
7167 
7168 // Secure device operation window procedure
SecureDeviceWindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,void * param)7169 UINT SecureDeviceWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
7170 {
7171 	SECURE_DEVICE_WINDOW *w = (SECURE_DEVICE_WINDOW *)param;
7172 	SECURE_DEVICE *dev = GetSecureDevice(w->device_id);
7173 
7174 	switch (msg)
7175 	{
7176 	case WM_INITDIALOG:
7177 		if (dev == NULL)
7178 		{
7179 			MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_ERROR_INVALID_ID"), w->device_id);
7180 			EndDialog(hWnd, 0);
7181 			break;
7182 		}
7183 
7184 		if (IsJPKI(dev->Id))
7185 		{
7186 			// Juki card
7187 			Hide(hWnd, S_IMAGE);
7188 			Show(hWnd, S_IMAGE2);
7189 			Hide(hWnd, S_IMAGE_TSUKUBA);
7190 		}
7191 		else
7192 		{
7193 			// Regular card
7194 			Hide(hWnd, S_IMAGE2);
7195 
7196 			if (w->BitmapId != 0)
7197 			{
7198 				// For University of Tsukuba
7199 				Hide(hWnd, S_IMAGE);
7200 				Show(hWnd, S_IMAGE_TSUKUBA);
7201 			}
7202 			else
7203 			{
7204 				// For general use
7205 				Show(hWnd, S_IMAGE);
7206 				Hide(hWnd, S_IMAGE_TSUKUBA);
7207 			}
7208 		}
7209 
7210 		FormatText(hWnd, 0, dev->Type != SECURE_USB_TOKEN ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN"),
7211 			dev->DeviceName);
7212 		FormatText(hWnd, S_TITLE, dev->DeviceName);
7213 		FormatText(hWnd, S_INSERT_SECURE,
7214 			dev->Type != SECURE_USB_TOKEN ? _UU("SEC_INIT_MSG_1") : _UU("SEC_INIT_MSG_2"));
7215 		FormatText(hWnd, S_DEVICE_INFO,
7216 			dev->DeviceName, dev->Manufacturer, dev->ModuleName);
7217 
7218 		DlgFont(hWnd, S_SOFTWARE_TITLE, 11, 0);
7219 		SetText(hWnd, S_SOFTWARE_TITLE, title_bar);
7220 
7221 		DlgFont(hWnd, S_TITLE, 14, true);
7222 		DlgFont(hWnd, S_DEVICE_INFO, 11, false);
7223 		DlgFont(hWnd, S_STATUS, 13, true);
7224 		EnableSecureDeviceWindowControls(hWnd, true);
7225 		OpenAvi(hWnd, A_PROGRESS, AVI_PROGRESS);
7226 
7227 		SetIcon(hWnd, 0, ICO_KEY);
7228 
7229 		// Initial PIN
7230 		if ((w->default_pin != NULL && StrLen(w->default_pin) != 0) || (cached_pin_code_expires >= Tick64()))
7231 		{
7232 			if (w->default_pin != NULL && StrLen(w->default_pin) != 0)
7233 			{
7234 				SetTextA(hWnd, E_PIN, w->default_pin);
7235 			}
7236 			else
7237 			{
7238 				SetTextA(hWnd, E_PIN, cached_pin_code);
7239 			}
7240 			SetTimer(hWnd, 1, 1, NULL);
7241 		}
7242 
7243 		break;
7244 
7245 	case WM_TIMER:
7246 		switch (wParam)
7247 		{
7248 		case 1:
7249 			KillTimer(hWnd, 1);
7250 			Command(hWnd, IDOK);
7251 			break;
7252 		}
7253 		break;
7254 
7255 	case WM_COMMAND:
7256 		switch (wParam)
7257 		{
7258 		case IDOK:
7259 			StartSecureDevice(hWnd, w);
7260 			break;
7261 
7262 		case IDCANCEL:
7263 			Close(hWnd);
7264 			break;
7265 		}
7266 		break;
7267 
7268 	case WM_CLOSE:
7269 		if (IsEnable(hWnd, IDCANCEL))
7270 		{
7271 			CloseAvi(hWnd, A_PROGRESS);
7272 			EndDialog(hWnd, false);
7273 		}
7274 		break;
7275 
7276 	case WM_APP + 1:
7277 		// There is a response from the thread
7278 		if (w->p != NULL)
7279 		{
7280 			if (w->p->Succeed)
7281 			{
7282 				// Success
7283 				if (w->default_pin != NULL)
7284 				{
7285 					StrCpy(w->default_pin, 128, w->p->pin);
7286 				}
7287 				StrCpy(cached_pin_code, sizeof(cached_pin_code), w->p->pin);
7288 				cached_pin_code_expires = Tick64() + (UINT64)WINUI_SECUREDEVICE_PIN_CACHE_TIME;
7289 				Free(w->p->pin);
7290 				Free(w->p);
7291 				EndDialog(hWnd, true);
7292 			}
7293 			else
7294 			{
7295 				// Failure
7296 				cached_pin_code_expires = 0;
7297 				EnableSecureDeviceWindowControls(hWnd, true);
7298 				FocusEx(hWnd, E_PIN);
7299 				MsgBox(hWnd, MB_ICONEXCLAMATION, w->p->ErrorMessage);
7300 				Free(w->p->pin);
7301 				Free(w->p->ErrorMessage);
7302 				Free(w->p);
7303 			}
7304 		}
7305 		break;
7306 	}
7307 
7308 	return 0;
7309 }
7310 
7311 // Send a WM_COMMAND
Command(HWND hWnd,UINT id)7312 void Command(HWND hWnd, UINT id)
7313 {
7314 	SendMessage(hWnd, WM_COMMAND, id, 0);
7315 }
7316 
7317 // Show the secure device window
SecureDeviceWindow(HWND hWnd,WINUI_SECURE_BATCH * batch,UINT num_batch,UINT device_id,UINT bitmap_id)7318 bool SecureDeviceWindow(HWND hWnd, WINUI_SECURE_BATCH *batch, UINT num_batch, UINT device_id, UINT bitmap_id)
7319 {
7320 	SECURE_DEVICE_WINDOW w;
7321 	UINT i;
7322 	// Validate arguments
7323 	if (batch == NULL || num_batch == 0 || device_id == 0)
7324 	{
7325 		return false;
7326 	}
7327 
7328 	// Initialize the success flag
7329 	for (i = 0;i < num_batch;i++)
7330 	{
7331 		batch[i].Succeed = false;
7332 	}
7333 
7334 	Zero(&w, sizeof(w));
7335 	w.batch = batch;
7336 	w.device_id = device_id;
7337 	w.num_batch = num_batch;
7338 	w.BitmapId = bitmap_id;
7339 
7340 	// Open a dialog
7341 	return (bool)Dialog(hWnd, D_SECURE, SecureDeviceWindowProc, &w);
7342 }
7343 
7344 // Stop playing the AVI
StopAvi(HWND hWnd,UINT id)7345 void StopAvi(HWND hWnd, UINT id)
7346 {
7347 	// Validate arguments
7348 	if (hWnd == NULL)
7349 	{
7350 		return;
7351 	}
7352 
7353 	Animate_Stop(DlgItem(hWnd, id));
7354 	Hide(hWnd, id);
7355 }
7356 
7357 // Play an AVI
PlayAvi(HWND hWnd,UINT id,bool repeat)7358 void PlayAvi(HWND hWnd, UINT id, bool repeat)
7359 {
7360 	// Validate arguments
7361 	if (hWnd == NULL)
7362 	{
7363 		return;
7364 	}
7365 
7366 	Show(hWnd, id);
7367 	Animate_Play(DlgItem(hWnd, id), 0, -1, (repeat ? -1 : 0));
7368 }
7369 
7370 // Close the AVI file
CloseAvi(HWND hWnd,UINT id)7371 void CloseAvi(HWND hWnd, UINT id)
7372 {
7373 	// Validate arguments
7374 	if (hWnd == NULL)
7375 	{
7376 		return;
7377 	}
7378 
7379 	StopAvi(hWnd, id);
7380 	Animate_Close(DlgItem(hWnd, id));
7381 }
7382 
7383 // Open an AVI file
OpenAvi(HWND hWnd,UINT id,UINT avi_id)7384 void OpenAvi(HWND hWnd, UINT id, UINT avi_id)
7385 {
7386 	// Validate arguments
7387 	if (hWnd == NULL || avi_id == 0)
7388 	{
7389 		return;
7390 	}
7391 
7392 	Hide(hWnd, id);
7393 	Animate_OpenEx(DlgItem(hWnd, id), hDll, MAKEINTRESOURCE(avi_id));
7394 }
7395 
7396 // Set the font to the control
DlgFont(HWND hWnd,UINT id,UINT size,UINT bold)7397 void DlgFont(HWND hWnd, UINT id, UINT size, UINT bold)
7398 {
7399 	DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);
7400 
7401 	if (param == NULL || param->meiryo == false)
7402 	{
7403 		SetFont(hWnd, id, Font(size, bold));
7404 	}
7405 	else
7406 	{
7407 		SetFont(hWnd, id, GetFont((_GETLANG() == 2 ? "Microsoft YaHei" : GetMeiryoFontName()), size, bold, false, false, false));
7408 	}
7409 }
7410 
7411 // Generate a standard font
Font(UINT size,UINT bold)7412 HFONT Font(UINT size, UINT bold)
7413 {
7414 	return GetFont(NULL, size, bold, false, false, false);
7415 }
7416 
7417 // Dialog procedure for internal management
InternalDialogProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)7418 UINT CALLBACK InternalDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
7419 {
7420 	DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);
7421 	void *app_param = NULL;
7422 	bool white_flag = false;
7423 	UINT ret;
7424 	// Validate arguments
7425 	if (hWnd == NULL)
7426 	{
7427 		return 0;
7428 	}
7429 
7430 	if (msg == WM_INITDIALOG)
7431 	{
7432 		DoEvents(hWnd);
7433 	}
7434 
7435 	if (param == NULL)
7436 	{
7437 		if (msg == WM_INITDIALOG)
7438 		{
7439 			param = (void *)lParam;
7440 			InitDialogInternational(hWnd, param);
7441 		}
7442 	}
7443 	if (param != NULL)
7444 	{
7445 		app_param = param->param;
7446 		white_flag = param->white;
7447 	}
7448 
7449 	ret = DlgProc(hWnd, msg, wParam, lParam, white_flag);
7450 	if (ret != 0)
7451 	{
7452 		return ret;
7453 	}
7454 
7455 	ret = 0;
7456 
7457 	if (param != NULL)
7458 	{
7459 		if (param->proc != NULL)
7460 		{
7461 			ret = param->proc(hWnd, msg, wParam, lParam, app_param);
7462 		}
7463 		else
7464 		{
7465 			if (msg == WM_CLOSE)
7466 			{
7467 				EndDialog(hWnd, 0);
7468 			}
7469 			else if (msg == WM_COMMAND && (wParam == IDOK || wParam == IDCANCEL))
7470 			{
7471 				Close(hWnd);
7472 			}
7473 		}
7474 	}
7475 
7476 	if (msg == WM_INITDIALOG)
7477 	{
7478 		SetForegroundWindow(hWnd);
7479 		SetActiveWindow(hWnd);
7480 	}
7481 
7482 	return ret;
7483 }
7484 
7485 // Show a dialog box
Dialog(HWND hWnd,UINT id,WINUI_DIALOG_PROC * proc,void * param)7486 UINT Dialog(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param)
7487 {
7488 	bool white = true;
7489 
7490 	return DialogEx(hWnd, id, proc, param, white);
7491 }
DialogEx(HWND hWnd,UINT id,WINUI_DIALOG_PROC * proc,void * param,bool white)7492 UINT DialogEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white)
7493 {
7494 	return DialogEx2(hWnd, id, proc, param, white, false);
7495 }
DialogEx2(HWND hWnd,UINT id,WINUI_DIALOG_PROC * proc,void * param,bool white,bool meiryo)7496 UINT DialogEx2(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white, bool meiryo)
7497 {
7498 	UINT ret;
7499 	DIALOG_PARAM p;
7500 	// Validate arguments
7501 	if (id == 0)
7502 	{
7503 		return 0;
7504 	}
7505 
7506 	Zero(&p, sizeof(p));
7507 	p.param = param;
7508 	p.white = white;
7509 	p.proc = proc;
7510 
7511 	p.BitmapList = NewBitmapList();
7512 
7513 	p.meiryo = meiryo;
7514 
7515 	ret = DialogInternal(hWnd, id, InternalDialogProc, &p);
7516 
7517 	FreeBitmapList(p.BitmapList);
7518 
7519 	return ret;
7520 }
7521 
7522 // Initialize the icon cache
InitIconCache()7523 void InitIconCache()
7524 {
7525 	if (icon_cache_list != NULL)
7526 	{
7527 		return;
7528 	}
7529 
7530 	icon_cache_list = NewList(NULL);
7531 }
7532 
7533 // Release the icon cache
FreeIconCache()7534 void FreeIconCache()
7535 {
7536 	UINT i;
7537 	if (icon_cache_list == NULL)
7538 	{
7539 		return;
7540 	}
7541 
7542 	for (i = 0;i < LIST_NUM(icon_cache_list);i++)
7543 	{
7544 		ICON_CACHE *c = LIST_DATA(icon_cache_list, i);
7545 		DestroyIcon(c->hIcon);
7546 		Free(c);
7547 	}
7548 
7549 	ReleaseList(icon_cache_list);
7550 	icon_cache_list = NULL;
7551 }
7552 
7553 // Get the Icon
LoadIconEx(UINT id,bool small_icon)7554 HICON LoadIconEx(UINT id, bool small_icon)
7555 {
7556 	HICON h = NULL;
7557 	UINT i;
7558 	if (icon_cache_list == NULL)
7559 	{
7560 		return small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);
7561 	}
7562 
7563 	LockList(icon_cache_list);
7564 	{
7565 		for (i = 0;i < LIST_NUM(icon_cache_list);i++)
7566 		{
7567 			ICON_CACHE *c = LIST_DATA(icon_cache_list, i);
7568 			if (c->id == id && c->small_icon == small_icon)
7569 			{
7570 				h = c->hIcon;
7571 				break;
7572 			}
7573 		}
7574 
7575 		if (h == NULL)
7576 		{
7577 			h = small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);
7578 			if (h != NULL)
7579 			{
7580 				ICON_CACHE *c = ZeroMalloc(sizeof(ICON_CACHE));
7581 				c->hIcon = h;
7582 				c->id = id;
7583 				c->small_icon = small_icon;
7584 				Add(icon_cache_list, c);
7585 			}
7586 		}
7587 	}
7588 	UnlockList(icon_cache_list);
7589 
7590 	return h;
7591 }
7592 
7593 // Get a large Icon
LoadLargeIcon(UINT id)7594 HICON LoadLargeIcon(UINT id)
7595 {
7596 	return LoadIconEx(id, false);
7597 }
7598 
7599 // Get a small icon
LoadSmallIcon(UINT id)7600 HICON LoadSmallIcon(UINT id)
7601 {
7602 	return LoadIconEx(id, true);
7603 }
7604 
7605 // Get a large icon
LoadLargeIconInner(UINT id)7606 HICON LoadLargeIconInner(UINT id)
7607 {
7608 	HICON ret;
7609 	ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, 0);
7610 	if (ret == NULL)
7611 	{
7612 		ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, LR_VGACOLOR);
7613 		if (ret == NULL)
7614 		{
7615 			ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);
7616 			if (ret == NULL)
7617 			{
7618 				ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);
7619 				if (ret == NULL)
7620 				{
7621 					ret = LoadIcon(hDll, MAKEINTRESOURCE(id));
7622 				}
7623 			}
7624 		}
7625 	}
7626 	return ret;
7627 }
7628 
7629 // Get a small icon
LoadSmallIconInner(UINT id)7630 HICON LoadSmallIconInner(UINT id)
7631 {
7632 	HICON ret;
7633 	ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, 0);
7634 	if (ret == NULL)
7635 	{
7636 		ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, LR_VGACOLOR);
7637 		if (ret == NULL)
7638 		{
7639 			ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);
7640 			if (ret == NULL)
7641 			{
7642 				ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);
7643 				if (ret == NULL)
7644 				{
7645 					ret = LoadLargeIconInner(id);
7646 				}
7647 			}
7648 		}
7649 	}
7650 	return ret;
7651 }
7652 
7653 // Set the icon to the button or window
SetIcon(HWND hWnd,UINT id,UINT icon_id)7654 void SetIcon(HWND hWnd, UINT id, UINT icon_id)
7655 {
7656 	HICON icon1, icon2;
7657 	// Validate arguments
7658 	if (hWnd == NULL)
7659 	{
7660 		return;
7661 	}
7662 
7663 	icon1 = LoadLargeIcon(icon_id);
7664 	if (icon1 == NULL)
7665 	{
7666 		return;
7667 	}
7668 
7669 	if (id == 0)
7670 	{
7671 		SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon1);
7672 		icon2 = LoadSmallIcon(icon_id);
7673 		if (icon2 == NULL)
7674 		{
7675 			icon2 = icon1;
7676 		}
7677 		SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon2);
7678 	}
7679 	else
7680 	{
7681 		bool is_btn = true;
7682 		wchar_t *s = GetClass(hWnd, id);
7683 		if (s != NULL)
7684 		{
7685 			if (UniStrCmpi(s, L"Static") == 0)
7686 			{
7687 				is_btn = false;
7688 			}
7689 			Free(s);
7690 		}
7691 
7692 		if (is_btn)
7693 		{
7694 			SendMsg(hWnd, id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon1);
7695 		}
7696 		else
7697 		{
7698 			SendMsg(hWnd, id, STM_SETICON, (WPARAM)icon1, 0);
7699 		}
7700 	}
7701 }
7702 
7703 // Check whether the radio button is checked
IsChecked(HWND hWnd,UINT id)7704 bool IsChecked(HWND hWnd, UINT id)
7705 {
7706 	// Validate arguments
7707 	if (hWnd == NULL)
7708 	{
7709 		return false;
7710 	}
7711 
7712 	return IsDlgButtonChecked(hWnd, id) == BST_CHECKED ? true : false;
7713 }
7714 
7715 // Check the radio button
Check(HWND hWnd,UINT id,bool b)7716 void Check(HWND hWnd, UINT id, bool b)
7717 {
7718 	// Validate arguments
7719 	if (hWnd == NULL)
7720 	{
7721 		return;
7722 	}
7723 
7724 	if ((!(!IsChecked(hWnd, id))) != (!(!b)))
7725 	{
7726 		CheckDlgButton(hWnd, id, b ? BST_CHECKED : BST_UNCHECKED);
7727 	}
7728 }
7729 
7730 // Limit the number of characters that can be entered into the text-box
LimitText(HWND hWnd,UINT id,UINT count)7731 void LimitText(HWND hWnd, UINT id, UINT count)
7732 {
7733 	// Validate arguments
7734 	if (hWnd == NULL)
7735 	{
7736 		return;
7737 	}
7738 
7739 	SendMsg(hWnd, id, EM_LIMITTEXT, count, 0);
7740 }
7741 
7742 // Font settings
SetFont(HWND hWnd,UINT id,HFONT hFont)7743 void SetFont(HWND hWnd, UINT id, HFONT hFont)
7744 {
7745 	SetFontEx(hWnd, id, hFont, false);
7746 }
SetFontEx(HWND hWnd,UINT id,HFONT hFont,bool no_adjust_font_size)7747 void SetFontEx(HWND hWnd, UINT id, HFONT hFont, bool no_adjust_font_size)
7748 {
7749 	// Validate arguments
7750 	if (hWnd == NULL || hFont == NULL)
7751 	{
7752 		return;
7753 	}
7754 
7755 	SendMessage(DlgItem(hWnd, id), WM_SETFONT, (WPARAM)hFont, true);
7756 
7757 	if (no_adjust_font_size == false)
7758 	{
7759 		AdjustFontSize(hWnd, id);
7760 	}
7761 }
7762 
7763 // Calculate the font size
CalcFontSize(HFONT hFont,UINT * x,UINT * y)7764 bool CalcFontSize(HFONT hFont, UINT *x, UINT *y)
7765 {
7766 	UINT xx = 0, yy = 0;
7767 	TEXTMETRIC tm;
7768 	SIZE sz;
7769 	bool ret = false;
7770 	HDC hDC;
7771 
7772 	hDC = CreateCompatibleDC(NULL);
7773 
7774 	SelectObject(hDC, hFont);
7775 
7776 	Zero(&tm, sizeof(tm));
7777 	Zero(&sz, sizeof(sz));
7778 
7779 	if (GetTextMetrics(hDC, &tm))
7780 	{
7781 		xx = tm.tmAveCharWidth;
7782 		yy = tm.tmHeight;
7783 
7784 		ret = true;
7785 
7786 		if (GetTextExtentPoint32(hDC,
7787 			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
7788 			52, &sz))
7789 		{
7790 			xx = (sz.cx / 26 + 1) / 2;
7791 		}
7792 	}
7793 
7794 	if (x != NULL)
7795 	{
7796 		*x = xx;
7797 	}
7798 
7799 	if (y != NULL)
7800 	{
7801 		*y = yy;
7802 	}
7803 
7804 	DeleteDC(hDC);
7805 
7806 	return ret;
7807 }
7808 
7809 // Get the font magnification
GetTextScalingFactor()7810 double GetTextScalingFactor()
7811 {
7812 	static int cached_dpi = 0;
7813 	double ret = 1.0;
7814 
7815 	if (cached_dpi == 0)
7816 	{
7817 		HDC hDC = CreateCompatibleDC(NULL);
7818 
7819 		if (hDC != NULL)
7820 		{
7821 			cached_dpi = GetDeviceCaps(hDC, LOGPIXELSY);
7822 
7823 			DeleteDC(hDC);
7824 		}
7825 	}
7826 
7827 	if (cached_dpi != 0)
7828 	{
7829 		ret = (double)cached_dpi / 96.0;
7830 
7831 		if (ret < 0)
7832 		{
7833 			ret = -ret;
7834 		}
7835 	}
7836 
7837 	return ret;
7838 }
7839 
7840 // Get the parameters of the font that was created in the past
GetFontParam(HFONT hFont,struct FONT * f)7841 bool GetFontParam(HFONT hFont, struct FONT *f)
7842 {
7843 	bool ret = false;
7844 	// Validate arguments
7845 	if (hFont == NULL || f == NULL)
7846 	{
7847 		return false;
7848 	}
7849 
7850 	// Search for the existing font
7851 	LockList(font_list);
7852 	{
7853 		UINT i;
7854 
7855 		for (i = 0;i < LIST_NUM(font_list);i++)
7856 		{
7857 			FONT *n = LIST_DATA(font_list, i);
7858 
7859 			if (n->hFont == hFont)
7860 			{
7861 				Copy(f, n, sizeof(FONT));
7862 
7863 				ret = true;
7864 
7865 				break;
7866 			}
7867 		}
7868 	}
7869 	UnlockList(font_list);
7870 
7871 	return ret;
7872 }
7873 
7874 // Get the font
GetFont(char * name,UINT size,bool bold,bool italic,bool underline,bool strikeout)7875 HFONT GetFont(char *name, UINT size, bool bold, bool italic, bool underline, bool strikeout)
7876 {
7877 	HFONT hFont;
7878 	HDC hDC;
7879 	// Validate arguments
7880 	if (name == NULL)
7881 	{
7882 		name = font_name;
7883 	}
7884 	if (size == 0)
7885 	{
7886 		size = font_size;
7887 		if (size == 0)
7888 		{
7889 			size = 9;
7890 		}
7891 	}
7892 
7893 	// Search for the existing font
7894 	LockList(font_list);
7895 	{
7896 		FONT *f, t;
7897 		DWORD font_quality = ANTIALIASED_QUALITY;
7898 		OS_INFO *os = GetOsInfo();
7899 		UINT x = 0;
7900 		UINT y = 0;
7901 		int rotate = 0;
7902 		UINT dpi;
7903 
7904 		Zero(&t, sizeof(t));
7905 		t.Bold = bold;
7906 		t.Italic = italic;
7907 		t.Size = size;
7908 		t.StrikeOut = strikeout;
7909 		t.UnderLine = underline;
7910 		t.Name = CopyStr(name);
7911 		f = Search(font_list, &t);
7912 		Free(t.Name);
7913 
7914 		if (f != NULL)
7915 		{
7916 			// Font is found
7917 			UnlockList(font_list);
7918 			return f->hFont;
7919 		}
7920 
7921 		// Create a new font
7922 		hDC = CreateCompatibleDC(NULL);
7923 
7924 		font_quality = CLEARTYPE_NATURAL_QUALITY;
7925 		rotate = 3600;
7926 		dpi = GetDeviceCaps(hDC, LOGPIXELSY);
7927 
7928 		// Create a font
7929 		hFont = CreateFontA(-MulDiv(size, dpi, 72),
7930 			0, rotate, rotate, (bold == false ? 500 : FW_BOLD),
7931 			italic, underline, strikeout, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
7932 			CLIP_DEFAULT_PRECIS, font_quality, DEFAULT_PITCH, name);
7933 
7934 		if (hFont == NULL)
7935 		{
7936 			// Failure
7937 			DeleteDC(hDC);
7938 			UnlockList(font_list);
7939 
7940 			return NULL;
7941 		}
7942 
7943 		CalcFontSize(hFont, &x, &y);
7944 
7945 		// Add to the table
7946 		f = ZeroMalloc(sizeof(FONT));
7947 		f->Bold = bold;
7948 		f->hFont = hFont;
7949 		f->Italic = italic;
7950 		f->Name = CopyStr(name);
7951 		f->Size = size;
7952 		f->StrikeOut = strikeout;
7953 		f->UnderLine = underline;
7954 		f->x = x;
7955 		f->y = y;
7956 
7957 		Insert(font_list, f);
7958 
7959 		DeleteDC(hDC);
7960 	}
7961 	UnlockList(font_list);
7962 
7963 	return hFont;
7964 }
7965 
7966 // Comparison of the font
CompareFont(void * p1,void * p2)7967 int CompareFont(void *p1, void *p2)
7968 {
7969 	FONT *f1, *f2;
7970 	UINT r;
7971 	if (p1 == NULL || p2 == NULL)
7972 	{
7973 		return 0;
7974 	}
7975 	f1 = *(FONT **)p1;
7976 	f2 = *(FONT **)p2;
7977 	if (f1 == NULL || f2 == NULL)
7978 	{
7979 		return 0;
7980 	}
7981 	r = StrCmpi(f1->Name, f2->Name);
7982 	if (r != 0)
7983 	{
7984 		return r;
7985 	}
7986 	else
7987 	{
7988 		if (f1->Bold > f2->Bold)
7989 		{
7990 			return 1;
7991 		}
7992 		else if (f1->Bold < f2->Bold)
7993 		{
7994 			return -1;
7995 		}
7996 		else if (f1->Italic > f2->Italic)
7997 		{
7998 			return 1;
7999 		}
8000 		else if (f1->Italic < f2->Italic)
8001 		{
8002 			return -1;
8003 		}
8004 		else if (f1->Size > f2->Size)
8005 		{
8006 			return 1;
8007 		}
8008 		else if (f1->Size < f2->Size)
8009 		{
8010 			return -1;
8011 		}
8012 		else if (f1->StrikeOut > f2->StrikeOut)
8013 		{
8014 			return 1;
8015 		}
8016 		else if (f1->StrikeOut < f2->StrikeOut)
8017 		{
8018 			return -1;
8019 		}
8020 		else if (f1->UnderLine > f2->UnderLine)
8021 		{
8022 			return 1;
8023 		}
8024 		else if (f1->UnderLine < f2->UnderLine)
8025 		{
8026 			return -1;
8027 		}
8028 		else
8029 		{
8030 			return 0;
8031 		}
8032 	}
8033 }
8034 
8035 // Initialize the font
InitFont()8036 void InitFont()
8037 {
8038 	if (font_list != NULL)
8039 	{
8040 		return;
8041 	}
8042 	font_list = NewList(CompareFont);
8043 }
8044 
8045 // Release the font
FreeFont()8046 void FreeFont()
8047 {
8048 	UINT i;
8049 	if (font_list == NULL)
8050 	{
8051 		return;
8052 	}
8053 	for (i = 0;i < LIST_NUM(font_list);i++)
8054 	{
8055 		FONT *f = LIST_DATA(font_list, i);
8056 		Free(f->Name);
8057 		DeleteObject((HGDIOBJ)f->hFont);
8058 		Free(f);
8059 	}
8060 	ReleaseList(font_list);
8061 	font_list = NULL;
8062 }
8063 
8064 // Show a button to close the window
EnableClose(HWND hWnd)8065 void EnableClose(HWND hWnd)
8066 {
8067 	HMENU h;
8068 	// Validate arguments
8069 	if (hWnd == NULL)
8070 	{
8071 		return;
8072 	}
8073 
8074 	h = GetSystemMenu(hWnd, false);
8075 	EnableMenuItem(h, SC_CLOSE, MF_ENABLED);
8076 	DrawMenuBar(hWnd);
8077 }
8078 
8079 // Hide the button to close the window
DisableClose(HWND hWnd)8080 void DisableClose(HWND hWnd)
8081 {
8082 	HMENU h;
8083 	// Validate arguments
8084 	if (hWnd == NULL)
8085 	{
8086 		return;
8087 	}
8088 
8089 	h = GetSystemMenu(hWnd, false);
8090 	EnableMenuItem(h, SC_CLOSE, MF_GRAYED);
8091 	DrawMenuBar(hWnd);
8092 }
8093 
8094 // Move to the center of the parent window
CenterParent(HWND hWnd)8095 void CenterParent(HWND hWnd)
8096 {
8097 	RECT rp;
8098 	RECT r;
8099 	HWND hWndParent = GetParent(hWnd);
8100 	int win_x, win_y;
8101 	int x, y;
8102 
8103 	if (hWndParent == NULL || IsHide(hWndParent, 0) || IsIconic(hWndParent))
8104 	{
8105 		Center(hWnd);
8106 		return;
8107 	}
8108 
8109 	if (GetWindowRect(hWndParent, &rp) == false)
8110 	{
8111 		Center(hWnd);
8112 		return;
8113 	}
8114 
8115 	GetWindowRect(hWnd, &r);
8116 
8117 	win_x = r.right - r.left;
8118 	win_y = r.bottom - r.top;
8119 
8120 	x = (rp.right - rp.left - win_x) / 2 + rp.left;
8121 	y = (rp.bottom - rp.top - win_y) / 2 + rp.top;
8122 
8123 	x = MAX(x, 0);
8124 	y = MAX(y, 0);
8125 
8126 	SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
8127 }
8128 
8129 // Move the window to the center
Center(HWND hWnd)8130 void Center(HWND hWnd)
8131 {
8132 	RECT screen;
8133 	RECT win;
8134 	UINT x, y;
8135 	UINT win_x, win_y;
8136 	// Validate arguments
8137 	if (hWnd == NULL)
8138 	{
8139 		return;
8140 	}
8141 
8142 	if (SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0) == false)
8143 	{
8144 		return;
8145 	}
8146 
8147 	GetWindowRect(hWnd, &win);
8148 	win_x = win.right - win.left;
8149 	win_y = win.bottom - win.top;
8150 
8151 	if (win_x < (UINT)(screen.right - screen.left))
8152 	{
8153 		x = (screen.right - screen.left - win_x) / 2;
8154 	}
8155 	else
8156 	{
8157 		x = 0;
8158 	}
8159 
8160 	if (win_y < (UINT)(screen.bottom - screen.top))
8161 	{
8162 		y = (screen.bottom - screen.top - win_y) / 2;
8163 	}
8164 	else
8165 	{
8166 		y = 0;
8167 	}
8168 
8169 	SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
8170 }
8171 
8172 // Format the string in the window
FormatText(HWND hWnd,UINT id,...)8173 void FormatText(HWND hWnd, UINT id, ...)
8174 {
8175 	va_list args;
8176 	wchar_t *buf;
8177 	UINT size;
8178 	wchar_t *str;
8179 	// Validate arguments
8180 	if (hWnd == NULL)
8181 	{
8182 		return;
8183 	}
8184 
8185 	str = GetText(hWnd, id);
8186 	if (str == NULL)
8187 	{
8188 		return;
8189 	}
8190 
8191 	size = MAX(UniStrSize(str) * 10, MAX_SIZE * 10);
8192 	buf = MallocEx(size, true);
8193 
8194 	va_start(args, id);
8195 	UniFormatArgs(buf, size, str, args);
8196 
8197 	SetText(hWnd, id, buf);
8198 
8199 	Free(buf);
8200 
8201 	Free(str);
8202 	va_end(args);
8203 }
8204 
8205 // Show the variable-length message box
MsgBoxEx(HWND hWnd,UINT flag,wchar_t * msg,...)8206 UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...)
8207 {
8208 	va_list args;
8209 	wchar_t *buf;
8210 	UINT size;
8211 	UINT ret;
8212 	// Validate arguments
8213 	if (msg == NULL)
8214 	{
8215 		msg = L"MessageBox";
8216 	}
8217 
8218 	size = MAX(UniStrSize(msg) * 10, MAX_SIZE * 10);
8219 	buf = MallocEx(size, true);
8220 
8221 	va_start(args, msg);
8222 	UniFormatArgs(buf, size, msg, args);
8223 
8224 	ret = MsgBox(hWnd, flag, buf);
8225 	Free(buf);
8226 	va_end(args);
8227 
8228 	return ret;
8229 }
8230 
8231 // Show the message box
MsgBox(HWND hWnd,UINT flag,wchar_t * msg)8232 UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg)
8233 {
8234 	UINT ret;
8235 	wchar_t *title;
8236 	// Validate arguments
8237 	if (msg == NULL)
8238 	{
8239 		msg = L"MessageBox";
8240 	}
8241 
8242 	if (title_bar != NULL)
8243 	{
8244 		title = CopyUniStr(title_bar);
8245 	}
8246 	else
8247 	{
8248 		title = CopyStrToUni(CEDAR_PRODUCT_STR);
8249 	}
8250 
8251 	if (hWnd)
8252 	{
8253 		// Raise the message box to top-level if the parent window is the top-level window
8254 		if (GetExStyle(hWnd, 0) & WS_EX_TOPMOST)
8255 		{
8256 			flag |= MB_SYSTEMMODAL;
8257 		}
8258 	}
8259 
8260 	ret = MessageBoxW(hWnd, msg, title, flag);
8261 
8262 	Free(title);
8263 
8264 	return ret;
8265 }
8266 
8267 // Create a dialog (internal)
DialogInternal(HWND hWnd,UINT id,DIALOG_PROC * proc,void * param)8268 UINT DialogInternal(HWND hWnd, UINT id, DIALOG_PROC *proc, void *param)
8269 {
8270 	// Validate arguments
8271 	if (proc == NULL)
8272 	{
8273 		return 0;
8274 	}
8275 
8276 	return (UINT)DialogBoxParamW(hDll, MAKEINTRESOURCEW(id), hWnd, (DLGPROC)proc, (LPARAM)param);
8277 }
8278 
8279 // Dialog box procedure managed by WinUi
DlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,bool white_color)8280 UINT DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, bool white_color)
8281 {
8282 	void *param;
8283 	HWND hWndParent;
8284 	// Validate arguments
8285 	if (hWnd == NULL)
8286 	{
8287 		return 0;
8288 	}
8289 
8290 	switch (msg)
8291 	{
8292 	case WM_INITDIALOG:
8293 		if (true)
8294 		{
8295 			RECT rect1;
8296 
8297 			SetRect(&rect1, 0, 0, 100, 100);
8298 			MapDialogRect(hWnd, &rect1);
8299 			Debug("%u %u %u %u\n", rect1.left, rect1.right, rect1.top, rect1.bottom);
8300 		}
8301 
8302 		param = (void *)lParam;
8303 		SetParam(hWnd, param);
8304 
8305 		// Examine whether the parent window exists
8306 		hWndParent = GetParent(hWnd);
8307 		if (hWndParent == NULL || IsShow(hWndParent, 0) == false)
8308 		{
8309 			// Place in the center if parent does not exist
8310 			Center(hWnd);
8311 		}
8312 
8313 		if (UseAlpha)
8314 		{
8315 			bool (WINAPI *_SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD);
8316 			HINSTANCE hInst;
8317 
8318 			hInst = LoadLibrary("user32.dll");
8319 			_SetLayeredWindowAttributes =
8320 				(bool (__stdcall *)(HWND,COLORREF,BYTE,DWORD))
8321 				GetProcAddress(hInst, "SetLayeredWindowAttributes");
8322 
8323 			if (_SetLayeredWindowAttributes != NULL)
8324 			{
8325 				// Only available on Windows 2000 or later
8326 				SetExStyle(hWnd, 0, WS_EX_LAYERED);
8327 				_SetLayeredWindowAttributes(hWnd, 0, AlphaValue * 255 / 100, LWA_ALPHA);
8328 			}
8329 		}
8330 
8331 		break;
8332 
8333 	case WM_CTLCOLORBTN:
8334 	case WM_CTLCOLORDLG:
8335 	case WM_CTLCOLOREDIT:
8336 	case WM_CTLCOLORLISTBOX:
8337 	case WM_CTLCOLORMSGBOX:
8338 	case WM_CTLCOLORSCROLLBAR:
8339 	case WM_CTLCOLORSTATIC:
8340 		if (white_color)
8341 		{
8342 			return (UINT)GetStockObject(WHITE_BRUSH);
8343 		}
8344 		break;
8345 	}
8346 
8347 	return 0;
8348 }
8349 
8350 // Set the parameters of the dialog box
SetParam(HWND hWnd,void * param)8351 void SetParam(HWND hWnd, void *param)
8352 {
8353 	// Validate arguments
8354 	if (hWnd == NULL)
8355 	{
8356 		return;
8357 	}
8358 
8359 	SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)param);
8360 }
8361 
8362 // Get the parameters of the dialog box
GetParam(HWND hWnd)8363 void *GetParam(HWND hWnd)
8364 {
8365 	void *ret;
8366 	// Validate arguments
8367 	if (hWnd == NULL)
8368 	{
8369 		return NULL;
8370 	}
8371 
8372 	ret = (void *)GetWindowLongPtr(hWnd, DWLP_USER);
8373 	return ret;
8374 }
8375 
8376 // Show the windows as foreground
Top(HWND hWnd)8377 void Top(HWND hWnd)
8378 {
8379 	// Validate arguments
8380 	if (hWnd == NULL)
8381 	{
8382 		return;
8383 	}
8384 
8385 	SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
8386 }
8387 
8388 // Hide the window
Hide(HWND hWnd,UINT id)8389 void Hide(HWND hWnd, UINT id)
8390 {
8391 	// Validate arguments
8392 	if (hWnd == NULL)
8393 	{
8394 		return;
8395 	}
8396 
8397 	if (IsShow(hWnd, id))
8398 	{
8399 		ShowWindow(DlgItem(hWnd, id), SW_HIDE);
8400 	}
8401 }
8402 
8403 // Show the window
Show(HWND hWnd,UINT id)8404 void Show(HWND hWnd, UINT id)
8405 {
8406 	// Validate arguments
8407 	if (hWnd == NULL)
8408 	{
8409 		return;
8410 	}
8411 
8412 	if (IsHide(hWnd, id))
8413 	{
8414 		ShowWindow(DlgItem(hWnd, id), SW_SHOW);
8415 	}
8416 }
8417 
8418 // Change the display settings
SetShow(HWND hWnd,UINT id,bool b)8419 void SetShow(HWND hWnd, UINT id, bool b)
8420 {
8421 	// Validate arguments
8422 	if (hWnd == NULL)
8423 	{
8424 		return;
8425 	}
8426 
8427 	if (b)
8428 	{
8429 		Show(hWnd, id);
8430 	}
8431 	else
8432 	{
8433 		Hide(hWnd, id);
8434 	}
8435 }
8436 
8437 // Get whether the window is shown
IsShow(HWND hWnd,UINT id)8438 bool IsShow(HWND hWnd, UINT id)
8439 {
8440 	return IsHide(hWnd, id) ? false : true;
8441 }
8442 
8443 // Get whether the window is hidden
IsHide(HWND hWnd,UINT id)8444 bool IsHide(HWND hWnd, UINT id)
8445 {
8446 	// Validate arguments
8447 	if (hWnd == NULL)
8448 	{
8449 		return true;
8450 	}
8451 
8452 	if (GetStyle(hWnd, id) & WS_VISIBLE)
8453 	{
8454 		return false;
8455 	}
8456 	else
8457 	{
8458 		return true;
8459 	}
8460 }
8461 
8462 // Remove the window style
RemoveExStyle(HWND hWnd,UINT id,UINT style)8463 void RemoveExStyle(HWND hWnd, UINT id, UINT style)
8464 {
8465 	UINT old;
8466 	// Validate arguments
8467 	if (hWnd == NULL)
8468 	{
8469 		return;
8470 	}
8471 
8472 	old = GetExStyle(hWnd, id);
8473 	if ((old & style) == 0)
8474 	{
8475 		return;
8476 	}
8477 
8478 	SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old & ~style);
8479 	Refresh(DlgItem(hWnd, id));
8480 }
8481 
8482 // Set the window style
SetExStyle(HWND hWnd,UINT id,UINT style)8483 void SetExStyle(HWND hWnd, UINT id, UINT style)
8484 {
8485 	UINT old;
8486 	// Validate arguments
8487 	if (hWnd == NULL)
8488 	{
8489 		return;
8490 	}
8491 
8492 	old = GetExStyle(hWnd, id);
8493 	if (old & style)
8494 	{
8495 		return;
8496 	}
8497 
8498 	SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old | style);
8499 	Refresh(DlgItem(hWnd, id));
8500 }
8501 
8502 // Get the window style
GetExStyle(HWND hWnd,UINT id)8503 UINT GetExStyle(HWND hWnd, UINT id)
8504 {
8505 	// Validate arguments
8506 	if (hWnd == NULL)
8507 	{
8508 		return 0;
8509 	}
8510 
8511 	return GetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE);
8512 }
8513 
8514 // Remove the window style
RemoveStyle(HWND hWnd,UINT id,UINT style)8515 void RemoveStyle(HWND hWnd, UINT id, UINT style)
8516 {
8517 	UINT old;
8518 	// Validate arguments
8519 	if (hWnd == NULL)
8520 	{
8521 		return;
8522 	}
8523 
8524 	old = GetStyle(hWnd, id);
8525 	if ((old & style) == 0)
8526 	{
8527 		return;
8528 	}
8529 
8530 	SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old & ~style);
8531 	Refresh(DlgItem(hWnd, id));
8532 }
8533 
8534 // Set the window style
SetStyle(HWND hWnd,UINT id,UINT style)8535 void SetStyle(HWND hWnd, UINT id, UINT style)
8536 {
8537 	UINT old;
8538 	// Validate arguments
8539 	if (hWnd == NULL)
8540 	{
8541 		return;
8542 	}
8543 
8544 	old = GetStyle(hWnd, id);
8545 	if (old & style)
8546 	{
8547 		return;
8548 	}
8549 
8550 	SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old | style);
8551 	Refresh(DlgItem(hWnd, id));
8552 }
8553 
8554 // Get the window style
GetStyle(HWND hWnd,UINT id)8555 UINT GetStyle(HWND hWnd, UINT id)
8556 {
8557 	// Validate arguments
8558 	if (hWnd == NULL)
8559 	{
8560 		return 0;
8561 	}
8562 
8563 	return GetWindowLong(DlgItem(hWnd, id), GWL_STYLE);
8564 }
8565 
8566 // Get the number of characters in the text
GetTextLen(HWND hWnd,UINT id,bool unicode)8567 UINT GetTextLen(HWND hWnd, UINT id, bool unicode)
8568 {
8569 	wchar_t *s;
8570 	UINT ret;
8571 	// Validate arguments
8572 	if (hWnd == NULL)
8573 	{
8574 		return 0;
8575 	}
8576 
8577 	s = GetText(hWnd, id);
8578 	if (s == NULL)
8579 	{
8580 		return 0;
8581 	}
8582 
8583 	if (unicode)
8584 	{
8585 		ret = UniStrLen(s);
8586 	}
8587 	else
8588 	{
8589 		char *tmp = CopyUniToStr(s);
8590 		ret = StrLen(tmp);
8591 		Free(tmp);
8592 	}
8593 
8594 	Free(s);
8595 
8596 	return ret;
8597 }
8598 
8599 // Check whether the text is blank
IsEmpty(HWND hWnd,UINT id)8600 bool IsEmpty(HWND hWnd, UINT id)
8601 {
8602 	bool ret;
8603 	wchar_t *s;
8604 	// Validate arguments
8605 	if (hWnd == NULL)
8606 	{
8607 		return true;
8608 	}
8609 
8610 	s = GetText(hWnd, id);
8611 
8612 	UniTrim(s);
8613 	if (UniStrLen(s) == 0)
8614 	{
8615 		ret = true;
8616 	}
8617 	else
8618 	{
8619 		ret = false;
8620 	}
8621 
8622 	Free(s);
8623 
8624 	return ret;
8625 }
8626 
8627 // Get the window class
GetClass(HWND hWnd,UINT id)8628 wchar_t *GetClass(HWND hWnd, UINT id)
8629 {
8630 	wchar_t tmp[MAX_SIZE];
8631 
8632 	// Validate arguments
8633 	if (hWnd == NULL)
8634 	{
8635 		return CopyUniStr(L"");
8636 	}
8637 
8638 	GetClassNameW(DlgItem(hWnd, id), tmp, sizeof(tmp));
8639 
8640 	return UniCopyStr(tmp);
8641 }
GetClassA(HWND hWnd,UINT id)8642 char *GetClassA(HWND hWnd, UINT id)
8643 {
8644 	char tmp[MAX_SIZE];
8645 	// Validate arguments
8646 	if (hWnd == NULL)
8647 	{
8648 		return CopyStr("");
8649 	}
8650 
8651 	GetClassName(DlgItem(hWnd, id), tmp, sizeof(tmp));
8652 
8653 	return CopyStr(tmp);
8654 }
8655 
8656 // Transmit a message to the control
SendMsg(HWND hWnd,UINT id,UINT msg,WPARAM wParam,LPARAM lParam)8657 UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam)
8658 {
8659 	// Validate arguments
8660 	if (hWnd == NULL)
8661 	{
8662 		return 0;
8663 	}
8664 
8665 	return (UINT)SendMessageW(DlgItem(hWnd, id), msg, wParam, lParam);
8666 }
8667 
8668 // Move the cursor to the right edge of the text in the EDIT
SetCursorOnRight(HWND hWnd,UINT id)8669 void SetCursorOnRight(HWND hWnd, UINT id)
8670 {
8671 	wchar_t *class_name;
8672 	// Validate arguments
8673 	if (hWnd == NULL)
8674 	{
8675 		return;
8676 	}
8677 
8678 	class_name = GetClass(hWnd, id);
8679 
8680 	if (class_name != NULL)
8681 	{
8682 		if (UniStrCmpi(class_name, L"edit") == 0)
8683 		{
8684 			wchar_t *str = GetText(hWnd, id);
8685 
8686 			if (str != NULL)
8687 			{
8688 				UINT len = UniStrLen(str);
8689 
8690 				SendMsg(hWnd, id, EM_SETSEL, len, len);
8691 
8692 				Free(str);
8693 			}
8694 		}
8695 		Free(class_name);
8696 	}
8697 }
8698 
8699 // Select entire the text in the EDIT
SelectEdit(HWND hWnd,UINT id)8700 void SelectEdit(HWND hWnd, UINT id)
8701 {
8702 	wchar_t *class_name;
8703 
8704 	// Validate arguments
8705 	if (hWnd == NULL)
8706 	{
8707 		return;
8708 	}
8709 
8710 	class_name = GetClass(hWnd, id);
8711 
8712 	if (class_name != NULL)
8713 	{
8714 		if (UniStrCmpi(class_name, L"edit") == 0)
8715 		{
8716 			SendMsg(hWnd, id, EM_SETSEL, 0, -1);
8717 		}
8718 		Free(class_name);
8719 	}
8720 }
8721 
8722 // Deselect the text of EDIT
UnselectEdit(HWND hWnd,UINT id)8723 void UnselectEdit(HWND hWnd, UINT id)
8724 {
8725 	wchar_t *class_name;
8726 
8727 	// Validate arguments
8728 	if (hWnd == NULL)
8729 	{
8730 		return;
8731 	}
8732 
8733 	class_name = GetClass(hWnd, id);
8734 
8735 	if (class_name != NULL)
8736 	{
8737 		if (UniStrCmpi(class_name, L"edit") == 0)
8738 		{
8739 			SendMsg(hWnd, id, EM_SETSEL, -1, 0);
8740 		}
8741 		Free(class_name);
8742 	}
8743 }
8744 
8745 // Select all by setting the focus to the EDIT
FocusEx(HWND hWnd,UINT id)8746 void FocusEx(HWND hWnd, UINT id)
8747 {
8748 	// Validate arguments
8749 	if (hWnd == NULL)
8750 	{
8751 		return;
8752 	}
8753 
8754 	if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)
8755 	{
8756 		return;
8757 	}
8758 
8759 	SelectEdit(hWnd, id);
8760 
8761 	Focus(hWnd, id);
8762 }
8763 
8764 // Get whether the specified window has focus
IsFocus(HWND hWnd,UINT id)8765 bool IsFocus(HWND hWnd, UINT id)
8766 {
8767 	// Validate arguments
8768 	if (hWnd == NULL)
8769 	{
8770 		return false;
8771 	}
8772 
8773 	if (GetFocus() == DlgItem(hWnd, id))
8774 	{
8775 		return true;
8776 	}
8777 
8778 	return false;
8779 }
8780 
8781 // Set the focus
Focus(HWND hWnd,UINT id)8782 void Focus(HWND hWnd, UINT id)
8783 {
8784 	// Validate arguments
8785 	if (hWnd == NULL)
8786 	{
8787 		return;
8788 	}
8789 
8790 	if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)
8791 	{
8792 		return;
8793 	}
8794 
8795 	SetFocus(DlgItem(hWnd, id));
8796 }
8797 
8798 // Set the value of the int type
SetInt(HWND hWnd,UINT id,UINT value)8799 void SetInt(HWND hWnd, UINT id, UINT value)
8800 {
8801 	wchar_t tmp[MAX_SIZE];
8802 	// Validate arguments
8803 	if (hWnd == NULL)
8804 	{
8805 		return;
8806 	}
8807 
8808 	UniToStru(tmp, value);
8809 	SetText(hWnd, id, tmp);
8810 }
SetIntEx(HWND hWnd,UINT id,UINT value)8811 void SetIntEx(HWND hWnd, UINT id, UINT value)
8812 {
8813 	// Validate arguments
8814 	if (hWnd == NULL)
8815 	{
8816 		return;
8817 	}
8818 
8819 	if (value == 0)
8820 	{
8821 		// Leave blank in the case of 0
8822 		SetText(hWnd, id, L"");
8823 	}
8824 	else
8825 	{
8826 		SetInt(hWnd, id, value);
8827 	}
8828 }
8829 
8830 // Get the value of the int type
GetInt(HWND hWnd,UINT id)8831 UINT GetInt(HWND hWnd, UINT id)
8832 {
8833 	wchar_t *s;
8834 	UINT ret;
8835 	// Validate arguments
8836 	if (hWnd == NULL)
8837 	{
8838 		return 0;
8839 	}
8840 
8841 	s = GetText(hWnd, id);
8842 	if (s == NULL)
8843 	{
8844 		return 0;
8845 	}
8846 
8847 	ret = UniToInt(s);
8848 	Free(s);
8849 
8850 	return ret;
8851 }
8852 
8853 // Update the window appearance
Refresh(HWND hWnd)8854 void Refresh(HWND hWnd)
8855 {
8856 	HWND parent;
8857 	// Validate arguments
8858 	if (hWnd == NULL)
8859 	{
8860 		return;
8861 	}
8862 
8863 	DoEvents(hWnd);
8864 	UpdateWindow(hWnd);
8865 	DoEvents(hWnd);
8866 
8867 	parent = GetParent(hWnd);
8868 	if (parent != NULL)
8869 	{
8870 		Refresh(parent);
8871 	}
8872 }
8873 
8874 // Handle the event
DoEvents(HWND hWnd)8875 void DoEvents(HWND hWnd)
8876 {
8877 	MSG msg;
8878 
8879 	if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
8880 	{
8881 		TranslateMessage(&msg);
8882 		DispatchMessage(&msg);
8883 	}
8884 	UpdateWindow(hWnd);
8885 
8886 	if (hWnd)
8887 	{
8888 		DoEvents(NULL);
8889 	}
8890 }
8891 
8892 // Close the window
Close(HWND hWnd)8893 void Close(HWND hWnd)
8894 {
8895 	// Validate arguments
8896 	if (hWnd == NULL)
8897 	{
8898 		return;
8899 	}
8900 
8901 	SendMessage(hWnd, WM_CLOSE, 0, 0);
8902 }
8903 
8904 // Disable the window
Disable(HWND hWnd,UINT id)8905 void Disable(HWND hWnd, UINT id)
8906 {
8907 	SetEnable(hWnd, id, false);
8908 }
8909 
8910 // Enable the window
Enable(HWND hWnd,UINT id)8911 void Enable(HWND hWnd, UINT id)
8912 {
8913 	SetEnable(hWnd, id, true);
8914 }
8915 
8916 // Set the enabled state of a window
SetEnable(HWND hWnd,UINT id,bool b)8917 void SetEnable(HWND hWnd, UINT id, bool b)
8918 {
8919 	// Validate arguments
8920 	if (hWnd == NULL)
8921 	{
8922 		return;
8923 	}
8924 
8925 	if (b == false)
8926 	{
8927 		if (IsEnable(hWnd, id))
8928 		{
8929 			if (id != 0 && IsFocus(hWnd, id))
8930 			{
8931 				Focus(hWnd, IDCANCEL);
8932 				Focus(hWnd, IDOK);
8933 			}
8934 			EnableWindow(DlgItem(hWnd, id), false);
8935 			Refresh(DlgItem(hWnd, id));
8936 		}
8937 	}
8938 	else
8939 	{
8940 		if (IsDisable(hWnd, id))
8941 		{
8942 			EnableWindow(DlgItem(hWnd, id), true);
8943 			Refresh(DlgItem(hWnd, id));
8944 		}
8945 	}
8946 }
8947 
8948 // Examine whether the window is disabled
IsDisable(HWND hWnd,UINT id)8949 bool IsDisable(HWND hWnd, UINT id)
8950 {
8951 	return IsEnable(hWnd, id) ? false : true;
8952 }
8953 
8954 // Examine whether the window is enabled
IsEnable(HWND hWnd,UINT id)8955 bool IsEnable(HWND hWnd, UINT id)
8956 {
8957 	// Validate arguments
8958 	if (hWnd == NULL)
8959 	{
8960 		return false;
8961 	}
8962 
8963 	return IsWindowEnabled(DlgItem(hWnd, id));
8964 }
8965 
8966 // If the control protrude by large font size, adjust into appropriate size
AdjustFontSize(HWND hWnd,UINT id)8967 void AdjustFontSize(HWND hWnd, UINT id)
8968 {
8969 	char class_name[MAX_PATH];
8970 	UINT style;
8971 	UINT format = 0;
8972 	HFONT current_font;
8973 	FONT font;
8974 	wchar_t *text;
8975 	RECT rect;
8976 	UINT width, height;
8977 	HFONT new_font = NULL;
8978 	UINT old_font_size;
8979 	UINT style1;
8980 	// Validate arguments
8981 	if (hWnd == NULL)
8982 	{
8983 		return;
8984 	}
8985 
8986 	hWnd = DlgItem(hWnd, id);
8987 
8988 	if (GetClassNameA(hWnd, class_name, sizeof(class_name)) == 0)
8989 	{
8990 		return;
8991 	}
8992 
8993 	if (StrCmpi(class_name, "static") != 0)
8994 	{
8995 		return;
8996 	}
8997 
8998 	style = GetStyle(hWnd, 0);
8999 
9000 	if ((style & SS_ENDELLIPSIS) || (style & SS_PATHELLIPSIS))
9001 	{
9002 		return;
9003 	}
9004 
9005 	style1 = style & 0x0F;
9006 
9007 	// Create a format for DrawText
9008 	if (style1 == SS_RIGHT)
9009 	{
9010 		// Right justification
9011 		format |= DT_RIGHT;
9012 	}
9013 	else if (style1 == SS_CENTER)
9014 	{
9015 		// Center justification
9016 		format |= DT_CENTER;
9017 	}
9018 	else if (style1 == SS_LEFT)
9019 	{
9020 		// Left justification
9021 		format |= DT_LEFT;
9022 	}
9023 	else
9024 	{
9025 		// Others
9026 		return;
9027 	}
9028 
9029 	if (style & DT_NOPREFIX)
9030 	{
9031 		// Without prefix
9032 		format |= DT_NOPREFIX;
9033 	}
9034 
9035 	// Get the font parameters currently set
9036 	current_font = (HFONT)SendMessageA(hWnd, WM_GETFONT, 0, 0);
9037 	if (current_font == NULL)
9038 	{
9039 		return;
9040 	}
9041 
9042 	Zero(&font, sizeof(font));
9043 	if (GetFontParam(current_font, &font) == false)
9044 	{
9045 		return;
9046 	}
9047 
9048 	// Get the size of the static area
9049 	Zero(&rect, sizeof(rect));
9050 	if (GetWindowRect(hWnd, &rect) == false)
9051 	{
9052 		return;
9053 	}
9054 
9055 	// Get the text that is currently set
9056 	text = GetText(hWnd, 0);
9057 	if (text == NULL)
9058 	{
9059 		return;
9060 	}
9061 
9062 	if (IsEmptyUniStr(text))
9063 	{
9064 		Free(text);
9065 		return;
9066 	}
9067 
9068 	width = GET_ABS(rect.right - rect.left);
9069 	height = GET_ABS(rect.bottom - rect.top);
9070 
9071 	new_font = NULL;
9072 	old_font_size = font.Size;
9073 
9074 	// Try to gradually reduce the font size until drawing succeeds
9075 	while (font.Size != 0)
9076 	{
9077 		// Drawing test
9078 		bool aborted = false;
9079 
9080 		if (IsFontFitInRect(&font, width, height, text, format, &aborted))
9081 		{
9082 			// Drawing success
9083 			if (old_font_size != font.Size)
9084 			{
9085 				// Font size is changed
9086 				new_font = GetFont(font.Name, font.Size, font.Bold, font.Italic, font.UnderLine, font.StrikeOut);
9087 			}
9088 			break;
9089 		}
9090 		else
9091 		{
9092 			if (aborted)
9093 			{
9094 				// Fatal error
9095 				break;
9096 			}
9097 		}
9098 
9099 		font.Size--;
9100 
9101 		if (font.Size == 1)
9102 		{
9103 			// Not supposed to become a font size like this. Fatal error
9104 			break;
9105 		}
9106 	}
9107 
9108 	Free(text);
9109 
9110 	if (new_font != NULL)
9111 	{
9112 		// Change the font size
9113 		SetFontEx(hWnd, 0, new_font, true);
9114 	}
9115 }
9116 
9117 // Check whether the specified string can be drawn in the specified area with the specified font
IsFontFitInRect(struct FONT * f,UINT width,UINT height,wchar_t * text,UINT format,bool * aborted)9118 bool IsFontFitInRect(struct FONT *f, UINT width, UINT height, wchar_t *text, UINT format, bool *aborted)
9119 {
9120 	RECT r;
9121 	int i;
9122 	bool dummy_bool;
9123 	UINT new_height;
9124 	HFONT hCreatedFont, hOldFont;
9125 	// Validate arguments
9126 	if (f == NULL || text == NULL)
9127 	{
9128 		return false;
9129 	}
9130 	if (aborted == NULL)
9131 	{
9132 		aborted = &dummy_bool;
9133 	}
9134 
9135 	format |= DT_CALCRECT | DT_WORDBREAK;
9136 
9137 	*aborted = false;
9138 
9139 	// Create a font
9140 	hCreatedFont = GetFont(f->Name, f->Size, f->Bold, f->Italic, f->UnderLine, f->StrikeOut);
9141 	if (hCreatedFont == NULL)
9142 	{
9143 		*aborted = true;
9144 		return false;
9145 	}
9146 
9147 	Lock(lock_common_dc);
9148 	{
9149 		hOldFont = SelectObject(hCommonDC, hCreatedFont);
9150 
9151 		Zero(&r, sizeof(r));
9152 		r.left = r.top = 0;
9153 		r.right = width;
9154 		r.bottom = height;
9155 
9156 		i = DrawTextW(hCommonDC, text, -1, &r, format);
9157 
9158 		SelectObject(hCommonDC, hOldFont);
9159 	}
9160 	Unlock(lock_common_dc);
9161 
9162 	if (i == 0)
9163 	{
9164 		*aborted = true;
9165 		return false;
9166 	}
9167 
9168 	new_height = GET_ABS(r.bottom - r.top);
9169 
9170 	if (new_height > height)
9171 	{
9172 		return false;
9173 	}
9174 
9175 	return true;
9176 }
9177 
9178 // Set a text string
SetText(HWND hWnd,UINT id,wchar_t * str)9179 void SetText(HWND hWnd, UINT id, wchar_t *str)
9180 {
9181 	// Validate arguments
9182 	if (hWnd == NULL || str == NULL)
9183 	{
9184 		return;
9185 	}
9186 
9187 	SetTextInner(hWnd, id, str);
9188 }
SetTextInner(HWND hWnd,UINT id,wchar_t * str)9189 void SetTextInner(HWND hWnd, UINT id, wchar_t *str)
9190 {
9191 	wchar_t *old;
9192 	// Validate arguments
9193 	if (hWnd == NULL || str == NULL)
9194 	{
9195 		return;
9196 	}
9197 
9198 	// Get the old string
9199 	old = GetText(hWnd, id);
9200 	if (UniStrCmp(str, old) == 0)
9201 	{
9202 		// Identity
9203 		Free(old);
9204 		return;
9205 	}
9206 
9207 	Free(old);
9208 
9209 	SetWindowTextW(DlgItem(hWnd, id), str);
9210 
9211 	AdjustFontSize(hWnd, id);
9212 
9213 	if (id != 0)
9214 	{
9215 		Refresh(DlgItem(hWnd, id));
9216 	}
9217 }
SetTextA(HWND hWnd,UINT id,char * str)9218 void SetTextA(HWND hWnd, UINT id, char *str)
9219 {
9220 	wchar_t *s;
9221 	// Validate arguments
9222 	if (hWnd == NULL || str == NULL)
9223 	{
9224 		return;
9225 	}
9226 
9227 	s = CopyStrToUni(str);
9228 	if (s == NULL)
9229 	{
9230 		return;
9231 	}
9232 
9233 	SetText(hWnd, id, s);
9234 
9235 	Free(s);
9236 }
9237 
9238 // Get the text string to the buffer
GetTxt(HWND hWnd,UINT id,wchar_t * str,UINT size)9239 bool GetTxt(HWND hWnd, UINT id, wchar_t *str, UINT size)
9240 {
9241 	wchar_t *s;
9242 	// Validate arguments
9243 	if (hWnd == NULL || str == NULL)
9244 	{
9245 		return false;
9246 	}
9247 
9248 	s = GetText(hWnd, id);
9249 	if (s == NULL)
9250 	{
9251 		UniStrCpy(str, size, L"");
9252 		return false;
9253 	}
9254 
9255 	UniStrCpy(str, size, s);
9256 	Free(s);
9257 
9258 	return true;
9259 }
GetTxtA(HWND hWnd,UINT id,char * str,UINT size)9260 bool GetTxtA(HWND hWnd, UINT id, char *str, UINT size)
9261 {
9262 	char *s;
9263 	// Validate arguments
9264 	if (hWnd == NULL || str == NULL)
9265 	{
9266 		return false;
9267 	}
9268 
9269 	s = GetTextA(hWnd, id);
9270 	if (s == NULL)
9271 	{
9272 		StrCpy(str, size, "");
9273 		return false;
9274 	}
9275 
9276 	StrCpy(str, size, s);
9277 	Free(s);
9278 
9279 	return true;
9280 }
9281 
9282 // Get the text string
GetText(HWND hWnd,UINT id)9283 wchar_t *GetText(HWND hWnd, UINT id)
9284 {
9285 	wchar_t *ret;
9286 	UINT size, len;
9287 	// Validate arguments
9288 	if (hWnd == NULL)
9289 	{
9290 		return NULL;
9291 	}
9292 
9293 	len = GetWindowTextLengthW(DlgItem(hWnd, id));
9294 	if (len == 0)
9295 	{
9296 		return CopyUniStr(L"");
9297 	}
9298 
9299 	size = (len + 1) * 2;
9300 	ret = ZeroMallocEx(size, true);
9301 
9302 	GetWindowTextW(DlgItem(hWnd, id), ret, size);
9303 
9304 	return ret;
9305 }
GetTextA(HWND hWnd,UINT id)9306 char *GetTextA(HWND hWnd, UINT id)
9307 {
9308 	char *ret;
9309 	UINT size, len;
9310 	// Validate arguments
9311 	if (hWnd == NULL)
9312 	{
9313 		return NULL;
9314 	}
9315 
9316 	len = GetWindowTextLengthA(DlgItem(hWnd, id));
9317 	if (len == 0)
9318 	{
9319 		return CopyStr("");
9320 	}
9321 
9322 	size = len + 1;
9323 	ret = ZeroMallocEx(size, true);
9324 
9325 	GetWindowTextA(DlgItem(hWnd, id), ret, size);
9326 
9327 	return ret;
9328 }
9329 
9330 // Get the item in the dialog
DlgItem(HWND hWnd,UINT id)9331 HWND DlgItem(HWND hWnd, UINT id)
9332 {
9333 	// Validate arguments
9334 	if (hWnd == NULL)
9335 	{
9336 		return NULL;
9337 	}
9338 
9339 	if (id == 0)
9340 	{
9341 		return hWnd;
9342 	}
9343 	else
9344 	{
9345 		return GetDlgItem(hWnd, id);
9346 	}
9347 }
9348 
9349 // Initialize the WinUi
InitWinUi(wchar_t * software_name,char * font,UINT fontsize)9350 void InitWinUi(wchar_t *software_name, char *font, UINT fontsize)
9351 {
9352 	if (tls_current_wizard == 0xffffffff)
9353 	{
9354 		tls_current_wizard = TlsAlloc();
9355 	}
9356 
9357 	if ((init_winui_counter++) != 0)
9358 	{
9359 		return;
9360 	}
9361 
9362 	if (hDll != NULL)
9363 	{
9364 		return;
9365 	}
9366 
9367 	if (MayaquaIsMinimalMode() == false)
9368 	{
9369 		if (Is64())
9370 		{
9371 			hDll = MsLoadLibraryAsDataFile(PENCORE_DLL_NAME);
9372 		}
9373 		else
9374 		{
9375 			hDll = MsLoadLibrary(PENCORE_DLL_NAME);
9376 		}
9377 
9378 		if (hDll == NULL)
9379 		{
9380 			Alert(PENCORE_DLL_NAME " not found. "CEDAR_PRODUCT_STR " VPN couldn't start.\r\n\r\n"
9381 				"Please reinstall all files with "CEDAR_PRODUCT_STR " VPN Installer.",
9382 				NULL);
9383 			exit(0);
9384 		}
9385 	}
9386 	else
9387 	{
9388 		hDll = LoadLibrary(MsGetExeFileName());
9389 
9390 		if (hDll == NULL)
9391 		{
9392 			Alert("MsLoadLibrary() Error.",
9393 				NULL);
9394 			exit(0);
9395 		}
9396 	}
9397 
9398 	if (software_name != NULL)
9399 	{
9400 		title_bar = CopyUniStr(software_name);
9401 	}
9402 	else
9403 	{
9404 		title_bar = CopyUniStr(CEDAR_PRODUCT_STR_W L" VPN");
9405 	}
9406 
9407 	if (font != NULL)
9408 	{
9409 		font_name = CopyStr(font);
9410 	}
9411 	else
9412 	{
9413 		font_name = CopyStr(_SS("DEFAULT_FONT"));
9414 	}
9415 
9416 	if (MsIsWindows7())
9417 	{
9418 		char *win7_font = _SS("DEFAULT_FONT_WIN7");
9419 
9420 		if (IsEmptyStr(win7_font) == false)
9421 		{
9422 			Free(font_name);
9423 			font_name = CopyStr(win7_font);
9424 		}
9425 
9426 		if (GetTextScalingFactor() >= 1.44)
9427 		{
9428 			// Use a substitute font in the case of high-DPI in Windows 7 and later
9429 			char *alternative_font = _SS("DEFAULT_FONT_HIGHDPI");
9430 
9431 			if (IsEmptyStr(alternative_font) == false)
9432 			{
9433 				Free(font_name);
9434 				font_name = CopyStr(alternative_font);
9435 			}
9436 		}
9437 	}
9438 
9439 	if (fontsize != 0)
9440 	{
9441 		font_size = fontsize;
9442 	}
9443 	else
9444 	{
9445 		font_size = _II("DEFAULT_FONT_SIZE");
9446 		if (font_size == 0)
9447 		{
9448 			font_size = 9;
9449 		}
9450 	}
9451 
9452 	lock_common_dc = NewLock();
9453 
9454 	hCommonDC = CreateCompatibleDC(NULL);
9455 
9456 	InitIconCache();
9457 
9458 	InitFont();
9459 
9460 	InitImageList();
9461 }
9462 
9463 // Release the WinUi
FreeWinUi()9464 void FreeWinUi()
9465 {
9466 	if ((--init_winui_counter) != 0)
9467 	{
9468 		return;
9469 	}
9470 
9471 	if (hDll == NULL)
9472 	{
9473 		return;
9474 	}
9475 
9476 	FreeImageList();
9477 
9478 	FreeFont();
9479 
9480 	FreeIconCache();
9481 
9482 	FreeLibrary(hDll);
9483 	hDll = NULL;
9484 
9485 	Free(title_bar);
9486 	title_bar = NULL;
9487 
9488 	Free(font_name);
9489 	font_name = NULL;
9490 
9491 	if (hCommonDC != NULL)
9492 	{
9493 		DeleteDC(hCommonDC);
9494 		hCommonDC = NULL;
9495 	}
9496 
9497 	DeleteLock(lock_common_dc);
9498 	lock_common_dc = NULL;
9499 }
9500 
9501 #endif	// WIN32
9502