Reformat source code with uncrustify

Closes: #445

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
pull/643/head
Frank Lichtenheld 1 year ago
parent f2aad3a879
commit 2cb3c6e417

@ -44,7 +44,9 @@ extern options_t o;
#define MAX_UNAME_LEN (UNLEN + DNLEN + 2) /* UNLEN, DNLEN from lmcons.h +2 for '\' and NULL */ #define MAX_UNAME_LEN (UNLEN + DNLEN + 2) /* UNLEN, DNLEN from lmcons.h +2 for '\' and NULL */
static BOOL GetOwnerSID(PSID sid, DWORD sid_size); static BOOL GetOwnerSID(PSID sid, DWORD sid_size);
static BOOL IsUserInGroup(PSID sid, PTOKEN_GROUPS token_groups, const WCHAR *group_name); static BOOL IsUserInGroup(PSID sid, PTOKEN_GROUPS token_groups, const WCHAR *group_name);
static PTOKEN_GROUPS GetProcessTokenGroups(void); static PTOKEN_GROUPS GetProcessTokenGroups(void);
/* /*
@ -52,7 +54,7 @@ static PTOKEN_GROUPS GetProcessTokenGroups(void);
* Get the local name of the group using the SID. * Get the local name of the group using the SID.
*/ */
static BOOL static BOOL
GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen) GetBuiltinAdminGroupName(WCHAR *name, DWORD nlen)
{ {
BOOL b = FALSE; BOOL b = FALSE;
PSID admin_sid = NULL; PSID admin_sid = NULL;
@ -64,19 +66,21 @@ GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen)
admin_sid = malloc(sid_size); admin_sid = malloc(sid_size);
if (!admin_sid) if (!admin_sid)
{
return FALSE; return FALSE;
}
b = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, b = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid,
&sid_size); &sid_size);
if(b) if (b)
{ {
b = LookupAccountSidW(NULL, admin_sid, name, &nlen, domain, &dlen, &su); b = LookupAccountSidW(NULL, admin_sid, name, &nlen, domain, &dlen, &su);
} }
#ifdef DEBUG #ifdef DEBUG
PrintDebug (L"builtin admin group name = %ls", name); PrintDebug(L"builtin admin group name = %ls", name);
#endif #endif
free (admin_sid); free(admin_sid);
return b; return b;
} }
@ -86,7 +90,7 @@ GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen)
* Reject if the group name contains certain illegal characters. * Reject if the group name contains certain illegal characters.
*/ */
static BOOL static BOOL
AddUserToGroup (const WCHAR *group) AddUserToGroup(const WCHAR *group)
{ {
WCHAR username[MAX_UNAME_LEN]; WCHAR username[MAX_UNAME_LEN];
WCHAR cmd[MAX_PATH] = L"C:\\windows\\system32\\cmd.exe"; WCHAR cmd[MAX_PATH] = L"C:\\windows\\system32\\cmd.exe";
@ -109,17 +113,19 @@ AddUserToGroup (const WCHAR *group)
if (wcspbrk(group, reject) != NULL) if (wcspbrk(group, reject) != NULL)
{ {
#ifdef DEBUG #ifdef DEBUG
PrintDebug (L"AddUSerToGroup: illegal characters in group name: '%ls'.", group); PrintDebug(L"AddUSerToGroup: illegal characters in group name: '%ls'.", group);
#endif #endif
return retval; return retval;
} }
size = _countof(username); size = _countof(username);
if (!GetUserNameExW (NameSamCompatible, username, &size)) if (!GetUserNameExW(NameSamCompatible, username, &size))
{
return retval; return retval;
}
size = _countof(syspath); size = _countof(syspath);
if (GetSystemDirectory (syspath, size)) if (GetSystemDirectory(syspath, size))
{ {
syspath[size-1] = L'\0'; syspath[size-1] = L'\0';
size = _countof(cmd); size = _countof(cmd);
@ -130,26 +136,34 @@ AddUserToGroup (const WCHAR *group)
netcmd[size-1] = L'\0'; netcmd[size-1] = L'\0';
} }
size = (wcslen(fmt) + wcslen(username) + 2*wcslen(group) + 2*wcslen(netcmd)+ 1); size = (wcslen(fmt) + wcslen(username) + 2*wcslen(group) + 2*wcslen(netcmd)+ 1);
if ((params = malloc (size*sizeof(WCHAR))) == NULL) if ((params = malloc(size*sizeof(WCHAR))) == NULL)
{
return retval; return retval;
}
_snwprintf(params, size, fmt, netcmd, group, netcmd, group, username); _snwprintf(params, size, fmt, netcmd, group, netcmd, group, username);
params[size-1] = L'\0'; params[size-1] = L'\0';
status = RunAsAdmin (cmd, params); status = RunAsAdmin(cmd, params);
if (status == 0) if (status == 0)
{
retval = TRUE; retval = TRUE;
}
#ifdef DEBUG #ifdef DEBUG
if (status == (DWORD) -1) if (status == (DWORD) -1)
{
PrintDebug(L"RunAsAdmin: failed to execute the command [%ls %ls] : error = 0x%x", PrintDebug(L"RunAsAdmin: failed to execute the command [%ls %ls] : error = 0x%x",
cmd, params, GetLastError()); cmd, params, GetLastError());
}
else if (status) else if (status)
{
PrintDebug(L"RunAsAdmin: command [%ls %ls] returned exit_code = %lu", PrintDebug(L"RunAsAdmin: command [%ls %ls] returned exit_code = %lu",
cmd, params, status); cmd, params, status);
}
#endif #endif
free (params); free(params);
return retval; return retval;
} }
@ -158,18 +172,22 @@ AddUserToGroup (const WCHAR *group)
* interactive service. * interactive service.
*/ */
static BOOL static BOOL
CheckConfigPath (const WCHAR *config_dir) CheckConfigPath(const WCHAR *config_dir)
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
int size = wcslen(o.global_config_dir); int size = wcslen(o.global_config_dir);
/* if interactive service is not running, no access control: return TRUE */ /* if interactive service is not running, no access control: return TRUE */
if (!CheckIServiceStatus(FALSE)) if (!CheckIServiceStatus(FALSE))
{
ret = TRUE; ret = TRUE;
}
/* if config is from the global location allow it */ /* if config is from the global location allow it */
else if (wcsncmp(config_dir, o.global_config_dir, size) == 0 else if (wcsncmp(config_dir, o.global_config_dir, size) == 0
&& wcsstr(config_dir + size, L"..") == NULL) && wcsstr(config_dir + size, L"..") == NULL)
{
ret = TRUE; ret = TRUE;
}
return ret; return ret;
} }
@ -192,19 +210,27 @@ AuthorizeConfig(const connection_t *c)
PTOKEN_GROUPS groups = NULL; PTOKEN_GROUPS groups = NULL;
if (GetBuiltinAdminGroupName(sysadmin_group, _countof(sysadmin_group))) if (GetBuiltinAdminGroupName(sysadmin_group, _countof(sysadmin_group)))
{
admin_group = sysadmin_group; admin_group = sysadmin_group;
}
else else
{
admin_group = L"Administrators"; admin_group = L"Administrators";
}
PrintDebug(L"Authorized groups: '%ls', '%ls'", admin_group, o.ovpn_admin_group); PrintDebug(L"Authorized groups: '%ls', '%ls'", admin_group, o.ovpn_admin_group);
if (CheckConfigPath(c->config_dir)) if (CheckConfigPath(c->config_dir))
{
return TRUE; return TRUE;
}
if (!GetOwnerSID(sid, sid_size)) if (!GetOwnerSID(sid, sid_size))
{ {
if (!o.silent_connection) if (!o.silent_connection)
{
MessageBoxW(NULL, L"Failed to determine process owner SID", L""PACKAGE_NAME, MB_OK); MessageBoxW(NULL, L"Failed to determine process owner SID", L""PACKAGE_NAME, MB_OK);
}
return FALSE; return FALSE;
} }
groups = GetProcessTokenGroups(); groups = GetProcessTokenGroups();
@ -225,7 +251,7 @@ AuthorizeConfig(const connection_t *c)
return FALSE; return FALSE;
} }
if (WaitForSingleObject (o.netcmd_semaphore, 0) != WAIT_OBJECT_0) if (WaitForSingleObject(o.netcmd_semaphore, 0) != WAIT_OBJECT_0)
{ {
/* Could not lock semaphore -- auth dialog already running? */ /* Could not lock semaphore -- auth dialog already running? */
ShowLocalizedMsg(IDS_NFO_CONFIG_AUTH_PENDING, c->config_name, o.ovpn_admin_group); ShowLocalizedMsg(IDS_NFO_CONFIG_AUTH_PENDING, c->config_name, o.ovpn_admin_group);
@ -237,17 +263,21 @@ AuthorizeConfig(const connection_t *c)
o.ovpn_admin_group); o.ovpn_admin_group);
if (res == IDYES) if (res == IDYES)
{ {
AddUserToGroup (o.ovpn_admin_group); AddUserToGroup(o.ovpn_admin_group);
/* /*
* Check the success of above by testing the group membership again * Check the success of above by testing the group membership again
*/ */
if (IsUserInGroup(sid, NULL, o.ovpn_admin_group)) if (IsUserInGroup(sid, NULL, o.ovpn_admin_group))
{
retval = TRUE; retval = TRUE;
}
else else
{
ShowLocalizedMsg(IDS_ERR_ADD_USER_TO_ADMIN_GROUP, o.ovpn_admin_group); ShowLocalizedMsg(IDS_ERR_ADD_USER_TO_ADMIN_GROUP, o.ovpn_admin_group);
SetForegroundWindow (o.hWnd); }
SetForegroundWindow(o.hWnd);
} }
ReleaseSemaphore (o.netcmd_semaphore, 1, NULL); ReleaseSemaphore(o.netcmd_semaphore, 1, NULL);
return retval; return retval;
} }
@ -287,7 +317,9 @@ GetProcessTokenGroups(void)
DWORD buf_size = 0; DWORD buf_size = 0;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
{
return NULL; return NULL;
}
if (!GetTokenInformation(token, TokenGroups, NULL, 0, &buf_size) if (!GetTokenInformation(token, TokenGroups, NULL, 0, &buf_size)
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{ {
@ -301,7 +333,7 @@ GetProcessTokenGroups(void)
if (!GetTokenInformation(token, TokenGroups, groups, buf_size, &buf_size)) if (!GetTokenInformation(token, TokenGroups, groups, buf_size, &buf_size))
{ {
PrintDebug(L"Failed to get Token Group Information: error = %lu", GetLastError); PrintDebug(L"Failed to get Token Group Information: error = %lu", GetLastError);
free (groups); free(groups);
groups = NULL; groups = NULL;
} }
@ -345,7 +377,9 @@ IsUserInGroup(PSID sid, const PTOKEN_GROUPS token_groups, const WCHAR *group_nam
} }
if (!sid) if (!sid)
{
return FALSE; return FALSE;
}
do do
{ {
@ -354,7 +388,9 @@ IsUserInGroup(PSID sid, const PTOKEN_GROUPS token_groups, const WCHAR *group_nam
err = NetLocalGroupGetMembers(NULL, group_name, 0, (LPBYTE *) &members, err = NetLocalGroupGetMembers(NULL, group_name, 0, (LPBYTE *) &members,
MAX_PREFERRED_LENGTH, &nread, &nmax, &resume); MAX_PREFERRED_LENGTH, &nread, &nmax, &resume);
if (err != NERR_Success && err != ERROR_MORE_DATA) if (err != NERR_Success && err != ERROR_MORE_DATA)
{
break; break;
}
/* If a match is already found, ret = TRUE, the loop is skipped */ /* If a match is already found, ret = TRUE, the loop is skipped */
for (DWORD i = 0; i < nread && !ret; ++i) for (DWORD i = 0; i < nread && !ret; ++i)
@ -362,13 +398,17 @@ IsUserInGroup(PSID sid, const PTOKEN_GROUPS token_groups, const WCHAR *group_nam
ret = EqualSid(members[i].lgrmi0_sid, sid); ret = EqualSid(members[i].lgrmi0_sid, sid);
} }
NetApiBufferFree(members); NetApiBufferFree(members);
/* MSDN says the lookup should always iterate until err != ERROR_MORE_DATA */ /* MSDN says the lookup should always iterate until err != ERROR_MORE_DATA */
} while (err == ERROR_MORE_DATA && nloop++ < 100); } while (err == ERROR_MORE_DATA && nloop++ < 100);
if (err != NERR_Success && err != NERR_GroupNotFound) if (err != NERR_Success && err != NERR_GroupNotFound)
{
PrintDebug(L"NetLocalGroupGetMembers for group '%ls' failed: error = %lu", group_name, err); PrintDebug(L"NetLocalGroupGetMembers for group '%ls' failed: error = %lu", group_name, err);
}
if (ret) if (ret)
{
PrintDebug(L"User is in group '%ls'", group_name); PrintDebug(L"User is in group '%ls'", group_name);
}
return ret; return ret;
} }

@ -24,6 +24,6 @@
#include "options.h" #include "options.h"
BOOL AuthorizeConfig (const connection_t *c); BOOL AuthorizeConfig(const connection_t *c);
#endif #endif

389
as.c

@ -44,7 +44,8 @@ void
SanitizeFilename(wchar_t *fname) SanitizeFilename(wchar_t *fname)
{ {
const wchar_t *reserved = L"<>:\"/\\|?*;"; /* remap these and ascii 1 to 31 */ const wchar_t *reserved = L"<>:\"/\\|?*;"; /* remap these and ascii 1 to 31 */
while (*fname) { while (*fname)
{
wchar_t c = *fname; wchar_t c = *fname;
if (c < 32 || wcschr(reserved, c)) if (c < 32 || wcschr(reserved, c))
{ {
@ -80,12 +81,15 @@ ExtractProfileName(const WCHAR *profile, const WCHAR *default_name, WCHAR *out_n
WCHAR *ctx = NULL; WCHAR *ctx = NULL;
pch = wcstok_s(buf, L"\r\n", &ctx); pch = wcstok_s(buf, L"\r\n", &ctx);
while (pch != NULL) { while (pch != NULL)
if (wcsbegins(pch, PROFILE_NAME_TOKEN)) { {
if (wcsbegins(pch, PROFILE_NAME_TOKEN))
{
wcsncpy(profile_name, pch + wcslen(PROFILE_NAME_TOKEN), PROFILE_NAME_LEN - 1); wcsncpy(profile_name, pch + wcslen(PROFILE_NAME_TOKEN), PROFILE_NAME_LEN - 1);
profile_name[PROFILE_NAME_LEN - 1] = L'\0'; profile_name[PROFILE_NAME_LEN - 1] = L'\0';
} }
else if (wcsbegins(pch, FRIENDLY_NAME_TOKEN)) { else if (wcsbegins(pch, FRIENDLY_NAME_TOKEN))
{
wcsncpy(friendly_name, pch + wcslen(FRIENDLY_NAME_TOKEN), PROFILE_NAME_LEN - 1); wcsncpy(friendly_name, pch + wcslen(FRIENDLY_NAME_TOKEN), PROFILE_NAME_LEN - 1);
friendly_name[PROFILE_NAME_LEN - 1] = L'\0'; friendly_name[PROFILE_NAME_LEN - 1] = L'\0';
} }
@ -96,11 +100,17 @@ ExtractProfileName(const WCHAR *profile, const WCHAR *default_name, WCHAR *out_n
/* we use .ovpn here, but extension could be customized */ /* we use .ovpn here, but extension could be customized */
/* actual extension will be applied during import */ /* actual extension will be applied during import */
if (wcslen(friendly_name) > 0) if (wcslen(friendly_name) > 0)
{
swprintf(out_name, out_name_length, L"%ls.ovpn", friendly_name); swprintf(out_name, out_name_length, L"%ls.ovpn", friendly_name);
}
else if (wcslen(profile_name) > 0) else if (wcslen(profile_name) > 0)
{
swprintf(out_name, out_name_length, L"%ls.ovpn", profile_name); swprintf(out_name, out_name_length, L"%ls.ovpn", profile_name);
}
else else
{
swprintf(out_name, out_name_length, L"%ls.ovpn", default_name); swprintf(out_name, out_name_length, L"%ls.ovpn", default_name);
}
out_name[out_name_length - 1] = L'\0'; out_name[out_name_length - 1] = L'\0';
@ -114,7 +124,7 @@ ShowWinInetError(HANDLE hWnd)
{ {
WCHAR err[256] = { 0 }; WCHAR err[256] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM, GetModuleHandleW(L"wininet.dll"), FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM, GetModuleHandleW(L"wininet.dll"),
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, _countof(err), NULL); GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, _countof(err), NULL);
ShowLocalizedMsgEx(MB_OK, hWnd, _T(PACKAGE_NAME), IDS_ERR_URL_IMPORT_PROFILE, GetLastError(), err); ShowLocalizedMsgEx(MB_OK, hWnd, _T(PACKAGE_NAME), IDS_ERR_URL_IMPORT_PROFILE, GetLastError(), err);
} }
@ -128,26 +138,30 @@ struct UrlComponents
}; };
/** /**
* Extracts protocol, port and hostname from URL * Extracts protocol, port and hostname from URL
* *
* @param url URL to parse, length must be less than URL_MAX * @param url URL to parse, length must be less than URL_MAX
*/ */
void void
ParseUrl(const WCHAR *url, struct UrlComponents* comps) ParseUrl(const WCHAR *url, struct UrlComponents *comps)
{ {
ZeroMemory(comps, sizeof(struct UrlComponents)); ZeroMemory(comps, sizeof(struct UrlComponents));
comps->port = 443; comps->port = 443;
comps->https = true; comps->https = true;
if (wcsbegins(url, L"http://")) { if (wcsbegins(url, L"http://"))
{
url += 7; url += 7;
} else if (wcsbegins(url, L"https://")) { }
url +=8; else if (wcsbegins(url, L"https://"))
{
url += 8;
} }
WCHAR *strport = wcsstr(url, L":"); WCHAR *strport = wcsstr(url, L":");
WCHAR *pathptr = wcsstr(url, L"/"); WCHAR *pathptr = wcsstr(url, L"/");
if (strport) { if (strport)
{
wcsncpy_s(comps->host, URL_LEN, url, strport - url); wcsncpy_s(comps->host, URL_LEN, url, strport - url);
comps->port = wcstol(strport + 1, NULL, 10); comps->port = wcstol(strport + 1, NULL, 10);
} }
@ -175,35 +189,41 @@ ParseUrl(const WCHAR *url, struct UrlComponents* comps)
* @param psize pointer to a profile size, assigned by this function * @param psize pointer to a profile size, assigned by this function
*/ */
BOOL BOOL
DownloadProfileContent(HANDLE hWnd, HINTERNET hRequest, char** pbuf, size_t* psize) DownloadProfileContent(HANDLE hWnd, HINTERNET hRequest, char **pbuf, size_t *psize)
{ {
size_t pos = 0; size_t pos = 0;
size_t size = READ_CHUNK_LEN; size_t size = READ_CHUNK_LEN;
*pbuf = calloc(1, size + 1); *pbuf = calloc(1, size + 1);
char* buf = *pbuf; char *buf = *pbuf;
if (buf == NULL) { if (buf == NULL)
{
MessageBoxW(hWnd, L"Out of memory", _T(PACKAGE_NAME), MB_OK); MessageBoxW(hWnd, L"Out of memory", _T(PACKAGE_NAME), MB_OK);
return FALSE; return FALSE;
} }
while (true) { while (true)
{
DWORD bytesRead = 0; DWORD bytesRead = 0;
if (!InternetReadFile(hRequest, buf + pos, READ_CHUNK_LEN, &bytesRead)) { if (!InternetReadFile(hRequest, buf + pos, READ_CHUNK_LEN, &bytesRead))
{
ShowWinInetError(hWnd); ShowWinInetError(hWnd);
return FALSE; return FALSE;
} }
buf[pos + bytesRead] = '\0'; buf[pos + bytesRead] = '\0';
if (bytesRead == 0) { if (bytesRead == 0)
{
size = pos; size = pos;
break; break;
} }
if (pos + bytesRead >= size) { if (pos + bytesRead >= size)
{
size += READ_CHUNK_LEN; size += READ_CHUNK_LEN;
*pbuf = realloc(*pbuf, size + 1); *pbuf = realloc(*pbuf, size + 1);
if (!*pbuf) { if (!*pbuf)
{
free(buf); free(buf);
MessageBoxW(hWnd, L"Out of memory", _T(PACKAGE_NAME), MB_OK); MessageBoxW(hWnd, L"Out of memory", _T(PACKAGE_NAME), MB_OK);
return FALSE; return FALSE;
@ -225,15 +245,17 @@ DownloadProfileContent(HANDLE hWnd, HINTERNET hRequest, char** pbuf, size_t* psi
INT_PTR CALLBACK INT_PTR CALLBACK
CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
auth_param_t * param = NULL; auth_param_t *param = NULL;
switch (msg) { switch (msg)
{
case WM_INITDIALOG: case WM_INITDIALOG:
param = (auth_param_t*)lParam; param = (auth_param_t *)lParam;
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)param); TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)param);
WCHAR *wstr = Widen(param->str); WCHAR *wstr = Widen(param->str);
if (!wstr) { if (!wstr)
{
EndDialog(hwndDlg, LOWORD(wParam)); EndDialog(hwndDlg, LOWORD(wParam));
break; break;
} }
@ -242,7 +264,9 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
/* Set password echo on if needed */ /* Set password echo on if needed */
if (param->flags & FLAG_CR_ECHO) if (param->flags & FLAG_CR_ECHO)
{
SendMessage(GetDlgItem(hwndDlg, ID_EDT_RESPONSE), EM_SETPASSWORDCHAR, 0, 0); SendMessage(GetDlgItem(hwndDlg, ID_EDT_RESPONSE), EM_SETPASSWORDCHAR, 0, 0);
}
SetForegroundWindow(hwndDlg); SetForegroundWindow(hwndDlg);
@ -253,28 +277,30 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
break; break;
case WM_COMMAND: case WM_COMMAND:
param = (auth_param_t*)GetProp(hwndDlg, cfgProp); param = (auth_param_t *)GetProp(hwndDlg, cfgProp);
switch (LOWORD(wParam)) { switch (LOWORD(wParam))
case ID_EDT_RESPONSE: {
if (!(param->flags & FLAG_CR_ECHO)) case ID_EDT_RESPONSE:
{ if (!(param->flags & FLAG_CR_ECHO))
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE), {
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam); ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
} GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
if (HIWORD(wParam) == EN_UPDATE) { }
/* enable OK if response is non-empty */ if (HIWORD(wParam) == EN_UPDATE)
BOOL enableOK = GetWindowTextLength((HWND)lParam); {
EnableWindow(GetDlgItem(hwndDlg, IDOK), enableOK); /* enable OK if response is non-empty */
} BOOL enableOK = GetWindowTextLength((HWND)lParam);
break; EnableWindow(GetDlgItem(hwndDlg, IDOK), enableOK);
}
break;
case IDOK: { case IDOK: {
int len = 0; int len = 0;
GetDlgItemTextUtf8(hwndDlg, ID_EDT_RESPONSE, &param->cr_response, &len); GetDlgItemTextUtf8(hwndDlg, ID_EDT_RESPONSE, &param->cr_response, &len);
EndDialog(hwndDlg, LOWORD(wParam)); EndDialog(hwndDlg, LOWORD(wParam));
} }
return TRUE; return TRUE;
case IDCANCEL: case IDCANCEL:
EndDialog(hwndDlg, LOWORD(wParam)); EndDialog(hwndDlg, LOWORD(wParam));
@ -408,7 +434,7 @@ DownloadProfile(HANDLE hWnd, const struct UrlComponents *comps, const char *user
HANDLE hConnect = NULL; HANDLE hConnect = NULL;
HANDLE hRequest = NULL; HANDLE hRequest = NULL;
BOOL result = FALSE; BOOL result = FALSE;
char* buf = NULL; char *buf = NULL;
/* need to make copy of password to use it for dynamic response */ /* need to make copy of password to use it for dynamic response */
char password[USER_PASS_LEN] = { 0 }; char password[USER_PASS_LEN] = { 0 };
@ -421,7 +447,8 @@ DownloadProfile(HANDLE hWnd, const struct UrlComponents *comps, const char *user
} }
hInternet = InternetOpenW(L"openvpn-gui/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); hInternet = InternetOpenW(L"openvpn-gui/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInternet) { if (!hInternet)
{
ShowWinInetError(hWnd); ShowWinInetError(hWnd);
goto done; goto done;
} }
@ -435,7 +462,8 @@ DownloadProfile(HANDLE hWnd, const struct UrlComponents *comps, const char *user
SetCursor(LoadCursorW(0, IDC_WAIT)); SetCursor(LoadCursorW(0, IDC_WAIT));
hConnect = InternetConnectW(hInternet, comps->host, comps->port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); hConnect = InternetConnectW(hInternet, comps->host, comps->port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnect) { if (!hConnect)
{
ShowWinInetError(hWnd); ShowWinInetError(hWnd);
goto done; goto done;
} }
@ -443,13 +471,15 @@ DownloadProfile(HANDLE hWnd, const struct UrlComponents *comps, const char *user
DWORD req_flags = INTERNET_FLAG_RELOAD; /* load from server, do not use cached data */ DWORD req_flags = INTERNET_FLAG_RELOAD; /* load from server, do not use cached data */
req_flags |= comps->https ? INTERNET_FLAG_SECURE : 0; req_flags |= comps->https ? INTERNET_FLAG_SECURE : 0;
hRequest = HttpOpenRequestW(hConnect, NULL, comps->path, NULL, NULL, NULL, req_flags, 0); hRequest = HttpOpenRequestW(hConnect, NULL, comps->path, NULL, NULL, NULL, req_flags, 0);
if (!hRequest) { if (!hRequest)
{
ShowWinInetError(hWnd); ShowWinInetError(hWnd);
goto done; goto done;
} }
again: again:
if (buf) { if (buf)
{
free(buf); free(buf);
buf = NULL; buf = NULL;
} }
@ -462,26 +492,30 @@ again:
/* handle cert errors */ /* handle cert errors */
/* https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/182888 */ /* https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/182888 */
if (!HttpSendRequestW(hRequest, NULL, 0, NULL, 0)) { if (!HttpSendRequestW(hRequest, NULL, 0, NULL, 0))
{
#ifdef DEBUG #ifdef DEBUG
DWORD err = GetLastError(); DWORD err = GetLastError();
if ((err == ERROR_INTERNET_INVALID_CA) || if ((err == ERROR_INTERNET_INVALID_CA)
(err == ERROR_INTERNET_SEC_CERT_CN_INVALID) || || (err == ERROR_INTERNET_SEC_CERT_CN_INVALID)
(err == ERROR_INTERNET_SEC_CERT_DATE_INVALID) || || (err == ERROR_INTERNET_SEC_CERT_DATE_INVALID)
(err == ERROR_INTERNET_SEC_CERT_REV_FAILED)) { || (err == ERROR_INTERNET_SEC_CERT_REV_FAILED))
{
/* ask user what to do and modify options if needed */ /* ask user what to do and modify options if needed */
DWORD dlg_result = InternetErrorDlg(hWnd, hRequest, DWORD dlg_result = InternetErrorDlg(hWnd, hRequest,
err, err,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FILTER_FOR_ERRORS
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | |FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, |FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
NULL); NULL);
if (dlg_result == ERROR_SUCCESS) { if (dlg_result == ERROR_SUCCESS)
{
/* for unknown reasons InternetErrorDlg() doesn't change options for ERROR_INTERNET_SEC_CERT_REV_FAILED, /* for unknown reasons InternetErrorDlg() doesn't change options for ERROR_INTERNET_SEC_CERT_REV_FAILED,
* despite user is willing to continue, so we have to do it manually */ * despite user is willing to continue, so we have to do it manually */
if (err == ERROR_INTERNET_SEC_CERT_REV_FAILED) { if (err == ERROR_INTERNET_SEC_CERT_REV_FAILED)
{
DWORD flags; DWORD flags;
DWORD len = sizeof(flags); DWORD len = sizeof(flags);
InternetQueryOptionW(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&flags, &len); InternetQueryOptionW(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&flags, &len);
@ -495,9 +529,11 @@ again:
goto again; goto again;
} }
else else
{
goto done; goto done;
}
} }
#endif #endif /* ifdef DEBUG */
ShowWinInetError(hWnd); ShowWinInetError(hWnd);
goto done; goto done;
} }
@ -510,36 +546,49 @@ again:
size_t size = 0; size_t size = 0;
/* download profile content */ /* download profile content */
if ((status_code == 200) || (status_code == 401)) { if ((status_code == 200) || (status_code == 401))
{
if (!DownloadProfileContent(hWnd, hRequest, &buf, &size)) if (!DownloadProfileContent(hWnd, hRequest, &buf, &size))
{
goto done; goto done;
}
char* msg_begin = strstr(buf, "<Message>CRV1:"); char *msg_begin = strstr(buf, "<Message>CRV1:");
char* msg_end = strstr(buf, "</Message>"); char *msg_end = strstr(buf, "</Message>");
if ((status_code == 401) && msg_begin && msg_end) { if ((status_code == 401) && msg_begin && msg_end)
{
*msg_end = '\0'; *msg_end = '\0';
auth_param_t* param = (auth_param_t*)calloc(1, sizeof(auth_param_t)); auth_param_t *param = (auth_param_t *)calloc(1, sizeof(auth_param_t));
if (!param) if (!param)
{
goto done; goto done;
}
if (parse_dynamic_cr(msg_begin + 14, param)) { if (parse_dynamic_cr(msg_begin + 14, param))
{
/* prompt user for dynamic challenge */ /* prompt user for dynamic challenge */
INT_PTR res = LocalizedDialogBoxParam(ID_DLG_CHALLENGE_RESPONSE, CRDialogFunc, (LPARAM)param); INT_PTR res = LocalizedDialogBoxParam(ID_DLG_CHALLENGE_RESPONSE, CRDialogFunc, (LPARAM)param);
if (res == IDOK) if (res == IDOK)
{
_snprintf_0(password, "CRV1::%s::%s", param->id, param->cr_response); _snprintf_0(password, "CRV1::%s::%s", param->id, param->cr_response);
}
free_auth_param(param); free_auth_param(param);
if (res == IDOK) if (res == IDOK)
{
goto again; goto again;
}
} }
else { else
{
free_auth_param(param); free_auth_param(param);
} }
} }
} }
if (status_code != 200) { if (status_code != 200)
{
ShowLocalizedMsgEx(MB_OK, hWnd, _T(PACKAGE_NAME), IDS_ERR_URL_IMPORT_PROFILE, status_code, L"HTTP error"); ShowLocalizedMsgEx(MB_OK, hWnd, _T(PACKAGE_NAME), IDS_ERR_URL_IMPORT_PROFILE, status_code, L"HTTP error");
goto done; goto done;
} }
@ -563,8 +612,9 @@ again:
if (strlen(comps->content_type) == 0 /* AS profile */ if (strlen(comps->content_type) == 0 /* AS profile */
|| !ExtractFilenameFromHeader(hRequest, name, MAX_PATH)) || !ExtractFilenameFromHeader(hRequest, name, MAX_PATH))
{ {
WCHAR* wbuf = Widen(buf); WCHAR *wbuf = Widen(buf);
if (!wbuf) { if (!wbuf)
{
MessageBoxW(hWnd, L"Failed to convert profile content to wchar", _T(PACKAGE_NAME), MB_OK); MessageBoxW(hWnd, L"Failed to convert profile content to wchar", _T(PACKAGE_NAME), MB_OK);
goto done; goto done;
} }
@ -574,14 +624,16 @@ again:
/* save profile content into tmp file */ /* save profile content into tmp file */
DWORD res = GetTempPathW((DWORD)out_path_size, out_path); DWORD res = GetTempPathW((DWORD)out_path_size, out_path);
if (res == 0 || res > out_path_size) { if (res == 0 || res > out_path_size)
{
MessageBoxW(hWnd, L"Failed to get TMP path", _T(PACKAGE_NAME), MB_OK); MessageBoxW(hWnd, L"Failed to get TMP path", _T(PACKAGE_NAME), MB_OK);
goto done; goto done;
} }
swprintf(out_path, out_path_size, L"%ls%ls", out_path, name); swprintf(out_path, out_path_size, L"%ls%ls", out_path, name);
out_path[out_path_size - 1] = '\0'; out_path[out_path_size - 1] = '\0';
FILE* f = _wfopen(out_path, L"w"); FILE *f = _wfopen(out_path, L"w");
if (f == NULL) { if (f == NULL)
{
MessageBoxW(hWnd, L"Unable to save downloaded profile", _T(PACKAGE_NAME), MB_OK); MessageBoxW(hWnd, L"Unable to save downloaded profile", _T(PACKAGE_NAME), MB_OK);
goto done; goto done;
} }
@ -592,26 +644,34 @@ again:
done: done:
if (buf) if (buf)
{
free(buf); free(buf);
}
/* wipe the password */ /* wipe the password */
SecureZeroMemory(password, sizeof(password)); SecureZeroMemory(password, sizeof(password));
if (hRequest) if (hRequest)
{
InternetCloseHandle(hRequest); InternetCloseHandle(hRequest);
}
if (hConnect) if (hConnect)
{
InternetCloseHandle(hConnect); InternetCloseHandle(hConnect);
}
if (hInternet) if (hInternet)
{
InternetCloseHandle(hInternet); InternetCloseHandle(hInternet);
}
return result; return result;
} }
typedef enum { typedef enum {
server_as = 1, server_as = 1,
server_generic = 2 server_generic = 2
} server_type_t; } server_type_t;
INT_PTR CALLBACK INT_PTR CALLBACK
@ -623,116 +683,123 @@ ImportProfileFromURLDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
switch (msg) switch (msg)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
type = (server_type_t) lParam; type = (server_type_t) lParam;
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)lParam); TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)lParam);
SetStatusWinIcon(hwndDlg, ID_ICO_APP); SetStatusWinIcon(hwndDlg, ID_ICO_APP);
if (type == server_generic) if (type == server_generic)
{ {
/* Change window title and hide autologin checkbox */ /* Change window title and hide autologin checkbox */
SetWindowTextW(hwndDlg, LoadLocalizedString(IDS_MENU_IMPORT_URL)); SetWindowTextW(hwndDlg, LoadLocalizedString(IDS_MENU_IMPORT_URL));
ShowWindow(GetDlgItem(hwndDlg, ID_CHK_AUTOLOGIN), SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, ID_CHK_AUTOLOGIN), SW_HIDE);
}
/* disable OK button until required data is filled in */
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break;
case WM_COMMAND:
type = (server_type_t) GetProp(hwndDlg, cfgProp);
switch (LOWORD(wParam))
{
case ID_EDT_AUTH_PASS:
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
/* fall through */
case ID_EDT_AUTH_USER:
case ID_EDT_URL:
if (HIWORD(wParam) == EN_UPDATE) {
/* enable OK button only if url and username are filled */
BOOL enableOK = GetWindowTextLengthW(GetDlgItem(hwndDlg, ID_EDT_URL))
&& GetWindowTextLengthW(GetDlgItem(hwndDlg, ID_EDT_AUTH_USER));
EnableWindow(GetDlgItem(hwndDlg, IDOK), enableOK);
} }
/* disable OK button until required data is filled in */
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break; break;
case IDOK: case WM_COMMAND:
type = (server_type_t) GetProp(hwndDlg, cfgProp);
GetDlgItemTextW(hwndDlg, ID_EDT_URL, url, _countof(url)); switch (LOWORD(wParam))
int username_len = 0;
char *username = NULL;
GetDlgItemTextUtf8(hwndDlg, ID_EDT_AUTH_USER, &username, &username_len);
int password_len = 0;
char *password = NULL;
GetDlgItemTextUtf8(hwndDlg, ID_EDT_AUTH_PASS, &password, &password_len);
WCHAR path[MAX_PATH + 1] = { 0 };
struct UrlComponents comps = {0};
if (type == server_as)
{ {
case ID_EDT_AUTH_PASS:
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
autologin = IsDlgButtonChecked(hwndDlg, ID_CHK_AUTOLOGIN) == BST_CHECKED; /* fall through */
GetASUrl(url, autologin, &comps); case ID_EDT_AUTH_USER:
} case ID_EDT_URL:
else if (HIWORD(wParam) == EN_UPDATE)
{ {
ParseUrl(url, &comps); /* enable OK button only if url and username are filled */
strncpy_s(comps.content_type, _countof(comps.content_type), BOOL enableOK = GetWindowTextLengthW(GetDlgItem(hwndDlg, ID_EDT_URL))
"application/x-openvpn-profile", _TRUNCATE); && GetWindowTextLengthW(GetDlgItem(hwndDlg, ID_EDT_AUTH_USER));
} EnableWindow(GetDlgItem(hwndDlg, IDOK), enableOK);
BOOL downloaded = DownloadProfile(hwndDlg, &comps, username, password, path, _countof(path)); }
break;
case IDOK:
GetDlgItemTextW(hwndDlg, ID_EDT_URL, url, _countof(url));
int username_len = 0;
char *username = NULL;
GetDlgItemTextUtf8(hwndDlg, ID_EDT_AUTH_USER, &username, &username_len);
int password_len = 0;
char *password = NULL;
GetDlgItemTextUtf8(hwndDlg, ID_EDT_AUTH_PASS, &password, &password_len);
WCHAR path[MAX_PATH + 1] = { 0 };
struct UrlComponents comps = {0};
if (type == server_as)
{
autologin = IsDlgButtonChecked(hwndDlg, ID_CHK_AUTOLOGIN) == BST_CHECKED;
GetASUrl(url, autologin, &comps);
}
else
{
ParseUrl(url, &comps);
strncpy_s(comps.content_type, _countof(comps.content_type),
"application/x-openvpn-profile", _TRUNCATE);
}
BOOL downloaded = DownloadProfile(hwndDlg, &comps, username, password, path, _countof(path));
if (username_len > 0)
{
free(username);
}
if (password_len > 0)
{
SecureZeroMemory(password, strlen(password));
free(password);
}
if (downloaded)
{
EndDialog(hwndDlg, LOWORD(wParam));
ImportConfigFile(path, false); /* do not prompt user */
_wunlink(path);
}
return TRUE;
if (username_len > 0) case IDCANCEL:
free(username); EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
if (password_len > 0) case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
{ ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
SecureZeroMemory(password, strlen(password)); GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
free(password); return TRUE;
} }
break;
if (downloaded) {
EndDialog(hwndDlg, LOWORD(wParam));
ImportConfigFile(path, false); /* do not prompt user */
_wunlink(path);
}
return TRUE;
case IDCANCEL: case WM_CLOSE:
EndDialog(hwndDlg, LOWORD(wParam)); EndDialog(hwndDlg, LOWORD(wParam));
return TRUE; return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */ case WM_NCDESTROY:
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS), RemoveProp(hwndDlg, cfgProp);
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam); break;
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
case WM_NCDESTROY:
RemoveProp(hwndDlg, cfgProp);
break;
} }
return FALSE; return FALSE;
} }
void ImportConfigFromAS() void
ImportConfigFromAS()
{ {
LocalizedDialogBoxParam(ID_DLG_URL_PROFILE_IMPORT, ImportProfileFromURLDialogFunc, (LPARAM) server_as); LocalizedDialogBoxParam(ID_DLG_URL_PROFILE_IMPORT, ImportProfileFromURLDialogFunc, (LPARAM) server_as);
} }
void ImportConfigFromURL() void
ImportConfigFromURL()
{ {
LocalizedDialogBoxParam(ID_DLG_URL_PROFILE_IMPORT, ImportProfileFromURLDialogFunc, (LPARAM) server_generic); LocalizedDialogBoxParam(ID_DLG_URL_PROFILE_IMPORT, ImportProfileFromURLDialogFunc, (LPARAM) server_generic);
} }

@ -20,4 +20,5 @@
*/ */
void ImportConfigFromAS(); void ImportConfigFromAS();
void ImportConfigFromURL(); void ImportConfigFromURL();

@ -20,261 +20,260 @@
*/ */
WCHAR unicode_to_ascii[256] = { WCHAR unicode_to_ascii[256] = {
0x0000, 0x0000,
0x0001, 0x0001,
0x0002, 0x0002,
0x0003, 0x0003,
0x0004, 0x0004,
0x0005, 0x0005,
0x0006, 0x0006,
0x0007, 0x0007,
0x0008, 0x0008,
0x0009, 0x0009,
0x000a, 0x000a,
0x000b, 0x000b,
0x000c, 0x000c,
0x000d, 0x000d,
0x000e, 0x000e,
0x000f, 0x000f,
0x0010, 0x0010,
0x0011, 0x0011,
0x0012, 0x0012,
0x0013, 0x0013,
0x0014, 0x0014,
0x0015, 0x0015,
0x0016, 0x0016,
0x0017, 0x0017,
0x0018, 0x0018,
0x0019, 0x0019,
0x001a, 0x001a,
0x001b, 0x001b,
0x001c, 0x001c,
0x001d, 0x001d,
0x001e, 0x001e,
0x001f, 0x001f,
0x0020, 0x0020,
0x0021, 0x0021,
0x0022, 0x0022,
0x0023, 0x0023,
0x0024, 0x0024,
0x0025, 0x0025,
0x0026, 0x0026,
0x0027, 0x0027,
0x0028, 0x0028,
0x0029, 0x0029,
0x002a, 0x002a,
0x002b, 0x002b,
0x002c, 0x002c,
0x002d, 0x002d,
0x002e, 0x002e,
0x002f, 0x002f,
0x0030, 0x0030,
0x0031, 0x0031,
0x0032, 0x0032,
0x0033, 0x0033,
0x0034, 0x0034,
0x0035, 0x0035,
0x0036, 0x0036,
0x0037, 0x0037,
0x0038, 0x0038,
0x0039, 0x0039,
0x003a, 0x003a,
0x003b, 0x003b,
0x003c, 0x003c,
0x003d, 0x003d,
0x003e, 0x003e,
0x003f, 0x003f,
0x0040, 0x0040,
0x0041, 0x0041,
0x0042, 0x0042,
0x0043, 0x0043,
0x0044, 0x0044,
0x0045, 0x0045,
0x0046, 0x0046,
0x0047, 0x0047,
0x0048, 0x0048,
0x0049, 0x0049,
0x004a, 0x004a,
0x004b, 0x004b,
0x004c, 0x004c,
0x004d, 0x004d,
0x004e, 0x004e,
0x004f, 0x004f,
0x0050, 0x0050,
0x0051, 0x0051,
0x0052, 0x0052,
0x0053, 0x0053,
0x0054, 0x0054,
0x0055, 0x0055,
0x0056, 0x0056,
0x0057, 0x0057,
0x0058, 0x0058,
0x0059, 0x0059,
0x005a, 0x005a,
0x005b, 0x005b,
0x005c, 0x005c,
0x005d, 0x005d,
0x005e, 0x005e,
0x005f, 0x005f,
0x0060, 0x0060,
0x0061, 0x0061,
0x0062, 0x0062,
0x0063, 0x0063,
0x0064, 0x0064,
0x0065, 0x0065,
0x0066, 0x0066,
0x0067, 0x0067,
0x0068, 0x0068,
0x0069, 0x0069,
0x006a, 0x006a,
0x006b, 0x006b,
0x006c, 0x006c,
0x006d, 0x006d,
0x006e, 0x006e,
0x006f, 0x006f,
0x0070, 0x0070,
0x0071, 0x0071,
0x0072, 0x0072,
0x0073, 0x0073,
0x0074, 0x0074,
0x0075, 0x0075,
0x0076, 0x0076,
0x0077, 0x0077,
0x0078, 0x0078,
0x0079, 0x0079,
0x007a, 0x007a,
0x007b, 0x007b,
0x007c, 0x007c,
0x007d, 0x007d,
0x007e, 0x007e,
0x007f, 0x007f,
0x00c7, 0x00c7,
0x00fc, 0x00fc,
0x00e9, 0x00e9,
0x00e2, 0x00e2,
0x00e4, 0x00e4,
0x00e0, 0x00e0,
0x00e5, 0x00e5,
0x00e7, 0x00e7,
0x00ea, 0x00ea,
0x00eb, 0x00eb,
0x00e8, 0x00e8,
0x00ef, 0x00ef,
0x00ee, 0x00ee,
0x00ec, 0x00ec,
0x00c4, 0x00c4,
0x00c5, 0x00c5,
0x00c9, 0x00c9,
0x00e6, 0x00e6,
0x00c6, 0x00c6,
0x00f4, 0x00f4,
0x00f6, 0x00f6,
0x00f2, 0x00f2,
0x00fb, 0x00fb,
0x00f9, 0x00f9,
0x00ff, 0x00ff,
0x00d6, 0x00d6,
0x00dc, 0x00dc,
0x00f8, 0x00f8,
0x00a3, 0x00a3,
0x00d8, 0x00d8,
0x00d7, 0x00d7,
0x0192, 0x0192,
0x00e1, 0x00e1,
0x00ed, 0x00ed,
0x00f3, 0x00f3,
0x00fa, 0x00fa,
0x00f1, 0x00f1,
0x00d1, 0x00d1,
0x00aa, 0x00aa,
0x00ba, 0x00ba,
0x00bf, 0x00bf,
0x00ae, 0x00ae,
0x00ac, 0x00ac,
0x00bd, 0x00bd,
0x00bc, 0x00bc,
0x00a1, 0x00a1,
0x00ab, 0x00ab,
0x00bb, 0x00bb,
0x2591, 0x2591,
0x2592, 0x2592,
0x2593, 0x2593,
0x2502, 0x2502,
0x2524, 0x2524,
0x00c1, 0x00c1,
0x00c2, 0x00c2,
0x00c0, 0x00c0,
0x00a9, 0x00a9,
0x2563, 0x2563,
0x2551, 0x2551,
0x2557, 0x2557,
0x255d, 0x255d,
0x00a2, 0x00a2,
0x00a5, 0x00a5,
0x2510, 0x2510,
0x2514, 0x2514,
0x2534, 0x2534,
0x252c, 0x252c,
0x251c, 0x251c,
0x2500, 0x2500,
0x253c, 0x253c,
0x00e3, 0x00e3,
0x00c3, 0x00c3,
0x255a, 0x255a,
0x2554, 0x2554,
0x2569, 0x2569,
0x2566, 0x2566,
0x2560, 0x2560,
0x2550, 0x2550,
0x256c, 0x256c,
0x00a4, 0x00a4,
0x00f0, 0x00f0,
0x00d0, 0x00d0,
0x00ca, 0x00ca,
0x00cb, 0x00cb,
0x00c8, 0x00c8,
0x0131, 0x0131,
0x00cd, 0x00cd,
0x00ce, 0x00ce,
0x00cf, 0x00cf,
0x2518, 0x2518,
0x250c, 0x250c,
0x2588, 0x2588,
0x2584, 0x2584,
0x00a6, 0x00a6,
0x00cc, 0x00cc,
0x2580, 0x2580,
0x00d3, 0x00d3,
0x00df, 0x00df,
0x00d4, 0x00d4,
0x00d2, 0x00d2,
0x00f5, 0x00f5,
0x00d5, 0x00d5,
0x00b5, 0x00b5,
0x00fe, 0x00fe,
0x00de, 0x00de,
0x00da, 0x00da,
0x00db, 0x00db,
0x00d9, 0x00d9,
0x00fd, 0x00fd,
0x00dd, 0x00dd,
0x00af, 0x00af,
0x00b4, 0x00b4,
0x00ad, 0x00ad,
0x00b1, 0x00b1,
0x2017, 0x2017,
0x00be, 0x00be,
0x00b6, 0x00b6,
0x00a7, 0x00a7,
0x00f7, 0x00f7,
0x00b8, 0x00b8,
0x00b0, 0x00b0,
0x00a8, 0x00a8,
0x00b7, 0x00b7,
0x00b9, 0x00b9,
0x00b3, 0x00b3,
0x00b2, 0x00b2,
0x25a0, 0x25a0,
0x00a0 0x00a0
}; };

@ -22,7 +22,7 @@
#define PACKAGE_VERSION "11" #define PACKAGE_VERSION "11"
/* Version in windows resource format */ /* Version in windows resource format */
#define PACKAGE_VERSION_RESOURCE @GUI_VERSION_MAJOR@,@GUI_VERSION_MINOR@,0,0 #define PACKAGE_VERSION_RESOURCE @GUI_VERSION_MAJOR@, @GUI_VERSION_MINOR@, 0, 0
/* Version as a string */ /* Version as a string */
#define PACKAGE_VERSION_RESOURCE_STR "@GUI_VERSION_MAJOR@.@GUI_VERSION_MINOR@.0.0" #define PACKAGE_VERSION_RESOURCE_STR "@GUI_VERSION_MAJOR@.@GUI_VERSION_MINOR@.0.0"

@ -43,7 +43,7 @@ is_comment(wchar_t *s)
} }
static int static int
copy_token(wchar_t **dest, wchar_t **src, wchar_t* delim) copy_token(wchar_t **dest, wchar_t **src, wchar_t *delim)
{ {
wchar_t *p = *src; wchar_t *p = *src;
wchar_t *s = *dest; wchar_t *s = *dest;
@ -61,7 +61,9 @@ copy_token(wchar_t **dest, wchar_t **src, wchar_t* delim)
return -1; /* parse error -- illegal backslash in input */ return -1; /* parse error -- illegal backslash in input */
} }
else else
{
*s = *p; *s = *p;
}
} }
/* at this point p is one of the delimiters or null */ /* at this point p is one of the delimiters or null */
*s = L'\0'; *s = L'\0';
@ -79,9 +81,12 @@ tokenize(config_entry_t *ce)
unsigned int i = 0; unsigned int i = 0;
int status = 0; int status = 0;
for ( ; *p != L'\0'; p++, s++) for ( ; *p != L'\0'; p++, s++)
{ {
if (*p == L' ' || *p == L'\t') continue; if (*p == L' ' || *p == L'\t')
{
continue;
}
if (_countof(ce->tokens) <= i) if (_countof(ce->tokens) <= i)
{ {
@ -89,7 +94,7 @@ tokenize(config_entry_t *ce)
} }
ce->tokens[i++] = s; ce->tokens[i++] = s;
if (*p == L'\'' ) if (*p == L'\'')
{ {
int len = wcscspn(++p, L"\'"); int len = wcscspn(++p, L"\'");
wcsncpy(s, p, len); wcsncpy(s, p, len);
@ -119,7 +124,10 @@ tokenize(config_entry_t *ce)
return status; return status;
} }
if (*p == L'\0') break; if (*p == L'\0')
{
break;
}
} }
ce->ntokens = i; ce->ntokens = i;
return 0; return 0;
@ -145,8 +153,8 @@ config_readline(FILE *fd, int first)
config_entry_t *ce = calloc(sizeof(*ce), 1); config_entry_t *ce = calloc(sizeof(*ce), 1);
if (!ce) if (!ce)
{ {
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Out of memory in config_readline"); MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Out of memory in config_readline");
return NULL; return NULL;
} }
mbstowcs(ce->line, &tmp[offset], _countof(ce->line)-1); mbstowcs(ce->line, &tmp[offset], _countof(ce->line)-1);

@ -52,4 +52,4 @@ config_entry_t *config_parse(wchar_t *fname);
*/ */
void config_list_free(config_entry_t *head); void config_list_free(config_entry_t *head);
#endif #endif /* ifndef CONFIG_PARSER_H */

185
echo.c

@ -80,9 +80,11 @@ echo_msg_add_fp(struct echo_msg *msg, time_t timestamp)
msg->fp.timestamp = timestamp; msg->fp.timestamp = timestamp;
if (md_init(&ctx, CALG_SHA1) != 0) if (md_init(&ctx, CALG_SHA1) != 0)
{
return; return;
md_update(&ctx, (BYTE*) msg->text, msg->txtlen*sizeof(msg->text[0])); }
md_update(&ctx, (BYTE*) msg->title, wcslen(msg->title)*sizeof(msg->title[0])); md_update(&ctx, (BYTE *) msg->text, msg->txtlen*sizeof(msg->text[0]));
md_update(&ctx, (BYTE *) msg->title, wcslen(msg->title)*sizeof(msg->title[0]));
md_final(&ctx, msg->fp.digest); md_final(&ctx, msg->fp.digest);
return; return;
} }
@ -91,15 +93,18 @@ echo_msg_add_fp(struct echo_msg *msg, time_t timestamp)
static struct echo_msg_history * static struct echo_msg_history *
echo_msg_recall(const BYTE *digest, struct echo_msg_history *hist) echo_msg_recall(const BYTE *digest, struct echo_msg_history *hist)
{ {
for( ; hist; hist = hist->next) for (; hist; hist = hist->next)
{ {
if (memcmp(hist->fp.digest, digest, HASHLEN) == 0) break; if (memcmp(hist->fp.digest, digest, HASHLEN) == 0)
{
break;
}
} }
return hist; return hist;
} }
/* Add an item to message history and return the head of the list */ /* Add an item to message history and return the head of the list */
static struct echo_msg_history* static struct echo_msg_history *
echo_msg_history_add(struct echo_msg_history *head, const struct echo_msg_fp *fp) echo_msg_history_add(struct echo_msg_history *head, const struct echo_msg_fp *fp)
{ {
struct echo_msg_history *hist = malloc(sizeof(struct echo_msg_history)); struct echo_msg_history *hist = malloc(sizeof(struct echo_msg_history));
@ -137,10 +142,15 @@ echo_msg_persist(connection_t *c)
for (hist = c->echo_msg.history; hist; hist = hist->next) for (hist = c->echo_msg.history; hist; hist = hist->next)
{ {
len++; len++;
if (len > 99) break; /* max 100 history items persisted */ if (len > 99)
{
break; /* max 100 history items persisted */
}
} }
if (len == 0) if (len == 0)
{
return; return;
}
size_t size = len*sizeof(struct echo_msg_fp); size_t size = len*sizeof(struct echo_msg_fp);
struct echo_msg_fp *data = malloc(size); struct echo_msg_fp *data = malloc(size);
@ -156,7 +166,9 @@ echo_msg_persist(connection_t *c)
data[i++] = hist->fp; data[i++] = hist->fp;
} }
if (!SetConfigRegistryValueBinary(c->config_name, L"echo_msg_history", (BYTE *) data, size)) if (!SetConfigRegistryValueBinary(c->config_name, L"echo_msg_history", (BYTE *) data, size))
{
WriteStatusLog(c, L"GUI> ", L"Failed to persist echo msg history: error writing to registry", false); WriteStatusLog(c, L"GUI> ", L"Failed to persist echo msg history: error writing to registry", false);
}
free(data); free(data);
return; return;
@ -171,7 +183,9 @@ echo_msg_load(connection_t *c)
size_t size = GetConfigRegistryValue(c->config_name, L"echo_msg_history", NULL, 0); size_t size = GetConfigRegistryValue(c->config_name, L"echo_msg_history", NULL, 0);
if (size == 0) if (size == 0)
{
return; /* no history in registry */ return; /* no history in registry */
}
else if (size%item_len != 0) else if (size%item_len != 0)
{ {
WriteStatusLog(c, L"GUI> ", L"echo msg history in registry has invalid size", false); WriteStatusLog(c, L"GUI> ", L"echo msg history in registry has invalid size", false);
@ -179,11 +193,13 @@ echo_msg_load(connection_t *c)
} }
data = malloc(size); data = malloc(size);
if (!data || !GetConfigRegistryValue(c->config_name, L"echo_msg_history", (BYTE*) data, size)) if (!data || !GetConfigRegistryValue(c->config_name, L"echo_msg_history", (BYTE *) data, size))
{
goto out; goto out;
}
size_t len = size/item_len; size_t len = size/item_len;
for(size_t i = 0; i < len; i++) for (size_t i = 0; i < len; i++)
{ {
c->echo_msg.history = echo_msg_history_add(c->echo_msg.history, &data[i]); c->echo_msg.history = echo_msg_history_add(c->echo_msg.history, &data[i]);
} }
@ -255,7 +271,7 @@ echo_msg_display(connection_t *c, time_t timestamp, const char *title, int type)
} }
echo_msg_add_fp(&c->echo_msg, timestamp); /* add fingerprint: digest+timestamp */ echo_msg_add_fp(&c->echo_msg, timestamp); /* add fingerprint: digest+timestamp */
/* Check whether the message is muted */ /* Check whether the message is muted */
if (c->flags & FLAG_DISABLE_ECHO_MSG || echo_msg_repeated(&c->echo_msg)) if (c->flags & FLAG_DISABLE_ECHO_MSG || echo_msg_repeated(&c->echo_msg))
{ {
return; return;
@ -356,7 +372,9 @@ static wchar_t *
get_text_in_range(HWND h, CHARRANGE chrg) get_text_in_range(HWND h, CHARRANGE chrg)
{ {
if (chrg.cpMax <= chrg.cpMin) if (chrg.cpMax <= chrg.cpMin)
return NULL; {
return NULL;
}
size_t len = chrg.cpMax - chrg.cpMin; size_t len = chrg.cpMax - chrg.cpMin;
wchar_t *txt = malloc((len + 1)*sizeof(wchar_t)); wchar_t *txt = malloc((len + 1)*sizeof(wchar_t));
@ -365,9 +383,13 @@ get_text_in_range(HWND h, CHARRANGE chrg)
{ {
TEXTRANGEW txtrg = {chrg, txt}; TEXTRANGEW txtrg = {chrg, txt};
if (SendMessage(h, EM_GETTEXTRANGE, 0, (LPARAM)&txtrg) <= 0) if (SendMessage(h, EM_GETTEXTRANGE, 0, (LPARAM)&txtrg) <= 0)
{
txt[0] = '\0'; txt[0] = '\0';
}
else else
{
txt[len] = '\0'; /* safety */ txt[len] = '\0'; /* safety */
}
} }
return txt; return txt;
} }
@ -392,7 +414,9 @@ OnEnLinkNotify(HWND UNUSED hwnd, ENLINK *el)
/* get the link text */ /* get the link text */
wchar_t *url = get_text_in_range(el->nmhdr.hwndFrom, el->chrg); wchar_t *url = get_text_in_range(el->nmhdr.hwndFrom, el->chrg);
if (url) if (url)
{
open_url(url); open_url(url);
}
free(url); free(url);
return 1; return 1;
} }
@ -431,7 +455,7 @@ AddMessageBoxText(HWND hwnd, const wchar_t *text, const wchar_t *title, const wc
cfm.dwEffects |= CFE_ITALIC; cfm.dwEffects |= CFE_ITALIC;
SendMessage(hmsg, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cfm); SendMessage(hmsg, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cfm);
/* Align to right */ /* Align to right */
pf.wAlignment = align[1]; pf.wAlignment = align[1];
SendMessage(hmsg, EM_SETPARAFORMAT, 0, (LPARAM) &pf); SendMessage(hmsg, EM_SETPARAFORMAT, 0, (LPARAM) &pf);
SendMessage(hmsg, EM_REPLACESEL, FALSE, (LPARAM) from); SendMessage(hmsg, EM_REPLACESEL, FALSE, (LPARAM) from);
@ -500,69 +524,70 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
switch (msg) switch (msg)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
hIcon = LoadLocalizedIcon(ID_ICO_APP); hIcon = LoadLocalizedIcon(ID_ICO_APP);
if (hIcon) { if (hIcon)
SendMessage(hwnd, WM_SETICON, (WPARAM) (ICON_SMALL), (LPARAM) (hIcon));
SendMessage(hwnd, WM_SETICON, (WPARAM) (ICON_BIG), (LPARAM) (hIcon));
}
hmsg = GetDlgItem(hwnd, ID_TXT_MESSAGE);
SetWindowText(hwnd, L"OpenVPN Messages");
SendMessage(hmsg, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,
MAKELPARAM(side_margin, side_margin));
if (LangFlowDirection() == 1)
{
LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | WS_EX_RTLREADING | WS_EX_LAYOUTRTL);
exstyle = GetWindowLong(hmsg, GWL_EXSTYLE);
SetWindowLong(hmsg, GWL_EXSTYLE, exstyle | WS_EX_LEFTSCROLLBAR);
}
enable_url_detection(hmsg);
/* Position the window close to top right corner of the screen */
RECT rc;
GetWindowRect(hwnd, &rc);
OffsetRect(&rc, -rc.left, -rc.top);
int ox = GetSystemMetrics(SM_CXSCREEN); /* screen size along x */
ox -= rc.right + DPI_SCALE(rand()%50 + 25);
int oy = DPI_SCALE(rand()%50 + 25);
SetWindowPos(hwnd, HWND_TOP, ox > 0 ? ox:0, oy, 0, 0, SWP_NOSIZE);
return TRUE;
case WM_SIZE:
hmsg = GetDlgItem(hwnd, ID_TXT_MESSAGE);
/* leave some space as top margin */
SetWindowPos(hmsg, NULL, 0, top_margin, LOWORD(lParam), HIWORD(lParam)-top_margin, 0);
InvalidateRect(hwnd, NULL, TRUE);
break;
/* set the whole client area background to white */
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
return (INT_PTR) GetStockObject(WHITE_BRUSH);
break;
case WM_COMMAND:
if (LOWORD(wParam) == ID_TXT_MESSAGE)
{
/* The caret is distracting in a readonly msg box: hide it when we get focus */
if (HIWORD(wParam) == EN_SETFOCUS)
{ {
HideCaret((HWND)lParam); SendMessage(hwnd, WM_SETICON, (WPARAM) (ICON_SMALL), (LPARAM) (hIcon));
SendMessage(hwnd, WM_SETICON, (WPARAM) (ICON_BIG), (LPARAM) (hIcon));
} }
else if (HIWORD(wParam) == EN_KILLFOCUS) hmsg = GetDlgItem(hwnd, ID_TXT_MESSAGE);
SetWindowText(hwnd, L"OpenVPN Messages");
SendMessage(hmsg, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,
MAKELPARAM(side_margin, side_margin));
if (LangFlowDirection() == 1)
{ {
ShowCaret((HWND)lParam); LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | WS_EX_RTLREADING | WS_EX_LAYOUTRTL);
exstyle = GetWindowLong(hmsg, GWL_EXSTYLE);
SetWindowLong(hmsg, GWL_EXSTYLE, exstyle | WS_EX_LEFTSCROLLBAR);
} }
}
break;
/* Must be sent with lParam = connection pointer enable_url_detection(hmsg);
* Adds the current echo message and shows the window.
*/ /* Position the window close to top right corner of the screen */
case WM_OVPN_ECHOMSG: RECT rc;
GetWindowRect(hwnd, &rc);
OffsetRect(&rc, -rc.left, -rc.top);
int ox = GetSystemMetrics(SM_CXSCREEN); /* screen size along x */
ox -= rc.right + DPI_SCALE(rand()%50 + 25);
int oy = DPI_SCALE(rand()%50 + 25);
SetWindowPos(hwnd, HWND_TOP, ox > 0 ? ox : 0, oy, 0, 0, SWP_NOSIZE);
return TRUE;
case WM_SIZE:
hmsg = GetDlgItem(hwnd, ID_TXT_MESSAGE);
/* leave some space as top margin */
SetWindowPos(hmsg, NULL, 0, top_margin, LOWORD(lParam), HIWORD(lParam)-top_margin, 0);
InvalidateRect(hwnd, NULL, TRUE);
break;
/* set the whole client area background to white */
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
return (INT_PTR) GetStockObject(WHITE_BRUSH);
break;
case WM_COMMAND:
if (LOWORD(wParam) == ID_TXT_MESSAGE)
{
/* The caret is distracting in a readonly msg box: hide it when we get focus */
if (HIWORD(wParam) == EN_SETFOCUS)
{
HideCaret((HWND)lParam);
}
else if (HIWORD(wParam) == EN_KILLFOCUS)
{
ShowCaret((HWND)lParam);
}
}
break;
/* Must be sent with lParam = connection pointer
* Adds the current echo message and shows the window.
*/
case WM_OVPN_ECHOMSG:
{ {
connection_t *c = (connection_t *) lParam; connection_t *c = (connection_t *) lParam;
wchar_t from[256]; wchar_t from[256];
@ -570,7 +595,9 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
/* strip \n added by _wctime */ /* strip \n added by _wctime */
if (wcslen(from) > 0) if (wcslen(from) > 0)
{
from[wcslen(from)-1] = L'\0'; from[wcslen(from)-1] = L'\0';
}
AddMessageBoxText(hwnd, c->echo_msg.text, c->echo_msg.title, from); AddMessageBoxText(hwnd, c->echo_msg.text, c->echo_msg.title, from);
SetForegroundWindow(hwnd); SetForegroundWindow(hwnd);
@ -578,16 +605,18 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
} }
break; break;
case WM_NOTIFY: case WM_NOTIFY:
nmh = (NMHDR*) lParam; nmh = (NMHDR *) lParam;
/* We handle only EN_LINK messages */ /* We handle only EN_LINK messages */
if (nmh->idFrom == ID_TXT_MESSAGE && nmh->code == EN_LINK) if (nmh->idFrom == ID_TXT_MESSAGE && nmh->code == EN_LINK)
return OnEnLinkNotify(hwnd, (ENLINK*)lParam); {
break; return OnEnLinkNotify(hwnd, (ENLINK *)lParam);
}
break;
case WM_CLOSE: case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE); ShowWindow(hwnd, SW_HIDE);
return TRUE; return TRUE;
} }
return 0; return 0;

@ -54,4 +54,4 @@ void echo_msg_clear(connection_t *c, BOOL clear_history);
/* Load echo msg history from the registry */ /* Load echo msg history from the registry */
void echo_msg_load(connection_t *c); void echo_msg_load(connection_t *c);
#endif #endif /* ifndef ECHO_H */

@ -94,7 +94,10 @@ env_item_del(struct env_item *head, const wchar_t *name)
{ {
struct env_item *item, *prev = NULL; struct env_item *item, *prev = NULL;
if (!name) return head; if (!name)
{
return head;
}
for (item = head; item; item = item->next) for (item = head; item; item = item->next)
{ {
@ -102,9 +105,13 @@ env_item_del(struct env_item *head, const wchar_t *name)
{ {
/* matching item found */ /* matching item found */
if (prev) if (prev)
{
prev->next = item->next; prev->next = item->next;
}
else /* head is going to be deleted */ else /* head is going to be deleted */
{
head = item->next; head = item->next;
}
env_item_free(item); env_item_free(item);
break; break;
} }
@ -132,7 +139,7 @@ env_item_insert(struct env_item *head, struct env_item *item)
cmp = env_name_compare(item->nameval, tmp->nameval); cmp = env_name_compare(item->nameval, tmp->nameval);
if (cmp <= 0) /* found the position to add */ if (cmp <= 0) /* found the position to add */
{ {
break; break;
} }
prev = tmp; prev = tmp;
continue; continue;
@ -148,9 +155,13 @@ env_item_insert(struct env_item *head, struct env_item *item)
} }
if (prev) if (prev)
{
prev->next = item; prev->next = item;
}
else else
{
head = item; head = item;
}
return head; return head;
} }
@ -194,13 +205,15 @@ env_item_new_utf8(const char *nameval)
/* Insert an env item to the set given nameval: name=val. /* Insert an env item to the set given nameval: name=val.
* Returns new head of the list. * Returns new head of the list.
*/ */
static struct env_item* static struct env_item *
env_item_insert_utf8(struct env_item *head, const char *nameval) env_item_insert_utf8(struct env_item *head, const char *nameval)
{ {
struct env_item *item = env_item_new_utf8(nameval); struct env_item *item = env_item_new_utf8(nameval);
if (!item) if (!item)
{
return head; return head;
}
return env_item_insert(head, item); return env_item_insert(head, item);
} }
@ -247,11 +260,10 @@ merge_env_block(const struct env_item *es)
for (pe = e; *pe; pe += wcslen(pe)+1) for (pe = e; *pe; pe += wcslen(pe)+1)
{ {
;
} }
len = (pe + 1 - e); /* including the extra '\0' at the end */ len = (pe + 1 - e); /* including the extra '\0' at the end */
for(item = es; item; item = item->next) for (item = es; item; item = item->next)
{ {
len += wcslen(item->nameval) + 1; len += wcslen(item->nameval) + 1;
} }
@ -291,7 +303,9 @@ merge_env_block(const struct env_item *es)
{ {
pe += len; pe += len;
if (*pe) /* update len */ if (*pe) /* update len */
{
len = wcslen(pe) + 1; len = wcslen(pe) + 1;
}
} }
} }
/* Add any remaining entries -- either item or *pe is NULL at this point. /* Add any remaining entries -- either item or *pe is NULL at this point.
@ -326,7 +340,9 @@ process_setenv(connection_t *c, UNUSED time_t timestamp, const char *msg)
char *nameval; char *nameval;
if (!strbegins(msg, "setenv ")) if (!strbegins(msg, "setenv "))
{
return; return;
}
msg += strlen("setenv "); /* character following "setenv" */ msg += strlen("setenv "); /* character following "setenv" */
msg += strspn(msg, " \t"); /* skip leading space */ msg += strspn(msg, " \t"); /* skip leading space */

@ -41,6 +41,6 @@ void process_setenv(connection_t *c, time_t timestamp, const char *msg);
* as the env block or NULL on error. The caller must free the returned * as the env block or NULL on error. The caller must free the returned
* pointer. * pointer.
*/ */
wchar_t * merge_env_block(const struct env_item *es); wchar_t *merge_env_block(const struct env_item *es);
#endif #endif

@ -52,18 +52,24 @@ FindResourceLang(PTSTR resType, PTSTR resId, LANGID langId)
/* try to find the resource in requested language */ /* try to find the resource in requested language */
res = FindResourceEx(o.hInstance, resType, resId, langId); res = FindResourceEx(o.hInstance, resType, resId, langId);
if (res) if (res)
{
return res; return res;
}
/* try to find the resource in the default sublanguage */ /* try to find the resource in the default sublanguage */
LANGID defLangId = MAKELANGID(PRIMARYLANGID(langId), SUBLANG_DEFAULT); LANGID defLangId = MAKELANGID(PRIMARYLANGID(langId), SUBLANG_DEFAULT);
res = FindResourceEx(o.hInstance, resType, resId, defLangId); res = FindResourceEx(o.hInstance, resType, resId, defLangId);
if (res) if (res)
{
return res; return res;
}
/* try to find the resource in the default language */ /* try to find the resource in the default language */
res = FindResourceEx(o.hInstance, resType, resId, fallbackLangId); res = FindResourceEx(o.hInstance, resType, resId, fallbackLangId);
if (res) if (res)
{
return res; return res;
}
/* try to find the resource in any language */ /* try to find the resource in any language */
return FindResource(o.hInstance, resId, resType); return FindResource(o.hInstance, resId, resType);
@ -90,7 +96,9 @@ LANGID
GetGUILanguage(void) GetGUILanguage(void)
{ {
if (gui_language != 0) if (gui_language != 0)
{
return gui_language; return gui_language;
}
HKEY regkey; HKEY regkey;
DWORD value = 0; DWORD value = 0;
@ -113,8 +121,10 @@ SetGUILanguage(LANGID langId)
{ {
HKEY regkey; HKEY regkey;
if (RegCreateKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, NULL, 0, if (RegCreateKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, NULL, 0,
KEY_WRITE, NULL, &regkey, NULL) != ERROR_SUCCESS ) KEY_WRITE, NULL, &regkey, NULL) != ERROR_SUCCESS)
{
ShowLocalizedMsg(IDS_ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU); ShowLocalizedMsg(IDS_ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU);
}
SetRegistryValueNumeric(regkey, _T("ui_language"), langId); SetRegistryValueNumeric(regkey, _T("ui_language"), langId);
InitMUILanguage(langId); InitMUILanguage(langId);
@ -197,12 +207,16 @@ LoadStringLang(UINT stringId, LANGID langId, PTSTR buffer, int bufferSize, va_li
/* find resource block for string */ /* find resource block for string */
HRSRC res = FindResourceLang(RT_STRING, resBlockId, langId); HRSRC res = FindResourceLang(RT_STRING, resBlockId, langId);
if (res == NULL) if (res == NULL)
{
goto err; goto err;
}
/* get pointer to first entry in resource block */ /* get pointer to first entry in resource block */
entry = (PWCH) LoadResource(o.hInstance, res); entry = (PWCH) LoadResource(o.hInstance, res);
if (entry == NULL) if (entry == NULL)
{
goto err; goto err;
}
/* search for string in block */ /* search for string in block */
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
@ -216,12 +230,16 @@ LoadStringLang(UINT stringId, LANGID langId, PTSTR buffer, int bufferSize, va_li
/* string does not exist */ /* string does not exist */
if (i == resIndex && *entry == 0) if (i == resIndex && *entry == 0)
{
break; break;
}
/* string found, copy it */ /* string found, copy it */
PTSTR formatStr = (PTSTR) malloc((*entry + 1) * sizeof(TCHAR)); PTSTR formatStr = (PTSTR) malloc((*entry + 1) * sizeof(TCHAR));
if (formatStr == NULL) if (formatStr == NULL)
{
break; break;
}
formatStr[*entry] = 0; formatStr[*entry] = 0;
wcsncpy(formatStr, entry + 1, *entry); wcsncpy(formatStr, entry + 1, *entry);
@ -234,7 +252,9 @@ LoadStringLang(UINT stringId, LANGID langId, PTSTR buffer, int bufferSize, va_li
err: err:
/* not found, try again with the default language */ /* not found, try again with the default language */
if (langId != fallbackLangId) if (langId != fallbackLangId)
{
return LoadStringLang(stringId, fallbackLangId, buffer, bufferSize, args); return LoadStringLang(stringId, fallbackLangId, buffer, bufferSize, args);
}
return 0; return 0;
} }
@ -276,7 +296,7 @@ static int
__ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, va_list args) __ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, va_list args)
{ {
return MessageBoxEx(parent, __LoadLocalizedString(stringId, args), caption, return MessageBoxEx(parent, __LoadLocalizedString(stringId, args), caption,
type | MB_SETFOREGROUND | MBOX_RTL_FLAGS, GetGUILanguage()); type | MB_SETFOREGROUND | MBOX_RTL_FLAGS, GetGUILanguage());
} }
int int
@ -305,12 +325,16 @@ LoadLocalizedIconEx(const UINT iconId, int cxDesired, int cyDesired)
LANGID langId = GetGUILanguage(); LANGID langId = GetGUILanguage();
HICON hIcon = HICON hIcon =
(HICON) LoadImage (o.hInstance, MAKEINTRESOURCE(iconId), (HICON) LoadImage(o.hInstance, MAKEINTRESOURCE(iconId),
IMAGE_ICON, cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED); IMAGE_ICON, cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED);
if (hIcon) if (hIcon)
{
return hIcon; return hIcon;
}
else else
PrintDebug (L"Loading icon using LoadImage failed."); {
PrintDebug(L"Loading icon using LoadImage failed.");
}
/* Fallback to CreateIconFromResource which always scales /* Fallback to CreateIconFromResource which always scales
* from the first image in the resource * from the first image in the resource
@ -318,51 +342,63 @@ LoadLocalizedIconEx(const UINT iconId, int cxDesired, int cyDesired)
/* find group icon resource */ /* find group icon resource */
HRSRC res = FindResourceLang(RT_GROUP_ICON, MAKEINTRESOURCE(iconId), langId); HRSRC res = FindResourceLang(RT_GROUP_ICON, MAKEINTRESOURCE(iconId), langId);
if (res == NULL) if (res == NULL)
{
return NULL; return NULL;
}
HGLOBAL resInfo = LoadResource(o.hInstance, res); HGLOBAL resInfo = LoadResource(o.hInstance, res);
if (resInfo == NULL) if (resInfo == NULL)
{
return NULL; return NULL;
}
int id = LookupIconIdFromDirectory(resInfo, TRUE); int id = LookupIconIdFromDirectory(resInfo, TRUE);
if (id == 0) if (id == 0)
{
return NULL; return NULL;
}
/* find the actual icon */ /* find the actual icon */
res = FindResourceLang(RT_ICON, MAKEINTRESOURCE(id), langId); res = FindResourceLang(RT_ICON, MAKEINTRESOURCE(id), langId);
if (res == NULL) if (res == NULL)
{
return NULL; return NULL;
}
resInfo = LoadResource(o.hInstance, res); resInfo = LoadResource(o.hInstance, res);
if (resInfo == NULL) if (resInfo == NULL)
{
return NULL; return NULL;
}
DWORD resSize = SizeofResource(o.hInstance, res); DWORD resSize = SizeofResource(o.hInstance, res);
if (resSize == 0) if (resSize == 0)
{
return NULL; return NULL;
}
/* Note: this uses the first icon in the resource and scales it */ /* Note: this uses the first icon in the resource and scales it */
hIcon = CreateIconFromResourceEx(resInfo, resSize, TRUE, 0x30000, hIcon = CreateIconFromResourceEx(resInfo, resSize, TRUE, 0x30000,
cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED); cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED);
return hIcon; return hIcon;
} }
HICON HICON
LoadLocalizedIcon(const UINT iconId) LoadLocalizedIcon(const UINT iconId)
{ {
/* get the required normal icon size (e.g., taskbar icon) */ /* get the required normal icon size (e.g., taskbar icon) */
int cx = GetSystemMetrics(SM_CXICON); int cx = GetSystemMetrics(SM_CXICON);
int cy = GetSystemMetrics(SM_CYICON); int cy = GetSystemMetrics(SM_CYICON);
return LoadLocalizedIconEx(iconId, cx, cy); return LoadLocalizedIconEx(iconId, cx, cy);
} }
HICON HICON
LoadLocalizedSmallIcon(const UINT iconId) LoadLocalizedSmallIcon(const UINT iconId)
{ {
/* get the required small icon size (e.g., tray icon) */ /* get the required small icon size (e.g., tray icon) */
int cx = GetSystemMetrics(SM_CXSMICON); int cx = GetSystemMetrics(SM_CXSMICON);
int cy = GetSystemMetrics(SM_CYSMICON); int cy = GetSystemMetrics(SM_CYSMICON);
return LoadLocalizedIconEx(iconId, cx, cy); return LoadLocalizedIconEx(iconId, cx, cy);
} }
LPCDLGTEMPLATE LPCDLGTEMPLATE
@ -371,7 +407,9 @@ LocalizedDialogResource(const UINT dialogId)
/* find dialog resource */ /* find dialog resource */
HRSRC res = FindResourceLang(RT_DIALOG, MAKEINTRESOURCE(dialogId), GetGUILanguage()); HRSRC res = FindResourceLang(RT_DIALOG, MAKEINTRESOURCE(dialogId), GetGUILanguage());
if (res == NULL) if (res == NULL)
{
return NULL; return NULL;
}
return LoadResource(o.hInstance, res); return LoadResource(o.hInstance, res);
} }
@ -388,7 +426,9 @@ LocalizedDialogBoxParamEx(const UINT dialogId, HWND owner, DLGPROC dialogFunc, c
{ {
LPCDLGTEMPLATE resInfo = LocalizedDialogResource(dialogId); LPCDLGTEMPLATE resInfo = LocalizedDialogResource(dialogId);
if (resInfo == NULL) if (resInfo == NULL)
{
return -1; return -1;
}
return DialogBoxIndirectParam(o.hInstance, resInfo, owner, dialogFunc, param); return DialogBoxIndirectParam(o.hInstance, resInfo, owner, dialogFunc, param);
} }
@ -399,11 +439,15 @@ CreateLocalizedDialogParam(const UINT dialogId, DLGPROC dialogFunc, const LPARAM
/* find dialog resource */ /* find dialog resource */
HRSRC res = FindResourceLang(RT_DIALOG, MAKEINTRESOURCE(dialogId), GetGUILanguage()); HRSRC res = FindResourceLang(RT_DIALOG, MAKEINTRESOURCE(dialogId), GetGUILanguage());
if (res == NULL) if (res == NULL)
{
return NULL; return NULL;
}
HGLOBAL resInfo = LoadResource(o.hInstance, res); HGLOBAL resInfo = LoadResource(o.hInstance, res);
if (resInfo == NULL) if (resInfo == NULL)
{
return NULL; return NULL;
}
return CreateDialogIndirectParam(o.hInstance, resInfo, o.hWnd, dialogFunc, param); return CreateDialogIndirectParam(o.hInstance, resInfo, o.hWnd, dialogFunc, param);
} }
@ -438,59 +482,71 @@ typedef struct {
static BOOL static BOOL
FillLangListProc(UNUSED HANDLE module, UNUSED PTSTR type, UNUSED PTSTR stringId, WORD langId, LONG_PTR lParam) FillLangListProc(UNUSED HANDLE module, UNUSED PTSTR type, UNUSED PTSTR stringId, WORD langId, LONG_PTR lParam)
{ {
langProcData *data = (langProcData*) lParam; langProcData *data = (langProcData *) lParam;
int index = ComboBox_AddString(data->languages, LangListEntry(IDS_LANGUAGE_NAME, langId)); int index = ComboBox_AddString(data->languages, LangListEntry(IDS_LANGUAGE_NAME, langId));
ComboBox_SetItemData(data->languages, index, langId); ComboBox_SetItemData(data->languages, index, langId);
/* Select this item if it is the currently displayed language */ /* Select this item if it is the currently displayed language */
if (langId == data->language if (langId == data->language
|| (PRIMARYLANGID(langId) == PRIMARYLANGID(data->language) || (PRIMARYLANGID(langId) == PRIMARYLANGID(data->language)
&& ComboBox_GetCurSel(data->languages) == CB_ERR) ) && ComboBox_GetCurSel(data->languages) == CB_ERR) )
{
ComboBox_SetCurSel(data->languages, index); ComboBox_SetCurSel(data->languages, index);
}
return TRUE; return TRUE;
} }
static BOOL static BOOL
GetLaunchOnStartup() GetLaunchOnStartup()
{ {
WCHAR regPath[MAX_PATH], exePath[MAX_PATH]; WCHAR regPath[MAX_PATH], exePath[MAX_PATH];
BOOL result = FALSE; BOOL result = FALSE;
HKEY regkey; HKEY regkey;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &regkey) == ERROR_SUCCESS) { if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &regkey) == ERROR_SUCCESS)
{
if (GetRegistryValue(regkey, L"OpenVPN-GUI", regPath, MAX_PATH) && if (GetRegistryValue(regkey, L"OpenVPN-GUI", regPath, MAX_PATH)
GetModuleFileNameW(NULL, exePath, MAX_PATH)) { && GetModuleFileNameW(NULL, exePath, MAX_PATH))
{
if (_wcsicmp(regPath, exePath) == 0) if (_wcsicmp(regPath, exePath) == 0)
{
result = TRUE; result = TRUE;
}
} }
RegCloseKey(regkey); RegCloseKey(regkey);
} }
return result; return result;
} }
static void static void
SetLaunchOnStartup(BOOL value) SetLaunchOnStartup(BOOL value)
{ {
WCHAR exePath[MAX_PATH]; WCHAR exePath[MAX_PATH];
HKEY regkey; HKEY regkey;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &regkey) == ERROR_SUCCESS) { if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &regkey) == ERROR_SUCCESS)
{
if (value) { if (value)
if (GetModuleFileNameW(NULL, exePath, MAX_PATH)) {
if (GetModuleFileNameW(NULL, exePath, MAX_PATH))
{
SetRegistryValue(regkey, L"OpenVPN-GUI", exePath); SetRegistryValue(regkey, L"OpenVPN-GUI", exePath);
}
}
else
{
RegDeleteValue(regkey, L"OpenVPN-GUI");
} }
else
RegDeleteValue(regkey, L"OpenVPN-GUI");
RegCloseKey(regkey); RegCloseKey(regkey);
@ -507,108 +563,155 @@ GeneralSettingsDlgProc(HWND hwndDlg, UINT msg, UNUSED WPARAM wParam, LPARAM lPar
.language = GetGUILanguage() .language = GetGUILanguage()
}; };
switch(msg) { switch (msg)
{
case WM_INITDIALOG:
/* Populate UI language selection combo box */
EnumResourceLanguages( NULL, RT_STRING, MAKEINTRESOURCE(IDS_LANGUAGE_NAME / 16 + 1),
(ENUMRESLANGPROC) FillLangListProc, (LONG_PTR) &langData );
/* If none of the available languages matched, select the fallback */
if (ComboBox_GetCurSel(langData.languages) == CB_ERR)
ComboBox_SelectString(langData.languages, -1,
LangListEntry(IDS_LANGUAGE_NAME, fallbackLangId));
/* Clear language id data for the selected item */
ComboBox_SetItemData(langData.languages, ComboBox_GetCurSel(langData.languages), 0);
if (GetLaunchOnStartup())
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_STARTUP), BST_CHECKED);
if (o.log_append)
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_LOG_APPEND), BST_CHECKED);
if (o.silent_connection)
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_SILENT), BST_CHECKED);
if (o.iservice_admin)
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_ALWAYS_USE_ISERVICE), BST_CHECKED);
if (o.show_balloon == 0)
CheckRadioButton (hwndDlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON0);
else if (o.show_balloon == 1)
CheckRadioButton (hwndDlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON1);
else if (o.show_balloon == 2)
CheckRadioButton (hwndDlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON2);
if (o.show_script_window)
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_SHOW_SCRIPT_WIN), BST_CHECKED);
if (o.enable_persistent == 0) /* Never */
CheckRadioButton (hwndDlg, ID_RB_BALLOON3, ID_RB_BALLOON5, ID_RB_BALLOON5);
else if (o.enable_persistent == 1) /* Enabled, but no auto-attach */
CheckRadioButton (hwndDlg, ID_RB_BALLOON3, ID_RB_BALLOON5, ID_RB_BALLOON4);
else if (o.enable_persistent == 2) /* Enabled and auto-attach */
CheckRadioButton (hwndDlg, ID_RB_BALLOON3, ID_RB_BALLOON5, ID_RB_BALLOON3);
int plap_status = GetPLAPRegistrationStatus();
if (plap_status == -1) /* PLAP not supported in this version */
ShowWindow(GetDlgItem(hwndDlg, ID_CHK_PLAP_REG), SW_HIDE);
else if (plap_status != 0)
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_PLAP_REG), BST_CHECKED);
if (o.enable_auto_restart)
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_AUTO_RESTART), BST_CHECKED);
break;
case WM_COMMAND:
if (LOWORD(wParam) == ID_CHK_PLAP_REG && HIWORD(wParam) == BN_CLICKED)
{
/* change PLAPRegistration state */
HWND h = GetDlgItem(hwndDlg, ID_CHK_PLAP_REG);
BOOL newstate = Button_GetCheck(h) == BST_CHECKED ? TRUE : FALSE;
if (SetPLAPRegistration(newstate) != 0) /* failed or user cancelled -- reset checkmark */
Button_SetCheck(h, newstate ? BST_UNCHECKED : BST_CHECKED);
}
break;
case WM_NOTIFY: case WM_INITDIALOG:
psn = (LPPSHNOTIFY) lParam; /* Populate UI language selection combo box */
if (psn->hdr.code == (UINT) PSN_APPLY) EnumResourceLanguages( NULL, RT_STRING, MAKEINTRESOURCE(IDS_LANGUAGE_NAME / 16 + 1),
{ (ENUMRESLANGPROC) FillLangListProc, (LONG_PTR) &langData );
LANGID langId = (LANGID) ComboBox_GetItemData(langData.languages,
ComboBox_GetCurSel(langData.languages)); /* If none of the available languages matched, select the fallback */
if (ComboBox_GetCurSel(langData.languages) == CB_ERR)
if (langId != 0) {
SetGUILanguage(langId); ComboBox_SelectString(langData.languages, -1,
LangListEntry(IDS_LANGUAGE_NAME, fallbackLangId));
SetLaunchOnStartup(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_STARTUP)) == BST_CHECKED); }
o.log_append = /* Clear language id data for the selected item */
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_LOG_APPEND)) == BST_CHECKED); ComboBox_SetItemData(langData.languages, ComboBox_GetCurSel(langData.languages), 0);
o.silent_connection =
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_SILENT)) == BST_CHECKED); if (GetLaunchOnStartup())
o.iservice_admin = {
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_ALWAYS_USE_ISERVICE)) == BST_CHECKED); Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_STARTUP), BST_CHECKED);
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON0)) }
o.show_balloon = 0;
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON2)) if (o.log_append)
o.show_balloon = 2; {
else Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_LOG_APPEND), BST_CHECKED);
o.show_balloon = 1; }
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON3)) if (o.silent_connection)
o.enable_persistent = 2; {
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON4)) Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_SILENT), BST_CHECKED);
o.enable_persistent = 1; }
else if (o.iservice_admin)
o.enable_persistent = 0; {
o.show_script_window = Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_ALWAYS_USE_ISERVICE), BST_CHECKED);
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_SHOW_SCRIPT_WIN)) == BST_CHECKED); }
o.enable_auto_restart = if (o.show_balloon == 0)
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_AUTO_RESTART)) == BST_CHECKED); {
CheckRadioButton(hwndDlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON0);
}
SaveRegistryKeys(); else if (o.show_balloon == 1)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); CheckRadioButton(hwndDlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON1);
return TRUE; }
} else if (o.show_balloon == 2)
break; {
CheckRadioButton(hwndDlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON2);
}
if (o.show_script_window)
{
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_SHOW_SCRIPT_WIN), BST_CHECKED);
}
if (o.enable_persistent == 0) /* Never */
{
CheckRadioButton(hwndDlg, ID_RB_BALLOON3, ID_RB_BALLOON5, ID_RB_BALLOON5);
}
else if (o.enable_persistent == 1) /* Enabled, but no auto-attach */
{
CheckRadioButton(hwndDlg, ID_RB_BALLOON3, ID_RB_BALLOON5, ID_RB_BALLOON4);
}
else if (o.enable_persistent == 2) /* Enabled and auto-attach */
{
CheckRadioButton(hwndDlg, ID_RB_BALLOON3, ID_RB_BALLOON5, ID_RB_BALLOON3);
}
int plap_status = GetPLAPRegistrationStatus();
if (plap_status == -1) /* PLAP not supported in this version */
{
ShowWindow(GetDlgItem(hwndDlg, ID_CHK_PLAP_REG), SW_HIDE);
}
else if (plap_status != 0)
{
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_PLAP_REG), BST_CHECKED);
}
if (o.enable_auto_restart)
{
Button_SetCheck(GetDlgItem(hwndDlg, ID_CHK_AUTO_RESTART), BST_CHECKED);
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == ID_CHK_PLAP_REG && HIWORD(wParam) == BN_CLICKED)
{
/* change PLAPRegistration state */
HWND h = GetDlgItem(hwndDlg, ID_CHK_PLAP_REG);
BOOL newstate = Button_GetCheck(h) == BST_CHECKED ? TRUE : FALSE;
if (SetPLAPRegistration(newstate) != 0) /* failed or user cancelled -- reset checkmark */
{
Button_SetCheck(h, newstate ? BST_UNCHECKED : BST_CHECKED);
}
}
break;
case WM_NOTIFY:
psn = (LPPSHNOTIFY) lParam;
if (psn->hdr.code == (UINT) PSN_APPLY)
{
LANGID langId = (LANGID) ComboBox_GetItemData(langData.languages,
ComboBox_GetCurSel(langData.languages));
if (langId != 0)
{
SetGUILanguage(langId);
}
SetLaunchOnStartup(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_STARTUP)) == BST_CHECKED);
o.log_append =
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_LOG_APPEND)) == BST_CHECKED);
o.silent_connection =
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_SILENT)) == BST_CHECKED);
o.iservice_admin =
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_ALWAYS_USE_ISERVICE)) == BST_CHECKED);
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON0))
{
o.show_balloon = 0;
}
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON2))
{
o.show_balloon = 2;
}
else
{
o.show_balloon = 1;
}
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON3))
{
o.enable_persistent = 2;
}
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON4))
{
o.enable_persistent = 1;
}
else
{
o.enable_persistent = 0;
}
o.show_script_window =
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_SHOW_SCRIPT_WIN)) == BST_CHECKED);
o.enable_auto_restart =
(Button_GetCheck(GetDlgItem(hwndDlg, ID_CHK_AUTO_RESTART)) == BST_CHECKED);
SaveRegistryKeys();
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
}
break;
} }
return FALSE; return FALSE;

@ -23,26 +23,43 @@
#define LOCALIZATION_H #define LOCALIZATION_H
int LocalizedTime(const time_t, LPTSTR, size_t); int LocalizedTime(const time_t, LPTSTR, size_t);
wchar_t *LocalizedFileTime(const FILETIME *ft); wchar_t *LocalizedFileTime(const FILETIME *ft);
PTSTR LoadLocalizedString(const UINT, ...); PTSTR LoadLocalizedString(const UINT, ...);
int LoadLocalizedStringBuf(PTSTR, const int, const UINT, ...); int LoadLocalizedStringBuf(PTSTR, const int, const UINT, ...);
void ShowLocalizedMsg(const UINT, ...); void ShowLocalizedMsg(const UINT, ...);
int ShowLocalizedMsgEx(const UINT, HANDLE, LPCTSTR, const UINT, ...); int ShowLocalizedMsgEx(const UINT, HANDLE, LPCTSTR, const UINT, ...);
HICON LoadLocalizedIconEx(const UINT, int cx, int cy); HICON LoadLocalizedIconEx(const UINT, int cx, int cy);
HICON LoadLocalizedIcon(const UINT); HICON LoadLocalizedIcon(const UINT);
HICON LoadLocalizedSmallIcon(const UINT); HICON LoadLocalizedSmallIcon(const UINT);
LPCDLGTEMPLATE LocalizedDialogResource(const UINT); LPCDLGTEMPLATE LocalizedDialogResource(const UINT);
INT_PTR LocalizedDialogBoxParam(const UINT, DLGPROC, const LPARAM); INT_PTR LocalizedDialogBoxParam(const UINT, DLGPROC, const LPARAM);
INT_PTR LocalizedDialogBoxParamEx(const UINT, HWND parent, DLGPROC, const LPARAM); INT_PTR LocalizedDialogBoxParamEx(const UINT, HWND parent, DLGPROC, const LPARAM);
HWND CreateLocalizedDialogParam(const UINT, DLGPROC, const LPARAM); HWND CreateLocalizedDialogParam(const UINT, DLGPROC, const LPARAM);
HWND CreateLocalizedDialog(const UINT, DLGPROC); HWND CreateLocalizedDialog(const UINT, DLGPROC);
INT_PTR CALLBACK GeneralSettingsDlgProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK GeneralSettingsDlgProc(HWND, UINT, WPARAM, LPARAM);
LANGID GetGUILanguage(void); LANGID GetGUILanguage(void);
/* /*
* Detect whether the selected UI language is LTR or RTL. * Detect whether the selected UI language is LTR or RTL.
* Returns 0 for LTR, 1 for RTL, 2 or 3 for vertical * Returns 0 for LTR, 1 for RTL, 2 or 3 for vertical
*/ */
int LangFlowDirection(void); int LangFlowDirection(void);
#define MBOX_RTL_FLAGS ((LangFlowDirection() == 1) ? MB_RIGHT|MB_RTLREADING : 0) #define MBOX_RTL_FLAGS ((LangFlowDirection() == 1) ? MB_RIGHT|MB_RTLREADING : 0)
#endif #endif /* ifndef LOCALIZATION_H */

991
main.c

File diff suppressed because it is too large Load Diff

@ -28,16 +28,16 @@
#include <tchar.h> #include <tchar.h>
/* Define this to enable DEBUG build */ /* Define this to enable DEBUG build */
//#define DEBUG /*#define DEBUG */
#define DEBUG_FILE L"C:\\windows\\temp\\openvpngui_debug.txt" #define DEBUG_FILE L"C:\\windows\\temp\\openvpngui_debug.txt"
/* Registry key for User Settings */ /* Registry key for User Settings */
#define GUI_REGKEY_HKCU _T("Software\\OpenVPN-GUI") #define GUI_REGKEY_HKCU _T("Software\\OpenVPN-GUI")
#define MAX_LOG_LENGTH 1024/* Max number of characters per log line */ #define MAX_LOG_LENGTH 1024/* Max number of characters per log line */
#define MAX_LOG_LINES 500 /* Max number of lines in LogWindow */ #define MAX_LOG_LINES 500 /* Max number of lines in LogWindow */
#define DEL_LOG_LINES 10 /* Number of lines to delete from LogWindow */ #define DEL_LOG_LINES 10 /* Number of lines to delete from LogWindow */
#define USAGE_BUF_SIZE 3000 /* Size of buffer used to display usage message */ #define USAGE_BUF_SIZE 3000 /* Size of buffer used to display usage message */
/* Authorized group who can use any options and config locations */ /* Authorized group who can use any options and config locations */
#define OVPN_ADMIN_GROUP TEXT("OpenVPN Administrators") /* May be reset in registry */ #define OVPN_ADMIN_GROUP TEXT("OpenVPN Administrators") /* May be reset in registry */
@ -78,11 +78,11 @@
#define NORETURN __attribute__ ((noreturn)) #define NORETURN __attribute__ ((noreturn))
#endif #endif
#define PACKVERSION(major,minor) MAKELONG(minor,major) #define PACKVERSION(major, minor) MAKELONG(minor, major)
struct security_attributes struct security_attributes
{ {
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd; SECURITY_DESCRIPTOR sd;
}; };
/* clear an object */ /* clear an object */
@ -90,9 +90,9 @@ struct security_attributes
/* _sntprintf with guaranteed \0 termination */ /* _sntprintf with guaranteed \0 termination */
#define _sntprintf_0(buf, ...) \ #define _sntprintf_0(buf, ...) \
do { \ do { \
__sntprintf_0(buf, _countof(buf), __VA_ARGS__); \ __sntprintf_0(buf, _countof(buf), __VA_ARGS__); \
} while(0); } while(0);
static inline int static inline int
__sntprintf_0(TCHAR *buf, size_t size, TCHAR *format, ...) __sntprintf_0(TCHAR *buf, size_t size, TCHAR *format, ...)
@ -108,9 +108,9 @@ __sntprintf_0(TCHAR *buf, size_t size, TCHAR *format, ...)
/* _snprintf with guaranteed \0 termination */ /* _snprintf with guaranteed \0 termination */
#define _snprintf_0(buf, ...) \ #define _snprintf_0(buf, ...) \
do { \ do { \
__snprintf_0(buf, sizeof(buf), __VA_ARGS__); \ __snprintf_0(buf, sizeof(buf), __VA_ARGS__); \
} while(0); } while(0);
static inline int static inline int
__snprintf_0(char *buf, size_t size, char *format, ...) __snprintf_0(char *buf, size_t size, char *format, ...)
{ {
@ -126,14 +126,15 @@ __snprintf_0(char *buf, size_t size, char *format, ...)
#ifdef DEBUG #ifdef DEBUG
/* Print Debug Message */ /* Print Debug Message */
#define PrintDebug(...) \ #define PrintDebug(...) \
do { \ do { \
TCHAR x_msg[256]; \ TCHAR x_msg[256]; \
_sntprintf_0(x_msg, __VA_ARGS__); \ _sntprintf_0(x_msg, __VA_ARGS__); \
PrintDebugMsg(x_msg); \ PrintDebugMsg(x_msg); \
} while(0) } while(0)
void PrintDebugMsg(TCHAR *msg); void PrintDebugMsg(TCHAR *msg);
#else
#else /* ifdef DEBUG */
#define PrintDebug(...) do { } while(0) #define PrintDebug(...) do { } while(0)
#endif #endif
@ -141,4 +142,4 @@ DWORD GetDllVersion(LPCTSTR lpszDllName);
void ErrorExit(int exit_code, const wchar_t *msg); void ErrorExit(int exit_code, const wchar_t *msg);
#endif #endif /* ifndef MAIN_H */

@ -63,18 +63,22 @@ OpenManagement(connection_t *c)
{ {
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return FALSE; return FALSE;
}
c->manage.connected = 0; c->manage.connected = 0;
c->manage.sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); c->manage.sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (c->manage.sk == INVALID_SOCKET) if (c->manage.sk == INVALID_SOCKET)
{ {
WSACleanup (); WSACleanup();
return FALSE; return FALSE;
} }
if (WSAAsyncSelect(c->manage.sk, c->hwndStatus, WM_MANAGEMENT, if (WSAAsyncSelect(c->manage.sk, c->hwndStatus, WM_MANAGEMENT,
FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE) != 0) FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE) != 0)
{
return FALSE; return FALSE;
}
connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr)); connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr));
c->manage.timeout = time(NULL) + max_connect_time; c->manage.timeout = time(NULL) + max_connect_time;
@ -92,14 +96,20 @@ SendCommand(connection_t *c)
int res; int res;
mgmt_cmd_t *cmd = c->manage.cmd_queue; mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (cmd == NULL || cmd->size == 0) if (cmd == NULL || cmd->size == 0)
{
return; return;
}
res = send(c->manage.sk, cmd->command, cmd->size, 0); res = send(c->manage.sk, cmd->command, cmd->size, 0);
if (res < 1) if (res < 1)
{
return; return;
}
if (res != cmd->size) if (res != cmd->size)
{
memmove(cmd->command, cmd->command + res, cmd->size - res); memmove(cmd->command, cmd->command + res, cmd->size - res);
}
cmd->size -= res; cmd->size -= res;
} }
@ -113,7 +123,9 @@ ManagementCommand(connection_t *c, char *command, mgmt_msg_func handler, mgmt_cm
{ {
mgmt_cmd_t *cmd = calloc(1, sizeof(*cmd)); mgmt_cmd_t *cmd = calloc(1, sizeof(*cmd));
if (cmd == NULL) if (cmd == NULL)
{
return FALSE; return FALSE;
}
cmd->size = strlen(command) + 1; cmd->size = strlen(command) + 1;
cmd->command = malloc(cmd->size); cmd->command = malloc(cmd->size);
@ -141,7 +153,9 @@ ManagementCommand(connection_t *c, char *command, mgmt_msg_func handler, mgmt_cm
} }
if (c->manage.cmd_queue == cmd) if (c->manage.cmd_queue == cmd)
{
SendCommand(c); SendCommand(c);
}
return TRUE; return TRUE;
} }
@ -155,7 +169,9 @@ UnqueueCommand(connection_t *c)
{ {
mgmt_cmd_t *cmd = c->manage.cmd_queue; mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (!cmd) if (!cmd)
{
return FALSE; return FALSE;
}
/* Wipe command as it may contain passwords */ /* Wipe command as it may contain passwords */
memset(cmd->command, 'x', cmd->size); memset(cmd->command, 'x', cmd->size);
@ -197,241 +213,281 @@ OnManagement(SOCKET sk, LPARAM lParam)
connection_t *c = GetConnByManagement(sk); connection_t *c = GetConnByManagement(sk);
if (c == NULL) if (c == NULL)
{
return; return;
}
switch (WSAGETSELECTEVENT(lParam)) switch (WSAGETSELECTEVENT(lParam))
{ {
case FD_CONNECT: case FD_CONNECT:
if (WSAGETSELECTERROR(lParam)) if (WSAGETSELECTERROR(lParam))
{
/* keep trying for connections with persistent daemons */
if (c->flags & FLAG_DAEMON_PERSISTENT
|| time(NULL) < c->manage.timeout)
{ {
/* show a message on status window */ /* keep trying for connections with persistent daemons */
if (rtmsg_handler[log_] && (c->flags & FLAG_DAEMON_PERSISTENT)) if (c->flags & FLAG_DAEMON_PERSISTENT
|| time(NULL) < c->manage.timeout)
{ {
char buf[256]; /* show a message on status window */
_snprintf_0(buf, "%lld,W,Waiting for the management interface to come up", if (rtmsg_handler[log_] && (c->flags & FLAG_DAEMON_PERSISTENT))
(long long)time(NULL)) {
rtmsg_handler[log_](c, buf); char buf[256];
_snprintf_0(buf, "%lld,W,Waiting for the management interface to come up",
(long long)time(NULL))
rtmsg_handler[log_](c, buf);
}
connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr));
}
else
{
/* Connection to MI timed out. */
CloseManagement(c);
if (c->state != disconnected)
{
rtmsg_handler[timeout_](c, "");
}
} }
connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr));
} }
else else
{ {
/* Connection to MI timed out. */ c->manage.connected = 1;
CloseManagement (c);
if (c->state != disconnected)
rtmsg_handler[timeout_](c, "");
} }
} break;
else
c->manage.connected = 1;
break;
case FD_READ:
if (ioctlsocket(c->manage.sk, FIONREAD, &data_size) != 0
|| data_size == 0)
return;
data = malloc(c->manage.saved_size + data_size);
if (data == NULL)
return;
res = recv(c->manage.sk, data + c->manage.saved_size, data_size, 0);
if (res != (int) data_size)
{
free(data);
return;
}
/* Copy previously saved management data */
if (c->manage.saved_size)
{
memcpy(data, c->manage.saved_data, c->manage.saved_size);
data_size += c->manage.saved_size;
free(c->manage.saved_data);
c->manage.saved_data = NULL;
c->manage.saved_size = 0;
}
offset = 0; case FD_READ:
while (offset < data_size) if (ioctlsocket(c->manage.sk, FIONREAD, &data_size) != 0
{ || data_size == 0)
char *pos;
char *line = data + offset;
size_t line_size = data_size - offset;
BOOL passwd_request = false;
const char *passwd_prompt = "ENTER PASSWORD:";
if (line_size >= strlen(passwd_prompt)
&& memcmp(line, passwd_prompt, strlen(passwd_prompt)) == 0)
{
pos = memchr(line, ':', line_size);
passwd_request = true;
}
else
{ {
pos = memchr(line, '\n', line_size); return;
} }
if (pos == NULL) data = malloc(c->manage.saved_size + data_size);
if (data == NULL)
{ {
c->manage.saved_data = malloc(line_size); return;
if (c->manage.saved_data)
{
c->manage.saved_size = line_size;
memcpy(c->manage.saved_data, line, c->manage.saved_size);
}
break;
} }
offset += (pos - line) + 1; res = recv(c->manage.sk, data + c->manage.saved_size, data_size, 0);
if (res != (int) data_size)
/* Reply to a management password request */
if (*c->manage.password && passwd_request)
{ {
ManagementCommand(c, c->manage.password, NULL, regular); free(data);
SecureZeroMemory(c->manage.password, sizeof(c->manage.password)); return;
continue;
} }
if (!*c->manage.password && passwd_request) /* Copy previously saved management data */
if (c->manage.saved_size)
{ {
/* either we don't have a password or we used it and didn't match */ memcpy(data, c->manage.saved_data, c->manage.saved_size);
MsgToEventLog(EVENTLOG_WARNING_TYPE, L"%ls: management password mismatch", data_size += c->manage.saved_size;
c->config_name); free(c->manage.saved_data);
c->state = disconnecting; c->manage.saved_data = NULL;
CloseManagement (c); c->manage.saved_size = 0;
rtmsg_handler[stop_](c, "");
continue;
} }
/* Handle regular management interface output */ offset = 0;
line[pos - line - 1] = '\0'; while (offset < data_size)
if (line[0] == '>')
{ {
/* Real time notifications */ char *pos;
pos = line + 1; char *line = data + offset;
if (strncmp(pos, "LOG:", 4) == 0) size_t line_size = data_size - offset;
{ BOOL passwd_request = false;
if (rtmsg_handler[log_]) const char *passwd_prompt = "ENTER PASSWORD:";
rtmsg_handler[log_](c, pos + 4);
} if (line_size >= strlen(passwd_prompt)
else if (strncmp(pos, "STATE:", 6) == 0) && memcmp(line, passwd_prompt, strlen(passwd_prompt)) == 0)
{
if (rtmsg_handler[state_])
rtmsg_handler[state_](c, pos + 6);
}
else if (strncmp(pos, "HOLD:", 5) == 0)
{ {
if (rtmsg_handler[hold_]) pos = memchr(line, ':', line_size);
rtmsg_handler[hold_](c, pos + 5); passwd_request = true;
} }
else if (strncmp(pos, "PASSWORD:", 9) == 0) else
{ {
if (rtmsg_handler[password_]) pos = memchr(line, '\n', line_size);
rtmsg_handler[password_](c, pos + 9);
} }
else if (strncmp(pos, "PROXY:", 6) == 0)
{ if (pos == NULL)
if (rtmsg_handler[proxy_])
rtmsg_handler[proxy_](c, pos + 6);
}
else if (strncmp(pos, "INFO:", 5) == 0)
{
/* delay until management interface accepts input */
/* use real sleep here, since WM_MANAGEMENT might arrive before management is ready */
Sleep(100);
c->manage.connected = 2;
if (rtmsg_handler[ready_])
rtmsg_handler[ready_](c, pos + 5);
}
else if (strncmp(pos, "NEED-OK:", 8) == 0)
{
if (rtmsg_handler[needok_])
rtmsg_handler[needok_](c, pos + 8);
}
else if (strncmp(pos, "NEED-STR:", 9) == 0)
{ {
if (rtmsg_handler[needstr_]) c->manage.saved_data = malloc(line_size);
rtmsg_handler[needstr_](c, pos + 9); if (c->manage.saved_data)
{
c->manage.saved_size = line_size;
memcpy(c->manage.saved_data, line, c->manage.saved_size);
}
break;
} }
else if (strncmp(pos, "ECHO:", 5) == 0)
offset += (pos - line) + 1;
/* Reply to a management password request */
if (*c->manage.password && passwd_request)
{ {
if (rtmsg_handler[echo_]) ManagementCommand(c, c->manage.password, NULL, regular);
rtmsg_handler[echo_](c, pos + 5); SecureZeroMemory(c->manage.password, sizeof(c->manage.password));
continue;
} }
else if (strncmp(pos, "BYTECOUNT:", 10) == 0)
if (!*c->manage.password && passwd_request)
{ {
if (rtmsg_handler[bytecount_]) /* either we don't have a password or we used it and didn't match */
rtmsg_handler[bytecount_](c, pos + 10); MsgToEventLog(EVENTLOG_WARNING_TYPE, L"%ls: management password mismatch",
c->config_name);
c->state = disconnecting;
CloseManagement(c);
rtmsg_handler[stop_](c, "");
continue;
} }
else if (strncmp(pos, "INFOMSG:", 8) == 0)
/* Handle regular management interface output */
line[pos - line - 1] = '\0';
if (line[0] == '>')
{ {
if (rtmsg_handler[infomsg_]) /* Real time notifications */
rtmsg_handler[infomsg_](c, pos + 8); pos = line + 1;
if (strncmp(pos, "LOG:", 4) == 0)
{
if (rtmsg_handler[log_])
{
rtmsg_handler[log_](c, pos + 4);
}
}
else if (strncmp(pos, "STATE:", 6) == 0)
{
if (rtmsg_handler[state_])
{
rtmsg_handler[state_](c, pos + 6);
}
}
else if (strncmp(pos, "HOLD:", 5) == 0)
{
if (rtmsg_handler[hold_])
{
rtmsg_handler[hold_](c, pos + 5);
}
}
else if (strncmp(pos, "PASSWORD:", 9) == 0)
{
if (rtmsg_handler[password_])
{
rtmsg_handler[password_](c, pos + 9);
}
}
else if (strncmp(pos, "PROXY:", 6) == 0)
{
if (rtmsg_handler[proxy_])
{
rtmsg_handler[proxy_](c, pos + 6);
}
}
else if (strncmp(pos, "INFO:", 5) == 0)
{
/* delay until management interface accepts input */
/* use real sleep here, since WM_MANAGEMENT might arrive before management is ready */
Sleep(100);
c->manage.connected = 2;
if (rtmsg_handler[ready_])
{
rtmsg_handler[ready_](c, pos + 5);
}
}
else if (strncmp(pos, "NEED-OK:", 8) == 0)
{
if (rtmsg_handler[needok_])
{
rtmsg_handler[needok_](c, pos + 8);
}
}
else if (strncmp(pos, "NEED-STR:", 9) == 0)
{
if (rtmsg_handler[needstr_])
{
rtmsg_handler[needstr_](c, pos + 9);
}
}
else if (strncmp(pos, "ECHO:", 5) == 0)
{
if (rtmsg_handler[echo_])
{
rtmsg_handler[echo_](c, pos + 5);
}
}
else if (strncmp(pos, "BYTECOUNT:", 10) == 0)
{
if (rtmsg_handler[bytecount_])
{
rtmsg_handler[bytecount_](c, pos + 10);
}
}
else if (strncmp(pos, "INFOMSG:", 8) == 0)
{
if (rtmsg_handler[infomsg_])
{
rtmsg_handler[infomsg_](c, pos + 8);
}
}
else if (strncmp(pos, "PKCS11ID", 8) == 0
&& c->manage.cmd_queue)
{
/* This is not a real-time message, but unfortunately implemented
* in the core as one. Work around by handling the response here.
*/
mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (cmd->handler)
{
cmd->handler(c, line);
}
UnqueueCommand(c);
}
} }
else if (strncmp(pos, "PKCS11ID", 8) == 0 else if (c->manage.cmd_queue)
&& c->manage.cmd_queue)
{ {
/* This is not a real-time message, but unfortunately implemented /* Response to commands */
* in the core as one. Work around by handling the response here.
*/
mgmt_cmd_t *cmd = c->manage.cmd_queue; mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (cmd->handler) if (strncmp(line, "SUCCESS:", 8) == 0)
{
if (cmd->handler)
{
cmd->handler(c, line + 9);
}
UnqueueCommand(c);
}
else if (strncmp(line, "ERROR:", 6) == 0)
{
/* Response sent to management is not processed. Log an error in status window */
char buf[256];
_snprintf_0(buf, "%lld,N,Previous command sent to management failed: %s",
(long long)time(NULL), line)
rtmsg_handler[log_](c, buf);
if (cmd->handler)
{
cmd->handler(c, NULL);
}
UnqueueCommand(c);
}
else if (strcmp(line, "END") == 0)
{
UnqueueCommand(c);
}
else if (cmd->handler)
{
cmd->handler(c, line); cmd->handler(c, line);
UnqueueCommand(c); }
}
}
else if (c->manage.cmd_queue)
{
/* Response to commands */
mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (strncmp(line, "SUCCESS:", 8) == 0)
{
if (cmd->handler)
cmd->handler(c, line + 9);
UnqueueCommand(c);
}
else if (strncmp(line, "ERROR:", 6) == 0)
{
/* Response sent to management is not processed. Log an error in status window */
char buf[256];
_snprintf_0(buf, "%lld,N,Previous command sent to management failed: %s",
(long long)time(NULL), line)
rtmsg_handler[log_](c, buf);
if (cmd->handler)
cmd->handler(c, NULL);
UnqueueCommand(c);
}
else if (strcmp(line, "END") == 0)
{
UnqueueCommand(c);
}
else if (cmd->handler)
{
cmd->handler(c, line);
} }
} }
} free(data);
free(data); break;
break;
case FD_WRITE: case FD_WRITE:
SendCommand(c); SendCommand(c);
break; break;
case FD_CLOSE: case FD_CLOSE:
CloseManagement (c); CloseManagement(c);
if (rtmsg_handler[stop_]) if (rtmsg_handler[stop_])
rtmsg_handler[stop_](c, ""); {
break; rtmsg_handler[stop_](c, "");
}
break;
} }
} }
@ -450,7 +506,8 @@ CloseManagement(connection_t *c)
c->manage.sk = INVALID_SOCKET; c->manage.sk = INVALID_SOCKET;
c->manage.connected = 0; c->manage.connected = 0;
while (UnqueueCommand(c)) while (UnqueueCommand(c))
; {
}
WSACleanup(); WSACleanup();
} }
} }

@ -64,10 +64,13 @@ typedef struct mgmt_cmd {
void InitManagement(const mgmt_rtmsg_handler *handler); void InitManagement(const mgmt_rtmsg_handler *handler);
BOOL OpenManagement(connection_t *); BOOL OpenManagement(connection_t *);
BOOL ManagementCommand(connection_t *, char *, mgmt_msg_func, mgmt_cmd_type); BOOL ManagementCommand(connection_t *, char *, mgmt_msg_func, mgmt_cmd_type);
void OnManagement(SOCKET, LPARAM); void OnManagement(SOCKET, LPARAM);
void CloseManagement(connection_t *); void CloseManagement(connection_t *);
#endif #endif /* ifndef MANAGE_H */

159
misc.c

@ -57,27 +57,29 @@ Base64Encode(const char *input, int input_len, char **output)
if (input_len == 0) if (input_len == 0)
{ {
/* set output to empty string -- matches the behavior in openvpn */ /* set output to empty string -- matches the behavior in openvpn */
*output = calloc (1, sizeof(char)); *output = calloc(1, sizeof(char));
return TRUE; return TRUE;
} }
if (!CryptBinaryToStringA((const BYTE *) input, (DWORD) input_len, if (!CryptBinaryToStringA((const BYTE *) input, (DWORD) input_len,
flags, NULL, &output_len) || output_len == 0) flags, NULL, &output_len) || output_len == 0)
{ {
#ifdef DEBUG #ifdef DEBUG
PrintDebug (L"Error in CryptBinaryToStringA: input = '%.*hs'", input_len, input); PrintDebug(L"Error in CryptBinaryToStringA: input = '%.*hs'", input_len, input);
#endif #endif
*output = NULL; *output = NULL;
return FALSE; return FALSE;
} }
*output = (char *)malloc(output_len); *output = (char *)malloc(output_len);
if (*output == NULL) if (*output == NULL)
{
return FALSE; return FALSE;
}
if (!CryptBinaryToStringA((const BYTE *) input, (DWORD) input_len, if (!CryptBinaryToStringA((const BYTE *) input, (DWORD) input_len,
flags, *output, &output_len)) flags, *output, &output_len))
{ {
#ifdef DEBUG #ifdef DEBUG
PrintDebug (L"Error in CryptBinaryToStringA: input = '%.*hs'", input_len, input); PrintDebug(L"Error in CryptBinaryToStringA: input = '%.*hs'", input_len, input);
#endif #endif
free(*output); free(*output);
*output = NULL; *output = NULL;
@ -100,7 +102,7 @@ Base64Decode(const char *input, char **output)
{ {
DWORD len; DWORD len;
PrintDebug (L"decoding %hs", input); PrintDebug(L"decoding %hs", input);
if (!CryptStringToBinaryA(input, 0, CRYPT_STRING_BASE64_ANY, if (!CryptStringToBinaryA(input, 0, CRYPT_STRING_BASE64_ANY,
NULL, &len, NULL, NULL) || len == 0) NULL, &len, NULL, NULL) || len == 0)
{ {
@ -110,10 +112,12 @@ Base64Decode(const char *input, char **output)
*output = malloc(len + 1); *output = malloc(len + 1);
if (*output == NULL) if (*output == NULL)
{
return -1; return -1;
}
if (!CryptStringToBinaryA(input, 0, if (!CryptStringToBinaryA(input, 0,
CRYPT_STRING_BASE64, (BYTE *) *output, &len, NULL, NULL)) CRYPT_STRING_BASE64, (BYTE *) *output, &len, NULL, NULL))
{ {
free(*output); free(*output);
*output = NULL; *output = NULL;
@ -122,7 +126,7 @@ Base64Decode(const char *input, char **output)
/* NUL terminate output */ /* NUL terminate output */
(*output)[len] = '\0'; (*output)[len] = '\0';
PrintDebug (L"Decoded output %hs", *output); PrintDebug(L"Decoded output %hs", *output);
return len; return len;
} }
@ -140,19 +144,27 @@ GetDlgItemTextUtf8(HWND hDlg, int id, LPSTR *str, int *len)
ucs2_len = GetWindowTextLength(GetDlgItem(hDlg, id)) + 1; ucs2_len = GetWindowTextLength(GetDlgItem(hDlg, id)) + 1;
if (ucs2_len == 1) if (ucs2_len == 1)
{
goto out; goto out;
}
ucs2_str = malloc(ucs2_len * sizeof(*ucs2_str)); ucs2_str = malloc(ucs2_len * sizeof(*ucs2_str));
if (ucs2_str == NULL) if (ucs2_str == NULL)
{
goto out; goto out;
}
if (GetDlgItemText(hDlg, id, ucs2_str, ucs2_len) == 0) if (GetDlgItemText(hDlg, id, ucs2_str, ucs2_len) == 0)
{
goto out; goto out;
}
utf8_len = WideCharToMultiByte(CP_UTF8, 0, ucs2_str, -1, NULL, 0, NULL, NULL); utf8_len = WideCharToMultiByte(CP_UTF8, 0, ucs2_str, -1, NULL, 0, NULL, NULL);
utf8_str = malloc(utf8_len); utf8_str = malloc(utf8_len);
if (utf8_str == NULL) if (utf8_str == NULL)
{
goto out; goto out;
}
WideCharToMultiByte(CP_UTF8, 0, ucs2_str, -1, utf8_str, utf8_len, NULL, NULL); WideCharToMultiByte(CP_UTF8, 0, ucs2_str, -1, utf8_str, utf8_len, NULL, NULL);
@ -255,7 +267,7 @@ out:
* Generate a management command from double user inputs and send it * Generate a management command from double user inputs and send it
*/ */
BOOL BOOL
ManagementCommandFromTwoInputsBase64(connection_t *c, LPCSTR fmt, HWND hDlg,int id, int id2) ManagementCommandFromTwoInputsBase64(connection_t *c, LPCSTR fmt, HWND hDlg, int id, int id2)
{ {
BOOL retval = FALSE; BOOL retval = FALSE;
LPSTR input, input2, input_b64, input2_b64, cmd; LPSTR input, input2, input_b64, input2_b64, cmd;
@ -268,9 +280,13 @@ ManagementCommandFromTwoInputsBase64(connection_t *c, LPCSTR fmt, HWND hDlg,int
GetDlgItemTextUtf8(hDlg, id2, &input2, &input2_len); GetDlgItemTextUtf8(hDlg, id2, &input2, &input2_len);
if (!Base64Encode(input, input_len, &input_b64)) if (!Base64Encode(input, input_len, &input_b64))
{
goto out; goto out;
}
if (!Base64Encode(input2, input2_len, &input2_b64)) if (!Base64Encode(input2, input2_len, &input2_b64))
{
goto out; goto out;
}
cmd_len = strlen(input_b64) + strlen(input2_b64) + strlen(fmt); cmd_len = strlen(input_b64) + strlen(input2_b64) + strlen(fmt);
cmd = malloc(cmd_len); cmd = malloc(cmd_len);
@ -284,9 +300,13 @@ ManagementCommandFromTwoInputsBase64(connection_t *c, LPCSTR fmt, HWND hDlg,int
out: out:
/* Clear buffers with potentially secret content */ /* Clear buffers with potentially secret content */
if (input_b64) if (input_b64)
{
memset(input_b64, 0, strlen(input_b64)); memset(input_b64, 0, strlen(input_b64));
}
if (input2_b64) if (input2_b64)
{
memset(input2_b64, 0, strlen(input2_b64)); memset(input2_b64, 0, strlen(input2_b64));
}
free(input_b64); free(input_b64);
free(input2_b64); free(input2_b64);
@ -310,7 +330,7 @@ out:
* Generate a management command from base64-encoded user inputs and send it * Generate a management command from base64-encoded user inputs and send it
*/ */
BOOL BOOL
ManagementCommandFromInputBase64(connection_t* c, LPCSTR fmt, HWND hDlg, int id) ManagementCommandFromInputBase64(connection_t *c, LPCSTR fmt, HWND hDlg, int id)
{ {
BOOL retval = FALSE; BOOL retval = FALSE;
LPSTR input, input_b64, cmd; LPSTR input, input_b64, cmd;
@ -321,7 +341,9 @@ ManagementCommandFromInputBase64(connection_t* c, LPCSTR fmt, HWND hDlg, int id)
GetDlgItemTextUtf8(hDlg, id, &input, &input_len); GetDlgItemTextUtf8(hDlg, id, &input, &input_len);
if (!Base64Encode(input, input_len, &input_b64)) if (!Base64Encode(input, input_len, &input_b64))
{
goto out; goto out;
}
cmd_len = strlen(input_b64) + strlen(fmt); cmd_len = strlen(input_b64) + strlen(fmt);
cmd = malloc(cmd_len); cmd = malloc(cmd_len);
@ -335,7 +357,9 @@ ManagementCommandFromInputBase64(connection_t* c, LPCSTR fmt, HWND hDlg, int id)
out: out:
/* Clear buffers with potentially secret content */ /* Clear buffers with potentially secret content */
if (input_b64) if (input_b64)
{
memset(input_b64, 0, strlen(input_b64)); memset(input_b64, 0, strlen(input_b64));
}
free(input_b64); free(input_b64);
if (input_len) if (input_len)
@ -365,20 +389,26 @@ EnsureDirExists(LPTSTR dir)
{ {
LPTSTR pos = _tcsrchr(dir, '\\'); LPTSTR pos = _tcsrchr(dir, '\\');
if (pos == NULL) if (pos == NULL)
{
return FALSE; return FALSE;
}
*pos = '\0'; *pos = '\0';
BOOL ret = EnsureDirExists(dir); BOOL ret = EnsureDirExists(dir);
*pos = '\\'; *pos = '\\';
if (ret == FALSE) if (ret == FALSE)
{
return FALSE; return FALSE;
}
} }
else if (error != ERROR_FILE_NOT_FOUND) else if (error != ERROR_FILE_NOT_FOUND)
{
return FALSE; return FALSE;
}
/* No error if directory already exists */ /* No error if directory already exists */
return (CreateDirectory(dir, NULL) == TRUE return (CreateDirectory(dir, NULL) == TRUE
|| GetLastError() == ERROR_ALREADY_EXISTS); || GetLastError() == ERROR_ALREADY_EXISTS);
} }
return (attr & FILE_ATTRIBUTE_DIRECTORY ? TRUE : FALSE); return (attr & FILE_ATTRIBUTE_DIRECTORY ? TRUE : FALSE);
@ -425,13 +455,17 @@ ForceForegroundWindow(HWND hWnd)
* Set scale factor of windows in pixels. Scale = 100% for dpi = 96 * Set scale factor of windows in pixels. Scale = 100% for dpi = 96
*/ */
void void
DpiSetScale(options_t* options, UINT dpix) DpiSetScale(options_t *options, UINT dpix)
{ {
/* scale factor in percentage compared to the reference dpi of 96 */ /* scale factor in percentage compared to the reference dpi of 96 */
if (dpix != 0) if (dpix != 0)
{
options->dpi_scale = MulDiv(dpix, 100, 96); options->dpi_scale = MulDiv(dpix, 100, 96);
}
else else
{
options->dpi_scale = 100; options->dpi_scale = 100;
}
PrintDebug(L"DPI scale set to %u", options->dpi_scale); PrintDebug(L"DPI scale set to %u", options->dpi_scale);
} }
@ -442,19 +476,22 @@ DpiSetScale(options_t* options, UINT dpix)
* in its SID. Assumes the caller is not impersonating and has access to open its own * in its SID. Assumes the caller is not impersonating and has access to open its own
* process token. * process token.
*/ */
BOOL IsUserAdmin(VOID) BOOL
IsUserAdmin(VOID)
{ {
BOOL b; BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
PSID AdministratorsGroup; PSID AdministratorsGroup;
b = AllocateAndInitializeSid (&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
&AdministratorsGroup); &AdministratorsGroup);
if(b) if (b)
{ {
if (!CheckTokenMembership(NULL, AdministratorsGroup, &b)) if (!CheckTokenMembership(NULL, AdministratorsGroup, &b))
{
b = FALSE; b = FALSE;
}
FreeSid(AdministratorsGroup); FreeSid(AdministratorsGroup);
} }
@ -462,15 +499,15 @@ BOOL IsUserAdmin(VOID)
} }
HANDLE HANDLE
InitSemaphore (WCHAR *name) InitSemaphore(WCHAR *name)
{ {
HANDLE semaphore = NULL; HANDLE semaphore = NULL;
semaphore = CreateSemaphore (NULL, 1, 1, name); semaphore = CreateSemaphore(NULL, 1, 1, name);
if (!semaphore) if (!semaphore)
{ {
MessageBoxW (NULL, L"Error creating semaphore", TEXT(PACKAGE_NAME), MB_OK); MessageBoxW(NULL, L"Error creating semaphore", TEXT(PACKAGE_NAME), MB_OK);
#ifdef DEBUG #ifdef DEBUG
PrintDebug (L"InitSemaphore: CreateSemaphore failed [error = %lu]", GetLastError()); PrintDebug(L"InitSemaphore: CreateSemaphore failed [error = %lu]", GetLastError());
#endif #endif
} }
return semaphore; return semaphore;
@ -488,17 +525,17 @@ CloseSemaphore(HANDLE sem)
/* Check access rights on an existing file */ /* Check access rights on an existing file */
BOOL BOOL
CheckFileAccess (const TCHAR *path, int access) CheckFileAccess(const TCHAR *path, int access)
{ {
HANDLE h; HANDLE h;
bool ret = FALSE; bool ret = FALSE;
h = CreateFile (path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, h = CreateFile(path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
if ( h != INVALID_HANDLE_VALUE ) if (h != INVALID_HANDLE_VALUE)
{ {
ret = TRUE; ret = TRUE;
CloseHandle (h); CloseHandle(h);
} }
return ret; return ret;
@ -514,17 +551,23 @@ WidenEx(UINT codepage, const char *str)
{ {
WCHAR *wstr = NULL; WCHAR *wstr = NULL;
if (!str) if (!str)
{
return wstr; return wstr;
}
int nch = MultiByteToWideChar(codepage, 0, str, -1, NULL, 0); int nch = MultiByteToWideChar(codepage, 0, str, -1, NULL, 0);
if (nch > 0) if (nch > 0)
{
wstr = malloc(sizeof(WCHAR) * nch); wstr = malloc(sizeof(WCHAR) * nch);
}
if (wstr) if (wstr)
{
nch = MultiByteToWideChar(codepage, 0, str, -1, wstr, nch); nch = MultiByteToWideChar(codepage, 0, str, -1, wstr, nch);
}
if (nch == 0 && wstr) if (nch == 0 && wstr)
{ {
free (wstr); free(wstr);
wstr = NULL; wstr = NULL;
} }
@ -545,7 +588,9 @@ BOOL
validate_input(const WCHAR *input, const WCHAR *exclude) validate_input(const WCHAR *input, const WCHAR *exclude)
{ {
if (!exclude) if (!exclude)
{
exclude = L"\n"; exclude = L"\n";
}
return (wcspbrk(input, exclude) == NULL); return (wcspbrk(input, exclude) == NULL);
} }
@ -556,17 +601,27 @@ wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WC
int n = 0; int n = 0;
if (!dest || len == 0) if (!dest || len == 0)
{
return; return;
}
if (src1 && src2 && src1[0] && src2[0]) if (src1 && src2 && src1[0] && src2[0])
{
n = swprintf(dest, len, L"%ls%ls%ls", src1, sep, src2); n = swprintf(dest, len, L"%ls%ls%ls", src1, sep, src2);
}
else if (src1 && src1[0]) else if (src1 && src1[0])
{
n = swprintf(dest, len, L"%ls", src1); n = swprintf(dest, len, L"%ls", src1);
}
else if (src2 && src2[0]) else if (src2 && src2[0])
{
n = swprintf(dest, len, L"%ls", src2); n = swprintf(dest, len, L"%ls", src2);
}
if (n < 0 || n >= len) /*swprintf failed */ if (n < 0 || n >= len) /*swprintf failed */
{
n = 0; n = 0;
}
dest[n] = L'\0'; dest[n] = L'\0';
} }
@ -594,7 +649,9 @@ url_decode(const char *src)
char *o; char *o;
if (!out) if (!out)
{
return NULL; return NULL;
}
for (o = out; *s; o++) for (o = out; *s; o++)
{ {
@ -618,7 +675,9 @@ md_init(md_ctx *ctx, ALG_ID hash_type)
DWORD status = 0; DWORD status = 0;
if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
goto err; goto err;
}
if (!CryptCreateHash(ctx->prov, hash_type, 0, 0, &ctx->hash)) if (!CryptCreateHash(ctx->prov, hash_type, 0, 0, &ctx->hash))
{ {
CryptReleaseContext(ctx->prov, 0); CryptReleaseContext(ctx->prov, 0);
@ -684,7 +743,7 @@ open_url(const wchar_t *url)
extern options_t o; extern options_t o;
void void
ImportConfigFile(const TCHAR* source, bool prompt_user) ImportConfigFile(const TCHAR *source, bool prompt_user)
{ {
TCHAR fileName[MAX_PATH] = _T(""); TCHAR fileName[MAX_PATH] = _T("");
TCHAR ext[MAX_PATH] = _T(""); TCHAR ext[MAX_PATH] = _T("");
@ -723,7 +782,7 @@ ImportConfigFile(const TCHAR* source, bool prompt_user)
{ {
if (prompt_user if (prompt_user
&& ShowLocalizedMsgEx(MB_YESNO|MB_TOPMOST, o.hWnd, TEXT(PACKAGE_NAME), && ShowLocalizedMsgEx(MB_YESNO|MB_TOPMOST, o.hWnd, TEXT(PACKAGE_NAME),
IDS_NFO_IMPORT_SOURCE, fileName) == IDNO) IDS_NFO_IMPORT_SOURCE, fileName) == IDNO)
{ {
return; return;
} }
@ -741,10 +800,10 @@ ImportConfigFile(const TCHAR* source, bool prompt_user)
if (!CopyFile(source, destination, no_overwrite)) if (!CopyFile(source, destination, no_overwrite))
{ {
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Copy file <%ls> to <%ls> failed (error = %lu)", MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Copy file <%ls> to <%ls> failed (error = %lu)",
source, destination, GetLastError()); source, destination, GetLastError());
ShowLocalizedMsg(IDS_ERR_IMPORT_FAILED, destination); ShowLocalizedMsg(IDS_ERR_IMPORT_FAILED, destination);
return; return;
} }
ShowTrayBalloon(LoadLocalizedString(IDS_NFO_IMPORT_SUCCESS), fileName); ShowTrayBalloon(LoadLocalizedString(IDS_NFO_IMPORT_SUCCESS), fileName);
@ -900,7 +959,9 @@ MsgToEventLog(WORD type, wchar_t *format, ...)
{ {
o.event_log = RegisterEventSource(NULL, TEXT(PACKAGE_NAME)); o.event_log = RegisterEventSource(NULL, TEXT(PACKAGE_NAME));
if (!o.event_log) if (!o.event_log)
{
return; return;
}
} }
va_list args; va_list args;
@ -908,7 +969,10 @@ MsgToEventLog(WORD type, wchar_t *format, ...)
int nchar = vswprintf(buf, size-1, format, args); int nchar = vswprintf(buf, size-1, format, args);
va_end(args); va_end(args);
if (nchar == -1) return; if (nchar == -1)
{
return;
}
buf[size - 1] = '\0'; buf[size - 1] = '\0';
@ -954,11 +1018,13 @@ GetPLAPRegistrationStatus(void)
wchar_t dllPath[MAX_PATH]; wchar_t dllPath[MAX_PATH];
_sntprintf_0(dllPath, L"%ls%ls", o.install_path, L"bin\\libopenvpn_plap.dll"); _sntprintf_0(dllPath, L"%ls%ls", o.install_path, L"bin\\libopenvpn_plap.dll");
if (!CheckFileAccess(dllPath, GENERIC_READ)) { if (!CheckFileAccess(dllPath, GENERIC_READ))
{
res = -1; res = -1;
} }
else if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID\\"PLAP_CLASSID, 0, KEY_READ, &regkey) else if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID\\"PLAP_CLASSID, 0, KEY_READ, &regkey)
== ERROR_SUCCESS) { == ERROR_SUCCESS)
{
res = 1; res = 1;
RegCloseKey(regkey); RegCloseKey(regkey);
} }
@ -975,19 +1041,24 @@ SetPLAPRegistration(BOOL value)
/* Run only if the state has changed */ /* Run only if the state has changed */
int plap_status = GetPLAPRegistrationStatus(); int plap_status = GetPLAPRegistrationStatus();
if (plap_status > 0 && (BOOL) plap_status == value) return 0; if (plap_status > 0 && (BOOL) plap_status == value)
{
return 0;
}
if (value) { if (value)
{
_sntprintf_0( params, L"import \"%ls%ls\"", o.install_path, L"bin\\openvpn-plap-install.reg"); _sntprintf_0( params, L"import \"%ls%ls\"", o.install_path, L"bin\\openvpn-plap-install.reg");
} }
else { else
{
_sntprintf_0( params, L"import \"%ls%ls\"", o.install_path, L"bin\\openvpn-plap-uninstall.reg"); _sntprintf_0( params, L"import \"%ls%ls\"", o.install_path, L"bin\\openvpn-plap-uninstall.reg");
} }
res = RunAsAdmin(cmd, params); res = RunAsAdmin(cmd, params);
if (res != 0) if (res != 0)
{ {
ShowLocalizedMsg(value? IDS_ERR_PLAP_REG : IDS_ERR_PLAP_UNREG, res); ShowLocalizedMsg(value ? IDS_ERR_PLAP_REG : IDS_ERR_PLAP_UNREG, res);
} }
return res; return res;
} }
@ -1003,7 +1074,7 @@ RunAsAdmin(const WCHAR *cmd, const WCHAR *params)
SHELLEXECUTEINFO shinfo; SHELLEXECUTEINFO shinfo;
DWORD status = -1; DWORD status = -1;
CLEAR (shinfo); CLEAR(shinfo);
shinfo.cbSize = sizeof(shinfo); shinfo.cbSize = sizeof(shinfo);
shinfo.fMask = SEE_MASK_NOCLOSEPROCESS; shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shinfo.hwnd = NULL; shinfo.hwnd = NULL;
@ -1038,7 +1109,7 @@ OVPNMsgWait(DWORD timeout, HWND hdlg)
if (MsgWaitForMultipleObjectsEx(0, NULL, end - now, QS_ALLINPUT, MWMO_INPUTAVAILABLE) == WAIT_OBJECT_0) if (MsgWaitForMultipleObjectsEx(0, NULL, end - now, QS_ALLINPUT, MWMO_INPUTAVAILABLE) == WAIT_OBJECT_0)
{ {
MSG msg; MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{ {
if (msg.message == WM_QUIT) if (msg.message == WM_QUIT)
{ {
@ -1069,14 +1140,20 @@ GetRandomPassword(char *buf, size_t len)
unsigned i; unsigned i;
if (!CryptAcquireContext(&cp, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT)) if (!CryptAcquireContext(&cp, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT))
{
return FALSE; return FALSE;
}
if (!CryptGenRandom(cp, len, (PBYTE) buf)) if (!CryptGenRandom(cp, len, (PBYTE) buf))
{
goto out; goto out;
}
/* Make sure all values are between 0x21 '!' and 0x7e '~' */ /* Make sure all values are between 0x21 '!' and 0x7e '~' */
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
{
buf[i] = (buf[i] & 0x5d) + 0x21; buf[i] = (buf[i] & 0x5d) + 0x21;
}
retval = TRUE; retval = TRUE;
out: out:

@ -27,30 +27,44 @@
#include "options.h" #include "options.h"
BOOL ManagementCommandFromInput(connection_t *, LPCSTR, HWND, int); BOOL ManagementCommandFromInput(connection_t *, LPCSTR, HWND, int);
BOOL ManagementCommandFromTwoInputsBase64(connection_t*, LPCSTR, HWND, int, int);
BOOL ManagementCommandFromTwoInputsBase64(connection_t *, LPCSTR, HWND, int, int);
BOOL ManagementCommandFromInputBase64(connection_t *, LPCSTR, HWND, int); BOOL ManagementCommandFromInputBase64(connection_t *, LPCSTR, HWND, int);
BOOL EnsureDirExists(LPTSTR); BOOL EnsureDirExists(LPTSTR);
BOOL streq(LPCSTR, LPCSTR); BOOL streq(LPCSTR, LPCSTR);
BOOL strbegins(const char *str, const char *begin); BOOL strbegins(const char *str, const char *begin);
BOOL wcsbegins(LPCWSTR, LPCWSTR); BOOL wcsbegins(LPCWSTR, LPCWSTR);
BOOL ForceForegroundWindow(HWND); BOOL ForceForegroundWindow(HWND);
void DpiSetScale(options_t*, UINT dpix);
void DpiSetScale(options_t *, UINT dpix);
BOOL IsUserAdmin(VOID); BOOL IsUserAdmin(VOID);
HANDLE InitSemaphore (WCHAR *);
BOOL CheckFileAccess (const TCHAR *path, int access); HANDLE InitSemaphore(WCHAR *);
BOOL CheckFileAccess(const TCHAR *path, int access);
BOOL Base64Encode(const char *input, int input_len, char **output); BOOL Base64Encode(const char *input, int input_len, char **output);
int Base64Decode(const char *input, char **output); int Base64Decode(const char *input, char **output);
WCHAR *Widen(const char *utf8); WCHAR *Widen(const char *utf8);
WCHAR *WidenEx(UINT codepage, const char *utf8); WCHAR *WidenEx(UINT codepage, const char *utf8);
BOOL validate_input(const WCHAR *input, const WCHAR *exclude); BOOL validate_input(const WCHAR *input, const WCHAR *exclude);
/* Concatenate two wide strings with a separator */ /* Concatenate two wide strings with a separator */
void wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WCHAR *sep); void wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WCHAR *sep);
void CloseSemaphore(HANDLE sem); void CloseSemaphore(HANDLE sem);
/* Close a handle if not null or invalid */ /* Close a handle if not null or invalid */
void CloseHandleEx(LPHANDLE h); void CloseHandleEx(LPHANDLE h);
@ -61,25 +75,27 @@ char *url_decode(const char *src);
/* digest functions */ /* digest functions */
typedef struct md_ctx { typedef struct md_ctx {
HCRYPTPROV prov; HCRYPTPROV prov;
HCRYPTHASH hash; HCRYPTHASH hash;
} md_ctx; } md_ctx;
DWORD md_init(md_ctx *ctx, ALG_ID hash_type); DWORD md_init(md_ctx *ctx, ALG_ID hash_type);
DWORD md_update(md_ctx *ctx, const BYTE *data, size_t size); DWORD md_update(md_ctx *ctx, const BYTE *data, size_t size);
DWORD md_final(md_ctx *ctx, BYTE *md); DWORD md_final(md_ctx *ctx, BYTE *md);
/* Open specified http/https URL using ShellExecute. */ /* Open specified http/https URL using ShellExecute. */
BOOL open_url(const wchar_t *url); BOOL open_url(const wchar_t *url);
void ImportConfigFile(const TCHAR* path, bool prompt_user); void ImportConfigFile(const TCHAR *path, bool prompt_user);
/* /*
* Helper function to convert UCS-2 text from a dialog item to UTF-8. * Helper function to convert UCS-2 text from a dialog item to UTF-8.
* Caller must free *str if *len != 0. * Caller must free *str if *len != 0.
*/ */
BOOL BOOL
GetDlgItemTextUtf8(HWND hDlg, int id, LPSTR* str, int* len); GetDlgItemTextUtf8(HWND hDlg, int id, LPSTR *str, int *len);
/* Return escaped copy of a string */ /* Return escaped copy of a string */
char *escape_string(const char *str); char *escape_string(const char *str);
@ -157,6 +173,7 @@ bool OVPNMsgWait(DWORD timeout, HWND hdlg);
bool GetRandomPassword(char *buf, size_t len); bool GetRandomPassword(char *buf, size_t len);
void ResetPasswordReveal(HWND edit, HWND btn, WPARAM wParam); void ResetPasswordReveal(HWND edit, HWND btn, WPARAM wParam);
void ChangePasswordVisibility(HWND edit, HWND btn, WPARAM wParam); void ChangePasswordVisibility(HWND edit, HWND btn, WPARAM wParam);
#endif #endif /* ifndef MISC_H */

@ -409,4 +409,4 @@
/* Timer IDs */ /* Timer IDs */
#define IDT_STOP_TIMER 2500 /* Timer used to trigger force termination */ #define IDT_STOP_TIMER 2500 /* Timer used to trigger force termination */
#endif #endif /* ifndef OPENVPN_GUI_RES_H */

File diff suppressed because it is too large Load Diff

@ -26,33 +26,51 @@
#include "options.h" #include "options.h"
#define TRY_SETPROP(hwnd, name, p) \ #define TRY_SETPROP(hwnd, name, p) \
do { if (SetPropW(hwnd, name, p)) break; \ do { if (SetPropW(hwnd, name, p)) break; \
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs:%d GetProp returned null", \ MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs:%d GetProp returned null", \
__func__, __LINE__); \ __func__, __LINE__); \
EndDialog(hwnd, IDABORT); \ EndDialog(hwnd, IDABORT); \
return false; \ return false; \
} while(0) } while(0)
BOOL StartOpenVPN(connection_t *); BOOL StartOpenVPN(connection_t *);
void StopOpenVPN(connection_t *); void StopOpenVPN(connection_t *);
void DetachOpenVPN(connection_t *); void DetachOpenVPN(connection_t *);
void SuspendOpenVPN(int config); void SuspendOpenVPN(int config);
void RestartOpenVPN(connection_t *); void RestartOpenVPN(connection_t *);
void ReleaseOpenVPN(connection_t *); void ReleaseOpenVPN(connection_t *);
BOOL CheckVersion(); BOOL CheckVersion();
void SetStatusWinIcon(HWND hwndDlg, int IconID); void SetStatusWinIcon(HWND hwndDlg, int IconID);
void OnReady(connection_t *, char *); void OnReady(connection_t *, char *);
void OnHold(connection_t *, char *); void OnHold(connection_t *, char *);
void OnLogLine(connection_t *, char *); void OnLogLine(connection_t *, char *);
void OnStateChange(connection_t *, char *); void OnStateChange(connection_t *, char *);
void OnPassword(connection_t *, char *); void OnPassword(connection_t *, char *);
void OnStop(connection_t *, char *); void OnStop(connection_t *, char *);
void OnNeedOk(connection_t *, char *); void OnNeedOk(connection_t *, char *);
void OnNeedStr(connection_t *, char *); void OnNeedStr(connection_t *, char *);
void OnEcho(connection_t *, char *); void OnEcho(connection_t *, char *);
void OnByteCount(connection_t *, char *); void OnByteCount(connection_t *, char *);
void OnInfoMsg(connection_t*, char*);
void OnInfoMsg(connection_t *, char *);
void OnTimeout(connection_t *, char *); void OnTimeout(connection_t *, char *);
void ResetSavePasswords(connection_t *); void ResetSavePasswords(connection_t *);
@ -66,7 +84,7 @@ extern const TCHAR *cfgProp;
#define ERROR_MESSAGE_TYPE 0x20000003 #define ERROR_MESSAGE_TYPE 0x20000003
/* Write a line to status window and optionally to the log file */ /* Write a line to status window and optionally to the log file */
void WriteStatusLog (connection_t *c, const WCHAR *prefix, const WCHAR *line, BOOL fileio); void WriteStatusLog(connection_t *c, const WCHAR *prefix, const WCHAR *line, BOOL fileio);
#define FLAG_CR_TYPE_SCRV1 0x1 /* static challenege */ #define FLAG_CR_TYPE_SCRV1 0x1 /* static challenege */
#define FLAG_CR_TYPE_CRV1 0x2 /* dynamic challenege */ #define FLAG_CR_TYPE_CRV1 0x2 /* dynamic challenege */
@ -78,12 +96,12 @@ void WriteStatusLog (connection_t *c, const WCHAR *prefix, const WCHAR *line, BO
#define FLAG_CR_TYPE_CRTEXT 0x80 /* crtext */ #define FLAG_CR_TYPE_CRTEXT 0x80 /* crtext */
typedef struct { typedef struct {
connection_t* c; connection_t *c;
unsigned int flags; unsigned int flags;
char* str; char *str;
char* id; char *id;
char* user; char *user;
char* cr_response; char *cr_response;
} auth_param_t; } auth_param_t;
/* /*
@ -92,10 +110,10 @@ typedef struct {
* even on error. * even on error.
*/ */
BOOL BOOL
parse_dynamic_cr(const char* str, auth_param_t* param); parse_dynamic_cr(const char *str, auth_param_t *param);
void void
free_auth_param(auth_param_t* param); free_auth_param(auth_param_t *param);
/* /*
* Given an OpenVPN state as reported by the management interface * Given an OpenVPN state as reported by the management interface
@ -103,4 +121,4 @@ free_auth_param(auth_param_t* param);
*/ */
int daemon_state_resid(const char *name); int daemon_state_resid(const char *name);
#endif #endif /* ifndef OPENVPN_H */

@ -50,28 +50,34 @@ match(const WIN32_FIND_DATA *find, const TCHAR *ext)
int i; int i;
if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
return match_dir; return match_dir;
}
if (ext_len == 0) if (ext_len == 0)
{
return match_file; return match_file;
}
i = _tcslen(find->cFileName) - ext_len - 1; i = _tcslen(find->cFileName) - ext_len - 1;
if (i > 0 && find->cFileName[i] == '.' if (i > 0 && find->cFileName[i] == '.'
&& _tcsicmp(find->cFileName + i + 1, ext) == 0) && _tcsicmp(find->cFileName + i + 1, ext) == 0)
{
return match_file; return match_file;
}
return match_false; return match_false;
} }
static bool static bool
CheckReadAccess (const TCHAR *dir, const TCHAR *file) CheckReadAccess(const TCHAR *dir, const TCHAR *file)
{ {
TCHAR path[MAX_PATH]; TCHAR path[MAX_PATH];
_sntprintf_0 (path, _T("%ls\\%ls"), dir, file); _sntprintf_0(path, _T("%ls\\%ls"), dir, file);
return CheckFileAccess (path, GENERIC_READ); return CheckFileAccess(path, GENERIC_READ);
} }
static int static int
@ -80,7 +86,9 @@ ConfigAlreadyExists(TCHAR *newconfig)
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (_tcsicmp(c->config_file, newconfig) == 0) if (_tcsicmp(c->config_file, newconfig) == 0)
{
return true; return true;
}
} }
return false; return false;
} }
@ -148,9 +156,13 @@ AddConfigFileToList(int group, const TCHAR *filename, const TCHAR *config_dir)
else else
{ {
if (IsAuthPassSaved(c->config_name)) if (IsAuthPassSaved(c->config_name))
{
c->flags |= FLAG_SAVE_AUTH_PASS; c->flags |= FLAG_SAVE_AUTH_PASS;
}
if (IsKeyPassSaved(c->config_name)) if (IsKeyPassSaved(c->config_name))
{
c->flags |= FLAG_SAVE_KEY_PASS; c->flags |= FLAG_SAVE_KEY_PASS;
}
} }
if (o.disable_popup_messages) if (o.disable_popup_messages)
{ {
@ -214,7 +226,9 @@ ActivateConfigGroups(void)
/* children is a counter re-used for activation, menu indexing etc. -- reset before use */ /* children is a counter re-used for activation, menu indexing etc. -- reset before use */
for (int i = 0; i < o.num_groups; i++) for (int i = 0; i < o.num_groups; i++)
{
o.groups[i].children = 0; o.groups[i].children = 0;
}
/* count children of each group -- this includes groups /* count children of each group -- this includes groups
* and configs which have it as parent * and configs which have it as parent
@ -229,7 +243,9 @@ ActivateConfigGroups(void)
config_group_t *this = &o.groups[i]; config_group_t *this = &o.groups[i];
config_group_t *parent = PARENT_GROUP(this); config_group_t *parent = PARENT_GROUP(this);
if (parent) /* should be true as i = 0 is omitted */ if (parent) /* should be true as i = 0 is omitted */
{
parent->children++; parent->children++;
}
/* unless activated below the group stays inactive */ /* unless activated below the group stays inactive */
this->active = false; this->active = false;
@ -290,7 +306,9 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, int group, int flags)
_sntprintf_0(find_string, _T("%ls\\*"), config_dir); _sntprintf_0(find_string, _T("%ls\\*"), config_dir);
find_handle = FindFirstFile(find_string, &find_obj); find_handle = FindFirstFile(find_string, &find_obj);
if (find_handle == INVALID_HANDLE_VALUE) if (find_handle == INVALID_HANDLE_VALUE)
{
return; return;
}
/* Loop over each config file in config dir */ /* Loop over each config file in config dir */
do do
@ -301,11 +319,13 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, int group, int flags)
if (ConfigAlreadyExists(find_obj.cFileName)) if (ConfigAlreadyExists(find_obj.cFileName))
{ {
if (flags & FLAG_WARN_DUPLICATES) if (flags & FLAG_WARN_DUPLICATES)
{
ShowLocalizedMsg(IDS_ERR_CONFIG_EXIST, find_obj.cFileName); ShowLocalizedMsg(IDS_ERR_CONFIG_EXIST, find_obj.cFileName);
}
continue; continue;
} }
if (CheckReadAccess (config_dir, find_obj.cFileName)) if (CheckReadAccess(config_dir, find_obj.cFileName))
{ {
AddConfigFileToList(group, find_obj.cFileName, config_dir); AddConfigFileToList(group, find_obj.cFileName, config_dir);
} }
@ -316,11 +336,15 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, int group, int flags)
/* optionally loop over each subdir */ /* optionally loop over each subdir */
if (recurse_depth < 1) if (recurse_depth < 1)
{
return; return;
}
find_handle = FindFirstFile (find_string, &find_obj); find_handle = FindFirstFile(find_string, &find_obj);
if (find_handle == INVALID_HANDLE_VALUE) if (find_handle == INVALID_HANDLE_VALUE)
{
return; return;
}
do do
{ {
@ -389,13 +413,16 @@ IsSamePath(const wchar_t *path1, const wchar_t *path2)
BOOL ret = false; BOOL ret = false;
BY_HANDLE_FILE_INFORMATION info1, info2; BY_HANDLE_FILE_INFORMATION info1, info2;
if (_wcsicmp(path1, path2) == 0) return true; if (_wcsicmp(path1, path2) == 0)
{
return true;
}
if (GetFileInfo(path1, &info1) && GetFileInfo(path2, &info2)) if (GetFileInfo(path1, &info1) && GetFileInfo(path2, &info2))
{ {
ret = (info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber ret = (info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
&& info1.nFileIndexLow == info2.nFileIndexLow && info1.nFileIndexLow == info2.nFileIndexLow
&& info1.nFileIndexHigh == info2.nFileIndexHigh); && info1.nFileIndexHigh == info2.nFileIndexHigh);
} }
return ret; return ret;
@ -410,7 +437,9 @@ BuildFileList()
static int root_gp, system_gp, persistent_gp; static int root_gp, system_gp, persistent_gp;
if (o.silent_connection) if (o.silent_connection)
{
issue_warnings = false; issue_warnings = false;
}
/* /*
* If first time or no entries in the connection list reset groups and rescan * If first time or no entries in the connection list reset groups and rescan
@ -438,11 +467,11 @@ BuildFileList()
flags |= FLAG_WARN_DUPLICATES | FLAG_WARN_MAX_CONFIGS; flags |= FLAG_WARN_DUPLICATES | FLAG_WARN_MAX_CONFIGS;
} }
BuildFileList0 (o.config_dir, recurse_depth, root_gp, flags); BuildFileList0(o.config_dir, recurse_depth, root_gp, flags);
if (!IsSamePath(o.global_config_dir, o.config_dir)) if (!IsSamePath(o.global_config_dir, o.config_dir))
{ {
BuildFileList0 (o.global_config_dir, recurse_depth, system_gp, flags); BuildFileList0(o.global_config_dir, recurse_depth, system_gp, flags);
} }
if (o.service_state == service_connected if (o.service_state == service_connected
@ -450,12 +479,14 @@ BuildFileList()
{ {
if (!IsSamePath(o.config_auto_dir, o.config_dir)) if (!IsSamePath(o.config_auto_dir, o.config_dir))
{ {
BuildFileList0 (o.config_auto_dir, recurse_depth, persistent_gp, flags); BuildFileList0(o.config_auto_dir, recurse_depth, persistent_gp, flags);
} }
} }
if (o.num_configs == 0 && issue_warnings) if (o.num_configs == 0 && issue_warnings)
{
ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir); ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir);
}
ActivateConfigGroups(); ActivateConfigGroups();

@ -25,7 +25,9 @@
#include "main.h" #include "main.h"
void BuildFileList(void); void BuildFileList(void);
bool ConfigFileOptionExist(int, const char *); bool ConfigFileOptionExist(int, const char *);
void FreeConfigList(options_t *o); void FreeConfigList(options_t *o);
#endif #endif

@ -50,37 +50,37 @@
extern options_t o; extern options_t o;
static version_t static version_t
MakeVersion (short ma, short mi, short b, short r) MakeVersion(short ma, short mi, short b, short r)
{ {
version_t v = {ma, mi, b, r}; version_t v = {ma, mi, b, r};
return v; return v;
} }
static void static void
ExpandString (WCHAR *str, int max_len) ExpandString(WCHAR *str, int max_len)
{ {
WCHAR expanded_string[MAX_PATH]; WCHAR expanded_string[MAX_PATH];
int len = ExpandEnvironmentStringsW (str, expanded_string, _countof(expanded_string)); int len = ExpandEnvironmentStringsW(str, expanded_string, _countof(expanded_string));
if (len > max_len || len > (int) _countof(expanded_string)) if (len > max_len || len > (int) _countof(expanded_string))
{ {
PrintDebug (L"Failed to expanded env vars in '%ls'. String too long", str); PrintDebug(L"Failed to expanded env vars in '%ls'. String too long", str);
return; return;
} }
wcsncpy (str, expanded_string, max_len); wcsncpy(str, expanded_string, max_len);
} }
void void
ExpandOptions (void) ExpandOptions(void)
{ {
ExpandString (o.exe_path, _countof(o.exe_path)); ExpandString(o.exe_path, _countof(o.exe_path));
ExpandString (o.config_dir, _countof(o.config_dir)); ExpandString(o.config_dir, _countof(o.config_dir));
ExpandString (o.global_config_dir, _countof(o.global_config_dir)); ExpandString(o.global_config_dir, _countof(o.global_config_dir));
ExpandString (o.config_auto_dir, _countof(o.config_auto_dir)); ExpandString(o.config_auto_dir, _countof(o.config_auto_dir));
ExpandString (o.log_dir, _countof(o.log_dir)); ExpandString(o.log_dir, _countof(o.log_dir));
ExpandString (o.editor, _countof(o.editor)); ExpandString(o.editor, _countof(o.editor));
ExpandString (o.log_viewer, _countof(o.log_viewer)); ExpandString(o.log_viewer, _countof(o.log_viewer));
ExpandString (o.install_path, _countof(o.install_path)); ExpandString(o.install_path, _countof(o.install_path));
} }
static int static int
@ -157,8 +157,8 @@ add_option(options_t *options, int i, TCHAR **p)
++i; ++i;
_tcsncpy(options->priority_string, p[1], _countof(options->priority_string) - 1); _tcsncpy(options->priority_string, p[1], _countof(options->priority_string) - 1);
} }
else if ( (streq(p[0], _T("append_string")) || else if ( (streq(p[0], _T("append_string"))
streq(p[0], _T("log_append"))) && p[1] ) || streq(p[0], _T("log_append"))) && p[1])
{ {
++i; ++i;
options->log_append = _ttoi(p[1]) ? 1 : 0; options->log_append = _ttoi(p[1]) ? 1 : 0;
@ -181,22 +181,22 @@ add_option(options_t *options, int i, TCHAR **p)
else if (streq(p[0], _T("allow_edit")) && p[1]) else if (streq(p[0], _T("allow_edit")) && p[1])
{ {
++i; ++i;
PrintDebug (L"Deprecated option: '%ls' ignored.", p[0]); PrintDebug(L"Deprecated option: '%ls' ignored.", p[0]);
} }
else if (streq(p[0], _T("allow_service")) && p[1]) else if (streq(p[0], _T("allow_service")) && p[1])
{ {
++i; ++i;
PrintDebug (L"Deprecated option: '%ls' ignored.", p[0]); PrintDebug(L"Deprecated option: '%ls' ignored.", p[0]);
} }
else if (streq(p[0], _T("allow_password")) && p[1]) else if (streq(p[0], _T("allow_password")) && p[1])
{ {
++i; ++i;
PrintDebug (L"Deprecated option: '%ls' ignored.", p[0]); PrintDebug(L"Deprecated option: '%ls' ignored.", p[0]);
} }
else if (streq(p[0], _T("allow_proxy")) && p[1]) else if (streq(p[0], _T("allow_proxy")) && p[1])
{ {
++i; ++i;
PrintDebug (L"Deprecated option: '%ls' ignored.", p[0]); PrintDebug(L"Deprecated option: '%ls' ignored.", p[0]);
} }
else if (streq(p[0], _T("show_balloon")) && p[1]) else if (streq(p[0], _T("show_balloon")) && p[1])
{ {
@ -206,7 +206,7 @@ add_option(options_t *options, int i, TCHAR **p)
else if (streq(p[0], _T("service_only")) && p[1]) else if (streq(p[0], _T("service_only")) && p[1])
{ {
++i; ++i;
PrintDebug (L"Deprecated option: '%ls' ignored.", p[0]); PrintDebug(L"Deprecated option: '%ls' ignored.", p[0]);
} }
else if (streq(p[0], _T("show_script_window")) && p[1]) else if (streq(p[0], _T("show_script_window")) && p[1])
{ {
@ -221,7 +221,7 @@ add_option(options_t *options, int i, TCHAR **p)
else if (streq(p[0], _T("passphrase_attempts")) && p[1]) else if (streq(p[0], _T("passphrase_attempts")) && p[1])
{ {
++i; ++i;
PrintDebug (L"Deprecated option: '%ls' ignored.", p[0]); PrintDebug(L"Deprecated option: '%ls' ignored.", p[0]);
} }
else if (streq(p[0], _T("connectscript_timeout")) && p[1]) else if (streq(p[0], _T("connectscript_timeout")) && p[1])
{ {
@ -362,7 +362,9 @@ parse_argv(options_t *options, int argc, TCHAR **argv)
{ {
TCHAR *arg = argv[i + j]; TCHAR *arg = argv[i + j];
if (_tcsncmp(arg, _T("--"), 2) == 0) if (_tcsncmp(arg, _T("--"), 2) == 0)
{
break; break;
}
p[j] = arg; p[j] = arg;
} }
} }
@ -375,8 +377,8 @@ void
InitOptions(options_t *opt) InitOptions(options_t *opt)
{ {
CLEAR(*opt); CLEAR(*opt);
opt->netcmd_semaphore = InitSemaphore (NULL); opt->netcmd_semaphore = InitSemaphore(NULL);
opt->version = MakeVersion (PACKAGE_VERSION_RESOURCE); opt->version = MakeVersion(PACKAGE_VERSION_RESOURCE);
opt->clr_warning = RGB(0xff, 0, 0); opt->clr_warning = RGB(0xff, 0, 0);
opt->clr_error = RGB(0xff, 0, 0); opt->clr_error = RGB(0xff, 0, 0);
} }
@ -393,49 +395,67 @@ ProcessCommandLine(options_t *options, TCHAR *command_line)
do do
{ {
while (*pos == _T(' ')) while (*pos == _T(' '))
{
++pos; ++pos;
}
if (*pos == _T('\0')) if (*pos == _T('\0'))
{
break; break;
}
++argc; ++argc;
while (*pos != _T('\0') && *pos != _T(' ')) while (*pos != _T('\0') && *pos != _T(' '))
++pos; {
++pos;
}
} }
while (*pos != _T('\0')); while (*pos != _T('\0'));
if (argc == 0) if (argc == 0)
{
return; return;
}
/* Tokenize the arguments */ /* Tokenize the arguments */
argv = (TCHAR**) malloc(argc * sizeof(TCHAR*)); argv = (TCHAR **) malloc(argc * sizeof(TCHAR *));
pos = command_line; pos = command_line;
argc = 0; argc = 0;
do do
{ {
while (*pos == _T(' ')) while (*pos == _T(' '))
{
pos++; pos++;
}
if (*pos == _T('\0')) if (*pos == _T('\0'))
{
break; break;
}
if (*pos == _T('\"')) if (*pos == _T('\"'))
{ {
argv[argc++] = ++pos; argv[argc++] = ++pos;
while (*pos != _T('\0') && *pos != _T('\"')) while (*pos != _T('\0') && *pos != _T('\"'))
{
++pos; ++pos;
}
} }
else else
{ {
argv[argc++] = pos; argv[argc++] = pos;
while (*pos != _T('\0') && *pos != _T(' ')) while (*pos != _T('\0') && *pos != _T(' '))
{
++pos; ++pos;
}
} }
if (*pos == _T('\0')) if (*pos == _T('\0'))
{
break; break;
}
*pos++ = _T('\0'); *pos++ = _T('\0');
} }
@ -445,7 +465,7 @@ ProcessCommandLine(options_t *options, TCHAR *command_line)
free(argv); free(argv);
ExpandOptions (); ExpandOptions();
} }
@ -458,52 +478,58 @@ CountConnState(conn_state_t check)
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (c->state == check) if (c->state == check)
{
++count; ++count;
}
} }
return count; return count;
} }
connection_t* connection_t *
GetConnByManagement(SOCKET sk) GetConnByManagement(SOCKET sk)
{ {
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (c->manage.sk == sk) if (c->manage.sk == sk)
{
return c; return c;
}
} }
return NULL; return NULL;
} }
connection_t* connection_t *
GetConnByName(const WCHAR *name) GetConnByName(const WCHAR *name)
{ {
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (wcsicmp (c->config_file, name) == 0 if (wcsicmp(c->config_file, name) == 0
|| wcsicmp(c->config_name, name) == 0) || wcsicmp(c->config_name, name) == 0)
{
return c; return c;
}
} }
return NULL; return NULL;
} }
static BOOL static BOOL
BrowseFolder (const WCHAR* initial_path, WCHAR* selected_path, size_t selected_path_size) BrowseFolder(const WCHAR *initial_path, WCHAR *selected_path, size_t selected_path_size)
{ {
IFileOpenDialog* pfd; IFileOpenDialog *pfd;
HRESULT initResult, result, dialogResult = E_FAIL; HRESULT initResult, result, dialogResult = E_FAIL;
// Create dialog /* Create dialog */
initResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); initResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(initResult)) if (FAILED(initResult))
{ {
return false; return false;
} }
result = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, (void**)&pfd); result = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, (void **)&pfd);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
// Select folders, not files /* Select folders, not files */
DWORD dwOptions; DWORD dwOptions;
result = pfd->lpVtbl->GetOptions(pfd, &dwOptions); result = pfd->lpVtbl->GetOptions(pfd, &dwOptions);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
@ -512,24 +538,24 @@ BrowseFolder (const WCHAR* initial_path, WCHAR* selected_path, size_t selected_p
result = pfd->lpVtbl->SetOptions(pfd, dwOptions); result = pfd->lpVtbl->SetOptions(pfd, dwOptions);
} }
// Set initial path /* Set initial path */
IShellItem* psi; IShellItem *psi;
result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, (void**)&psi); result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, (void **)&psi);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
pfd->lpVtbl->SetFolder(pfd, psi); pfd->lpVtbl->SetFolder(pfd, psi);
psi->lpVtbl->Release(psi); psi->lpVtbl->Release(psi);
} }
// Show dialog and copy the selected file path if the user didn't cancel /* Show dialog and copy the selected file path if the user didn't cancel */
dialogResult = pfd->lpVtbl->Show(pfd, NULL); dialogResult = pfd->lpVtbl->Show(pfd, NULL);
if (SUCCEEDED(dialogResult)) if (SUCCEEDED(dialogResult))
{ {
IShellItem* psi; IShellItem *psi;
LPOLESTR path = NULL; LPOLESTR path = NULL;
result = pfd->lpVtbl->GetResult(pfd, &psi); result = pfd->lpVtbl->GetResult(pfd, &psi);
if(SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
result = psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &path); result = psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &path);
} }
@ -548,65 +574,71 @@ BrowseFolder (const WCHAR* initial_path, WCHAR* selected_path, size_t selected_p
} }
} }
// Cleanup /* Cleanup */
pfd->lpVtbl->Release(pfd); pfd->lpVtbl->Release(pfd);
} }
if (initResult != RPC_E_CHANGED_MODE && SUCCEEDED(initResult)) if (initResult != RPC_E_CHANGED_MODE && SUCCEEDED(initResult))
{ {
CoUninitialize(); //All successful CoInitializeEx calls must be balanced by a corresponding CoUninitialize CoUninitialize(); /*All successful CoInitializeEx calls must be balanced by a corresponding CoUninitialize */
} }
return SUCCEEDED(dialogResult); return SUCCEEDED(dialogResult);
} }
static BOOL static BOOL
CheckAdvancedDlgParams (HWND hdlg) CheckAdvancedDlgParams(HWND hdlg)
{ {
WCHAR tmp_path[MAX_PATH]; WCHAR tmp_path[MAX_PATH];
/* replace empty entries by current values */ /* replace empty entries by current values */
if (GetWindowTextLength (GetDlgItem(hdlg, ID_EDT_CONFIG_DIR)) == 0) if (GetWindowTextLength(GetDlgItem(hdlg, ID_EDT_CONFIG_DIR)) == 0)
SetDlgItemText (hdlg, ID_EDT_CONFIG_DIR, o.config_dir); {
if (GetWindowTextLength (GetDlgItem(hdlg, ID_EDT_LOG_DIR)) == 0) SetDlgItemText(hdlg, ID_EDT_CONFIG_DIR, o.config_dir);
SetDlgItemText (hdlg, ID_EDT_LOG_DIR, o.log_dir); }
if (GetWindowTextLength (GetDlgItem(hdlg, ID_EDT_CONFIG_EXT)) == 0) if (GetWindowTextLength(GetDlgItem(hdlg, ID_EDT_LOG_DIR)) == 0)
SetDlgItemText (hdlg, ID_EDT_CONFIG_EXT, o.ext_string); {
SetDlgItemText(hdlg, ID_EDT_LOG_DIR, o.log_dir);
}
if (GetWindowTextLength(GetDlgItem(hdlg, ID_EDT_CONFIG_EXT)) == 0)
{
SetDlgItemText(hdlg, ID_EDT_CONFIG_EXT, o.ext_string);
}
/* ensure paths are absolute */ /* ensure paths are absolute */
GetDlgItemText (hdlg, ID_EDT_CONFIG_DIR, tmp_path, _countof(tmp_path)); GetDlgItemText(hdlg, ID_EDT_CONFIG_DIR, tmp_path, _countof(tmp_path));
ExpandString (tmp_path, _countof(tmp_path)); ExpandString(tmp_path, _countof(tmp_path));
if (PathIsRelativeW (tmp_path)) if (PathIsRelativeW(tmp_path))
{ {
MessageBox (hdlg, L"Specified config directory is not an absolute path", MessageBox(hdlg, L"Specified config directory is not an absolute path",
L"Option error", MB_OK); L"Option error", MB_OK);
return false; return false;
} }
GetDlgItemText (hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path)); GetDlgItemText(hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path));
ExpandString (tmp_path, _countof(tmp_path)); ExpandString(tmp_path, _countof(tmp_path));
if (PathIsRelativeW (tmp_path)) if (PathIsRelativeW(tmp_path))
{ {
MessageBox (hdlg, L"Specified log directory is not an absolute path", MessageBox(hdlg, L"Specified log directory is not an absolute path",
L"Option error", MB_OK); L"Option error", MB_OK);
return false; return false;
} }
BOOL status; BOOL status;
int tmp = GetDlgItemInt (hdlg, ID_EDT_MGMT_PORT, &status, FALSE); int tmp = GetDlgItemInt(hdlg, ID_EDT_MGMT_PORT, &status, FALSE);
/* Restrict the port offset to sensible range -- port used is this + upto ~4000 as connection index */ /* Restrict the port offset to sensible range -- port used is this + upto ~4000 as connection index */
if (!status || (tmp < 1 || tmp > 61000)) if (!status || (tmp < 1 || tmp > 61000))
{ {
MessageBox (hdlg, L"Specified port is not valid (must be in the range 1 to 61000)", MessageBox(hdlg, L"Specified port is not valid (must be in the range 1 to 61000)",
L"Option error", MB_OK); L"Option error", MB_OK);
return false; return false;
} }
tmp = GetDlgItemInt (hdlg, ID_EDT_POPUP_MUTE, &status, FALSE); tmp = GetDlgItemInt(hdlg, ID_EDT_POPUP_MUTE, &status, FALSE);
if (!status || tmp < 0) if (!status || tmp < 0)
{ {
MessageBox (hdlg, L"Specified mute interval is not valid (must be a positive integer)", MessageBox(hdlg, L"Specified mute interval is not valid (must be a positive integer)",
L"Option error", MB_OK); L"Option error", MB_OK);
return false; return false;
} }
@ -614,159 +646,202 @@ CheckAdvancedDlgParams (HWND hdlg)
} }
static BOOL static BOOL
SaveAdvancedDlgParams (HWND hdlg) SaveAdvancedDlgParams(HWND hdlg)
{ {
WCHAR tmp_path[MAX_PATH], tmp_path1[MAX_PATH]; WCHAR tmp_path[MAX_PATH], tmp_path1[MAX_PATH];
UINT tmp; UINT tmp;
BOOL status; BOOL status;
GetDlgItemText (hdlg, ID_EDT_CONFIG_DIR, o.config_dir, _countof(o.config_dir)); GetDlgItemText(hdlg, ID_EDT_CONFIG_DIR, o.config_dir, _countof(o.config_dir));
GetDlgItemText (hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path)); GetDlgItemText(hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path));
wcsncpy (tmp_path1, tmp_path, _countof(tmp_path1)); wcsncpy(tmp_path1, tmp_path, _countof(tmp_path1));
ExpandString (tmp_path1, _countof(tmp_path1)); ExpandString(tmp_path1, _countof(tmp_path1));
if (EnsureDirExists (tmp_path1)) /* this will try to create the path if needed */ if (EnsureDirExists(tmp_path1)) /* this will try to create the path if needed */
wcsncpy (o.log_dir, tmp_path, _countof(o.log_dir)); /* save unexpanded path */ {
wcsncpy(o.log_dir, tmp_path, _countof(o.log_dir)); /* save unexpanded path */
}
else else
{ {
ShowLocalizedMsg(IDS_ERR_CREATE_PATH, L"Log", tmp_path1); ShowLocalizedMsg(IDS_ERR_CREATE_PATH, L"Log", tmp_path1);
return false; return false;
} }
GetDlgItemText (hdlg, ID_EDT_CONFIG_EXT, o.ext_string, _countof(o.ext_string)); GetDlgItemText(hdlg, ID_EDT_CONFIG_EXT, o.ext_string, _countof(o.ext_string));
tmp = GetDlgItemInt (hdlg, ID_EDT_PRECONNECT_TIMEOUT, &status, FALSE); tmp = GetDlgItemInt(hdlg, ID_EDT_PRECONNECT_TIMEOUT, &status, FALSE);
if (status && tmp > 0) o.preconnectscript_timeout = tmp; if (status && tmp > 0)
{
o.preconnectscript_timeout = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_CONNECT_TIMEOUT, &status, FALSE); tmp = GetDlgItemInt(hdlg, ID_EDT_CONNECT_TIMEOUT, &status, FALSE);
if (status) o.connectscript_timeout = tmp; if (status)
{
o.connectscript_timeout = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_DISCONNECT_TIMEOUT, &status, FALSE); tmp = GetDlgItemInt(hdlg, ID_EDT_DISCONNECT_TIMEOUT, &status, FALSE);
if (status && tmp > 0) o.disconnectscript_timeout = tmp; if (status && tmp > 0)
{
o.disconnectscript_timeout = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_MGMT_PORT, &status, FALSE); tmp = GetDlgItemInt(hdlg, ID_EDT_MGMT_PORT, &status, FALSE);
if (status) o.mgmt_port_offset = tmp; if (status)
{
o.mgmt_port_offset = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_POPUP_MUTE, &status, FALSE); tmp = GetDlgItemInt(hdlg, ID_EDT_POPUP_MUTE, &status, FALSE);
if (status) o.popup_mute_interval = tmp; if (status)
{
o.popup_mute_interval = tmp;
}
o.ovpn_engine = IsDlgButtonChecked(hdlg, ID_RB_ENGINE_OVPN3) ? o.ovpn_engine = IsDlgButtonChecked(hdlg, ID_RB_ENGINE_OVPN3) ?
OPENVPN_ENGINE_OVPN3 : OPENVPN_ENGINE_OVPN2; OPENVPN_ENGINE_OVPN3 : OPENVPN_ENGINE_OVPN2;
SaveRegistryKeys (); SaveRegistryKeys();
ExpandOptions (); ExpandOptions();
return true; return true;
} }
static void static void
LoadAdvancedDlgParams (HWND hdlg) LoadAdvancedDlgParams(HWND hdlg)
{ {
SetDlgItemText (hdlg, ID_EDT_CONFIG_DIR, o.config_dir); SetDlgItemText(hdlg, ID_EDT_CONFIG_DIR, o.config_dir);
SetDlgItemText (hdlg, ID_EDT_CONFIG_EXT, o.ext_string); SetDlgItemText(hdlg, ID_EDT_CONFIG_EXT, o.ext_string);
SetDlgItemText (hdlg, ID_EDT_LOG_DIR, o.log_dir); SetDlgItemText(hdlg, ID_EDT_LOG_DIR, o.log_dir);
SetDlgItemInt (hdlg, ID_EDT_PRECONNECT_TIMEOUT, o.preconnectscript_timeout, FALSE); SetDlgItemInt(hdlg, ID_EDT_PRECONNECT_TIMEOUT, o.preconnectscript_timeout, FALSE);
SetDlgItemInt (hdlg, ID_EDT_CONNECT_TIMEOUT, o.connectscript_timeout, FALSE); SetDlgItemInt(hdlg, ID_EDT_CONNECT_TIMEOUT, o.connectscript_timeout, FALSE);
SetDlgItemInt (hdlg, ID_EDT_DISCONNECT_TIMEOUT, o.disconnectscript_timeout, FALSE); SetDlgItemInt(hdlg, ID_EDT_DISCONNECT_TIMEOUT, o.disconnectscript_timeout, FALSE);
SetDlgItemInt (hdlg, ID_EDT_MGMT_PORT, o.mgmt_port_offset, FALSE); SetDlgItemInt(hdlg, ID_EDT_MGMT_PORT, o.mgmt_port_offset, FALSE);
SetDlgItemInt (hdlg, ID_EDT_POPUP_MUTE, o.popup_mute_interval, FALSE); SetDlgItemInt(hdlg, ID_EDT_POPUP_MUTE, o.popup_mute_interval, FALSE);
if (o.config_menu_view == 0) if (o.config_menu_view == 0)
CheckRadioButton (hdlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON0); {
CheckRadioButton(hdlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON0);
}
else if (o.config_menu_view == 1) else if (o.config_menu_view == 1)
CheckRadioButton (hdlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON1); {
CheckRadioButton(hdlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON1);
}
else if (o.config_menu_view == 2) else if (o.config_menu_view == 2)
CheckRadioButton (hdlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON2); {
CheckRadioButton(hdlg, ID_RB_BALLOON0, ID_RB_BALLOON2, ID_RB_BALLOON2);
}
/* BALLOON3 sets echo msg display to auto, BALLOON4 to never */ /* BALLOON3 sets echo msg display to auto, BALLOON4 to never */
if (o.disable_popup_messages) if (o.disable_popup_messages)
CheckRadioButton (hdlg, ID_RB_BALLOON3, ID_RB_BALLOON4, ID_RB_BALLOON4); {
CheckRadioButton(hdlg, ID_RB_BALLOON3, ID_RB_BALLOON4, ID_RB_BALLOON4);
}
else else
CheckRadioButton (hdlg, ID_RB_BALLOON3, ID_RB_BALLOON4, ID_RB_BALLOON3); {
CheckRadioButton(hdlg, ID_RB_BALLOON3, ID_RB_BALLOON4, ID_RB_BALLOON3);
}
#ifdef ENABLE_OVPN3 #ifdef ENABLE_OVPN3
CheckRadioButton(hdlg, ID_RB_ENGINE_OVPN2, ID_RB_ENGINE_OVPN3, CheckRadioButton(hdlg, ID_RB_ENGINE_OVPN2, ID_RB_ENGINE_OVPN3,
o.ovpn_engine == OPENVPN_ENGINE_OVPN3 ? ID_RB_ENGINE_OVPN3 : ID_RB_ENGINE_OVPN2); o.ovpn_engine == OPENVPN_ENGINE_OVPN3 ? ID_RB_ENGINE_OVPN3 : ID_RB_ENGINE_OVPN2);
#endif #endif
} }
INT_PTR CALLBACK INT_PTR CALLBACK
AdvancedSettingsDlgProc (HWND hwndDlg, UINT msg, UNUSED WPARAM wParam, LPARAM lParam) AdvancedSettingsDlgProc(HWND hwndDlg, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
{ {
LPPSHNOTIFY psn; LPPSHNOTIFY psn;
switch(msg) { switch (msg)
{
case WM_INITDIALOG:
/* Limit extension editbox to 4 chars. */ case WM_INITDIALOG:
SendMessage (GetDlgItem(hwndDlg, ID_EDT_CONFIG_EXT), EM_SETLIMITTEXT, 4, 0); /* Limit extension editbox to 4 chars. */
/* Limit management port editbox to 5 chars */ SendMessage(GetDlgItem(hwndDlg, ID_EDT_CONFIG_EXT), EM_SETLIMITTEXT, 4, 0);
SendMessage(GetDlgItem(hwndDlg, ID_EDT_MGMT_PORT), EM_SETLIMITTEXT, 5, 0); /* Limit management port editbox to 5 chars */
/* Populate UI */ SendMessage(GetDlgItem(hwndDlg, ID_EDT_MGMT_PORT), EM_SETLIMITTEXT, 5, 0);
LoadAdvancedDlgParams (hwndDlg); /* Populate UI */
break; LoadAdvancedDlgParams(hwndDlg);
case WM_COMMAND:
switch (LOWORD(wParam)) {
WCHAR path[MAX_PATH];
case ID_BTN_CONFIG_DIR:
GetDlgItemText (hwndDlg, ID_EDT_CONFIG_DIR, path, _countof(path));
if (BrowseFolder (path, path, _countof(path)))
SetDlgItemText (hwndDlg, ID_EDT_CONFIG_DIR, path);
break; break;
case ID_BTN_LOG_DIR: case WM_COMMAND:
GetDlgItemText (hwndDlg, ID_EDT_LOG_DIR, path, _countof(path)); switch (LOWORD(wParam))
if (BrowseFolder (path, path, _countof(path))) {
SetDlgItemText (hwndDlg, ID_EDT_LOG_DIR, path); WCHAR path[MAX_PATH];
case ID_BTN_CONFIG_DIR:
GetDlgItemText(hwndDlg, ID_EDT_CONFIG_DIR, path, _countof(path));
if (BrowseFolder(path, path, _countof(path)))
{
SetDlgItemText(hwndDlg, ID_EDT_CONFIG_DIR, path);
}
break;
case ID_BTN_LOG_DIR:
GetDlgItemText(hwndDlg, ID_EDT_LOG_DIR, path, _countof(path));
if (BrowseFolder(path, path, _countof(path)))
{
SetDlgItemText(hwndDlg, ID_EDT_LOG_DIR, path);
}
break;
}
break; break;
}
break;
case WM_NOTIFY: case WM_NOTIFY:
psn = (LPPSHNOTIFY) lParam; psn = (LPPSHNOTIFY) lParam;
if (psn->hdr.code == (UINT) PSN_KILLACTIVE) if (psn->hdr.code == (UINT) PSN_KILLACTIVE)
{ {
SetWindowLongPtr (hwndDlg, DWLP_MSGRESULT, (CheckAdvancedDlgParams(hwndDlg) ? FALSE : TRUE)); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (CheckAdvancedDlgParams(hwndDlg) ? FALSE : TRUE));
return TRUE; return TRUE;
} }
if (psn->hdr.code == (UINT) PSN_APPLY) if (psn->hdr.code == (UINT) PSN_APPLY)
{ {
BOOL status = SaveAdvancedDlgParams (hwndDlg); BOOL status = SaveAdvancedDlgParams(hwndDlg);
SetWindowLongPtr (hwndDlg, DWLP_MSGRESULT, status? PSNRET_NOERROR:PSNRET_INVALID); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, status ? PSNRET_NOERROR : PSNRET_INVALID);
return TRUE; return TRUE;
} }
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON2)) if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON2))
o.config_menu_view = 2; {
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON1)) o.config_menu_view = 2;
o.config_menu_view = 1; }
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON0)) else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON1))
o.config_menu_view = 0; {
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON3)) o.config_menu_view = 1;
o.disable_popup_messages = 0; }
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON4)) else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON0))
o.disable_popup_messages = 1; {
break; o.config_menu_view = 0;
}
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON3))
{
o.disable_popup_messages = 0;
}
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON4))
{
o.disable_popup_messages = 1;
}
break;
} }
return FALSE; return FALSE;
} }
int int
CompareStringExpanded (const WCHAR *str1, const WCHAR *str2) CompareStringExpanded(const WCHAR *str1, const WCHAR *str2)
{ {
WCHAR str1_cpy[MAX_PATH], str2_cpy[MAX_PATH]; WCHAR str1_cpy[MAX_PATH], str2_cpy[MAX_PATH];
wcsncpy (str1_cpy, str1, _countof(str1_cpy)); wcsncpy(str1_cpy, str1, _countof(str1_cpy));
wcsncpy (str2_cpy, str2, _countof(str2_cpy)); wcsncpy(str2_cpy, str2, _countof(str2_cpy));
str1_cpy[MAX_PATH-1] = L'\0'; str1_cpy[MAX_PATH-1] = L'\0';
str2_cpy[MAX_PATH-1] = L'\0'; str2_cpy[MAX_PATH-1] = L'\0';
ExpandString (str1_cpy, _countof(str1_cpy)); ExpandString(str1_cpy, _countof(str1_cpy));
ExpandString (str2_cpy, _countof(str2_cpy)); ExpandString(str2_cpy, _countof(str2_cpy));
return wcsicmp (str1_cpy, str2_cpy); return wcsicmp(str1_cpy, str2_cpy);
} }
/* Hide the password save options from user */ /* Hide the password save options from user */

@ -249,16 +249,27 @@ typedef struct {
} options_t; } options_t;
void InitOptions(options_t *); void InitOptions(options_t *);
void ProcessCommandLine(options_t *, TCHAR *); void ProcessCommandLine(options_t *, TCHAR *);
int CountConnState(conn_state_t); int CountConnState(conn_state_t);
connection_t* GetConnByManagement(SOCKET);
connection_t* GetConnByName(const WCHAR *config_name); connection_t *GetConnByManagement(SOCKET);
connection_t *GetConnByName(const WCHAR *config_name);
INT_PTR CALLBACK ScriptSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ScriptSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK ConnectionSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ConnectionSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK AdvancedSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK AdvancedSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
void DisableSavePasswords(connection_t *); void DisableSavePasswords(connection_t *);
void DisablePopupMessages(connection_t *); void DisablePopupMessages(connection_t *);
void ExpandOptions(void); void ExpandOptions(void);
int CompareStringExpanded(const WCHAR *str1, const WCHAR *str2); int CompareStringExpanded(const WCHAR *str1, const WCHAR *str2);
#endif
#endif /* ifndef OPTIONS_H */

@ -553,7 +553,7 @@ display_certificate(HWND parent, connection_t *c, UINT i)
*/ */
#if defined(HAVE_LIBCRYPTUI) || defined (_MSC_VER) #if defined(HAVE_LIBCRYPTUI) || defined (_MSC_VER)
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, l->pe[i].cert.ctx, CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, l->pe[i].cert.ctx,
parent, L"Certificate", 0, NULL); parent, L"Certificate", 0, NULL);
#else #else
(void) i; (void) i;
(void) parent; (void) parent;
@ -652,7 +652,7 @@ QueryPkcs11DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
} }
if (ln->hdr.code == NM_DBLCLK && ln->iItem >= 0) if (ln->hdr.code == NM_DBLCLK && ln->iItem >= 0)
{ {
display_certificate(hwndDlg, c, (UINT) ln->iItem); display_certificate(hwndDlg, c, (UINT) ln->iItem);
} }
} }
break; break;

@ -37,7 +37,9 @@ void
init_debug() init_debug()
{ {
if (!fp) if (!fp)
{
fp = _wfopen(L"C:\\Windows\\Temp\\openvpn-plap-debug.txt", L"a+,ccs=UTF-8"); fp = _wfopen(L"C:\\Windows\\Temp\\openvpn-plap-debug.txt", L"a+,ccs=UTF-8");
}
InitializeCriticalSection(&log_write); InitializeCriticalSection(&log_write);
} }
@ -45,7 +47,9 @@ void
uninit_debug() uninit_debug()
{ {
if (fp) if (fp)
{
fclose(fp); fclose(fp);
}
DeleteCriticalSection(&log_write); DeleteCriticalSection(&log_write);
} }
@ -58,8 +62,8 @@ x_dmsg(const char *file, const char *func, const wchar_t *fmt, ...)
return; return;
} }
va_list args; va_list args;
va_start (args, fmt); va_start(args, fmt);
vswprintf(buf, _countof(buf), fmt, args); vswprintf(buf, _countof(buf), fmt, args);
va_end(args); va_end(args);
@ -93,7 +97,7 @@ void
debug_print_guid(const GUID *riid, const wchar_t *context) debug_print_guid(const GUID *riid, const wchar_t *context)
{ {
RPC_CSTR str = NULL; RPC_CSTR str = NULL;
if (UuidToStringA((GUID*) riid, &str) == RPC_S_OK) if (UuidToStringA((GUID *) riid, &str) == RPC_S_OK)
{ {
x_dmsg(NULL, NULL, L"%ls %hs", context, str); x_dmsg(NULL, NULL, L"%ls %hs", context, str);
RpcStringFreeA(&str); RpcStringFreeA(&str);

@ -36,14 +36,17 @@ extern "C" {
#endif #endif
#ifdef DEBUG #ifdef DEBUG
#define dmsg(fmt, ...) x_dmsg(__FILE__, __func__, fmt, ##__VA_ARGS__) #define dmsg(fmt, ...) x_dmsg(__FILE__, __func__, fmt, ## __VA_ARGS__)
#else #else
#define dmsg(...) do { ; } while (0) #define dmsg(...) do {; } while (0)
#endif #endif
void x_dmsg(const char *file, const char *func, const wchar_t *fmt, ...); void x_dmsg(const char *file, const char *func, const wchar_t *fmt, ...);
void init_debug(); void init_debug();
void uninit_debug(); void uninit_debug();
void debug_print_guid(const GUID *riid, const wchar_t *context); void debug_print_guid(const GUID *riid, const wchar_t *context);
/* Shortcuts for cumbersome calls to COM methods of an object through its v-table */ /* Shortcuts for cumbersome calls to COM methods of an object through its v-table */
@ -64,6 +67,5 @@ void debug_print_guid(const GUID *riid, const wchar_t *context);
*/ */
#ifdef DEFINE_GUID #ifdef DEFINE_GUID
DEFINE_GUID(CLSID_OpenVPNProvider, 0x4fbb8b67, 0xcf02, 0x4982, 0xa7, 0xa8, DEFINE_GUID(CLSID_OpenVPNProvider, 0x4fbb8b67, 0xcf02, 0x4982, 0xa7, 0xa8,
0x3d, 0xd0, 0x6a, 0x2c, 0x2e, 0xbd); 0x3d, 0xd0, 0x6a, 0x2c, 0x2e, 0xbd);
#endif #endif

@ -59,36 +59,55 @@ extern DWORD status_menu_id;
/* Methods in IConnectableCredentialProviderCredential that we need to define */ /* Methods in IConnectableCredentialProviderCredential that we need to define */
/* IUnknown */ /* IUnknown */
static HRESULT WINAPI QueryInterface(ICCPC *this, REFIID riid, void** ppv); static HRESULT WINAPI QueryInterface(ICCPC *this, REFIID riid, void **ppv);
static ULONG WINAPI AddRef(ICCPC *this); static ULONG WINAPI AddRef(ICCPC *this);
static ULONG WINAPI Release(ICCPC *this); static ULONG WINAPI Release(ICCPC *this);
/* ICredentialProviderCredential */ /* ICredentialProviderCredential */
static HRESULT WINAPI Advise(ICCPC *this, ICredentialProviderCredentialEvents *e); static HRESULT WINAPI Advise(ICCPC *this, ICredentialProviderCredentialEvents *e);
static HRESULT WINAPI UnAdvise(ICCPC *this); static HRESULT WINAPI UnAdvise(ICCPC *this);
static HRESULT WINAPI SetSelected(ICCPC *this, BOOL *auto_logon); static HRESULT WINAPI SetSelected(ICCPC *this, BOOL *auto_logon);
static HRESULT WINAPI SetDeselected(ICCPC *this); static HRESULT WINAPI SetDeselected(ICCPC *this);
static HRESULT WINAPI GetFieldState(ICCPC *this, DWORD field, CREDENTIAL_PROVIDER_FIELD_STATE *fs, static HRESULT WINAPI GetFieldState(ICCPC *this, DWORD field, CREDENTIAL_PROVIDER_FIELD_STATE *fs,
CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *fis); CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *fis);
static HRESULT WINAPI GetStringValue(ICCPC *this, DWORD index, WCHAR **ws); static HRESULT WINAPI GetStringValue(ICCPC *this, DWORD index, WCHAR **ws);
static HRESULT WINAPI GetBitmapValue(ICCPC *this, DWORD field, HBITMAP *bmp); static HRESULT WINAPI GetBitmapValue(ICCPC *this, DWORD field, HBITMAP *bmp);
static HRESULT WINAPI GetSubmitButtonValue(ICCPC *this, DWORD field, DWORD *adjacent); static HRESULT WINAPI GetSubmitButtonValue(ICCPC *this, DWORD field, DWORD *adjacent);
static HRESULT WINAPI SetStringValue(ICCPC *this, DWORD field, const WCHAR *ws); static HRESULT WINAPI SetStringValue(ICCPC *this, DWORD field, const WCHAR *ws);
static HRESULT WINAPI GetCheckboxValue(ICCPC *this, DWORD field, BOOL *checked, wchar_t **label); static HRESULT WINAPI GetCheckboxValue(ICCPC *this, DWORD field, BOOL *checked, wchar_t **label);
static HRESULT WINAPI GetComboBoxValueCount(ICCPC *this, DWORD field, DWORD *items, DWORD *selected_item); static HRESULT WINAPI GetComboBoxValueCount(ICCPC *this, DWORD field, DWORD *items, DWORD *selected_item);
static HRESULT WINAPI GetComboBoxValueAt(ICCPC *this, DWORD field, DWORD item, wchar_t **item_value); static HRESULT WINAPI GetComboBoxValueAt(ICCPC *this, DWORD field, DWORD item, wchar_t **item_value);
static HRESULT WINAPI SetCheckboxValue(ICCPC *this, DWORD field, BOOL checked); static HRESULT WINAPI SetCheckboxValue(ICCPC *this, DWORD field, BOOL checked);
static HRESULT WINAPI SetComboBoxSelectedValue(ICCPC *this, DWORD field, DWORD selected_item); static HRESULT WINAPI SetComboBoxSelectedValue(ICCPC *this, DWORD field, DWORD selected_item);
static HRESULT WINAPI CommandLinkClicked(ICCPC *this, DWORD field); static HRESULT WINAPI CommandLinkClicked(ICCPC *this, DWORD field);
static HRESULT WINAPI GetSerialization(ICCPC *this, static HRESULT WINAPI GetSerialization(ICCPC *this,
CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *response, CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *response,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs, wchar_t **text, CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs, wchar_t **text,
CREDENTIAL_PROVIDER_STATUS_ICON *icon); CREDENTIAL_PROVIDER_STATUS_ICON *icon);
static HRESULT WINAPI ReportResult(ICCPC *this, NTSTATUS status, NTSTATUS substatus, static HRESULT WINAPI ReportResult(ICCPC *this, NTSTATUS status, NTSTATUS substatus,
wchar_t **status_text, CREDENTIAL_PROVIDER_STATUS_ICON *icon); wchar_t **status_text, CREDENTIAL_PROVIDER_STATUS_ICON *icon);
/* IConnectableCredentialProviderCredential */ /* IConnectableCredentialProviderCredential */
static HRESULT WINAPI Connect(ICCPC *this, IQueryContinueWithStatus *qc); static HRESULT WINAPI Connect(ICCPC *this, IQueryContinueWithStatus *qc);
static HRESULT WINAPI Disconnect(ICCPC *this); static HRESULT WINAPI Disconnect(ICCPC *this);
/* use a static table for filling in the methods */ /* use a static table for filling in the methods */
@ -169,7 +188,7 @@ Release(ICCPC *this)
} }
static HRESULT WINAPI static HRESULT WINAPI
QueryInterface(ICCPC *this, REFIID riid, void** ppv) QueryInterface(ICCPC *this, REFIID riid, void **ppv)
{ {
HRESULT hr; HRESULT hr;
@ -205,7 +224,8 @@ QueryInterface(ICCPC *this, REFIID riid, void** ppv)
* making callbacks to notify changes asynchronously * making callbacks to notify changes asynchronously
*/ */
static HRESULT static HRESULT
WINAPI Advise(ICCPC *this, ICredentialProviderCredentialEvents *e) WINAPI
Advise(ICCPC *this, ICredentialProviderCredentialEvents *e)
{ {
HWND hwnd; HWND hwnd;
@ -214,7 +234,9 @@ WINAPI Advise(ICCPC *this, ICredentialProviderCredentialEvents *e)
OpenVPNConnection *oc = (OpenVPNConnection *) this; OpenVPNConnection *oc = (OpenVPNConnection *) this;
if (oc->events) if (oc->events)
{
RELEASE(oc->events); RELEASE(oc->events);
}
oc->events = e; oc->events = e;
ADDREF(e); ADDREF(e);
@ -236,7 +258,9 @@ UnAdvise(ICCPC *this)
OpenVPNConnection *oc = (OpenVPNConnection *) this; OpenVPNConnection *oc = (OpenVPNConnection *) this;
if (oc->events) if (oc->events)
{
RELEASE(oc->events); RELEASE(oc->events);
}
oc->events = NULL; oc->events = NULL;
return S_OK; return S_OK;
} }
@ -282,8 +306,8 @@ SetDeselected(ICCPC *this)
*/ */
static HRESULT WINAPI static HRESULT WINAPI
GetFieldState(UNUSED ICCPC *this, DWORD field, GetFieldState(UNUSED ICCPC *this, DWORD field,
CREDENTIAL_PROVIDER_FIELD_STATE *fs, CREDENTIAL_PROVIDER_FIELD_STATE *fs,
CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *fis) CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE *fis)
{ {
HRESULT hr; HRESULT hr;
@ -292,9 +316,13 @@ GetFieldState(UNUSED ICCPC *this, DWORD field,
if (field < _countof(field_states)) if (field < _countof(field_states))
{ {
if (fs) if (fs)
{
*fs = field_states[field]; *fs = field_states[field];
}
if (fis) if (fis)
{
*fis = (field_desc[field].cpft == CPFT_SUBMIT_BUTTON) ? CPFIS_FOCUSED : CPFIS_NONE; *fis = (field_desc[field].cpft == CPFT_SUBMIT_BUTTON) ? CPFIS_FOCUSED : CPFIS_NONE;
}
hr = S_OK; hr = S_OK;
} }
else else
@ -418,7 +446,7 @@ SetStringValue(UNUSED ICCPC *this, UNUSED DWORD field, UNUSED const WCHAR *ws )
static HRESULT WINAPI static HRESULT WINAPI
GetCheckboxValue(UNUSED ICCPC *this, UNUSED DWORD field, GetCheckboxValue(UNUSED ICCPC *this, UNUSED DWORD field,
UNUSED BOOL *checked, UNUSED wchar_t **label) UNUSED BOOL *checked, UNUSED wchar_t **label)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
return E_NOTIMPL; return E_NOTIMPL;
@ -426,7 +454,7 @@ GetCheckboxValue(UNUSED ICCPC *this, UNUSED DWORD field,
static HRESULT WINAPI static HRESULT WINAPI
GetComboBoxValueCount(UNUSED ICCPC *this, UNUSED DWORD field, UNUSED DWORD *items, GetComboBoxValueCount(UNUSED ICCPC *this, UNUSED DWORD field, UNUSED DWORD *items,
UNUSED DWORD *selected_item) UNUSED DWORD *selected_item)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
return E_NOTIMPL; return E_NOTIMPL;
@ -434,7 +462,7 @@ GetComboBoxValueCount(UNUSED ICCPC *this, UNUSED DWORD field, UNUSED DWORD *item
static HRESULT WINAPI static HRESULT WINAPI
GetComboBoxValueAt(UNUSED ICCPC *this, UNUSED DWORD field, UNUSED DWORD item, GetComboBoxValueAt(UNUSED ICCPC *this, UNUSED DWORD field, UNUSED DWORD item,
UNUSED wchar_t **item_value) UNUSED wchar_t **item_value)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
return E_NOTIMPL; return E_NOTIMPL;
@ -470,8 +498,8 @@ CommandLinkClicked(UNUSED ICCPC *this, UNUSED DWORD field)
*/ */
static HRESULT WINAPI static HRESULT WINAPI
GetSerialization(ICCPC *this, CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *response, GetSerialization(ICCPC *this, CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *response,
UNUSED CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs, wchar_t **text, UNUSED CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs, wchar_t **text,
CREDENTIAL_PROVIDER_STATUS_ICON *icon) CREDENTIAL_PROVIDER_STATUS_ICON *icon)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -490,9 +518,13 @@ GetSerialization(ICCPC *this, CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *re
if (text && icon) if (text && icon)
{ {
if (oc->connect_cancelled) if (oc->connect_cancelled)
{
hr = SHStrDupW(LoadLocalizedString(IDS_NFO_CONN_CANCELLED), text); hr = SHStrDupW(LoadLocalizedString(IDS_NFO_CONN_CANCELLED), text);
}
else else
{
hr = SHStrDupW(LoadLocalizedString(IDS_NFO_CONN_FAILED, oc->display_name), text); hr = SHStrDupW(LoadLocalizedString(IDS_NFO_CONN_FAILED, oc->display_name), text);
}
*icon = CPSI_ERROR; *icon = CPSI_ERROR;
} }
@ -513,7 +545,7 @@ GetSerialization(ICCPC *this, CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *re
static HRESULT WINAPI static HRESULT WINAPI
ReportResult(UNUSED ICCPC *this, UNUSED NTSTATUS status, UNUSED NTSTATUS substatus, ReportResult(UNUSED ICCPC *this, UNUSED NTSTATUS status, UNUSED NTSTATUS substatus,
UNUSED wchar_t **status_text, UNUSED CREDENTIAL_PROVIDER_STATUS_ICON *icon) UNUSED wchar_t **status_text, UNUSED CREDENTIAL_PROVIDER_STATUS_ICON *icon)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
return E_NOTIMPL; return E_NOTIMPL;
@ -525,8 +557,8 @@ NotifyEvents(OpenVPNConnection *oc, const wchar_t *status)
{ {
if (oc->events) if (oc->events)
{ {
oc->events->lpVtbl->SetFieldString(oc->events, (ICredentialProviderCredential*) oc, oc->events->lpVtbl->SetFieldString(oc->events, (ICredentialProviderCredential *) oc,
STATUS_FIELD_INDEX, status); STATUS_FIELD_INDEX, status);
} }
if (oc->qc) if (oc->qc)
{ {
@ -646,7 +678,7 @@ again:
oc->qc = NULL; oc->qc = NULL;
SetActiveProfile(NULL); SetActiveProfile(NULL);
dmsg (L"Exit with: <%ls>", ISCONNECTED(oc->c) ? L"success" : L"error/cancel"); dmsg(L"Exit with: <%ls>", ISCONNECTED(oc->c) ? L"success" : L"error/cancel");
return ISCONNECTED(oc->c) ? S_OK : E_FAIL; return ISCONNECTED(oc->c) ? S_OK : E_FAIL;
} }
@ -655,7 +687,7 @@ static HRESULT WINAPI
Disconnect(ICCPC *this) Disconnect(ICCPC *this)
{ {
OpenVPNConnection *oc = (OpenVPNConnection *) this; OpenVPNConnection *oc = (OpenVPNConnection *) this;
dmsg (L"profile <%ls>", oc->display_name); dmsg(L"profile <%ls>", oc->display_name);
NotifyEvents(oc, LoadLocalizedString(IDS_NFO_STATE_DISCONNECTING)); NotifyEvents(oc, LoadLocalizedString(IDS_NFO_STATE_DISCONNECTING));
@ -679,8 +711,9 @@ OVPNConnection_Initialize(OpenVPNConnection *this, connection_t *conn, const wch
} }
/* Copy field descriptor -- caller will free using CoTaskMemFree, alloc using compatible allocator */ /* Copy field descriptor -- caller will free using CoTaskMemFree, alloc using compatible allocator */
HRESULT CopyFieldDescriptor(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_out, HRESULT
const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_in) CopyFieldDescriptor(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_out,
const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_in)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;

@ -52,7 +52,7 @@ static const CREDENTIAL_PROVIDER_FIELD_STATE field_states[] =
/** Helper to deep copy field descriptor */ /** Helper to deep copy field descriptor */
HRESULT CopyFieldDescriptor(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_out, HRESULT CopyFieldDescriptor(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_out,
const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_in); const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_in);
typedef struct OpenVPNConnection OpenVPNConnection; typedef struct OpenVPNConnection OpenVPNConnection;

@ -48,25 +48,29 @@ DllMain(HINSTANCE hinstDll, DWORD dwReason, UNUSED LPVOID pReserved)
DisableThreadLibraryCalls(hinstDll); DisableThreadLibraryCalls(hinstDll);
init_debug(); init_debug();
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
uninit_debug(); uninit_debug();
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
break; break;
} }
hinst_global = hinstDll; /* global */ hinst_global = hinstDll; /* global */
return TRUE; return TRUE;
} }
void dll_addref() void
dll_addref()
{ {
InterlockedIncrement(&dll_ref_count); InterlockedIncrement(&dll_ref_count);
dmsg(L"ref_count after increment = %lu", dll_ref_count); dmsg(L"ref_count after increment = %lu", dll_ref_count);
} }
void dll_release() void
dll_release()
{ {
InterlockedDecrement(&dll_ref_count); InterlockedDecrement(&dll_ref_count);
dmsg(L"ref_count after decrement = %lu", dll_ref_count); dmsg(L"ref_count after decrement = %lu", dll_ref_count);
@ -79,9 +83,13 @@ void dll_release()
/* ClassFactory methods we have to implement */ /* ClassFactory methods we have to implement */
static ULONG WINAPI AddRef(IClassFactory *this); static ULONG WINAPI AddRef(IClassFactory *this);
static ULONG WINAPI Release(IClassFactory *this); static ULONG WINAPI Release(IClassFactory *this);
static HRESULT WINAPI QueryInterface(IClassFactory *this, REFIID riid, void **ppv); static HRESULT WINAPI QueryInterface(IClassFactory *this, REFIID riid, void **ppv);
static HRESULT WINAPI CreateInstance(IClassFactory *this, IUnknown *iunk, REFIID riid, void **ppv); static HRESULT WINAPI CreateInstance(IClassFactory *this, IUnknown *iunk, REFIID riid, void **ppv);
static HRESULT WINAPI LockServer(IClassFactory *this, BOOL lock); static HRESULT WINAPI LockServer(IClassFactory *this, BOOL lock);
/* template object for creation */ /* template object for creation */
@ -116,7 +124,7 @@ static HRESULT WINAPI
QueryInterface(IClassFactory *this, REFIID riid, void **ppv) QueryInterface(IClassFactory *this, REFIID riid, void **ppv)
{ {
HRESULT hr; HRESULT hr;
dmsg (L"Entry"); dmsg(L"Entry");
#ifdef DEBUG #ifdef DEBUG
debug_print_guid(riid, L"In CF_Queryinterface with iid = "); debug_print_guid(riid, L"In CF_Queryinterface with iid = ");
@ -184,7 +192,8 @@ LockServer(UNUSED IClassFactory *this, BOOL lock)
} }
/* exported methods */ /* exported methods */
STDAPI DllCanUnloadNow() STDAPI
DllCanUnloadNow()
{ {
HRESULT hr; HRESULT hr;
@ -206,7 +215,8 @@ STDAPI DllCanUnloadNow()
* create class of type rclsid. We support only OpenVPNProvider * create class of type rclsid. We support only OpenVPNProvider
* class and check it here. * class and check it here.
*/ */
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) STDAPI
DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
HRESULT hr; HRESULT hr;

@ -33,10 +33,12 @@ extern HINSTANCE hinst_global;
HRESULT OpenVPNProvider_CreateInstance(REFIID riid, void **ppv); HRESULT OpenVPNProvider_CreateInstance(REFIID riid, void **ppv);
void dll_addref(); void dll_addref();
void dll_release(); void dll_release();
STDAPI DllCanUnloadNow(); STDAPI DllCanUnloadNow();
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv);
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -47,25 +47,31 @@ typedef struct OpenVPNProvider
/* methods we have to implement */ /* methods we have to implement */
static HRESULT WINAPI QueryInterface(ICredentialProvider *this, REFIID riid, void **ppv); static HRESULT WINAPI QueryInterface(ICredentialProvider *this, REFIID riid, void **ppv);
static ULONG WINAPI AddRef(ICredentialProvider *this); static ULONG WINAPI AddRef(ICredentialProvider *this);
static ULONG WINAPI Release(ICredentialProvider *this); static ULONG WINAPI Release(ICredentialProvider *this);
static HRESULT WINAPI SetUsageScenario(ICredentialProvider *this, static HRESULT WINAPI SetUsageScenario(ICredentialProvider *this,
CREDENTIAL_PROVIDER_USAGE_SCENARIO us, DWORD flags); CREDENTIAL_PROVIDER_USAGE_SCENARIO us, DWORD flags);
static HRESULT WINAPI SetSerialization(ICredentialProvider *this, static HRESULT WINAPI SetSerialization(ICredentialProvider *this,
const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs); const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs);
static HRESULT WINAPI Advise(ICredentialProvider *this, ICredentialProviderEvents *e, UINT_PTR context); static HRESULT WINAPI Advise(ICredentialProvider *this, ICredentialProviderEvents *e, UINT_PTR context);
static HRESULT WINAPI UnAdvise(ICredentialProvider *this); static HRESULT WINAPI UnAdvise(ICredentialProvider *this);
static HRESULT WINAPI GetFieldDescriptorCount(ICredentialProvider *this, DWORD *count); static HRESULT WINAPI GetFieldDescriptorCount(ICredentialProvider *this, DWORD *count);
static HRESULT WINAPI GetFieldDescriptorAt(ICredentialProvider *this, DWORD index, static HRESULT WINAPI GetFieldDescriptorAt(ICredentialProvider *this, DWORD index,
CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **fd); CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **fd);
static HRESULT WINAPI GetCredentialCount(ICredentialProvider *this, DWORD *count, static HRESULT WINAPI GetCredentialCount(ICredentialProvider *this, DWORD *count,
DWORD *default_cred, BOOL *autologon_default); DWORD *default_cred, BOOL *autologon_default);
static HRESULT WINAPI GetCredentialAt(ICredentialProvider *this, DWORD index, static HRESULT WINAPI GetCredentialAt(ICredentialProvider *this, DWORD index,
ICredentialProviderCredential **c); ICredentialProviderCredential **c);
/* a helper function for generating our connection array */ /* a helper function for generating our connection array */
static HRESULT CreateOVPNConnectionArray(OpenVPNProvider *op); static HRESULT CreateOVPNConnectionArray(OpenVPNProvider *op);
@ -118,7 +124,7 @@ OpenVPNProvider_free(OpenVPNProvider *this)
{ {
if (this->connections[i]) if (this->connections[i])
{ {
RELEASE((ICCPC*) this->connections[i]); RELEASE((ICCPC *) this->connections[i]);
} }
} }
/* Destroy GUI threads and any associated data */ /* Destroy GUI threads and any associated data */
@ -200,7 +206,7 @@ QueryInterface(ICredentialProvider *this, REFIID riid, void **ppv)
*/ */
static HRESULT WINAPI static HRESULT WINAPI
SetUsageScenario(ICredentialProvider *this, SetUsageScenario(ICredentialProvider *this,
CREDENTIAL_PROVIDER_USAGE_SCENARIO us, UNUSED DWORD flags) CREDENTIAL_PROVIDER_USAGE_SCENARIO us, UNUSED DWORD flags)
{ {
/* I think flags may be ignored for PLAP */ /* I think flags may be ignored for PLAP */
@ -223,7 +229,7 @@ SetUsageScenario(ICredentialProvider *this,
*/ */
static HRESULT WINAPI static HRESULT WINAPI
SetSerialization(UNUSED ICredentialProvider *this, SetSerialization(UNUSED ICredentialProvider *this,
UNUSED const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs) UNUSED const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *cs)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
return E_NOTIMPL; return E_NOTIMPL;
@ -234,7 +240,7 @@ SetSerialization(UNUSED ICredentialProvider *this,
*/ */
static HRESULT WINAPI static HRESULT WINAPI
Advise(UNUSED ICredentialProvider *this, Advise(UNUSED ICredentialProvider *this,
UNUSED ICredentialProviderEvents *e, UNUSED UINT_PTR ctx) UNUSED ICredentialProviderEvents *e, UNUSED UINT_PTR ctx)
{ {
dmsg(L"Entry"); dmsg(L"Entry");
return S_OK; return S_OK;
@ -273,7 +279,7 @@ GetFieldDescriptorCount(UNUSED ICredentialProvider *this, DWORD *count)
*/ */
static HRESULT WINAPI static HRESULT WINAPI
GetFieldDescriptorAt(UNUSED ICredentialProvider *this, DWORD index, GetFieldDescriptorAt(UNUSED ICredentialProvider *this, DWORD index,
CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **fd) CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **fd)
{ {
HRESULT hr = E_OUTOFMEMORY; HRESULT hr = E_OUTOFMEMORY;
@ -315,7 +321,7 @@ GetFieldDescriptorAt(UNUSED ICredentialProvider *this, DWORD index,
*/ */
static HRESULT WINAPI static HRESULT WINAPI
GetCredentialCount(ICredentialProvider *this, DWORD *count, DWORD *default_cred, GetCredentialCount(ICredentialProvider *this, DWORD *count, DWORD *default_cred,
BOOL *autologon_default) BOOL *autologon_default)
{ {
OpenVPNProvider *op = (OpenVPNProvider *) this; OpenVPNProvider *op = (OpenVPNProvider *) this;
@ -341,7 +347,7 @@ GetCredentialAt(ICredentialProvider *this, DWORD index, ICredentialProviderCrede
OpenVPNProvider *op = (OpenVPNProvider *) this; OpenVPNProvider *op = (OpenVPNProvider *) this;
if(index < op->conn_count && ic) if (index < op->conn_count && ic)
{ {
hr = QUERY_INTERFACE((ICredentialProviderCredential *) op->connections[index], hr = QUERY_INTERFACE((ICredentialProviderCredential *) op->connections[index],
&IID_ICredentialProviderCredential, (void **)ic); &IID_ICredentialProviderCredential, (void **)ic);
@ -374,7 +380,7 @@ CreateOVPNConnectionArray(OpenVPNProvider *op)
/* delete previous connections if any */ /* delete previous connections if any */
for (size_t i = 0; i < op->conn_count; i++) for (size_t i = 0; i < op->conn_count; i++)
{ {
RELEASE((ICCPC*) op->connections[i]); RELEASE((ICCPC *) op->connections[i]);
} }
op->conn_count = 0; op->conn_count = 0;
@ -404,7 +410,7 @@ CreateOVPNConnectionArray(OpenVPNProvider *op)
} }
else else
{ {
RELEASE((ICCPC*) oc); RELEASE((ICCPC *) oc);
} }
} }
else else

@ -31,7 +31,8 @@
#include "localization.h" #include "localization.h"
#include "ui_glue.h" #include "ui_glue.h"
void PrintDebugMsg(wchar_t *msg) void
PrintDebugMsg(wchar_t *msg)
{ {
x_dmsg("GUI-source", "", msg); x_dmsg("GUI-source", "", msg);
} }
@ -40,143 +41,176 @@ void
ErrorExit(UNUSED int exit_code, const wchar_t *msg) ErrorExit(UNUSED int exit_code, const wchar_t *msg)
{ {
if (msg) if (msg)
{
MessageBoxExW(NULL, msg, TEXT(PACKAGE_NAME), MessageBoxExW(NULL, msg, TEXT(PACKAGE_NAME),
MB_OK | MB_SETFOREGROUND|MB_ICONERROR, GetGUILanguage()); MB_OK | MB_SETFOREGROUND|MB_ICONERROR, GetGUILanguage());
}
DetachAllOpenVPN(); DetachAllOpenVPN();
/* do not exit */ /* do not exit */
} }
void RecreatePopupMenus(void) void
RecreatePopupMenus(void)
{ {
return; return;
} }
void CreatePopupMenus(void) void
CreatePopupMenus(void)
{ {
return; return;
} }
void OnNotifyTray(UNUSED LPARAM lp) void
OnNotifyTray(UNUSED LPARAM lp)
{ {
return; return;
} }
void OnDestroyTray(void) void
OnDestroyTray(void)
{ {
return; return;
} }
void ShowTrayIcon(void) void
ShowTrayIcon(void)
{ {
return; return;
} }
void SetTrayIcon(UNUSED conn_state_t state) void
SetTrayIcon(UNUSED conn_state_t state)
{ {
return; return;
} }
void SetMenuStatus(UNUSED connection_t *c, UNUSED conn_state_t state) void
SetMenuStatus(UNUSED connection_t *c, UNUSED conn_state_t state)
{ {
return; return;
} }
void SetServiceMenuStatus(void) void
SetServiceMenuStatus(void)
{ {
return; return;
} }
void ShowTrayBalloon(UNUSED wchar_t *s1, UNUSED wchar_t *s2) void
ShowTrayBalloon(UNUSED wchar_t *s1, UNUSED wchar_t *s2)
{ {
return; return;
} }
void CheckAndSetTrayIcon(void) void
CheckAndSetTrayIcon(void)
{ {
return; return;
} }
void RunPreconnectScript(UNUSED connection_t *c) void
RunPreconnectScript(UNUSED connection_t *c)
{ {
return; return;
} }
void RunConnectScript(UNUSED connection_t *ic, UNUSED int run_as_service) void
RunConnectScript(UNUSED connection_t *ic, UNUSED int run_as_service)
{ {
return; return;
} }
void RunDisconnectScript(UNUSED connection_t *c, UNUSED int run_as_service) void
RunDisconnectScript(UNUSED connection_t *c, UNUSED int run_as_service)
{ {
return; return;
} }
int SaveKeyPass(UNUSED const WCHAR *config_name, UNUSED const WCHAR *password) int
SaveKeyPass(UNUSED const WCHAR *config_name, UNUSED const WCHAR *password)
{ {
return 1; return 1;
} }
int SaveAuthPass(UNUSED const WCHAR *config_name, UNUSED const WCHAR *password) int
SaveAuthPass(UNUSED const WCHAR *config_name, UNUSED const WCHAR *password)
{ {
return 1; return 1;
} }
int SaveUsername(UNUSED const WCHAR *config_name, UNUSED const WCHAR *username) int
SaveUsername(UNUSED const WCHAR *config_name, UNUSED const WCHAR *username)
{ {
return 1; return 1;
} }
int RecallKeyPass(UNUSED const WCHAR *config_name, UNUSED WCHAR *password) int
RecallKeyPass(UNUSED const WCHAR *config_name, UNUSED WCHAR *password)
{ {
return 0; return 0;
} }
int RecallAuthPass(UNUSED const WCHAR *config_name, UNUSED WCHAR *password) int
RecallAuthPass(UNUSED const WCHAR *config_name, UNUSED WCHAR *password)
{ {
return 0; return 0;
} }
int RecallUsername(UNUSED const WCHAR *config_name, UNUSED WCHAR *username) int
RecallUsername(UNUSED const WCHAR *config_name, UNUSED WCHAR *username)
{ {
return 0; return 0;
} }
void DeleteSavedAuthPass(UNUSED const WCHAR *config_name) void
DeleteSavedAuthPass(UNUSED const WCHAR *config_name)
{ {
return; return;
} }
void DeleteSavedKeyPass(UNUSED const WCHAR *config_name) void
DeleteSavedKeyPass(UNUSED const WCHAR *config_name)
{ {
return; return;
} }
void DeleteSavedPasswords(UNUSED const WCHAR *config_name) void
DeleteSavedPasswords(UNUSED const WCHAR *config_name)
{ {
return; return;
} }
BOOL IsAuthPassSaved(UNUSED const WCHAR *config_name) BOOL
IsAuthPassSaved(UNUSED const WCHAR *config_name)
{ {
return 0; return 0;
} }
BOOL IsKeyPassSaved(UNUSED const WCHAR *config_name) BOOL
IsKeyPassSaved(UNUSED const WCHAR *config_name)
{ {
return 0; return 0;
} }
void env_item_del_all(UNUSED struct env_item *head) void
env_item_del_all(UNUSED struct env_item *head)
{ {
return; return;
} }
void process_setenv(UNUSED connection_t *c, UNUSED time_t timestamp, UNUSED const char *msg) void
process_setenv(UNUSED connection_t *c, UNUSED time_t timestamp, UNUSED const char *msg)
{ {
return; return;
} }
BOOL AuthorizeConfig(UNUSED const connection_t *c) BOOL
AuthorizeConfig(UNUSED const connection_t *c)
{ {
return 1; return 1;
} }
void echo_msg_process(UNUSED connection_t *c, UNUSED time_t timestamp, UNUSED const char *msg) void
echo_msg_process(UNUSED connection_t *c, UNUSED time_t timestamp, UNUSED const char *msg)
{ {
return; return;
} }
void echo_msg_clear(UNUSED connection_t *c, UNUSED BOOL clear_history) void
echo_msg_clear(UNUSED connection_t *c, UNUSED BOOL clear_history)
{ {
return; return;
} }
void echo_msg_load(UNUSED connection_t *c) void
echo_msg_load(UNUSED connection_t *c)
{ {
return; return;
} }
BOOL CheckKeyFileWriteAccess(UNUSED connection_t *c) BOOL
CheckKeyFileWriteAccess(UNUSED connection_t *c)
{ {
return 0; return 0;
} }

@ -72,7 +72,7 @@ OnStop_(connection_t *c, UNUSED char *msg)
* in PLAP context. * in PLAP context.
*/ */
static void static void
OnInfoMsg_(connection_t* c, char* msg) OnInfoMsg_(connection_t *c, char *msg)
{ {
if (strbegins(msg, "CR_TEXT:")) if (strbegins(msg, "CR_TEXT:"))
{ {
@ -167,7 +167,7 @@ InitializeUI(HINSTANCE hinstance)
WSADATA wsaData; WSADATA wsaData;
/* a session local semaphore to detect second instance */ /* a session local semaphore to detect second instance */
HANDLE session_semaphore = InitSemaphore(L"Local\\"PACKAGE_NAME"-PLAP"); HANDLE session_semaphore = InitSemaphore(L"Local\\"PACKAGE_NAME "-PLAP");
srand(time(NULL)); srand(time(NULL));
/* try to lock the semaphore, else we are not the first instance */ /* try to lock the semaphore, else we are not the first instance */
@ -188,7 +188,7 @@ InitializeUI(HINSTANCE hinstance)
dmsg(L"Starting OpenVPN UI v%hs", PACKAGE_VERSION); dmsg(L"Starting OpenVPN UI v%hs", PACKAGE_VERSION);
if(!GetModuleHandle(_T("RICHED20.DLL"))) if (!GetModuleHandle(_T("RICHED20.DLL")))
{ {
LoadLibrary(_T("RICHED20.DLL")); LoadLibrary(_T("RICHED20.DLL"));
} }
@ -202,20 +202,20 @@ InitializeUI(HINSTANCE hinstance)
* Some handlers are replaced by local functions * Some handlers are replaced by local functions
*/ */
mgmt_rtmsg_handler handler[] = { mgmt_rtmsg_handler handler[] = {
{ ready_, OnReady }, { ready_, OnReady },
{ hold_, OnHold }, { hold_, OnHold },
{ log_, OnLogLine }, { log_, OnLogLine },
{ state_, OnStateChange_ }, { state_, OnStateChange_ },
{ password_, OnPassword_ }, { password_, OnPassword_ },
{ proxy_, OnProxy_ }, { proxy_, OnProxy_ },
{ stop_, OnStop_ }, { stop_, OnStop_ },
{ needok_, OnNeedOk_ }, { needok_, OnNeedOk_ },
{ needstr_, OnNeedStr_ }, { needstr_, OnNeedStr_ },
{ echo_, OnEcho }, { echo_, OnEcho },
{ bytecount_,OnByteCount }, { bytecount_, OnByteCount },
{ infomsg_, OnInfoMsg_ }, { infomsg_, OnInfoMsg_ },
{ timeout_, OnTimeout }, { timeout_, OnTimeout },
{ 0, NULL} { 0, NULL}
}; };
InitManagement(handler); InitManagement(handler);
@ -267,10 +267,14 @@ InitializeUI(HINSTANCE hinstance)
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (c->flags & FLAG_DAEMON_PERSISTENT) num_persistent++; if (c->flags & FLAG_DAEMON_PERSISTENT)
{
num_persistent++;
}
} }
if (o.service_state == service_disconnected && num_persistent > 0) { if (o.service_state == service_disconnected && num_persistent > 0)
{
dmsg(L"Attempting to start automatic service"); dmsg(L"Attempting to start automatic service");
StartAutomaticService(); StartAutomaticService();
CheckServiceStatus(); CheckServiceStatus();
@ -301,7 +305,7 @@ FindPLAPConnections(connection_t *conn[], size_t max_count)
} }
static void static void
WaitOnThread (connection_t *c, DWORD timeout) WaitOnThread(connection_t *c, DWORD timeout)
{ {
HANDLE h = OpenThread(THREAD_ALL_ACCESS, FALSE, c->threadId); HANDLE h = OpenThread(THREAD_ALL_ACCESS, FALSE, c->threadId);
if (!h) if (!h)
@ -311,8 +315,8 @@ WaitOnThread (connection_t *c, DWORD timeout)
} }
DWORD exit_code; DWORD exit_code;
if (WaitForSingleObject(h, timeout) == WAIT_OBJECT_0 && if (WaitForSingleObject(h, timeout) == WAIT_OBJECT_0
GetExitCodeThread(h, &exit_code) && exit_code != STILL_ACTIVE) && GetExitCodeThread(h, &exit_code) && exit_code != STILL_ACTIVE)
{ {
dmsg(L"Connection thread closed"); dmsg(L"Connection thread closed");
goto out; goto out;
@ -320,7 +324,7 @@ WaitOnThread (connection_t *c, DWORD timeout)
/* Kill the thread */ /* Kill the thread */
dmsg(L"Force terminating a connection thread"); dmsg(L"Force terminating a connection thread");
TerminateThread (h, 1); TerminateThread(h, 1);
c->hwndStatus = NULL; c->hwndStatus = NULL;
c->threadId = 0; c->threadId = 0;
@ -365,7 +369,7 @@ GetConnectionStatusText(connection_t *c, wchar_t *status, DWORD len)
void void
SetParentWindow(HWND hwnd) SetParentWindow(HWND hwnd)
{ {
o.hWnd = hwnd; o.hWnd = hwnd;
} }
void void
@ -442,7 +446,7 @@ DeleteUI(void)
FreeConfigList(&o); FreeConfigList(&o);
CloseSemaphore(o.session_semaphore); CloseSemaphore(o.session_semaphore);
WSACleanup(); WSACleanup();
memset (&o, 0, sizeof(o)); memset(&o, 0, sizeof(o));
} }
void void
@ -527,7 +531,7 @@ RunProgressDialog(connection_t *c, PFTASKDIALOGCALLBACK cb_fn, LONG_PTR cb_data)
.cButtons = _countof(extra_buttons), .cButtons = _countof(extra_buttons),
.pButtons = extra_buttons, .pButtons = extra_buttons,
.dwCommonButtons = TDCBF_CANCEL_BUTTON|TDCBF_RETRY_BUTTON, .dwCommonButtons = TDCBF_CANCEL_BUTTON|TDCBF_RETRY_BUTTON,
.pszWindowTitle = L""PACKAGE_NAME" PLAP", .pszWindowTitle = L""PACKAGE_NAME " PLAP",
.pszMainInstruction = main_text, .pszMainInstruction = main_text,
.pszContent = L"Starting", /* updated in progress callback */ .pszContent = L"Starting", /* updated in progress callback */
.pfCallback = cb_fn, .pfCallback = cb_fn,

@ -52,95 +52,95 @@ ProxySettingsDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, UNUSED LPARAM lPa
switch (msg) switch (msg)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
hIcon = LoadLocalizedIcon(ID_ICO_APP); hIcon = LoadLocalizedIcon(ID_ICO_APP);
if (hIcon) if (hIcon)
{
SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_SMALL), (LPARAM) (hIcon));
SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_BIG), (LPARAM) (hIcon));
}
/* Limit Port editbox to 5 chars. */
SendMessage(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), EM_SETLIMITTEXT, 5, 0);
LoadProxySettings(hwndDlg);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_RB_PROXY_OPENVPN:
if (HIWORD(wParam) == BN_CLICKED)
{ {
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), FALSE); SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_SMALL), (LPARAM) (hIcon));
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), FALSE); SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_BIG), (LPARAM) (hIcon));
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), FALSE);
} }
break;
case ID_RB_PROXY_MSIE: /* Limit Port editbox to 5 chars. */
if (HIWORD(wParam) == BN_CLICKED) SendMessage(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), EM_SETLIMITTEXT, 5, 0);
{
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), FALSE); LoadProxySettings(hwndDlg);
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), FALSE);
}
break; break;
case ID_RB_PROXY_MANUAL: case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED) switch (LOWORD(wParam))
{ {
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), TRUE); case ID_RB_PROXY_OPENVPN:
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), TRUE); if (HIWORD(wParam) == BN_CLICKED)
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), TRUE); {
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), TRUE); EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), TRUE); EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), TRUE); EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), FALSE);
}
break;
case ID_RB_PROXY_MSIE:
if (HIWORD(wParam) == BN_CLICKED)
{
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), FALSE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), FALSE);
}
break;
case ID_RB_PROXY_MANUAL:
if (HIWORD(wParam) == BN_CLICKED)
{
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), TRUE);
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), TRUE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), TRUE);
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), TRUE);
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), TRUE);
}
break;
case ID_RB_PROXY_HTTP:
if (HIWORD(wParam) == BN_CLICKED)
{
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address);
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port);
}
break;
case ID_RB_PROXY_SOCKS:
if (HIWORD(wParam) == BN_CLICKED)
{
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address);
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port);
}
break;
} }
break; break;
case ID_RB_PROXY_HTTP: case WM_NOTIFY:
if (HIWORD(wParam) == BN_CLICKED) psn = (LPPSHNOTIFY) lParam;
if (psn->hdr.code == (UINT) PSN_KILLACTIVE)
{ {
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (CheckProxySettings(hwndDlg) ? FALSE : TRUE));
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port); return TRUE;
} }
break; else if (psn->hdr.code == (UINT) PSN_APPLY)
case ID_RB_PROXY_SOCKS:
if (HIWORD(wParam) == BN_CLICKED)
{ {
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address); SaveProxySettings(hwndDlg);
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
} }
break; break;
}
break;
case WM_NOTIFY: case WM_CLOSE:
psn = (LPPSHNOTIFY) lParam; EndDialog(hwndDlg, LOWORD(wParam));
if (psn->hdr.code == (UINT) PSN_KILLACTIVE)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (CheckProxySettings(hwndDlg) ? FALSE : TRUE));
return TRUE;
}
else if (psn->hdr.code == (UINT) PSN_APPLY)
{
SaveProxySettings(hwndDlg);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE; return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
} }
return FALSE; return FALSE;
} }
@ -250,9 +250,9 @@ SaveProxySettings(HWND hwndDlg)
proxy_type_string[0] = _T('0'); proxy_type_string[0] = _T('0');
GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address, GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address,
_countof(o.proxy_http_address)); _countof(o.proxy_http_address));
GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port, GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port,
_countof(o.proxy_http_port)); _countof(o.proxy_http_port));
} }
else else
{ {
@ -260,9 +260,9 @@ SaveProxySettings(HWND hwndDlg)
proxy_type_string[0] = _T('1'); proxy_type_string[0] = _T('1');
GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address, GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address,
_countof(o.proxy_socks_address)); _countof(o.proxy_socks_address));
GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port, GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port,
_countof(o.proxy_socks_port)); _countof(o.proxy_socks_port));
} }
/* Open Registry for writing */ /* Open Registry for writing */
@ -300,7 +300,9 @@ GetProxyRegistrySettings()
_sntprintf_0(proxy_subkey, _T("%ls\\proxy"), GUI_REGKEY_HKCU); _sntprintf_0(proxy_subkey, _T("%ls\\proxy"), GUI_REGKEY_HKCU);
status = RegOpenKeyEx(HKEY_CURRENT_USER, proxy_subkey, 0, KEY_READ, &regkey); status = RegOpenKeyEx(HKEY_CURRENT_USER, proxy_subkey, 0, KEY_READ, &regkey);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
{
return; return;
}
/* get registry settings */ /* get registry settings */
GetRegistryValue(regkey, _T("proxy_http_address"), o.proxy_http_address, _countof(o.proxy_http_address)); GetRegistryValue(regkey, _T("proxy_http_address"), o.proxy_http_address, _countof(o.proxy_http_address));
@ -338,53 +340,57 @@ ProxyAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
switch (msg) switch (msg)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
/* Set connection for this dialog and show it */ /* Set connection for this dialog and show it */
c = (connection_t *) lParam; c = (connection_t *) lParam;
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE) c); TRY_SETPROP(hwndDlg, cfgProp, (HANDLE) c);
if (c->state == resuming) if (c->state == resuming)
ForceForegroundWindow(hwndDlg); {
else ForceForegroundWindow(hwndDlg);
SetForegroundWindow(hwndDlg); }
break; else
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_EDT_PROXY_USER:
if (HIWORD(wParam) == EN_UPDATE)
{ {
int len = Edit_GetTextLength((HWND) lParam); SetForegroundWindow(hwndDlg);
EnableWindow(GetDlgItem(hwndDlg, IDOK), (len ? TRUE : FALSE));
} }
break; break;
case IDOK: case WM_COMMAND:
c = (connection_t *) GetProp(hwndDlg, cfgProp); switch (LOWORD(wParam))
proxy_type = (c->proxy_type == http ? "HTTP" : "SOCKS"); {
case ID_EDT_PROXY_USER:
snprintf(fmt, sizeof(fmt), "username \"%s Proxy\" \"%%s\"", proxy_type); if (HIWORD(wParam) == EN_UPDATE)
ManagementCommandFromInput(c, fmt, hwndDlg, ID_EDT_PROXY_USER); {
int len = Edit_GetTextLength((HWND) lParam);
snprintf(fmt, sizeof(fmt), "password \"%s Proxy\" \"%%s\"", proxy_type); EnableWindow(GetDlgItem(hwndDlg, IDOK), (len ? TRUE : FALSE));
ManagementCommandFromInput(c, fmt, hwndDlg, ID_EDT_PROXY_PASS); }
break;
case IDOK:
c = (connection_t *) GetProp(hwndDlg, cfgProp);
proxy_type = (c->proxy_type == http ? "HTTP" : "SOCKS");
snprintf(fmt, sizeof(fmt), "username \"%s Proxy\" \"%%s\"", proxy_type);
ManagementCommandFromInput(c, fmt, hwndDlg, ID_EDT_PROXY_USER);
snprintf(fmt, sizeof(fmt), "password \"%s Proxy\" \"%%s\"", proxy_type);
ManagementCommandFromInput(c, fmt, hwndDlg, ID_EDT_PROXY_PASS);
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
}
break;
case WM_OVPN_STATE: /* state changed -- destroy the dialog */
EndDialog(hwndDlg, LOWORD(wParam)); EndDialog(hwndDlg, LOWORD(wParam));
return TRUE; return TRUE;
}
break;
case WM_OVPN_STATE: /* state changed -- destroy the dialog */
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
case WM_CLOSE: case WM_CLOSE:
EndDialog(hwndDlg, LOWORD(wParam)); EndDialog(hwndDlg, LOWORD(wParam));
return TRUE; return TRUE;
case WM_NCDESTROY: case WM_NCDESTROY:
RemoveProp(hwndDlg, cfgProp); RemoveProp(hwndDlg, cfgProp);
break; break;
} }
return FALSE; return FALSE;
} }
@ -428,13 +434,15 @@ QueryWindowsProxySettings(const url_scheme scheme, LPCSTR host)
LPWSTR old_url = auto_config_url; LPWSTR old_url = auto_config_url;
DWORD flags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; DWORD flags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
if (WinHttpDetectAutoProxyConfigUrl(flags, &auto_config_url)) if (WinHttpDetectAutoProxyConfigUrl(flags, &auto_config_url))
{
GlobalFree(old_url); GlobalFree(old_url);
}
} }
if (auto_config_url) if (auto_config_url)
{ {
HINTERNET session = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, HINTERNET session = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (session) if (session)
{ {
int size = _snwprintf(NULL, 0, L"%ls://%hs", UrlSchemeStr(scheme), host) + 1; int size = _snwprintf(NULL, 0, L"%ls://%hs", UrlSchemeStr(scheme), host) + 1;
@ -476,7 +484,9 @@ ParseProxyString(LPWSTR proxy_str, url_scheme scheme,
LPCSTR *type, LPCWSTR *host, LPCWSTR *port) LPCSTR *type, LPCWSTR *host, LPCWSTR *port)
{ {
if (proxy_str == NULL) if (proxy_str == NULL)
{
return; return;
}
LPCWSTR delim = L"; "; LPCWSTR delim = L"; ";
LPWSTR ctx = NULL; LPWSTR ctx = NULL;
@ -518,9 +528,13 @@ ParseProxyString(LPWSTR proxy_str, url_scheme scheme,
{ {
LPWSTR server = token; LPWSTR server = token;
if (css) if (css)
{
server = css + 3; server = css + 3;
}
else if (eq) else if (eq)
{
server = eq + 1; server = eq + 1;
}
/* IPv6 addresses are surrounded by brackets */ /* IPv6 addresses are surrounded by brackets */
LPWSTR port_delim; LPWSTR port_delim;
@ -529,7 +543,9 @@ ParseProxyString(LPWSTR proxy_str, url_scheme scheme,
server += 1; server += 1;
LPWSTR end = wcschr(server, ']'); LPWSTR end = wcschr(server, ']');
if (end == NULL) if (end == NULL)
{
continue; continue;
}
*end++ = '\0'; *end++ = '\0';
port_delim = (*end == ':' ? end : NULL); port_delim = (*end == ':' ? end : NULL);
@ -538,15 +554,21 @@ ParseProxyString(LPWSTR proxy_str, url_scheme scheme,
{ {
port_delim = wcsrchr(server, ':'); port_delim = wcsrchr(server, ':');
if (port_delim) if (port_delim)
{
*port_delim = '\0'; *port_delim = '\0';
}
} }
*type = (scheme == HTTPS_URL ? "HTTP" : "SOCKS"); *type = (scheme == HTTPS_URL ? "HTTP" : "SOCKS");
*host = server; *host = server;
if (port_delim) if (port_delim)
{
*port = port_delim + 1; *port = port_delim + 1;
}
else else
*port = (scheme == HTTPS_URL ? L"80": L"1080"); {
*port = (scheme == HTTPS_URL ? L"80" : L"1080");
}
break; break;
} }
@ -565,17 +587,23 @@ OnProxy(connection_t *c, char *line)
LPSTR proto, host; LPSTR proto, host;
char *pos = strchr(line, ','); char *pos = strchr(line, ',');
if (pos == NULL) if (pos == NULL)
{
return; return;
}
proto = ++pos; proto = ++pos;
pos = strchr(pos, ','); pos = strchr(pos, ',');
if (pos == NULL) if (pos == NULL)
{
return; return;
}
*pos = '\0'; *pos = '\0';
host = ++pos; host = ++pos;
if (host[0] == '\0') if (host[0] == '\0')
{
return; return;
}
LPCSTR type = "NONE"; LPCSTR type = "NONE";
LPCWSTR addr = L"", port = L""; LPCWSTR addr = L"", port = L"";

@ -23,13 +23,17 @@
#define PROXY_H #define PROXY_H
INT_PTR CALLBACK ProxySettingsDialogFunc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK ProxySettingsDialogFunc(HWND, UINT, WPARAM, LPARAM);
void QueryProxyAuth(connection_t *, proxy_t); void QueryProxyAuth(connection_t *, proxy_t);
void OnProxy(connection_t *, char *); void OnProxy(connection_t *, char *);
int CheckProxySettings(HWND); int CheckProxySettings(HWND);
void LoadProxySettings(HWND); void LoadProxySettings(HWND);
void SaveProxySettings(HWND); void SaveProxySettings(HWND);
void GetProxyRegistrySettings(); void GetProxyRegistrySettings();
#endif #endif

@ -43,159 +43,174 @@ struct regkey_str {
int len; int len;
const WCHAR *value; const WCHAR *value;
} regkey_str[] = { } regkey_str[] = {
{L"config_dir", o.config_dir, _countof(o.config_dir), L"%USERPROFILE%\\OpenVPN\\config"}, {L"config_dir", o.config_dir, _countof(o.config_dir), L"%USERPROFILE%\\OpenVPN\\config"},
{L"config_ext", o.ext_string, _countof(o.ext_string), L"ovpn"}, {L"config_ext", o.ext_string, _countof(o.ext_string), L"ovpn"},
{L"log_dir", o.log_dir, _countof(o.log_dir), L"%USERPROFILE%\\OpenVPN\\log"} {L"log_dir", o.log_dir, _countof(o.log_dir), L"%USERPROFILE%\\OpenVPN\\log"}
}; };
struct regkey_int { struct regkey_int {
const WCHAR *name; const WCHAR *name;
DWORD *var; DWORD *var;
DWORD value; DWORD value;
} regkey_int[] = { } regkey_int[] = {
{L"log_append", &o.log_append, 0}, {L"log_append", &o.log_append, 0},
{L"iservice_admin", &o.iservice_admin, 1}, {L"iservice_admin", &o.iservice_admin, 1},
{L"show_balloon", &o.show_balloon, 1}, {L"show_balloon", &o.show_balloon, 1},
{L"silent_connection", &o.silent_connection, 0}, {L"silent_connection", &o.silent_connection, 0},
{L"preconnectscript_timeout", &o.preconnectscript_timeout, 10}, {L"preconnectscript_timeout", &o.preconnectscript_timeout, 10},
{L"connectscript_timeout", &o.connectscript_timeout, 30}, {L"connectscript_timeout", &o.connectscript_timeout, 30},
{L"disconnectscript_timeout", &o.disconnectscript_timeout, 10}, {L"disconnectscript_timeout", &o.disconnectscript_timeout, 10},
{L"show_script_window", &o.show_script_window, 0}, {L"show_script_window", &o.show_script_window, 0},
{L"config_menu_view", &o.config_menu_view, CONFIG_VIEW_AUTO}, {L"config_menu_view", &o.config_menu_view, CONFIG_VIEW_AUTO},
{L"popup_mute_interval", &o.popup_mute_interval, 24}, {L"popup_mute_interval", &o.popup_mute_interval, 24},
{L"disable_popup_messages", &o.disable_popup_messages, 0}, {L"disable_popup_messages", &o.disable_popup_messages, 0},
{L"management_port_offset", &o.mgmt_port_offset, 25340}, {L"management_port_offset", &o.mgmt_port_offset, 25340},
{L"enable_peristent_connections", &o.enable_persistent, 2}, {L"enable_peristent_connections", &o.enable_persistent, 2},
{L"enable_auto_restart", &o.enable_auto_restart, 1}, {L"enable_auto_restart", &o.enable_auto_restart, 1},
{L"ovpn_engine", &o.ovpn_engine, OPENVPN_ENGINE_OVPN2} {L"ovpn_engine", &o.ovpn_engine, OPENVPN_ENGINE_OVPN2}
}; };
static int static int
RegValueExists (HKEY regkey, const WCHAR *name) RegValueExists(HKEY regkey, const WCHAR *name)
{ {
return (RegQueryValueEx (regkey, name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS); return (RegQueryValueEx(regkey, name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS);
} }
static int static int
GetGlobalRegistryKeys() GetGlobalRegistryKeys()
{ {
TCHAR windows_dir[MAX_PATH]; TCHAR windows_dir[MAX_PATH];
HKEY regkey; HKEY regkey;
if (!GetWindowsDirectory(windows_dir, _countof(windows_dir))) { if (!GetWindowsDirectory(windows_dir, _countof(windows_dir)))
/* can't get windows dir */ {
ShowLocalizedMsg(IDS_ERR_GET_WINDOWS_DIR); /* can't get windows dir */
/* Use a default value */ ShowLocalizedMsg(IDS_ERR_GET_WINDOWS_DIR);
_sntprintf_0(windows_dir, L"C:\\Windows"); /* Use a default value */
} _sntprintf_0(windows_dir, L"C:\\Windows");
}
/* set default editor and log_viewer as a fallback for opening config/log files */ /* set default editor and log_viewer as a fallback for opening config/log files */
_sntprintf_0(o.editor, L"%ls\\%ls", windows_dir, L"System32\\notepad.exe"); _sntprintf_0(o.editor, L"%ls\\%ls", windows_dir, L"System32\\notepad.exe");
_sntprintf_0(o.log_viewer, L"%ls", o.editor); _sntprintf_0(o.log_viewer, L"%ls", o.editor);
/* Get path to OpenVPN installation. */ /* Get path to OpenVPN installation. */
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\OpenVPN"), 0, KEY_READ, &regkey) if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\OpenVPN"), 0, KEY_READ, &regkey)
!= ERROR_SUCCESS) != ERROR_SUCCESS)
{ {
/* registry key not found */ /* registry key not found */
regkey = NULL; regkey = NULL;
ShowLocalizedMsg(IDS_ERR_OPEN_REGISTRY); ShowLocalizedMsg(IDS_ERR_OPEN_REGISTRY);
} }
if (!regkey || !GetRegistryValue(regkey, _T(""), o.install_path, _countof(o.install_path)) if (!regkey || !GetRegistryValue(regkey, _T(""), o.install_path, _countof(o.install_path))
|| _tcslen(o.install_path) == 0) || _tcslen(o.install_path) == 0)
{ {
/* error reading registry value */ /* error reading registry value */
if (regkey) if (regkey)
ShowLocalizedMsg(IDS_ERR_READING_REGISTRY); {
/* Use a sane default value */ ShowLocalizedMsg(IDS_ERR_READING_REGISTRY);
_sntprintf_0(o.install_path, _T("%ls"), _T("C:\\Program Files\\OpenVPN\\")); }
/* Use a sane default value */
_sntprintf_0(o.install_path, _T("%ls"), _T("C:\\Program Files\\OpenVPN\\"));
}
if (o.install_path[_tcslen(o.install_path) - 1] != _T('\\'))
{
_tcscat(o.install_path, _T("\\"));
} }
if (o.install_path[_tcslen(o.install_path) - 1] != _T('\\'))
_tcscat(o.install_path, _T("\\"));
/* an admin-defined global config dir defined in HKLM\OpenVPN\config_dir */ /* an admin-defined global config dir defined in HKLM\OpenVPN\config_dir */
if (!regkey || !GetRegistryValue(regkey, _T("config_dir"), o.global_config_dir, _countof(o.global_config_dir))) if (!regkey || !GetRegistryValue(regkey, _T("config_dir"), o.global_config_dir, _countof(o.global_config_dir)))
{ {
/* use default = openvpnpath\config */ /* use default = openvpnpath\config */
_sntprintf_0(o.global_config_dir, _T("%lsconfig"), o.install_path); _sntprintf_0(o.global_config_dir, _T("%lsconfig"), o.install_path);
} }
if (!regkey || !GetRegistryValue(regkey, _T("autostart_config_dir"), o.config_auto_dir, _countof(o.config_auto_dir))) if (!regkey || !GetRegistryValue(regkey, _T("autostart_config_dir"), o.config_auto_dir, _countof(o.config_auto_dir)))
{ {
/* use default = openvpnpath\config-auto */ /* use default = openvpnpath\config-auto */
_sntprintf_0(o.config_auto_dir, L"%lsconfig-auto", o.install_path); _sntprintf_0(o.config_auto_dir, L"%lsconfig-auto", o.install_path);
} }
if (!regkey || !GetRegistryValue(regkey, _T("log_dir"), o.global_log_dir, _countof(o.global_log_dir))) if (!regkey || !GetRegistryValue(regkey, _T("log_dir"), o.global_log_dir, _countof(o.global_log_dir)))
{ {
/* use default = openvpnpath\log */ /* use default = openvpnpath\log */
_sntprintf_0(o.global_log_dir, L"%lslog", o.install_path); _sntprintf_0(o.global_log_dir, L"%lslog", o.install_path);
} }
if (!regkey || !GetRegistryValue(regkey, _T("ovpn_admin_group"), o.ovpn_admin_group, _countof(o.ovpn_admin_group))) if (!regkey || !GetRegistryValue(regkey, _T("ovpn_admin_group"), o.ovpn_admin_group, _countof(o.ovpn_admin_group)))
{ {
_tcsncpy(o.ovpn_admin_group, OVPN_ADMIN_GROUP, _countof(o.ovpn_admin_group)-1); _tcsncpy(o.ovpn_admin_group, OVPN_ADMIN_GROUP, _countof(o.ovpn_admin_group)-1);
} }
if (!regkey || !GetRegistryValue(regkey, _T("exe_path"), o.exe_path, _countof(o.exe_path))) if (!regkey || !GetRegistryValue(regkey, _T("exe_path"), o.exe_path, _countof(o.exe_path)))
{ {
_sntprintf_0(o.exe_path, _T("%lsbin\\openvpn.exe"), o.install_path); _sntprintf_0(o.exe_path, _T("%lsbin\\openvpn.exe"), o.install_path);
} }
if (!regkey || !GetRegistryValue(regkey, _T("priority"), o.priority_string, _countof(o.priority_string))) if (!regkey || !GetRegistryValue(regkey, _T("priority"), o.priority_string, _countof(o.priority_string)))
{
_tcsncpy(o.priority_string, _T("NORMAL_PRIORITY_CLASS"), _countof(o.priority_string)-1);
}
if (!regkey || !GetRegistryValueNumeric(regkey, _T("disable_save_passwords"), &o.disable_save_passwords))
{ {
_tcsncpy(o.priority_string, _T("NORMAL_PRIORITY_CLASS"), _countof(o.priority_string)-1); o.disable_save_passwords = 0;
} }
if (!regkey || !GetRegistryValueNumeric(regkey, _T("disable_save_passwords"), &o.disable_save_passwords)) if (regkey)
{ {
o.disable_save_passwords = 0; RegCloseKey(regkey);
} }
if (regkey) return true;
RegCloseKey(regkey);
return true;
} }
int int
GetRegistryKeys () GetRegistryKeys()
{ {
HKEY regkey; HKEY regkey;
DWORD status; DWORD status;
int i; int i;
if (!GetGlobalRegistryKeys()) if (!GetGlobalRegistryKeys())
{
return false; return false;
}
status = RegOpenKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, KEY_READ, &regkey); status = RegOpenKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, KEY_READ, &regkey);
for (i = 0 ; i < (int) _countof (regkey_str); ++i) for (i = 0; i < (int) _countof(regkey_str); ++i)
{ {
if ( status != ERROR_SUCCESS || if (status != ERROR_SUCCESS
!GetRegistryValue (regkey, regkey_str[i].name, regkey_str[i].var, regkey_str[i].len)) || !GetRegistryValue(regkey, regkey_str[i].name, regkey_str[i].var, regkey_str[i].len))
{ {
/* no value found in registry, use the default */ /* no value found in registry, use the default */
wcsncpy (regkey_str[i].var, regkey_str[i].value, regkey_str[i].len); wcsncpy(regkey_str[i].var, regkey_str[i].value, regkey_str[i].len);
regkey_str[i].var[regkey_str[i].len-1] = L'\0'; regkey_str[i].var[regkey_str[i].len-1] = L'\0';
PrintDebug(L"default: %ls = %ls", regkey_str[i].name, regkey_str[i].var); PrintDebug(L"default: %ls = %ls", regkey_str[i].name, regkey_str[i].var);
} }
else else
{
PrintDebug(L"from registry: %ls = %ls", regkey_str[i].name, regkey_str[i].var); PrintDebug(L"from registry: %ls = %ls", regkey_str[i].name, regkey_str[i].var);
}
} }
for (i = 0 ; i < (int) _countof (regkey_int); ++i) for (i = 0; i < (int) _countof(regkey_int); ++i)
{ {
if ( status != ERROR_SUCCESS || if (status != ERROR_SUCCESS
!GetRegistryValueNumeric (regkey, regkey_int[i].name, regkey_int[i].var)) || !GetRegistryValueNumeric(regkey, regkey_int[i].name, regkey_int[i].var))
{ {
/* no value found in registry, use the default */ /* no value found in registry, use the default */
*regkey_int[i].var = regkey_int[i].value; *regkey_int[i].var = regkey_int[i].value;
PrintDebug(L"default: %ls = %lu", regkey_int[i].name, *regkey_int[i].var); PrintDebug(L"default: %ls = %lu", regkey_int[i].name, *regkey_int[i].var);
} }
else else
{
PrintDebug(L"from registry: %ls = %lu", regkey_int[i].name, *regkey_int[i].var); PrintDebug(L"from registry: %ls = %lu", regkey_int[i].name, *regkey_int[i].var);
}
} }
if ( status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
RegCloseKey (regkey); {
RegCloseKey(regkey);
}
if ((o.disconnectscript_timeout == 0)) if ((o.disconnectscript_timeout == 0))
{ {
@ -229,12 +244,12 @@ GetRegistryKeys ()
RegCloseKey(regkey); RegCloseKey(regkey);
} }
ExpandOptions (); ExpandOptions();
return true; return true;
} }
int int
SaveRegistryKeys () SaveRegistryKeys()
{ {
HKEY regkey; HKEY regkey;
DWORD status; DWORD status;
@ -245,27 +260,31 @@ SaveRegistryKeys ()
KEY_WRITE|KEY_READ, NULL, &regkey, NULL); KEY_WRITE|KEY_READ, NULL, &regkey, NULL);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
{ {
ShowLocalizedMsg (IDS_ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU); ShowLocalizedMsg(IDS_ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU);
goto out; goto out;
} }
for (i = 0 ; i < (int) _countof (regkey_str); ++i) for (i = 0; i < (int) _countof(regkey_str); ++i)
{ {
/* save only if the value differs from default or already present in registry */ /* save only if the value differs from default or already present in registry */
if ( CompareStringExpanded (regkey_str[i].var, regkey_str[i].value) != 0 || if (CompareStringExpanded(regkey_str[i].var, regkey_str[i].value) != 0
RegValueExists(regkey, regkey_str[i].name) ) || RegValueExists(regkey, regkey_str[i].name) )
{ {
if (!SetRegistryValue (regkey, regkey_str[i].name, regkey_str[i].var)) if (!SetRegistryValue(regkey, regkey_str[i].name, regkey_str[i].var))
{
goto out; goto out;
}
} }
} }
for (i = 0 ; i < (int) _countof (regkey_int); ++i) for (i = 0; i < (int) _countof(regkey_int); ++i)
{ {
if ( *regkey_int[i].var != regkey_int[i].value || if (*regkey_int[i].var != regkey_int[i].value
RegValueExists(regkey, regkey_int[i].name) ) || RegValueExists(regkey, regkey_int[i].name) )
{ {
if (!SetRegistryValueNumeric (regkey, regkey_int[i].name, *regkey_int[i].var)) if (!SetRegistryValueNumeric(regkey, regkey_int[i].name, *regkey_int[i].var))
{
goto out; goto out;
}
} }
} }
ret = true; ret = true;
@ -273,29 +292,33 @@ SaveRegistryKeys ()
out: out:
if (status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
{
RegCloseKey(regkey); RegCloseKey(regkey);
}
return ret; return ret;
} }
static BOOL static BOOL
GetRegistryVersion (version_t *v) GetRegistryVersion(version_t *v)
{ {
HKEY regkey; HKEY regkey;
CLEAR (*v); CLEAR(*v);
DWORD len = sizeof(*v); DWORD len = sizeof(*v);
if (RegOpenKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, KEY_READ, &regkey) == ERROR_SUCCESS) if (RegOpenKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, KEY_READ, &regkey) == ERROR_SUCCESS)
{ {
if (RegGetValueW (regkey, NULL, L"version", RRF_RT_REG_BINARY, NULL, v, &len) if (RegGetValueW(regkey, NULL, L"version", RRF_RT_REG_BINARY, NULL, v, &len)
!= ERROR_SUCCESS) != ERROR_SUCCESS)
CLEAR (*v); {
CLEAR(*v);
}
RegCloseKey(regkey); RegCloseKey(regkey);
} }
return true; return true;
} }
static BOOL static BOOL
SetRegistryVersion (const version_t *v) SetRegistryVersion(const version_t *v)
{ {
HKEY regkey; HKEY regkey;
DWORD status; DWORD status;
@ -305,12 +328,16 @@ SetRegistryVersion (const version_t *v)
KEY_WRITE, NULL, &regkey, NULL); KEY_WRITE, NULL, &regkey, NULL);
if (status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
{ {
if (RegSetValueEx(regkey, L"version", 0, REG_BINARY, (const BYTE*) v, sizeof(*v)) == ERROR_SUCCESS) if (RegSetValueEx(regkey, L"version", 0, REG_BINARY, (const BYTE *) v, sizeof(*v)) == ERROR_SUCCESS)
{
ret = true; ret = true;
}
RegCloseKey(regkey); RegCloseKey(regkey);
} }
else else
PrintDebug (L"Eror opening/creating 'HKCU\\%ls' registry key", GUI_REGKEY_HKCU); {
PrintDebug(L"Eror opening/creating 'HKCU\\%ls' registry key", GUI_REGKEY_HKCU);
}
return ret; return ret;
} }
@ -322,16 +349,18 @@ MigrateNilingsKeys()
HKEY regkey, regkey_proxy, regkey_nilings; HKEY regkey, regkey_proxy, regkey_nilings;
status = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Nilings\\OpenVPN-GUI", 0, status = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Nilings\\OpenVPN-GUI", 0,
KEY_READ, &regkey_nilings); KEY_READ, &regkey_nilings);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
{
return true; /* No old keys to migrate */ return true; /* No old keys to migrate */
}
status = RegCreateKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, NULL, REG_OPTION_NON_VOLATILE, status = RegCreateKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &regkey, NULL); KEY_ALL_ACCESS, NULL, &regkey, NULL);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
{ {
ShowLocalizedMsg (IDS_ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU); ShowLocalizedMsg(IDS_ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU);
RegCloseKey (regkey_nilings); RegCloseKey(regkey_nilings);
return false; return false;
} }
@ -343,112 +372,132 @@ MigrateNilingsKeys()
DWORD ui_lang; DWORD ui_lang;
/* Move language setting from Nilings to GUI_REGKEY_HKCU */ /* Move language setting from Nilings to GUI_REGKEY_HKCU */
if (GetRegistryValueNumeric(regkey_nilings, L"ui_language", &ui_lang)) if (GetRegistryValueNumeric(regkey_nilings, L"ui_language", &ui_lang))
SetRegistryValueNumeric (regkey, L"ui_language", ui_lang); {
SetRegistryValueNumeric(regkey, L"ui_language", ui_lang);
}
status = RegCopyTree (regkey_nilings, NULL, regkey_proxy); status = RegCopyTree(regkey_nilings, NULL, regkey_proxy);
if (status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
{ {
RegDeleteValue (regkey_proxy, L"ui_language"); /* in case copied here */ RegDeleteValue(regkey_proxy, L"ui_language"); /* in case copied here */
ret = true; ret = true;
} }
RegCloseKey (regkey_proxy); RegCloseKey(regkey_proxy);
} }
else else
PrintDebug (L"Error creating key 'proxy' in HKCU\\%ls", GUI_REGKEY_HKCU); {
PrintDebug(L"Error creating key 'proxy' in HKCU\\%ls", GUI_REGKEY_HKCU);
}
RegCloseKey (regkey); RegCloseKey(regkey);
RegCloseKey (regkey_nilings); RegCloseKey(regkey_nilings);
return ret; return ret;
} }
int int
UpdateRegistry (void) UpdateRegistry(void)
{ {
version_t v; version_t v;
GetRegistryVersion (&v); GetRegistryVersion(&v);
if (memcmp(&v, &o.version, sizeof(v)) == 0) if (memcmp(&v, &o.version, sizeof(v)) == 0)
{
return true; return true;
}
switch (v.major) switch (v.major)
{ {
case 0: /* Cleanup GUI_REGKEY_HKCU and migrate any values under Nilings */ case 0: /* Cleanup GUI_REGKEY_HKCU and migrate any values under Nilings */
RegDeleteTree (HKEY_CURRENT_USER, GUI_REGKEY_HKCU); /* delete all values and subkeys */ RegDeleteTree(HKEY_CURRENT_USER, GUI_REGKEY_HKCU); /* delete all values and subkeys */
if (!MigrateNilingsKeys()) if (!MigrateNilingsKeys())
{
return false; return false;
}
/* fall through to handle further updates */ /* fall through to handle further updates */
case 11: case 11:
/* current version -- nothing to do */ /* current version -- nothing to do */
break; break;
default: default:
break; break;
} }
SetRegistryVersion (&o.version); SetRegistryVersion(&o.version);
PrintDebug (L"Registry updated to version %hu.%hu", o.version.major, o.version.minor); PrintDebug(L"Registry updated to version %hu.%hu", o.version.major, o.version.minor);
return true; return true;
} }
LONG GetRegistryValue(HKEY regkey, const TCHAR *name, TCHAR *data, DWORD len) LONG
GetRegistryValue(HKEY regkey, const TCHAR *name, TCHAR *data, DWORD len)
{ {
LONG status; LONG status;
DWORD type; DWORD type;
DWORD data_len; DWORD data_len;
data_len = len * sizeof(*data); data_len = len * sizeof(*data);
/* get a registry string */ /* get a registry string */
status = RegQueryValueEx(regkey, name, NULL, &type, (byte *) data, &data_len); status = RegQueryValueEx(regkey, name, NULL, &type, (byte *) data, &data_len);
if (status != ERROR_SUCCESS || type != REG_SZ) if (status != ERROR_SUCCESS || type != REG_SZ)
return(0); {
return(0);
}
data_len /= sizeof(*data); data_len /= sizeof(*data);
if (data_len > 0) if (data_len > 0)
data[data_len - 1] = L'\0'; /* REG_SZ strings are not guaranteed to be null-terminated */ {
else data[data_len - 1] = L'\0'; /* REG_SZ strings are not guaranteed to be null-terminated */
data[0] = L'\0'; }
else
{
data[0] = L'\0';
}
return(data_len); return(data_len);
} }
LONG LONG
GetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD *data) GetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD *data)
{ {
DWORD type; DWORD type;
DWORD size = sizeof(*data); DWORD size = sizeof(*data);
LONG status = RegQueryValueEx(regkey, name, NULL, &type, (PBYTE) data, &size); LONG status = RegQueryValueEx(regkey, name, NULL, &type, (PBYTE) data, &size);
return (type == REG_DWORD && status == ERROR_SUCCESS) ? 1 : 0; return (type == REG_DWORD && status == ERROR_SUCCESS) ? 1 : 0;
} }
int SetRegistryValue(HKEY regkey, const TCHAR *name, const TCHAR *data) int
SetRegistryValue(HKEY regkey, const TCHAR *name, const TCHAR *data)
{ {
/* set a registry string */ /* set a registry string */
DWORD size = (_tcslen(data) + 1) * sizeof(*data); DWORD size = (_tcslen(data) + 1) * sizeof(*data);
if(RegSetValueEx(regkey, name, 0, REG_SZ, (PBYTE) data, size) != ERROR_SUCCESS) if (RegSetValueEx(regkey, name, 0, REG_SZ, (PBYTE) data, size) != ERROR_SUCCESS)
{ {
/* Error writing registry value */ /* Error writing registry value */
ShowLocalizedMsg(IDS_ERR_WRITE_REGVALUE, GUI_REGKEY_HKCU, name); ShowLocalizedMsg(IDS_ERR_WRITE_REGVALUE, GUI_REGKEY_HKCU, name);
return(0); return(0);
} }
return(1); return(1);
} }
int int
SetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD data) SetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD data)
{ {
LONG status = RegSetValueEx(regkey, name, 0, REG_DWORD, (PBYTE) &data, sizeof(data)); LONG status = RegSetValueEx(regkey, name, 0, REG_DWORD, (PBYTE) &data, sizeof(data));
if (status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
return 1; {
return 1;
}
ShowLocalizedMsg(IDS_ERR_WRITE_REGVALUE, GUI_REGKEY_HKCU, name); ShowLocalizedMsg(IDS_ERR_WRITE_REGVALUE, GUI_REGKEY_HKCU, name);
return 0; return 0;
} }
/* /*
@ -464,18 +513,24 @@ OpenConfigRegistryKey(const WCHAR *config_name, HKEY *regkey, BOOL create)
WCHAR *name = malloc(count * sizeof(WCHAR)); WCHAR *name = malloc(count * sizeof(WCHAR));
if (!name) if (!name)
{
return 0; return 0;
}
_snwprintf(name, count, fmt, config_name); _snwprintf(name, count, fmt, config_name);
name[count-1] = L'\0'; name[count-1] = L'\0';
if (!create) if (!create)
status = RegOpenKeyEx (HKEY_CURRENT_USER, name, 0, KEY_READ | KEY_WRITE, regkey); {
status = RegOpenKeyEx(HKEY_CURRENT_USER, name, 0, KEY_READ | KEY_WRITE, regkey);
}
else else
/* create if key doesn't exist */ {
status = RegCreateKeyEx(HKEY_CURRENT_USER, name, 0, NULL, /* create if key doesn't exist */
REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, regkey, NULL); status = RegCreateKeyEx(HKEY_CURRENT_USER, name, 0, NULL,
free (name); REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, regkey, NULL);
}
free(name);
return (status == ERROR_SUCCESS); return (status == ERROR_SUCCESS);
} }
@ -487,7 +542,9 @@ SetConfigRegistryValueBinary(const WCHAR *config_name, const WCHAR *name, const
DWORD status; DWORD status;
if (!OpenConfigRegistryKey(config_name, &regkey, TRUE)) if (!OpenConfigRegistryKey(config_name, &regkey, TRUE))
{
return 0; return 0;
}
status = RegSetValueEx(regkey, name, 0, REG_BINARY, data, len); status = RegSetValueEx(regkey, name, 0, REG_BINARY, data, len);
RegCloseKey(regkey); RegCloseKey(regkey);
@ -507,13 +564,19 @@ GetConfigRegistryValue(const WCHAR *config_name, const WCHAR *name, BYTE *data,
HKEY regkey; HKEY regkey;
if (!OpenConfigRegistryKey(config_name, &regkey, FALSE)) if (!OpenConfigRegistryKey(config_name, &regkey, FALSE))
{
return 0; return 0;
}
status = RegQueryValueEx(regkey, name, NULL, &type, data, &len); status = RegQueryValueEx(regkey, name, NULL, &type, data, &len);
RegCloseKey(regkey); RegCloseKey(regkey);
if (status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
{
return len; return len;
}
else else
{
return 0; return 0;
}
} }
int int
@ -523,7 +586,9 @@ DeleteConfigRegistryValue(const WCHAR *config_name, const WCHAR *name)
HKEY regkey; HKEY regkey;
if (!OpenConfigRegistryKey(config_name, &regkey, FALSE)) if (!OpenConfigRegistryKey(config_name, &regkey, FALSE))
{
return 0; return 0;
}
status = RegDeleteValue(regkey, name); status = RegDeleteValue(regkey, name);
RegCloseKey(regkey); RegCloseKey(regkey);

@ -23,15 +23,25 @@
#define REGISTRY_H #define REGISTRY_H
int GetRegistryKeys(void); int GetRegistryKeys(void);
int SaveRegistryKeys(void); int SaveRegistryKeys(void);
int UpdateRegistry(void); int UpdateRegistry(void);
int GetRegKey(const TCHAR name[], TCHAR data[], const TCHAR default_data[], DWORD len); int GetRegKey(const TCHAR name[], TCHAR data[], const TCHAR default_data[], DWORD len);
LONG GetRegistryValue(HKEY regkey, const TCHAR *name, TCHAR *data, DWORD len); LONG GetRegistryValue(HKEY regkey, const TCHAR *name, TCHAR *data, DWORD len);
LONG GetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD *data); LONG GetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD *data);
int SetRegistryValue(HKEY regkey, const TCHAR *name, const TCHAR *data); int SetRegistryValue(HKEY regkey, const TCHAR *name, const TCHAR *data);
int SetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD data); int SetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD data);
int SetConfigRegistryValueBinary(const WCHAR *config_name, const WCHAR *name, const BYTE *data, DWORD len); int SetConfigRegistryValueBinary(const WCHAR *config_name, const WCHAR *name, const BYTE *data, DWORD len);
DWORD GetConfigRegistryValue(const WCHAR *config_name, const WCHAR *name, BYTE *data, DWORD len); DWORD GetConfigRegistryValue(const WCHAR *config_name, const WCHAR *name, BYTE *data, DWORD len);
int DeleteConfigRegistryValue(const WCHAR *config_name, const WCHAR *name); int DeleteConfigRegistryValue(const WCHAR *config_name, const WCHAR *name);
#endif #endif /* ifndef REGISTRY_H */

@ -46,10 +46,10 @@ crypt_protect(BYTE *data, int szdata, char *entropy, BYTE **out)
data_in.pbData = data; data_in.pbData = data;
data_in.cbData = szdata; data_in.cbData = szdata;
e.pbData = (BYTE*) entropy; e.pbData = (BYTE *) entropy;
e.cbData = entropy? strlen(entropy) : 0; e.cbData = entropy ? strlen(entropy) : 0;
if(CryptProtectData(&data_in, NULL, &e, NULL, NULL, 0, &data_out)) if (CryptProtectData(&data_in, NULL, &e, NULL, NULL, 0, &data_out))
{ {
*out = data_out.pbData; *out = data_out.pbData;
return data_out.cbData; return data_out.cbData;
@ -62,15 +62,15 @@ static DWORD
crypt_unprotect(BYTE *data, int szdata, char *entropy, BYTE **out) crypt_unprotect(BYTE *data, int szdata, char *entropy, BYTE **out)
{ {
DATA_BLOB data_in; DATA_BLOB data_in;
DATA_BLOB data_out = {0,0}; DATA_BLOB data_out = {0, 0};
DATA_BLOB e; DATA_BLOB e;
data_in.pbData = data; data_in.pbData = data;
data_in.cbData = szdata; data_in.cbData = szdata;
e.pbData = (BYTE *) entropy; e.pbData = (BYTE *) entropy;
e.cbData = entropy? strlen(entropy) : 0; e.cbData = entropy ? strlen(entropy) : 0;
if(CryptUnprotectData(&data_in, NULL, &e, NULL, NULL, 0, &data_out)) if (CryptUnprotectData(&data_in, NULL, &e, NULL, NULL, 0, &data_out))
{ {
*out = data_out.pbData; *out = data_out.pbData;
return data_out.cbData; return data_out.cbData;
@ -78,7 +78,7 @@ crypt_unprotect(BYTE *data, int szdata, char *entropy, BYTE **out)
else else
{ {
PrintDebug(L"CryptUnprotectData: decryption failed"); PrintDebug(L"CryptUnprotectData: decryption failed");
LocalFree (data_out.pbData); LocalFree(data_out.pbData);
return 0; return 0;
} }
} }
@ -105,10 +105,14 @@ get_entropy(const WCHAR *config_name, char *e, int sz, BOOL generate)
e[sz-1] = '\0'; e[sz-1] = '\0';
PrintDebug(L"Created new entropy string : %hs", e); PrintDebug(L"Created new entropy string : %hs", e);
if (SetConfigRegistryValueBinary(config_name, ENTROPY_DATA, (BYTE *)e, sz)) if (SetConfigRegistryValueBinary(config_name, ENTROPY_DATA, (BYTE *)e, sz))
{
return; return;
}
} }
if (generate) if (generate)
{
PrintDebug(L"Failed to generate or save new entropy string -- using null string"); PrintDebug(L"Failed to generate or save new entropy string -- using null string");
}
*e = '\0'; *e = '\0';
return; return;
} }
@ -125,15 +129,17 @@ save_encrypted(const WCHAR *config_name, const WCHAR *password, const WCHAR *nam
char entropy[ENTROPY_LEN+1]; char entropy[ENTROPY_LEN+1];
get_entropy(config_name, entropy, sizeof(entropy), true); get_entropy(config_name, entropy, sizeof(entropy), true);
len = crypt_protect((BYTE*) password, len, entropy, &out); len = crypt_protect((BYTE *) password, len, entropy, &out);
if(len > 0) if (len > 0)
{ {
SetConfigRegistryValueBinary(config_name, name, out, len); SetConfigRegistryValueBinary(config_name, name, out, len);
LocalFree(out); LocalFree(out);
return 1; return 1;
} }
else else
{
return 0; return 0;
}
} }
/* /*
@ -171,15 +177,19 @@ recall_encrypted(const WCHAR *config_name, WCHAR *password, DWORD capacity, cons
get_entropy(config_name, entropy, sizeof(entropy), false); get_entropy(config_name, entropy, sizeof(entropy), false);
memset (password, 0, capacity); memset(password, 0, capacity);
len = GetConfigRegistryValue(config_name, name, in, sizeof(in)); len = GetConfigRegistryValue(config_name, name, in, sizeof(in));
if(len == 0) if (len == 0)
{
return 0; return 0;
}
len = crypt_unprotect(in, len, entropy, &out); len = crypt_unprotect(in, len, entropy, &out);
if(len == 0) if (len == 0)
{
return 0; return 0;
}
if (len <= capacity * sizeof(*password)) if (len <= capacity * sizeof(*password))
{ {
@ -188,7 +198,9 @@ recall_encrypted(const WCHAR *config_name, WCHAR *password, DWORD capacity, cons
retval = 1; retval = 1;
} }
else else
{
PrintDebug(L"recall_encrypted: saved '%ls' too long (len = %d bytes)", name, len); PrintDebug(L"recall_encrypted: saved '%ls' too long (len = %d bytes)", name, len);
}
SecureZeroMemory(out, len); SecureZeroMemory(out, len);
LocalFree(out); LocalFree(out);
@ -222,7 +234,7 @@ int
SaveUsername(const WCHAR *config_name, const WCHAR *username) SaveUsername(const WCHAR *config_name, const WCHAR *username)
{ {
DWORD len = (wcslen(username) + 1) * sizeof(*username); DWORD len = (wcslen(username) + 1) * sizeof(*username);
SetConfigRegistryValueBinary(config_name, AUTH_USER_DATA,(BYTE *) username, len); SetConfigRegistryValueBinary(config_name, AUTH_USER_DATA, (BYTE *) username, len);
return 1; return 1;
} }
/* /*
@ -237,7 +249,9 @@ RecallUsername(const WCHAR *config_name, WCHAR *username)
len = GetConfigRegistryValue(config_name, AUTH_USER_DATA, (BYTE *) username, capacity); len = GetConfigRegistryValue(config_name, AUTH_USER_DATA, (BYTE *) username, capacity);
if (len == 0) if (len == 0)
{
return 0; return 0;
}
username[USER_PASS_LEN-1] = L'\0'; username[USER_PASS_LEN-1] = L'\0';
return 1; return 1;
} }

@ -28,17 +28,25 @@
#define KEY_PASS_LEN 128 #define KEY_PASS_LEN 128
int SaveKeyPass(const WCHAR *config_name, const WCHAR *password); int SaveKeyPass(const WCHAR *config_name, const WCHAR *password);
int SaveAuthPass(const WCHAR *config_name, const WCHAR *password); int SaveAuthPass(const WCHAR *config_name, const WCHAR *password);
int SaveUsername(const WCHAR *config_name, const WCHAR *username); int SaveUsername(const WCHAR *config_name, const WCHAR *username);
int RecallKeyPass(const WCHAR *config_name, WCHAR *password); int RecallKeyPass(const WCHAR *config_name, WCHAR *password);
int RecallAuthPass(const WCHAR *config_name, WCHAR *password); int RecallAuthPass(const WCHAR *config_name, WCHAR *password);
int RecallUsername(const WCHAR *config_name, WCHAR *username); int RecallUsername(const WCHAR *config_name, WCHAR *username);
void DeleteSavedAuthPass(const WCHAR *config_name); void DeleteSavedAuthPass(const WCHAR *config_name);
void DeleteSavedKeyPass(const WCHAR *config_name); void DeleteSavedKeyPass(const WCHAR *config_name);
void DeleteSavedPasswords(const WCHAR *config_name); void DeleteSavedPasswords(const WCHAR *config_name);
BOOL IsAuthPassSaved(const WCHAR *config_name); BOOL IsAuthPassSaved(const WCHAR *config_name);
BOOL IsKeyPassSaved(const WCHAR *config_name); BOOL IsKeyPassSaved(const WCHAR *config_name);
#endif
#endif /* ifndef SAVEPASS_H */

@ -60,13 +60,15 @@ RunPreconnectScript(connection_t *c)
/* Return if no script exists */ /* Return if no script exists */
if (_tstat(cmdline, &st) == -1) if (_tstat(cmdline, &st) == -1)
{
return; return;
}
// Create the filename of the logfile /* Create the filename of the logfile */
TCHAR script_log_filename[MAX_PATH]; TCHAR script_log_filename[MAX_PATH];
_sntprintf_0(script_log_filename, _T("%ls\\%ls_pre.log"), o.log_dir, c->config_name); _sntprintf_0(script_log_filename, _T("%ls\\%ls_pre.log"), o.log_dir, c->config_name);
// Create the log file /* Create the log file */
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
CLEAR(sa); CLEAR(sa);
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -133,16 +135,20 @@ RunConnectScript(connection_t *c, int run_as_service)
/* Return if no script exists */ /* Return if no script exists */
if (_tstat(cmdline, &st) == -1) if (_tstat(cmdline, &st) == -1)
{
return; return;
}
if (!run_as_service) if (!run_as_service)
{
SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONN_SCRIPT)); SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONN_SCRIPT));
}
// Create the filename of the logfile /* Create the filename of the logfile */
TCHAR script_log_filename[MAX_PATH]; TCHAR script_log_filename[MAX_PATH];
_sntprintf_0(script_log_filename, _T("%ls\\%ls_up.log"), o.log_dir, c->config_name); _sntprintf_0(script_log_filename, _T("%ls\\%ls_up.log"), o.log_dir, c->config_name);
// Create the log file /* Create the log file */
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
CLEAR(sa); CLEAR(sa);
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -175,7 +181,9 @@ RunConnectScript(connection_t *c, int run_as_service)
} }
if (o.connectscript_timeout == 0) if (o.connectscript_timeout == 0)
{
goto out; goto out;
}
for (i = 0; i <= (int) o.connectscript_timeout; i++) for (i = 0; i <= (int) o.connectscript_timeout; i++)
{ {
@ -188,7 +196,9 @@ RunConnectScript(connection_t *c, int run_as_service)
if (exit_code != STILL_ACTIVE) if (exit_code != STILL_ACTIVE)
{ {
if (exit_code != 0) if (exit_code != 0)
{
ShowLocalizedMsgEx(MB_OK|MB_ICONERROR, c->hwndStatus, TEXT(PACKAGE_NAME), IDS_ERR_CONN_SCRIPT_FAILED, exit_code); ShowLocalizedMsgEx(MB_OK|MB_ICONERROR, c->hwndStatus, TEXT(PACKAGE_NAME), IDS_ERR_CONN_SCRIPT_FAILED, exit_code);
}
goto out; goto out;
} }
@ -227,16 +237,20 @@ RunDisconnectScript(connection_t *c, int run_as_service)
/* Return if no script exists */ /* Return if no script exists */
if (_tstat(cmdline, &st) == -1) if (_tstat(cmdline, &st) == -1)
{
return; return;
}
if (!run_as_service) if (!run_as_service)
{
SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONN_SCRIPT)); SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONN_SCRIPT));
}
// Create the filename of the logfile /* Create the filename of the logfile */
TCHAR script_log_filename[MAX_PATH]; TCHAR script_log_filename[MAX_PATH];
_sntprintf_0(script_log_filename, _T("%ls\\%ls_down.log"), o.log_dir, c->config_name); _sntprintf_0(script_log_filename, _T("%ls\\%ls_down.log"), o.log_dir, c->config_name);
// Create the log file /* Create the log file */
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
CLEAR(sa); CLEAR(sa);
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);

@ -24,7 +24,9 @@
#define SCRIPTS_H #define SCRIPTS_H
void RunPreconnectScript(connection_t *); void RunPreconnectScript(connection_t *);
void RunConnectScript(connection_t *, int run_as_service); void RunConnectScript(connection_t *, int run_as_service);
void RunDisconnectScript(connection_t *, int run_as_service); void RunDisconnectScript(connection_t *, int run_as_service);
#endif #endif

@ -46,26 +46,32 @@ CheckIServiceStatus(BOOL warn)
SERVICE_STATUS ssStatus; SERVICE_STATUS ssStatus;
BOOL ret = false; BOOL ret = false;
// Open a handle to the SC Manager database. /* Open a handle to the SC Manager database. */
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (NULL == schSCManager) if (NULL == schSCManager)
{
return(false); return(false);
}
schService = OpenService(schSCManager, o.ovpn_engine == OPENVPN_ENGINE_OVPN3 ? schService = OpenService(schSCManager, o.ovpn_engine == OPENVPN_ENGINE_OVPN3 ?
OPENVPN_SERVICE_NAME_OVPN3 : OPENVPN_SERVICE_NAME_OVPN2, SERVICE_QUERY_STATUS); OPENVPN_SERVICE_NAME_OVPN3 : OPENVPN_SERVICE_NAME_OVPN2, SERVICE_QUERY_STATUS);
if (schService == NULL && if (schService == NULL
GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) && GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{ {
/* warn that iservice is not installed */ /* warn that iservice is not installed */
if (warn) if (warn)
{
ShowLocalizedMsg(IDS_ERR_INSTALL_ISERVICE); ShowLocalizedMsg(IDS_ERR_INSTALL_ISERVICE);
}
goto out; goto out;
} }
if (!QueryServiceStatus(schService, &ssStatus)) if (!QueryServiceStatus(schService, &ssStatus))
{
goto out; goto out;
}
if (ssStatus.dwCurrentState != SERVICE_RUNNING) if (ssStatus.dwCurrentState != SERVICE_RUNNING)
{ {
@ -73,9 +79,13 @@ CheckIServiceStatus(BOOL warn)
if (warn) if (warn)
{ {
if (IsUserAdmin()) if (IsUserAdmin())
{
ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE_ADM); ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE_ADM);
}
else else
{
ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE); ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE);
}
} }
goto out; goto out;
} }
@ -83,42 +93,49 @@ CheckIServiceStatus(BOOL warn)
out: out:
if (schService) if (schService)
{
CloseServiceHandle(schService); CloseServiceHandle(schService);
}
if (schSCManager) if (schSCManager)
{
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
}
return ret; return ret;
} }
VOID CheckServiceStatus() VOID
CheckServiceStatus()
{ {
SC_HANDLE schSCManager = NULL; SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL; SC_HANDLE schService = NULL;
SERVICE_STATUS ssStatus; SERVICE_STATUS ssStatus;
// Open a handle to the SC Manager database. /* Open a handle to the SC Manager database. */
schSCManager = OpenSCManager( schSCManager = OpenSCManager(
NULL, // local machine NULL, /* local machine */
NULL, // ServicesActive database NULL, /* ServicesActive database */
SC_MANAGER_CONNECT); // Connect rights SC_MANAGER_CONNECT); /* Connect rights */
if (NULL == schSCManager) { if (NULL == schSCManager)
{
o.service_state = service_noaccess; o.service_state = service_noaccess;
goto out; goto out;
} }
schService = OpenService( schService = OpenService(
schSCManager, // SCM database schSCManager, /* SCM database */
_T("OpenVPNService"), // service name _T("OpenVPNService"), /* service name */
SERVICE_QUERY_STATUS); SERVICE_QUERY_STATUS);
if (schService == NULL) { if (schService == NULL)
{
o.service_state = service_noaccess; o.service_state = service_noaccess;
goto out; goto out;
} }
if (!QueryServiceStatus( if (!QueryServiceStatus(
schService, // handle to service schService, /* handle to service */
&ssStatus) ) // address of status information structure &ssStatus) ) /* address of status information structure */
{ {
/* query failed */ /* query failed */
o.service_state = service_noaccess; o.service_state = service_noaccess;
@ -139,25 +156,32 @@ VOID CheckServiceStatus()
out: out:
if (schService) if (schService)
{
CloseServiceHandle(schService); CloseServiceHandle(schService);
}
if (schSCManager) if (schSCManager)
{
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
}
} }
/* Attempt to start OpenVPN Automatc Service */ /* Attempt to start OpenVPN Automatc Service */
void StartAutomaticService(void) void
StartAutomaticService(void)
{ {
SC_HANDLE schSCManager = NULL; SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL; SC_HANDLE schService = NULL;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schSCManager) { if (schSCManager)
{
schService = OpenService(schSCManager, L"OpenVPNService", SERVICE_START); schService = OpenService(schSCManager, L"OpenVPNService", SERVICE_START);
if (schService) { if (schService)
StartService(schService, 0, NULL); {
CloseServiceHandle(schService); StartService(schService, 0, NULL);
CloseServiceHandle(schService);
} }
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);

@ -20,6 +20,8 @@
*/ */
VOID CheckServiceStatus(); VOID CheckServiceStatus();
BOOL CheckIServiceStatus(BOOL warn); BOOL CheckIServiceStatus(BOOL warn);
/* Attempt to start OpenVPN Automatc Service */ /* Attempt to start OpenVPN Automatc Service */
void StartAutomaticService(void); void StartAutomaticService(void);

149
tray.c

@ -50,13 +50,14 @@ NOTIFYICONDATA ni;
extern options_t o; extern options_t o;
#define USE_NESTED_CONFIG_MENU ((o.config_menu_view == CONFIG_VIEW_AUTO && o.num_configs > 25) \ #define USE_NESTED_CONFIG_MENU ((o.config_menu_view == CONFIG_VIEW_AUTO && o.num_configs > 25) \
|| (o.config_menu_view == CONFIG_VIEW_NESTED)) || (o.config_menu_view == CONFIG_VIEW_NESTED))
static void static void
DeleteMenuBitmaps(void) DeleteMenuBitmaps(void)
{ {
if (hbmpConnecting) { if (hbmpConnecting)
{
DeleteObject(hbmpConnecting); DeleteObject(hbmpConnecting);
hbmpConnecting = NULL; hbmpConnecting = NULL;
} }
@ -92,8 +93,14 @@ CreateMenuBitmaps(void)
{ {
DeleteObject(iconinfo.hbmMask); DeleteObject(iconinfo.hbmMask);
DeleteObject(iconinfo.hbmColor); DeleteObject(iconinfo.hbmColor);
if (maskDC) DeleteDC(maskDC); if (maskDC)
if (imgDC) DeleteDC(imgDC); {
DeleteDC(maskDC);
}
if (imgDC)
{
DeleteDC(imgDC);
}
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Error creating DCs for drawing"); MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Error creating DCs for drawing");
return; return;
} }
@ -106,10 +113,14 @@ CreateMenuBitmaps(void)
COLORREF ref = RGB(255, 255, 255); COLORREF ref = RGB(255, 255, 255);
COLORREF bg = GetSysColor(COLOR_MENU); COLORREF bg = GetSysColor(COLOR_MENU);
for (int x = 0; x < cx; x++) { for (int x = 0; x < cx; x++)
for (int y = 0; y < cy; y++) { {
for (int y = 0; y < cy; y++)
{
if (GetPixel(maskDC, x, y) == ref) if (GetPixel(maskDC, x, y) == ref)
{
SetPixel(imgDC, x, y, bg); SetPixel(imgDC, x, y, bg);
}
} }
} }
@ -132,13 +143,18 @@ CreateMenuBitmaps(void)
void void
AllocateConnectionMenu() AllocateConnectionMenu()
{ {
if (hmenu_size >= o.num_configs) return; if (hmenu_size >= o.num_configs)
{
return;
}
HMENU *tmp = (HMENU *) realloc(hMenuConn, sizeof(HMENU)*(o.num_configs + 50)); HMENU *tmp = (HMENU *) realloc(hMenuConn, sizeof(HMENU)*(o.num_configs + 50));
if (tmp) { if (tmp)
{
hmenu_size = o.num_configs + 50; hmenu_size = o.num_configs + 50;
hMenuConn = tmp; hMenuConn = tmp;
} }
else { else
{
o.num_configs = hmenu_size; o.num_configs = hmenu_size;
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Allocation of hMenuConn failed. Ignoring configs beyond index = %d", o.num_configs); MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Allocation of hMenuConn failed. Ignoring configs beyond index = %d", o.num_configs);
} }
@ -175,7 +191,9 @@ CreatePopupMenus()
for (int i = 0; i < o.num_groups; i++) for (int i = 0; i < o.num_groups; i++)
{ {
if (!o.groups[i].active) if (!o.groups[i].active)
{
continue; continue;
}
o.groups[i].menu = CreatePopupMenu(); o.groups[i].menu = CreatePopupMenu();
o.groups[i].children = 0; /* we have to recount this when assigning menu position index */ o.groups[i].children = 0; /* we have to recount this when assigning menu position index */
} }
@ -188,7 +206,8 @@ CreatePopupMenus()
minfo.dwStyle |= MNS_NOTIFYBYPOS; minfo.dwStyle |= MNS_NOTIFYBYPOS;
SetMenuInfo(hMenu, &minfo); SetMenuInfo(hMenu, &minfo);
if (o.num_configs == 1 && o.chead) { if (o.num_configs == 1 && o.chead)
{
/* Set main menu's menudata to first connection */ /* Set main menu's menudata to first connection */
minfo.fMask = MIM_MENUDATA; minfo.fMask = MIM_MENUDATA;
GetMenuInfo(hMenu, &minfo); GetMenuInfo(hMenu, &minfo);
@ -215,12 +234,13 @@ CreatePopupMenus()
AppendMenu(hMenuImport, MF_STRING, IDM_IMPORT_AS, LoadLocalizedString(IDS_MENU_IMPORT_AS)); AppendMenu(hMenuImport, MF_STRING, IDM_IMPORT_AS, LoadLocalizedString(IDS_MENU_IMPORT_AS));
AppendMenu(hMenuImport, MF_STRING, IDM_IMPORT_URL, LoadLocalizedString(IDS_MENU_IMPORT_URL)); AppendMenu(hMenuImport, MF_STRING, IDM_IMPORT_URL, LoadLocalizedString(IDS_MENU_IMPORT_URL));
AppendMenu(hMenu, MF_STRING ,IDM_SETTINGS, LoadLocalizedString(IDS_MENU_SETTINGS)); AppendMenu(hMenu, MF_STRING, IDM_SETTINGS, LoadLocalizedString(IDS_MENU_SETTINGS));
AppendMenu(hMenu, MF_STRING ,IDM_CLOSE, LoadLocalizedString(IDS_MENU_CLOSE)); AppendMenu(hMenu, MF_STRING, IDM_CLOSE, LoadLocalizedString(IDS_MENU_CLOSE));
SetMenuStatus(o.chead, o.chead->state); SetMenuStatus(o.chead, o.chead->state);
} }
else { else
{
/* construct the submenu tree first */ /* construct the submenu tree first */
/* i = 0 is the root menu and has no parent */ /* i = 0 is the root menu and has no parent */
for (int i = 1; i < o.num_groups; i++) for (int i = 1; i < o.num_groups; i++)
@ -240,7 +260,7 @@ CreatePopupMenus()
this->pos = parent->children++; this->pos = parent->children++;
PrintDebug(L"Submenu %d named %ls added to parent %ls with position %d", PrintDebug(L"Submenu %d named %ls added to parent %ls with position %d",
i, this->name, parent->name, this->pos); i, this->name, parent->name, this->pos);
} }
/* add config file (connection) entries */ /* add config file (connection) entries */
@ -268,11 +288,13 @@ CreatePopupMenus()
c->pos = parent->children++; c->pos = parent->children++;
PrintDebug(L"Config %d named %ls added to submenu %ls with position %d", PrintDebug(L"Config %d named %ls added to submenu %ls with position %d",
c->id, c->config_name, parent->name, c->pos); c->id, c->config_name, parent->name, c->pos);
} }
if (o.num_configs > 0) if (o.num_configs > 0)
{
AppendMenu(hMenu, MF_SEPARATOR, 0, 0); AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
}
hMenuImport = CreatePopupMenu(); hMenuImport = CreatePopupMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR) hMenuImport, LoadLocalizedString(IDS_MENU_IMPORT)); AppendMenu(hMenu, MF_POPUP, (UINT_PTR) hMenuImport, LoadLocalizedString(IDS_MENU_IMPORT));
@ -337,17 +359,18 @@ OnNotifyTray(LPARAM lParam)
{ {
POINT pt; POINT pt;
switch (lParam) { switch (lParam)
case WM_RBUTTONUP: {
RecreatePopupMenus(); case WM_RBUTTONUP:
RecreatePopupMenus();
GetCursorPos(&pt); GetCursorPos(&pt);
SetForegroundWindow(o.hWnd); SetForegroundWindow(o.hWnd);
TrackPopupMenu(hMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, o.hWnd, NULL); TrackPopupMenu(hMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, o.hWnd, NULL);
PostMessage(o.hWnd, WM_NULL, 0, 0); PostMessage(o.hWnd, WM_NULL, 0, 0);
break; break;
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
{ {
int disconnected_conns = CountConnState(disconnected); int disconnected_conns = CountConnState(disconnected);
@ -355,26 +378,33 @@ OnNotifyTray(LPARAM lParam)
/* Start connection if only one config exist */ /* Start connection if only one config exist */
if (o.num_configs == 1 && o.chead->state == disconnected) if (o.num_configs == 1 && o.chead->state == disconnected)
StartOpenVPN(o.chead); {
StartOpenVPN(o.chead);
}
/* show the status window of all connected/connecting profiles upto a max of 10 */ /* show the status window of all connected/connecting profiles upto a max of 10 */
else if (disconnected_conns < o.num_configs) { else if (disconnected_conns < o.num_configs)
{
int num_shown = 0; int num_shown = 0;
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (c->state != disconnected && c->hwndStatus) { if (c->state != disconnected && c->hwndStatus)
{
ShowWindow(c->hwndStatus, SW_SHOW); ShowWindow(c->hwndStatus, SW_SHOW);
SetForegroundWindow(c->hwndStatus); SetForegroundWindow(c->hwndStatus);
if (++num_shown >= 10) break; if (++num_shown >= 10)
{
break;
}
} }
} }
} }
} }
break; break;
case WM_OVPN_RESCAN: case WM_OVPN_RESCAN:
/* Rescan config folders and recreate popup menus */ /* Rescan config folders and recreate popup menus */
RecreatePopupMenus(); RecreatePopupMenus();
break; break;
} }
} }
@ -398,15 +428,15 @@ OnDestroyTray()
void void
ShowTrayIcon() ShowTrayIcon()
{ {
ni.cbSize = sizeof(ni); ni.cbSize = sizeof(ni);
ni.uID = 0; ni.uID = 0;
ni.hWnd = o.hWnd; ni.hWnd = o.hWnd;
ni.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON; ni.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON;
ni.uCallbackMessage = WM_NOTIFYICONTRAY; ni.uCallbackMessage = WM_NOTIFYICONTRAY;
ni.hIcon = LoadLocalizedSmallIcon(ID_ICO_DISCONNECTED); ni.hIcon = LoadLocalizedSmallIcon(ID_ICO_DISCONNECTED);
_tcsncpy(ni.szTip, LoadLocalizedString(IDS_TIP_DEFAULT), _countof(ni.szTip)); _tcsncpy(ni.szTip, LoadLocalizedString(IDS_TIP_DEFAULT), _countof(ni.szTip));
Shell_NotifyIcon(NIM_ADD, &ni); Shell_NotifyIcon(NIM_ADD, &ni);
} }
void void
@ -426,7 +456,8 @@ SetTrayIcon(conn_state_t state)
first_conn = TRUE; first_conn = TRUE;
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (c->state == connected) { if (c->state == connected)
{
/* Append connection name to Icon Tip Msg */ /* Append connection name to Icon Tip Msg */
_tcsncat(msg, (first_conn ? msg_connected : _T(", ")), _countof(msg) - _tcslen(msg) - 1); _tcsncat(msg, (first_conn ? msg_connected : _T(", ")), _countof(msg) - _tcslen(msg) - 1);
_tcsncat(msg, c->config_name, _countof(msg) - _tcslen(msg) - 1); _tcsncat(msg, c->config_name, _countof(msg) - _tcslen(msg) - 1);
@ -438,7 +469,8 @@ SetTrayIcon(conn_state_t state)
first_conn = TRUE; first_conn = TRUE;
for (connection_t *c = o.chead; c; c = c->next) for (connection_t *c = o.chead; c; c = c->next)
{ {
if (c->state == connecting || c->state == resuming || c->state == reconnecting) { if (c->state == connecting || c->state == resuming || c->state == reconnecting)
{
/* Append connection name to Icon Tip Msg */ /* Append connection name to Icon Tip Msg */
_tcsncat(msg, (first_conn ? msg_connecting : _T(", ")), _countof(msg) - _tcslen(msg) - 1); _tcsncat(msg, (first_conn ? msg_connecting : _T(", ")), _countof(msg) - _tcslen(msg) - 1);
_tcsncat(msg, c->config_name, _countof(msg) - _tcslen(msg) - 1); _tcsncat(msg, c->config_name, _countof(msg) - _tcslen(msg) - 1);
@ -446,7 +478,8 @@ SetTrayIcon(conn_state_t state)
} }
} }
if (CountConnState(connected) == 1 && cc) { if (CountConnState(connected) == 1 && cc)
{
/* Append "Connected since and assigned IP" to message */ /* Append "Connected since and assigned IP" to message */
TCHAR time[50]; TCHAR time[50];
@ -463,9 +496,13 @@ SetTrayIcon(conn_state_t state)
icon_id = ID_ICO_CONNECTING; icon_id = ID_ICO_CONNECTING;
if (state == connected) if (state == connected)
{
icon_id = ID_ICO_CONNECTED; icon_id = ID_ICO_CONNECTED;
}
else if (state == disconnected) else if (state == disconnected)
{
icon_id = ID_ICO_DISCONNECTED; icon_id = ID_ICO_DISCONNECTED;
}
ni.cbSize = sizeof(ni); ni.cbSize = sizeof(ni);
ni.uID = 0; ni.uID = 0;
@ -490,9 +527,13 @@ CheckAndSetTrayIcon()
{ {
if (CountConnState(connecting) != 0 || CountConnState(reconnecting) != 0 if (CountConnState(connecting) != 0 || CountConnState(reconnecting) != 0
|| CountConnState(resuming) != 0) || CountConnState(resuming) != 0)
{
SetTrayIcon(connecting); SetTrayIcon(connecting);
}
else else
{
SetTrayIcon(disconnected); SetTrayIcon(disconnected);
}
} }
} }
@ -519,8 +560,14 @@ SetMenuStatus(connection_t *c, conn_state_t state)
int checked = 0; int checked = 0;
int i = c->id; int i = c->id;
if (state == connected || state == disconnecting) checked = 1; if (state == connected || state == disconnecting)
else if (state != disconnected && state != detached && state != onhold) checked = 2; {
checked = 1;
}
else if (state != disconnected && state != detached && state != onhold)
{
checked = 2;
}
if (o.num_configs == 1) if (o.num_configs == 1)
{ {
@ -553,9 +600,13 @@ SetMenuStatus(connection_t *c, conn_state_t state)
EnableMenuItem(hMenu, IDM_STATUSMENU, MF_ENABLED); EnableMenuItem(hMenu, IDM_STATUSMENU, MF_ENABLED);
} }
if (c->flags & (FLAG_SAVE_AUTH_PASS | FLAG_SAVE_KEY_PASS)) if (c->flags & (FLAG_SAVE_AUTH_PASS | FLAG_SAVE_KEY_PASS))
{
EnableMenuItem(hMenu, IDM_CLEARPASSMENU, MF_ENABLED); EnableMenuItem(hMenu, IDM_CLEARPASSMENU, MF_ENABLED);
}
else else
{
EnableMenuItem(hMenu, IDM_CLEARPASSMENU, MF_GRAYED); EnableMenuItem(hMenu, IDM_CLEARPASSMENU, MF_GRAYED);
}
} }
else else
{ {
@ -584,7 +635,7 @@ SetMenuStatus(connection_t *c, conn_state_t state)
CheckMenuItem(parent->menu, pos, MF_BYPOSITION | (checked ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(parent->menu, pos, MF_BYPOSITION | (checked ? MF_CHECKED : MF_UNCHECKED));
PrintDebug(L"Setting state of config %ls checked = %d, parent %ls, pos %d", PrintDebug(L"Setting state of config %ls checked = %d, parent %ls, pos %d",
c->config_name, checked, (parent->id == 0)? L"Main Menu" : L"SubMenu", pos); c->config_name, checked, (parent->id == 0) ? L"Main Menu" : L"SubMenu", pos);
if (checked) /* also check all parent groups */ if (checked) /* also check all parent groups */
{ {
@ -625,8 +676,12 @@ SetMenuStatus(connection_t *c, conn_state_t state)
EnableMenuItem(hMenuConn[i], IDM_STATUSMENU, MF_ENABLED); EnableMenuItem(hMenuConn[i], IDM_STATUSMENU, MF_ENABLED);
} }
if (c->flags & (FLAG_SAVE_AUTH_PASS | FLAG_SAVE_KEY_PASS)) if (c->flags & (FLAG_SAVE_AUTH_PASS | FLAG_SAVE_KEY_PASS))
{
EnableMenuItem(hMenuConn[i], IDM_CLEARPASSMENU, MF_ENABLED); EnableMenuItem(hMenuConn[i], IDM_CLEARPASSMENU, MF_ENABLED);
}
else else
{
EnableMenuItem(hMenuConn[i], IDM_CLEARPASSMENU, MF_GRAYED); EnableMenuItem(hMenuConn[i], IDM_CLEARPASSMENU, MF_GRAYED);
}
} }
} }

@ -46,15 +46,25 @@
#define IDM_RECONNECTMENU (1 + IDM_CLEARPASSMENU) #define IDM_RECONNECTMENU (1 + IDM_CLEARPASSMENU)
void RecreatePopupMenus(void); void RecreatePopupMenus(void);
void CreatePopupMenus(); void CreatePopupMenus();
void OnNotifyTray(LPARAM); void OnNotifyTray(LPARAM);
void OnDestroyTray(void); void OnDestroyTray(void);
void ShowTrayIcon(); void ShowTrayIcon();
void RemoveTrayIcon(); void RemoveTrayIcon();
void SetTrayIcon(conn_state_t); void SetTrayIcon(conn_state_t);
void SetMenuStatus(connection_t *, conn_state_t); void SetMenuStatus(connection_t *, conn_state_t);
void SetServiceMenuStatus(); void SetServiceMenuStatus();
void ShowTrayBalloon(TCHAR *, TCHAR *); void ShowTrayBalloon(TCHAR *, TCHAR *);
void CheckAndSetTrayIcon(); void CheckAndSetTrayIcon();
#endif #endif /* ifndef TRAY_H */

@ -37,112 +37,122 @@
extern options_t o; extern options_t o;
void ViewLog(connection_t *c) void
ViewLog(connection_t *c)
{ {
TCHAR filename[2*MAX_PATH]; TCHAR filename[2*MAX_PATH];
STARTUPINFO start_info; STARTUPINFO start_info;
PROCESS_INFORMATION proc_info; PROCESS_INFORMATION proc_info;
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd; SECURITY_DESCRIPTOR sd;
HINSTANCE status; HINSTANCE status;
CLEAR (start_info); CLEAR(start_info);
CLEAR (proc_info); CLEAR(proc_info);
CLEAR (sa); CLEAR(sa);
CLEAR (sd); CLEAR(sd);
/* Try first using file association */ /* Try first using file association */
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */
status = ShellExecuteW (o.hWnd, L"open", c->log_path, NULL, o.log_dir, SW_SHOWNORMAL); status = ShellExecuteW(o.hWnd, L"open", c->log_path, NULL, o.log_dir, SW_SHOWNORMAL);
if (status > (HINSTANCE) 32) /* Success */ if (status > (HINSTANCE) 32) /* Success */
return; {
else return;
PrintDebug (L"Opening log file using ShellExecute with verb = open failed" }
" for config '%ls' (status = %lu)", c->config_name, status); else
{
_sntprintf_0(filename, _T("%ls \"%ls\""), o.log_viewer, c->log_path); PrintDebug(L"Opening log file using ShellExecute with verb = open failed"
" for config '%ls' (status = %lu)", c->config_name, status);
/* fill in STARTUPINFO struct */ }
GetStartupInfo(&start_info);
start_info.cb = sizeof(start_info); _sntprintf_0(filename, _T("%ls \"%ls\""), o.log_viewer, c->log_path);
start_info.dwFlags = 0;
start_info.wShowWindow = SW_SHOWDEFAULT; /* fill in STARTUPINFO struct */
start_info.hStdInput = NULL; GetStartupInfo(&start_info);
start_info.hStdOutput = NULL; start_info.cb = sizeof(start_info);
start_info.dwFlags = 0;
if (!CreateProcess(NULL, start_info.wShowWindow = SW_SHOWDEFAULT;
filename, //commandline start_info.hStdInput = NULL;
NULL, start_info.hStdOutput = NULL;
NULL,
TRUE, if (!CreateProcess(NULL,
CREATE_NEW_CONSOLE, filename, /*commandline */
NULL, NULL,
o.log_dir, //start-up dir NULL,
&start_info, TRUE,
&proc_info)) CREATE_NEW_CONSOLE,
NULL,
o.log_dir, /*start-up dir */
&start_info,
&proc_info))
{ {
/* could not start log viewer */ /* could not start log viewer */
ShowLocalizedMsg(IDS_ERR_START_LOG_VIEWER, o.log_viewer); ShowLocalizedMsg(IDS_ERR_START_LOG_VIEWER, o.log_viewer);
} }
CloseHandle(proc_info.hThread); CloseHandle(proc_info.hThread);
CloseHandle(proc_info.hProcess); CloseHandle(proc_info.hProcess);
} }
void EditConfig(connection_t *c) void
EditConfig(connection_t *c)
{ {
TCHAR filename[2*MAX_PATH]; TCHAR filename[2*MAX_PATH];
STARTUPINFO start_info; STARTUPINFO start_info;
PROCESS_INFORMATION proc_info; PROCESS_INFORMATION proc_info;
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd; SECURITY_DESCRIPTOR sd;
HINSTANCE status; HINSTANCE status;
CLEAR (start_info); CLEAR(start_info);
CLEAR (proc_info); CLEAR(proc_info);
CLEAR (sa); CLEAR(sa);
CLEAR (sd); CLEAR(sd);
/* Try first using file association */ /* Try first using file association */
_sntprintf_0(filename, L"%ls\\%ls", c->config_dir, c->config_file); _sntprintf_0(filename, L"%ls\\%ls", c->config_dir, c->config_file);
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */
status = ShellExecuteW (o.hWnd, L"open", filename, NULL, c->config_dir, SW_SHOWNORMAL); status = ShellExecuteW(o.hWnd, L"open", filename, NULL, c->config_dir, SW_SHOWNORMAL);
if (status > (HINSTANCE) 32) if (status > (HINSTANCE) 32)
return; {
else return;
PrintDebug (L"Opening config file using ShellExecute with verb = open failed" }
" for config '%ls' (status = %lu)", c->config_name, status); else
{
_sntprintf_0(filename, _T("%ls \"%ls\\%ls\""), o.editor, c->config_dir, c->config_file); PrintDebug(L"Opening config file using ShellExecute with verb = open failed"
" for config '%ls' (status = %lu)", c->config_name, status);
/* fill in STARTUPINFO struct */ }
GetStartupInfo(&start_info);
start_info.cb = sizeof(start_info); _sntprintf_0(filename, _T("%ls \"%ls\\%ls\""), o.editor, c->config_dir, c->config_file);
start_info.dwFlags = 0;
start_info.wShowWindow = SW_SHOWDEFAULT; /* fill in STARTUPINFO struct */
start_info.hStdInput = NULL; GetStartupInfo(&start_info);
start_info.hStdOutput = NULL; start_info.cb = sizeof(start_info);
start_info.dwFlags = 0;
if (!CreateProcess(NULL, start_info.wShowWindow = SW_SHOWDEFAULT;
filename, //commandline start_info.hStdInput = NULL;
NULL, start_info.hStdOutput = NULL;
NULL,
TRUE, if (!CreateProcess(NULL,
CREATE_NEW_CONSOLE, filename, /*commandline */
NULL, NULL,
c->config_dir, //start-up dir NULL,
&start_info, TRUE,
&proc_info)) CREATE_NEW_CONSOLE,
NULL,
c->config_dir, /*start-up dir */
&start_info,
&proc_info))
{ {
/* could not start editor */ /* could not start editor */
ShowLocalizedMsg(IDS_ERR_START_CONF_EDITOR, o.editor); ShowLocalizedMsg(IDS_ERR_START_CONF_EDITOR, o.editor);
} }
CloseHandle(proc_info.hThread); CloseHandle(proc_info.hThread);
CloseHandle(proc_info.hProcess); CloseHandle(proc_info.hProcess);
} }

Loading…
Cancel
Save