mirror of https://github.com/OpenVPN/openvpn-gui
Use a list instead of array for connections list
Currently we use an array of connection pointers which needs to be reallocated when space runs out. But, that happens from the main thread while the status thread may be referring to those pointers. Its very hard to fence against possible invalid memory access. Instead, use a list so that connection pointer never changes once created. The connection list is no longer recreated from scratch even when no connections are active. This means configs added while GUI is running will always appear at the bottom of the root group listing until the GUI is restarted. TODO: This behaviour could be improved by scanning through the groups to graft new configs at the right branch in the config-group tree. v2: removed unused references to SetMenuStatusById() Signed-off-by: Selva Nair <selva.nair@gmail.com>pull/589/head
parent
8a4fec9d13
commit
9417991168
109
main.c
109
main.c
|
@ -358,17 +358,17 @@ StopAllOpenVPN()
|
|||
* at their current state. Use the disconnect menu to put them into
|
||||
* hold state before exit, if desired.
|
||||
*/
|
||||
for (i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].state != disconnected && o.conn[i].state != detached)
|
||||
if (c->state != disconnected && c->state != detached)
|
||||
{
|
||||
if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT)
|
||||
if (c->flags & FLAG_DAEMON_PERSISTENT)
|
||||
{
|
||||
DetachOpenVPN(&o.conn[i]);
|
||||
DetachOpenVPN(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
StopOpenVPN(&o.conn[i]);
|
||||
StopOpenVPN(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -385,12 +385,10 @@ StopAllOpenVPN()
|
|||
static int
|
||||
AutoStartConnections()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].auto_connect && !(o.conn[i].flags & FLAG_DAEMON_PERSISTENT))
|
||||
StartOpenVPN(&o.conn[i]);
|
||||
if (c->auto_connect && !(c->flags & FLAG_DAEMON_PERSISTENT))
|
||||
StartOpenVPN(c);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -400,15 +398,15 @@ AutoStartConnections()
|
|||
static void
|
||||
ResumeConnections()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < o.num_configs; i++) {
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
/* Restart suspend connections */
|
||||
if (o.conn[i].state == suspended)
|
||||
StartOpenVPN(&o.conn[i]);
|
||||
if (c->state == suspended)
|
||||
StartOpenVPN(c);
|
||||
|
||||
/* If some connection never reached SUSPENDED state */
|
||||
if (o.conn[i].state == suspending)
|
||||
StopOpenVPN(&o.conn[i]);
|
||||
if (c->state == suspending)
|
||||
StopOpenVPN(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,19 +490,19 @@ ManagePersistent(HWND hwnd, UINT UNUSED msg, UINT_PTR id, DWORD UNUSED now)
|
|||
CheckServiceStatus();
|
||||
if (o.service_state == service_connected)
|
||||
{
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT
|
||||
&& o.conn[i].auto_connect
|
||||
&& (o.conn[i].state == disconnected || o.conn[i].state == detached))
|
||||
if (c->flags & FLAG_DAEMON_PERSISTENT
|
||||
&& c->auto_connect
|
||||
&& (c->state == disconnected || c->state == detached))
|
||||
{
|
||||
/* disable auto-connect to avoid repeated re-connect
|
||||
* after unrecoverable errors. Re-enabled on successful
|
||||
* connect.
|
||||
*/
|
||||
o.conn[i].auto_connect = false;
|
||||
o.conn[i].state = detached; /* this is required to retain management-hold on re-attach */
|
||||
StartOpenVPN(&o.conn[i]); /* attach to the management i/f */
|
||||
c->auto_connect = false;
|
||||
c->state = detached; /* this is required to retain management-hold on re-attach */
|
||||
StartOpenVPN(c); /* attach to the management i/f */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,14 +517,14 @@ ManagePersistent(HWND hwnd, UINT UNUSED msg, UINT_PTR id, DWORD UNUSED now)
|
|||
static void
|
||||
HandleSessionLock(void)
|
||||
{
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT
|
||||
&& (o.conn[i].state != disconnected && o.conn[i].state != detached))
|
||||
if (c->flags & FLAG_DAEMON_PERSISTENT
|
||||
&& (c->state != disconnected && c->state != detached))
|
||||
{
|
||||
o.conn[i].auto_connect = false;
|
||||
DetachOpenVPN(&o.conn[i]);
|
||||
o.conn[i].flags |= FLAG_WAIT_UNLOCK;
|
||||
c->auto_connect = false;
|
||||
DetachOpenVPN(c);
|
||||
c->flags |= FLAG_WAIT_UNLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -536,12 +534,12 @@ HandleSessionLock(void)
|
|||
void
|
||||
HandleSessionUnlock(void)
|
||||
{
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].flags & FLAG_WAIT_UNLOCK)
|
||||
if (c->flags & FLAG_WAIT_UNLOCK)
|
||||
{
|
||||
o.conn[i].auto_connect = true; /* so that ManagePersistent will trigger attach */
|
||||
o.conn[i].flags &= ~ FLAG_WAIT_UNLOCK;
|
||||
c->auto_connect = true; /* so that ManagePersistent will trigger attach */
|
||||
c->flags &= ~ FLAG_WAIT_UNLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -550,8 +548,8 @@ HandleSessionUnlock(void)
|
|||
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static UINT s_uTaskbarRestart;
|
||||
int conn_id = 0;
|
||||
MENUINFO minfo = {.cbSize = sizeof(MENUINFO)};
|
||||
connection_t *c = NULL;
|
||||
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
|
@ -633,36 +631,37 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
else {
|
||||
minfo.fMask = MIM_MENUDATA;
|
||||
GetMenuInfo((HMENU) lParam, &minfo);
|
||||
conn_id = (INT) minfo.dwMenuData;
|
||||
if (conn_id < 0 || conn_id >= o.num_configs) break; /* ignore invalid connection id */
|
||||
c = (connection_t *) minfo.dwMenuData;
|
||||
if (!c)
|
||||
break; /* ignore invalid connection */
|
||||
}
|
||||
|
||||
/* reach here only if the command did not match any global items and a valid connection id is available */
|
||||
|
||||
if (LOWORD(wParam) == IDM_CONNECTMENU) {
|
||||
StartOpenVPN(&o.conn[conn_id]);
|
||||
StartOpenVPN(c);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDM_DISCONNECTMENU) {
|
||||
StopOpenVPN(&o.conn[conn_id]);
|
||||
StopOpenVPN(c);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDM_RECONNECTMENU) {
|
||||
RestartOpenVPN(&o.conn[conn_id]);
|
||||
RestartOpenVPN(c);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDM_STATUSMENU) {
|
||||
ShowWindow(o.conn[conn_id].hwndStatus, SW_SHOW);
|
||||
ShowWindow(c->hwndStatus, SW_SHOW);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDM_VIEWLOGMENU) {
|
||||
ViewLog(conn_id);
|
||||
ViewLog(c);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDM_EDITMENU) {
|
||||
EditConfig(conn_id);
|
||||
EditConfig(c);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDM_CLEARPASSMENU) {
|
||||
ResetSavePasswords(&o.conn[conn_id]);
|
||||
ResetSavePasswords(c);
|
||||
}
|
||||
#ifndef DISABLE_CHANGE_PASSWORD
|
||||
else if (LOWORD(wParam) == IDM_PASSPHRASEMENU) {
|
||||
ShowChangePassphraseDialog(&o.conn[conn_id]);
|
||||
ShowChangePassphraseDialog(c);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -825,13 +824,11 @@ ShowSettingsDialog()
|
|||
void
|
||||
CloseApplication(HWND hwnd)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Show a message if any non-persistent connections are active */
|
||||
for (i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].state == disconnected
|
||||
|| o.conn[i].flags & FLAG_DAEMON_PERSISTENT)
|
||||
if (c->state == disconnected
|
||||
|| c->flags & FLAG_DAEMON_PERSISTENT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -980,7 +977,7 @@ SaveAutoRestartList()
|
|||
return;
|
||||
}
|
||||
|
||||
int *active_conns = malloc((size_t) max_active*sizeof(int));
|
||||
connection_t **active_conns = malloc((size_t) max_active*sizeof(connection_t *));
|
||||
|
||||
if (!active_conns)
|
||||
{
|
||||
|
@ -988,16 +985,16 @@ SaveAutoRestartList()
|
|||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c && nactive < max_active; c = c->next)
|
||||
{
|
||||
if (o.conn[i].state == disconnected
|
||||
|| o.conn[i].flags & FLAG_DAEMON_PERSISTENT)
|
||||
if (c->state == disconnected
|
||||
|| c->flags & FLAG_DAEMON_PERSISTENT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* accumulate space needed for list of active connections */
|
||||
len += wcslen(o.conn[i].config_name) + 1;
|
||||
active_conns[nactive++] = i;
|
||||
len += wcslen(c->config_name) + 1;
|
||||
active_conns[nactive++] = c;
|
||||
}
|
||||
len++; /* for double nul termination */
|
||||
|
||||
|
@ -1015,7 +1012,7 @@ SaveAutoRestartList()
|
|||
wchar_t *p = list;
|
||||
for (int i = 0; i < nactive; i++)
|
||||
{
|
||||
connection_t *c = &o.conn[active_conns[i]];
|
||||
connection_t *c = active_conns[i];
|
||||
wcscpy(p, c->config_name); /* wcscpy is safe here */
|
||||
p += wcslen(c->config_name) + 1;
|
||||
}
|
||||
|
|
|
@ -2681,12 +2681,6 @@ TerminateOpenVPN (connection_t *c)
|
|||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
SuspendOpenVPN(int config)
|
||||
{
|
||||
PostMessage(o.conn[config].hwndStatus, WM_OVPN_SUSPEND, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
RestartOpenVPN(connection_t *c)
|
||||
{
|
||||
|
|
|
@ -79,22 +79,36 @@ CheckReadAccess (const TCHAR *dir, const TCHAR *file)
|
|||
static int
|
||||
ConfigAlreadyExists(TCHAR *newconfig)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < o.num_configs; ++i)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (_tcsicmp(o.conn[i].config_file, newconfig) == 0)
|
||||
if (_tcsicmp(c->config_file, newconfig) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
AddConfigFileToList(int config, const TCHAR *filename, const TCHAR *config_dir)
|
||||
AddConfigFileToList(int group, const TCHAR *filename, const TCHAR *config_dir)
|
||||
{
|
||||
connection_t *c = &o.conn[config];
|
||||
int i;
|
||||
connection_t *c = calloc(1, sizeof(connection_t));
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
if (!c)
|
||||
{
|
||||
ErrorExit(1, L"Out of memory in AddConfigFileToList");
|
||||
}
|
||||
|
||||
if (o.ctail)
|
||||
{
|
||||
o.ctail->next = c;
|
||||
o.ctail = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
o.chead = o.ctail = c;
|
||||
}
|
||||
|
||||
c->id = o.num_configs++;
|
||||
c->group = group;
|
||||
|
||||
_tcsncpy(c->config_file, filename, _countof(c->config_file) - 1);
|
||||
_tcsncpy(c->config_dir, config_dir, _countof(c->config_dir) - 1);
|
||||
|
@ -105,7 +119,7 @@ AddConfigFileToList(int config, const TCHAR *filename, const TCHAR *config_dir)
|
|||
c->manage.sk = INVALID_SOCKET;
|
||||
c->manage.skaddr.sin_family = AF_INET;
|
||||
c->manage.skaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
c->manage.skaddr.sin_port = htons(o.mgmt_port_offset + config);
|
||||
c->manage.skaddr.sin_port = htons(o.mgmt_port_offset + c->id);
|
||||
|
||||
#ifndef DISABLE_CHANGE_PASSWORD
|
||||
if (CheckKeyFileWriteAccess (c))
|
||||
|
@ -123,7 +137,7 @@ AddConfigFileToList(int config, const TCHAR *filename, const TCHAR *config_dir)
|
|||
}
|
||||
|
||||
/* Check if connection should be autostarted */
|
||||
for (i = 0; i < o.num_auto_connect; ++i)
|
||||
for (int i = 0; i < o.num_auto_connect; ++i)
|
||||
{
|
||||
if (_tcsicmp(c->config_file, o.auto_connect[i]) == 0
|
||||
|| _tcsicmp(c->config_name, o.auto_connect[i]) == 0)
|
||||
|
@ -211,9 +225,9 @@ ActivateConfigGroups(void)
|
|||
/* count children of each group -- this includes groups
|
||||
* and configs which have it as parent
|
||||
*/
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
CONFIG_GROUP(&o.conn[i])->children++;
|
||||
CONFIG_GROUP(c)->children++;
|
||||
}
|
||||
|
||||
for (int i = 1; i < o.num_groups; i++)
|
||||
|
@ -235,23 +249,23 @@ ActivateConfigGroups(void)
|
|||
* script etc.) in a separate directory, without making the menu structure
|
||||
* too deeply nested.
|
||||
*/
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
config_group_t *cg = CONFIG_GROUP(&o.conn[i]);
|
||||
config_group_t *cg = CONFIG_GROUP(c);
|
||||
|
||||
/* if not root and has only this config as child -- squash it */
|
||||
if (PARENT_GROUP(cg) && cg->children == 1
|
||||
&& !wcscmp(cg->name, o.conn[i].config_name))
|
||||
&& !wcscmp(cg->name, c->config_name))
|
||||
{
|
||||
cg->children--;
|
||||
o.conn[i].group = cg->parent;
|
||||
c->group = cg->parent;
|
||||
}
|
||||
}
|
||||
|
||||
/* activate all groups that connect a config to the root */
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
config_group_t *cg = CONFIG_GROUP(&o.conn[i]);
|
||||
config_group_t *cg = CONFIG_GROUP(c);
|
||||
|
||||
while (cg)
|
||||
{
|
||||
|
@ -287,19 +301,6 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, int group, int flags)
|
|||
/* Loop over each config file in config dir */
|
||||
do
|
||||
{
|
||||
if (!o.conn || o.num_configs == o.max_configs)
|
||||
{
|
||||
o.max_configs += 50;
|
||||
void *tmp = realloc(o.conn, sizeof(*o.conn)*o.max_configs);
|
||||
if (!tmp)
|
||||
{
|
||||
o.max_configs -= 50;
|
||||
FindClose(find_handle);
|
||||
ErrorExit(1, L"Out of memory while scanning configs");
|
||||
}
|
||||
o.conn = tmp;
|
||||
}
|
||||
|
||||
match_t match_type = match(&find_obj, o.ext_string);
|
||||
if (match_type == match_file)
|
||||
{
|
||||
|
@ -312,8 +313,7 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, int group, int flags)
|
|||
|
||||
if (CheckReadAccess (config_dir, find_obj.cFileName))
|
||||
{
|
||||
AddConfigFileToList(o.num_configs, find_obj.cFileName, config_dir);
|
||||
o.conn[o.num_configs++].group = group;
|
||||
AddConfigFileToList(group, find_obj.cFileName, config_dir);
|
||||
}
|
||||
}
|
||||
} while (FindNextFile(find_handle, &find_obj));
|
||||
|
@ -419,17 +419,12 @@ BuildFileList()
|
|||
issue_warnings = false;
|
||||
|
||||
/*
|
||||
* If no connections are active reset num_configs and rescan
|
||||
* If first time or no entries in the connection list reset groups and rescan
|
||||
* to make a new list. Else we keep all current configs and
|
||||
* rescan to add any new one's found.
|
||||
* Do the same when persistent connections are in auto-attach mode,
|
||||
* to avoid over-writing their status info such as auto_connect=false
|
||||
* after manual detach.
|
||||
*/
|
||||
if (!o.num_groups
|
||||
|| (CountConnState(disconnected) == o.num_configs && o.enable_persistent != 2))
|
||||
if (!o.num_configs)
|
||||
{
|
||||
o.num_configs = 0;
|
||||
o.num_groups = 0;
|
||||
flags |= FLAG_ADD_CONFIG_GROUPS;
|
||||
root_gp = NewConfigGroup(L"ROOT", -1, flags); /* -1 indicates no parent */
|
||||
|
|
20
options.c
20
options.c
|
@ -453,12 +453,11 @@ ProcessCommandLine(options_t *options, TCHAR *command_line)
|
|||
int
|
||||
CountConnState(conn_state_t check)
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
for (i = 0; i < o.num_configs; ++i)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].state == check)
|
||||
if (c->state == check)
|
||||
++count;
|
||||
}
|
||||
|
||||
|
@ -468,11 +467,10 @@ CountConnState(conn_state_t check)
|
|||
connection_t*
|
||||
GetConnByManagement(SOCKET sk)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < o.num_configs; ++i)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].manage.sk == sk)
|
||||
return &o.conn[i];
|
||||
if (c->manage.sk == sk)
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -480,11 +478,11 @@ GetConnByManagement(SOCKET sk)
|
|||
connection_t*
|
||||
GetConnByName(const WCHAR *name)
|
||||
{
|
||||
for (int i = 0; i < o.num_configs; ++i)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (wcsicmp (o.conn[i].config_file, name) == 0
|
||||
|| wcsicmp(o.conn[i].config_name, name) == 0)
|
||||
return &o.conn[i];
|
||||
if (wcsicmp (c->config_file, name) == 0
|
||||
|| wcsicmp(c->config_name, name) == 0)
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -167,6 +167,8 @@ struct connection {
|
|||
struct echo_msg echo_msg; /* Message echo-ed from server or client config and related data */
|
||||
struct pkcs11_list pkcs11_list;
|
||||
char daemon_state[20]; /* state of openvpn.ex: WAIT, AUTH, GET_CONFIG etc.. */
|
||||
int id; /* index of config -- treat as immutable once assigned */
|
||||
connection_t *next;
|
||||
};
|
||||
|
||||
/* All options used within OpenVPN GUI */
|
||||
|
@ -175,7 +177,8 @@ typedef struct {
|
|||
const TCHAR **auto_connect;
|
||||
|
||||
/* Connection parameters */
|
||||
connection_t *conn; /* Array of connection structure */
|
||||
connection_t *chead; /* Head of connection list */
|
||||
connection_t *ctail; /* Tail of connection list */
|
||||
config_group_t *groups; /* Array of nodes defining the config groups tree */
|
||||
int num_configs; /* Number of configs */
|
||||
int num_auto_connect; /* Number of auto-connect configs */
|
||||
|
|
|
@ -76,10 +76,6 @@ void SetMenuStatus(UNUSED connection_t *c, UNUSED conn_state_t state)
|
|||
{
|
||||
return;
|
||||
}
|
||||
void SetMenuStatusById(UNUSED int id, UNUSED conn_state_t state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void SetServiceMenuStatus(void)
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -265,8 +265,9 @@ InitializeUI(HINSTANCE hinstance)
|
|||
CheckServiceStatus();
|
||||
int num_persistent = 0;
|
||||
|
||||
for (int i = 0; i < o.num_configs; i++) {
|
||||
if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT) num_persistent++;
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (c->flags & FLAG_DAEMON_PERSISTENT) num_persistent++;
|
||||
}
|
||||
|
||||
if (o.service_state == service_disconnected && num_persistent > 0) {
|
||||
|
@ -281,15 +282,14 @@ InitializeUI(HINSTANCE hinstance)
|
|||
/* Returns number of PLAP enabled configs -- for now
|
||||
* same as autostarted (persistent) connections.
|
||||
* The corresponding connection pointers are set in
|
||||
* the conn[] array.
|
||||
* the conn[] array
|
||||
*/
|
||||
DWORD
|
||||
FindPLAPConnections(connection_t *conn[], size_t max_count)
|
||||
{
|
||||
DWORD count = 0;
|
||||
for (int i = 0; i < o.num_configs && count < max_count; i++)
|
||||
for (connection_t *c = o.chead; c && count < max_count; c = c->next)
|
||||
{
|
||||
connection_t *c = &o.conn[i];
|
||||
if (!(c->flags & FLAG_DAEMON_PERSISTENT)
|
||||
|| !ParseManagementAddress(c))
|
||||
{
|
||||
|
@ -390,11 +390,11 @@ DetachAllOpenVPN()
|
|||
int i;
|
||||
|
||||
/* Detach from the mgmt i/f of all connections */
|
||||
for (i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].state != disconnected)
|
||||
if (c->state != disconnected)
|
||||
{
|
||||
DetachOpenVPN(&o.conn[i]);
|
||||
DetachOpenVPN(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,12 +408,12 @@ DetachAllOpenVPN()
|
|||
Sleep(100);
|
||||
}
|
||||
|
||||
for (i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (o.conn[i].hwndStatus)
|
||||
if (c->hwndStatus)
|
||||
{
|
||||
/* Status thread still running? kill it */
|
||||
WaitOnThread(&o.conn[i], 0);
|
||||
WaitOnThread(c, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
90
tray.c
90
tray.c
|
@ -161,13 +161,13 @@ CreatePopupMenus()
|
|||
CreateMenuBitmaps();
|
||||
MENUINFO minfo = {.cbSize = sizeof(MENUINFO)};
|
||||
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
hMenuConn[i] = CreatePopupMenu();
|
||||
hMenuConn[c->id] = CreatePopupMenu();
|
||||
/* Save the connection index in the menu.*/
|
||||
minfo.fMask = MIM_MENUDATA;
|
||||
minfo.dwMenuData = i;
|
||||
SetMenuInfo(hMenuConn[i], &minfo);
|
||||
minfo.dwMenuData = (UINT_PTR) c;
|
||||
SetMenuInfo(hMenuConn[c->id], &minfo);
|
||||
}
|
||||
for (int i = 0; i < o.num_groups; i++)
|
||||
{
|
||||
|
@ -185,7 +185,7 @@ CreatePopupMenus()
|
|||
minfo.dwStyle |= MNS_NOTIFYBYPOS;
|
||||
SetMenuInfo(hMenu, &minfo);
|
||||
|
||||
if (o.num_configs == 1) {
|
||||
if (o.num_configs == 1 && o.chead) {
|
||||
/* Create Main menu with actions */
|
||||
AppendMenu(hMenu, MF_STRING, IDM_CONNECTMENU, LoadLocalizedString(IDS_MENU_CONNECT));
|
||||
AppendMenu(hMenu, MF_STRING, IDM_DISCONNECTMENU, LoadLocalizedString(IDS_MENU_DISCONNECT));
|
||||
|
@ -199,7 +199,7 @@ CreatePopupMenus()
|
|||
AppendMenu(hMenu, MF_STRING, IDM_CLEARPASSMENU, LoadLocalizedString(IDS_MENU_CLEARPASS));
|
||||
|
||||
#ifndef DISABLE_CHANGE_PASSWORD
|
||||
if (o.conn[0].flags & FLAG_ALLOW_CHANGE_PASSPHRASE)
|
||||
if (o.chead->flags & FLAG_ALLOW_CHANGE_PASSPHRASE)
|
||||
AppendMenu(hMenu, MF_STRING, IDM_PASSPHRASEMENU, LoadLocalizedString(IDS_MENU_PASSPHRASE));
|
||||
#endif
|
||||
|
||||
|
@ -214,7 +214,7 @@ CreatePopupMenus()
|
|||
AppendMenu(hMenu, MF_STRING ,IDM_SETTINGS, LoadLocalizedString(IDS_MENU_SETTINGS));
|
||||
AppendMenu(hMenu, MF_STRING ,IDM_CLOSE, LoadLocalizedString(IDS_MENU_CLOSE));
|
||||
|
||||
SetMenuStatusById(0, o.conn[0].state);
|
||||
SetMenuStatus(o.chead, o.chead->state);
|
||||
}
|
||||
else {
|
||||
/* construct the submenu tree first */
|
||||
|
@ -240,9 +240,8 @@ CreatePopupMenus()
|
|||
}
|
||||
|
||||
/* add config file (connection) entries */
|
||||
for (int i = 0; i < o.num_configs; i++)
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
connection_t *c = &o.conn[i];
|
||||
config_group_t *parent = &o.groups[0]; /* by default config is added to the root */
|
||||
|
||||
if (USE_NESTED_CONFIG_MENU)
|
||||
|
@ -257,11 +256,11 @@ CreatePopupMenus()
|
|||
assert(parent);
|
||||
|
||||
/* Add config to the current sub menu */
|
||||
AppendMenu(parent->menu, MF_POPUP, (UINT_PTR) hMenuConn[i], c->config_name);
|
||||
AppendMenu(parent->menu, MF_POPUP, (UINT_PTR) hMenuConn[c->id], c->config_name);
|
||||
c->pos = parent->children++;
|
||||
|
||||
PrintDebug(L"Config %d named %ls added to submenu %ls with position %d",
|
||||
i, c->config_name, parent->name, c->pos);
|
||||
c->id, c->config_name, parent->name, c->pos);
|
||||
}
|
||||
|
||||
if (o.num_configs > 0)
|
||||
|
@ -277,7 +276,9 @@ CreatePopupMenus()
|
|||
AppendMenu(hMenu, MF_STRING, IDM_CLOSE, LoadLocalizedString(IDS_MENU_CLOSE));
|
||||
|
||||
/* Create popup menus for every connection */
|
||||
for (int i = 0; i < o.num_configs; i++) {
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
int i = c->id;
|
||||
AppendMenu(hMenuConn[i], MF_STRING, IDM_CONNECTMENU, LoadLocalizedString(IDS_MENU_CONNECT));
|
||||
AppendMenu(hMenuConn[i], MF_STRING, IDM_DISCONNECTMENU, LoadLocalizedString(IDS_MENU_DISCONNECT));
|
||||
AppendMenu(hMenuConn[i], MF_STRING, IDM_RECONNECTMENU, LoadLocalizedString(IDS_MENU_RECONNECT));
|
||||
|
@ -290,11 +291,11 @@ CreatePopupMenus()
|
|||
AppendMenu(hMenuConn[i], MF_STRING, IDM_CLEARPASSMENU, LoadLocalizedString(IDS_MENU_CLEARPASS));
|
||||
|
||||
#ifndef DISABLE_CHANGE_PASSWORD
|
||||
if (o.conn[i].flags & FLAG_ALLOW_CHANGE_PASSPHRASE)
|
||||
if (c->flags & FLAG_ALLOW_CHANGE_PASSPHRASE)
|
||||
AppendMenu(hMenuConn[i], MF_STRING, IDM_PASSPHRASEMENU, LoadLocalizedString(IDS_MENU_PASSPHRASE));
|
||||
#endif
|
||||
|
||||
SetMenuStatusById(i, o.conn[i].state);
|
||||
SetMenuStatus(c, c->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,9 +305,10 @@ CreatePopupMenus()
|
|||
static void
|
||||
DestroyPopupMenus()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < o.num_configs; i++)
|
||||
DestroyMenu(hMenuConn[i]);
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
DestroyMenu(hMenuConn[c->id]);
|
||||
}
|
||||
|
||||
DestroyMenu(hMenuImport);
|
||||
DestroyMenu(hMenu);
|
||||
|
@ -349,16 +351,16 @@ OnNotifyTray(LPARAM lParam)
|
|||
RecreatePopupMenus();
|
||||
|
||||
/* Start connection if only one config exist */
|
||||
if (o.num_configs == 1 && o.conn[0].state == disconnected)
|
||||
StartOpenVPN(&o.conn[0]);
|
||||
if (o.num_configs == 1 && o.chead->state == disconnected)
|
||||
StartOpenVPN(o.chead);
|
||||
/* show the status window of all connected/connecting profiles upto a max of 10 */
|
||||
else if (disconnected_conns < o.num_configs) {
|
||||
int i;
|
||||
int num_shown = 0;
|
||||
for (i = 0; i < o.num_configs; i++) {
|
||||
if (o.conn[i].state != disconnected) {
|
||||
ShowWindow(o.conn[i].hwndStatus, SW_SHOW);
|
||||
SetForegroundWindow(o.conn[i].hwndStatus);
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
if (c->state != disconnected && c->hwndStatus) {
|
||||
ShowWindow(c->hwndStatus, SW_SHOW);
|
||||
SetForegroundWindow(c->hwndStatus);
|
||||
if (++num_shown >= 10) break;
|
||||
}
|
||||
}
|
||||
|
@ -402,47 +404,48 @@ SetTrayIcon(conn_state_t state)
|
|||
TCHAR msg[500];
|
||||
TCHAR msg_connected[100];
|
||||
TCHAR msg_connecting[100];
|
||||
int i, config = 0;
|
||||
BOOL first_conn;
|
||||
UINT icon_id;
|
||||
connection_t *cc = NULL; /* a connected config */
|
||||
|
||||
_tcsncpy(msg, LoadLocalizedString(IDS_TIP_DEFAULT), _countof(ni.szTip));
|
||||
_tcsncpy(msg_connected, LoadLocalizedString(IDS_TIP_CONNECTED), _countof(msg_connected));
|
||||
_tcsncpy(msg_connecting, LoadLocalizedString(IDS_TIP_CONNECTING), _countof(msg_connecting));
|
||||
|
||||
first_conn = TRUE;
|
||||
for (i = 0; i < o.num_configs; i++) {
|
||||
if (o.conn[i].state == connected) {
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
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, o.conn[i].config_name, _countof(msg) - _tcslen(msg) - 1);
|
||||
_tcsncat(msg, c->config_name, _countof(msg) - _tcslen(msg) - 1);
|
||||
first_conn = FALSE;
|
||||
config = i;
|
||||
cc = c;
|
||||
}
|
||||
}
|
||||
|
||||
first_conn = TRUE;
|
||||
for (i = 0; i < o.num_configs; i++) {
|
||||
if (o.conn[i].state == connecting || o.conn[i].state == resuming || o.conn[i].state == reconnecting) {
|
||||
for (connection_t *c = o.chead; c; c = c->next)
|
||||
{
|
||||
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, o.conn[i].config_name, _countof(msg) - _tcslen(msg) - 1);
|
||||
_tcsncat(msg, c->config_name, _countof(msg) - _tcslen(msg) - 1);
|
||||
first_conn = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (CountConnState(connected) == 1) {
|
||||
if (CountConnState(connected) == 1 && cc) {
|
||||
/* Append "Connected since and assigned IP" to message */
|
||||
const connection_t *c = &o.conn[config];
|
||||
TCHAR time[50];
|
||||
|
||||
LocalizedTime(o.conn[config].connected_since, time, _countof(time));
|
||||
LocalizedTime(cc->connected_since, time, _countof(time));
|
||||
_tcsncat(msg, LoadLocalizedString(IDS_TIP_CONNECTED_SINCE), _countof(msg) - _tcslen(msg) - 1);
|
||||
_tcsncat(msg, time, _countof(msg) - _tcslen(msg) - 1);
|
||||
|
||||
/* concatenate ipv4 and ipv6 addresses into one string */
|
||||
WCHAR ip[64];
|
||||
wcs_concat2(ip, _countof(ip), c->ip, c->ipv6, L", ");
|
||||
wcs_concat2(ip, _countof(ip), cc->ip, cc->ipv6, L", ");
|
||||
WCHAR *assigned_ip = LoadLocalizedString(IDS_TIP_ASSIGNED_IP, ip);
|
||||
_tcsncat(msg, assigned_ip, _countof(msg) - _tcslen(msg) - 1);
|
||||
}
|
||||
|
@ -502,21 +505,8 @@ ShowTrayBalloon(TCHAR *infotitle_msg, TCHAR *info_msg)
|
|||
void
|
||||
SetMenuStatus(connection_t *c, conn_state_t state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < o.num_configs; ++i)
|
||||
{
|
||||
if (c == &o.conn[i])
|
||||
break;
|
||||
}
|
||||
SetMenuStatusById(i, state);
|
||||
}
|
||||
|
||||
void
|
||||
SetMenuStatusById(int i, conn_state_t state)
|
||||
{
|
||||
connection_t *c = &o.conn[i];
|
||||
int checked = 0;
|
||||
int i = c->id;
|
||||
|
||||
if (state == connected || state == disconnecting) checked = 1;
|
||||
else if (state != disconnected && state != detached && state != onhold) checked = 2;
|
||||
|
|
1
tray.h
1
tray.h
|
@ -52,7 +52,6 @@ void OnDestroyTray(void);
|
|||
void ShowTrayIcon();
|
||||
void SetTrayIcon(conn_state_t);
|
||||
void SetMenuStatus(connection_t *, conn_state_t);
|
||||
void SetMenuStatusById(int, conn_state_t);
|
||||
void SetServiceMenuStatus();
|
||||
void ShowTrayBalloon(TCHAR *, TCHAR *);
|
||||
void CheckAndSetTrayIcon();
|
||||
|
|
20
viewlog.c
20
viewlog.c
|
@ -37,7 +37,7 @@
|
|||
|
||||
extern options_t o;
|
||||
|
||||
void ViewLog(int config)
|
||||
void ViewLog(connection_t *c)
|
||||
{
|
||||
TCHAR filename[2*MAX_PATH];
|
||||
|
||||
|
@ -54,15 +54,15 @@ void ViewLog(int config)
|
|||
|
||||
/* Try first using file association */
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */
|
||||
status = ShellExecuteW (o.hWnd, L"open", o.conn[config].log_path, NULL, o.log_dir, SW_SHOWNORMAL);
|
||||
status = ShellExecuteW (o.hWnd, L"open", c->log_path, NULL, o.log_dir, SW_SHOWNORMAL);
|
||||
|
||||
if (status > (HINSTANCE) 32) /* Success */
|
||||
return;
|
||||
else
|
||||
PrintDebug (L"Opening log file using ShellExecute with verb = open failed"
|
||||
" for config '%ls' (status = %lu)", o.conn[config].config_name, status);
|
||||
" for config '%ls' (status = %lu)", c->config_name, status);
|
||||
|
||||
_sntprintf_0(filename, _T("%ls \"%ls\""), o.log_viewer, o.conn[config].log_path);
|
||||
_sntprintf_0(filename, _T("%ls \"%ls\""), o.log_viewer, c->log_path);
|
||||
|
||||
/* fill in STARTUPINFO struct */
|
||||
GetStartupInfo(&start_info);
|
||||
|
@ -92,7 +92,7 @@ void ViewLog(int config)
|
|||
}
|
||||
|
||||
|
||||
void EditConfig(int config)
|
||||
void EditConfig(connection_t *c)
|
||||
{
|
||||
TCHAR filename[2*MAX_PATH];
|
||||
|
||||
|
@ -108,17 +108,17 @@ void EditConfig(int config)
|
|||
CLEAR (sd);
|
||||
|
||||
/* Try first using file association */
|
||||
_sntprintf_0(filename, L"%ls\\%ls", o.conn[config].config_dir, o.conn[config].config_file);
|
||||
_sntprintf_0(filename, L"%ls\\%ls", c->config_dir, c->config_file);
|
||||
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */
|
||||
status = ShellExecuteW (o.hWnd, L"open", filename, NULL, o.conn[config].config_dir, SW_SHOWNORMAL);
|
||||
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)", o.conn[config].config_name, status);
|
||||
" for config '%ls' (status = %lu)", c->config_name, status);
|
||||
|
||||
_sntprintf_0(filename, _T("%ls \"%ls\\%ls\""), o.editor, o.conn[config].config_dir, o.conn[config].config_file);
|
||||
_sntprintf_0(filename, _T("%ls \"%ls\\%ls\""), o.editor, c->config_dir, c->config_file);
|
||||
|
||||
/* fill in STARTUPINFO struct */
|
||||
GetStartupInfo(&start_info);
|
||||
|
@ -135,7 +135,7 @@ void EditConfig(int config)
|
|||
TRUE,
|
||||
CREATE_NEW_CONSOLE,
|
||||
NULL,
|
||||
o.conn[config].config_dir, //start-up dir
|
||||
c->config_dir, //start-up dir
|
||||
&start_info,
|
||||
&proc_info))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue