Browse Source

Reformat source code with uncrustify

Closes: #445

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
pull/643/head
Frank Lichtenheld 1 year ago
parent
commit
2cb3c6e417
  1. 82
      access.c
  2. 2
      access.h
  3. 389
      as.c
  4. 1
      as.h
  5. 513
      chartable.h
  6. 2
      config-msvc.h.in
  7. 22
      config_parser.c
  8. 2
      config_parser.h
  9. 185
      echo.c
  10. 2
      echo.h
  11. 26
      env_set.c
  12. 2
      env_set.h
  13. 365
      localization.c
  14. 19
      localization.h
  15. 991
      main.c
  16. 45
      main.h
  17. 445
      manage.c
  18. 5
      manage.h
  19. 159
      misc.c
  20. 35
      misc.h
  21. 2
      openvpn-gui-res.h
  22. 1950
      openvpn.c
  23. 50
      openvpn.h
  24. 55
      openvpn_config.c
  25. 2
      openvpn_config.h
  26. 403
      options.c
  27. 17
      options.h
  28. 4
      pkcs11.c
  29. 10
      plap/plap_common.c
  30. 10
      plap/plap_common.h
  31. 77
      plap/plap_connection.c
  32. 2
      plap/plap_connection.h
  33. 22
      plap/plap_dll.c
  34. 4
      plap/plap_dll.h
  35. 34
      plap/plap_provider.c
  36. 98
      plap/stub.c
  37. 56
      plap/ui_glue.c
  38. 262
      proxy.c
  39. 4
      proxy.h
  40. 371
      registry.c
  41. 12
      registry.h
  42. 40
      save_pass.c
  43. 10
      save_pass.h
  44. 26
      scripts.c
  45. 2
      scripts.h
  46. 64
      service.c
  47. 2
      service.h
  48. 149
      tray.c
  49. 12
      tray.h
  50. 204
      viewlog.c

82
access.c

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

2
access.h

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

389
as.c

@ -44,7 +44,8 @@ void
SanitizeFilename(wchar_t *fname)
{
const wchar_t *reserved = L"<>:\"/\\|?*;"; /* remap these and ascii 1 to 31 */
while (*fname) {
while (*fname)
{
wchar_t c = *fname;
if (c < 32 || wcschr(reserved, c))
{
@ -80,12 +81,15 @@ ExtractProfileName(const WCHAR *profile, const WCHAR *default_name, WCHAR *out_n
WCHAR *ctx = NULL;
pch = wcstok_s(buf, L"\r\n", &ctx);
while (pch != NULL) {
if (wcsbegins(pch, PROFILE_NAME_TOKEN)) {
while (pch != NULL)
{
if (wcsbegins(pch, PROFILE_NAME_TOKEN))
{
wcsncpy(profile_name, pch + wcslen(PROFILE_NAME_TOKEN), PROFILE_NAME_LEN - 1);
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);
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 */
/* actual extension will be applied during import */
if (wcslen(friendly_name) > 0)
{
swprintf(out_name, out_name_length, L"%ls.ovpn", friendly_name);
}
else if (wcslen(profile_name) > 0)
{
swprintf(out_name, out_name_length, L"%ls.ovpn", profile_name);
}
else
{
swprintf(out_name, out_name_length, L"%ls.ovpn", default_name);
}
out_name[out_name_length - 1] = L'\0';
@ -114,7 +124,7 @@ ShowWinInetError(HANDLE hWnd)
{
WCHAR err[256] = { 0 };
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);
}
@ -128,26 +138,30 @@ struct UrlComponents
};
/**
* Extracts protocol, port and hostname from URL
*
* @param url URL to parse, length must be less than URL_MAX
*/
* Extracts protocol, port and hostname from URL
*
* @param url URL to parse, length must be less than URL_MAX
*/
void
ParseUrl(const WCHAR *url, struct UrlComponents* comps)
ParseUrl(const WCHAR *url, struct UrlComponents *comps)
{
ZeroMemory(comps, sizeof(struct UrlComponents));
comps->port = 443;
comps->https = true;
if (wcsbegins(url, L"http://")) {
if (wcsbegins(url, L"http://"))
{
url += 7;
} else if (wcsbegins(url, L"https://")) {
url +=8;
}
else if (wcsbegins(url, L"https://"))
{
url += 8;
}
WCHAR *strport = wcsstr(url, L":");
WCHAR *pathptr = wcsstr(url, L"/");
if (strport) {
if (strport)
{
wcsncpy_s(comps->host, URL_LEN, url, strport - url);
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
*/
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 size = READ_CHUNK_LEN;
*pbuf = calloc(1, size + 1);
char* buf = *pbuf;
if (buf == NULL) {
char *buf = *pbuf;
if (buf == NULL)
{
MessageBoxW(hWnd, L"Out of memory", _T(PACKAGE_NAME), MB_OK);
return FALSE;
}
while (true) {
while (true)
{
DWORD bytesRead = 0;
if (!InternetReadFile(hRequest, buf + pos, READ_CHUNK_LEN, &bytesRead)) {
if (!InternetReadFile(hRequest, buf + pos, READ_CHUNK_LEN, &bytesRead))
{
ShowWinInetError(hWnd);
return FALSE;
}
buf[pos + bytesRead] = '\0';
if (bytesRead == 0) {
if (bytesRead == 0)
{
size = pos;
break;
}
if (pos + bytesRead >= size) {
if (pos + bytesRead >= size)
{
size += READ_CHUNK_LEN;
*pbuf = realloc(*pbuf, size + 1);
if (!*pbuf) {
if (!*pbuf)
{
free(buf);
MessageBoxW(hWnd, L"Out of memory", _T(PACKAGE_NAME), MB_OK);
return FALSE;
@ -225,15 +245,17 @@ DownloadProfileContent(HANDLE hWnd, HINTERNET hRequest, char** pbuf, size_t* psi
INT_PTR CALLBACK
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:
param = (auth_param_t*)lParam;
param = (auth_param_t *)lParam;
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)param);
WCHAR *wstr = Widen(param->str);
if (!wstr) {
if (!wstr)
{
EndDialog(hwndDlg, LOWORD(wParam));
break;
}
@ -242,7 +264,9 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
/* Set password echo on if needed */
if (param->flags & FLAG_CR_ECHO)
{
SendMessage(GetDlgItem(hwndDlg, ID_EDT_RESPONSE), EM_SETPASSWORDCHAR, 0, 0);
}
SetForegroundWindow(hwndDlg);
@ -253,28 +277,30 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
break;
case WM_COMMAND:
param = (auth_param_t*)GetProp(hwndDlg, cfgProp);
param = (auth_param_t *)GetProp(hwndDlg, cfgProp);
switch (LOWORD(wParam)) {
case ID_EDT_RESPONSE:
if (!(param->flags & FLAG_CR_ECHO))
{
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
}
if (HIWORD(wParam) == EN_UPDATE) {
/* enable OK if response is non-empty */
BOOL enableOK = GetWindowTextLength((HWND)lParam);
EnableWindow(GetDlgItem(hwndDlg, IDOK), enableOK);
}
break;
switch (LOWORD(wParam))
{
case ID_EDT_RESPONSE:
if (!(param->flags & FLAG_CR_ECHO))
{
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
}
if (HIWORD(wParam) == EN_UPDATE)
{
/* enable OK if response is non-empty */
BOOL enableOK = GetWindowTextLength((HWND)lParam);
EnableWindow(GetDlgItem(hwndDlg, IDOK), enableOK);
}
break;
case IDOK: {
int len = 0;
GetDlgItemTextUtf8(hwndDlg, ID_EDT_RESPONSE, &param->cr_response, &len);
EndDialog(hwndDlg, LOWORD(wParam));
}
return TRUE;
return TRUE;
case IDCANCEL:
EndDialog(hwndDlg, LOWORD(wParam));
@ -408,7 +434,7 @@ DownloadProfile(HANDLE hWnd, const struct UrlComponents *comps, const char *user
HANDLE hConnect = NULL;
HANDLE hRequest = NULL;
BOOL result = FALSE;
char* buf = NULL;
char *buf = NULL;
/* need to make copy of password to use it for dynamic response */
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);
if (!hInternet) {
if (!hInternet)
{
ShowWinInetError(hWnd);
goto done;
}
@ -435,7 +462,8 @@ DownloadProfile(HANDLE hWnd, const struct UrlComponents *comps, const char *user
SetCursor(LoadCursorW(0, IDC_WAIT));
hConnect = InternetConnectW(hInternet, comps->host, comps->port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnect) {
if (!hConnect)
{
ShowWinInetError(hWnd);
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 */
req_flags |= comps->https ? INTERNET_FLAG_SECURE : 0;
hRequest = HttpOpenRequestW(hConnect, NULL, comps->path, NULL, NULL, NULL, req_flags, 0);
if (!hRequest) {
if (!hRequest)
{
ShowWinInetError(hWnd);
goto done;
}
again:
if (buf) {
if (buf)
{
free(buf);
buf = NULL;
}
@ -462,26 +492,30 @@ again:
/* handle cert errors */
/* 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
DWORD err = GetLastError();
if ((err == ERROR_INTERNET_INVALID_CA) ||
(err == ERROR_INTERNET_SEC_CERT_CN_INVALID) ||
(err == ERROR_INTERNET_SEC_CERT_DATE_INVALID) ||
(err == ERROR_INTERNET_SEC_CERT_REV_FAILED)) {
if ((err == ERROR_INTERNET_INVALID_CA)
|| (err == ERROR_INTERNET_SEC_CERT_CN_INVALID)
|| (err == ERROR_INTERNET_SEC_CERT_DATE_INVALID)
|| (err == ERROR_INTERNET_SEC_CERT_REV_FAILED))
{
/* ask user what to do and modify options if needed */
DWORD dlg_result = InternetErrorDlg(hWnd, hRequest,
err,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
NULL);
err,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS
|FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
|FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
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,
* 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 len = sizeof(flags);
InternetQueryOptionW(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&flags, &len);
@ -495,9 +529,11 @@ again:
goto again;
}
else
{
goto done;
}
}
#endif
#endif /* ifdef DEBUG */
ShowWinInetError(hWnd);
goto done;
}
@ -510,36 +546,49 @@ again:
size_t size = 0;
/* download profile content */
if ((status_code == 200) || (status_code == 401)) {
if ((status_code == 200) || (status_code == 401))
{
if (!DownloadProfileContent(hWnd, hRequest, &buf, &size))
{
goto done;
}
char* msg_begin = strstr(buf, "<Message>CRV1:");
char* msg_end = strstr(buf, "</Message>");
if ((status_code == 401) && msg_begin && msg_end) {
char *msg_begin = strstr(buf, "<Message>CRV1:");
char *msg_end = strstr(buf, "</Message>");
if ((status_code == 401) && msg_begin && msg_end)
{
*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)
{
goto done;
}
if (parse_dynamic_cr(msg_begin + 14, param)) {
if (parse_dynamic_cr(msg_begin + 14, param))
{
/* prompt user for dynamic challenge */
INT_PTR res = LocalizedDialogBoxParam(ID_DLG_CHALLENGE_RESPONSE, CRDialogFunc, (LPARAM)param);
if (res == IDOK)
{
_snprintf_0(password, "CRV1::%s::%s", param->id, param->cr_response);
}
free_auth_param(param);
if (res == IDOK)
{
goto again;
}
}
else {
else
{
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");
goto done;
}
@ -563,8 +612,9 @@ again:
if (strlen(comps->content_type) == 0 /* AS profile */
|| !ExtractFilenameFromHeader(hRequest, name, MAX_PATH))
{
WCHAR* wbuf = Widen(buf);
if (!wbuf) {
WCHAR *wbuf = Widen(buf);
if (!wbuf)
{
MessageBoxW(hWnd, L"Failed to convert profile content to wchar", _T(PACKAGE_NAME), MB_OK);
goto done;
}
@ -574,14 +624,16 @@ again:
/* save profile content into tmp file */
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);
goto done;
}
swprintf(out_path, out_path_size, L"%ls%ls", out_path, name);
out_path[out_path_size - 1] = '\0';
FILE* f = _wfopen(out_path, L"w");
if (f == NULL) {
FILE *f = _wfopen(out_path, L"w");
if (f == NULL)
{
MessageBoxW(hWnd, L"Unable to save downloaded profile", _T(PACKAGE_NAME), MB_OK);
goto done;
}
@ -592,26 +644,34 @@ again:
done:
if (buf)
{
free(buf);
}
/* wipe the password */
SecureZeroMemory(password, sizeof(password));
if (hRequest)
{
InternetCloseHandle(hRequest);
}
if (hConnect)
{
InternetCloseHandle(hConnect);
}
if (hInternet)
{
InternetCloseHandle(hInternet);
}
return result;
}
typedef enum {
server_as = 1,
server_generic = 2
server_as = 1,
server_generic = 2
} server_type_t;
INT_PTR CALLBACK
@ -623,116 +683,123 @@ ImportProfileFromURLDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
switch (msg)
{
case WM_INITDIALOG:
type = (server_type_t) lParam;
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)lParam);
SetStatusWinIcon(hwndDlg, ID_ICO_APP);
case WM_INITDIALOG:
type = (server_type_t) lParam;
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE)lParam);
SetStatusWinIcon(hwndDlg, ID_ICO_APP);
if (type == server_generic)
{
/* Change window title and hide autologin checkbox */
SetWindowTextW(hwndDlg, LoadLocalizedString(IDS_MENU_IMPORT_URL));
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);
if (type == server_generic)
{
/* Change window title and hide autologin checkbox */
SetWindowTextW(hwndDlg, LoadLocalizedString(IDS_MENU_IMPORT_URL));
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 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)
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);
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));
/* 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);
}
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)
free(username);
case IDCANCEL:
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
if (password_len > 0)
{
SecureZeroMemory(password, strlen(password));
free(password);
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
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));
return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
case WM_NCDESTROY:
RemoveProp(hwndDlg, cfgProp);
break;
case WM_NCDESTROY:
RemoveProp(hwndDlg, cfgProp);
break;
}
return FALSE;
}
void ImportConfigFromAS()
void
ImportConfigFromAS()
{
LocalizedDialogBoxParam(ID_DLG_URL_PROFILE_IMPORT, ImportProfileFromURLDialogFunc, (LPARAM) server_as);
}
void ImportConfigFromURL()
void
ImportConfigFromURL()
{
LocalizedDialogBoxParam(ID_DLG_URL_PROFILE_IMPORT, ImportProfileFromURLDialogFunc, (LPARAM) server_generic);
}

1
as.h

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

513
chartable.h

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

2
config-msvc.h.in

@ -22,7 +22,7 @@
#define PACKAGE_VERSION "11"
/* 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 */
#define PACKAGE_VERSION_RESOURCE_STR "@GUI_VERSION_MAJOR@.@GUI_VERSION_MINOR@.0.0"

22
config_parser.c

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

2
config_parser.h

@ -52,4 +52,4 @@ config_entry_t *config_parse(wchar_t *fname);
*/
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;
if (md_init(&ctx, CALG_SHA1) != 0)
{
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);
return;
}
@ -91,15 +93,18 @@ echo_msg_add_fp(struct echo_msg *msg, time_t timestamp)
static struct echo_msg_history *
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;
}
/* 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)
{
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)
{
len++;
if (len > 99) break; /* max 100 history items persisted */
if (len > 99)
{
break; /* max 100 history items persisted */
}
}
if (len == 0)
{
return;
}
size_t size = len*sizeof(struct echo_msg_fp);
struct echo_msg_fp *data = malloc(size);
@ -156,7 +166,9 @@ echo_msg_persist(connection_t *c)
data[i++] = hist->fp;
}
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);
}
free(data);
return;
@ -171,7 +183,9 @@ echo_msg_load(connection_t *c)
size_t size = GetConfigRegistryValue(c->config_name, L"echo_msg_history", NULL, 0);
if (size == 0)
{
return; /* no history in registry */
}
else if (size%item_len != 0)
{
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);
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;
}
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]);
}
@ -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 */
/* 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))
{
return;
@ -356,7 +372,9 @@ static wchar_t *
get_text_in_range(HWND h, CHARRANGE chrg)
{
if (chrg.cpMax <= chrg.cpMin)
return NULL;
{
return NULL;
}
size_t len = chrg.cpMax - chrg.cpMin;
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};
if (SendMessage(h, EM_GETTEXTRANGE, 0, (LPARAM)&txtrg) <= 0)
{
txt[0] = '\0';
}
else
{
txt[len] = '\0'; /* safety */
}
}
return txt;
}
@ -392,7 +414,9 @@ OnEnLinkNotify(HWND UNUSED hwnd, ENLINK *el)
/* get the link text */
wchar_t *url = get_text_in_range(el->nmhdr.hwndFrom, el->chrg);
if (url)
{
open_url(url);
}
free(url);
return 1;
}
@ -431,7 +455,7 @@ AddMessageBoxText(HWND hwnd, const wchar_t *text, const wchar_t *title, const wc
cfm.dwEffects |= CFE_ITALIC;
SendMessage(hmsg, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cfm);
/* Align to right */
/* Align to right */
pf.wAlignment = align[1];
SendMessage(hmsg, EM_SETPARAFORMAT, 0, (LPARAM) &pf);
SendMessage(hmsg, EM_REPLACESEL, FALSE, (LPARAM) from);
@ -500,69 +524,70 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
switch (msg)
{
case WM_INITDIALOG:
hIcon = LoadLocalizedIcon(ID_ICO_APP);
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)
case WM_INITDIALOG:
hIcon = LoadLocalizedIcon(ID_ICO_APP);
if (hIcon)
{
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
* Adds the current echo message and shows the window.
*/
case WM_OVPN_ECHOMSG:
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);
}
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;
wchar_t from[256];
@ -570,7 +595,9 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
/* strip \n added by _wctime */
if (wcslen(from) > 0)
{
from[wcslen(from)-1] = L'\0';
}
AddMessageBoxText(hwnd, c->echo_msg.text, c->echo_msg.title, from);
SetForegroundWindow(hwnd);
@ -578,16 +605,18 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
}
break;
case WM_NOTIFY:
nmh = (NMHDR*) lParam;
/* We handle only EN_LINK messages */
if (nmh->idFrom == ID_TXT_MESSAGE && nmh->code == EN_LINK)
return OnEnLinkNotify(hwnd, (ENLINK*)lParam);
break;
case WM_NOTIFY:
nmh = (NMHDR *) lParam;
/* We handle only EN_LINK messages */
if (nmh->idFrom == ID_TXT_MESSAGE && nmh->code == EN_LINK)
{
return OnEnLinkNotify(hwnd, (ENLINK *)lParam);
}
break;
case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE);
return TRUE;
case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE);
return TRUE;
}
return 0;

2
echo.h

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

26
env_set.c

@ -94,7 +94,10 @@ env_item_del(struct env_item *head, const wchar_t *name)
{
struct env_item *item, *prev = NULL;
if (!name) return head;
if (!name)
{
return head;
}
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 */
if (prev)
{
prev->next = item->next;
}
else /* head is going to be deleted */
{
head = item->next;
}
env_item_free(item);
break;
}
@ -132,7 +139,7 @@ env_item_insert(struct env_item *head, struct env_item *item)
cmp = env_name_compare(item->nameval, tmp->nameval);
if (cmp <= 0) /* found the position to add */
{
break;
break;
}
prev = tmp;
continue;
@ -148,9 +155,13 @@ env_item_insert(struct env_item *head, struct env_item *item)
}
if (prev)
{
prev->next = item;
}
else
{
head = item;
}
return head;
}
@ -194,13 +205,15 @@ env_item_new_utf8(const char *nameval)
/* Insert an env item to the set given nameval: name=val.
* 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)
{
struct env_item *item = env_item_new_utf8(nameval);
if (!item)
{
return head;
}
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)
{
;
}
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;
}
@ -291,7 +303,9 @@ merge_env_block(const struct env_item *es)
{
pe += len;
if (*pe) /* update len */
{
len = wcslen(pe) + 1;
}
}
}
/* 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;
if (!strbegins(msg, "setenv "))
{
return;
}
msg += strlen("setenv "); /* character following "setenv" */
msg += strspn(msg, " \t"); /* skip leading space */

2
env_set.h

@ -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
* pointer.
*/
wchar_t * merge_env_block(const struct env_item *es);
wchar_t *merge_env_block(const struct env_item *es);
#endif

365
localization.c

@ -52,18 +52,24 @@ FindResourceLang(PTSTR resType, PTSTR resId, LANGID langId)
/* try to find the resource in requested language */
res = FindResourceEx(o.hInstance, resType, resId, langId);
if (res)
{
return res;
}
/* try to find the resource in the default sublanguage */
LANGID defLangId = MAKELANGID(PRIMARYLANGID(langId), SUBLANG_DEFAULT);
res = FindResourceEx(o.hInstance, resType, resId, defLangId);
if (res)
{
return res;
}
/* try to find the resource in the default language */
res = FindResourceEx(o.hInstance, resType, resId, fallbackLangId);
if (res)
{
return res;
}
/* try to find the resource in any language */
return FindResource(o.hInstance, resId, resType);
@ -90,7 +96,9 @@ LANGID
GetGUILanguage(void)
{
if (gui_language != 0)
{
return gui_language;
}
HKEY regkey;
DWORD value = 0;
@ -113,8 +121,10 @@ SetGUILanguage(LANGID langId)
{
HKEY regkey;
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);
}
SetRegistryValueNumeric(regkey, _T("ui_language"), langId);
InitMUILanguage(langId);
@ -197,12 +207,16 @@ LoadStringLang(UINT stringId, LANGID langId, PTSTR buffer, int bufferSize, va_li
/* find resource block for string */
HRSRC res = FindResourceLang(RT_STRING, resBlockId, langId);
if (res == NULL)
{
goto err;
}
/* get pointer to first entry in resource block */
entry = (PWCH) LoadResource(o.hInstance, res);
if (entry == NULL)
{
goto err;
}
/* search for string in block */
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 */
if (i == resIndex && *entry == 0)
{
break;
}
/* string found, copy it */
PTSTR formatStr = (PTSTR) malloc((*entry + 1) * sizeof(TCHAR));
if (formatStr == NULL)
{
break;
}
formatStr[*entry] = 0;
wcsncpy(formatStr, entry + 1, *entry);
@ -234,7 +252,9 @@ LoadStringLang(UINT stringId, LANGID langId, PTSTR buffer, int bufferSize, va_li
err:
/* not found, try again with the default language */
if (langId != fallbackLangId)
{
return LoadStringLang(stringId, fallbackLangId, buffer, bufferSize, args);
}
return 0;
}
@ -276,7 +296,7 @@ static int
__ShowLocalizedMsgEx(const UINT type, HANDLE parent, LPCTSTR caption, const UINT stringId, va_list args)
{
return MessageBoxEx(parent, __LoadLocalizedString(stringId, args), caption,
type | MB_SETFOREGROUND | MBOX_RTL_FLAGS, GetGUILanguage());
type | MB_SETFOREGROUND | MBOX_RTL_FLAGS, GetGUILanguage());
}
int
@ -305,12 +325,16 @@ LoadLocalizedIconEx(const UINT iconId, int cxDesired, int cyDesired)
LANGID langId = GetGUILanguage();
HICON hIcon =
(HICON) LoadImage (o.hInstance, MAKEINTRESOURCE(iconId),
IMAGE_ICON, cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED);
(HICON) LoadImage(o.hInstance, MAKEINTRESOURCE(iconId),
IMAGE_ICON, cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED);
if (hIcon)
{
return hIcon;
}
else
PrintDebug (L"Loading icon using LoadImage failed.");
{
PrintDebug(L"Loading icon using LoadImage failed.");
}
/* Fallback to CreateIconFromResource which always scales
* from the first image in the resource
@ -318,51 +342,63 @@ LoadLocalizedIconEx(const UINT iconId, int cxDesired, int cyDesired)
/* find group icon resource */
HRSRC res = FindResourceLang(RT_GROUP_ICON, MAKEINTRESOURCE(iconId), langId);
if (res == NULL)
{
return NULL;
}
HGLOBAL resInfo = LoadResource(o.hInstance, res);
if (resInfo == NULL)
{
return NULL;
}
int id = LookupIconIdFromDirectory(resInfo, TRUE);
if (id == 0)
{
return NULL;
}
/* find the actual icon */
res = FindResourceLang(RT_ICON, MAKEINTRESOURCE(id), langId);
if (res == NULL)
{
return NULL;
}
resInfo = LoadResource(o.hInstance, res);
if (resInfo == NULL)
{
return NULL;
}
DWORD resSize = SizeofResource(o.hInstance, res);
if (resSize == 0)
{
return NULL;
}
/* Note: this uses the first icon in the resource and scales it */
hIcon = CreateIconFromResourceEx(resInfo, resSize, TRUE, 0x30000,
cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED);
cxDesired, cyDesired, LR_DEFAULTSIZE|LR_SHARED);
return hIcon;
}
HICON
LoadLocalizedIcon(const UINT iconId)
{
/* get the required normal icon size (e.g., taskbar icon) */
int cx = GetSystemMetrics(SM_CXICON);
int cy = GetSystemMetrics(SM_CYICON);
return LoadLocalizedIconEx(iconId, cx, cy);
/* get the required normal icon size (e.g., taskbar icon) */
int cx = GetSystemMetrics(SM_CXICON);
int cy = GetSystemMetrics(SM_CYICON);
return LoadLocalizedIconEx(iconId, cx, cy);
}
HICON
LoadLocalizedSmallIcon(const UINT iconId)
{
/* get the required small icon size (e.g., tray icon) */
int cx = GetSystemMetrics(SM_CXSMICON);
int cy = GetSystemMetrics(SM_CYSMICON);
return LoadLocalizedIconEx(iconId, cx, cy);
/* get the required small icon size (e.g., tray icon) */
int cx = GetSystemMetrics(SM_CXSMICON);
int cy = GetSystemMetrics(SM_CYSMICON);
return LoadLocalizedIconEx(iconId, cx, cy);
}
LPCDLGTEMPLATE
@ -371,7 +407,9 @@ LocalizedDialogResource(const UINT dialogId)
/* find dialog resource */
HRSRC res = FindResourceLang(RT_DIALOG, MAKEINTRESOURCE(dialogId), GetGUILanguage());
if (res == NULL)
{
return NULL;
}
return LoadResource(o.hInstance, res);
}
@ -388,7 +426,9 @@ LocalizedDialogBoxParamEx(const UINT dialogId, HWND owner, DLGPROC dialogFunc, c
{
LPCDLGTEMPLATE resInfo = LocalizedDialogResource(dialogId);
if (resInfo == NULL)
{
return -1;
}
return DialogBoxIndirectParam(o.hInstance, resInfo, owner, dialogFunc, param);
}
@ -399,11 +439,15 @@ CreateLocalizedDialogParam(const UINT dialogId, DLGPROC dialogFunc, const LPARAM
/* find dialog resource */
HRSRC res = FindResourceLang(RT_DIALOG, MAKEINTRESOURCE(dialogId), GetGUILanguage());
if (res == NULL)
{
return NULL;
}
HGLOBAL resInfo = LoadResource(o.hInstance, res);
if (resInfo == NULL)
{
return NULL;
}
return CreateDialogIndirectParam(o.hInstance, resInfo, o.hWnd, dialogFunc, param);
}
@ -438,59 +482,71 @@ typedef struct {
static BOOL
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));
ComboBox_SetItemData(data->languages, index, langId);
/* Select this item if it is the currently displayed language */
if (langId == data->language
|| (PRIMARYLANGID(langId) == PRIMARYLANGID(data->language)
&& ComboBox_GetCurSel(data->languages) == CB_ERR) )
|| (PRIMARYLANGID(langId) == PRIMARYLANGID(data->language)
&& ComboBox_GetCurSel(data->languages) == CB_ERR) )
{
ComboBox_SetCurSel(data->languages, index);
}
return TRUE;
}
static BOOL
static BOOL
GetLaunchOnStartup()
{
WCHAR regPath[MAX_PATH], exePath[MAX_PATH];
WCHAR regPath[MAX_PATH], exePath[MAX_PATH];
BOOL result = FALSE;
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) &&
GetModuleFileNameW(NULL, exePath, MAX_PATH)) {
if (GetRegistryValue(regkey, L"OpenVPN-GUI", regPath, MAX_PATH)
&& GetModuleFileNameW(NULL, exePath, MAX_PATH))
{
if (_wcsicmp(regPath, exePath) == 0)
{
result = TRUE;
}
}
RegCloseKey(regkey);
}
return result;
}
static void
SetLaunchOnStartup(BOOL value)
SetLaunchOnStartup(BOOL value)
{
WCHAR exePath[MAX_PATH];
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 (GetModuleFileNameW(NULL, exePath, MAX_PATH))
if (value)
{
if (GetModuleFileNameW(NULL, exePath, MAX_PATH))
{
SetRegistryValue(regkey, L"OpenVPN-GUI", exePath);
}
}
else
{
RegDeleteValue(regkey, L"OpenVPN-GUI");
}
else
RegDeleteValue(regkey, L"OpenVPN-GUI");
RegCloseKey(regkey);
@ -507,108 +563,155 @@ GeneralSettingsDlgProc(HWND hwndDlg, UINT msg, UNUSED WPARAM wParam, LPARAM lPar
.language = GetGUILanguage()
};
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;
switch (msg)
{
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;
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:
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;

19
localization.h

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

45
main.h

@ -28,16 +28,16 @@
#include <tchar.h>
/* Define this to enable DEBUG build */
//#define DEBUG
#define DEBUG_FILE L"C:\\windows\\temp\\openvpngui_debug.txt"
/*#define DEBUG */
#define DEBUG_FILE L"C:\\windows\\temp\\openvpngui_debug.txt"
/* 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_LINES 500 /* Max number of lines in 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 MAX_LOG_LINES 500 /* Max number of lines in 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 */
/* Authorized group who can use any options and config locations */
#define OVPN_ADMIN_GROUP TEXT("OpenVPN Administrators") /* May be reset in registry */
@ -78,11 +78,11 @@
#define NORETURN __attribute__ ((noreturn))
#endif
#define PACKVERSION(major,minor) MAKELONG(minor,major)
#define PACKVERSION(major, minor) MAKELONG(minor, major)
struct security_attributes
{
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
};
/* clear an object */
@ -90,9 +90,9 @@ struct security_attributes
/* _sntprintf with guaranteed \0 termination */
#define _sntprintf_0(buf, ...) \
do { \
__sntprintf_0(buf, _countof(buf), __VA_ARGS__); \
} while(0);
do { \
__sntprintf_0(buf, _countof(buf), __VA_ARGS__); \
} while(0);
static inline int
__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 */
#define _snprintf_0(buf, ...) \
do { \
__snprintf_0(buf, sizeof(buf), __VA_ARGS__); \
} while(0);
do { \
__snprintf_0(buf, sizeof(buf), __VA_ARGS__); \
} while(0);
static inline int
__snprintf_0(char *buf, size_t size, char *format, ...)
{
@ -126,14 +126,15 @@ __snprintf_0(char *buf, size_t size, char *format, ...)
#ifdef DEBUG
/* Print Debug Message */
#define PrintDebug(...) \
do { \
TCHAR x_msg[256]; \
_sntprintf_0(x_msg, __VA_ARGS__); \
PrintDebugMsg(x_msg); \
} while(0)
do { \
TCHAR x_msg[256]; \
_sntprintf_0(x_msg, __VA_ARGS__); \
PrintDebugMsg(x_msg); \
} while(0)
void PrintDebugMsg(TCHAR *msg);
#else
#else /* ifdef DEBUG */
#define PrintDebug(...) do { } while(0)
#endif
@ -141,4 +142,4 @@ DWORD GetDllVersion(LPCTSTR lpszDllName);
void ErrorExit(int exit_code, const wchar_t *msg);
#endif
#endif /* ifndef MAIN_H */

445
manage.c

@ -63,18 +63,22 @@ OpenManagement(connection_t *c)
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return FALSE;
}
c->manage.connected = 0;
c->manage.sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (c->manage.sk == INVALID_SOCKET)
{
WSACleanup ();
WSACleanup();
return FALSE;
}
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;
}
connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr));
c->manage.timeout = time(NULL) + max_connect_time;
@ -92,14 +96,20 @@ SendCommand(connection_t *c)
int res;
mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (cmd == NULL || cmd->size == 0)
{
return;
}
res = send(c->manage.sk, cmd->command, cmd->size, 0);
if (res < 1)
{
return;
}
if (res != cmd->size)
{
memmove(cmd->command, cmd->command + 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));
if (cmd == NULL)
{
return FALSE;
}
cmd->size = strlen(command) + 1;
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)
{
SendCommand(c);
}
return TRUE;
}
@ -155,7 +169,9 @@ UnqueueCommand(connection_t *c)
{
mgmt_cmd_t *cmd = c->manage.cmd_queue;
if (!cmd)
{
return FALSE;
}
/* Wipe command as it may contain passwords */
memset(cmd->command, 'x', cmd->size);
@ -197,241 +213,281 @@ OnManagement(SOCKET sk, LPARAM lParam)
connection_t *c = GetConnByManagement(sk);
if (c == NULL)
{
return;
}
switch (WSAGETSELECTEVENT(lParam))
{
case FD_CONNECT:
if (WSAGETSELECTERROR(lParam))
{
/* keep trying for connections with persistent daemons */
if (c->flags & FLAG_DAEMON_PERSISTENT
|| time(NULL) < c->manage.timeout)
case FD_CONNECT:
if (WSAGETSELECTERROR(lParam))
{
/* show a message on status window */
if (rtmsg_handler[log_] && (c->flags & FLAG_DAEMON_PERSISTENT))
/* keep trying for connections with persistent daemons */
if (c->flags & FLAG_DAEMON_PERSISTENT
|| time(NULL) < c->manage.timeout)
{
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);
/* show a message on status window */
if (rtmsg_handler[log_] && (c->flags & FLAG_DAEMON_PERSISTENT))
{
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
{
/* Connection to MI timed out. */
CloseManagement (c);
if (c->state != disconnected)
rtmsg_handler[timeout_](c, "");
c->manage.connected = 1;
}
}
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;
}
break;
offset = 0;
while (offset < data_size)
{
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
case FD_READ:
if (ioctlsocket(c->manage.sk, FIONREAD, &data_size) != 0
|| data_size == 0)
{
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);
if (c->manage.saved_data)
{
c->manage.saved_size = line_size;
memcpy(c->manage.saved_data, line, c->manage.saved_size);
}
break;
return;
}
offset += (pos - line) + 1;
/* Reply to a management password request */
if (*c->manage.password && passwd_request)
res = recv(c->manage.sk, data + c->manage.saved_size, data_size, 0);
if (res != (int) data_size)
{
ManagementCommand(c, c->manage.password, NULL, regular);
SecureZeroMemory(c->manage.password, sizeof(c->manage.password));
continue;
free(data);
return;
}
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 */
MsgToEventLog(EVENTLOG_WARNING_TYPE, L"%ls: management password mismatch",
c->config_name);
c->state = disconnecting;
CloseManagement (c);
rtmsg_handler[stop_](c, "");
continue;
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;
}
/* Handle regular management interface output */
line[pos - line - 1] = '\0';
if (line[0] == '>')
offset = 0;
while (offset < data_size)
{
/* Real time notifications */
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)
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)
{
if (rtmsg_handler[hold_])
rtmsg_handler[hold_](c, pos + 5);
pos = memchr(line, ':', line_size);
passwd_request = true;
}
else if (strncmp(pos, "PASSWORD:", 9) == 0)
else
{
if (rtmsg_handler[password_])
rtmsg_handler[password_](c, pos + 9);
pos = memchr(line, '\n', line_size);
}
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 (pos == NULL)
{
if (rtmsg_handler[needstr_])
rtmsg_handler[needstr_](c, pos + 9);
c->manage.saved_data = malloc(line_size);
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_])
rtmsg_handler[echo_](c, pos + 5);
ManagementCommand(c, c->manage.password, NULL, regular);
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_])
rtmsg_handler[bytecount_](c, pos + 10);
/* either we don't have a password or we used it and didn't match */
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_])
rtmsg_handler[infomsg_](c, pos + 8);
/* Real time notifications */
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
&& c->manage.cmd_queue)
else if (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.
*/
/* Response to commands */
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);
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);
break;
free(data);
break;
case FD_WRITE:
SendCommand(c);
break;
case FD_WRITE:
SendCommand(c);
break;
case FD_CLOSE:
CloseManagement (c);
if (rtmsg_handler[stop_])
rtmsg_handler[stop_](c, "");
break;
case FD_CLOSE:
CloseManagement(c);
if (rtmsg_handler[stop_])
{
rtmsg_handler[stop_](c, "");
}
break;
}
}
@ -450,7 +506,8 @@ CloseManagement(connection_t *c)
c->manage.sk = INVALID_SOCKET;
c->manage.connected = 0;
while (UnqueueCommand(c))
;
{
}
WSACleanup();
}
}

5
manage.h

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

35
misc.h

@ -27,30 +27,44 @@
#include "options.h"
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 EnsureDirExists(LPTSTR);
BOOL streq(LPCSTR, LPCSTR);
BOOL strbegins(const char *str, const char *begin);
BOOL wcsbegins(LPCWSTR, LPCWSTR);
BOOL ForceForegroundWindow(HWND);
void DpiSetScale(options_t*, UINT dpix);
void DpiSetScale(options_t *, UINT dpix);
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);
int Base64Decode(const char *input, char **output);
WCHAR *Widen(const char *utf8);
WCHAR *WidenEx(UINT codepage, const char *utf8);
BOOL validate_input(const WCHAR *input, const WCHAR *exclude);
/* Concatenate two wide strings with a separator */
void wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WCHAR *sep);
void CloseSemaphore(HANDLE sem);
/* Close a handle if not null or invalid */
void CloseHandleEx(LPHANDLE h);
@ -61,25 +75,27 @@ char *url_decode(const char *src);
/* digest functions */
typedef struct md_ctx {
HCRYPTPROV prov;
HCRYPTHASH hash;
HCRYPTPROV prov;
HCRYPTHASH hash;
} md_ctx;
DWORD md_init(md_ctx *ctx, ALG_ID hash_type);
DWORD md_update(md_ctx *ctx, const BYTE *data, size_t size);
DWORD md_final(md_ctx *ctx, BYTE *md);
/* Open specified http/https URL using ShellExecute. */
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.
* Caller must free *str if *len != 0.
*/
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 */
char *escape_string(const char *str);
@ -157,6 +173,7 @@ bool OVPNMsgWait(DWORD timeout, HWND hdlg);
bool GetRandomPassword(char *buf, size_t len);
void ResetPasswordReveal(HWND edit, HWND btn, WPARAM wParam);
void ChangePasswordVisibility(HWND edit, HWND btn, WPARAM wParam);
#endif
#endif /* ifndef MISC_H */

2
openvpn-gui-res.h

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

1950
openvpn.c

File diff suppressed because it is too large Load Diff

50
openvpn.h

@ -26,33 +26,51 @@
#include "options.h"
#define TRY_SETPROP(hwnd, name, p) \
do { if (SetPropW(hwnd, name, p)) break; \
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs:%d GetProp returned null", \
__func__, __LINE__); \
EndDialog(hwnd, IDABORT); \
return false; \
} while(0)
do { if (SetPropW(hwnd, name, p)) break; \
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs:%d GetProp returned null", \
__func__, __LINE__); \
EndDialog(hwnd, IDABORT); \
return false; \
} while(0)
BOOL StartOpenVPN(connection_t *);
void StopOpenVPN(connection_t *);
void DetachOpenVPN(connection_t *);
void SuspendOpenVPN(int config);
void RestartOpenVPN(connection_t *);
void ReleaseOpenVPN(connection_t *);
BOOL CheckVersion();
void SetStatusWinIcon(HWND hwndDlg, int IconID);
void OnReady(connection_t *, char *);
void OnHold(connection_t *, char *);
void OnLogLine(connection_t *, char *);
void OnStateChange(connection_t *, char *);
void OnPassword(connection_t *, char *);
void OnStop(connection_t *, char *);
void OnNeedOk(connection_t *, char *);
void OnNeedStr(connection_t *, char *);
void OnEcho(connection_t *, char *);
void OnByteCount(connection_t *, char *);
void OnInfoMsg(connection_t*, char*);
void OnInfoMsg(connection_t *, char *);
void OnTimeout(connection_t *, char *);
void ResetSavePasswords(connection_t *);
@ -66,7 +84,7 @@ extern const TCHAR *cfgProp;
#define ERROR_MESSAGE_TYPE 0x20000003
/* 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_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 */
typedef struct {
connection_t* c;
connection_t *c;
unsigned int flags;
char* str;
char* id;
char* user;
char* cr_response;
char *str;
char *id;
char *user;
char *cr_response;
} auth_param_t;
/*
@ -92,10 +110,10 @@ typedef struct {
* even on error.
*/
BOOL
parse_dynamic_cr(const char* str, auth_param_t* param);
parse_dynamic_cr(const char *str, auth_param_t *param);
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
@ -103,4 +121,4 @@ free_auth_param(auth_param_t* param);
*/
int daemon_state_resid(const char *name);
#endif
#endif /* ifndef OPENVPN_H */

55
openvpn_config.c

@ -50,28 +50,34 @@ match(const WIN32_FIND_DATA *find, const TCHAR *ext)
int i;
if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
return match_dir;
}
if (ext_len == 0)
{
return match_file;
}
i = _tcslen(find->cFileName) - ext_len - 1;
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_false;
}
static bool
CheckReadAccess (const TCHAR *dir, const TCHAR *file)
CheckReadAccess(const TCHAR *dir, const TCHAR *file)
{
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
@ -80,7 +86,9 @@ ConfigAlreadyExists(TCHAR *newconfig)
for (connection_t *c = o.chead; c; c = c->next)
{
if (_tcsicmp(c->config_file, newconfig) == 0)
{
return true;
}
}
return false;
}
@ -148,9 +156,13 @@ AddConfigFileToList(int group, const TCHAR *filename, const TCHAR *config_dir)
else
{
if (IsAuthPassSaved(c->config_name))
{
c->flags |= FLAG_SAVE_AUTH_PASS;
}
if (IsKeyPassSaved(c->config_name))
{
c->flags |= FLAG_SAVE_KEY_PASS;
}
}
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 */
for (int i = 0; i < o.num_groups; i++)
{
o.groups[i].children = 0;
}
/* count children of each group -- this includes groups
* and configs which have it as parent
@ -229,7 +243,9 @@ ActivateConfigGroups(void)
config_group_t *this = &o.groups[i];
config_group_t *parent = PARENT_GROUP(this);
if (parent) /* should be true as i = 0 is omitted */
{
parent->children++;
}
/* unless activated below the group stays inactive */
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);
find_handle = FindFirstFile(find_string, &find_obj);
if (find_handle == INVALID_HANDLE_VALUE)
{
return;
}
/* Loop over each config file in config dir */
do
@ -301,11 +319,13 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, int group, int flags)
if (ConfigAlreadyExists(find_obj.cFileName))
{
if (flags & FLAG_WARN_DUPLICATES)
{
ShowLocalizedMsg(IDS_ERR_CONFIG_EXIST, find_obj.cFileName);
}
continue;
}
if (CheckReadAccess (config_dir, find_obj.cFileName))
if (CheckReadAccess(config_dir, find_obj.cFileName))
{
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 */
if (recurse_depth < 1)
{
return;
}
find_handle = FindFirstFile (find_string, &find_obj);
find_handle = FindFirstFile(find_string, &find_obj);
if (find_handle == INVALID_HANDLE_VALUE)
{
return;
}
do
{
@ -389,13 +413,16 @@ IsSamePath(const wchar_t *path1, const wchar_t *path2)
BOOL ret = false;
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))
{
ret = (info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
&& info1.nFileIndexLow == info2.nFileIndexLow
&& info1.nFileIndexHigh == info2.nFileIndexHigh);
&& info1.nFileIndexLow == info2.nFileIndexLow
&& info1.nFileIndexHigh == info2.nFileIndexHigh);
}
return ret;
@ -410,7 +437,9 @@ BuildFileList()
static int root_gp, system_gp, persistent_gp;
if (o.silent_connection)
{
issue_warnings = false;
}
/*
* 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;
}
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))
{
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
@ -450,12 +479,14 @@ BuildFileList()
{
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)
{
ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir);
}
ActivateConfigGroups();

2
openvpn_config.h

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

403
options.c

@ -50,37 +50,37 @@
extern options_t o;
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};
return v;
}
static void
ExpandString (WCHAR *str, int max_len)
ExpandString(WCHAR *str, int max_len)
{
WCHAR expanded_string[MAX_PATH];
int len = ExpandEnvironmentStringsW (str, expanded_string, _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);
return;
}
wcsncpy (str, expanded_string, max_len);
WCHAR expanded_string[MAX_PATH];
int len = ExpandEnvironmentStringsW(str, expanded_string, _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);
return;
}
wcsncpy(str, expanded_string, max_len);
}
void
ExpandOptions (void)
ExpandOptions(void)
{
ExpandString (o.exe_path, _countof(o.exe_path));
ExpandString (o.config_dir, _countof(o.config_dir));
ExpandString (o.global_config_dir, _countof(o.global_config_dir));
ExpandString (o.config_auto_dir, _countof(o.config_auto_dir));
ExpandString (o.log_dir, _countof(o.log_dir));
ExpandString (o.editor, _countof(o.editor));
ExpandString (o.log_viewer, _countof(o.log_viewer));
ExpandString (o.install_path, _countof(o.install_path));
ExpandString(o.exe_path, _countof(o.exe_path));
ExpandString(o.config_dir, _countof(o.config_dir));
ExpandString(o.global_config_dir, _countof(o.global_config_dir));
ExpandString(o.config_auto_dir, _countof(o.config_auto_dir));
ExpandString(o.log_dir, _countof(o.log_dir));
ExpandString(o.editor, _countof(o.editor));
ExpandString(o.log_viewer, _countof(o.log_viewer));
ExpandString(o.install_path, _countof(o.install_path));
}
static int
@ -157,8 +157,8 @@ add_option(options_t *options, int i, TCHAR **p)
++i;
_tcsncpy(options->priority_string, p[1], _countof(options->priority_string) - 1);
}
else if ( (streq(p[0], _T("append_string")) ||
streq(p[0], _T("log_append"))) && p[1] )
else if ( (streq(p[0], _T("append_string"))
|| streq(p[0], _T("log_append"))) && p[1])
{
++i;
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])
{
++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])
{
++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])
{
++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])
{
++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])
{
@ -206,7 +206,7 @@ add_option(options_t *options, int i, TCHAR **p)
else if (streq(p[0], _T("service_only")) && p[1])
{
++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])
{
@ -221,7 +221,7 @@ add_option(options_t *options, int i, TCHAR **p)
else if (streq(p[0], _T("passphrase_attempts")) && p[1])
{
++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])
{
@ -362,7 +362,9 @@ parse_argv(options_t *options, int argc, TCHAR **argv)
{
TCHAR *arg = argv[i + j];
if (_tcsncmp(arg, _T("--"), 2) == 0)
{
break;
}
p[j] = arg;
}
}
@ -375,8 +377,8 @@ void
InitOptions(options_t *opt)
{
CLEAR(*opt);
opt->netcmd_semaphore = InitSemaphore (NULL);
opt->version = MakeVersion (PACKAGE_VERSION_RESOURCE);
opt->netcmd_semaphore = InitSemaphore(NULL);
opt->version = MakeVersion(PACKAGE_VERSION_RESOURCE);
opt->clr_warning = RGB(0xff, 0, 0);
opt->clr_error = RGB(0xff, 0, 0);
}
@ -393,49 +395,67 @@ ProcessCommandLine(options_t *options, TCHAR *command_line)
do
{
while (*pos == _T(' '))
{
++pos;
}
if (*pos == _T('\0'))
{
break;
}
++argc;
while (*pos != _T('\0') && *pos != _T(' '))
++pos;
{
++pos;
}
}
while (*pos != _T('\0'));
if (argc == 0)
{
return;
}
/* Tokenize the arguments */
argv = (TCHAR**) malloc(argc * sizeof(TCHAR*));
argv = (TCHAR **) malloc(argc * sizeof(TCHAR *));
pos = command_line;
argc = 0;
do
{
while (*pos == _T(' '))
{
pos++;
}
if (*pos == _T('\0'))
{
break;
}
if (*pos == _T('\"'))
{
argv[argc++] = ++pos;
while (*pos != _T('\0') && *pos != _T('\"'))
{
++pos;
}
}
else
{
argv[argc++] = pos;
while (*pos != _T('\0') && *pos != _T(' '))
{
++pos;
}
}
if (*pos == _T('\0'))
{
break;
}
*pos++ = _T('\0');
}
@ -445,7 +465,7 @@ ProcessCommandLine(options_t *options, TCHAR *command_line)
free(argv);
ExpandOptions ();
ExpandOptions();
}
@ -458,52 +478,58 @@ CountConnState(conn_state_t check)
for (connection_t *c = o.chead; c; c = c->next)
{
if (c->state == check)
{
++count;
}
}
return count;
}
connection_t*
connection_t *
GetConnByManagement(SOCKET sk)
{
for (connection_t *c = o.chead; c; c = c->next)
{
if (c->manage.sk == sk)
{
return c;
}
}
return NULL;
}
connection_t*
connection_t *
GetConnByName(const WCHAR *name)
{
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)
{
return c;
}
}
return NULL;
}
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;
// Create dialog
/* Create dialog */
initResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(initResult))
{
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))
{
// Select folders, not files
/* Select folders, not files */
DWORD dwOptions;
result = pfd->lpVtbl->GetOptions(pfd, &dwOptions);
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);
}
// Set initial path
IShellItem* psi;
result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, (void**)&psi);
/* Set initial path */
IShellItem *psi;
result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, (void **)&psi);
if (SUCCEEDED(result))
{
pfd->lpVtbl->SetFolder(pfd, 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);
if (SUCCEEDED(dialogResult))
{
IShellItem* psi;
IShellItem *psi;
LPOLESTR path = NULL;
result = pfd->lpVtbl->GetResult(pfd, &psi);
if(SUCCEEDED(result))
if (SUCCEEDED(result))
{
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);
}
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);
}
static BOOL
CheckAdvancedDlgParams (HWND hdlg)
CheckAdvancedDlgParams(HWND hdlg)
{
WCHAR tmp_path[MAX_PATH];
/* replace empty entries by current values */
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_LOG_DIR, o.log_dir);
if (GetWindowTextLength (GetDlgItem(hdlg, ID_EDT_CONFIG_EXT)) == 0)
SetDlgItemText (hdlg, ID_EDT_CONFIG_EXT, o.ext_string);
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_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 */
GetDlgItemText (hdlg, ID_EDT_CONFIG_DIR, tmp_path, _countof(tmp_path));
ExpandString (tmp_path, _countof(tmp_path));
if (PathIsRelativeW (tmp_path))
GetDlgItemText(hdlg, ID_EDT_CONFIG_DIR, tmp_path, _countof(tmp_path));
ExpandString(tmp_path, _countof(tmp_path));
if (PathIsRelativeW(tmp_path))
{
MessageBox (hdlg, L"Specified config directory is not an absolute path",
L"Option error", MB_OK);
MessageBox(hdlg, L"Specified config directory is not an absolute path",
L"Option error", MB_OK);
return false;
}
GetDlgItemText (hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path));
ExpandString (tmp_path, _countof(tmp_path));
if (PathIsRelativeW (tmp_path))
GetDlgItemText(hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path));
ExpandString(tmp_path, _countof(tmp_path));
if (PathIsRelativeW(tmp_path))
{
MessageBox (hdlg, L"Specified log directory is not an absolute path",
L"Option error", MB_OK);
MessageBox(hdlg, L"Specified log directory is not an absolute path",
L"Option error", MB_OK);
return false;
}
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 */
if (!status || (tmp < 1 || tmp > 61000))
{
MessageBox (hdlg, L"Specified port is not valid (must be in the range 1 to 61000)",
L"Option error", MB_OK);
MessageBox(hdlg, L"Specified port is not valid (must be in the range 1 to 61000)",
L"Option error", MB_OK);
return false;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_POPUP_MUTE, &status, FALSE);
tmp = GetDlgItemInt(hdlg, ID_EDT_POPUP_MUTE, &status, FALSE);
if (!status || tmp < 0)
{
MessageBox (hdlg, L"Specified mute interval is not valid (must be a positive integer)",
L"Option error", MB_OK);
MessageBox(hdlg, L"Specified mute interval is not valid (must be a positive integer)",
L"Option error", MB_OK);
return false;
}
@ -614,159 +646,202 @@ CheckAdvancedDlgParams (HWND hdlg)
}
static BOOL
SaveAdvancedDlgParams (HWND hdlg)
SaveAdvancedDlgParams(HWND hdlg)
{
WCHAR tmp_path[MAX_PATH], tmp_path1[MAX_PATH];
UINT tmp;
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));
wcsncpy (tmp_path1, tmp_path, _countof(tmp_path1));
ExpandString (tmp_path1, _countof(tmp_path1));
GetDlgItemText(hdlg, ID_EDT_LOG_DIR, tmp_path, _countof(tmp_path));
wcsncpy(tmp_path1, tmp_path, _countof(tmp_path1));
ExpandString(tmp_path1, _countof(tmp_path1));
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 */
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 */
}
else
{
ShowLocalizedMsg(IDS_ERR_CREATE_PATH, L"Log", tmp_path1);
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);
if (status && tmp > 0) o.preconnectscript_timeout = tmp;
tmp = GetDlgItemInt(hdlg, ID_EDT_PRECONNECT_TIMEOUT, &status, FALSE);
if (status && tmp > 0)
{
o.preconnectscript_timeout = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_CONNECT_TIMEOUT, &status, FALSE);
if (status) o.connectscript_timeout = tmp;
tmp = GetDlgItemInt(hdlg, ID_EDT_CONNECT_TIMEOUT, &status, FALSE);
if (status)
{
o.connectscript_timeout = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_DISCONNECT_TIMEOUT, &status, FALSE);
if (status && tmp > 0) o.disconnectscript_timeout = tmp;
tmp = GetDlgItemInt(hdlg, ID_EDT_DISCONNECT_TIMEOUT, &status, FALSE);
if (status && tmp > 0)
{
o.disconnectscript_timeout = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_MGMT_PORT, &status, FALSE);
if (status) o.mgmt_port_offset = tmp;
tmp = GetDlgItemInt(hdlg, ID_EDT_MGMT_PORT, &status, FALSE);
if (status)
{
o.mgmt_port_offset = tmp;
}
tmp = GetDlgItemInt (hdlg, ID_EDT_POPUP_MUTE, &status, FALSE);
if (status) o.popup_mute_interval = tmp;
tmp = GetDlgItemInt(hdlg, ID_EDT_POPUP_MUTE, &status, FALSE);
if (status)
{
o.popup_mute_interval = tmp;
}
o.ovpn_engine = IsDlgButtonChecked(hdlg, ID_RB_ENGINE_OVPN3) ?
OPENVPN_ENGINE_OVPN3 : OPENVPN_ENGINE_OVPN2;
OPENVPN_ENGINE_OVPN3 : OPENVPN_ENGINE_OVPN2;
SaveRegistryKeys ();
ExpandOptions ();
SaveRegistryKeys();
ExpandOptions();
return true;
}
static void
LoadAdvancedDlgParams (HWND hdlg)
LoadAdvancedDlgParams(HWND hdlg)
{
SetDlgItemText (hdlg, ID_EDT_CONFIG_DIR, o.config_dir);
SetDlgItemText (hdlg, ID_EDT_CONFIG_EXT, o.ext_string);
SetDlgItemText (hdlg, ID_EDT_LOG_DIR, o.log_dir);
SetDlgItemInt (hdlg, ID_EDT_PRECONNECT_TIMEOUT, o.preconnectscript_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_MGMT_PORT, o.mgmt_port_offset, FALSE);
SetDlgItemInt (hdlg, ID_EDT_POPUP_MUTE, o.popup_mute_interval, FALSE);
SetDlgItemText(hdlg, ID_EDT_CONFIG_DIR, o.config_dir);
SetDlgItemText(hdlg, ID_EDT_CONFIG_EXT, o.ext_string);
SetDlgItemText(hdlg, ID_EDT_LOG_DIR, o.log_dir);
SetDlgItemInt(hdlg, ID_EDT_PRECONNECT_TIMEOUT, o.preconnectscript_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_MGMT_PORT, o.mgmt_port_offset, FALSE);
SetDlgItemInt(hdlg, ID_EDT_POPUP_MUTE, o.popup_mute_interval, FALSE);
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)
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)
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 */
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
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
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
}
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;
switch(msg) {
case WM_INITDIALOG:
/* Limit extension editbox to 4 chars. */
SendMessage (GetDlgItem(hwndDlg, ID_EDT_CONFIG_EXT), EM_SETLIMITTEXT, 4, 0);
/* Limit management port editbox to 5 chars */
SendMessage(GetDlgItem(hwndDlg, ID_EDT_MGMT_PORT), EM_SETLIMITTEXT, 5, 0);
/* Populate UI */
LoadAdvancedDlgParams (hwndDlg);
break;
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);
switch (msg)
{
case WM_INITDIALOG:
/* Limit extension editbox to 4 chars. */
SendMessage(GetDlgItem(hwndDlg, ID_EDT_CONFIG_EXT), EM_SETLIMITTEXT, 4, 0);
/* Limit management port editbox to 5 chars */
SendMessage(GetDlgItem(hwndDlg, ID_EDT_MGMT_PORT), EM_SETLIMITTEXT, 5, 0);
/* Populate UI */
LoadAdvancedDlgParams(hwndDlg);
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);
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;
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;
case WM_NOTIFY:
psn = (LPPSHNOTIFY) lParam;
if (psn->hdr.code == (UINT) PSN_KILLACTIVE)
{
SetWindowLongPtr (hwndDlg, DWLP_MSGRESULT, (CheckAdvancedDlgParams(hwndDlg) ? FALSE : TRUE));
return TRUE;
}
if (psn->hdr.code == (UINT) PSN_APPLY)
{
BOOL status = SaveAdvancedDlgParams (hwndDlg);
SetWindowLongPtr (hwndDlg, DWLP_MSGRESULT, status? PSNRET_NOERROR:PSNRET_INVALID);
return TRUE;
}
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON2))
o.config_menu_view = 2;
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON1))
o.config_menu_view = 1;
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON0))
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;
case WM_NOTIFY:
psn = (LPPSHNOTIFY) lParam;
if (psn->hdr.code == (UINT) PSN_KILLACTIVE)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (CheckAdvancedDlgParams(hwndDlg) ? FALSE : TRUE));
return TRUE;
}
if (psn->hdr.code == (UINT) PSN_APPLY)
{
BOOL status = SaveAdvancedDlgParams(hwndDlg);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, status ? PSNRET_NOERROR : PSNRET_INVALID);
return TRUE;
}
if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON2))
{
o.config_menu_view = 2;
}
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON1))
{
o.config_menu_view = 1;
}
else if (IsDlgButtonChecked(hwndDlg, ID_RB_BALLOON0))
{
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;
}
int
CompareStringExpanded (const WCHAR *str1, const WCHAR *str2)
CompareStringExpanded(const WCHAR *str1, const WCHAR *str2)
{
WCHAR str1_cpy[MAX_PATH], str2_cpy[MAX_PATH];
wcsncpy (str1_cpy, str1, _countof(str1_cpy));
wcsncpy (str2_cpy, str2, _countof(str2_cpy));
wcsncpy(str1_cpy, str1, _countof(str1_cpy));
wcsncpy(str2_cpy, str2, _countof(str2_cpy));
str1_cpy[MAX_PATH-1] = L'\0';
str2_cpy[MAX_PATH-1] = L'\0';
ExpandString (str1_cpy, _countof(str1_cpy));
ExpandString (str2_cpy, _countof(str2_cpy));
ExpandString(str1_cpy, _countof(str1_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 */

17
options.h

@ -249,16 +249,27 @@ typedef struct {
} options_t;
void InitOptions(options_t *);
void ProcessCommandLine(options_t *, TCHAR *);
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 ConnectionSettingsDlgProc(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 DisablePopupMessages(connection_t *);
void ExpandOptions(void);
int CompareStringExpanded(const WCHAR *str1, const WCHAR *str2);
#endif
#endif /* ifndef OPTIONS_H */

4
pkcs11.c

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

10
plap/plap_common.c

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

10
plap/plap_common.h

@ -36,14 +36,17 @@ extern "C" {
#endif
#ifdef DEBUG
#define dmsg(fmt, ...) x_dmsg(__FILE__, __func__, fmt, ##__VA_ARGS__)
#define dmsg(fmt, ...) x_dmsg(__FILE__, __func__, fmt, ## __VA_ARGS__)
#else
#define dmsg(...) do { ; } while (0)
#define dmsg(...) do {; } while (0)
#endif
void x_dmsg(const char *file, const char *func, const wchar_t *fmt, ...);
void init_debug();
void uninit_debug();
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 */
@ -64,6 +67,5 @@ void debug_print_guid(const GUID *riid, const wchar_t *context);
*/
#ifdef DEFINE_GUID
DEFINE_GUID(CLSID_OpenVPNProvider, 0x4fbb8b67, 0xcf02, 0x4982, 0xa7, 0xa8,
0x3d, 0xd0, 0x6a, 0x2c, 0x2e, 0xbd);
0x3d, 0xd0, 0x6a, 0x2c, 0x2e, 0xbd);
#endif

77
plap/plap_connection.c

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

2
plap/plap_connection.h

@ -52,7 +52,7 @@ static const CREDENTIAL_PROVIDER_FIELD_STATE field_states[] =
/** Helper to deep copy field descriptor */
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;

22
plap/plap_dll.c

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

4
plap/plap_dll.h

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

34
plap/plap_provider.c

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

98
plap/stub.c

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

56
plap/ui_glue.c

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

262
proxy.c

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

4
proxy.h

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

371
registry.c

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

12
registry.h

@ -23,15 +23,25 @@
#define REGISTRY_H
int GetRegistryKeys(void);
int SaveRegistryKeys(void);
int UpdateRegistry(void);
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 GetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD *data);
int SetRegistryValue(HKEY regkey, const TCHAR *name, const TCHAR *data);
int SetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD data);
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);
int DeleteConfigRegistryValue(const WCHAR *config_name, const WCHAR *name);
#endif
#endif /* ifndef REGISTRY_H */

40
save_pass.c

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

10
save_pass.h

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

26
scripts.c

@ -60,13 +60,15 @@ RunPreconnectScript(connection_t *c)
/* Return if no script exists */
if (_tstat(cmdline, &st) == -1)
{
return;
}
// Create the filename of the logfile
/* Create the filename of the logfile */
TCHAR script_log_filename[MAX_PATH];
_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;
CLEAR(sa);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -133,16 +135,20 @@ RunConnectScript(connection_t *c, int run_as_service)
/* Return if no script exists */
if (_tstat(cmdline, &st) == -1)
{
return;
}
if (!run_as_service)
{
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];
_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;
CLEAR(sa);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -175,7 +181,9 @@ RunConnectScript(connection_t *c, int run_as_service)
}
if (o.connectscript_timeout == 0)
{
goto out;
}
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 != 0)
{
ShowLocalizedMsgEx(MB_OK|MB_ICONERROR, c->hwndStatus, TEXT(PACKAGE_NAME), IDS_ERR_CONN_SCRIPT_FAILED, exit_code);
}
goto out;
}
@ -227,16 +237,20 @@ RunDisconnectScript(connection_t *c, int run_as_service)
/* Return if no script exists */
if (_tstat(cmdline, &st) == -1)
{
return;
}
if (!run_as_service)
{
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];
_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;
CLEAR(sa);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);

2
scripts.h

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

64
service.c

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

2
service.h

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

149
tray.c

@ -50,13 +50,14 @@ NOTIFYICONDATA ni;
extern options_t o;
#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
DeleteMenuBitmaps(void)
{
if (hbmpConnecting) {
if (hbmpConnecting)
{
DeleteObject(hbmpConnecting);
hbmpConnecting = NULL;
}
@ -92,8 +93,14 @@ CreateMenuBitmaps(void)
{
DeleteObject(iconinfo.hbmMask);
DeleteObject(iconinfo.hbmColor);
if (maskDC) DeleteDC(maskDC);
if (imgDC) DeleteDC(imgDC);
if (maskDC)
{
DeleteDC(maskDC);
}
if (imgDC)
{
DeleteDC(imgDC);
}
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Error creating DCs for drawing");
return;
}
@ -106,10 +113,14 @@ CreateMenuBitmaps(void)
COLORREF ref = RGB(255, 255, 255);
COLORREF bg = GetSysColor(COLOR_MENU);
for (int x = 0; x < cx; x++) {
for (int y = 0; y < cy; y++) {
for (int x = 0; x < cx; x++)
{
for (int y = 0; y < cy; y++)
{
if (GetPixel(maskDC, x, y) == ref)
{
SetPixel(imgDC, x, y, bg);
}
}
}
@ -132,13 +143,18 @@ CreateMenuBitmaps(void)
void
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));
if (tmp) {
if (tmp)
{
hmenu_size = o.num_configs + 50;
hMenuConn = tmp;
}
else {
else
{
o.num_configs = hmenu_size;
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++)
{
if (!o.groups[i].active)
{
continue;
}
o.groups[i].menu = CreatePopupMenu();
o.groups[i].children = 0; /* we have to recount this when assigning menu position index */
}
@ -188,7 +206,8 @@ CreatePopupMenus()
minfo.dwStyle |= MNS_NOTIFYBYPOS;
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 */
minfo.fMask = MIM_MENUDATA;
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_URL, LoadLocalizedString(IDS_MENU_IMPORT_URL));
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_SETTINGS, LoadLocalizedString(IDS_MENU_SETTINGS));
AppendMenu(hMenu, MF_STRING, IDM_CLOSE, LoadLocalizedString(IDS_MENU_CLOSE));
SetMenuStatus(o.chead, o.chead->state);
}
else {
else
{
/* construct the submenu tree first */
/* i = 0 is the root menu and has no parent */
for (int i = 1; i < o.num_groups; i++)
@ -240,7 +260,7 @@ CreatePopupMenus()
this->pos = parent->children++;
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 */
@ -268,11 +288,13 @@ CreatePopupMenus()
c->pos = parent->children++;
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)
{
AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
}
hMenuImport = CreatePopupMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR) hMenuImport, LoadLocalizedString(IDS_MENU_IMPORT));
@ -337,17 +359,18 @@ OnNotifyTray(LPARAM lParam)
{
POINT pt;
switch (lParam) {
case WM_RBUTTONUP:
RecreatePopupMenus();
switch (lParam)
{
case WM_RBUTTONUP:
RecreatePopupMenus();
GetCursorPos(&pt);
SetForegroundWindow(o.hWnd);
TrackPopupMenu(hMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, o.hWnd, NULL);
PostMessage(o.hWnd, WM_NULL, 0, 0);
break;
GetCursorPos(&pt);
SetForegroundWindow(o.hWnd);
TrackPopupMenu(hMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, o.hWnd, NULL);
PostMessage(o.hWnd, WM_NULL, 0, 0);
break;
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDBLCLK:
{
int disconnected_conns = CountConnState(disconnected);
@ -355,26 +378,33 @@ OnNotifyTray(LPARAM lParam)
/* Start connection if only one config exist */
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 */
else if (disconnected_conns < o.num_configs) {
else if (disconnected_conns < o.num_configs)
{
int num_shown = 0;
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);
SetForegroundWindow(c->hwndStatus);
if (++num_shown >= 10) break;
if (++num_shown >= 10)
{
break;
}
}
}
}
}
break;
case WM_OVPN_RESCAN:
/* Rescan config folders and recreate popup menus */
RecreatePopupMenus();
break;
case WM_OVPN_RESCAN:
/* Rescan config folders and recreate popup menus */
RecreatePopupMenus();
break;
}
}
@ -398,15 +428,15 @@ OnDestroyTray()
void
ShowTrayIcon()
{
ni.cbSize = sizeof(ni);
ni.uID = 0;
ni.hWnd = o.hWnd;
ni.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON;
ni.uCallbackMessage = WM_NOTIFYICONTRAY;
ni.hIcon = LoadLocalizedSmallIcon(ID_ICO_DISCONNECTED);
_tcsncpy(ni.szTip, LoadLocalizedString(IDS_TIP_DEFAULT), _countof(ni.szTip));
Shell_NotifyIcon(NIM_ADD, &ni);
ni.cbSize = sizeof(ni);
ni.uID = 0;
ni.hWnd = o.hWnd;
ni.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON;
ni.uCallbackMessage = WM_NOTIFYICONTRAY;
ni.hIcon = LoadLocalizedSmallIcon(ID_ICO_DISCONNECTED);
_tcsncpy(ni.szTip, LoadLocalizedString(IDS_TIP_DEFAULT), _countof(ni.szTip));
Shell_NotifyIcon(NIM_ADD, &ni);
}
void
@ -426,7 +456,8 @@ SetTrayIcon(conn_state_t state)
first_conn = TRUE;
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 */
_tcsncat(msg, (first_conn ? msg_connected : _T(", ")), _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;
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 */
_tcsncat(msg, (first_conn ? msg_connecting : _T(", ")), _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 */
TCHAR time[50];
@ -463,9 +496,13 @@ SetTrayIcon(conn_state_t state)
icon_id = ID_ICO_CONNECTING;
if (state == connected)
{
icon_id = ID_ICO_CONNECTED;
}
else if (state == disconnected)
{
icon_id = ID_ICO_DISCONNECTED;
}
ni.cbSize = sizeof(ni);
ni.uID = 0;
@ -490,9 +527,13 @@ CheckAndSetTrayIcon()
{
if (CountConnState(connecting) != 0 || CountConnState(reconnecting) != 0
|| CountConnState(resuming) != 0)
{
SetTrayIcon(connecting);
}
else
{
SetTrayIcon(disconnected);
}
}
}
@ -519,8 +560,14 @@ SetMenuStatus(connection_t *c, conn_state_t state)
int checked = 0;
int i = c->id;
if (state == connected || state == disconnecting) checked = 1;
else if (state != disconnected && state != detached && state != onhold) checked = 2;
if (state == connected || state == disconnecting)
{
checked = 1;
}
else if (state != disconnected && state != detached && state != onhold)
{
checked = 2;
}
if (o.num_configs == 1)
{
@ -553,9 +600,13 @@ SetMenuStatus(connection_t *c, conn_state_t state)
EnableMenuItem(hMenu, IDM_STATUSMENU, MF_ENABLED);
}
if (c->flags & (FLAG_SAVE_AUTH_PASS | FLAG_SAVE_KEY_PASS))
{
EnableMenuItem(hMenu, IDM_CLEARPASSMENU, MF_ENABLED);
}
else
{
EnableMenuItem(hMenu, IDM_CLEARPASSMENU, MF_GRAYED);
}
}
else
{
@ -584,7 +635,7 @@ SetMenuStatus(connection_t *c, conn_state_t state)
CheckMenuItem(parent->menu, pos, MF_BYPOSITION | (checked ? MF_CHECKED : MF_UNCHECKED));
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 */
{
@ -625,8 +676,12 @@ SetMenuStatus(connection_t *c, conn_state_t state)
EnableMenuItem(hMenuConn[i], IDM_STATUSMENU, MF_ENABLED);
}
if (c->flags & (FLAG_SAVE_AUTH_PASS | FLAG_SAVE_KEY_PASS))
{
EnableMenuItem(hMenuConn[i], IDM_CLEARPASSMENU, MF_ENABLED);
}
else
{
EnableMenuItem(hMenuConn[i], IDM_CLEARPASSMENU, MF_GRAYED);
}
}
}

12
tray.h

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

204
viewlog.c

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

Loading…
Cancel
Save