From 94179911682503e916b9d105f100c85964f711be Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Sat, 14 Jan 2023 10:34:11 -0500 Subject: [PATCH] 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 --- main.c | 109 +++++++++++++++++++++++------------------------ openvpn.c | 6 --- openvpn_config.c | 73 +++++++++++++++---------------- options.c | 20 ++++----- options.h | 5 ++- plap/stub.c | 4 -- plap/ui_glue.c | 22 +++++----- tray.c | 90 +++++++++++++++++--------------------- tray.h | 1 - viewlog.c | 20 ++++----- viewlog.h | 6 ++- 11 files changed, 165 insertions(+), 191 deletions(-) diff --git a/main.c b/main.c index 385b414..f20ee4c 100644 --- a/main.c +++ b/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; } diff --git a/openvpn.c b/openvpn.c index bf8fb1c..630361e 100644 --- a/openvpn.c +++ b/openvpn.c @@ -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) { diff --git a/openvpn_config.c b/openvpn_config.c index 59aa7f9..510a2f2 100644 --- a/openvpn_config.c +++ b/openvpn_config.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 */ diff --git a/options.c b/options.c index 32e86b4..94e2581 100644 --- a/options.c +++ b/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; } diff --git a/options.h b/options.h index 2b1a383..72757a6 100644 --- a/options.h +++ b/options.h @@ -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 */ diff --git a/plap/stub.c b/plap/stub.c index f58e393..291dfea 100644 --- a/plap/stub.c +++ b/plap/stub.c @@ -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; diff --git a/plap/ui_glue.c b/plap/ui_glue.c index 1b819f7..f26d22b 100644 --- a/plap/ui_glue.c +++ b/plap/ui_glue.c @@ -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); } } } diff --git a/tray.c b/tray.c index d79f21e..22b8e0b 100644 --- a/tray.c +++ b/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; diff --git a/tray.h b/tray.h index 7ab9dab..b6f5a94 100644 --- a/tray.h +++ b/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(); diff --git a/viewlog.c b/viewlog.c index 1ef9a84..94d80cb 100644 --- a/viewlog.c +++ b/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)) { diff --git a/viewlog.h b/viewlog.h index 2faa53f..bcb825a 100644 --- a/viewlog.h +++ b/viewlog.h @@ -19,5 +19,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -void ViewLog(int config); -void EditConfig(int config); +struct connection; + +void ViewLog(struct connection *c); +void EditConfig(struct connection *c);