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