2017-10-19 05:48:23 +03:00
|
|
|
// SoftEther VPN Source Code - Developer Edition Master Branch
|
2014-01-04 17:00:08 +04:00
|
|
|
// Cedar Communication Module
|
|
|
|
|
|
|
|
|
|
|
|
// WinUi.c
|
|
|
|
// User interface code for Win32
|
|
|
|
|
2021-04-05 05:48:25 +03:00
|
|
|
#ifdef OS_WIN32
|
|
|
|
|
|
|
|
#define WINUI_C
|
|
|
|
|
|
|
|
#include "WinUi.h"
|
|
|
|
|
|
|
|
#include "Client.h"
|
|
|
|
#include "CM.h"
|
|
|
|
#include "Protocol.h"
|
|
|
|
#include "Session.h"
|
|
|
|
#include "Win32Com.h"
|
|
|
|
|
|
|
|
#include "Mayaqua/FileIO.h"
|
|
|
|
#include "Mayaqua/Internat.h"
|
|
|
|
#include "Mayaqua/Microsoft.h"
|
|
|
|
#include "Mayaqua/Memory.h"
|
|
|
|
#include "Mayaqua/Object.h"
|
|
|
|
#include "Mayaqua/Pack.h"
|
|
|
|
#include "Mayaqua/Secure.h"
|
|
|
|
#include "Mayaqua/Str.h"
|
|
|
|
#include "Mayaqua/Table.h"
|
|
|
|
#include "Mayaqua/Tick64.h"
|
|
|
|
#include "Mayaqua/Win32.h"
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-05 05:48:25 +03:00
|
|
|
#include "../PenCore/resource.h"
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-05 05:48:25 +03:00
|
|
|
#include <commdlg.h>
|
|
|
|
#include <shellapi.h>
|
2014-01-04 17:00:08 +04:00
|
|
|
#include <shlobj.h>
|
2021-04-05 05:48:25 +03:00
|
|
|
|
2021-09-24 12:12:51 +03:00
|
|
|
#include <openssl/evp.h>
|
|
|
|
#include <openssl/ec.h>
|
|
|
|
|
2021-04-05 05:48:25 +03:00
|
|
|
// Process name list of incompatible anti-virus software
|
|
|
|
static BAD_PROCESS bad_processes[] =
|
|
|
|
{
|
|
|
|
{"nod32krn.exe", "NOD32 Antivirus"},
|
|
|
|
{"avp.exe", "Kaspersky"}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const UINT num_bad_processes = sizeof(bad_processes) / sizeof(bad_processes[0]);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
char cached_pin_code[MAX_SIZE] = {0};
|
|
|
|
UINT64 cached_pin_code_expires = 0;
|
|
|
|
|
|
|
|
static HINSTANCE hDll = NULL;
|
|
|
|
static wchar_t *title_bar = NULL;
|
|
|
|
static char *font_name = NULL;
|
|
|
|
static UINT font_size = 9;
|
|
|
|
static HIMAGELIST large_image_list = NULL, small_image_list = NULL;
|
|
|
|
static LIST *icon_list = NULL;
|
|
|
|
static HINSTANCE hMsHtml = NULL;
|
|
|
|
static UINT init_winui_counter = 0;
|
|
|
|
static HDC hCommonDC = NULL;
|
|
|
|
static LOCK *lock_common_dc = NULL;
|
|
|
|
|
|
|
|
bool UseAlpha = false;
|
|
|
|
UINT AlphaValue = 100;
|
|
|
|
|
|
|
|
static THREAD *led_thread = NULL;
|
|
|
|
static bool thread_stop = false;
|
|
|
|
static bool g_led_special = false;
|
|
|
|
static bool g_tcpip_topmost = false;
|
|
|
|
static DWORD tls_current_wizard = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
#define WINUI_PSM_SHOWWIZBUTTONS (WM_USER + 138)
|
|
|
|
#define WINUI_PropSheet_ShowWizButtons(hDlg, dwFlag, dwButton) \
|
|
|
|
PSTMSG(hDlg, WINUI_PSM_SHOWWIZBUTTONS, (WPARAM)(dwFlag), (LPARAM)(dwButton))
|
|
|
|
|
|
|
|
typedef struct _WINUI_SHSTOCKICONINFO
|
|
|
|
{
|
|
|
|
DWORD cbSize;
|
|
|
|
HICON hIcon;
|
|
|
|
int iSysImageIndex;
|
|
|
|
int iIcon;
|
|
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
} WINUI_SHSTOCKICONINFO;
|
|
|
|
|
|
|
|
// Get whether the current process is foreground
|
|
|
|
bool IsThisProcessForeground()
|
|
|
|
{
|
|
|
|
HWND hWnd = GetForegroundWindow();
|
|
|
|
DWORD proc_id, thread_id;
|
|
|
|
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
proc_id = 0;
|
|
|
|
thread_id = GetWindowThreadProcessId(hWnd, &proc_id);
|
|
|
|
|
|
|
|
if (proc_id == MsGetCurrentProcessId())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool IsThisProcessForegroundForUpdateUi(UPDATE_CLIENT *c, void *p)
|
|
|
|
{
|
|
|
|
return IsThisProcessForeground();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update notification screen dialog procedure
|
|
|
|
UINT UpdateConfigDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
WINUI_UPDATE *u = (WINUI_UPDATE *)param;
|
|
|
|
UPDATE_CLIENT_SETTING s;
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetTimer(hWnd, 1, 100, NULL);
|
|
|
|
|
|
|
|
LoadUpdateUiSetting(u, &s);
|
|
|
|
|
|
|
|
Check(hWnd, S_ENABLE, s.DisableCheck == false);
|
2018-05-17 00:47:10 +03:00
|
|
|
Check(hWnd, S_DISABLE, s.DisableCheck);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
DlgFont(hWnd, S_TITLE, 10, true);
|
|
|
|
FormatText(hWnd, S_TITLE, u->SoftwareTitle);
|
|
|
|
FormatText(hWnd, S_INFO, u->SoftwareTitle);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if (u->UpdateClient->HaltFlag)
|
|
|
|
{
|
|
|
|
goto LABEL_CLOSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
LABEL_CLOSE:
|
|
|
|
LoadUpdateUiSetting(u, &s);
|
|
|
|
|
2018-05-17 00:47:10 +03:00
|
|
|
s.DisableCheck = IsChecked(hWnd, S_DISABLE);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
if (s.DisableCheck)
|
|
|
|
{
|
|
|
|
s.LatestIgnoreBuild = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SaveUpdateUiSetting(u, &s);
|
|
|
|
|
|
|
|
SetUpdateClientSetting(u->UpdateClient, &s);
|
|
|
|
|
|
|
|
EndDialog(hWnd, !s.DisableCheck);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the update notification setting screen
|
|
|
|
bool ConfigUpdateUi(WINUI_UPDATE *u, HWND hWnd)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (u == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Dialog(hWnd, D_UPDATE_CONFIG, UpdateConfigDlgProc, u);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update notification dialog procedure
|
|
|
|
UINT UpdateNoticeDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
WINUI_UPDATE_DLG_PARAM *p = (WINUI_UPDATE_DLG_PARAM *)param;
|
|
|
|
WINUI_UPDATE *u = NULL;
|
|
|
|
UPDATE_CLIENT_SETTING s;
|
|
|
|
char date_current[64];
|
|
|
|
char date_latest[64];
|
|
|
|
wchar_t date_current_str[128];
|
|
|
|
wchar_t date_latest_str[128];
|
|
|
|
char *font_name = NULL;
|
|
|
|
|
|
|
|
if (p != NULL)
|
|
|
|
{
|
|
|
|
u = p->Update;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
Zero(date_current_str, sizeof(date_current_str));
|
|
|
|
Zero(date_latest_str, sizeof(date_latest_str));
|
|
|
|
|
|
|
|
GetDateStr64(date_current, sizeof(date_current), u->CurrentDate);
|
|
|
|
if (u->CurrentDate != 0)
|
|
|
|
{
|
|
|
|
UniFormat(date_current_str, sizeof(date_current_str), _UU("DLG_UPDATE_DATE"), date_current);
|
|
|
|
}
|
|
|
|
|
|
|
|
GetDateStr64(date_latest, sizeof(date_latest), p->LatestDate);
|
|
|
|
if (p->LatestDate != 0)
|
|
|
|
{
|
|
|
|
UniFormat(date_latest_str, sizeof(date_latest_str), _UU("DLG_UPDATE_DATE"), date_latest);
|
|
|
|
}
|
|
|
|
|
|
|
|
FormatText(hWnd, 0, u->UpdateClient->SoftwareTitle);
|
|
|
|
FormatText(hWnd, S_INFO, u->UpdateClient->SoftwareTitle);
|
|
|
|
SetText(hWnd, S_PRODUCT_STR, u->UpdateClient->SoftwareTitle);
|
|
|
|
|
|
|
|
FormatText(hWnd, S_CURRENT_STR, u->CurrentVer / 100, u->CurrentVer % 100, u->CurrentBuild, date_current_str);
|
|
|
|
FormatText(hWnd, S_LATEST_STR, p->LatestVer, date_latest_str);
|
|
|
|
|
|
|
|
if (MsIsWindows7())
|
|
|
|
{
|
|
|
|
if (_GETLANG() == 0)
|
|
|
|
{
|
|
|
|
font_name = GetMeiryoFontName();
|
|
|
|
}
|
|
|
|
else if (_GETLANG() == 2)
|
|
|
|
{
|
|
|
|
font_name = "Microsoft YaHei";
|
|
|
|
}
|
2017-12-02 01:04:57 +03:00
|
|
|
else if (_GETLANG() == 3)
|
|
|
|
{
|
|
|
|
font_name = "Microsoft JhengHei";
|
|
|
|
}
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
SetFont(hWnd, S_INFO, GetFont(font_name, 11, false, false, false, false));
|
|
|
|
SetFont(hWnd, IDOK, GetFont(font_name, 0, true, false, false, false));
|
|
|
|
SetFont(hWnd, IDCANCEL, GetFont(font_name, 0, false, false, false, false));
|
|
|
|
SetFont(hWnd, S_PRODUCT_STR, GetFont(font_name, 10, true, false, false, false));
|
|
|
|
SetFont(hWnd, S_CURRENT_STR, GetFont(font_name, 10, true, false, false, false));
|
|
|
|
SetFont(hWnd, S_LATEST_STR, GetFont(font_name, 10, true, false, false, false));
|
|
|
|
|
|
|
|
SetFont(hWnd, S_PRODUCT, GetFont(font_name, 0, false, false, false, false));
|
|
|
|
SetFont(hWnd, S_CURRENT, GetFont(font_name, 0, false, false, false, false));
|
|
|
|
SetFont(hWnd, S_LATEST, GetFont(font_name, 0, false, false, false, false));
|
|
|
|
SetFont(hWnd, B_CONFIG, GetFont(font_name, 0, false, false, false, false));
|
|
|
|
|
|
|
|
SetTimer(hWnd, 1, 100, NULL);
|
|
|
|
|
|
|
|
//MessageBeep(MB_ICONASTERISK);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK: // Web View
|
|
|
|
OnceMsgEx(hWnd, NULL, _UU("DLG_UPDATE_HINT"), true, ICO_INTERNET, (bool *)p->halt_flag);
|
|
|
|
|
|
|
|
ShellExecuteA(hWnd, "open", p->Url, NULL, NULL, SW_SHOWNORMAL);
|
|
|
|
SleepThread(250);
|
|
|
|
|
|
|
|
// Ignore the update notification of this version for future
|
|
|
|
LoadUpdateUiSetting(u, &s);
|
|
|
|
s.LatestIgnoreBuild = p->LatestBuild;
|
|
|
|
SaveUpdateUiSetting(u, &s);
|
|
|
|
|
|
|
|
EndDialog(hWnd, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDCANCEL: // Ignore this version
|
|
|
|
LoadUpdateUiSetting(u, &s);
|
|
|
|
s.LatestIgnoreBuild = p->LatestBuild;
|
|
|
|
SaveUpdateUiSetting(u, &s);
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_CONFIG: // Show the notification settings screen
|
|
|
|
p->IsInConfigDialog = true;
|
|
|
|
|
|
|
|
if (ConfigUpdateUi(u, hWnd) == false)
|
|
|
|
{
|
|
|
|
// Decided not to notify any more as a result of setting
|
|
|
|
Close(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->IsInConfigDialog = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if (p->IsInConfigDialog == false)
|
|
|
|
{
|
|
|
|
if (*(p->halt_flag))
|
|
|
|
{
|
|
|
|
// Close the screen forcibly
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE: // Close
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update notification dialog
|
|
|
|
void UpdateNotifyProcUi(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param)
|
|
|
|
{
|
|
|
|
WINUI_UPDATE *u = (WINUI_UPDATE *)param;
|
|
|
|
WINUI_UPDATE_DLG_PARAM p;
|
|
|
|
// Validate arguments
|
|
|
|
if (c == NULL || latest_build == 0 || latest_date == 0 || latest_ver == NULL || url == NULL || halt_flag == NULL || param == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-11 21:06:20 +04:00
|
|
|
if (u->UseSuppressFlag)
|
|
|
|
{
|
|
|
|
// Check the suppress flag
|
|
|
|
if (MsRegReadIntEx2(REG_LOCAL_MACHINE, PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGKEY,
|
|
|
|
PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGVALUE, false, true))
|
|
|
|
{
|
|
|
|
// Supress the dialog
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-03 19:09:23 +04:00
|
|
|
if (u->CurrentlyDisabled)
|
|
|
|
{
|
|
|
|
// Hide
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
// Show the update screen
|
|
|
|
Zero(&p, sizeof(p));
|
|
|
|
|
|
|
|
p.Update = u;
|
|
|
|
p.LatestBuild = latest_build;
|
|
|
|
p.LatestDate = latest_date;
|
|
|
|
p.LatestVer = latest_ver;
|
|
|
|
p.Url = url;
|
|
|
|
p.halt_flag = halt_flag;
|
|
|
|
|
|
|
|
Dialog(NULL, D_UPDATE_NOTICE, UpdateNoticeDlgProc, &p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the update notification
|
2014-07-11 21:06:20 +04:00
|
|
|
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)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
|
|
|
WINUI_UPDATE *u;
|
|
|
|
UPDATE_CLIENT_SETTING s;
|
|
|
|
LANGLIST t;
|
|
|
|
// Validate arguments
|
|
|
|
if (title == NULL || name == NULL || current_build == 0 || current_ver == 0)
|
|
|
|
{
|
2017-10-19 05:48:23 +03:00
|
|
|
return NULL;
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
2016-04-24 17:49:31 +03:00
|
|
|
if (MsIsWine())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2014-01-04 17:00:08 +04:00
|
|
|
if (IsEmptyStr(family_name))
|
|
|
|
{
|
|
|
|
family_name = UPDATE_FAMILY_NAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = ZeroMalloc(sizeof(WINUI_UPDATE));
|
|
|
|
|
|
|
|
StrCpy(u->ClientId, sizeof(u->ClientId), client_id);
|
|
|
|
UniStrCpy(u->SoftwareTitle, sizeof(u->SoftwareTitle), title);
|
|
|
|
StrCpy(u->SoftwareName, sizeof(u->SoftwareName), name);
|
|
|
|
u->CurrentDate = current_date;
|
|
|
|
u->CurrentBuild = current_build;
|
|
|
|
u->CurrentVer = current_ver;
|
2014-07-11 21:06:20 +04:00
|
|
|
u->UseSuppressFlag = use_suppress_flag;
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
Format(u->RegKey, sizeof(u->RegKey), WINUI_UPDATE_REGKEY, u->SoftwareName);
|
|
|
|
|
|
|
|
Zero(&s, sizeof(s));
|
|
|
|
LoadUpdateUiSetting(u, &s);
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
GetCurrentLang(&t);
|
|
|
|
|
|
|
|
u->UpdateClient = NewUpdateClient(UpdateNotifyProcUi, IsThisProcessForegroundForUpdateUi, u, family_name, u->SoftwareName, u->SoftwareTitle,
|
|
|
|
u->CurrentBuild, u->CurrentDate, t.Name, &s, client_id);
|
|
|
|
|
|
|
|
if (u->UpdateClient == NULL)
|
|
|
|
{
|
|
|
|
Free(u);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
2014-10-03 19:09:23 +04:00
|
|
|
// Disable the update notification UI
|
|
|
|
void DisableUpdateUi(WINUI_UPDATE *u)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (u == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
u->CurrentlyDisabled = true;
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
// Release the update notification
|
|
|
|
void FreeUpdateUi(WINUI_UPDATE *u)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (u == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (u->UpdateClient != NULL)
|
|
|
|
{
|
|
|
|
FreeUpdateClient(u->UpdateClient);
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(u);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the current settings from the registry
|
|
|
|
void LoadUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s)
|
|
|
|
{
|
|
|
|
Zero(s, sizeof(UPDATE_CLIENT_SETTING));
|
|
|
|
// Validate arguments
|
|
|
|
if (u == NULL || s == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->DisableCheck = MsRegReadInt(REG_CURRENT_USER, u->RegKey, "DisableCheck");
|
|
|
|
s->LatestIgnoreBuild = MsRegReadInt(REG_CURRENT_USER, u->RegKey, "LatestIgnoreBuild");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the current settings to the registry
|
|
|
|
void SaveUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (u == NULL || s == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MsRegWriteInt(REG_CURRENT_USER, u->RegKey, "DisableCheck", s->DisableCheck);
|
|
|
|
MsRegWriteInt(REG_CURRENT_USER, u->RegKey, "LatestIgnoreBuild", s->LatestIgnoreBuild);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the UAC icon to the control in the dialog
|
|
|
|
void SetUacIcon(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
static HINSTANCE hShell32 = NULL;
|
|
|
|
static HRESULT (__stdcall *_SHGetStockIconInfo)(UINT siid, UINT uFlags, void *psii) = NULL;
|
|
|
|
bool ok = false;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hShell32 == NULL)
|
|
|
|
{
|
|
|
|
hShell32 = LoadLibraryA("shell32.dll");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hShell32 != NULL)
|
|
|
|
{
|
|
|
|
if (_SHGetStockIconInfo == NULL)
|
|
|
|
{
|
|
|
|
_SHGetStockIconInfo = (HRESULT (__stdcall *)(UINT,UINT,void *))GetProcAddress(hShell32, "SHGetStockIconInfo");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_SHGetStockIconInfo != NULL)
|
|
|
|
{
|
|
|
|
WINUI_SHSTOCKICONINFO sii;
|
|
|
|
|
|
|
|
Zero(&sii, sizeof(sii));
|
|
|
|
|
|
|
|
sii.cbSize = sizeof(sii);
|
|
|
|
if (_SHGetStockIconInfo(77, 0x000000100 | 0x000000001, &sii) == S_OK)
|
|
|
|
{
|
|
|
|
SendMessage(DlgItem(hWnd, id), STM_SETICON, (WPARAM)sii.hIcon, 0);
|
|
|
|
|
|
|
|
ok = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
if (!ok)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
Hide(hWnd, id);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Procedure of the wizard page
|
|
|
|
UINT CALLBACK WizardPageDefDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
DIALOG_PARAM *dp = (DIALOG_PARAM *)GetParam(hWnd);
|
|
|
|
WIZARD_PAGE *wizard_page = NULL;
|
|
|
|
WIZARD *wizard = NULL;
|
|
|
|
UINT ret_value = 0;
|
|
|
|
bool do_not_send_msg = false;
|
|
|
|
|
|
|
|
if (dp != NULL)
|
|
|
|
{
|
|
|
|
wizard_page = dp->wizard_page;
|
|
|
|
wizard = wizard_page->Wizard;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
{
|
|
|
|
PROPSHEETPAGEW_V3 *t = (PROPSHEETPAGEW_V3 *)lParam;
|
|
|
|
dp = (DIALOG_PARAM *)t->lParam;
|
|
|
|
wizard_page = dp->wizard_page;
|
|
|
|
wizard = wizard_page->Wizard;
|
|
|
|
|
|
|
|
wizard->hWndWizard = GetParent(hWnd);
|
|
|
|
wizard_page->hWndPage = hWnd;
|
|
|
|
|
|
|
|
SetParam(hWnd, dp);
|
|
|
|
|
|
|
|
InitDialogInternational(hWnd, dp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CTLCOLORBTN:
|
|
|
|
case WM_CTLCOLORDLG:
|
|
|
|
case WM_CTLCOLOREDIT:
|
|
|
|
case WM_CTLCOLORLISTBOX:
|
|
|
|
case WM_CTLCOLORMSGBOX:
|
|
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
|
|
return (UINT)GetStockObject(WHITE_BRUSH);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NOTIFY:
|
|
|
|
{
|
|
|
|
NMHDR *pnmh = (NMHDR *)lParam;
|
|
|
|
UINT ret = 0;
|
|
|
|
UINT next_page = INFINITE;
|
|
|
|
|
|
|
|
switch (pnmh->code)
|
|
|
|
{
|
|
|
|
case PSN_SETACTIVE: // Activate
|
|
|
|
SetWizardButton(wizard_page, true, true, true, false);
|
|
|
|
dp->wizard_proc(hWnd, WM_WIZ_SHOW, 0, 0, wizard, wizard_page, wizard->Param);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PSN_KILLACTIVE: // Deactivate
|
|
|
|
dp->wizard_proc(hWnd, WM_WIZ_HIDE, 0, 0, wizard, wizard_page, wizard->Param);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PSN_WIZNEXT: // Determine the destination of [Next] button
|
|
|
|
ret = dp->wizard_proc(hWnd, WM_WIZ_NEXT, 0, 0, wizard, wizard_page, wizard->Param);
|
|
|
|
do_not_send_msg = true;
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret_value = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PSN_WIZBACK: // Determine the destination of [back] button
|
|
|
|
ret = dp->wizard_proc(hWnd, WM_WIZ_BACK, 0, 0, wizard, wizard_page, wizard->Param);
|
|
|
|
do_not_send_msg = true;
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret_value = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PSN_QUERYCANCEL: // Determine the process of the [Cancel] button
|
|
|
|
if (dp->wizard_page->EnableClose == false)
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
ret = dp->wizard_proc(hWnd, WM_WIZ_CLOSE, 0, 0, wizard, wizard_page, wizard->Param);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
if (IsEmptyUniStr(wizard->CloseConfirmMsg) == false &&
|
|
|
|
MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, wizard->CloseConfirmMsg) == IDNO)
|
|
|
|
{
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetWindowLong(hWnd, DWLP_MSGRESULT, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret_value = 1;
|
|
|
|
do_not_send_msg = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (do_not_send_msg == false)
|
|
|
|
{
|
|
|
|
if (dp != NULL)
|
|
|
|
{
|
|
|
|
UINT ret = dp->wizard_proc(hWnd, msg, wParam, lParam, wizard, wizard_page, wizard->Param);
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
ret_value = ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg == WM_INITDIALOG)
|
|
|
|
{
|
|
|
|
if (wizard->SetCenterFlag == false)
|
|
|
|
{
|
|
|
|
wizard->SetCenterFlag = true;
|
|
|
|
|
|
|
|
Center(wizard->hWndWizard);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetForegroundWindow(wizard->hWndWizard);
|
|
|
|
SetActiveWindow(wizard->hWndWizard);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Button setting of the wizard
|
|
|
|
void SetWizardButton(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish)
|
|
|
|
{
|
|
|
|
SetWizardButtonEx(p, enable_next, enable_back, enable_close, is_finish, false);
|
|
|
|
}
|
|
|
|
void SetWizardButtonEx(WIZARD_PAGE *p, bool enable_next, bool enable_back, bool enable_close, bool is_finish, bool shield_icon)
|
|
|
|
{
|
|
|
|
DWORD flags = 0;
|
|
|
|
DWORD flags2 = 0;
|
|
|
|
DWORD flags3 = 0;
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->EnableNext = enable_next;
|
|
|
|
p->EnableBack = enable_back;
|
|
|
|
p->EnableClose = enable_close;
|
|
|
|
p->IsFinish = is_finish;
|
|
|
|
|
|
|
|
if (is_finish == false)
|
|
|
|
{
|
|
|
|
if (p->EnableNext)
|
|
|
|
{
|
|
|
|
flags |= PSWIZB_NEXT;
|
|
|
|
flags2 |= PSWIZB_NEXT;
|
|
|
|
|
|
|
|
if (shield_icon)
|
|
|
|
{
|
|
|
|
if (p->Wizard->IsAreoStyle)
|
|
|
|
{
|
|
|
|
if (MsIsAdmin() == false)
|
|
|
|
{
|
|
|
|
flags3 |= PSWIZBF_ELEVATIONREQUIRED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (p->EnableNext)
|
|
|
|
{
|
|
|
|
flags |= PSWIZB_FINISH;
|
|
|
|
flags2 |= PSWIZB_FINISH;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags |= PSWIZB_DISABLEDFINISH;
|
|
|
|
flags2 |= PSWIZB_FINISH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->EnableBack)
|
|
|
|
{
|
|
|
|
flags |= PSWIZB_BACK;
|
|
|
|
flags2 |= PSWIZB_BACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->EnableClose)
|
|
|
|
{
|
|
|
|
flags2 |= 0x00000010;
|
|
|
|
}
|
|
|
|
|
|
|
|
PostMessage(p->Wizard->hWndWizard, PSM_SETWIZBUTTONS, flags3, flags);
|
|
|
|
|
|
|
|
SetEnable(p->Wizard->hWndWizard, IDCANCEL, p->EnableClose);
|
|
|
|
|
|
|
|
WINUI_PropSheet_ShowWizButtons(p->Wizard->hWndWizard,
|
|
|
|
flags2, PSWIZB_BACK | PSWIZB_NEXT | PSWIZB_FINISH | 0x00000010);
|
|
|
|
|
|
|
|
if (p->EnableClose)
|
|
|
|
{
|
|
|
|
EnableClose(p->Wizard->hWndWizard);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DisableClose(p->Wizard->hWndWizard);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LRESULT CALLBACK WizardCustomizedWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
WIZARD *wizard = (WIZARD *)TlsGetValue(tls_current_wizard);
|
|
|
|
|
|
|
|
if (wizard != NULL)
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_CTLCOLORBTN:
|
|
|
|
case WM_CTLCOLORDLG:
|
|
|
|
case WM_CTLCOLOREDIT:
|
|
|
|
case WM_CTLCOLORLISTBOX:
|
|
|
|
case WM_CTLCOLORMSGBOX:
|
|
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
|
|
return (UINT)GetStockObject(WHITE_BRUSH);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
return CallWindowProcW(wizard->OriginalWindowProc, hWnd, msg, wParam, lParam);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Procedure of the wizard
|
|
|
|
UINT CALLBACK WizardDlgProc(HWND hWnd, UINT msg, LPARAM lParam)
|
|
|
|
{
|
|
|
|
WIZARD *wizard = (WIZARD *)TlsGetValue(tls_current_wizard);
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case PSCB_INITIALIZED:
|
|
|
|
if (wizard != NULL)
|
|
|
|
{
|
|
|
|
if (wizard->hWndWizard != NULL)
|
|
|
|
{
|
|
|
|
wizard->hWndWizard = hWnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wizard->ReplaceWindowProcFlag == false)
|
|
|
|
{
|
|
|
|
wizard->ReplaceWindowProcFlag = true;
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
wizard->OriginalWindowProc = (void *)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
|
2014-01-04 17:00:08 +04:00
|
|
|
if (wizard->OriginalWindowProc != NULL)
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)WizardCustomizedWindowProc);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Jump to another wizard page
|
|
|
|
void JumpWizard(WIZARD_PAGE *p, UINT next_id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL || next_id == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PropSheet_SetCurSelByID(p->Wizard->hWndWizard, next_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the wizard
|
|
|
|
void CloseWizard(WIZARD_PAGE *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->Wizard->CloseConfirmMsg = NULL;
|
|
|
|
SetWizardButton(p, false, false, true, false);
|
|
|
|
|
|
|
|
if (p->Wizard->IsAreoStyle)
|
|
|
|
{
|
|
|
|
PropSheet_PressButton(p->hWndPage, PSBTN_CANCEL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Close(p->Wizard->hWndWizard);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the wizard
|
|
|
|
void ShowWizard(HWND hWndParent, WIZARD *w, UINT start_id)
|
|
|
|
{
|
|
|
|
void **pages_array;
|
|
|
|
UINT num_pages;
|
|
|
|
UINT i;
|
|
|
|
PROPSHEETHEADERW_V2 h;
|
|
|
|
WIZARD_PAGE *start_page;
|
|
|
|
// Validate arguments
|
|
|
|
if (w == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_pages = LIST_NUM(w->Pages);
|
|
|
|
pages_array = ZeroMalloc(sizeof(void *) * num_pages);
|
|
|
|
|
|
|
|
for (i = 0;i < num_pages;i++)
|
|
|
|
{
|
|
|
|
WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
|
|
|
|
|
|
|
|
pages_array[i] = CreateWizardPageInstance(w, p);
|
|
|
|
|
|
|
|
p->Index = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&h, sizeof(h));
|
|
|
|
h.dwSize = sizeof(PROPSHEETHEADERW_V2);
|
|
|
|
h.dwFlags = PSH_WIZARD97 | PSH_HEADER | PSH_USEICONID | PSH_USECALLBACK;
|
|
|
|
|
|
|
|
if (MsIsAeroColor() == false)
|
|
|
|
{
|
|
|
|
// Aero Wizard can not be used If the color of Aero is disabled
|
|
|
|
// even in Vista or later (if the background color is not white)
|
|
|
|
w->IsAreoStyle = false;
|
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:15 +03:00
|
|
|
if (MsIsWindows10())
|
|
|
|
{
|
|
|
|
// Windows 10 Icon Bug: Disable Aero Style!
|
|
|
|
w->IsAreoStyle = false;
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
if (w->IsAreoStyle)
|
|
|
|
{
|
|
|
|
// Aero Wizard
|
|
|
|
h.dwFlags = PSH_WIZARD | 0x00004000 | PSH_HEADER | PSH_USEICONID | PSH_USECALLBACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
h.hInstance = hDll;
|
|
|
|
h.pszIcon = MAKEINTRESOURCEW(w->Icon);
|
|
|
|
h.hwndParent = hWndParent;
|
|
|
|
h.nPages = num_pages;
|
|
|
|
h.phpage = (HPROPSHEETPAGE *)pages_array;
|
|
|
|
h.pszbmHeader = MAKEINTRESOURCEW(w->Bitmap);
|
|
|
|
h.pszCaption = w->Caption;
|
|
|
|
h.pfnCallback = WizardDlgProc;
|
|
|
|
|
|
|
|
start_page = GetWizardPage(w, start_id);
|
|
|
|
if (start_page != NULL)
|
|
|
|
{
|
|
|
|
h.nStartPage = start_page->Index;
|
|
|
|
}
|
|
|
|
|
|
|
|
w->hWndParent = hWndParent;
|
|
|
|
w->hWndWizard = NULL;
|
|
|
|
w->SetCenterFlag = false;
|
|
|
|
|
|
|
|
TlsSetValue(tls_current_wizard, w);
|
|
|
|
|
|
|
|
PropertySheetW(&h);
|
|
|
|
|
|
|
|
TlsSetValue(tls_current_wizard, NULL);
|
|
|
|
|
|
|
|
Free(pages_array);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create an instance of the wizard page
|
|
|
|
void *CreateWizardPageInstance(WIZARD *w, WIZARD_PAGE *p)
|
|
|
|
{
|
|
|
|
PROPSHEETPAGEW_V3 t;
|
|
|
|
// Validate arguments
|
|
|
|
if (w == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.dwSize = sizeof(PROPSHEETPAGEW_V3);
|
|
|
|
t.dwFlags = PSP_USETITLE | PSP_USEHEADERTITLE;// | PSP_USEHEADERSUBTITLE;
|
|
|
|
t.hInstance = hDll;
|
|
|
|
t.pszTemplate = MAKEINTRESOURCEW(p->Id);
|
|
|
|
t.pfnDlgProc = (DLGPROC)WizardPageDefDlgProc;
|
|
|
|
t.pszHeaderTitle = p->Title;
|
|
|
|
t.pszTitle = w->Caption;
|
|
|
|
|
|
|
|
if (p->DialogParam != NULL)
|
|
|
|
{
|
|
|
|
FreeBitmapList(p->DialogParam->BitmapList);
|
|
|
|
Free(p->DialogParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->DialogParam = ZeroMalloc(sizeof(DIALOG_PARAM));
|
|
|
|
|
|
|
|
p->DialogParam->BitmapList = NewBitmapList();
|
|
|
|
p->DialogParam->wizard = w;
|
|
|
|
p->DialogParam->wizard_page = p;
|
|
|
|
p->DialogParam->wizard_proc = p->Proc;
|
|
|
|
p->DialogParam->param = w->Param;
|
|
|
|
p->DialogParam->white = false;
|
|
|
|
p->DialogParam->meiryo = false;
|
|
|
|
|
|
|
|
t.lParam = (LPARAM)p->DialogParam;
|
|
|
|
|
|
|
|
return CreatePropertySheetPageW(&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new wizard
|
|
|
|
WIZARD *NewWizard(UINT icon, UINT bitmap, wchar_t *caption, void *param)
|
|
|
|
{
|
|
|
|
WIZARD *w = ZeroMalloc(sizeof(WIZARD));
|
|
|
|
|
|
|
|
w->Icon = icon;
|
|
|
|
w->Pages = NewList(NULL);
|
|
|
|
w->Param = param;
|
|
|
|
w->Bitmap = bitmap;
|
|
|
|
w->Caption = CopyUniStr(caption);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the wizard
|
|
|
|
void FreeWizard(WIZARD *w)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (w == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(w->Pages);i++)
|
|
|
|
{
|
|
|
|
WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
|
|
|
|
|
|
|
|
FreeWizardPage(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseList(w->Pages);
|
|
|
|
|
|
|
|
Free(w->Caption);
|
|
|
|
|
|
|
|
Free(w);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the wizard page
|
|
|
|
WIZARD_PAGE *GetWizardPage(WIZARD *w, UINT id)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (w == NULL || id == 0)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(w->Pages);i++)
|
|
|
|
{
|
|
|
|
WIZARD_PAGE *p = LIST_DATA(w->Pages, i);
|
|
|
|
|
|
|
|
if (p->Id == id)
|
|
|
|
{
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a wizard page
|
|
|
|
void AddWizardPage(WIZARD *w, WIZARD_PAGE *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (w == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Add(w->Pages, p);
|
|
|
|
|
|
|
|
p->Wizard = w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new wizard page
|
|
|
|
WIZARD_PAGE *NewWizardPage(UINT id, WINUI_WIZARD_PROC *proc, wchar_t *title)
|
|
|
|
{
|
|
|
|
WIZARD_PAGE *p;
|
|
|
|
// Validate arguments
|
|
|
|
if (id == 0 || proc == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = ZeroMalloc(sizeof(WIZARD_PAGE));
|
|
|
|
p->Id = id;
|
|
|
|
p->Proc = proc;
|
|
|
|
p->Title = CopyUniStr(title);
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the wizard page
|
|
|
|
void FreeWizardPage(WIZARD_PAGE *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->DialogParam != NULL)
|
|
|
|
{
|
|
|
|
FreeBitmapList(p->DialogParam->BitmapList);
|
|
|
|
Free(p->DialogParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(p->Title);
|
|
|
|
|
|
|
|
Free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// NIC information dialog procedure
|
|
|
|
UINT NicInfoProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
UI_NICINFO *info = (UI_NICINFO *)param;
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
NicInfoInit(hWnd, info);
|
|
|
|
|
|
|
|
SetTimer(hWnd, 1, 50, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
|
|
|
|
NicInfoOnTimer(hWnd, info);
|
|
|
|
|
|
|
|
SetTimer(hWnd, 1, 50, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
KillTimer(hWnd, 2);
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
KillTimer(hWnd, 2);
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void NicInfoCloseAfterTime(HWND hWnd, UI_NICINFO *info, UINT tick)
|
|
|
|
{
|
|
|
|
UINT64 now;
|
|
|
|
UINT64 closetime;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || info == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
now = Tick64();
|
|
|
|
closetime = now + (UINT64)tick;
|
|
|
|
|
|
|
|
if (info->CloseAfterTime == 0 || info->CloseAfterTime >= closetime)
|
|
|
|
{
|
|
|
|
info->CloseAfterTime = closetime;
|
|
|
|
KillTimer(hWnd, 2);
|
|
|
|
SetTimer(hWnd, 2, tick, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void NicInfoShowStatus(HWND hWnd, UI_NICINFO *info, wchar_t *msg1, wchar_t *msg2, UINT icon, bool animate)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || info == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (icon == 0)
|
|
|
|
{
|
|
|
|
icon = ICO_TEST;
|
|
|
|
}
|
|
|
|
if (msg1 == NULL)
|
|
|
|
{
|
|
|
|
msg1 = L"";
|
|
|
|
}
|
|
|
|
if (msg2 == NULL)
|
|
|
|
{
|
|
|
|
msg2 = L"";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->CurrentIcon != icon)
|
|
|
|
{
|
|
|
|
SetIcon(hWnd, S_ICON, icon);
|
|
|
|
info->CurrentIcon = icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetText(hWnd, S_STATUS1, msg1);
|
|
|
|
SetText(hWnd, S_STATUS2, msg2);
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
SetShow(hWnd, P_BAR, animate);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
void NicInfoRefresh(HWND hWnd, UI_NICINFO *info)
|
|
|
|
{
|
|
|
|
MS_ADAPTER *a;
|
|
|
|
IP ip;
|
|
|
|
char ip_str[MAX_SIZE];
|
|
|
|
char title[MAX_SIZE];
|
|
|
|
UINT i;
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
bool has_ip = false;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || info == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Format(title, sizeof(title), VLAN_ADAPTER_NAME_TAG, info->NicName);
|
|
|
|
|
|
|
|
a = MsGetAdapter(title);
|
|
|
|
if (a == NULL)
|
|
|
|
{
|
|
|
|
Close(hWnd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether an IP address is assigned
|
|
|
|
Zero(&ip, sizeof(ip));
|
|
|
|
for (i = 0;i < MAX_MS_ADAPTER_IP_ADDRESS;i++)
|
|
|
|
{
|
|
|
|
if (IsZeroIP(&a->IpAddresses[i]) == false)
|
|
|
|
{
|
|
|
|
Copy(&ip, &a->IpAddresses[i], sizeof(IP));
|
|
|
|
|
2021-04-07 22:24:55 +03:00
|
|
|
if (!(IPV4(ip.address)[0] == 169 && IPV4(ip.address)[1] == 254))
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
|
|
|
has_ip = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
IPToStr(ip_str, sizeof(ip_str), &ip);
|
|
|
|
|
|
|
|
if (has_ip == false)
|
|
|
|
{
|
|
|
|
if (a->UseDhcp)
|
|
|
|
{
|
|
|
|
NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_1"), ICO_NIC_OFFLINE, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_2"), ICO_NIC_OFFLINE, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (a->UseDhcp)
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("NICINFO_2_1"), ip_str);
|
|
|
|
NicInfoShowStatus(hWnd, info, _UU("NICINFO_2"), tmp, ICO_NIC_ONLINE, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("NICINFO_3_1"), ip_str);
|
|
|
|
NicInfoShowStatus(hWnd, info, _UU("NICINFO_3"), tmp, ICO_NIC_ONLINE, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_2);
|
|
|
|
}
|
|
|
|
|
|
|
|
MsFreeAdapter(a);
|
|
|
|
}
|
|
|
|
void NicInfoInit(HWND hWnd, UI_NICINFO *info)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || info == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
// Show a progress bar
|
|
|
|
SendMsg(hWnd, P_BAR, PBM_SETMARQUEE, TRUE, 150);
|
|
|
|
SetStyle(hWnd, P_BAR, PBS_MARQUEE);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
DlgFont(hWnd, S_STATUS1, 9, false);
|
|
|
|
DlgFont(hWnd, S_STATUS2, 11, false);
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, ICO_NIC_ONLINE);
|
|
|
|
|
|
|
|
FormatText(hWnd, 0, info->NicName);
|
|
|
|
|
|
|
|
NicInfoRefresh(hWnd, info);
|
|
|
|
|
|
|
|
NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_1);
|
|
|
|
}
|
|
|
|
void NicInfoOnTimer(HWND hWnd, UI_NICINFO *info)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || info == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->Halt)
|
|
|
|
{
|
|
|
|
Close(hWnd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->RouteChange != NULL &&
|
|
|
|
IsRouteChanged(info->RouteChange) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NicInfoRefresh(hWnd, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the NIC information dialog
|
|
|
|
void NicInfo(UI_NICINFO *info)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (info == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->RouteChange = NewRouteChange();
|
|
|
|
|
|
|
|
DialogEx2(NULL, D_NICINFO, NicInfoProc, info, true, true);
|
|
|
|
|
|
|
|
FreeRouteChange(info->RouteChange);
|
|
|
|
info->RouteChange = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP connection thread
|
|
|
|
void WinConnectDlgThread(THREAD *thread, void *param)
|
|
|
|
{
|
|
|
|
SOCK *s;
|
|
|
|
WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;
|
|
|
|
UINT nat_t_error_code;
|
|
|
|
char *nat_t_svc_name = NULL;
|
|
|
|
// Validate arguments
|
|
|
|
if (d == NULL || thread == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Socket connection
|
|
|
|
if (IsEmptyStr(d->nat_t_svc_name) == false)
|
|
|
|
{
|
|
|
|
nat_t_svc_name = d->nat_t_svc_name;
|
|
|
|
}
|
|
|
|
|
2021-12-17 12:57:23 +03:00
|
|
|
s = ConnectEx5(d->hostname, d->port, d->timeout, &d->cancel, nat_t_svc_name, &nat_t_error_code, d->try_start_ssl, false, d->ssl_option, d->ssl_err, d->hint_str, NULL);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
d->ret_sock = s;
|
|
|
|
d->nat_t_error_code = nat_t_error_code;
|
|
|
|
|
|
|
|
PostMessageA(d->hWnd, WM_APP + 68, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP connection dialog procedure
|
|
|
|
UINT WinConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || d == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
// UI setting
|
|
|
|
CenterParent(hWnd);
|
|
|
|
SetText(hWnd, 0, d->caption);
|
|
|
|
SetText(hWnd, S_INFO, d->info);
|
|
|
|
SetIcon(hWnd, S_ICON, d->icon_id);
|
|
|
|
d->hWnd = hWnd;
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
// Show a progress bar
|
|
|
|
SendMsg(hWnd, IDC_PROGRESS1, PBM_SETMARQUEE, TRUE, 100);
|
|
|
|
SetStyle(hWnd, IDC_PROGRESS1, PBS_MARQUEE);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
// Create a thread
|
|
|
|
d->thread = NewThread(WinConnectDlgThread, d);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_APP + 68:
|
|
|
|
case WM_CLOSE:
|
|
|
|
if (d->cancel == false)
|
|
|
|
{
|
|
|
|
d->cancel = true;
|
|
|
|
Disable(hWnd, IDCANCEL);
|
|
|
|
if (d->ret_sock == NULL)
|
|
|
|
{
|
|
|
|
SetText(hWnd, S_INFO, _UU("CONNECTDLG_CANCELING"));
|
|
|
|
}
|
|
|
|
DoEvents(hWnd);
|
|
|
|
Refresh(hWnd);
|
|
|
|
WaitThread(d->thread, INFINITE);
|
|
|
|
ReleaseThread(d->thread);
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP connection with showing the UI
|
2018-07-30 10:03:07 +03:00
|
|
|
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)
|
2021-12-14 19:54:40 +03:00
|
|
|
{
|
2021-12-17 12:57:23 +03:00
|
|
|
return WinConnectEx4(hWnd, server, port, timeout, icon_id, caption, info, nat_t_error_code, nat_t_svc_name, try_start_ssl, NULL, NULL, NULL);
|
2021-12-14 19:54:40 +03:00
|
|
|
}
|
2021-12-17 12:57:23 +03:00
|
|
|
SOCK *WinConnectEx4(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, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
wchar_t tmp2[MAX_SIZE];
|
|
|
|
WINCONNECT_DLG_DATA d;
|
|
|
|
// Validate arguments
|
|
|
|
if (server == NULL || port == 0)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (icon_id == 0)
|
|
|
|
{
|
|
|
|
icon_id = ICO_USER_ADMIN;
|
|
|
|
}
|
|
|
|
if (caption == NULL)
|
|
|
|
{
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
caption = _UU("CONNECTDLG_CAPTION");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GetTxt(hWnd, 0, tmp2, sizeof(tmp2));
|
|
|
|
caption = tmp2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (info == NULL)
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("CONNECTDLG_MESSAGE"), server, port);
|
|
|
|
|
|
|
|
info = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&d, sizeof(d));
|
|
|
|
|
|
|
|
d.try_start_ssl = try_start_ssl;
|
|
|
|
d.cancel = false;
|
|
|
|
d.caption = caption;
|
|
|
|
d.icon_id = icon_id;
|
|
|
|
d.info = info;
|
|
|
|
d.timeout = timeout;
|
|
|
|
d.hostname = server;
|
|
|
|
d.port = port;
|
2021-12-17 12:57:23 +03:00
|
|
|
d.ssl_option = ssl_option;
|
|
|
|
d.ssl_err = ssl_err;
|
2021-12-14 19:54:40 +03:00
|
|
|
d.hint_str = hint_str;
|
2014-01-04 17:00:08 +04:00
|
|
|
StrCpy(d.nat_t_svc_name, sizeof(d.nat_t_svc_name), nat_t_svc_name);
|
|
|
|
|
|
|
|
Dialog(hWnd, D_CONNECT, WinConnectDlgProc, &d);
|
|
|
|
|
|
|
|
if (nat_t_error_code != NULL)
|
|
|
|
{
|
|
|
|
*nat_t_error_code = d.nat_t_error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
return d.ret_sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the Windows Network Setup screen
|
|
|
|
bool ShowWindowsNetworkConnectionDialog()
|
|
|
|
{
|
|
|
|
wchar_t exe_name[MAX_SIZE];
|
|
|
|
void *proc;
|
|
|
|
|
|
|
|
CombinePathW(exe_name, sizeof(exe_name), MsGetSystem32DirW(), L"control.exe");
|
|
|
|
|
|
|
|
proc = Win32RunEx2W(exe_name, L"netconnections", false, NULL);
|
|
|
|
|
|
|
|
if (proc == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Win32CloseProcess(proc);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the best Meiryo font name for the current OS
|
|
|
|
char *GetMeiryoFontName()
|
|
|
|
{
|
|
|
|
if (MsIsWindows7())
|
|
|
|
{
|
|
|
|
return "Meiryo UI";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
return "Meiryo";
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the Meiryo font
|
|
|
|
HFONT GetMeiryoFont()
|
|
|
|
{
|
|
|
|
return GetMeiryoFontEx(0);
|
|
|
|
}
|
|
|
|
HFONT GetMeiryoFontEx(UINT font_size)
|
|
|
|
{
|
|
|
|
return GetMeiryoFontEx2(font_size, false);
|
|
|
|
}
|
|
|
|
HFONT GetMeiryoFontEx2(UINT font_size, bool bold)
|
|
|
|
{
|
|
|
|
if (_GETLANG() == 0)
|
|
|
|
{
|
|
|
|
return GetFont(GetMeiryoFontName(), font_size, bold, false, false, false);
|
|
|
|
}
|
|
|
|
else if (_GETLANG() == 2)
|
|
|
|
{
|
|
|
|
return GetFont("Microsoft YaHei", font_size, bold, false, false, false);
|
|
|
|
}
|
2017-12-02 01:04:57 +03:00
|
|
|
else if (_GETLANG() == 3)
|
2015-05-19 19:19:22 +03:00
|
|
|
{
|
|
|
|
return GetFont("Microsoft JhengHei", font_size, bold, false, false, false);
|
|
|
|
}
|
2014-01-04 17:00:08 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
return GetFont(NULL, font_size, bold, false, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set font to Meiryo
|
|
|
|
void SetFontMeiryo(HWND hWnd, UINT id, UINT font_size)
|
|
|
|
{
|
|
|
|
SetFont(hWnd, id, GetMeiryoFontEx(font_size));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set as the default font
|
|
|
|
void SetFontDefault(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
SetFont(hWnd, id, GetDialogDefaultFont());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Display the warning messages about bad process
|
|
|
|
void ShowBadProcessWarning(HWND hWnd, BAD_PROCESS *bad)
|
|
|
|
{
|
|
|
|
wchar_t title[MAX_SIZE];
|
|
|
|
wchar_t message[8192];
|
|
|
|
// Validate arguments
|
|
|
|
if (bad == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UniFormat(title, sizeof(title), _UU("BAD_PROCESS_TITLE"), bad->Title);
|
|
|
|
UniFormat(message, sizeof(message), _UU("BAD_PROCESS_MESSAGE"),
|
|
|
|
bad->Title, bad->Title, bad->Title, bad->Title);
|
|
|
|
|
|
|
|
OnceMsg(hWnd, title, message, true, ICO_WARNING);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is process which is included in incompatible anti-virus software list, show appropriate
|
|
|
|
bool CheckBadProcesses(HWND hWnd)
|
|
|
|
{
|
|
|
|
bool ret = true;
|
|
|
|
UINT i;
|
|
|
|
LIST *o;
|
|
|
|
|
|
|
|
o = MsGetProcessList();
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(o);i++)
|
|
|
|
{
|
|
|
|
MS_PROCESS *p = LIST_DATA(o, i);
|
|
|
|
char exe[MAX_PATH];
|
|
|
|
BAD_PROCESS *bad;
|
|
|
|
|
|
|
|
GetFileNameFromFilePath(exe, sizeof(exe), p->ExeFilename);
|
|
|
|
|
|
|
|
bad = IsBadProcess(exe);
|
|
|
|
|
|
|
|
if (bad != NULL)
|
|
|
|
{
|
|
|
|
// Display the message because a bad process have been found
|
|
|
|
ret = false;
|
|
|
|
|
|
|
|
ShowBadProcessWarning(hWnd, bad);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MsFreeProcessList(o);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search whether the specified process name is the appropriate to a bad process
|
|
|
|
BAD_PROCESS *IsBadProcess(char *exe)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (exe == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < num_bad_processes;i++)
|
|
|
|
{
|
|
|
|
BAD_PROCESS *bad = &bad_processes[i];
|
|
|
|
|
|
|
|
if (StrCmpi(bad->ExeName, exe) == 0)
|
|
|
|
{
|
|
|
|
return bad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Message display procedure
|
|
|
|
UINT OnceMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
ONCEMSG_DLG *d = (ONCEMSG_DLG *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetText(hWnd, 0, d->Title);
|
|
|
|
SetText(hWnd, E_TEXT, d->Message);
|
|
|
|
SetShow(hWnd, C_DONTSHOWAGAIN, d->ShowCheckbox);
|
|
|
|
//DisableClose(hWnd);
|
|
|
|
Focus(hWnd, IDCANCEL);
|
|
|
|
if (d->Icon != 0)
|
|
|
|
{
|
|
|
|
SetIcon(hWnd, 0, d->Icon);
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
SetFont(hWnd, E_TEXT, GetMeiryoFont());
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
SetTimer(hWnd, 1, 50, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if (*d->halt)
|
|
|
|
{
|
|
|
|
Close(hWnd);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
d->Checked = IsChecked(hWnd, C_DONTSHOWAGAIN);
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show a message
|
|
|
|
void OnceMsg(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon)
|
|
|
|
{
|
|
|
|
OnceMsgEx(hWnd, title, message, show_checkbox, icon, NULL);
|
|
|
|
}
|
|
|
|
void OnceMsgEx(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon, bool *halt)
|
|
|
|
{
|
|
|
|
ONCEMSG_DLG d;
|
|
|
|
UINT hash;
|
|
|
|
char valuename[MAX_PATH];
|
|
|
|
bool b_dummy = false;
|
|
|
|
// Validate arguments
|
|
|
|
if (title == NULL)
|
|
|
|
{
|
|
|
|
title = title_bar;
|
|
|
|
}
|
|
|
|
if (message == NULL)
|
|
|
|
{
|
|
|
|
message = L"message";
|
|
|
|
}
|
|
|
|
if (halt == NULL)
|
|
|
|
{
|
|
|
|
halt = &b_dummy;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&d, sizeof(d));
|
|
|
|
d.Message = message;
|
|
|
|
d.Title = title;
|
|
|
|
d.ShowCheckbox = show_checkbox;
|
|
|
|
d.Icon = icon;
|
|
|
|
d.halt = halt;
|
|
|
|
|
|
|
|
hash = GetOnceMsgHash(title, message);
|
|
|
|
Format(valuename, sizeof(valuename), ONCE_MSG_REGVALUE, hash);
|
|
|
|
|
|
|
|
if (MsRegReadInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename) == 0)
|
|
|
|
{
|
|
|
|
switch (icon)
|
|
|
|
{
|
|
|
|
case ICO_WARNING:
|
|
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ICO_INFORMATION:
|
|
|
|
MessageBeep(MB_ICONASTERISK);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dialog(hWnd, D_ONCEMSG, OnceMsgProc, &d);
|
|
|
|
|
|
|
|
if (show_checkbox)
|
|
|
|
{
|
|
|
|
if (d.Checked)
|
|
|
|
{
|
|
|
|
MsRegWriteInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the message hash
|
|
|
|
UINT GetOnceMsgHash(wchar_t *title, wchar_t *message)
|
|
|
|
{
|
|
|
|
BUF *b;
|
|
|
|
UCHAR hash[SHA1_SIZE];
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (title == NULL)
|
|
|
|
{
|
|
|
|
title = title_bar;
|
|
|
|
}
|
|
|
|
if (message == NULL)
|
|
|
|
{
|
|
|
|
message = L"message";
|
|
|
|
}
|
|
|
|
|
|
|
|
b = NewBuf();
|
|
|
|
// 2013.5.19: Exclude the title from the hash calculation
|
|
|
|
//WriteBuf(b, title, UniStrSize(title));
|
|
|
|
WriteBuf(b, message, UniStrSize(message));
|
2018-09-22 07:35:30 +03:00
|
|
|
Sha1(hash, b->Buf, b->Size);
|
2014-01-04 17:00:08 +04:00
|
|
|
FreeBuf(b);
|
|
|
|
|
|
|
|
Copy(&ret, hash, sizeof(UINT));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set a theme for Windows Vista
|
|
|
|
void InitVistaWindowTheme(HWND hWnd)
|
|
|
|
{
|
|
|
|
static HINSTANCE hInstDll = NULL;
|
|
|
|
HRESULT (WINAPI *_SetWindowTheme)(HWND, LPCWSTR, LPCWSTR) = NULL;
|
|
|
|
|
|
|
|
if (hInstDll == NULL)
|
|
|
|
{
|
|
|
|
hInstDll = LoadLibraryA("uxtheme.dll");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hInstDll == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_SetWindowTheme == NULL)
|
|
|
|
{
|
|
|
|
_SetWindowTheme = (HRESULT (WINAPI *)(HWND,LPCWSTR,LPCWSTR))GetProcAddress(hInstDll, "SetWindowTheme");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_SetWindowTheme == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_SetWindowTheme(hWnd, L"explorer", NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register all applications to be registered in the Windows firewall
|
|
|
|
// that may be present in the current directory
|
|
|
|
void RegistWindowsFirewallAll()
|
|
|
|
{
|
|
|
|
char exedir[MAX_SIZE];
|
|
|
|
|
|
|
|
GetExeDir(exedir, sizeof(exedir));
|
|
|
|
|
|
|
|
RegistWindowsFirewallAllEx(exedir);
|
|
|
|
}
|
|
|
|
void RegistWindowsFirewallAllEx(char *dir)
|
|
|
|
{
|
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "vpnclient.exe", dir);
|
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "vpncmgr.exe", dir);
|
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_MANAGER_STR, "vpnsmgr.exe", dir);
|
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "vpnserver.exe", dir);
|
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_BRIDGE_STR, "vpnbridge.exe", dir);
|
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "vpncmd.exe", dir);
|
2018-10-08 05:19:39 +03:00
|
|
|
MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "vpntest.exe", dir);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the notification service is already running
|
|
|
|
bool Win32CnCheckAlreadyExists(bool lock)
|
|
|
|
{
|
|
|
|
char tmp[MAX_SIZE];
|
|
|
|
HANDLE hMutex;
|
|
|
|
|
|
|
|
HashInstanceNameLocal(tmp, sizeof(tmp), CLIENT_NOTIFY_SERVICE_INSTANCENAME);
|
|
|
|
|
|
|
|
hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, tmp);
|
|
|
|
if (hMutex != NULL)
|
|
|
|
{
|
|
|
|
CloseHandle(hMutex);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lock == false)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hMutex = CreateMutex(NULL, FALSE, tmp);
|
|
|
|
if (hMutex == NULL)
|
|
|
|
{
|
|
|
|
CloseHandle(hMutex);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the Easter Egg
|
|
|
|
void ShowEasterEgg(HWND hWnd)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP/IP optimization selection dialog procedure
|
|
|
|
UINT TcpMsgDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetIcon(hWnd, 0, ICO_SETUP);
|
|
|
|
//DlgFont(hWnd, R_OPTIMIZE, 0, true);
|
|
|
|
|
|
|
|
Check(hWnd, R_NO, true);
|
|
|
|
|
|
|
|
if (g_tcpip_topmost)
|
|
|
|
{
|
|
|
|
Top(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
ret = 1;
|
|
|
|
if (IsChecked(hWnd, R_MANUAL))
|
|
|
|
{
|
|
|
|
ret = 2;
|
|
|
|
}
|
|
|
|
else if (IsChecked(hWnd, R_NO))
|
|
|
|
{
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EndDialog(hWnd, ret);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the dialog
|
|
|
|
void TcpIpDlgInit(HWND hWnd)
|
|
|
|
{
|
|
|
|
MS_TCP tcp;
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, ICO_SETUP);
|
|
|
|
|
|
|
|
MsGetTcpConfig(&tcp);
|
|
|
|
|
|
|
|
Check(hWnd, R_RECV_DISABLE, tcp.RecvWindowSize == 0);
|
|
|
|
Check(hWnd, R_RECV_ENABLE, tcp.RecvWindowSize != 0);
|
|
|
|
SetInt(hWnd, E_RECV, tcp.RecvWindowSize != 0 ? tcp.RecvWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);
|
|
|
|
|
|
|
|
Check(hWnd, R_SEND_DISABLE, tcp.SendWindowSize == 0);
|
|
|
|
Check(hWnd, R_SEND_ENABLE, tcp.SendWindowSize != 0);
|
|
|
|
SetInt(hWnd, E_SEND, tcp.SendWindowSize != 0 ? tcp.SendWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);
|
|
|
|
|
|
|
|
TcpIpDlgUpdate(hWnd);
|
|
|
|
|
|
|
|
Top(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the dialog
|
|
|
|
void TcpIpDlgUpdate(HWND hWnd)
|
|
|
|
{
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
SetEnable(hWnd, E_RECV, IsChecked(hWnd, R_RECV_ENABLE));
|
|
|
|
SetEnable(hWnd, S_RECV, IsChecked(hWnd, R_RECV_ENABLE));
|
|
|
|
SetEnable(hWnd, E_SEND, IsChecked(hWnd, R_SEND_ENABLE));
|
|
|
|
SetEnable(hWnd, S_SEND, IsChecked(hWnd, R_SEND_ENABLE));
|
|
|
|
|
|
|
|
if (IsChecked(hWnd, R_RECV_ENABLE) && GetInt(hWnd, E_RECV) < 1454)
|
|
|
|
{
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsChecked(hWnd, R_SEND_ENABLE) && GetInt(hWnd, E_SEND) < 1454)
|
|
|
|
{
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnable(hWnd, IDOK, ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP/IP dialog procedure
|
|
|
|
UINT TcpIpDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
MS_TCP tcp, old;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
TcpIpDlgInit(hWnd);
|
|
|
|
|
|
|
|
if (g_tcpip_topmost)
|
|
|
|
{
|
|
|
|
Top(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case R_RECV_DISABLE:
|
|
|
|
case R_RECV_ENABLE:
|
|
|
|
case R_SEND_DISABLE:
|
|
|
|
case R_SEND_ENABLE:
|
|
|
|
case E_RECV:
|
|
|
|
case E_SEND:
|
|
|
|
TcpIpDlgUpdate(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
Zero(&tcp, sizeof(tcp));
|
|
|
|
|
|
|
|
if (IsChecked(hWnd, R_RECV_ENABLE))
|
|
|
|
{
|
|
|
|
tcp.RecvWindowSize = GetInt(hWnd, E_RECV);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsChecked(hWnd, R_SEND_ENABLE))
|
|
|
|
{
|
|
|
|
tcp.SendWindowSize = GetInt(hWnd, E_SEND);
|
|
|
|
}
|
|
|
|
|
|
|
|
MsGetTcpConfig(&old);
|
|
|
|
|
|
|
|
MsSetTcpConfig(&tcp);
|
|
|
|
MsSaveTcpConfigReg(&tcp);
|
|
|
|
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case R_RECV_ENABLE:
|
|
|
|
FocusEx(hWnd, E_RECV);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case R_SEND_ENABLE:
|
|
|
|
FocusEx(hWnd, E_SEND);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_RECV:
|
|
|
|
SetInt(hWnd, E_RECV, DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);
|
|
|
|
Check(hWnd, R_RECV_DISABLE, false);
|
|
|
|
Check(hWnd, R_RECV_ENABLE, true);
|
|
|
|
TcpIpDlgUpdate(hWnd);
|
|
|
|
FocusEx(hWnd, E_RECV);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_SEND:
|
|
|
|
SetInt(hWnd, E_SEND, DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);
|
|
|
|
Check(hWnd, R_SEND_DISABLE, false);
|
|
|
|
Check(hWnd, R_SEND_ENABLE, true);
|
|
|
|
TcpIpDlgUpdate(hWnd);
|
|
|
|
FocusEx(hWnd, E_SEND);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_DELETE:
|
|
|
|
Zero(&tcp, sizeof(tcp));
|
|
|
|
MsSetTcpConfig(&tcp);
|
|
|
|
MsDeleteTcpConfigReg();
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Warning dialog about 64-bit
|
|
|
|
UINT Cpu64DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetIcon(hWnd, 0, ICO_WARNING);
|
|
|
|
DlgFont(hWnd, S_BOLD, 9, true);
|
|
|
|
SetTimer(hWnd, 1, 30 * 1000, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
Command(hWnd, IDOK);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Display a warning dialog about 64-bit
|
|
|
|
void ShowCpu64Warning()
|
|
|
|
{
|
|
|
|
Dialog(NULL, D_CPU64_WARNING, Cpu64DlgProc, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the TCP/IP configuration utility
|
|
|
|
void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode)
|
|
|
|
{
|
|
|
|
if (MsIsTcpConfigSupported() == false)
|
|
|
|
{
|
|
|
|
if (util_mode)
|
|
|
|
{
|
|
|
|
// Show a message that is not supported by the current OS
|
|
|
|
if (MsIsAdmin() == false)
|
|
|
|
{
|
|
|
|
MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_ADMIN"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_SUPPORTED"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (util_mode == false)
|
|
|
|
{
|
|
|
|
// Exit immediately by start the vpncmd
|
|
|
|
wchar_t tmp[MAX_PATH];
|
|
|
|
wchar_t exedir[MAX_PATH];
|
|
|
|
HANDLE h;
|
|
|
|
|
|
|
|
GetExeDirW(exedir, sizeof(exedir));
|
|
|
|
|
2021-03-01 06:26:14 +03:00
|
|
|
UniFormat(tmp, sizeof(tmp), L"%s\\vpncmd.exe", exedir);
|
2014-01-04 17:00:08 +04:00
|
|
|
if (IsFileW(tmp))
|
|
|
|
{
|
|
|
|
RunW(tmp, L"/tool /cmd:exit", true, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable the task off-loading by netsh
|
2021-04-03 03:25:19 +03:00
|
|
|
if (true)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
|
|
|
DIRLIST *dl;
|
|
|
|
UINT i;
|
|
|
|
bool b = false;
|
|
|
|
|
|
|
|
dl = EnumDirW(exedir);
|
|
|
|
|
|
|
|
for (i = 0;i < dl->NumFiles;i++)
|
|
|
|
{
|
|
|
|
if (UniInStr(dl->File[i]->FileNameW, L"vpnbridge") ||
|
|
|
|
UniInStr(dl->File[i]->FileNameW, L"vpnserver"))
|
|
|
|
{
|
|
|
|
b = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dl);
|
|
|
|
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
// Disable the off-loading
|
|
|
|
MsDisableNetworkOffloadingEtc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Windows Firewall registration
|
|
|
|
RegistWindowsFirewallAll();
|
|
|
|
|
|
|
|
SleepThread(1000);
|
|
|
|
|
|
|
|
// Start vpnclient.exe /uihelp
|
|
|
|
h = CmExecUiHelperMain();
|
|
|
|
if (h != NULL)
|
|
|
|
{
|
|
|
|
CloseHandle(h);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Is64() == false)
|
|
|
|
{
|
|
|
|
if (MsIs64BitWindows())
|
|
|
|
{
|
|
|
|
// Show a warning message if a 32-bit version is used in 64-bit Windows
|
|
|
|
ShowCpu64Warning();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MsIsAdmin())
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
// If installing on Windows Vista,
|
|
|
|
// dispel the network limitation of MMCSS
|
|
|
|
if (MsIsMMCSSNetworkThrottlingEnabled())
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
MsSetMMCSSNetworkThrottlingEnable(false);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (util_mode == false && MsIsShouldShowTcpConfigApp() == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (util_mode == false)
|
|
|
|
{
|
|
|
|
// 2006.07.04 nobori
|
|
|
|
// I decided not to show TCP/IP optimization utility in the installer
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_tcpip_topmost = util_mode ? false : true;
|
|
|
|
|
|
|
|
if (util_mode == false)
|
|
|
|
{
|
|
|
|
UINT ret = Dialog(hWnd, D_TCP_MSG, TcpMsgDlgProc, NULL);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
MS_TCP tcp;
|
|
|
|
|
|
|
|
Zero(&tcp, sizeof(tcp));
|
|
|
|
MsGetTcpConfig(&tcp);
|
|
|
|
MsSaveTcpConfigReg(&tcp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (ret == 1)
|
|
|
|
{
|
|
|
|
MS_TCP tcp;
|
|
|
|
|
|
|
|
Zero(&tcp, sizeof(tcp));
|
|
|
|
|
|
|
|
tcp.RecvWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_RECV;
|
|
|
|
tcp.SendWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_SEND;
|
|
|
|
MsSetTcpConfig(&tcp);
|
|
|
|
MsSaveTcpConfigReg(&tcp);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Dialog(hWnd, D_TCP, TcpIpDlgProc, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Internationalization of menu (Unicode)
|
|
|
|
void InitMenuInternationalUni(HMENU hMenu, char *prefix)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || prefix == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of items in the menu
|
|
|
|
num = GetMenuItemCount(hMenu);
|
|
|
|
|
|
|
|
// Enumerate the menu items
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
HMENU hSubMenu = GetSubMenu(hMenu, i);
|
|
|
|
MENUITEMINFOW info;
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
|
|
|
|
if (hSubMenu != NULL)
|
|
|
|
{
|
|
|
|
// If there is a sub-menu, call it recursively
|
|
|
|
InitMenuInternational(hSubMenu, prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the menu item
|
|
|
|
Zero(&info, sizeof(info));
|
|
|
|
info.cbSize = sizeof(info);
|
|
|
|
info.cch = sizeof(tmp);
|
|
|
|
info.dwTypeData = tmp;
|
|
|
|
info.fMask = MIIM_STRING;
|
|
|
|
Zero(tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
if (GetMenuItemInfoW(hMenu, i, true, &info))
|
|
|
|
{
|
|
|
|
if (tmp[0] == L'@')
|
|
|
|
{
|
|
|
|
char name[256];
|
|
|
|
wchar_t *ret;
|
|
|
|
|
|
|
|
Format(name, sizeof(name), "%s@%S", prefix, &tmp[1]);
|
|
|
|
|
|
|
|
ret = _UU(name);
|
|
|
|
if (UniIsEmptyStr(ret) == false)
|
|
|
|
{
|
|
|
|
UniStrCpy(tmp, sizeof(tmp), ret);
|
|
|
|
info.cch = UniStrLen(tmp);
|
|
|
|
|
|
|
|
SetMenuItemInfoW(hMenu, i, true, &info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Internationalization of menu
|
|
|
|
void InitMenuInternational(HMENU hMenu, char *prefix)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || prefix == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
InitMenuInternationalUni(hMenu, prefix);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the default font for the dialog box
|
|
|
|
HFONT GetDialogDefaultFont()
|
|
|
|
{
|
|
|
|
return GetDialogDefaultFontEx(false);
|
|
|
|
}
|
|
|
|
HFONT GetDialogDefaultFontEx(bool meiryo)
|
|
|
|
{
|
|
|
|
char *default_font_name = _SS("DEFAULT_FONT");
|
|
|
|
UINT default_font_size = _II("DEFAULT_FONT_SIZE");
|
|
|
|
char *win7_font = _SS("DEFAULT_FONT_WIN7");
|
|
|
|
|
|
|
|
if (meiryo)
|
|
|
|
{
|
|
|
|
if (_GETLANG() == 2)
|
|
|
|
{
|
|
|
|
default_font_name = "Microsoft YaHei";
|
|
|
|
}
|
2017-12-02 01:04:57 +03:00
|
|
|
if (_GETLANG() == 3)
|
2015-05-19 19:19:22 +03:00
|
|
|
{
|
|
|
|
default_font_name = "Microsoft JhengHei";
|
|
|
|
}
|
2014-01-04 17:00:08 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
default_font_name = GetMeiryoFontName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MsIsWindows7())
|
|
|
|
{
|
|
|
|
if (IsEmptyStr(win7_font) == false)
|
|
|
|
{
|
|
|
|
default_font_name = win7_font;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetTextScalingFactor() >= 1.44)
|
|
|
|
{
|
|
|
|
// Use a substitute font in the case of high-DPI in Windows 7 and later
|
|
|
|
char *alternative_font = _SS("DEFAULT_FONT_HIGHDPI");
|
|
|
|
|
|
|
|
if (IsEmptyStr(alternative_font) == false)
|
|
|
|
{
|
|
|
|
default_font_name = alternative_font;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEmptyStr(default_font_name))
|
|
|
|
{
|
|
|
|
default_font_name = font_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (default_font_size == 0)
|
|
|
|
{
|
|
|
|
default_font_size = 9;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetFont(default_font_name, default_font_size, false, false, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the control size and window size
|
|
|
|
void AdjustWindowAndControlSize(HWND hWnd, bool *need_resize, double *factor_x, double *factor_y)
|
|
|
|
{
|
|
|
|
HFONT hDlgFont;
|
|
|
|
UINT dlgfont_x, dlgfont_y;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || need_resize == NULL || factor_x == NULL || factor_y == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*need_resize = true;
|
|
|
|
|
|
|
|
// Get the font of the current window
|
|
|
|
hDlgFont = (HFONT)SendMsg(hWnd, 0, WM_GETFONT, 0, 0);
|
|
|
|
|
|
|
|
// Get the width and height of the font of the current window
|
|
|
|
CalcFontSize(hDlgFont, &dlgfont_x, &dlgfont_y);
|
|
|
|
|
|
|
|
if ((dlgfont_x == WINUI_DEFAULT_DIALOG_UNIT_X) &&
|
|
|
|
(dlgfont_y == WINUI_DEFAULT_DIALOG_UNIT_Y))
|
|
|
|
{
|
|
|
|
// There is no need to adjust
|
|
|
|
*need_resize = false;
|
|
|
|
*factor_x = 1.0;
|
|
|
|
*factor_y = 1.0;
|
2015-03-27 14:52:15 +03:00
|
|
|
//Debug("// There is no need to adjust\n");
|
2014-01-04 17:00:08 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the adjustment amount
|
|
|
|
*factor_x = (double)dlgfont_x / (double)WINUI_DEFAULT_DIALOG_UNIT_X;
|
|
|
|
*factor_y = (double)dlgfont_y / (double)WINUI_DEFAULT_DIALOG_UNIT_Y;
|
2015-03-27 14:52:15 +03:00
|
|
|
//Debug("Factors: %f %f\n", *factor_x, *factor_y);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the values of x and y according to the font
|
|
|
|
void AdjustDialogXY(UINT *x, UINT *y, UINT dlgfont_x, UINT dlgfont_y)
|
|
|
|
{
|
|
|
|
if (x != NULL)
|
|
|
|
{
|
|
|
|
*x = (UINT)(((double)*x) * (double)WINUI_DEFAULT_DIALOG_UNIT_X / (double)dlgfont_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y != NULL)
|
|
|
|
{
|
|
|
|
*y = (UINT)(((double)*y) * (double)WINUI_DEFAULT_DIALOG_UNIT_Y / (double)dlgfont_y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Internationalizing process for the dialog box
|
|
|
|
void InitDialogInternational(HWND hWnd, void *pparam)
|
|
|
|
{
|
|
|
|
LIST *o;
|
|
|
|
UINT i;
|
|
|
|
bool is_managed_dialog = false;
|
|
|
|
char caption[MAX_PATH];
|
|
|
|
char *dialog_name;
|
|
|
|
DIALOG_PARAM *param = (DIALOG_PARAM *)pparam;
|
|
|
|
HDC hDC;
|
|
|
|
bool need_resize = false;
|
|
|
|
double factor_x = 0.0, factor_y = 0.0;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || param == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hDC = CreateCompatibleDC(NULL);
|
|
|
|
|
|
|
|
AdjustWindowAndControlSize(hWnd, &need_resize, &factor_x, &factor_y);
|
|
|
|
|
|
|
|
GetTxtA(hWnd, 0, caption, sizeof(caption));
|
|
|
|
if (caption[0] == '@')
|
|
|
|
{
|
|
|
|
dialog_name = &caption[1];
|
|
|
|
|
|
|
|
is_managed_dialog = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enumerate all window handles
|
|
|
|
o = EnumAllChildWindow(hWnd);
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(o);i++)
|
|
|
|
{
|
|
|
|
HWND hControl = *((HWND *)LIST_DATA(o, i));
|
|
|
|
|
|
|
|
if (hControl != NULL)
|
|
|
|
{
|
2016-04-24 17:49:31 +03:00
|
|
|
bool set_font = true;
|
2014-01-04 17:00:08 +04:00
|
|
|
HFONT hFont = GetDialogDefaultFontEx(param && ((DIALOG_PARAM *)param)->meiryo);
|
|
|
|
|
2016-04-24 17:49:31 +03:00
|
|
|
if (MsIsWine())
|
|
|
|
{
|
|
|
|
char classname[MAX_PATH];
|
|
|
|
char parent_classname[MAX_PATH];
|
|
|
|
HWND hParent = GetParent(hControl);
|
|
|
|
|
|
|
|
Zero(classname, sizeof(classname));
|
|
|
|
Zero(parent_classname, sizeof(parent_classname));
|
|
|
|
|
|
|
|
GetClassNameA(hControl, classname, sizeof(classname));
|
|
|
|
|
|
|
|
if (hParent != NULL)
|
|
|
|
{
|
|
|
|
GetClassNameA(hParent, parent_classname, sizeof(parent_classname));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrCmpi(classname, "edit") == 0)
|
|
|
|
{
|
|
|
|
set_font = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrCmpi(classname, "combobox") == 0)
|
|
|
|
{
|
|
|
|
set_font = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrCmpi(classname, "syslistview32") == 0)
|
|
|
|
{
|
|
|
|
set_font = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrCmpi(classname, "sysheader32") == 0)
|
|
|
|
{
|
|
|
|
set_font = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrCmpi(parent_classname, "SysIPAddress32") == 0 ||
|
|
|
|
StrCmpi(classname, "SysIPAddress32") == 0)
|
|
|
|
{
|
|
|
|
set_font = true;
|
|
|
|
hFont = GetFont("Tahoma", 8, false, false, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (set_font)
|
|
|
|
{
|
|
|
|
SetFont(hControl, 0, hFont);
|
|
|
|
}
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
char classname[MAX_PATH];
|
|
|
|
GetClassNameA(hControl, classname, sizeof(classname));
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
if (StrCmpi(classname, "syslistview32") == 0)
|
|
|
|
{
|
|
|
|
InitVistaWindowTheme(hControl);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (is_managed_dialog)
|
|
|
|
{
|
|
|
|
char str[MAX_PATH];
|
|
|
|
|
|
|
|
GetTxtA(hControl, 0, str, sizeof(str));
|
|
|
|
if (str[0] == '@')
|
|
|
|
{
|
|
|
|
char *control_name = &str[1];
|
|
|
|
char tmp[MAX_PATH];
|
|
|
|
wchar_t *ret;
|
|
|
|
|
|
|
|
StrCpy(tmp, sizeof(tmp), dialog_name);
|
|
|
|
StrCat(tmp, sizeof(tmp), "@");
|
|
|
|
|
|
|
|
if (hWnd == hControl)
|
|
|
|
{
|
|
|
|
StrCat(tmp, sizeof(tmp), "CAPTION");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StrCat(tmp, sizeof(tmp), control_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = _UU(tmp);
|
|
|
|
|
|
|
|
if (ret != NULL && UniIsEmptyStr(ret) == false)
|
|
|
|
{
|
|
|
|
SetText(hControl, 0, ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeWindowList(o);
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
if (need_resize)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
|
|
|
// Since the window size is changed automatically by the OS by the dpi setting
|
|
|
|
// in Windows Vista or later, a static (bitmap) control needs to be expanded
|
|
|
|
// by anticipating the size after changing
|
|
|
|
|
|
|
|
// Enumerate all child window (not recursive)
|
|
|
|
o = EnumAllChildWindowEx(hWnd, true, false, true);
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(o);i++)
|
|
|
|
{
|
|
|
|
HWND hControl = *((HWND *)LIST_DATA(o, i));
|
|
|
|
|
|
|
|
if (hControl != NULL)
|
|
|
|
{
|
|
|
|
char class_name[MAX_SIZE];
|
|
|
|
|
|
|
|
Zero(class_name, sizeof(class_name));
|
|
|
|
GetClassNameA(hControl, class_name, sizeof(class_name));
|
|
|
|
|
|
|
|
if (StrCmpi(class_name, "static") == 0)
|
|
|
|
{
|
|
|
|
UINT style = GetStyle(hControl, 0);
|
|
|
|
|
|
|
|
if (style & SS_BITMAP)
|
|
|
|
{
|
|
|
|
// Get the Bitmap
|
|
|
|
HBITMAP hBitmap = (HBITMAP)SendMessage(hControl, STM_GETIMAGE, IMAGE_BITMAP, 0);
|
|
|
|
|
|
|
|
if (hBitmap != NULL)
|
|
|
|
{
|
|
|
|
// Get the size of this bitmap
|
|
|
|
UINT src_x;
|
|
|
|
UINT src_y;
|
|
|
|
|
|
|
|
if (GetBitmapSize(hBitmap, &src_x, &src_y))
|
|
|
|
{
|
|
|
|
RECT ctl_rect;
|
|
|
|
|
|
|
|
Zero(&ctl_rect, sizeof(ctl_rect));
|
|
|
|
|
|
|
|
if (GetWindowRect(hControl, &ctl_rect))
|
|
|
|
{
|
|
|
|
// Use the smaller magnification of the height and the width
|
|
|
|
//double scale_factor = 1.5;
|
|
|
|
double scale_factor = MIN(factor_x, factor_y);
|
|
|
|
UINT dst_x = (UINT)((double)src_x * scale_factor);
|
|
|
|
UINT dst_y = (UINT)((double)src_y * scale_factor);
|
|
|
|
|
|
|
|
HBITMAP hDst = ResizeBitmap(hBitmap, src_x, src_y, dst_x, dst_y);
|
|
|
|
|
|
|
|
if (hDst != NULL)
|
|
|
|
{
|
|
|
|
Add(param->BitmapList, hDst);
|
|
|
|
|
|
|
|
SendMessage(hControl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hDst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeWindowList(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteDC(hDC);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the size of the bitmap
|
|
|
|
bool GetBitmapSize(void *bmp, UINT *x, UINT *y)
|
|
|
|
{
|
|
|
|
BITMAP info;
|
|
|
|
// Validate arguments
|
|
|
|
if (bmp == NULL || x == NULL || y == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&info, sizeof(info));
|
|
|
|
if (GetObject((HANDLE)bmp, sizeof(info), &info) == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*x = info.bmWidth;
|
|
|
|
*y = info.bmHeight;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resize the bitmap
|
|
|
|
HBITMAP ResizeBitmap(HBITMAP hSrc, UINT src_x, UINT src_y, UINT dst_x, UINT dst_y)
|
|
|
|
{
|
|
|
|
HDC hMemDC;
|
|
|
|
HDC hSrcDC;
|
|
|
|
HBITMAP ret = NULL;
|
|
|
|
BITMAPINFOHEADER h;
|
|
|
|
BITMAPINFO bi;
|
|
|
|
UCHAR *data = NULL;
|
|
|
|
// Validate arguments
|
|
|
|
if (hSrc == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hSrcDC = CreateCompatibleDC(NULL);
|
|
|
|
if (hSrcDC != NULL)
|
|
|
|
{
|
|
|
|
HBITMAP hOld = SelectObject(hSrcDC, hSrc);
|
|
|
|
|
|
|
|
if (hOld != NULL)
|
|
|
|
{
|
|
|
|
hMemDC = CreateCompatibleDC(NULL);
|
|
|
|
|
|
|
|
if (hMemDC != NULL)
|
|
|
|
{
|
|
|
|
HBITMAP hOld;
|
|
|
|
HBITMAP srcHbitMap;
|
|
|
|
UCHAR* srcData;
|
|
|
|
CT_RectF_c destRect;
|
|
|
|
CT_RectF_c srcRect;
|
|
|
|
|
|
|
|
Zero(&h, sizeof(h));
|
|
|
|
h.biSize = sizeof(h);
|
|
|
|
h.biWidth = src_x;
|
|
|
|
h.biHeight = src_y;
|
|
|
|
h.biPlanes = 1;
|
|
|
|
h.biBitCount = 32;
|
|
|
|
h.biXPelsPerMeter = 2834;
|
|
|
|
h.biYPelsPerMeter = 2834;
|
|
|
|
h.biCompression = BI_RGB;
|
|
|
|
|
|
|
|
// Copy once the transfer source
|
|
|
|
Zero(&bi, sizeof(bi));
|
|
|
|
Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));
|
|
|
|
srcHbitMap = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, &srcData, NULL, 0);
|
|
|
|
|
|
|
|
hOld = SelectObject(hMemDC, srcHbitMap);
|
|
|
|
|
|
|
|
BitBlt(hMemDC,0,0,src_x,src_y,hSrcDC,0,0, SRCCOPY);
|
|
|
|
|
|
|
|
GdiFlush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate a resized version
|
|
|
|
if(src_x != dst_x || src_y != dst_y)
|
|
|
|
{
|
|
|
|
h.biWidth = dst_x;
|
|
|
|
h.biHeight = dst_y;
|
|
|
|
Zero(&bi, sizeof(bi));
|
|
|
|
Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));
|
|
|
|
|
|
|
|
ret = CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, &data, NULL, 0);
|
|
|
|
|
|
|
|
if(srcData != NULL && data != NULL)
|
|
|
|
{
|
|
|
|
destRect.X = 0; destRect.Y = 0;
|
|
|
|
destRect.Width = (float)dst_x; destRect.Height = (float)dst_y;
|
|
|
|
srcRect = destRect;
|
|
|
|
srcRect.Width = (float)src_x; srcRect.Height = (float)src_y;
|
|
|
|
|
|
|
|
CT_DrawImage((UCHAR*)data, destRect, dst_x,dst_y,
|
|
|
|
(UCHAR*)srcData, srcRect,src_x, src_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(srcHbitMap != NULL)
|
|
|
|
{
|
|
|
|
DeleteObject(srcHbitMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = srcHbitMap;
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectObject(hMemDC, hOld);
|
|
|
|
|
|
|
|
DeleteDC(hMemDC);
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectObject(hSrcDC, hOld);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteDC(hSrcDC);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the bitmap list
|
|
|
|
LIST *NewBitmapList()
|
|
|
|
{
|
|
|
|
LIST *o = NewListFast(NULL);
|
|
|
|
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the bitmap list
|
|
|
|
void FreeBitmapList(LIST *o)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (o == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(o);i++)
|
|
|
|
{
|
|
|
|
HBITMAP *h = LIST_DATA(o, i);
|
|
|
|
|
|
|
|
DeleteObject(h);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseList(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Child window enumeration procedure
|
|
|
|
// Initialize the dialog
|
|
|
|
void StringDlgInit(HWND hWnd, STRING_DLG *s)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || s == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetText(hWnd, E_STRING, s->String);
|
|
|
|
|
|
|
|
SetIcon(hWnd, S_ICON, s->Icon);
|
|
|
|
SetText(hWnd, S_INFO, s->Info);
|
|
|
|
SetText(hWnd, 0, s->Title);
|
|
|
|
|
|
|
|
FocusEx(hWnd, E_STRING);
|
|
|
|
|
|
|
|
StringDlgUpdate(hWnd, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the dialog control
|
|
|
|
void StringDlgUpdate(HWND hWnd, STRING_DLG *s)
|
|
|
|
{
|
|
|
|
wchar_t *tmp;
|
|
|
|
bool b = true;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || s == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = GetText(hWnd, E_STRING);
|
|
|
|
|
|
|
|
if (tmp != NULL)
|
|
|
|
{
|
|
|
|
if (s->AllowEmpty == false)
|
|
|
|
{
|
|
|
|
if (UniIsEmptyStr(tmp))
|
|
|
|
{
|
|
|
|
b = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->AllowUnsafe == false)
|
|
|
|
{
|
|
|
|
if (IsSafeUniStr(tmp) == false)
|
|
|
|
{
|
|
|
|
b = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnable(hWnd, IDOK, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
// String dialog procedure
|
|
|
|
UINT StringDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
STRING_DLG *s = (STRING_DLG *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
StringDlgInit(hWnd, s);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case E_STRING:
|
|
|
|
StringDlgUpdate(hWnd, s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
GetTxt(hWnd, E_STRING, s->String, sizeof(s->String));
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the string dialog
|
|
|
|
wchar_t *StringDlg(HWND hWnd, wchar_t *title, wchar_t *info, wchar_t *def, UINT icon, bool allow_empty, bool allow_unsafe)
|
|
|
|
{
|
|
|
|
STRING_DLG s;
|
|
|
|
// Validate arguments
|
|
|
|
if (title == NULL)
|
|
|
|
{
|
|
|
|
title = _UU("DLG_STRING_DEFTITLE");
|
|
|
|
}
|
|
|
|
if (info == NULL)
|
|
|
|
{
|
|
|
|
info = _UU("DLG_STRING_DEFINFO");
|
|
|
|
}
|
|
|
|
if (def == NULL)
|
|
|
|
{
|
|
|
|
def = L"";
|
|
|
|
}
|
|
|
|
if (icon == 0)
|
|
|
|
{
|
|
|
|
icon = ICO_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&s, sizeof(s));
|
|
|
|
s.Icon = icon;
|
|
|
|
s.Info = info;
|
|
|
|
s.Title = title;
|
|
|
|
s.Icon = icon;
|
|
|
|
UniStrCpy(s.String, sizeof(s.String), def);
|
|
|
|
s.AllowEmpty = allow_empty;
|
|
|
|
s.AllowUnsafe = allow_unsafe;
|
|
|
|
|
|
|
|
if (Dialog(hWnd, D_STRING, StringDlgProc, &s) == false)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return CopyUniStr(s.String);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char *StringDlgA(HWND hWnd, wchar_t *title, wchar_t *info, char *def, UINT icon, bool allow_empty, bool allow_unsafe)
|
|
|
|
{
|
|
|
|
wchar_t unidef[MAX_SIZE];
|
|
|
|
wchar_t *tmp;
|
|
|
|
char *ret;
|
|
|
|
if (def == NULL)
|
|
|
|
{
|
|
|
|
def = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
StrToUni(unidef, sizeof(unidef), def);
|
|
|
|
|
|
|
|
tmp = StringDlg(hWnd, title, info, unidef, icon, allow_empty, allow_unsafe);
|
|
|
|
if (tmp == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = CopyUniToStr(tmp);
|
|
|
|
Free(tmp);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show a text file
|
|
|
|
void ShowTextFile(HWND hWnd, char *filename, wchar_t *caption, UINT icon)
|
|
|
|
{
|
|
|
|
BUF *b;
|
|
|
|
wchar_t *str;
|
|
|
|
// Validate arguments
|
|
|
|
if (filename == NULL || caption == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (icon == 0)
|
|
|
|
{
|
|
|
|
icon = ICO_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the text file
|
|
|
|
b = ReadDump(filename);
|
|
|
|
if (b == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SeekBufToEnd(b);
|
|
|
|
WriteBufChar(b, 0);
|
|
|
|
|
|
|
|
str = CopyUtfToUni(b->Buf);
|
|
|
|
|
|
|
|
OnceMsg(hWnd, caption, str, false, icon);
|
|
|
|
|
|
|
|
FreeBuf(b);
|
|
|
|
Free(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the version information
|
|
|
|
void AboutDlgInit(HWND hWnd, WINUI_ABOUT *a)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || a == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, ICO_INFORMATION);
|
|
|
|
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("ABOUT_CAPTION"), a->ProductName);
|
|
|
|
SetText(hWnd, 0, tmp);
|
|
|
|
|
|
|
|
SetFont(hWnd, S_INFO1, GetFont("Arial", 12, false, false, false, false));
|
2018-08-27 06:35:11 +03:00
|
|
|
FormatText(hWnd, S_INFO1, CEDAR_VERSION_MAJOR, CEDAR_VERSION_MAJOR, CEDAR_VERSION_MINOR, CEDAR_VERSION_BUILD);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
SetFont(hWnd, S_INFO2, GetFont("Arial", 8, false, false, false, false));
|
|
|
|
FormatText(hWnd, S_INFO2, BUILD_DATE_Y, a->Cedar->BuildInfo);
|
|
|
|
|
|
|
|
SetFont(hWnd, S_INFO3, GetFont("Arial", 7, false, false, false, false));
|
|
|
|
|
2016-04-24 17:49:31 +03:00
|
|
|
if (MsIsWine())
|
|
|
|
{
|
|
|
|
Disable(hWnd, B_LANGUAGE);
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
//DlgFont(hWnd, S_INFO4, 8, false);
|
|
|
|
|
|
|
|
SetShow(hWnd, B_UPDATE_CONFIG, (a->Update != NULL));
|
2014-03-20 00:45:05 +04:00
|
|
|
|
|
|
|
Show(hWnd, B_AUTHORS);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Version information procedure
|
|
|
|
UINT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
WINUI_ABOUT *a = (WINUI_ABOUT *)param;
|
|
|
|
char tmp[MAX_PATH];
|
|
|
|
LANGLIST t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
AboutDlgInit(hWnd, a);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
case IDCANCEL:
|
|
|
|
if ((GetKeyState(VK_SHIFT) & 0x8000) &&
|
|
|
|
(GetKeyState(VK_CONTROL) & 0x8000) &&
|
|
|
|
(GetKeyState(VK_MENU) & 0x8000))
|
|
|
|
{
|
|
|
|
ShowEasterEgg(hWnd);
|
|
|
|
}
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
break;
|
|
|
|
case B_WEB:
|
|
|
|
ShellExecute(hWnd, "open", _SS("SE_COMPANY_URL"), NULL, NULL, SW_SHOW);
|
|
|
|
break;
|
|
|
|
case B_EULA:
|
|
|
|
ShowTextFile(hWnd, "|eula.txt", _UU("SW_EULA_TITLE"), ICO_LOG);
|
|
|
|
break;
|
|
|
|
case B_IMPORTANT:
|
|
|
|
GetCurrentLang(&t);
|
|
|
|
Format(tmp, sizeof(tmp), "|warning_%s.txt", t.Name);
|
|
|
|
ShowTextFile(hWnd, tmp, _UU("SW_WARNING_TITLE"), ICO_LOG);
|
|
|
|
break;
|
|
|
|
case B_LEGAL:
|
|
|
|
ShowTextFile(hWnd, "|legal.txt", _UU("DLG_ABOUT_LEGAL"), ICO_LOG);
|
|
|
|
break;
|
|
|
|
case B_UPDATE_CONFIG:
|
|
|
|
ConfigUpdateUi(a->Update, hWnd);
|
|
|
|
break;
|
2014-03-20 00:45:05 +04:00
|
|
|
case B_AUTHORS:
|
|
|
|
ShowTextFile(hWnd, "|authors.txt", _UU("DLG_ABOUT_AUTHORS"), ICO_ZURUHAM);
|
|
|
|
break;
|
2014-01-04 17:00:08 +04:00
|
|
|
case B_LANGUAGE:
|
|
|
|
// Language settings
|
|
|
|
if (true)
|
|
|
|
{
|
|
|
|
wchar_t path[MAX_SIZE];
|
|
|
|
|
|
|
|
CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"vpnsetup.exe");
|
|
|
|
|
2014-02-05 20:36:42 +04:00
|
|
|
if (IsFileExistsW(path))
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
2014-02-05 20:36:42 +04:00
|
|
|
// with Installer
|
|
|
|
if (MsExecuteW(path, L"/language:yes") == false)
|
|
|
|
{
|
|
|
|
MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// without Installer
|
|
|
|
CombinePathW(path, sizeof(path), MsGetExeDirNameW(), L"lang.config");
|
|
|
|
if (MsExecuteW(path, L"") == false)
|
|
|
|
{
|
|
|
|
MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_CHILD_PROCESS_ERROR"));
|
|
|
|
}
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Version information
|
|
|
|
void About(HWND hWnd, CEDAR *cedar, wchar_t *product_name)
|
|
|
|
{
|
|
|
|
AboutEx(hWnd, cedar, product_name, NULL);
|
|
|
|
}
|
|
|
|
void AboutEx(HWND hWnd, CEDAR *cedar, wchar_t *product_name, WINUI_UPDATE *u)
|
|
|
|
{
|
|
|
|
WINUI_ABOUT a;
|
|
|
|
// Validate arguments
|
|
|
|
if (cedar == NULL || product_name == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&a, sizeof(a));
|
|
|
|
a.Cedar = cedar;
|
|
|
|
a.ProductName = product_name;
|
|
|
|
a.Update = u;
|
|
|
|
|
|
|
|
Dialog(hWnd, D_ABOUT, AboutDlgProc, &a);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examine the number of fields that an IP address is entered
|
|
|
|
UINT IpGetFilledNum(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
DWORD value;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examine whether an IP address has been entered
|
|
|
|
bool IpIsFilled(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
DWORD value;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
|
|
|
|
|
|
|
|
if (ret != 4)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get an IP address
|
|
|
|
UINT IpGet(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
DWORD value;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);
|
|
|
|
|
|
|
|
if (ret != 4)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Endian32((UINT)value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the IP addresses
|
|
|
|
void IpSet(HWND hWnd, UINT id, UINT ip)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, IPM_SETADDRESS, 0, Endian32(ip));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the candidates to the registry
|
|
|
|
void WriteCandidateToReg(UINT root, char *key, LIST *o, char *name)
|
|
|
|
{
|
|
|
|
BUF *b;
|
|
|
|
// Validate arguments
|
|
|
|
if (key == NULL || o == NULL || name == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
b = CandidateToBuf(o);
|
|
|
|
if (b == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MsRegWriteBin(root, key, name, b->Buf, b->Size);
|
|
|
|
|
|
|
|
FreeBuf(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the candidates from the registry
|
|
|
|
LIST *ReadCandidateFromReg(UINT root, char *key, char *name)
|
|
|
|
{
|
|
|
|
BUF *b;
|
|
|
|
// Validate arguments
|
|
|
|
if (key == NULL || name == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
b = MsRegReadBin(root, key, name);
|
|
|
|
if (b == NULL)
|
|
|
|
{
|
|
|
|
return NewCandidateList();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LIST *o = BufToCandidate(b);
|
|
|
|
FreeBuf(b);
|
|
|
|
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// initialize the remote connection dialog
|
|
|
|
void RemoteDlgInit(HWND hWnd, WINUI_REMOTE *r)
|
|
|
|
{
|
|
|
|
LIST *o;
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || r == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, r->Icon);
|
|
|
|
|
|
|
|
SetText(hWnd, 0, r->Caption);
|
|
|
|
SetText(hWnd, S_TITLE, r->Title);
|
|
|
|
SetIcon(hWnd, S_ICON, r->Icon);
|
|
|
|
|
|
|
|
// Read candidates
|
|
|
|
o = ReadCandidateFromReg(REG_CURRENT_USER, r->RegKeyName, "RemoteHostCandidate");
|
|
|
|
r->CandidateList = o;
|
|
|
|
|
|
|
|
// Show the candidates
|
|
|
|
for (i = 0;i < LIST_NUM(o);i++)
|
|
|
|
{
|
|
|
|
CANDIDATE *c = LIST_DATA(o, i);
|
|
|
|
CbAddStr(hWnd, C_HOSTNAME, c->Str, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r->DefaultHostname != NULL)
|
|
|
|
{
|
|
|
|
SetTextA(hWnd, C_HOSTNAME, r->DefaultHostname);
|
|
|
|
}
|
|
|
|
|
|
|
|
FocusEx(hWnd, C_HOSTNAME);
|
|
|
|
|
|
|
|
RemoteDlgRefresh(hWnd, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remote connection dialog update
|
|
|
|
void RemoteDlgRefresh(HWND hWnd, WINUI_REMOTE *r)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
bool ok = true;
|
|
|
|
bool localhost_mode = false;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || r == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetTextA(hWnd, C_HOSTNAME);
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
Trim(s);
|
|
|
|
if (StrCmpi(s, "localhost") == 0 || StartWith(s, "127."))
|
|
|
|
{
|
|
|
|
localhost_mode = true;
|
|
|
|
}
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (localhost_mode == false)
|
|
|
|
{
|
|
|
|
Enable(hWnd, C_HOSTNAME);
|
|
|
|
Enable(hWnd, S_HOSTNAME);
|
|
|
|
Check(hWnd, R_LOCAL, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (r->Title != _UU("NM_CONNECT_TITLE"))
|
|
|
|
{
|
|
|
|
Disable(hWnd, C_HOSTNAME);
|
|
|
|
Disable(hWnd, S_HOSTNAME);
|
|
|
|
}
|
|
|
|
Check(hWnd, R_LOCAL, true);
|
|
|
|
SetTextA(hWnd, C_HOSTNAME, "localhost");
|
|
|
|
|
|
|
|
if (r->flag1 == false)
|
|
|
|
{
|
|
|
|
Focus(hWnd, IDOK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEmpty(hWnd, C_HOSTNAME))
|
|
|
|
{
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnable(hWnd, IDOK, ok);
|
|
|
|
|
|
|
|
r->flag1 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remote connection dialog OK button
|
|
|
|
void RemoteDlgOnOk(HWND hWnd, WINUI_REMOTE *r)
|
|
|
|
{
|
|
|
|
char *hostname;
|
|
|
|
wchar_t *s;
|
|
|
|
LIST *o;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || r == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the entered host name
|
|
|
|
hostname = GetTextA(hWnd, C_HOSTNAME);
|
|
|
|
if (hostname == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Trim(hostname);
|
|
|
|
|
|
|
|
// Add a candidate
|
|
|
|
o = r->CandidateList;
|
|
|
|
s = CopyStrToUni(hostname);
|
|
|
|
AddCandidate(o, s, 64);
|
|
|
|
Free(s);
|
|
|
|
|
|
|
|
// Write the candidates
|
|
|
|
WriteCandidateToReg(REG_CURRENT_USER, r->RegKeyName, o, "RemoteHostCandidate");
|
|
|
|
FreeCandidateList(o);
|
|
|
|
|
|
|
|
r->Hostname = hostname;
|
|
|
|
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remote connection dialog procedure
|
|
|
|
UINT RemoteDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
WINUI_REMOTE *r = (WINUI_REMOTE *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
RemoteDlgInit(hWnd, r);
|
|
|
|
SetTimer(hWnd, 1, 100, NULL);
|
|
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
RemoteDlgRefresh(hWnd, r);
|
|
|
|
SetTimer(hWnd, 1, 100, NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case R_LOCAL:
|
|
|
|
if (IsChecked(hWnd, R_LOCAL) == false)
|
|
|
|
{
|
|
|
|
SetTextA(hWnd, C_HOSTNAME, "");
|
|
|
|
RemoteDlgRefresh(hWnd, r);
|
|
|
|
FocusEx(hWnd, C_HOSTNAME);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetTextA(hWnd, C_HOSTNAME, "localhost");
|
|
|
|
RemoteDlgRefresh(hWnd, r);
|
|
|
|
Focus(hWnd, IDOK);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
case IDOK:
|
|
|
|
RemoteDlgOnOk(hWnd, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case R_LOCAL:
|
|
|
|
case C_HOSTNAME:
|
|
|
|
RemoteDlgRefresh(hWnd, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
|
|
FreeCandidateList(r->CandidateList);
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remote connection dialog
|
|
|
|
char *RemoteDlg(HWND hWnd, char *regkey, UINT icon, wchar_t *caption, wchar_t *title, char *default_host)
|
|
|
|
{
|
|
|
|
WINUI_REMOTE r;
|
|
|
|
// Validate arguments
|
|
|
|
if (regkey == NULL)
|
|
|
|
{
|
|
|
|
regkey = "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\WinUI Common Module";
|
|
|
|
}
|
|
|
|
if (caption == NULL)
|
|
|
|
{
|
|
|
|
caption = _UU("REMOTE_DEF_CAPTION");
|
|
|
|
}
|
|
|
|
if (title == NULL)
|
|
|
|
{
|
|
|
|
title = _UU("REMOTE_DEF_TITLE");
|
|
|
|
}
|
|
|
|
if (icon == 0)
|
|
|
|
{
|
|
|
|
icon = ICO_INTERNET;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&r, sizeof(r));
|
|
|
|
r.RegKeyName = regkey;
|
|
|
|
r.Caption = caption;
|
|
|
|
r.Title = title;
|
|
|
|
r.Icon = icon;
|
|
|
|
r.DefaultHostname = default_host;
|
|
|
|
|
|
|
|
if (Dialog(hWnd, D_REMOTE, RemoteDlgProc, &r) == false)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Hostname;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Window Searching procedure
|
|
|
|
bool CALLBACK SearchWindowEnumProc(HWND hWnd, LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (hWnd != NULL && lParam != 0)
|
|
|
|
{
|
|
|
|
wchar_t *s = GetText(hWnd, 0);
|
|
|
|
SEARCH_WINDOW_PARAM *p = (SEARCH_WINDOW_PARAM *)lParam;
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(p->caption, s) == 0)
|
|
|
|
{
|
|
|
|
p->hWndFound = hWnd;
|
|
|
|
}
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for the window
|
|
|
|
HWND SearchWindow(wchar_t *caption)
|
|
|
|
{
|
|
|
|
SEARCH_WINDOW_PARAM p;
|
|
|
|
// Validate arguments
|
|
|
|
if (caption == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&p, sizeof(p));
|
|
|
|
p.caption = caption;
|
|
|
|
p.hWndFound = NULL;
|
|
|
|
|
|
|
|
EnumWindows(SearchWindowEnumProc, (LPARAM)&p);
|
|
|
|
|
|
|
|
return p.hWndFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allow for the specified process to become the foreground window
|
|
|
|
void AllowFGWindow(UINT process_id)
|
|
|
|
{
|
|
|
|
if (process_id == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
AllowSetForegroundWindow(process_id);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Rename the item
|
|
|
|
void LvRename(HWND hWnd, UINT id, UINT pos)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || pos == INFINITE)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListView_EditLabel(DlgItem(hWnd, id), pos);
|
|
|
|
}
|
|
|
|
|
2018-11-29 22:32:03 +03:00
|
|
|
// Enhanced function
|
|
|
|
LRESULT CALLBACK LvEnhancedProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
WNDPROC func = (WNDPROC)GetPropW(hWnd, L"ORIGINAL_FUNC");
|
2018-11-29 22:32:03 +03:00
|
|
|
if (func == NULL)
|
|
|
|
{
|
|
|
|
Debug("LvEnhancedProc(): GetProp() returned NULL!\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_HSCROLL:
|
|
|
|
case WM_VSCROLL:
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
{
|
|
|
|
// Prevent graphical glitches with the edit box by sending the NM_RETURN signal
|
|
|
|
// to the parent dialog (the parent dialog has to delete the edit box on NM_RETURN)
|
|
|
|
NMHDR nmh;
|
|
|
|
nmh.code = NM_RETURN;
|
|
|
|
nmh.idFrom = GetDlgCtrlID(hWnd);
|
|
|
|
nmh.hwndFrom = hWnd;
|
|
|
|
SendMsg(GetParent(hWnd), 0, WM_NOTIFY, nmh.idFrom, (LPARAM)&nmh);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
|
|
// Prevent list view from disappearing after pressing ESC in an edit box
|
|
|
|
return 0;
|
|
|
|
case WM_NCDESTROY:
|
|
|
|
// Restore original function during destruction
|
|
|
|
LvSetEnhanced(hWnd, 0, false);
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
return CallWindowProcW(func, hWnd, msg, wParam, lParam);
|
2018-11-29 22:32:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Toggle enhanced function
|
|
|
|
void LvSetEnhanced(HWND hWnd, UINT id, bool enable)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable)
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
const HANDLE fn = (HANDLE)SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)LvEnhancedProc);
|
|
|
|
SetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC", fn);
|
2018-11-29 22:32:03 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)GetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC"));
|
|
|
|
RemovePropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC");
|
2018-11-29 22:32:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enhanced function
|
|
|
|
LRESULT CALLBACK EditBoxEnhancedProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
WNDPROC func = (WNDPROC)GetPropW(hWnd, L"ORIGINAL_FUNC");
|
2018-11-29 22:32:03 +03:00
|
|
|
if (func == NULL)
|
|
|
|
{
|
|
|
|
Debug("EditBoxEnhancedProc(): GetProp() returned NULL!\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_CHAR:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
// CTRL + A
|
|
|
|
case 1:
|
|
|
|
SelectEdit(hWnd, 0);
|
|
|
|
return 0;
|
|
|
|
case VK_RETURN:
|
|
|
|
SendMsg(GetParent(hWnd), 0, WM_KEYDOWN, VK_RETURN, 0);
|
|
|
|
return 0;
|
|
|
|
case VK_ESCAPE:
|
|
|
|
DestroyWindow(hWnd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_NCDESTROY:
|
|
|
|
// Restore original function during destruction
|
|
|
|
EditBoxSetEnhanced(hWnd, 0, false);
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
return CallWindowProcW(func, hWnd, msg, wParam, lParam);
|
2018-11-29 22:32:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Toggle enhanced function
|
|
|
|
void EditBoxSetEnhanced(HWND hWnd, UINT id, bool enable)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable)
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
const HANDLE fn = (HANDLE)SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)EditBoxEnhancedProc);
|
|
|
|
SetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC", fn);
|
2018-11-29 22:32:03 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
SetWindowLongPtrW(DlgItem(hWnd, id), GWLP_WNDPROC, (LONG_PTR)GetPropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC"));
|
|
|
|
RemovePropW(DlgItem(hWnd, id), L"ORIGINAL_FUNC");
|
2018-11-29 22:32:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
// Show the menu
|
|
|
|
void PrintMenu(HWND hWnd, HMENU hMenu)
|
|
|
|
{
|
|
|
|
POINT p;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetCursorPos(&p);
|
|
|
|
|
|
|
|
TrackPopupMenu(hMenu, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove a shortcut string from the menu
|
|
|
|
void RemoveShortcutKeyStrFromMenu(HMENU hMenu)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = GetMenuNum(hMenu);
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
wchar_t *str = GetMenuStr(hMenu, i);
|
|
|
|
if (str != NULL)
|
|
|
|
{
|
|
|
|
UINT j, len;
|
|
|
|
len = UniStrLen(str);
|
|
|
|
for (j = 0;j < len;j++)
|
|
|
|
{
|
|
|
|
if (str[j] == L'\t')
|
|
|
|
{
|
|
|
|
str[j] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetMenuStr(hMenu, i, str);
|
|
|
|
Free(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of items in the menu
|
|
|
|
UINT GetMenuNum(HMENU hMenu)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = GetMenuItemCount(hMenu);
|
|
|
|
if (ret == INFINITE)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the string into the menu
|
|
|
|
void SetMenuStr(HMENU hMenu, UINT pos, wchar_t *str)
|
|
|
|
{
|
|
|
|
MENUITEMINFOW info;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || pos == INFINITE || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&info, sizeof(info));
|
|
|
|
info.cbSize = sizeof(info);
|
|
|
|
info.fMask = MIIM_STRING;
|
|
|
|
info.dwTypeData = str;
|
|
|
|
SetMenuItemInfoW(hMenu, pos, true, &info);
|
|
|
|
}
|
|
|
|
void SetMenuStrA(HMENU hMenu, UINT pos, char *str)
|
|
|
|
{
|
|
|
|
MENUITEMINFOA info;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || pos == INFINITE || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&info, sizeof(info));
|
|
|
|
info.cbSize = sizeof(info);
|
|
|
|
info.fMask = MIIM_STRING;
|
|
|
|
info.dwTypeData = str;
|
|
|
|
SetMenuItemInfoA(hMenu, pos, true, &info);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a string in the menu
|
|
|
|
wchar_t *GetMenuStr(HMENU hMenu, UINT pos)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || pos == INFINITE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetMenuStringW(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return UniCopyStr(tmp);
|
|
|
|
}
|
|
|
|
char *GetMenuStrA(HMENU hMenu, UINT pos)
|
|
|
|
{
|
|
|
|
char tmp[MAX_SIZE];
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || pos == INFINITE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetMenuString(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CopyStr(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bold the menu item
|
|
|
|
void SetMenuItemBold(HMENU hMenu, UINT pos, bool bold)
|
|
|
|
{
|
|
|
|
MENUITEMINFO info;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || pos == INFINITE)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&info, sizeof(info));
|
|
|
|
info.cbSize = sizeof(info);
|
|
|
|
info.fMask = MIIM_STATE;
|
|
|
|
|
|
|
|
if (GetMenuItemInfo(hMenu, pos, true, &info) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bold)
|
|
|
|
{
|
|
|
|
info.fState |= MFS_DEFAULT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
info.fState = info.fState & ~MFS_DEFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetMenuItemInfo(hMenu, pos, true, &info);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove a menu item
|
|
|
|
void DeleteMenuItem(HMENU hMenu, UINT pos)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL || pos == INFINITE)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteMenu(hMenu, pos, MF_BYPOSITION);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the position from the ID in the menu
|
|
|
|
UINT GetMenuItemPos(HMENU hMenu, UINT id)
|
|
|
|
{
|
|
|
|
UINT num, i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hMenu == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = GetMenuItemCount(hMenu);
|
|
|
|
if (num == INFINITE)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
if (GetMenuItemID(hMenu, i) == id)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a sub-menu
|
|
|
|
HMENU LoadSubMenu(UINT menu_id, UINT pos, HMENU *parent_menu)
|
|
|
|
{
|
|
|
|
HMENU h = LoadMenu(hDll, MAKEINTRESOURCE(menu_id));
|
|
|
|
HMENU ret;
|
|
|
|
if (h == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = GetSubMenu(h, pos);
|
|
|
|
|
|
|
|
if (parent_menu != NULL)
|
|
|
|
{
|
|
|
|
*parent_menu = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the DLL of the user interface
|
|
|
|
HINSTANCE GetUiDll()
|
|
|
|
{
|
|
|
|
return hDll;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connection Error dialog procedure
|
|
|
|
UINT ConnectErrorDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
UI_CONNECTERROR_DLG *p = (UI_CONNECTERROR_DLG *)param;
|
|
|
|
wchar_t tmp[1024];
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
if (p->Err == ERR_DISCONNECTED || p->Err == ERR_SESSION_TIMEOUT)
|
|
|
|
{
|
|
|
|
// Message indicating that the connection has been disconnected
|
|
|
|
SetText(hWnd, S_TITLE, _UU("ERRDLG_DISCONNECTED_MSG"));
|
|
|
|
}
|
|
|
|
if (p->HideWindow)
|
|
|
|
{
|
|
|
|
Hide(hWnd, R_HIDE);
|
|
|
|
}
|
|
|
|
FormatText(hWnd, 0, p->AccountName);
|
|
|
|
FormatText(hWnd, S_TITLE, p->ServerName);
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_ERRMSG"), p->Err, _E(p->Err));
|
|
|
|
SetText(hWnd, E_ERROR, tmp);
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, ICO_SERVER_OFFLINE);
|
|
|
|
|
|
|
|
if (p->RetryIntervalSec == 0)
|
|
|
|
{
|
|
|
|
SetText(hWnd, S_COUNTDOWN, _UU("ERRDLG_INFORMATION"));
|
|
|
|
Hide(hWnd, P_PROGRESS);
|
|
|
|
Hide(hWnd, S_RETRYINFO);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (p->RetryLimit != INFINITE)
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_1"), p->CurrentRetryCount, p->RetryLimit);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_2"), p->CurrentRetryCount);
|
|
|
|
}
|
|
|
|
SetText(hWnd, S_RETRYINFO, tmp);
|
|
|
|
SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec);
|
|
|
|
SetPos(hWnd, P_PROGRESS, 0);
|
|
|
|
SetTimer(hWnd, 1, 10, NULL);
|
|
|
|
p->StartTick = Tick64();
|
|
|
|
}
|
|
|
|
SetTimer(hWnd, 2, 10, NULL);
|
|
|
|
Focus(hWnd, IDOK);
|
|
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if (p->RetryIntervalSec != 0)
|
|
|
|
{
|
|
|
|
UINT64 start, end, now;
|
|
|
|
now = Tick64();
|
|
|
|
start = p->StartTick;
|
|
|
|
end = start + (UINT64)p->RetryIntervalSec;
|
|
|
|
|
|
|
|
if (end > now)
|
|
|
|
{
|
|
|
|
SetPos(hWnd, P_PROGRESS, (UINT)(now - start));
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRYCOUNT"), ((UINT)(end - now)) / 1000);
|
|
|
|
SetText(hWnd, S_COUNTDOWN, tmp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Command(hWnd, IDOK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (p->CancelEvent != NULL)
|
|
|
|
{
|
|
|
|
if (WaitForSingleObject((HANDLE)p->CancelEvent->pData, 0) != WAIT_TIMEOUT)
|
|
|
|
{
|
|
|
|
// Forced Cancel
|
|
|
|
Close(hWnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case R_HIDE:
|
|
|
|
p->HideWindow = IsChecked(hWnd, R_HIDE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the connection error dialog
|
|
|
|
bool ConnectErrorDlg(UI_CONNECTERROR_DLG *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DialogEx2(NULL, D_CONNECTERROR, ConnectErrorDlgProc, p, true, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Display the contents of the certificate
|
|
|
|
void PrintCheckCertInfo(HWND hWnd, UI_CHECKCERT *p)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
char tmp2[MAX_SIZE];
|
|
|
|
UCHAR md5[MD5_SIZE];
|
|
|
|
UCHAR sha1[SHA1_SIZE];
|
|
|
|
X *x;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = p->x;
|
|
|
|
|
|
|
|
GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);
|
|
|
|
SetText(hWnd, E_SUBJECT, tmp);
|
|
|
|
|
|
|
|
GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);
|
|
|
|
SetText(hWnd, E_ISSUER, tmp);
|
|
|
|
|
|
|
|
GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
|
|
|
|
SetText(hWnd, E_EXPIRES, tmp);
|
|
|
|
|
|
|
|
GetXDigest(x, md5, false);
|
|
|
|
BinToStr(tmp2, sizeof(tmp2), md5, sizeof(md5));
|
|
|
|
SetTextA(hWnd, E_MD5, tmp2);
|
|
|
|
|
|
|
|
GetXDigest(x, sha1, true);
|
|
|
|
BinToStr(tmp2, sizeof(tmp2), sha1, sizeof(sha1));
|
|
|
|
SetTextA(hWnd, E_SHA1, tmp2);
|
|
|
|
|
|
|
|
SetFont(hWnd, E_MD5, GetFont("Arial", 8, false, false, false, false));
|
|
|
|
SetFont(hWnd, E_SHA1, GetFont("Arial", 8, false, false, false, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Warn that the certificate is different
|
|
|
|
void ShowDlgDiffWarning(HWND hWnd, UI_CHECKCERT *p)
|
|
|
|
{
|
|
|
|
UCHAR sha1_new[SHA1_SIZE], sha1_old[SHA1_SIZE];
|
|
|
|
UCHAR md5_new[MD5_SIZE], md5_old[MD5_SIZE];
|
|
|
|
char sha1_new_str[MAX_SIZE], sha1_old_str[MAX_SIZE];
|
|
|
|
char md5_new_str[MAX_SIZE], md5_old_str[MAX_SIZE];
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL || p->x == NULL || p->old_x == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetXDigest(p->x, sha1_new, true);
|
|
|
|
GetXDigest(p->x, md5_new, false);
|
|
|
|
|
|
|
|
GetXDigest(p->old_x, sha1_old, true);
|
|
|
|
GetXDigest(p->old_x, md5_old, false);
|
|
|
|
|
|
|
|
BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));
|
|
|
|
BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));
|
|
|
|
BinToStrEx(sha1_old_str, sizeof(sha1_old_str), sha1_old, sizeof(sha1_old));
|
|
|
|
BinToStrEx(md5_old_str, sizeof(md5_old_str), md5_old, sizeof(md5_old));
|
|
|
|
|
|
|
|
MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CC_DANGEROUS_MSG"),
|
|
|
|
p->ServerName, md5_old_str, sha1_old_str, md5_new_str, sha1_new_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// [OK] button is pressed
|
|
|
|
void CheckCertDialogOnOk(HWND hWnd, UI_CHECKCERT *p)
|
|
|
|
{
|
|
|
|
UCHAR sha1_new[SHA1_SIZE];
|
|
|
|
UCHAR md5_new[MD5_SIZE];
|
|
|
|
char sha1_new_str[MAX_SIZE];
|
|
|
|
char md5_new_str[MAX_SIZE];
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetXDigest(p->x, sha1_new, true);
|
|
|
|
GetXDigest(p->x, md5_new, false);
|
|
|
|
BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));
|
|
|
|
BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));
|
|
|
|
|
|
|
|
ret = MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON2,
|
|
|
|
_UU("CC_WARNING_MSG"),
|
|
|
|
p->AccountName, sha1_new_str, md5_new_str);
|
|
|
|
|
|
|
|
if (ret == IDYES)
|
|
|
|
{
|
|
|
|
p->SaveServerCert = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == IDCANCEL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->Ok = true;
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Certificate dialog procedure
|
|
|
|
UINT CheckCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
UI_CHECKCERT *p = (UI_CHECKCERT *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || param == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
FormatText(hWnd, 0, p->AccountName);
|
|
|
|
FormatText(hWnd, S_TITLE, p->ServerName);
|
|
|
|
FormatText(hWnd, S_MSG1, p->ServerName);
|
|
|
|
|
|
|
|
PrintCheckCertInfo(hWnd, p);
|
|
|
|
|
|
|
|
Focus(hWnd, IDCANCEL);
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, ICO_WARNING);
|
|
|
|
|
|
|
|
if (p->DiffWarning)
|
|
|
|
{
|
|
|
|
SetTimer(hWnd, 1, 1, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetTimer(hWnd, 2, 100, NULL);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
ShowDlgDiffWarning(hWnd, p);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if ((p->Session != NULL && p->Session->Halt) ||
|
|
|
|
(p->Halt))
|
|
|
|
{
|
|
|
|
p->Ok = false;
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case B_SHOW:
|
|
|
|
CertDlg(hWnd, p->x, p->parent_x, false);
|
|
|
|
break;
|
|
|
|
case IDOK:
|
|
|
|
CheckCertDialogOnOk(hWnd, p);
|
|
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
|
|
p->Ok = false;
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Certificate Check dialog
|
|
|
|
void CheckCertDlg(UI_CHECKCERT *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dialog(NULL, D_CHECKCERT, CheckCertDlgProc, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the image list ID from the icon ID
|
|
|
|
UINT GetIcon(UINT icon_id)
|
|
|
|
{
|
|
|
|
IMAGELIST_ICON *c, t;
|
|
|
|
t.id = icon_id;
|
|
|
|
|
|
|
|
c = Search(icon_list, &t);
|
|
|
|
if (c == NULL)
|
|
|
|
{
|
|
|
|
if (icon_id != ICO_NULL)
|
|
|
|
{
|
|
|
|
return GetIcon(ICO_NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return c->Index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load an icon for the image list
|
|
|
|
IMAGELIST_ICON *LoadIconForImageList(UINT id)
|
|
|
|
{
|
|
|
|
IMAGELIST_ICON *ret = ZeroMalloc(sizeof(IMAGELIST_ICON));
|
|
|
|
HICON small_icon, large_icon;
|
|
|
|
|
|
|
|
ret->id = id;
|
|
|
|
|
|
|
|
large_icon = LoadLargeIcon(id);
|
|
|
|
if (large_icon == NULL)
|
|
|
|
{
|
|
|
|
large_icon = LoadSmallIcon(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
small_icon = LoadSmallIcon(id);
|
|
|
|
if (small_icon == NULL)
|
|
|
|
{
|
|
|
|
small_icon = LoadLargeIcon(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret->hSmallImage = small_icon;
|
|
|
|
ret->hLargeImage = large_icon;
|
|
|
|
ret->Index = ImageList_AddIcon(large_image_list, large_icon);
|
|
|
|
ImageList_AddIcon(small_image_list, small_icon);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comparison of the image list icons
|
|
|
|
int CompareImageListIcon(void *p1, void *p2)
|
|
|
|
{
|
|
|
|
IMAGELIST_ICON *c1, *c2;
|
|
|
|
if (p1 == NULL || p2 == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
c1 = *(IMAGELIST_ICON **)p1;
|
|
|
|
c2 = *(IMAGELIST_ICON **)p2;
|
|
|
|
if (c1 == NULL || c2 == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c1->id > c2->id)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (c1->id < c2->id)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize thr image list
|
|
|
|
void InitImageList()
|
|
|
|
{
|
|
|
|
large_image_list = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 1, 0);
|
|
|
|
ImageList_SetBkColor(large_image_list, RGB(255, 255, 255));
|
|
|
|
small_image_list = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 0);
|
|
|
|
ImageList_SetBkColor(small_image_list, RGB(255, 255, 255));
|
|
|
|
icon_list = NewList(CompareImageListIcon);
|
|
|
|
|
|
|
|
// Enumeration
|
|
|
|
EnumResourceNames(hDll, RT_GROUP_ICON, EnumResNameProc, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Icon resource enumeration procedure
|
|
|
|
BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
|
|
|
|
{
|
|
|
|
if (IS_INTRESOURCE(lpszName))
|
|
|
|
{
|
|
|
|
UINT icon_id = (UINT)lpszName;
|
|
|
|
IMAGELIST_ICON *img = LoadIconForImageList(icon_id);
|
|
|
|
|
|
|
|
Add(icon_list, img);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the image list
|
|
|
|
void FreeImageList()
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
ImageList_Destroy(large_image_list);
|
|
|
|
ImageList_Destroy(small_image_list);
|
|
|
|
large_image_list = small_image_list = NULL;
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(icon_list);i++)
|
|
|
|
{
|
|
|
|
IMAGELIST_ICON *c = LIST_DATA(icon_list, i);
|
|
|
|
Free(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseList(icon_list);
|
|
|
|
icon_list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the width of the column of the list view
|
|
|
|
UINT LvGetColumnWidth(HWND hWnd, UINT id, UINT index)
|
|
|
|
{
|
|
|
|
return (UINT)((double)ListView_GetColumnWidth(DlgItem(hWnd, id), index) / GetTextScalingFactor());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert the column into the list view
|
|
|
|
void LvInsertColumn(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT width)
|
|
|
|
{
|
|
|
|
LVCOLUMNW c;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
width = (UINT)((double)width * GetTextScalingFactor());
|
|
|
|
|
|
|
|
Zero(&c, sizeof(c));
|
|
|
|
c.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
|
|
|
|
|
|
|
|
c.pszText = str;
|
|
|
|
c.iSubItem = index;
|
|
|
|
c.cx = width;
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, LVM_INSERTCOLUMNW, index, (LPARAM)&c);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove all items from list view
|
|
|
|
void LvReset(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListView_DeleteAllItems(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the list view
|
|
|
|
void LvInitEx(HWND hWnd, UINT id, bool no_image)
|
|
|
|
{
|
|
|
|
LvInitEx2(hWnd, id, no_image, false);
|
|
|
|
}
|
|
|
|
void LvInitEx2(HWND hWnd, UINT id, bool no_image, bool large_icon)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListView_SetUnicodeFormat(DlgItem(hWnd, id), true);
|
|
|
|
|
|
|
|
if (no_image == false)
|
|
|
|
{
|
|
|
|
ListView_SetImageList(DlgItem(hWnd, id), large_image_list, LVSIL_NORMAL);
|
|
|
|
ListView_SetImageList(DlgItem(hWnd, id), large_icon ? large_image_list : small_image_list, LVSIL_SMALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ListView_SetExtendedListViewStyle(DlgItem(hWnd, id), LVS_EX_FULLROWSELECT);
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
LvSetStyle(hWnd, id, LVS_EX_DOUBLEBUFFER);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
void LvInit(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
LvInitEx(hWnd, id, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adding batch complete (high-speed)
|
|
|
|
void LvInsertEnd(LVB *b, HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
LvInsertEndEx(b, hWnd, id, false);
|
|
|
|
}
|
|
|
|
void LvInsertEndEx(LVB *b, HWND hWnd, UINT id, bool force_reset)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
LIST *new_list, *exist_list;
|
|
|
|
wchar_t *last_selected = NULL;
|
|
|
|
// Validate arguments
|
|
|
|
if (b == NULL || hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_list = NewListFast(CompareUniStr);
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(b->ItemList);i++)
|
|
|
|
{
|
|
|
|
LVB_ITEM *t = LIST_DATA(b->ItemList, i);
|
|
|
|
Add(new_list, t->Strings[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sort(new_list);
|
|
|
|
|
|
|
|
if ((LIST_NUM(b->ItemList) >= LV_INSERT_RESET_ALL_ITEM_MIN) || force_reset)
|
|
|
|
{
|
|
|
|
last_selected = LvGetFocusedStr(hWnd, id, 0);
|
|
|
|
LvReset(hWnd, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
exist_list = NewListFast(CompareUniStr);
|
|
|
|
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
|
|
|
|
// Delete the items which isn't contained in the batch list of existing items
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
bool exists = false;
|
|
|
|
wchar_t *s = LvGetStr(hWnd, id, i, 0);
|
|
|
|
if (Search(new_list, s) != NULL)
|
|
|
|
{
|
|
|
|
exists = true;
|
|
|
|
}
|
|
|
|
if (exists == false)
|
|
|
|
{
|
|
|
|
// Remove items that don't exist in the batch list of the adding plan from the list view
|
|
|
|
LvDeleteItem(hWnd, id, i);
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
i--;
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Add(exist_list, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sort(exist_list);
|
|
|
|
|
|
|
|
// Add items in the batch one by one
|
|
|
|
for (i = 0;i < LIST_NUM(b->ItemList);i++)
|
|
|
|
{
|
|
|
|
LVB_ITEM *t = LIST_DATA(b->ItemList, i);
|
|
|
|
UINT index;
|
|
|
|
UINT j;
|
|
|
|
bool exists = false;
|
|
|
|
|
|
|
|
if (Search(exist_list, t->Strings[0]) != NULL)
|
|
|
|
{
|
|
|
|
index = LvSearchStr(hWnd, id, 0, t->Strings[0]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
index = INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index != INFINITE)
|
|
|
|
{
|
|
|
|
UINT j;
|
|
|
|
// If an item with the string same to adding item already exists,
|
|
|
|
// update instead of adding
|
|
|
|
for (j = 0;j < t->NumStrings;j++)
|
|
|
|
{
|
|
|
|
LvSetItem(hWnd, id, index, j, t->Strings[j]);
|
|
|
|
}
|
|
|
|
LvSetItemImageByImageListId(hWnd, id, index, t->Image);
|
|
|
|
LvSetItemParam(hWnd, id, index, t->Param);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Add newly
|
|
|
|
UINT index = INFINITE;
|
|
|
|
UINT j;
|
|
|
|
for (j = 0;j < t->NumStrings;j++)
|
|
|
|
{
|
|
|
|
if (j == 0)
|
|
|
|
{
|
|
|
|
index = LvInsertItemByImageListId(hWnd, id, t->Image, t->Param, t->Strings[j]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LvSetItem(hWnd, id, index, j, t->Strings[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the memory
|
|
|
|
for (j = 0;j < t->NumStrings;j++)
|
|
|
|
{
|
|
|
|
Free(t->Strings[j]);
|
|
|
|
}
|
|
|
|
Free(t->Strings);
|
|
|
|
Free(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the list
|
|
|
|
ReleaseList(b->ItemList);
|
|
|
|
|
|
|
|
// Release the memory
|
|
|
|
Free(b);
|
|
|
|
|
|
|
|
ReleaseList(new_list);
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(exist_list);i++)
|
|
|
|
{
|
|
|
|
Free(LIST_DATA(exist_list, i));
|
|
|
|
}
|
|
|
|
ReleaseList(exist_list);
|
|
|
|
|
|
|
|
if (last_selected != NULL)
|
|
|
|
{
|
|
|
|
UINT pos = LvSearchStr(hWnd, id, 0, last_selected);
|
|
|
|
|
|
|
|
if (pos != INFINITE)
|
|
|
|
{
|
|
|
|
LvSelect(hWnd, id, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(last_selected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of columns of the list view
|
|
|
|
UINT LvGetColumnNum(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
LVCOLUMN c;
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;;i++)
|
|
|
|
{
|
|
|
|
Zero(&c, sizeof(c));
|
|
|
|
c.mask = LVCF_SUBITEM;
|
|
|
|
if (ListView_GetColumn(DlgItem(hWnd, id), i, &c) == false)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// List-view sort function
|
|
|
|
int CALLBACK LvSortProc(LPARAM param1, LPARAM param2, LPARAM sort_param)
|
|
|
|
{
|
|
|
|
WINUI_LV_SORT *sort = (WINUI_LV_SORT *)sort_param;
|
|
|
|
HWND hWnd;
|
|
|
|
UINT id;
|
|
|
|
UINT i1, i2;
|
|
|
|
int ret = 0;
|
|
|
|
wchar_t *s1, *s2;
|
|
|
|
if (sort == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
hWnd = sort->hWnd;
|
|
|
|
id = sort->id;
|
|
|
|
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
i1 = (UINT)param1;
|
|
|
|
i2 = (UINT)param2;
|
|
|
|
|
|
|
|
s1 = LvGetStr(hWnd, id, i1, sort->subitem);
|
|
|
|
if (s1 == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
s2 = LvGetStr(hWnd, id, i2, sort->subitem);
|
|
|
|
if (s2 == NULL)
|
|
|
|
{
|
|
|
|
Free(s1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sort->numeric == false)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(s1, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_LINK")) == 0)
|
|
|
|
{
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
else if (UniStrCmpi(s2, _UU("CM_NEW_ICON")) == 0 || UniStrCmpi(s2, _UU("CM_VGC_ICON")) == 0 || UniStrCmpi(s1, _UU("CM_VGC_LINK")) == 0)
|
|
|
|
{
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = UniStrCmpi(s1, s2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT64 v1, v2;
|
|
|
|
v1 = UniToInt64(s1);
|
|
|
|
v2 = UniToInt64(s2);
|
|
|
|
if (v1 > v2)
|
|
|
|
{
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
else if (v1 < v2)
|
|
|
|
{
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(s1);
|
|
|
|
Free(s2);
|
|
|
|
|
|
|
|
if (sort->desc)
|
|
|
|
{
|
|
|
|
ret = -ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Standard handler
|
|
|
|
void LvStandardHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)
|
|
|
|
{
|
|
|
|
NMHDR *n;
|
|
|
|
NMLVKEYDOWN *key;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LvSortHander(hWnd, msg, wParam, lParam, id);
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_NOTIFY:
|
|
|
|
n = (NMHDR *)lParam;
|
|
|
|
if (n->idFrom == id)
|
|
|
|
{
|
|
|
|
switch (n->code)
|
|
|
|
{
|
|
|
|
case NM_DBLCLK:
|
|
|
|
Command(hWnd, IDOK);
|
|
|
|
break;
|
|
|
|
case LVN_KEYDOWN:
|
|
|
|
key = (NMLVKEYDOWN *)n;
|
|
|
|
if (key != NULL)
|
|
|
|
{
|
|
|
|
UINT code = key->wVKey;
|
|
|
|
switch (code)
|
|
|
|
{
|
|
|
|
case VK_DELETE:
|
|
|
|
Command(hWnd, B_DELETE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_RETURN:
|
|
|
|
Command(hWnd, IDOK);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_F5:
|
|
|
|
Command(hWnd, B_REFRESH);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort header handler
|
|
|
|
void LvSortHander(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)
|
|
|
|
{
|
|
|
|
NMHDR *nmhdr;
|
|
|
|
UINT subitem;
|
|
|
|
bool desc;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_NOTIFY:
|
|
|
|
nmhdr = (NMHDR *)lParam;
|
|
|
|
|
|
|
|
if (nmhdr != NULL)
|
|
|
|
{
|
|
|
|
if (nmhdr->idFrom == id)
|
|
|
|
{
|
|
|
|
NMLISTVIEW *v;
|
|
|
|
switch (nmhdr->code)
|
|
|
|
{
|
|
|
|
case LVN_COLUMNCLICK:
|
|
|
|
desc = false;
|
|
|
|
v = (NMLISTVIEW *)lParam;
|
|
|
|
subitem = v->iSubItem;
|
|
|
|
|
|
|
|
if ((GetStyle(hWnd, id) & LVS_SORTDESCENDING) == 0)
|
|
|
|
{
|
|
|
|
desc = true;
|
|
|
|
SetStyle(hWnd, id, LVS_SORTDESCENDING);
|
|
|
|
RemoveStyle(hWnd, id, LVS_SORTASCENDING);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetStyle(hWnd, id, LVS_SORTASCENDING);
|
|
|
|
RemoveStyle(hWnd, id, LVS_SORTDESCENDING);
|
|
|
|
}
|
|
|
|
|
|
|
|
LvSort(hWnd, id, subitem, desc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do sort
|
|
|
|
void LvSort(HWND hWnd, UINT id, UINT subitem, bool desc)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
bool numeric = true;
|
|
|
|
wchar_t na[2] = {0xff0d, 0x0, };
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
wchar_t *s = LvGetStr(hWnd, id, i, subitem);
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
if (UniIsNum(s) == false && UniStrCmp(s, na) != 0)
|
|
|
|
{
|
|
|
|
numeric = false;
|
|
|
|
Free(s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
numeric = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LvSortEx(hWnd, id, subitem, desc, numeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LvSortEx(HWND hWnd, UINT id, UINT subitem, bool desc, bool numeric)
|
|
|
|
{
|
|
|
|
WINUI_LV_SORT s;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (subitem >= LvGetColumnNum(hWnd, id))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&s, sizeof(s));
|
|
|
|
s.desc = desc;
|
|
|
|
s.numeric = numeric;
|
|
|
|
s.id = id;
|
|
|
|
s.hWnd = hWnd;
|
|
|
|
s.subitem = subitem;
|
|
|
|
|
|
|
|
ListView_SortItemsEx(DlgItem(hWnd, id), LvSortProc, (LPARAM)&s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add an item to adding batch
|
|
|
|
void LvInsertAdd(LVB *b, UINT icon, void *param, UINT num_str, ...)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
va_list va;
|
|
|
|
UINT index = 0;
|
|
|
|
LVB_ITEM *t;
|
|
|
|
// Validate arguments
|
|
|
|
if (b == NULL || num_str == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = ZeroMalloc(sizeof(LVB_ITEM));
|
|
|
|
|
|
|
|
va_start(va, num_str);
|
|
|
|
|
|
|
|
t->Strings = (wchar_t **)ZeroMalloc(sizeof(wchar_t *) * num_str);
|
|
|
|
t->NumStrings = num_str;
|
|
|
|
|
|
|
|
for (i = 0;i < num_str;i++)
|
|
|
|
{
|
|
|
|
wchar_t *s = va_arg(va, wchar_t *);
|
|
|
|
|
|
|
|
t->Strings[i] = UniCopyStr(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
t->Param = param;
|
|
|
|
t->Image = GetIcon(icon);
|
|
|
|
|
|
|
|
Add(b->ItemList, t);
|
|
|
|
|
|
|
|
va_end(va);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start the item adding batch
|
|
|
|
LVB *LvInsertStart()
|
|
|
|
{
|
|
|
|
LVB *b = ZeroMalloc(sizeof(LVB));
|
|
|
|
b->ItemList = NewListFast(NULL);
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add items to the list view
|
|
|
|
void LvInsert(HWND hWnd, UINT id, UINT icon, void *param, UINT num_str, ...)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
va_list va;
|
|
|
|
UINT index = 0;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
va_start(va, num_str);
|
|
|
|
|
|
|
|
for (i = 0;i < num_str;i++)
|
|
|
|
{
|
|
|
|
wchar_t *s = va_arg(va, wchar_t *);
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
index = LvInsertItem(hWnd, id, icon, param, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LvSetItem(hWnd, id, index, i, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
va_end(va);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the item size automatically
|
|
|
|
void LvAutoSize(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (ListView_SetColumnWidth(DlgItem(hWnd, id), i, LVSCW_AUTOSIZE) == false)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add an item
|
|
|
|
UINT LvInsertItem(HWND hWnd, UINT id, UINT icon, void *param, wchar_t *str)
|
|
|
|
{
|
|
|
|
return LvInsertItemByImageListId(hWnd, id, GetIcon(icon), param, str);
|
|
|
|
}
|
|
|
|
UINT LvInsertItemByImageListId(HWND hWnd, UINT id, UINT image, void *param, wchar_t *str)
|
|
|
|
{
|
|
|
|
LVITEMW t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
|
|
|
|
t.pszText = str;
|
|
|
|
t.iImage = image;
|
|
|
|
t.lParam = (LPARAM)param;
|
|
|
|
t.iItem = LvNum(hWnd, id);
|
|
|
|
|
|
|
|
return SendMsg(hWnd, id, LVM_INSERTITEMW, 0, (LPARAM)&t);
|
|
|
|
}
|
|
|
|
UINT LvInsertItemByImageListIdA(HWND hWnd, UINT id, UINT image, void *param, char *str)
|
|
|
|
{
|
|
|
|
LVITEM t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
|
|
|
|
t.pszText = str;
|
|
|
|
t.iImage = image;
|
|
|
|
t.lParam = (LPARAM)param;
|
|
|
|
t.iItem = LvNum(hWnd, id);
|
|
|
|
|
|
|
|
return SendMsg(hWnd, id, LVM_INSERTITEM, 0, (LPARAM)&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change the image
|
|
|
|
void LvSetItemImageByImageListId(HWND hWnd, UINT id, UINT index, UINT image)
|
|
|
|
{
|
|
|
|
LVITEM t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_IMAGE;
|
|
|
|
t.iImage = image;
|
|
|
|
t.iItem = index;
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the parameters of the item
|
|
|
|
void LvSetItemParam(HWND hWnd, UINT id, UINT index, void *param)
|
|
|
|
{
|
|
|
|
LvSetItemParamEx(hWnd, id, index, 0, param);
|
|
|
|
}
|
|
|
|
void LvSetItemParamEx(HWND hWnd, UINT id, UINT index, UINT subitem, void *param)
|
|
|
|
{
|
|
|
|
LVITEM t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_PARAM;
|
|
|
|
t.iItem = index;
|
|
|
|
t.iSubItem = subitem;
|
|
|
|
t.lParam = (LPARAM)param;
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the item
|
|
|
|
void LvSetItem(HWND hWnd, UINT id, UINT index, UINT pos, wchar_t *str)
|
|
|
|
{
|
|
|
|
LVITEMW t;
|
|
|
|
wchar_t *old_str;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_TEXT;
|
|
|
|
t.pszText = str;
|
|
|
|
t.iItem = index;
|
|
|
|
t.iSubItem = pos;
|
|
|
|
|
|
|
|
old_str = LvGetStr(hWnd, id, index, pos);
|
|
|
|
|
|
|
|
if (UniStrCmp(old_str, str) != 0)
|
|
|
|
{
|
|
|
|
SendMsg(hWnd, id, LVM_SETITEMW, 0, (LPARAM)&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(old_str);
|
|
|
|
}
|
|
|
|
void LvSetItemA(HWND hWnd, UINT id, UINT index, UINT pos, char *str)
|
|
|
|
{
|
|
|
|
LVITEM t;
|
|
|
|
wchar_t *old_str;
|
|
|
|
char *old_str_2;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_TEXT;
|
|
|
|
t.pszText = str;
|
|
|
|
t.iItem = index;
|
|
|
|
t.iSubItem = pos;
|
|
|
|
|
|
|
|
old_str = LvGetStr(hWnd, id, index, pos);
|
|
|
|
old_str_2 = CopyUniToStr(old_str);
|
|
|
|
|
|
|
|
if (StrCmp(old_str_2, str) != 0)
|
|
|
|
{
|
|
|
|
SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(old_str_2);
|
|
|
|
Free(old_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the view of the list box
|
|
|
|
void LvSetView(HWND hWnd, UINT id, bool details)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (details)
|
|
|
|
{
|
|
|
|
RemoveStyle(hWnd, id, LVS_ICON);
|
|
|
|
SetStyle(hWnd, id, LVS_REPORT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RemoveStyle(hWnd, id, LVS_REPORT);
|
|
|
|
SetStyle(hWnd, id, LVS_ICON);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get whether there is currently selected item
|
|
|
|
bool LvIsSelected(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LvGetSelected(hWnd, id) == INFINITE)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the currently selected item
|
|
|
|
UINT LvGetFocused(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the parameter of the currently selected item
|
|
|
|
void *LvGetSelectedParam(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT index;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = LvGetSelected(hWnd, id);
|
|
|
|
|
|
|
|
if (index == INFINITE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return LvGetParam(hWnd, id, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a string that is currently selected
|
|
|
|
wchar_t *LvGetFocusedStr(HWND hWnd, UINT id, UINT pos)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = LvGetFocused(hWnd, id);
|
|
|
|
if (i == INFINITE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return LvGetStr(hWnd, id, i, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the currently selected item
|
|
|
|
UINT LvGetSelected(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED | LVNI_SELECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a string that is currently selected
|
|
|
|
wchar_t *LvGetSelectedStr(HWND hWnd, UINT id, UINT pos)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = LvGetSelected(hWnd, id);
|
|
|
|
if (i == INFINITE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return LvGetStr(hWnd, id, i, pos);
|
|
|
|
}
|
|
|
|
char *LvGetSelectedStrA(HWND hWnd, UINT id, UINT pos)
|
|
|
|
{
|
|
|
|
char *ret;
|
|
|
|
wchar_t *tmp = LvGetSelectedStr(hWnd, id, pos);
|
|
|
|
if (tmp == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret = CopyUniToStr(tmp);
|
|
|
|
Free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get whether two or more items are masked
|
|
|
|
bool LvIsMultiMasked(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = INFINITE;
|
|
|
|
i = LvGetNextMasked(hWnd, id, i);
|
|
|
|
if (i != INFINITE)
|
|
|
|
{
|
|
|
|
if (LvGetNextMasked(hWnd, id, i) != INFINITE)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examine whether just only one item is selected
|
|
|
|
bool LvIsSingleSelected(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
return LvIsSelected(hWnd, id) && (LvIsMultiMasked(hWnd, id) == false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get whether there are items that are currently masked
|
|
|
|
bool LvIsMasked(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LvGetNextMasked(hWnd, id, INFINITE) == INFINITE)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the items that is currently masked
|
|
|
|
UINT LvGetNextMasked(HWND hWnd, UINT id, UINT start)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ListView_GetNextItem(DlgItem(hWnd, id), start, LVNI_SELECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search an item with the specified string
|
2018-08-06 11:43:23 +03:00
|
|
|
UINT LvSearchStr(HWND hWnd, UINT id, UINT pos, wchar_t *str)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
2018-08-06 11:43:23 +03:00
|
|
|
UINT i, num;
|
2014-01-04 17:00:08 +04:00
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
2018-08-06 11:43:23 +03:00
|
|
|
num = LvNum(hWnd, id);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
wchar_t *s = LvGetStr(hWnd, id, i, pos);
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(s, str) == 0)
|
|
|
|
{
|
|
|
|
Free(s);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
UINT LvSearchStrA(HWND hWnd, UINT id, UINT pos, char *str)
|
|
|
|
{
|
|
|
|
wchar_t *tmp = CopyStrToUni(str);
|
|
|
|
UINT ret = LvSearchStr(hWnd, id, pos, tmp);
|
|
|
|
Free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for item that have a specified param
|
|
|
|
UINT LvSearchParam(HWND hWnd, UINT id, void *param)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
if (LvGetParam(hWnd, id, i) == param)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of items
|
|
|
|
UINT LvNum(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ListView_GetItemCount(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove an item
|
|
|
|
void LvDeleteItem(HWND hWnd, UINT id, UINT index)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListView_DeleteItem(DlgItem(hWnd, id), index);
|
|
|
|
|
|
|
|
i = LvGetSelected(hWnd, id);
|
|
|
|
if (i != INFINITE)
|
|
|
|
{
|
|
|
|
LvSelect(hWnd, id, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the data from the item
|
|
|
|
void *LvGetParam(HWND hWnd, UINT id, UINT index)
|
|
|
|
{
|
|
|
|
return LvGetParamEx(hWnd, id, index, 0);
|
|
|
|
}
|
|
|
|
void *LvGetParamEx(HWND hWnd, UINT id, UINT index, UINT subitem)
|
|
|
|
{
|
|
|
|
LVITEM t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (index == INFINITE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_PARAM;
|
|
|
|
t.iItem = index;
|
|
|
|
t.iSubItem = subitem;
|
|
|
|
|
|
|
|
if (ListView_GetItem(DlgItem(hWnd, id), &t) == false)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (void *)t.lParam;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the string of item
|
|
|
|
wchar_t *LvGetStr(HWND hWnd, UINT id, UINT index, UINT pos)
|
|
|
|
{
|
|
|
|
wchar_t *tmp;
|
|
|
|
UINT size;
|
|
|
|
LVITEMW t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = 65536;
|
|
|
|
tmp = Malloc(size);
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_TEXT;
|
|
|
|
t.iItem = index;
|
|
|
|
t.iSubItem = pos;
|
|
|
|
t.pszText = tmp;
|
|
|
|
t.cchTextMax = size;
|
|
|
|
|
|
|
|
if (SendMsg(hWnd, id, LVM_GETITEMTEXTW, index, (LPARAM)&t) <= 0)
|
|
|
|
{
|
|
|
|
Free(tmp);
|
|
|
|
return UniCopyStr(L"");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wchar_t *ret = UniCopyStr(tmp);
|
|
|
|
Free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char *LvGetStrA(HWND hWnd, UINT id, UINT index, UINT pos)
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
UINT size;
|
|
|
|
LVITEM t;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = 65536;
|
|
|
|
tmp = Malloc(size);
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.mask = LVIF_TEXT;
|
|
|
|
t.iItem = index;
|
|
|
|
t.iSubItem = pos;
|
|
|
|
t.pszText = tmp;
|
|
|
|
t.cchTextMax = size;
|
|
|
|
|
|
|
|
if (SendMsg(hWnd, id, LVM_GETITEMTEXT, index, (LPARAM)&t) <= 0)
|
|
|
|
{
|
|
|
|
Free(tmp);
|
|
|
|
return CopyStr("");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *ret = CopyStr(tmp);
|
|
|
|
Free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the style
|
|
|
|
void LvSetStyle(HWND hWnd, UINT id, UINT style)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) == 0)
|
|
|
|
{
|
|
|
|
ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, style);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the style
|
|
|
|
void LvRemoveStyle(HWND hWnd, UINT id, UINT style)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) != 0)
|
|
|
|
{
|
|
|
|
ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invert the selection of items
|
|
|
|
void LvSwitchSelect(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
bool *states;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
states = ZeroMalloc(sizeof(bool) * num);
|
|
|
|
|
|
|
|
i = INFINITE;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
i = LvGetNextMasked(hWnd, id, i);
|
|
|
|
if (i == INFINITE)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
states[i] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
if (states[i] == false)
|
|
|
|
{
|
|
|
|
ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(states);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select all items
|
|
|
|
void LvSelectAll(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select the item by specifying the parameter
|
|
|
|
void LvSelectByParam(HWND hWnd, UINT id, void *param)
|
|
|
|
{
|
|
|
|
UINT index;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || param == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = LvSearchParam(hWnd, id, param);
|
|
|
|
if (index == INFINITE)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LvSelect(hWnd, id, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select an item
|
|
|
|
void LvSelect(HWND hWnd, UINT id, UINT index)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == INFINITE)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
// Deselect all
|
|
|
|
num = LvNum(hWnd, id);
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Select
|
|
|
|
ListView_SetItemState(DlgItem(hWnd, id), index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
|
|
|
|
ListView_EnsureVisible(DlgItem(hWnd, id), index, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the certificate information
|
|
|
|
void PrintCertInfo(HWND hWnd, CERT_DLG *p)
|
|
|
|
{
|
|
|
|
X *x;
|
|
|
|
char *serial_tmp;
|
|
|
|
UINT serial_size;
|
|
|
|
wchar_t *wchar_tmp;
|
|
|
|
wchar_t tmp[1024 * 5];
|
|
|
|
UCHAR md5[MD5_SIZE];
|
|
|
|
UCHAR sha1[SHA1_SIZE];
|
|
|
|
char *s_tmp;
|
|
|
|
K *k;
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL || hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = p->x;
|
|
|
|
|
|
|
|
// Serial number
|
|
|
|
if (x->serial != NULL)
|
|
|
|
{
|
|
|
|
serial_size = x->serial->size * 3 + 1;
|
|
|
|
serial_tmp = ZeroMalloc(serial_size);
|
|
|
|
BinToStrEx(serial_tmp, serial_size, x->serial->data, x->serial->size);
|
|
|
|
wchar_tmp = CopyStrToUni(serial_tmp);
|
|
|
|
Free(serial_tmp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wchar_tmp = CopyUniStr(_UU("CERT_NO_SERIAL"));
|
|
|
|
}
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SERIAL"), wchar_tmp);
|
|
|
|
|
|
|
|
// Issuer
|
|
|
|
GetAllNameFromName(tmp, sizeof(tmp), x->issuer_name);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_ISSUER"), tmp);
|
|
|
|
|
|
|
|
// Subject
|
|
|
|
GetAllNameFromName(tmp, sizeof(tmp), x->subject_name);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SUBJECT"), tmp);
|
|
|
|
|
|
|
|
// Not available before
|
|
|
|
GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notBefore), NULL);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_BEFORE"), tmp);
|
|
|
|
|
|
|
|
// Not available after
|
|
|
|
GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_AFTER"), tmp);
|
|
|
|
|
|
|
|
// Public key
|
|
|
|
k = GetKFromX(x);
|
|
|
|
if (k != NULL)
|
|
|
|
{
|
2021-09-24 12:12:51 +03:00
|
|
|
UINT type = EVP_PKEY_base_id(k->pkey);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case EVP_PKEY_RSA:
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_KEY_ALGORITHM"), L"RSA");
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("CERT_BITS_FORMAT"), x->bits);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_BITS"), tmp);
|
|
|
|
break;
|
|
|
|
case EVP_PKEY_EC:
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_KEY_ALGORITHM"), L"ECDSA");
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("CERT_BITS_FORMAT"), x->bits);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_BITS"), tmp);
|
|
|
|
|
|
|
|
# ifndef OPENSSL_NO_EC
|
|
|
|
EC_KEY *key = EVP_PKEY_get0_EC_KEY(k->pkey);
|
|
|
|
if (key == NULL)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
EC_GROUP *group = EC_KEY_get0_group(key);
|
|
|
|
if (group == NULL)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nid = EC_GROUP_get_curve_name(group);
|
|
|
|
if (nid == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrToUni(tmp, sizeof(tmp), OBJ_nid2sn(nid)) > 0)
|
|
|
|
{
|
|
|
|
wchar_t *nname = CopyStrToUni(EC_curve_nid2nist(nid));
|
|
|
|
if (nname)
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), L"%s (%s)", tmp, nname);
|
|
|
|
}
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_KEY_PARAMETER"), tmp);
|
|
|
|
Free(nname);
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
BUF *b = KToBuf(k, false, NULL);
|
|
|
|
s_tmp = CopyBinToStrEx(b->Buf, b->Size);
|
|
|
|
StrToUni(tmp, sizeof(tmp), s_tmp);
|
|
|
|
Free(s_tmp);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_PUBLIC_KEY"), tmp);
|
|
|
|
FreeBuf(b);
|
|
|
|
}
|
|
|
|
FreeK(k);
|
|
|
|
|
|
|
|
GetXDigest(x, md5, false);
|
|
|
|
GetXDigest(x, sha1, true);
|
|
|
|
|
|
|
|
// Digest (MD5)
|
|
|
|
s_tmp = CopyBinToStrEx(md5, sizeof(md5));
|
|
|
|
StrToUni(tmp, sizeof(tmp), s_tmp);
|
|
|
|
Free(s_tmp);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_MD5"), tmp);
|
|
|
|
|
|
|
|
// Digest (SHA-1)
|
|
|
|
s_tmp = CopyBinToStrEx(sha1, sizeof(sha1));
|
|
|
|
StrToUni(tmp, sizeof(tmp), s_tmp);
|
|
|
|
Free(s_tmp);
|
|
|
|
LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_SHA1"), tmp);
|
|
|
|
|
|
|
|
Free(wchar_tmp);
|
|
|
|
|
|
|
|
LvSelect(hWnd, L_CERTINFO, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the display
|
|
|
|
void CertDlgUpdate(HWND hWnd, CERT_DLG *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LvIsSelected(hWnd, L_CERTINFO) == false)
|
|
|
|
{
|
|
|
|
SetText(hWnd, E_DETAIL, L"");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT i = LvGetSelected(hWnd, L_CERTINFO);
|
|
|
|
wchar_t *tmp = LvGetStr(hWnd, L_CERTINFO, i, 1);
|
|
|
|
SetText(hWnd, E_DETAIL, tmp);
|
|
|
|
Free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save the certificate
|
|
|
|
void CertDlgSave(HWND hWnd, CERT_DLG *p)
|
|
|
|
{
|
|
|
|
wchar_t *name;
|
|
|
|
X *x;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save to a file
|
|
|
|
name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");
|
|
|
|
x = p->x;
|
|
|
|
if (name != NULL)
|
|
|
|
{
|
|
|
|
wchar_t str[MAX_SIZE];
|
|
|
|
UniStrCpy(str, sizeof(str), name);
|
|
|
|
if (XToFileW(x, str, true))
|
|
|
|
{
|
|
|
|
MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));
|
|
|
|
}
|
|
|
|
Free(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Certificate display dialog procedure
|
|
|
|
UINT CertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
CERT_DLG *p = (CERT_DLG *)param;
|
|
|
|
X *x;
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
NMHDR *n;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetIcon(hWnd, 0, ICO_CERT);
|
|
|
|
x = p->x;
|
|
|
|
GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);
|
|
|
|
SetText(hWnd, E_SUBJECT, tmp);
|
|
|
|
GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);
|
|
|
|
SetText(hWnd, E_ISSUER, tmp);
|
|
|
|
GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);
|
|
|
|
SetText(hWnd, E_EXPIRES, tmp);
|
|
|
|
SetFont(hWnd, E_SUBJECT, Font(0, 1));
|
|
|
|
SetFont(hWnd, E_ISSUER, Font(0, 1));
|
|
|
|
SetFont(hWnd, E_EXPIRES, Font(0, 1));
|
|
|
|
SetIcon(hWnd, B_PARENT, ICO_CERT);
|
|
|
|
if (x->root_cert)
|
|
|
|
{
|
|
|
|
// Root certificate
|
|
|
|
Hide(hWnd, S_WARNING_ICON);
|
|
|
|
SetText(hWnd, S_PARENT, _UU("CERT_ROOT"));
|
|
|
|
Hide(hWnd, B_PARENT);
|
|
|
|
Hide(hWnd, S_PARENT_BUTTON_STR);
|
|
|
|
}
|
|
|
|
else if (p->issuer_x != NULL)
|
|
|
|
{
|
|
|
|
// Parent certificate exists
|
|
|
|
Hide(hWnd, S_WARNING_ICON);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// There is no parent certificate
|
|
|
|
Hide(hWnd, S_CERT_ICON);
|
|
|
|
Hide(hWnd, B_PARENT);
|
|
|
|
Hide(hWnd, S_PARENT_BUTTON_STR);
|
|
|
|
SetText(hWnd, S_PARENT, _UU("CERT_NOT_FOUND"));
|
|
|
|
if (p->ManagerMode)
|
|
|
|
{
|
|
|
|
Hide(hWnd, IDC_STATIC1);
|
|
|
|
Hide(hWnd, S_PARENT);
|
|
|
|
Hide(hWnd, S_WARNING_ICON);
|
|
|
|
Hide(hWnd, S_CERT_ICON);
|
|
|
|
Hide(hWnd, B_PARENT);
|
|
|
|
Hide(hWnd, S_PARENT_BUTTON_STR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LvInit(hWnd, L_CERTINFO);
|
|
|
|
LvInsertColumn(hWnd, L_CERTINFO, 0, _UU("CERT_LV_C1"), 130);
|
|
|
|
LvInsertColumn(hWnd, L_CERTINFO, 1, _UU("CERT_LV_C2"), 250);
|
|
|
|
|
|
|
|
PrintCertInfo(hWnd, p);
|
|
|
|
Focus(hWnd, L_CERTINFO);
|
|
|
|
|
|
|
|
CertDlgUpdate(hWnd, p);
|
|
|
|
|
|
|
|
if (p->ManagerMode)
|
|
|
|
{
|
|
|
|
Show(hWnd, B_SAVE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Hide for security
|
|
|
|
Hide(hWnd, B_SAVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
case B_PARENT:
|
|
|
|
CertDlg(hWnd, p->issuer_x, NULL, p->ManagerMode);
|
|
|
|
break;
|
|
|
|
case B_SAVE:
|
|
|
|
// Save to the file
|
|
|
|
CertDlgSave(hWnd, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
|
|
n = (NMHDR *)lParam;
|
|
|
|
switch (n->idFrom)
|
|
|
|
{
|
|
|
|
case L_CERTINFO:
|
|
|
|
switch (n->code)
|
|
|
|
{
|
|
|
|
case LVN_ITEMCHANGED:
|
|
|
|
CertDlgUpdate(hWnd, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
LvSortHander(hWnd, msg, wParam, lParam, L_CERTINFO);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Certificate display dialog
|
|
|
|
void CertDlg(HWND hWnd, X *x, X *issuer_x, bool manager)
|
|
|
|
{
|
|
|
|
CERT_DLG p;
|
|
|
|
// Validate arguments
|
|
|
|
if (x == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&p, sizeof(p));
|
|
|
|
p.x = x;
|
|
|
|
if (CompareX(x, issuer_x) == false)
|
|
|
|
{
|
|
|
|
p.issuer_x = issuer_x;
|
|
|
|
}
|
|
|
|
p.ManagerMode = manager;
|
|
|
|
Dialog(hWnd, D_CERT, CertDlgProc, &p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Status window dialog
|
|
|
|
UINT StatusPrinterWindowDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;
|
|
|
|
PACK *pack;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
// Initialize
|
|
|
|
SetIcon(hWnd, 0, ICO_SERVER_ONLINE);
|
|
|
|
RemoveExStyle(hWnd, 0, WS_EX_APPWINDOW);
|
|
|
|
p->hWnd = hWnd;
|
|
|
|
NoticeThreadInit(p->Thread);
|
|
|
|
FormatText(hWnd, 0, p->AccountName);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
case IDCANCEL:
|
|
|
|
// Cancel button
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_APP + 1:
|
|
|
|
// Set a string
|
|
|
|
SetText(hWnd, S_STATUS, (wchar_t *)lParam);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_APP + 2:
|
|
|
|
// Close this window
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
// End the session
|
|
|
|
pack = NewPack();
|
|
|
|
SendPack(p->Sock, pack);
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Status window control thread
|
|
|
|
void StatusPrinterWindowThread(THREAD *thread, void *param)
|
|
|
|
{
|
|
|
|
STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (thread == NULL || param == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->Thread = thread;
|
|
|
|
DialogEx2(NULL, D_STATUS, StatusPrinterWindowDlg, p, true, true);
|
|
|
|
|
|
|
|
Free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show a message in the status window
|
|
|
|
void StatusPrinterWindowPrint(STATUS_WINDOW *sw, wchar_t *str)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (sw == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMessage(sw->hWnd, WM_APP + 1, 0, (LPARAM)str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// End and release the status window
|
|
|
|
void StatusPrinterWindowStop(STATUS_WINDOW *sw)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (sw == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send stop message
|
|
|
|
SendMessage(sw->hWnd, WM_APP + 2, 0, 0);
|
|
|
|
|
|
|
|
// Wait until the thread terminates
|
|
|
|
WaitThread(sw->Thread, INFINITE);
|
|
|
|
|
|
|
|
// Release the memory
|
|
|
|
ReleaseThread(sw->Thread);
|
|
|
|
Free(sw);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the status window
|
|
|
|
STATUS_WINDOW *StatusPrinterWindowStart(SOCK *s, wchar_t *account_name)
|
|
|
|
{
|
|
|
|
STATUS_WINDOW_PARAM *p;
|
|
|
|
STATUS_WINDOW *sw;
|
|
|
|
THREAD *t;
|
|
|
|
// Validate arguments
|
|
|
|
if (s == NULL || account_name == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = ZeroMalloc(sizeof(STATUS_WINDOW_PARAM));
|
|
|
|
p->Sock = s;
|
|
|
|
UniStrCpy(p->AccountName, sizeof(p->AccountName), account_name);
|
|
|
|
|
|
|
|
// Create a thread
|
|
|
|
t = NewThread(StatusPrinterWindowThread, p);
|
|
|
|
WaitThreadInit(t);
|
|
|
|
|
|
|
|
sw = ZeroMalloc(sizeof(STATUS_WINDOW));
|
|
|
|
sw->hWnd = p->hWnd;
|
|
|
|
sw->Thread = t;
|
|
|
|
|
|
|
|
return sw;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove all
|
|
|
|
void LbReset(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, LB_RESETCONTENT, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Password input dialog state change
|
|
|
|
void PasswordDlgProcChange(HWND hWnd, UI_PASSWORD_DLG *p)
|
|
|
|
{
|
|
|
|
bool b;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
b = true;
|
|
|
|
if (IsEmpty(hWnd, E_USERNAME))
|
|
|
|
{
|
|
|
|
b = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnable(hWnd, IDOK, b);
|
|
|
|
|
|
|
|
p->StartTick = Tick64();
|
|
|
|
if (p->RetryIntervalSec)
|
|
|
|
{
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
Hide(hWnd, P_PROGRESS);
|
|
|
|
Hide(hWnd, S_COUNTDOWN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the string
|
|
|
|
wchar_t *CbGetStr(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetText(hWnd, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// String search
|
|
|
|
UINT CbFindStr(HWND hWnd, UINT id, wchar_t *str)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
UINT CbFindStr9xA(HWND hWnd, UINT id, char *str)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of items
|
|
|
|
UINT CbNum(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SendMsg(hWnd, id, CB_GETCOUNT, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a string
|
|
|
|
UINT CbAddStrA(HWND hWnd, UINT id, char *str, UINT data)
|
|
|
|
{
|
|
|
|
wchar_t *tmp;
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
tmp = CopyStrToUni(str);
|
|
|
|
ret = CbAddStr(hWnd, id, tmp, data);
|
|
|
|
Free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
UINT CbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);
|
|
|
|
SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
|
|
|
|
|
|
|
|
if (CbNum(hWnd, id) == 1)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
GetTxt(hWnd, id, tmp, sizeof(tmp));
|
|
|
|
if (UniStrLen(tmp) == 0)
|
|
|
|
{
|
|
|
|
CbSelectIndex(hWnd, id, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
UINT CbAddStr9xA(HWND hWnd, UINT id, char *str, UINT data)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);
|
|
|
|
SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);
|
|
|
|
|
|
|
|
if (CbNum(hWnd, id) == 1)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
GetTxt(hWnd, id, tmp, sizeof(tmp));
|
|
|
|
if (UniStrLen(tmp) == 0)
|
|
|
|
{
|
|
|
|
CbSelectIndex(hWnd, id, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove all
|
|
|
|
void CbReset(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t *s;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetText(hWnd, id);
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, CB_RESETCONTENT, 0, 0);
|
|
|
|
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
SetText(hWnd, id, s);
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select by specifying the index
|
|
|
|
void CbSelectIndex(HWND hWnd, UINT id, UINT index)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, CB_SETCURSEL, index, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the data
|
|
|
|
UINT CbGetData(HWND hWnd, UINT id, UINT index)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || index == INFINITE)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SendMsg(hWnd, id, CB_GETITEMDATA, index, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for the data
|
|
|
|
UINT CbFindData(HWND hWnd, UINT id, UINT data)
|
|
|
|
{
|
|
|
|
UINT i, num;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = CbNum(hWnd, id);
|
|
|
|
if (num == INFINITE)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < num;i++)
|
|
|
|
{
|
|
|
|
if (CbGetData(hWnd, id, i) == data)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the height of the item
|
|
|
|
void CbSetHeight(HWND hWnd, UINT id, UINT value)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, CB_SETITEMHEIGHT, 0, (UINT)(GetTextScalingFactor() * (double)value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search by specifying the data
|
|
|
|
void CbSelect(HWND hWnd, UINT id, int data)
|
|
|
|
{
|
|
|
|
UINT index;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data == INFINITE)
|
|
|
|
{
|
|
|
|
// Get the first item
|
|
|
|
CbSelectIndex(hWnd, id, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = CbFindData(hWnd, id, data);
|
|
|
|
if (index == INFINITE)
|
|
|
|
{
|
|
|
|
// Can not be found
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select
|
|
|
|
CbSelectIndex(hWnd, id, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the currently selected item
|
|
|
|
UINT CbGetSelectIndex(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SendMsg(hWnd, id, CB_GETCURSEL, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the value that is currently selected
|
|
|
|
UINT CbGetSelect(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
UINT index;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = CbGetSelectIndex(hWnd, id);
|
|
|
|
if (index == INFINITE)
|
|
|
|
{
|
|
|
|
return INFINITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CbGetData(hWnd, id, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// OK button is pressed
|
|
|
|
void PasswordDlgOnOk(HWND hWnd, UI_PASSWORD_DLG *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetTxtA(hWnd, E_USERNAME, p->Username, sizeof(p->Username));
|
|
|
|
GetTxtA(hWnd, E_PASSWORD, p->Password, sizeof(p->Password));
|
|
|
|
p->Type = CbGetSelect(hWnd, C_TYPE);
|
|
|
|
|
|
|
|
if (p->ShowNoSavePassword)
|
|
|
|
{
|
|
|
|
p->NoSavePassword = IsChecked(hWnd, R_NO_SAVE_PASSWORD);
|
|
|
|
}
|
|
|
|
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Password input dialog procedure
|
|
|
|
UINT PasswordDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
UI_PASSWORD_DLG *p = (UI_PASSWORD_DLG *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetIcon(hWnd, 0, ICO_KEY);
|
|
|
|
CbSetHeight(hWnd, C_TYPE, 18);
|
|
|
|
if (p->ServerName != NULL)
|
|
|
|
{
|
|
|
|
FormatText(hWnd, 0, p->ServerName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetText(hWnd, 0, _UU("PW_LOGIN_DLG_TITLE"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->ProxyServer == false)
|
|
|
|
{
|
|
|
|
FormatText(hWnd, S_TITLE, p->ServerName == NULL ? "" : p->ServerName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("PW_MSG_PROXY"), p->ServerName == NULL ? "" : p->ServerName);
|
|
|
|
SetText(hWnd, S_TITLE, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enumerate the connection methods
|
|
|
|
SendMsg(hWnd, C_TYPE, CBEM_SETUNICODEFORMAT, true, 0);
|
|
|
|
|
|
|
|
if (StrCmpi(p->Username, WINUI_PASSWORD_NULL_USERNAME) != 0)
|
|
|
|
{
|
|
|
|
SetTextA(hWnd, E_USERNAME, p->Username);
|
|
|
|
SetTextA(hWnd, E_PASSWORD, p->Password);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->RetryIntervalSec = 0;
|
|
|
|
SetTextA(hWnd, E_USERNAME, "");
|
|
|
|
SetTextA(hWnd, E_PASSWORD, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->AdminMode == false)
|
|
|
|
{
|
|
|
|
if (p->ProxyServer == false)
|
|
|
|
{
|
|
|
|
CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);
|
|
|
|
CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_PROXY"), 0);
|
|
|
|
Disable(hWnd, C_TYPE);
|
|
|
|
}
|
|
|
|
|
|
|
|
CbSelect(hWnd, C_TYPE, p->Type);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CbAddStr(hWnd, C_TYPE, _UU("SM_PASSWORD_TYPE_STR"), 0);
|
|
|
|
Disable(hWnd, C_TYPE);
|
|
|
|
SetTextA(hWnd, E_USERNAME, "Administrator");
|
|
|
|
Disable(hWnd, E_USERNAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEmpty(hWnd, E_USERNAME))
|
|
|
|
{
|
|
|
|
FocusEx(hWnd, E_USERNAME);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FocusEx(hWnd, E_PASSWORD);
|
|
|
|
}
|
|
|
|
LimitText(hWnd, E_USERNAME, MAX_USERNAME_LEN);
|
|
|
|
LimitText(hWnd, E_PASSWORD, MAX_PASSWORD_LEN);
|
|
|
|
|
|
|
|
PasswordDlgProcChange(hWnd, p);
|
|
|
|
|
|
|
|
if (p->RetryIntervalSec != 0)
|
|
|
|
{
|
|
|
|
SetTimer(hWnd, 1, 50, NULL);
|
|
|
|
FormatText(hWnd, S_COUNTDOWN, p->RetryIntervalSec);
|
|
|
|
Show(hWnd, S_COUNTDOWN);
|
|
|
|
Show(hWnd, P_PROGRESS);
|
|
|
|
SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec * 1000);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Hide(hWnd, S_COUNTDOWN);
|
|
|
|
Hide(hWnd, P_PROGRESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->ShowNoSavePassword)
|
|
|
|
{
|
|
|
|
Show(hWnd, R_NO_SAVE_PASSWORD);
|
|
|
|
Check(hWnd, R_NO_SAVE_PASSWORD, p->NoSavePassword);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Hide(hWnd, R_NO_SAVE_PASSWORD);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->StartTick = Tick64();
|
|
|
|
|
|
|
|
if (p->CancelEvent != NULL)
|
|
|
|
{
|
|
|
|
SetTimer(hWnd, 2, 50, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if (p->RetryIntervalSec != 0)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
UINT64 end, now, start;
|
|
|
|
start = p->StartTick;
|
|
|
|
end = p->StartTick + (UINT64)(p->RetryIntervalSec * 1000);
|
|
|
|
now = Tick64();
|
|
|
|
|
|
|
|
if (now <= end)
|
|
|
|
{
|
|
|
|
UniFormat(tmp, sizeof(tmp), _UU("PW_RETRYCOUNT"), (UINT)((end - now) / 1000));
|
|
|
|
SetText(hWnd, S_COUNTDOWN, tmp);
|
|
|
|
SetPos(hWnd, P_PROGRESS, (UINT)(now - start));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
if (p->CancelEvent != NULL)
|
|
|
|
{
|
|
|
|
// Wait for the end event
|
|
|
|
HANDLE hEvent = (HANDLE)p->CancelEvent->pData;
|
|
|
|
UINT ret = WaitForSingleObject(hEvent, 0);
|
|
|
|
if (ret != WAIT_TIMEOUT)
|
|
|
|
{
|
|
|
|
// Forced termination event is set
|
|
|
|
Close(hWnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
PasswordDlgOnOk(hWnd, p);
|
|
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (HIWORD(wParam))
|
|
|
|
{
|
|
|
|
case EN_CHANGE:
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case E_USERNAME:
|
|
|
|
case E_PASSWORD:
|
|
|
|
PasswordDlgProcChange(hWnd, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CBN_SELCHANGE:
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case C_TYPE:
|
|
|
|
PasswordDlgProcChange(hWnd, p);
|
|
|
|
if (IsEmpty(hWnd, E_USERNAME))
|
|
|
|
{
|
|
|
|
FocusEx(hWnd, E_USERNAME);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FocusEx(hWnd, E_PASSWORD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the position of the progress bar
|
|
|
|
void SetPos(HWND hWnd, UINT id, UINT pos)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, PBM_SETPOS, pos, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the range of the progress bar
|
|
|
|
void SetRange(HWND hWnd, UINT id, UINT start, UINT end)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, PBM_SETRANGE32, start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Password input dialog
|
|
|
|
bool PasswordDlg(HWND hWnd, UI_PASSWORD_DLG *p)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->StartTick = Tick64();
|
|
|
|
|
|
|
|
return Dialog(hWnd, D_PASSWORD, PasswordDlgProc, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Passphrase input dialog
|
|
|
|
bool PassphraseDlg(HWND hWnd, char *pass, UINT pass_size, BUF *buf, bool p12)
|
|
|
|
{
|
|
|
|
PASSPHRASE_DLG p;
|
|
|
|
// Validate arguments
|
|
|
|
if (pass == NULL || buf == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&p, sizeof(PASSPHRASE_DLG));
|
|
|
|
|
|
|
|
p.buf = buf;
|
|
|
|
p.p12 = p12;
|
|
|
|
|
|
|
|
// Examine whether it is encrypted first
|
|
|
|
if (p12 == false)
|
|
|
|
{
|
|
|
|
// Secret key
|
|
|
|
if (IsEncryptedK(buf, true) == false)
|
|
|
|
{
|
|
|
|
// Unencrypted
|
|
|
|
StrCpy(pass, pass_size, "");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// PKCS#12
|
|
|
|
P12 *p12 = BufToP12(buf);
|
|
|
|
if (p12 == NULL)
|
|
|
|
{
|
|
|
|
// It is in unknown format, but not encrypted
|
|
|
|
StrCpy(pass, pass_size, "");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEncryptedP12(p12) == false)
|
|
|
|
{
|
|
|
|
// Unencrypted
|
|
|
|
StrCpy(pass, pass_size, "");
|
|
|
|
FreeP12(p12);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
FreeP12(p12);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the dialog
|
|
|
|
if (Dialog(hWnd, D_PASSPHRASE, PassphraseDlgProc, &p) == false)
|
|
|
|
{
|
|
|
|
// Cancel
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
StrCpy(pass, pass_size, p.pass);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// WM_COMMAND handler
|
|
|
|
void PassphraseDlgProcCommand(HWND hWnd, PASSPHRASE_DLG *p)
|
|
|
|
{
|
|
|
|
char *pass;
|
|
|
|
bool ok;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pass = GetTextA(hWnd, E_PASSPHRASE);
|
|
|
|
if (pass == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok = false;
|
|
|
|
|
|
|
|
if (p->p12 == false)
|
|
|
|
{
|
|
|
|
K *k;
|
|
|
|
k = BufToK(p->buf, true, true, pass);
|
|
|
|
if (k != NULL)
|
|
|
|
{
|
|
|
|
ok = true;
|
|
|
|
FreeK(k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
X *x;
|
|
|
|
K *k;
|
|
|
|
P12 *p12;
|
|
|
|
p12 = BufToP12(p->buf);
|
|
|
|
if (p12 != NULL)
|
|
|
|
{
|
|
|
|
if (ParseP12(p12, &x, &k, pass))
|
|
|
|
{
|
|
|
|
FreeX(x);
|
|
|
|
FreeK(k);
|
|
|
|
ok = true;
|
|
|
|
}
|
|
|
|
FreeP12(p12);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(pass);
|
|
|
|
|
|
|
|
SetEnable(hWnd, IDOK, ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Passphrase input dialog procedure
|
|
|
|
UINT PassphraseDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
PASSPHRASE_DLG *p = (PASSPHRASE_DLG *)param;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
PassphraseDlgProcCommand(hWnd, p);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
GetTxtA(hWnd, E_PASSPHRASE, p->pass, sizeof(p->pass));
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case E_PASSPHRASE:
|
|
|
|
PassphraseDlgProcCommand(hWnd, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// [Save File] dialog
|
|
|
|
wchar_t *SaveDlg(HWND hWnd, wchar_t *filter, wchar_t *title, wchar_t *default_name, wchar_t *default_ext)
|
|
|
|
{
|
|
|
|
wchar_t *filter_str;
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
OPENFILENAMEW o;
|
|
|
|
|
|
|
|
// Validate arguments
|
|
|
|
if (filter == NULL)
|
|
|
|
{
|
|
|
|
filter = _UU("DLG_ALL_FILES");
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_str = MakeFilter(filter);
|
|
|
|
|
|
|
|
Zero(&o, sizeof(o));
|
|
|
|
Zero(tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
if (default_name != NULL)
|
|
|
|
{
|
|
|
|
UniStrCpy(tmp, sizeof(tmp), default_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
o.lStructSize = sizeof(o);
|
|
|
|
o.hwndOwner = hWnd;
|
|
|
|
o.hInstance = GetModuleHandle(NULL);
|
|
|
|
o.lpstrFile = tmp;
|
|
|
|
o.lpstrTitle = title;
|
|
|
|
o.lpstrFilter = filter_str;
|
|
|
|
o.nMaxFile = sizeof(tmp);
|
|
|
|
o.Flags = OFN_OVERWRITEPROMPT;
|
|
|
|
o.lpstrDefExt = default_ext;
|
|
|
|
|
|
|
|
if (GetSaveFileNameW(&o) == false)
|
|
|
|
{
|
|
|
|
Free(filter_str);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(filter_str);
|
|
|
|
|
|
|
|
return UniCopyStr(tmp);
|
|
|
|
}
|
|
|
|
char *SaveDlgA(HWND hWnd, char *filter, char *title, char *default_name, char *default_ext)
|
|
|
|
{
|
|
|
|
char *filter_str;
|
|
|
|
char tmp[MAX_SIZE];
|
|
|
|
OPENFILENAME o;
|
|
|
|
// Validate arguments
|
|
|
|
if (filter == NULL)
|
|
|
|
{
|
|
|
|
filter = _SS("DLG_ALL_FILES");
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_str = MakeFilterA(filter);
|
|
|
|
|
|
|
|
Zero(&o, sizeof(o));
|
|
|
|
Zero(tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
if (default_name != NULL)
|
|
|
|
{
|
|
|
|
StrCpy(tmp, sizeof(tmp), default_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
o.lStructSize = sizeof(o);
|
|
|
|
o.hwndOwner = hWnd;
|
|
|
|
o.hInstance = GetModuleHandle(NULL);
|
|
|
|
o.lpstrFile = tmp;
|
|
|
|
o.lpstrTitle = title;
|
|
|
|
o.lpstrFilter = filter_str;
|
|
|
|
o.nMaxFile = sizeof(tmp);
|
|
|
|
o.Flags = OFN_OVERWRITEPROMPT;
|
|
|
|
o.lpstrDefExt = default_ext;
|
|
|
|
|
|
|
|
if (GetSaveFileName(&o) == false)
|
|
|
|
{
|
|
|
|
Free(filter_str);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(filter_str);
|
|
|
|
|
|
|
|
return CopyStr(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// [Open File] dialog
|
|
|
|
wchar_t *OpenDlg(HWND hWnd, wchar_t *filter, wchar_t *title)
|
|
|
|
{
|
|
|
|
wchar_t *filter_str;
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
OPENFILENAMEW o;
|
|
|
|
|
|
|
|
// Validate arguments
|
|
|
|
if (filter == NULL)
|
|
|
|
{
|
|
|
|
filter = _UU("DLG_ALL_FILES");
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_str = MakeFilter(filter);
|
|
|
|
|
|
|
|
Zero(&o, sizeof(OPENFILENAMEW));
|
|
|
|
Zero(tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
o.lStructSize = sizeof(o);
|
|
|
|
o.hwndOwner = hWnd;
|
|
|
|
o.hInstance = GetModuleHandle(NULL);
|
|
|
|
o.lpstrFilter = filter_str;
|
|
|
|
o.lpstrFile = tmp;
|
|
|
|
o.nMaxFile = sizeof(tmp);
|
|
|
|
o.lpstrTitle = title;
|
|
|
|
o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
|
|
|
|
|
|
|
if (GetOpenFileNameW(&o) == false)
|
|
|
|
{
|
|
|
|
Free(filter_str);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(filter_str);
|
|
|
|
|
|
|
|
return UniCopyStr(tmp);
|
|
|
|
}
|
|
|
|
char *OpenDlgA(HWND hWnd, char *filter, char *title)
|
|
|
|
{
|
|
|
|
char *filter_str;
|
|
|
|
char tmp[MAX_SIZE];
|
|
|
|
OPENFILENAME o;
|
|
|
|
// Validate arguments
|
|
|
|
if (filter == NULL)
|
|
|
|
{
|
|
|
|
filter = _SS("DLG_ALL_FILES");
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_str = MakeFilterA(filter);
|
|
|
|
|
|
|
|
Zero(&o, sizeof(OPENFILENAME));
|
|
|
|
Zero(tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
o.lStructSize = sizeof(o);
|
|
|
|
o.hwndOwner = hWnd;
|
|
|
|
o.hInstance = GetModuleHandle(NULL);
|
|
|
|
o.lpstrFilter = filter_str;
|
|
|
|
o.lpstrFile = tmp;
|
|
|
|
o.nMaxFile = sizeof(tmp);
|
|
|
|
o.lpstrTitle = title;
|
|
|
|
o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
|
|
|
|
|
|
|
if (GetOpenFileName(&o) == false)
|
|
|
|
{
|
|
|
|
Free(filter_str);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(filter_str);
|
|
|
|
|
|
|
|
return CopyStr(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate the filter string
|
|
|
|
wchar_t *MakeFilter(wchar_t *str)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
wchar_t *ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (str == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ZeroMalloc(UniStrSize(str) + 32);
|
|
|
|
|
|
|
|
for (i = 0;i < UniStrLen(str);i++)
|
|
|
|
{
|
|
|
|
if (str[i] == L'|')
|
|
|
|
{
|
|
|
|
ret[i] = L'\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret[i] = str[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
char *MakeFilterA(char *str)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
char *ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (str == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ZeroMalloc(StrSize(str) + 32);
|
|
|
|
|
|
|
|
for (i = 0;i < StrLen(str);i++)
|
|
|
|
{
|
|
|
|
if (str[i] == '|')
|
|
|
|
{
|
|
|
|
ret[i] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret[i] = str[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execution of batch
|
|
|
|
bool ExecuteSecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev, WINUI_SECURE_BATCH *batch)
|
|
|
|
{
|
|
|
|
LIST *o;
|
|
|
|
void *buf;
|
|
|
|
UINT size = 10 * 1024; // Maximum size of the data
|
|
|
|
UINT type = INFINITE;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL || dev == NULL || batch == NULL || sec == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (batch->Type)
|
|
|
|
{
|
|
|
|
case WINUI_SECURE_DELETE_CERT:
|
|
|
|
type = SEC_X;
|
|
|
|
goto DELETE_OBJECT;
|
|
|
|
|
|
|
|
case WINUI_SECURE_DELETE_KEY:
|
|
|
|
type = SEC_K;
|
|
|
|
goto DELETE_OBJECT;
|
|
|
|
|
|
|
|
case WINUI_SECURE_DELETE_DATA:
|
|
|
|
type = SEC_DATA;
|
|
|
|
goto DELETE_OBJECT;
|
|
|
|
|
|
|
|
case WINUI_SECURE_DELETE_OBJECT:
|
|
|
|
// Delete the object
|
|
|
|
DELETE_OBJECT:
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_DELETE"));
|
|
|
|
if (DeleteSecObjectByName(sec, batch->Name, type) == false)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_DELETE"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_ENUM_OBJECTS:
|
|
|
|
// Enumerate objects
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_ENUM"));
|
|
|
|
o = EnumSecObject(sec);
|
|
|
|
if (o == NULL)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_ENUM"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
batch->EnumList = o;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_WRITE_DATA:
|
|
|
|
// Write the data
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_WRITE_DATA"));
|
|
|
|
if (WriteSecData(sec, batch->Private, batch->Name, batch->InputData->Buf, batch->InputData->Size) == false)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
|
|
|
|
_UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_READ_DATA:
|
|
|
|
// Read the data
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_READ_DATA"));
|
|
|
|
buf = MallocEx(size, true);
|
|
|
|
size = ReadSecData(sec, batch->Name, buf, size);
|
|
|
|
if (size == 0)
|
|
|
|
{
|
|
|
|
Free(buf);
|
|
|
|
p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
|
|
|
|
_UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
batch->OutputData = NewBuf();
|
|
|
|
WriteBuf(batch->OutputData, buf, size);
|
|
|
|
SeekBuf(batch->OutputData, 0, 0);
|
|
|
|
Free(buf);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_WRITE_CERT:
|
|
|
|
// Write the certificate
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_WRITE_CERT"));
|
|
|
|
if (WriteSecCert(sec, batch->Private, batch->Name, batch->InputX) == false)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
|
|
|
|
_UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_READ_CERT:
|
|
|
|
// Read the certificate
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_READ_CERT"));
|
|
|
|
batch->OutputX = ReadSecCert(sec, batch->Name);
|
|
|
|
if (batch->OutputX == NULL)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
|
|
|
|
_UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_WRITE_KEY:
|
|
|
|
// Write the secret key
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_WRITE_KEY"));
|
|
|
|
if (WriteSecKey(sec, batch->Private, batch->Name, batch->InputK) == false)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
|
|
|
|
_UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINUI_SECURE_SIGN_WITH_KEY:
|
|
|
|
// Signature
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_SIGN"));
|
|
|
|
if (SignSec(sec, batch->Name, batch->OutputSign, batch->InputData->Buf, batch->InputData->Size) == false)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?
|
|
|
|
_UU("SEC_ERROR_SIGN_1") : _UU("SEC_ERROR_SIGN_2"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run the secure device operations as a batch job
|
|
|
|
void SecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev)
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || p == NULL || dev == NULL || sec == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sequential processing
|
|
|
|
for (i = 0;i < p->w->num_batch;i++)
|
|
|
|
{
|
|
|
|
WINUI_SECURE_BATCH *batch = &p->w->batch[i];
|
|
|
|
|
|
|
|
if (ExecuteSecureDeviceBatch(hWnd, sec, p, dev, batch) == false)
|
|
|
|
{
|
|
|
|
// If fail even one, abort immediately
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All batch job succeeded
|
|
|
|
p->Succeed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Thread to perform a secure device operation
|
|
|
|
void SecureDeviceThread(THREAD *t, void *param)
|
|
|
|
{
|
|
|
|
SECURE *sec;
|
|
|
|
SECURE_DEVICE_THREAD *p = (SECURE_DEVICE_THREAD *)param;
|
|
|
|
SECURE_DEVICE *dev;
|
|
|
|
HWND hWnd;
|
|
|
|
// Validate arguments
|
|
|
|
if (t == NULL || param == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->Succeed = false;
|
|
|
|
p->ErrorMessage = NULL;
|
|
|
|
|
|
|
|
hWnd = p->hWnd;
|
|
|
|
|
|
|
|
// Open the device
|
|
|
|
dev = GetSecureDevice(p->w->device_id);
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_OPENING"));
|
|
|
|
sec = OpenSec(p->w->device_id);
|
|
|
|
if (sec == NULL)
|
|
|
|
{
|
|
|
|
// Device open failure
|
|
|
|
if (p->w->device_id != 9)
|
|
|
|
{
|
|
|
|
p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICE"), dev->DeviceName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICEEX"), dev->DeviceName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Open the session
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_OPEN_SESSION"));
|
|
|
|
if (OpenSecSession(sec, 0) == false)
|
|
|
|
{
|
|
|
|
// Session initialization failure
|
|
|
|
p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_SESSION"), dev->DeviceName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Login
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_LOGIN"));
|
|
|
|
if (LoginSec(sec, p->pin) == false)
|
|
|
|
{
|
|
|
|
// Login failure
|
|
|
|
p->ErrorMessage =UniCopyStr(_UU("SEC_ERROR_LOGIN"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Batch processing main
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_INIT_BATCH"));
|
|
|
|
SecureDeviceBatch(hWnd, sec, p, dev);
|
|
|
|
|
|
|
|
// Logout
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_LOGOUT"));
|
|
|
|
LogoutSec(sec);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the session
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_CLOSE_SESSION"));
|
|
|
|
CloseSecSession(sec);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the device
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_CLOSING"));
|
|
|
|
CloseSec(sec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->Succeed)
|
|
|
|
{
|
|
|
|
// If successful, show the message for 150ms (service)
|
|
|
|
SetText(hWnd, S_STATUS, _UU("SEC_FINISHED"));
|
|
|
|
SleepThread(150);
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMessage(p->hWnd, WM_APP + 1, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start a secure device operation
|
|
|
|
void StartSecureDevice(HWND hWnd, SECURE_DEVICE_WINDOW *w)
|
|
|
|
{
|
|
|
|
SECURE_DEVICE_THREAD *p;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || w == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable the control
|
|
|
|
EnableSecureDeviceWindowControls(hWnd, false);
|
|
|
|
|
|
|
|
// Start the thread
|
|
|
|
p = ZeroMalloc(sizeof(SECURE_DEVICE_THREAD));
|
|
|
|
p->w = w;
|
|
|
|
p->hWnd = hWnd;
|
|
|
|
w->p = p;
|
|
|
|
p->pin = GetTextA(hWnd, E_PIN);
|
|
|
|
ReleaseThread(NewThread(SecureDeviceThread, p));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable or disable the control of the secure device operation window
|
|
|
|
void EnableSecureDeviceWindowControls(HWND hWnd, bool enable)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
Show(hWnd, S_PIN_CODE);
|
|
|
|
Show(hWnd, E_PIN);
|
|
|
|
Show(hWnd, S_WARNING);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Hide(hWnd, S_PIN_CODE);
|
|
|
|
Hide(hWnd, E_PIN);
|
|
|
|
Hide(hWnd, S_WARNING);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnable(hWnd, IDOK, enable);
|
|
|
|
SetEnable(hWnd, IDCANCEL, enable);
|
|
|
|
SetEnable(hWnd, S_TITLE, enable);
|
|
|
|
SetEnable(hWnd, S_DEVICE_INFO, enable);
|
|
|
|
SetEnable(hWnd, S_INSERT_SECURE, enable);
|
|
|
|
|
|
|
|
if (enable == false)
|
|
|
|
{
|
|
|
|
DisableClose(hWnd);
|
|
|
|
SetText(hWnd, S_STATUS, L"");
|
|
|
|
Show(hWnd, S_STATUS);
|
|
|
|
PlayAvi(hWnd, A_PROGRESS, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EnableClose(hWnd);
|
|
|
|
SetText(hWnd, S_STATUS, L"");
|
|
|
|
Hide(hWnd, S_STATUS);
|
|
|
|
StopAvi(hWnd, A_PROGRESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Secure device operation window procedure
|
|
|
|
UINT SecureDeviceWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
|
|
|
|
{
|
|
|
|
SECURE_DEVICE_WINDOW *w = (SECURE_DEVICE_WINDOW *)param;
|
|
|
|
SECURE_DEVICE *dev = GetSecureDevice(w->device_id);
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
if (dev == NULL)
|
|
|
|
{
|
|
|
|
MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_ERROR_INVALID_ID"), w->device_id);
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsJPKI(dev->Id))
|
|
|
|
{
|
|
|
|
// Juki card
|
|
|
|
Hide(hWnd, S_IMAGE);
|
|
|
|
Show(hWnd, S_IMAGE2);
|
|
|
|
Hide(hWnd, S_IMAGE_TSUKUBA);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Regular card
|
|
|
|
Hide(hWnd, S_IMAGE2);
|
|
|
|
|
|
|
|
if (w->BitmapId != 0)
|
|
|
|
{
|
|
|
|
// For University of Tsukuba
|
|
|
|
Hide(hWnd, S_IMAGE);
|
|
|
|
Show(hWnd, S_IMAGE_TSUKUBA);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// For general use
|
|
|
|
Show(hWnd, S_IMAGE);
|
|
|
|
Hide(hWnd, S_IMAGE_TSUKUBA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FormatText(hWnd, 0, dev->Type != SECURE_USB_TOKEN ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN"),
|
|
|
|
dev->DeviceName);
|
|
|
|
FormatText(hWnd, S_TITLE, dev->DeviceName);
|
|
|
|
FormatText(hWnd, S_INSERT_SECURE,
|
|
|
|
dev->Type != SECURE_USB_TOKEN ? _UU("SEC_INIT_MSG_1") : _UU("SEC_INIT_MSG_2"));
|
|
|
|
FormatText(hWnd, S_DEVICE_INFO,
|
|
|
|
dev->DeviceName, dev->Manufacturer, dev->ModuleName);
|
|
|
|
|
|
|
|
DlgFont(hWnd, S_SOFTWARE_TITLE, 11, 0);
|
|
|
|
SetText(hWnd, S_SOFTWARE_TITLE, title_bar);
|
|
|
|
|
|
|
|
DlgFont(hWnd, S_TITLE, 14, true);
|
|
|
|
DlgFont(hWnd, S_DEVICE_INFO, 11, false);
|
|
|
|
DlgFont(hWnd, S_STATUS, 13, true);
|
|
|
|
EnableSecureDeviceWindowControls(hWnd, true);
|
|
|
|
OpenAvi(hWnd, A_PROGRESS, AVI_PROGRESS);
|
|
|
|
|
|
|
|
SetIcon(hWnd, 0, ICO_KEY);
|
|
|
|
|
|
|
|
// Initial PIN
|
|
|
|
if ((w->default_pin != NULL && StrLen(w->default_pin) != 0) || (cached_pin_code_expires >= Tick64()))
|
|
|
|
{
|
|
|
|
if (w->default_pin != NULL && StrLen(w->default_pin) != 0)
|
|
|
|
{
|
|
|
|
SetTextA(hWnd, E_PIN, w->default_pin);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetTextA(hWnd, E_PIN, cached_pin_code);
|
|
|
|
}
|
|
|
|
SetTimer(hWnd, 1, 1, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
KillTimer(hWnd, 1);
|
|
|
|
Command(hWnd, IDOK);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
StartSecureDevice(hWnd, w);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDCANCEL:
|
|
|
|
Close(hWnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
if (IsEnable(hWnd, IDCANCEL))
|
|
|
|
{
|
|
|
|
CloseAvi(hWnd, A_PROGRESS);
|
|
|
|
EndDialog(hWnd, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_APP + 1:
|
|
|
|
// There is a response from the thread
|
|
|
|
if (w->p != NULL)
|
|
|
|
{
|
|
|
|
if (w->p->Succeed)
|
|
|
|
{
|
|
|
|
// Success
|
|
|
|
if (w->default_pin != NULL)
|
|
|
|
{
|
|
|
|
StrCpy(w->default_pin, 128, w->p->pin);
|
|
|
|
}
|
|
|
|
StrCpy(cached_pin_code, sizeof(cached_pin_code), w->p->pin);
|
|
|
|
cached_pin_code_expires = Tick64() + (UINT64)WINUI_SECUREDEVICE_PIN_CACHE_TIME;
|
|
|
|
Free(w->p->pin);
|
|
|
|
Free(w->p);
|
|
|
|
EndDialog(hWnd, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Failure
|
|
|
|
cached_pin_code_expires = 0;
|
|
|
|
EnableSecureDeviceWindowControls(hWnd, true);
|
|
|
|
FocusEx(hWnd, E_PIN);
|
|
|
|
MsgBox(hWnd, MB_ICONEXCLAMATION, w->p->ErrorMessage);
|
|
|
|
Free(w->p->pin);
|
|
|
|
Free(w->p->ErrorMessage);
|
|
|
|
Free(w->p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a WM_COMMAND
|
|
|
|
void Command(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
SendMessage(hWnd, WM_COMMAND, id, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the secure device window
|
|
|
|
bool SecureDeviceWindow(HWND hWnd, WINUI_SECURE_BATCH *batch, UINT num_batch, UINT device_id, UINT bitmap_id)
|
|
|
|
{
|
|
|
|
SECURE_DEVICE_WINDOW w;
|
|
|
|
UINT i;
|
|
|
|
// Validate arguments
|
|
|
|
if (batch == NULL || num_batch == 0 || device_id == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the success flag
|
|
|
|
for (i = 0;i < num_batch;i++)
|
|
|
|
{
|
|
|
|
batch[i].Succeed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&w, sizeof(w));
|
|
|
|
w.batch = batch;
|
|
|
|
w.device_id = device_id;
|
|
|
|
w.num_batch = num_batch;
|
|
|
|
w.BitmapId = bitmap_id;
|
|
|
|
|
|
|
|
// Open a dialog
|
|
|
|
return (bool)Dialog(hWnd, D_SECURE, SecureDeviceWindowProc, &w);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop playing the AVI
|
|
|
|
void StopAvi(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Animate_Stop(DlgItem(hWnd, id));
|
|
|
|
Hide(hWnd, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Play an AVI
|
|
|
|
void PlayAvi(HWND hWnd, UINT id, bool repeat)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Show(hWnd, id);
|
|
|
|
Animate_Play(DlgItem(hWnd, id), 0, -1, (repeat ? -1 : 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the AVI file
|
|
|
|
void CloseAvi(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
StopAvi(hWnd, id);
|
|
|
|
Animate_Close(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open an AVI file
|
|
|
|
void OpenAvi(HWND hWnd, UINT id, UINT avi_id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || avi_id == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Hide(hWnd, id);
|
|
|
|
Animate_OpenEx(DlgItem(hWnd, id), hDll, MAKEINTRESOURCE(avi_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the font to the control
|
|
|
|
void DlgFont(HWND hWnd, UINT id, UINT size, UINT bold)
|
|
|
|
{
|
|
|
|
DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);
|
|
|
|
|
|
|
|
if (param == NULL || param->meiryo == false)
|
|
|
|
{
|
|
|
|
SetFont(hWnd, id, Font(size, bold));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetFont(hWnd, id, GetFont((_GETLANG() == 2 ? "Microsoft YaHei" : GetMeiryoFontName()), size, bold, false, false, false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate a standard font
|
|
|
|
HFONT Font(UINT size, UINT bold)
|
|
|
|
{
|
|
|
|
return GetFont(NULL, size, bold, false, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dialog procedure for internal management
|
|
|
|
UINT CALLBACK InternalDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);
|
|
|
|
void *app_param = NULL;
|
|
|
|
bool white_flag = false;
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg == WM_INITDIALOG)
|
|
|
|
{
|
|
|
|
DoEvents(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param == NULL)
|
|
|
|
{
|
|
|
|
if (msg == WM_INITDIALOG)
|
|
|
|
{
|
|
|
|
param = (void *)lParam;
|
|
|
|
InitDialogInternational(hWnd, param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (param != NULL)
|
|
|
|
{
|
|
|
|
app_param = param->param;
|
|
|
|
white_flag = param->white;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = DlgProc(hWnd, msg, wParam, lParam, white_flag);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (param != NULL)
|
|
|
|
{
|
|
|
|
if (param->proc != NULL)
|
|
|
|
{
|
|
|
|
ret = param->proc(hWnd, msg, wParam, lParam, app_param);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (msg == WM_CLOSE)
|
|
|
|
{
|
|
|
|
EndDialog(hWnd, 0);
|
|
|
|
}
|
|
|
|
else if (msg == WM_COMMAND && (wParam == IDOK || wParam == IDCANCEL))
|
|
|
|
{
|
|
|
|
Close(hWnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg == WM_INITDIALOG)
|
|
|
|
{
|
|
|
|
SetForegroundWindow(hWnd);
|
|
|
|
SetActiveWindow(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-08-06 11:43:23 +03:00
|
|
|
// Show a dialog box
|
|
|
|
UINT Dialog(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param)
|
|
|
|
{
|
|
|
|
bool white = true;
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2018-08-06 11:43:23 +03:00
|
|
|
return DialogEx(hWnd, id, proc, param, white);
|
|
|
|
}
|
|
|
|
UINT DialogEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white)
|
|
|
|
{
|
|
|
|
return DialogEx2(hWnd, id, proc, param, white, false);
|
|
|
|
}
|
|
|
|
UINT DialogEx2(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white, bool meiryo)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
DIALOG_PARAM p;
|
|
|
|
// Validate arguments
|
|
|
|
if (id == 0)
|
2014-01-04 17:00:08 +04:00
|
|
|
{
|
2018-08-06 11:43:23 +03:00
|
|
|
return 0;
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
2018-08-06 11:43:23 +03:00
|
|
|
Zero(&p, sizeof(p));
|
|
|
|
p.param = param;
|
|
|
|
p.white = white;
|
|
|
|
p.proc = proc;
|
|
|
|
|
|
|
|
p.BitmapList = NewBitmapList();
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
p.meiryo = meiryo;
|
2018-08-06 11:43:23 +03:00
|
|
|
|
|
|
|
ret = DialogInternal(hWnd, id, InternalDialogProc, &p);
|
|
|
|
|
|
|
|
FreeBitmapList(p.BitmapList);
|
|
|
|
|
|
|
|
return ret;
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the icon cache
|
|
|
|
void InitIconCache()
|
|
|
|
{
|
|
|
|
if (icon_cache_list != NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
icon_cache_list = NewList(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the icon cache
|
|
|
|
void FreeIconCache()
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
if (icon_cache_list == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(icon_cache_list);i++)
|
|
|
|
{
|
|
|
|
ICON_CACHE *c = LIST_DATA(icon_cache_list, i);
|
|
|
|
DestroyIcon(c->hIcon);
|
|
|
|
Free(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseList(icon_cache_list);
|
|
|
|
icon_cache_list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the Icon
|
|
|
|
HICON LoadIconEx(UINT id, bool small_icon)
|
|
|
|
{
|
|
|
|
HICON h = NULL;
|
|
|
|
UINT i;
|
|
|
|
if (icon_cache_list == NULL)
|
|
|
|
{
|
|
|
|
return small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
LockList(icon_cache_list);
|
|
|
|
{
|
|
|
|
for (i = 0;i < LIST_NUM(icon_cache_list);i++)
|
|
|
|
{
|
|
|
|
ICON_CACHE *c = LIST_DATA(icon_cache_list, i);
|
|
|
|
if (c->id == id && c->small_icon == small_icon)
|
|
|
|
{
|
|
|
|
h = c->hIcon;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (h == NULL)
|
|
|
|
{
|
|
|
|
h = small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);
|
|
|
|
if (h != NULL)
|
|
|
|
{
|
|
|
|
ICON_CACHE *c = ZeroMalloc(sizeof(ICON_CACHE));
|
|
|
|
c->hIcon = h;
|
|
|
|
c->id = id;
|
|
|
|
c->small_icon = small_icon;
|
|
|
|
Add(icon_cache_list, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UnlockList(icon_cache_list);
|
|
|
|
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a large Icon
|
|
|
|
HICON LoadLargeIcon(UINT id)
|
|
|
|
{
|
|
|
|
return LoadIconEx(id, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a small icon
|
|
|
|
HICON LoadSmallIcon(UINT id)
|
|
|
|
{
|
|
|
|
return LoadIconEx(id, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a large icon
|
|
|
|
HICON LoadLargeIconInner(UINT id)
|
|
|
|
{
|
|
|
|
HICON ret;
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, 0);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, LR_VGACOLOR);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadIcon(hDll, MAKEINTRESOURCE(id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a small icon
|
|
|
|
HICON LoadSmallIconInner(UINT id)
|
|
|
|
{
|
|
|
|
HICON ret;
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, 0);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, LR_VGACOLOR);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);
|
|
|
|
if (ret == NULL)
|
|
|
|
{
|
|
|
|
ret = LoadLargeIconInner(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the icon to the button or window
|
|
|
|
void SetIcon(HWND hWnd, UINT id, UINT icon_id)
|
|
|
|
{
|
|
|
|
HICON icon1, icon2;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
icon1 = LoadLargeIcon(icon_id);
|
|
|
|
if (icon1 == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == 0)
|
|
|
|
{
|
|
|
|
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon1);
|
|
|
|
icon2 = LoadSmallIcon(icon_id);
|
|
|
|
if (icon2 == NULL)
|
|
|
|
{
|
|
|
|
icon2 = icon1;
|
|
|
|
}
|
|
|
|
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool is_btn = true;
|
|
|
|
wchar_t *s = GetClass(hWnd, id);
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(s, L"Static") == 0)
|
|
|
|
{
|
|
|
|
is_btn = false;
|
|
|
|
}
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_btn)
|
|
|
|
{
|
|
|
|
SendMsg(hWnd, id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SendMsg(hWnd, id, STM_SETICON, (WPARAM)icon1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the radio button is checked
|
|
|
|
bool IsChecked(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsDlgButtonChecked(hWnd, id) == BST_CHECKED ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the radio button
|
|
|
|
void Check(HWND hWnd, UINT id, bool b)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!(!IsChecked(hWnd, id))) != (!(!b)))
|
|
|
|
{
|
|
|
|
CheckDlgButton(hWnd, id, b ? BST_CHECKED : BST_UNCHECKED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Limit the number of characters that can be entered into the text-box
|
|
|
|
void LimitText(HWND hWnd, UINT id, UINT count)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, EM_LIMITTEXT, count, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Font settings
|
|
|
|
void SetFont(HWND hWnd, UINT id, HFONT hFont)
|
|
|
|
{
|
|
|
|
SetFontEx(hWnd, id, hFont, false);
|
|
|
|
}
|
|
|
|
void SetFontEx(HWND hWnd, UINT id, HFONT hFont, bool no_adjust_font_size)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || hFont == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMessage(DlgItem(hWnd, id), WM_SETFONT, (WPARAM)hFont, true);
|
|
|
|
|
|
|
|
if (no_adjust_font_size == false)
|
|
|
|
{
|
|
|
|
AdjustFontSize(hWnd, id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the font size
|
|
|
|
bool CalcFontSize(HFONT hFont, UINT *x, UINT *y)
|
|
|
|
{
|
|
|
|
UINT xx = 0, yy = 0;
|
|
|
|
TEXTMETRIC tm;
|
|
|
|
SIZE sz;
|
|
|
|
bool ret = false;
|
|
|
|
HDC hDC;
|
|
|
|
|
|
|
|
hDC = CreateCompatibleDC(NULL);
|
|
|
|
|
|
|
|
SelectObject(hDC, hFont);
|
|
|
|
|
|
|
|
Zero(&tm, sizeof(tm));
|
|
|
|
Zero(&sz, sizeof(sz));
|
|
|
|
|
|
|
|
if (GetTextMetrics(hDC, &tm))
|
|
|
|
{
|
|
|
|
xx = tm.tmAveCharWidth;
|
|
|
|
yy = tm.tmHeight;
|
|
|
|
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
if (GetTextExtentPoint32(hDC,
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
|
|
|
52, &sz))
|
|
|
|
{
|
|
|
|
xx = (sz.cx / 26 + 1) / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x != NULL)
|
|
|
|
{
|
|
|
|
*x = xx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y != NULL)
|
|
|
|
{
|
|
|
|
*y = yy;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteDC(hDC);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the font magnification
|
|
|
|
double GetTextScalingFactor()
|
|
|
|
{
|
|
|
|
static int cached_dpi = 0;
|
|
|
|
double ret = 1.0;
|
|
|
|
|
|
|
|
if (cached_dpi == 0)
|
|
|
|
{
|
|
|
|
HDC hDC = CreateCompatibleDC(NULL);
|
|
|
|
|
|
|
|
if (hDC != NULL)
|
|
|
|
{
|
|
|
|
cached_dpi = GetDeviceCaps(hDC, LOGPIXELSY);
|
|
|
|
|
|
|
|
DeleteDC(hDC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cached_dpi != 0)
|
|
|
|
{
|
|
|
|
ret = (double)cached_dpi / 96.0;
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
ret = -ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the parameters of the font that was created in the past
|
|
|
|
bool GetFontParam(HFONT hFont, struct FONT *f)
|
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
// Validate arguments
|
|
|
|
if (hFont == NULL || f == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for the existing font
|
|
|
|
LockList(font_list);
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
|
|
|
|
for (i = 0;i < LIST_NUM(font_list);i++)
|
|
|
|
{
|
|
|
|
FONT *n = LIST_DATA(font_list, i);
|
|
|
|
|
|
|
|
if (n->hFont == hFont)
|
|
|
|
{
|
|
|
|
Copy(f, n, sizeof(FONT));
|
|
|
|
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UnlockList(font_list);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the font
|
|
|
|
HFONT GetFont(char *name, UINT size, bool bold, bool italic, bool underline, bool strikeout)
|
|
|
|
{
|
|
|
|
HFONT hFont;
|
|
|
|
HDC hDC;
|
|
|
|
// Validate arguments
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
name = font_name;
|
|
|
|
}
|
|
|
|
if (size == 0)
|
|
|
|
{
|
|
|
|
size = font_size;
|
|
|
|
if (size == 0)
|
|
|
|
{
|
|
|
|
size = 9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for the existing font
|
|
|
|
LockList(font_list);
|
|
|
|
{
|
|
|
|
FONT *f, t;
|
|
|
|
DWORD font_quality = ANTIALIASED_QUALITY;
|
|
|
|
OS_INFO *os = GetOsInfo();
|
|
|
|
UINT x = 0;
|
|
|
|
UINT y = 0;
|
|
|
|
int rotate = 0;
|
|
|
|
UINT dpi;
|
|
|
|
|
|
|
|
Zero(&t, sizeof(t));
|
|
|
|
t.Bold = bold;
|
|
|
|
t.Italic = italic;
|
|
|
|
t.Size = size;
|
|
|
|
t.StrikeOut = strikeout;
|
|
|
|
t.UnderLine = underline;
|
|
|
|
t.Name = CopyStr(name);
|
|
|
|
f = Search(font_list, &t);
|
|
|
|
Free(t.Name);
|
|
|
|
|
|
|
|
if (f != NULL)
|
|
|
|
{
|
|
|
|
// Font is found
|
|
|
|
UnlockList(font_list);
|
|
|
|
return f->hFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new font
|
|
|
|
hDC = CreateCompatibleDC(NULL);
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
font_quality = CLEARTYPE_NATURAL_QUALITY;
|
|
|
|
rotate = 3600;
|
|
|
|
dpi = GetDeviceCaps(hDC, LOGPIXELSY);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
// Create a font
|
|
|
|
hFont = CreateFontA(-MulDiv(size, dpi, 72),
|
|
|
|
0, rotate, rotate, (bold == false ? 500 : FW_BOLD),
|
|
|
|
italic, underline, strikeout, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
|
|
|
CLIP_DEFAULT_PRECIS, font_quality, DEFAULT_PITCH, name);
|
|
|
|
|
|
|
|
if (hFont == NULL)
|
|
|
|
{
|
|
|
|
// Failure
|
|
|
|
DeleteDC(hDC);
|
|
|
|
UnlockList(font_list);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CalcFontSize(hFont, &x, &y);
|
|
|
|
|
|
|
|
// Add to the table
|
|
|
|
f = ZeroMalloc(sizeof(FONT));
|
|
|
|
f->Bold = bold;
|
|
|
|
f->hFont = hFont;
|
|
|
|
f->Italic = italic;
|
|
|
|
f->Name = CopyStr(name);
|
|
|
|
f->Size = size;
|
|
|
|
f->StrikeOut = strikeout;
|
|
|
|
f->UnderLine = underline;
|
|
|
|
f->x = x;
|
|
|
|
f->y = y;
|
|
|
|
|
|
|
|
Insert(font_list, f);
|
|
|
|
|
|
|
|
DeleteDC(hDC);
|
|
|
|
}
|
|
|
|
UnlockList(font_list);
|
|
|
|
|
|
|
|
return hFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comparison of the font
|
|
|
|
int CompareFont(void *p1, void *p2)
|
|
|
|
{
|
|
|
|
FONT *f1, *f2;
|
|
|
|
UINT r;
|
|
|
|
if (p1 == NULL || p2 == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
f1 = *(FONT **)p1;
|
|
|
|
f2 = *(FONT **)p2;
|
|
|
|
if (f1 == NULL || f2 == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
r = StrCmpi(f1->Name, f2->Name);
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (f1->Bold > f2->Bold)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (f1->Bold < f2->Bold)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (f1->Italic > f2->Italic)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (f1->Italic < f2->Italic)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (f1->Size > f2->Size)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (f1->Size < f2->Size)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (f1->StrikeOut > f2->StrikeOut)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (f1->StrikeOut < f2->StrikeOut)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (f1->UnderLine > f2->UnderLine)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (f1->UnderLine < f2->UnderLine)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the font
|
|
|
|
void InitFont()
|
|
|
|
{
|
|
|
|
if (font_list != NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
font_list = NewList(CompareFont);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the font
|
|
|
|
void FreeFont()
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
if (font_list == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (i = 0;i < LIST_NUM(font_list);i++)
|
|
|
|
{
|
|
|
|
FONT *f = LIST_DATA(font_list, i);
|
|
|
|
Free(f->Name);
|
|
|
|
DeleteObject((HGDIOBJ)f->hFont);
|
|
|
|
Free(f);
|
|
|
|
}
|
|
|
|
ReleaseList(font_list);
|
|
|
|
font_list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show a button to close the window
|
|
|
|
void EnableClose(HWND hWnd)
|
|
|
|
{
|
|
|
|
HMENU h;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
h = GetSystemMenu(hWnd, false);
|
|
|
|
EnableMenuItem(h, SC_CLOSE, MF_ENABLED);
|
|
|
|
DrawMenuBar(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hide the button to close the window
|
|
|
|
void DisableClose(HWND hWnd)
|
|
|
|
{
|
|
|
|
HMENU h;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
h = GetSystemMenu(hWnd, false);
|
|
|
|
EnableMenuItem(h, SC_CLOSE, MF_GRAYED);
|
|
|
|
DrawMenuBar(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move to the center of the parent window
|
|
|
|
void CenterParent(HWND hWnd)
|
|
|
|
{
|
|
|
|
RECT rp;
|
|
|
|
RECT r;
|
|
|
|
HWND hWndParent = GetParent(hWnd);
|
|
|
|
int win_x, win_y;
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
if (hWndParent == NULL || IsHide(hWndParent, 0) || IsIconic(hWndParent))
|
|
|
|
{
|
|
|
|
Center(hWnd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetWindowRect(hWndParent, &rp) == false)
|
|
|
|
{
|
|
|
|
Center(hWnd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetWindowRect(hWnd, &r);
|
|
|
|
|
|
|
|
win_x = r.right - r.left;
|
|
|
|
win_y = r.bottom - r.top;
|
|
|
|
|
|
|
|
x = (rp.right - rp.left - win_x) / 2 + rp.left;
|
|
|
|
y = (rp.bottom - rp.top - win_y) / 2 + rp.top;
|
|
|
|
|
|
|
|
x = MAX(x, 0);
|
|
|
|
y = MAX(y, 0);
|
|
|
|
|
|
|
|
SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the window to the center
|
|
|
|
void Center(HWND hWnd)
|
|
|
|
{
|
|
|
|
RECT screen;
|
|
|
|
RECT win;
|
|
|
|
UINT x, y;
|
|
|
|
UINT win_x, win_y;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetWindowRect(hWnd, &win);
|
|
|
|
win_x = win.right - win.left;
|
|
|
|
win_y = win.bottom - win.top;
|
|
|
|
|
|
|
|
if (win_x < (UINT)(screen.right - screen.left))
|
|
|
|
{
|
|
|
|
x = (screen.right - screen.left - win_x) / 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (win_y < (UINT)(screen.bottom - screen.top))
|
|
|
|
{
|
|
|
|
y = (screen.bottom - screen.top - win_y) / 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format the string in the window
|
|
|
|
void FormatText(HWND hWnd, UINT id, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
wchar_t *buf;
|
|
|
|
UINT size;
|
|
|
|
wchar_t *str;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
str = GetText(hWnd, id);
|
|
|
|
if (str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = MAX(UniStrSize(str) * 10, MAX_SIZE * 10);
|
|
|
|
buf = MallocEx(size, true);
|
|
|
|
|
|
|
|
va_start(args, id);
|
|
|
|
UniFormatArgs(buf, size, str, args);
|
|
|
|
|
|
|
|
SetText(hWnd, id, buf);
|
|
|
|
|
|
|
|
Free(buf);
|
|
|
|
|
|
|
|
Free(str);
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the variable-length message box
|
|
|
|
UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
wchar_t *buf;
|
|
|
|
UINT size;
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (msg == NULL)
|
|
|
|
{
|
|
|
|
msg = L"MessageBox";
|
|
|
|
}
|
|
|
|
|
|
|
|
size = MAX(UniStrSize(msg) * 10, MAX_SIZE * 10);
|
|
|
|
buf = MallocEx(size, true);
|
|
|
|
|
|
|
|
va_start(args, msg);
|
|
|
|
UniFormatArgs(buf, size, msg, args);
|
|
|
|
|
|
|
|
ret = MsgBox(hWnd, flag, buf);
|
|
|
|
Free(buf);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the message box
|
|
|
|
UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
wchar_t *title;
|
|
|
|
// Validate arguments
|
|
|
|
if (msg == NULL)
|
|
|
|
{
|
|
|
|
msg = L"MessageBox";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (title_bar != NULL)
|
|
|
|
{
|
|
|
|
title = CopyUniStr(title_bar);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
title = CopyStrToUni(CEDAR_PRODUCT_STR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hWnd)
|
|
|
|
{
|
|
|
|
// Raise the message box to top-level if the parent window is the top-level window
|
|
|
|
if (GetExStyle(hWnd, 0) & WS_EX_TOPMOST)
|
|
|
|
{
|
|
|
|
flag |= MB_SYSTEMMODAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = MessageBoxW(hWnd, msg, title, flag);
|
|
|
|
|
|
|
|
Free(title);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a dialog (internal)
|
|
|
|
UINT DialogInternal(HWND hWnd, UINT id, DIALOG_PROC *proc, void *param)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (proc == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
return (UINT)DialogBoxParamW(hDll, MAKEINTRESOURCEW(id), hWnd, (DLGPROC)proc, (LPARAM)param);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Dialog box procedure managed by WinUi
|
|
|
|
UINT DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, bool white_color)
|
|
|
|
{
|
|
|
|
void *param;
|
|
|
|
HWND hWndParent;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
2015-03-27 14:52:15 +03:00
|
|
|
if (true)
|
|
|
|
{
|
|
|
|
RECT rect1;
|
|
|
|
|
|
|
|
SetRect(&rect1, 0, 0, 100, 100);
|
|
|
|
MapDialogRect(hWnd, &rect1);
|
|
|
|
Debug("%u %u %u %u\n", rect1.left, rect1.right, rect1.top, rect1.bottom);
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:00:08 +04:00
|
|
|
param = (void *)lParam;
|
|
|
|
SetParam(hWnd, param);
|
|
|
|
|
|
|
|
// Examine whether the parent window exists
|
|
|
|
hWndParent = GetParent(hWnd);
|
|
|
|
if (hWndParent == NULL || IsShow(hWndParent, 0) == false)
|
|
|
|
{
|
|
|
|
// Place in the center if parent does not exist
|
|
|
|
Center(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UseAlpha)
|
|
|
|
{
|
2021-04-03 03:25:19 +03:00
|
|
|
bool (WINAPI *_SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD);
|
|
|
|
HINSTANCE hInst;
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
hInst = LoadLibrary("user32.dll");
|
|
|
|
_SetLayeredWindowAttributes =
|
|
|
|
(bool (__stdcall *)(HWND,COLORREF,BYTE,DWORD))
|
|
|
|
GetProcAddress(hInst, "SetLayeredWindowAttributes");
|
2014-01-04 17:00:08 +04:00
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
if (_SetLayeredWindowAttributes != NULL)
|
|
|
|
{
|
|
|
|
// Only available on Windows 2000 or later
|
|
|
|
SetExStyle(hWnd, 0, WS_EX_LAYERED);
|
|
|
|
_SetLayeredWindowAttributes(hWnd, 0, AlphaValue * 255 / 100, LWA_ALPHA);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CTLCOLORBTN:
|
|
|
|
case WM_CTLCOLORDLG:
|
|
|
|
case WM_CTLCOLOREDIT:
|
|
|
|
case WM_CTLCOLORLISTBOX:
|
|
|
|
case WM_CTLCOLORMSGBOX:
|
|
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
|
|
if (white_color)
|
|
|
|
{
|
|
|
|
return (UINT)GetStockObject(WHITE_BRUSH);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the parameters of the dialog box
|
|
|
|
void SetParam(HWND hWnd, void *param)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)param);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the parameters of the dialog box
|
|
|
|
void *GetParam(HWND hWnd)
|
|
|
|
{
|
|
|
|
void *ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = (void *)GetWindowLongPtr(hWnd, DWLP_USER);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the windows as foreground
|
|
|
|
void Top(HWND hWnd)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hide the window
|
|
|
|
void Hide(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsShow(hWnd, id))
|
|
|
|
{
|
|
|
|
ShowWindow(DlgItem(hWnd, id), SW_HIDE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the window
|
|
|
|
void Show(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsHide(hWnd, id))
|
|
|
|
{
|
|
|
|
ShowWindow(DlgItem(hWnd, id), SW_SHOW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change the display settings
|
|
|
|
void SetShow(HWND hWnd, UINT id, bool b)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
Show(hWnd, id);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Hide(hWnd, id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get whether the window is shown
|
|
|
|
bool IsShow(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
return IsHide(hWnd, id) ? false : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get whether the window is hidden
|
|
|
|
bool IsHide(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetStyle(hWnd, id) & WS_VISIBLE)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the window style
|
|
|
|
void RemoveExStyle(HWND hWnd, UINT id, UINT style)
|
|
|
|
{
|
|
|
|
UINT old;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
old = GetExStyle(hWnd, id);
|
|
|
|
if ((old & style) == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old & ~style);
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the window style
|
|
|
|
void SetExStyle(HWND hWnd, UINT id, UINT style)
|
|
|
|
{
|
|
|
|
UINT old;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
old = GetExStyle(hWnd, id);
|
|
|
|
if (old & style)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old | style);
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the window style
|
|
|
|
UINT GetExStyle(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the window style
|
|
|
|
void RemoveStyle(HWND hWnd, UINT id, UINT style)
|
|
|
|
{
|
|
|
|
UINT old;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
old = GetStyle(hWnd, id);
|
|
|
|
if ((old & style) == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old & ~style);
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the window style
|
|
|
|
void SetStyle(HWND hWnd, UINT id, UINT style)
|
|
|
|
{
|
|
|
|
UINT old;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
old = GetStyle(hWnd, id);
|
|
|
|
if (old & style)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old | style);
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the window style
|
|
|
|
UINT GetStyle(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetWindowLong(DlgItem(hWnd, id), GWL_STYLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of characters in the text
|
|
|
|
UINT GetTextLen(HWND hWnd, UINT id, bool unicode)
|
|
|
|
{
|
|
|
|
wchar_t *s;
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetText(hWnd, id);
|
|
|
|
if (s == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unicode)
|
|
|
|
{
|
|
|
|
ret = UniStrLen(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *tmp = CopyUniToStr(s);
|
|
|
|
ret = StrLen(tmp);
|
|
|
|
Free(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(s);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the text is blank
|
|
|
|
bool IsEmpty(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
bool ret;
|
|
|
|
wchar_t *s;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetText(hWnd, id);
|
|
|
|
|
|
|
|
UniTrim(s);
|
|
|
|
if (UniStrLen(s) == 0)
|
|
|
|
{
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(s);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the window class
|
|
|
|
wchar_t *GetClass(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return CopyUniStr(L"");
|
|
|
|
}
|
|
|
|
|
|
|
|
GetClassNameW(DlgItem(hWnd, id), tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
return UniCopyStr(tmp);
|
|
|
|
}
|
|
|
|
char *GetClassA(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
char tmp[MAX_SIZE];
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return CopyStr("");
|
|
|
|
}
|
|
|
|
|
|
|
|
GetClassName(DlgItem(hWnd, id), tmp, sizeof(tmp));
|
|
|
|
|
|
|
|
return CopyStr(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transmit a message to the control
|
|
|
|
UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
return (UINT)SendMessageW(DlgItem(hWnd, id), msg, wParam, lParam);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Move the cursor to the right edge of the text in the EDIT
|
|
|
|
void SetCursorOnRight(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t *class_name;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
class_name = GetClass(hWnd, id);
|
|
|
|
|
|
|
|
if (class_name != NULL)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(class_name, L"edit") == 0)
|
|
|
|
{
|
|
|
|
wchar_t *str = GetText(hWnd, id);
|
|
|
|
|
|
|
|
if (str != NULL)
|
|
|
|
{
|
|
|
|
UINT len = UniStrLen(str);
|
|
|
|
|
|
|
|
SendMsg(hWnd, id, EM_SETSEL, len, len);
|
|
|
|
|
|
|
|
Free(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Free(class_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select entire the text in the EDIT
|
|
|
|
void SelectEdit(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t *class_name;
|
|
|
|
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
class_name = GetClass(hWnd, id);
|
|
|
|
|
|
|
|
if (class_name != NULL)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(class_name, L"edit") == 0)
|
|
|
|
{
|
|
|
|
SendMsg(hWnd, id, EM_SETSEL, 0, -1);
|
|
|
|
}
|
|
|
|
Free(class_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deselect the text of EDIT
|
|
|
|
void UnselectEdit(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t *class_name;
|
|
|
|
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
class_name = GetClass(hWnd, id);
|
|
|
|
|
|
|
|
if (class_name != NULL)
|
|
|
|
{
|
|
|
|
if (UniStrCmpi(class_name, L"edit") == 0)
|
|
|
|
{
|
|
|
|
SendMsg(hWnd, id, EM_SETSEL, -1, 0);
|
|
|
|
}
|
|
|
|
Free(class_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select all by setting the focus to the EDIT
|
|
|
|
void FocusEx(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectEdit(hWnd, id);
|
|
|
|
|
|
|
|
Focus(hWnd, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get whether the specified window has focus
|
|
|
|
bool IsFocus(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetFocus() == DlgItem(hWnd, id))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the focus
|
|
|
|
void Focus(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetFocus(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the value of the int type
|
|
|
|
void SetInt(HWND hWnd, UINT id, UINT value)
|
|
|
|
{
|
|
|
|
wchar_t tmp[MAX_SIZE];
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UniToStru(tmp, value);
|
|
|
|
SetText(hWnd, id, tmp);
|
|
|
|
}
|
|
|
|
void SetIntEx(HWND hWnd, UINT id, UINT value)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value == 0)
|
|
|
|
{
|
|
|
|
// Leave blank in the case of 0
|
|
|
|
SetText(hWnd, id, L"");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetInt(hWnd, id, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the value of the int type
|
|
|
|
UINT GetInt(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t *s;
|
|
|
|
UINT ret;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetText(hWnd, id);
|
|
|
|
if (s == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = UniToInt(s);
|
|
|
|
Free(s);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the window appearance
|
|
|
|
void Refresh(HWND hWnd)
|
|
|
|
{
|
|
|
|
HWND parent;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DoEvents(hWnd);
|
|
|
|
UpdateWindow(hWnd);
|
|
|
|
DoEvents(hWnd);
|
|
|
|
|
|
|
|
parent = GetParent(hWnd);
|
|
|
|
if (parent != NULL)
|
|
|
|
{
|
|
|
|
Refresh(parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle the event
|
|
|
|
void DoEvents(HWND hWnd)
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
|
|
|
|
if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
|
|
|
|
{
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessage(&msg);
|
|
|
|
}
|
|
|
|
UpdateWindow(hWnd);
|
|
|
|
|
|
|
|
if (hWnd)
|
|
|
|
{
|
|
|
|
DoEvents(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the window
|
|
|
|
void Close(HWND hWnd)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMessage(hWnd, WM_CLOSE, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable the window
|
|
|
|
void Disable(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
SetEnable(hWnd, id, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable the window
|
|
|
|
void Enable(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
SetEnable(hWnd, id, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the enabled state of a window
|
|
|
|
void SetEnable(HWND hWnd, UINT id, bool b)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b == false)
|
|
|
|
{
|
|
|
|
if (IsEnable(hWnd, id))
|
|
|
|
{
|
|
|
|
if (id != 0 && IsFocus(hWnd, id))
|
|
|
|
{
|
|
|
|
Focus(hWnd, IDCANCEL);
|
|
|
|
Focus(hWnd, IDOK);
|
|
|
|
}
|
|
|
|
EnableWindow(DlgItem(hWnd, id), false);
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (IsDisable(hWnd, id))
|
|
|
|
{
|
|
|
|
EnableWindow(DlgItem(hWnd, id), true);
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examine whether the window is disabled
|
|
|
|
bool IsDisable(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
return IsEnable(hWnd, id) ? false : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examine whether the window is enabled
|
|
|
|
bool IsEnable(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsWindowEnabled(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the control protrude by large font size, adjust into appropriate size
|
|
|
|
void AdjustFontSize(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
char class_name[MAX_PATH];
|
|
|
|
UINT style;
|
|
|
|
UINT format = 0;
|
|
|
|
HFONT current_font;
|
|
|
|
FONT font;
|
|
|
|
wchar_t *text;
|
|
|
|
RECT rect;
|
|
|
|
UINT width, height;
|
|
|
|
HFONT new_font = NULL;
|
|
|
|
UINT old_font_size;
|
|
|
|
UINT style1;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hWnd = DlgItem(hWnd, id);
|
|
|
|
|
|
|
|
if (GetClassNameA(hWnd, class_name, sizeof(class_name)) == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StrCmpi(class_name, "static") != 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
style = GetStyle(hWnd, 0);
|
|
|
|
|
|
|
|
if ((style & SS_ENDELLIPSIS) || (style & SS_PATHELLIPSIS))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
style1 = style & 0x0F;
|
|
|
|
|
|
|
|
// Create a format for DrawText
|
|
|
|
if (style1 == SS_RIGHT)
|
|
|
|
{
|
|
|
|
// Right justification
|
|
|
|
format |= DT_RIGHT;
|
|
|
|
}
|
|
|
|
else if (style1 == SS_CENTER)
|
|
|
|
{
|
|
|
|
// Center justification
|
|
|
|
format |= DT_CENTER;
|
|
|
|
}
|
|
|
|
else if (style1 == SS_LEFT)
|
|
|
|
{
|
|
|
|
// Left justification
|
|
|
|
format |= DT_LEFT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Others
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (style & DT_NOPREFIX)
|
|
|
|
{
|
|
|
|
// Without prefix
|
|
|
|
format |= DT_NOPREFIX;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the font parameters currently set
|
|
|
|
current_font = (HFONT)SendMessageA(hWnd, WM_GETFONT, 0, 0);
|
|
|
|
if (current_font == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zero(&font, sizeof(font));
|
|
|
|
if (GetFontParam(current_font, &font) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the size of the static area
|
|
|
|
Zero(&rect, sizeof(rect));
|
|
|
|
if (GetWindowRect(hWnd, &rect) == false)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the text that is currently set
|
|
|
|
text = GetText(hWnd, 0);
|
|
|
|
if (text == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsEmptyUniStr(text))
|
|
|
|
{
|
|
|
|
Free(text);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
width = GET_ABS(rect.right - rect.left);
|
|
|
|
height = GET_ABS(rect.bottom - rect.top);
|
|
|
|
|
|
|
|
new_font = NULL;
|
|
|
|
old_font_size = font.Size;
|
|
|
|
|
|
|
|
// Try to gradually reduce the font size until drawing succeeds
|
|
|
|
while (font.Size != 0)
|
|
|
|
{
|
|
|
|
// Drawing test
|
|
|
|
bool aborted = false;
|
|
|
|
|
|
|
|
if (IsFontFitInRect(&font, width, height, text, format, &aborted))
|
|
|
|
{
|
|
|
|
// Drawing success
|
|
|
|
if (old_font_size != font.Size)
|
|
|
|
{
|
|
|
|
// Font size is changed
|
|
|
|
new_font = GetFont(font.Name, font.Size, font.Bold, font.Italic, font.UnderLine, font.StrikeOut);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (aborted)
|
|
|
|
{
|
|
|
|
// Fatal error
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
font.Size--;
|
|
|
|
|
|
|
|
if (font.Size == 1)
|
|
|
|
{
|
|
|
|
// Not supposed to become a font size like this. Fatal error
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(text);
|
|
|
|
|
|
|
|
if (new_font != NULL)
|
|
|
|
{
|
|
|
|
// Change the font size
|
|
|
|
SetFontEx(hWnd, 0, new_font, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the specified string can be drawn in the specified area with the specified font
|
|
|
|
bool IsFontFitInRect(struct FONT *f, UINT width, UINT height, wchar_t *text, UINT format, bool *aborted)
|
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
int i;
|
|
|
|
bool dummy_bool;
|
|
|
|
UINT new_height;
|
|
|
|
HFONT hCreatedFont, hOldFont;
|
|
|
|
// Validate arguments
|
|
|
|
if (f == NULL || text == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (aborted == NULL)
|
|
|
|
{
|
|
|
|
aborted = &dummy_bool;
|
|
|
|
}
|
|
|
|
|
|
|
|
format |= DT_CALCRECT | DT_WORDBREAK;
|
|
|
|
|
|
|
|
*aborted = false;
|
|
|
|
|
|
|
|
// Create a font
|
|
|
|
hCreatedFont = GetFont(f->Name, f->Size, f->Bold, f->Italic, f->UnderLine, f->StrikeOut);
|
|
|
|
if (hCreatedFont == NULL)
|
|
|
|
{
|
|
|
|
*aborted = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Lock(lock_common_dc);
|
|
|
|
{
|
|
|
|
hOldFont = SelectObject(hCommonDC, hCreatedFont);
|
|
|
|
|
|
|
|
Zero(&r, sizeof(r));
|
|
|
|
r.left = r.top = 0;
|
|
|
|
r.right = width;
|
|
|
|
r.bottom = height;
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
i = DrawTextW(hCommonDC, text, -1, &r, format);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
SelectObject(hCommonDC, hOldFont);
|
|
|
|
}
|
|
|
|
Unlock(lock_common_dc);
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
*aborted = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_height = GET_ABS(r.bottom - r.top);
|
|
|
|
|
|
|
|
if (new_height > height)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set a text string
|
|
|
|
void SetText(HWND hWnd, UINT id, wchar_t *str)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetTextInner(hWnd, id, str);
|
|
|
|
}
|
|
|
|
void SetTextInner(HWND hWnd, UINT id, wchar_t *str)
|
|
|
|
{
|
|
|
|
wchar_t *old;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the old string
|
|
|
|
old = GetText(hWnd, id);
|
|
|
|
if (UniStrCmp(str, old) == 0)
|
|
|
|
{
|
|
|
|
// Identity
|
|
|
|
Free(old);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Free(old);
|
|
|
|
|
2021-04-03 03:25:19 +03:00
|
|
|
SetWindowTextW(DlgItem(hWnd, id), str);
|
2014-01-04 17:00:08 +04:00
|
|
|
|
|
|
|
AdjustFontSize(hWnd, id);
|
|
|
|
|
|
|
|
if (id != 0)
|
|
|
|
{
|
|
|
|
Refresh(DlgItem(hWnd, id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void SetTextA(HWND hWnd, UINT id, char *str)
|
|
|
|
{
|
|
|
|
wchar_t *s;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = CopyStrToUni(str);
|
|
|
|
if (s == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetText(hWnd, id, s);
|
|
|
|
|
|
|
|
Free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the text string to the buffer
|
|
|
|
bool GetTxt(HWND hWnd, UINT id, wchar_t *str, UINT size)
|
|
|
|
{
|
|
|
|
wchar_t *s;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetText(hWnd, id);
|
|
|
|
if (s == NULL)
|
|
|
|
{
|
|
|
|
UniStrCpy(str, size, L"");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
UniStrCpy(str, size, s);
|
|
|
|
Free(s);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool GetTxtA(HWND hWnd, UINT id, char *str, UINT size)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL || str == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = GetTextA(hWnd, id);
|
|
|
|
if (s == NULL)
|
|
|
|
{
|
|
|
|
StrCpy(str, size, "");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
StrCpy(str, size, s);
|
|
|
|
Free(s);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the text string
|
|
|
|
wchar_t *GetText(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
wchar_t *ret;
|
|
|
|
UINT size, len;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = GetWindowTextLengthW(DlgItem(hWnd, id));
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
return CopyUniStr(L"");
|
|
|
|
}
|
|
|
|
|
|
|
|
size = (len + 1) * 2;
|
|
|
|
ret = ZeroMallocEx(size, true);
|
|
|
|
|
|
|
|
GetWindowTextW(DlgItem(hWnd, id), ret, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
char *GetTextA(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
char *ret;
|
|
|
|
UINT size, len;
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = GetWindowTextLengthA(DlgItem(hWnd, id));
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
return CopyStr("");
|
|
|
|
}
|
|
|
|
|
|
|
|
size = len + 1;
|
|
|
|
ret = ZeroMallocEx(size, true);
|
|
|
|
|
|
|
|
GetWindowTextA(DlgItem(hWnd, id), ret, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the item in the dialog
|
|
|
|
HWND DlgItem(HWND hWnd, UINT id)
|
|
|
|
{
|
|
|
|
// Validate arguments
|
|
|
|
if (hWnd == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == 0)
|
|
|
|
{
|
|
|
|
return hWnd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return GetDlgItem(hWnd, id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the WinUi
|
|
|
|
void InitWinUi(wchar_t *software_name, char *font, UINT fontsize)
|
|
|
|
{
|
|
|
|
if (tls_current_wizard == 0xffffffff)
|
|
|
|
{
|
|
|
|
tls_current_wizard = TlsAlloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((init_winui_counter++) != 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hDll != NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MayaquaIsMinimalMode() == false)
|
|
|
|
{
|
|
|
|
if (Is64())
|
|
|
|
{
|
2020-07-27 08:25:00 +03:00
|
|
|
hDll = MsLoadLibraryAsDataFile(PENCORE_DLL_NAME);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-27 08:25:00 +03:00
|
|
|
hDll = MsLoadLibrary(PENCORE_DLL_NAME);
|
2014-01-04 17:00:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (hDll == NULL)
|
|
|
|
{
|
|
|
|
Alert(PENCORE_DLL_NAME " not found. "CEDAR_PRODUCT_STR " VPN couldn't start.\r\n\r\n"
|
|
|
|
"Please reinstall all files with "CEDAR_PRODUCT_STR " VPN Installer.",
|
|
|
|
NULL);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hDll = LoadLibrary(MsGetExeFileName());
|
|
|
|
|
|
|
|
if (hDll == NULL)
|
|
|
|
{
|
|
|
|
Alert("MsLoadLibrary() Error.",
|
|
|
|
NULL);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (software_name != NULL)
|
|
|
|
{
|
|
|
|
title_bar = CopyUniStr(software_name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
title_bar = CopyUniStr(CEDAR_PRODUCT_STR_W L" VPN");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (font != NULL)
|
|
|
|
{
|
|
|
|
font_name = CopyStr(font);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
font_name = CopyStr(_SS("DEFAULT_FONT"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MsIsWindows7())
|
|
|
|
{
|
|
|
|
char *win7_font = _SS("DEFAULT_FONT_WIN7");
|
|
|
|
|
|
|
|
if (IsEmptyStr(win7_font) == false)
|
|
|
|
{
|
|
|
|
Free(font_name);
|
|
|
|
font_name = CopyStr(win7_font);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetTextScalingFactor() >= 1.44)
|
|
|
|
{
|
|
|
|
// Use a substitute font in the case of high-DPI in Windows 7 and later
|
|
|
|
char *alternative_font = _SS("DEFAULT_FONT_HIGHDPI");
|
|
|
|
|
|
|
|
if (IsEmptyStr(alternative_font) == false)
|
|
|
|
{
|
|
|
|
Free(font_name);
|
|
|
|
font_name = CopyStr(alternative_font);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fontsize != 0)
|
|
|
|
{
|
|
|
|
font_size = fontsize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
font_size = _II("DEFAULT_FONT_SIZE");
|
|
|
|
if (font_size == 0)
|
|
|
|
{
|
|
|
|
font_size = 9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lock_common_dc = NewLock();
|
|
|
|
|
|
|
|
hCommonDC = CreateCompatibleDC(NULL);
|
|
|
|
|
|
|
|
InitIconCache();
|
|
|
|
|
|
|
|
InitFont();
|
|
|
|
|
|
|
|
InitImageList();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the WinUi
|
|
|
|
void FreeWinUi()
|
|
|
|
{
|
|
|
|
if ((--init_winui_counter) != 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hDll == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeImageList();
|
|
|
|
|
|
|
|
FreeFont();
|
|
|
|
|
|
|
|
FreeIconCache();
|
|
|
|
|
|
|
|
FreeLibrary(hDll);
|
|
|
|
hDll = NULL;
|
|
|
|
|
|
|
|
Free(title_bar);
|
|
|
|
title_bar = NULL;
|
|
|
|
|
|
|
|
Free(font_name);
|
|
|
|
font_name = NULL;
|
|
|
|
|
|
|
|
if (hCommonDC != NULL)
|
|
|
|
{
|
|
|
|
DeleteDC(hCommonDC);
|
|
|
|
hCommonDC = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteLock(lock_common_dc);
|
|
|
|
lock_common_dc = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // WIN32
|