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