[Openvpn-devel,openvpn-gui] Update system tray to populate Windows VPN flyout

Message ID BL0PR2101MB1058B863878E4C9740E1B125AB540@BL0PR2101MB1058.namprd21.prod.outlook.com
State Superseded
Headers show
Series [Openvpn-devel,openvpn-gui] Update system tray to populate Windows VPN flyout | expand

Commit Message

Kristof Provost via Openvpn-devel July 25, 2018, 7:01 a.m. UTC
From ed96e2d91a0eb9ecdaab8d7104f397f7d77e5ced Mon Sep 17 00:00:00 2001
From: Kevin Kane <kkane@microsoft.com>
Date: Fri, 13 Jul 2018 09:50:00 -0700
Subject: Update system tray to populate Windows VPN flyout

Add a DLL to be wired in as a custom dialer, which introduces new build dependencies
Add copyright notices as required where Microsoft has contributed code

Signed-off-by: Kevin Kane <kkane@microsoft.com>
---
.gitignore   |   3 +
BUILD.rst    |   1 +
Makefile.am  |  10 ++-
configure.ac |   4 ++
dialer.c     | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++
tray.c       | 117 +++++++++++++++++++++++++++++++++++
tray.h       |   2 +
7 files changed, 307 insertions(+), 1 deletion(-)
create mode 100644 dialer.c

--
2.17.1.windows.2
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Comments

Selva Nair July 25, 2018, 7:27 a.m. UTC | #1
Hi,

On Wed, Jul 25, 2018 at 1:01 PM, Kevin Kane via Openvpn-devel
<openvpn-devel@lists.sourceforge.net> wrote:
> From ed96e2d91a0eb9ecdaab8d7104f397f7d77e5ced Mon Sep 17 00:00:00 2001
>
> From: Kevin Kane <kkane@microsoft.com>
>
> Date: Fri, 13 Jul 2018 09:50:00 -0700
>
> Subject: Update system tray to populate Windows VPN flyout
>
>
>
> Add a DLL to be wired in as a custom dialer, which introduces new build
> dependencies
>
> Add copyright notices as required where Microsoft has contributed code
>
>
>
> Signed-off-by: Kevin Kane <kkane@microsoft.com>
>

As discussed in a previous thread, I'm not sure we should have this in
its current form:

(i) It adds and entry per config to network connections which will be
a nuisance for users who have far too many configs (there are some
users with 100's of config files) -- so we at least need an option to
enable/disable this.

(ii) This only supports connect, not disconnect and the entry does not
show whether its connected or not -- so this is a feature of very
dubious utility.

(iii) Communicating with the GUI using COPYDATA message (we support
connect, disconnect, status etc.) should be preferred over hard-coding
IDM_CONNECTMENU.

Selva

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Kristof Provost via Openvpn-devel July 25, 2018, 7:35 a.m. UTC | #2
I agree. This was the consensus when we discussed this feature before, but there was some interest in possibly taking this work in an experimental branch and later building something more production-ready on top of the plumbing work. It is with that expectation I'm offering it upstream.

-----Original Message-----
From: Selva Nair <selva.nair@gmail.com> 
Sent: Wednesday, July 25, 2018 10:28 AM
To: Kevin Kane <kkane@microsoft.com>
Cc: openvpn-devel <openvpn-devel@lists.sourceforge.net>
Subject: Re: [Openvpn-devel] [PATCH] [openvpn-gui] Update system tray to populate Windows VPN flyout

Hi,

On Wed, Jul 25, 2018 at 1:01 PM, Kevin Kane via Openvpn-devel <openvpn-devel@lists.sourceforge.net> wrote:
> From ed96e2d91a0eb9ecdaab8d7104f397f7d77e5ced Mon Sep 17 00:00:00 2001
>
> From: Kevin Kane <kkane@microsoft.com>
>
> Date: Fri, 13 Jul 2018 09:50:00 -0700
>
> Subject: Update system tray to populate Windows VPN flyout
>
>
>
> Add a DLL to be wired in as a custom dialer, which introduces new 
> build dependencies
>
> Add copyright notices as required where Microsoft has contributed code
>
>
>
> Signed-off-by: Kevin Kane <kkane@microsoft.com>
>

As discussed in a previous thread, I'm not sure we should have this in its current form:

(i) It adds and entry per config to network connections which will be a nuisance for users who have far too many configs (there are some users with 100's of config files) -- so we at least need an option to enable/disable this.

(ii) This only supports connect, not disconnect and the entry does not show whether its connected or not -- so this is a feature of very dubious utility.

(iii) Communicating with the GUI using COPYDATA message (we support connect, disconnect, status etc.) should be preferred over hard-coding IDM_CONNECTMENU.

Selva
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Gert Doering July 25, 2018, 8 a.m. UTC | #3
Hi,

as a side note, your mail client massacres leading whitespace, so
the patch is all squeezed to the left side:

On Wed, Jul 25, 2018 at 05:01:39PM +0000, Kevin Kane via Openvpn-devel wrote:
> diff --git a/Makefile.am b/Makefile.am
> index 8301087..d8435ed 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -2,6 +2,7 @@
> #
> #  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
> #                2010 Heiko Hund <heikoh@users.sf.net>
> +#  Portions Copyright (C) 2018 Microsoft Corporation
> #

... which makes it impossible to apply without manually adding the
leading space in non-changed lines.

Interesting enough...

>   *
>   *  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
>   *                2010 Heiko Hund <heikoh@users.sf.net>
> + *  Portions Copyright (C) 2018 Microsoft Corporation
>   *
>   *  This program is free software; you can redistribute it and/or modify
>   *  it under the terms of the GNU General Public License as published by

... the effect differs...


But anyway.  If possible, use "git send-email" (which is much better
at not massacring things than the standard clients) - and point it to
something which is not Exchange.  Unfortunately, we've seen that as
well, git-send-email sending via SMTP to Exchange, and Exchange hacking 
and slaying at the patch...

thanks :)

gert
Kristof Provost via Openvpn-devel July 25, 2018, 8:08 a.m. UTC | #4
Ugh. Thanks, Outlook. I'd have to use a personal e-mail account to use something other than Exchange.

The other option is for me to add the files to the e-mail as attachments. Is that acceptable, or do you really need the patch text to be in the message body?

-----Original Message-----
From: Gert Doering <gert@greenie.muc.de> 
Sent: Wednesday, July 25, 2018 11:00 AM
To: Kevin Kane <kkane@microsoft.com>
Cc: openvpn-devel <openvpn-devel@lists.sourceforge.net>
Subject: Re: [Openvpn-devel] [PATCH] [openvpn-gui] Update system tray to populate Windows VPN flyout

Hi,

as a side note, your mail client massacres leading whitespace, so the patch is all squeezed to the left side:

On Wed, Jul 25, 2018 at 05:01:39PM +0000, Kevin Kane via Openvpn-devel wrote:
> diff --git a/Makefile.am b/Makefile.am index 8301087..d8435ed 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -2,6 +2,7 @@
> #
> #  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
> #                2010 Heiko Hund <heikoh@users.sf.net>
> +#  Portions Copyright (C) 2018 Microsoft Corporation
> #

... which makes it impossible to apply without manually adding the leading space in non-changed lines.

Interesting enough...

>   *
>   *  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
>   *                2010 Heiko Hund <heikoh@users.sf.net>
> + *  Portions Copyright (C) 2018 Microsoft Corporation
>   *
>   *  This program is free software; you can redistribute it and/or modify
>   *  it under the terms of the GNU General Public License as published 
> by

... the effect differs...


But anyway.  If possible, use "git send-email" (which is much better at not massacring things than the standard clients) - and point it to something which is not Exchange.  Unfortunately, we've seen that as well, git-send-email sending via SMTP to Exchange, and Exchange hacking and slaying at the patch...

thanks :)

gert
--
"If was one thing all people took for granted, was conviction that if you  feed honest figures into a computer, honest figures come out. Never doubted  it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             gert@greenie.muc.de

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Gert Doering July 25, 2018, 8:17 a.m. UTC | #5
Hi,

On Wed, Jul 25, 2018 at 06:08:19PM +0000, Kevin Kane wrote:
> Ugh. Thanks, Outlook. I'd have to use a personal e-mail account to use something other than Exchange.
> 
> The other option is for me to add the files to the e-mail as attachments. Is that acceptable, or do you really need the patch text to be in the message body?

For applying with "git am" and for reviewing with "I can just quote
parts of the patch and comment on it", attachments in anything that is
not text/plain format are also not ideal, but we can try that.

We've had a few patches come in recently that were attachment in a 
signed mail, and neither patchwork nor git could handle these mails
in a satisfying way - as in: patchwork did not recognize them as
"patch", and "git am" declared "no patch in there" - so "save patch
as individual file, git am, manually add in-reply-to to the auto-
generated "patch applied" reply mail, etc.

It's a bit of try and error what works in a given environment.

(git send-email talking SMTP to Exchange might actually work more 
nicely than outlook.  Maybe that was just one particularily weird
version of Exchange, or "too many virus scanner plugins hooked in",
given that this was Sophos...)

gert
Kristof Provost via Openvpn-devel July 25, 2018, 10:03 a.m. UTC | #6
Alright, I found the SMTP server and sent the patches out again with git send-email. Let me know how those look.

-----Original Message-----
From: Gert Doering <gert@greenie.muc.de> 
Sent: Wednesday, July 25, 2018 11:18 AM
To: Kevin Kane <kkane@microsoft.com>
Cc: Gert Doering <gert@greenie.muc.de>; openvpn-devel <openvpn-devel@lists.sourceforge.net>
Subject: Re: [Openvpn-devel] [PATCH] [openvpn-gui] Update system tray to populate Windows VPN flyout

Hi,

On Wed, Jul 25, 2018 at 06:08:19PM +0000, Kevin Kane wrote:
> Ugh. Thanks, Outlook. I'd have to use a personal e-mail account to use something other than Exchange.
> 
> The other option is for me to add the files to the e-mail as attachments. Is that acceptable, or do you really need the patch text to be in the message body?

For applying with "git am" and for reviewing with "I can just quote parts of the patch and comment on it", attachments in anything that is not text/plain format are also not ideal, but we can try that.

We've had a few patches come in recently that were attachment in a signed mail, and neither patchwork nor git could handle these mails in a satisfying way - as in: patchwork did not recognize them as "patch", and "git am" declared "no patch in there" - so "save patch as individual file, git am, manually add in-reply-to to the auto- generated "patch applied" reply mail, etc.

It's a bit of try and error what works in a given environment.

(git send-email talking SMTP to Exchange might actually work more nicely than outlook.  Maybe that was just one particularily weird version of Exchange, or "too many virus scanner plugins hooked in", given that this was Sophos...)

gert

--
"If was one thing all people took for granted, was conviction that if you  feed honest figures into a computer, honest figures come out. Never doubted  it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             gert@greenie.muc.de

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Илья Шипицин July 25, 2018, 10:18 a.m. UTC | #7
чт, 26 июл. 2018 г. в 1:04, Kevin Kane via Openvpn-devel <
openvpn-devel@lists.sourceforge.net>:

> Alright, I found the SMTP server and sent the patches out again with git
> send-email. Let me know how those look.
>


looks good from patchwork point of view:

https://patchwork.openvpn.net/project/openvpn2/list/


>
> -----Original Message-----
> From: Gert Doering <gert@greenie.muc.de>
> Sent: Wednesday, July 25, 2018 11:18 AM
> To: Kevin Kane <kkane@microsoft.com>
> Cc: Gert Doering <gert@greenie.muc.de>; openvpn-devel <
> openvpn-devel@lists.sourceforge.net>
> Subject: Re: [Openvpn-devel] [PATCH] [openvpn-gui] Update system tray to
> populate Windows VPN flyout
>
> Hi,
>
> On Wed, Jul 25, 2018 at 06:08:19PM +0000, Kevin Kane wrote:
> > Ugh. Thanks, Outlook. I'd have to use a personal e-mail account to use
> something other than Exchange.
> >
> > The other option is for me to add the files to the e-mail as
> attachments. Is that acceptable, or do you really need the patch text to be
> in the message body?
>
> For applying with "git am" and for reviewing with "I can just quote parts
> of the patch and comment on it", attachments in anything that is not
> text/plain format are also not ideal, but we can try that.
>
> We've had a few patches come in recently that were attachment in a signed
> mail, and neither patchwork nor git could handle these mails in a
> satisfying way - as in: patchwork did not recognize them as "patch", and
> "git am" declared "no patch in there" - so "save patch as individual file,
> git am, manually add in-reply-to to the auto- generated "patch applied"
> reply mail, etc.
>
> It's a bit of try and error what works in a given environment.
>
> (git send-email talking SMTP to Exchange might actually work more nicely
> than outlook.  Maybe that was just one particularily weird version of
> Exchange, or "too many virus scanner plugins hooked in", given that this
> was Sophos...)
>
> gert
>
> --
> "If was one thing all people took for granted, was conviction that if you
> feed honest figures into a computer, honest figures come out. Never
> doubted  it myself till I met a computer with a sense of humor."
>                              Robert A. Heinlein, The Moon is a Harsh
> Mistress
>
> Gert Doering - Munich, Germany
> gert@greenie.muc.de
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
>
<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">чт, 26 июл. 2018 г. в 1:04, Kevin Kane via Openvpn-devel &lt;<a href="mailto:openvpn-devel@lists.sourceforge.net">openvpn-devel@lists.sourceforge.net</a>&gt;:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Alright, I found the SMTP server and sent the patches out again with git send-email. Let me know how those look.<br></blockquote><div><br></div><div><br></div><div>looks good from patchwork point of view:</div><div><br></div><div><a href="https://patchwork.openvpn.net/project/openvpn2/list/">https://patchwork.openvpn.net/project/openvpn2/list/</a><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
-----Original Message-----<br>
From: Gert Doering &lt;<a href="mailto:gert@greenie.muc.de" target="_blank">gert@greenie.muc.de</a>&gt; <br>
Sent: Wednesday, July 25, 2018 11:18 AM<br>
To: Kevin Kane &lt;<a href="mailto:kkane@microsoft.com" target="_blank">kkane@microsoft.com</a>&gt;<br>
Cc: Gert Doering &lt;<a href="mailto:gert@greenie.muc.de" target="_blank">gert@greenie.muc.de</a>&gt;; openvpn-devel &lt;<a href="mailto:openvpn-devel@lists.sourceforge.net" target="_blank">openvpn-devel@lists.sourceforge.net</a>&gt;<br>
Subject: Re: [Openvpn-devel] [PATCH] [openvpn-gui] Update system tray to populate Windows VPN flyout<br>
<br>
Hi,<br>
<br>
On Wed, Jul 25, 2018 at 06:08:19PM +0000, Kevin Kane wrote:<br>
&gt; Ugh. Thanks, Outlook. I&#39;d have to use a personal e-mail account to use something other than Exchange.<br>
&gt; <br>
&gt; The other option is for me to add the files to the e-mail as attachments. Is that acceptable, or do you really need the patch text to be in the message body?<br>
<br>
For applying with &quot;git am&quot; and for reviewing with &quot;I can just quote parts of the patch and comment on it&quot;, attachments in anything that is not text/plain format are also not ideal, but we can try that.<br>
<br>
We&#39;ve had a few patches come in recently that were attachment in a signed mail, and neither patchwork nor git could handle these mails in a satisfying way - as in: patchwork did not recognize them as &quot;patch&quot;, and &quot;git am&quot; declared &quot;no patch in there&quot; - so &quot;save patch as individual file, git am, manually add in-reply-to to the auto- generated &quot;patch applied&quot; reply mail, etc.<br>
<br>
It&#39;s a bit of try and error what works in a given environment.<br>
<br>
(git send-email talking SMTP to Exchange might actually work more nicely than outlook.  Maybe that was just one particularily weird version of Exchange, or &quot;too many virus scanner plugins hooked in&quot;, given that this was Sophos...)<br>
<br>
gert<br>
<br>
--<br>
&quot;If was one thing all people took for granted, was conviction that if you  feed honest figures into a computer, honest figures come out. Never doubted  it myself till I met a computer with a sense of humor.&quot;<br>
                             Robert A. Heinlein, The Moon is a Harsh Mistress<br>
<br>
Gert Doering - Munich, Germany                             <a href="mailto:gert@greenie.muc.de" target="_blank">gert@greenie.muc.de</a><br>
<br>
------------------------------------------------------------------------------<br>
Check out the vibrant tech community on one of the world&#39;s most<br>
engaging tech sites, Slashdot.org! <a href="http://sdm.link/slashdot" rel="noreferrer" target="_blank">http://sdm.link/slashdot</a><br>
_______________________________________________<br>
Openvpn-devel mailing list<br>
<a href="mailto:Openvpn-devel@lists.sourceforge.net" target="_blank">Openvpn-devel@lists.sourceforge.net</a><br>
<a href="https://lists.sourceforge.net/lists/listinfo/openvpn-devel" rel="noreferrer" target="_blank">https://lists.sourceforge.net/lists/listinfo/openvpn-devel</a><br>
</blockquote></div></div>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Patch

diff --git a/.gitignore b/.gitignore
index ac37772..e36e0a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@ 
*.log
*.tar.gz
*.bak
+*.lo
+*.la

.deps
Makefile
@@ -30,3 +32,4 @@  depcomp
stamp-h1
install-sh
missing
+libtool
diff --git a/BUILD.rst b/BUILD.rst
index 9354784..3c70b52 100644
--- a/BUILD.rst
+++ b/BUILD.rst
@@ -24,6 +24,7 @@  their dependencies. You can install these packages using the standard
- mingw64-x86_64-gcc-core
- mingw64-x86_64-g++
- mingw64-x86_64-openssl
+- libtool

 Build
diff --git a/Makefile.am b/Makefile.am
index 8301087..d8435ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,6 +2,7 @@ 
#
#  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
#                2010 Heiko Hund <heikoh@users.sf.net>
+#  Portions Copyright (C) 2018 Microsoft Corporation
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
@@ -22,6 +23,7 @@  RCCOMPILE = $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
     $(AM_CPPFLAGS) $(CPPFLAGS)

AUTOMAKE_OPTIONS = foreign 1.9
+ACLOCAL_AMFLAGS = -I m4

MAINTAINERCLEANFILES = \
                config.log config.status \
@@ -106,7 +108,13 @@  openvpn_gui_LDADD = \
                -lnetapi32 \
                -lole32 \
                -lshlwapi \
-              -lsecur32
+             -lsecur32 \
+             -lrasapi32

openvpn-gui-res.o: $(openvpn_gui_RESOURCES) $(srcdir)/openvpn-gui-res.h
                $(RCCOMPILE) -i $< -o $@
+
+lib_LTLIBRARIES              = libopenvpndialer.la
+libopenvpndialer_la_SOURCES  = dialer.c
+libopenvpndialer_la_LDFLAGS  = -no-undefined
+libopenvpndialer_la_LIBADD   = -lrasapi32
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
index 9a2ba75..4fe6b81 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,6 +2,7 @@  dnl  OpenVPN-GUI -- A Windows GUI for OpenVPN.
dnl
dnl  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
dnl                2010 Heiko Hund <heikoh@users.sf.net>
+dnl  Portions Copyright (C) 2018 Microsoft Corporation
dnl
dnl  This program is free software; you can redistribute it and/or modify
dnl  it under the terms of the GNU General Public License as published by
@@ -29,10 +30,13 @@  AC_DEFINE([CORE_COPYRIGHT_YEAR_END], ["2018"], [Last copyright year for daemon i
AC_CONFIG_AUX_DIR([.])
AM_CONFIG_HEADER([config.h])
AC_CONFIG_SRCDIR([main.h])
+AC_CONFIG_MACRO_DIRS([m4])
AM_INIT_AUTOMAKE
AC_CANONICAL_HOST
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC_C99
+LT_INIT([win32-dll])
+AC_LIBTOOL_WIN32_DLL
AC_CHECK_TOOL([WINDRES], [windres])

AC_ARG_ENABLE(
diff --git a/dialer.c b/dialer.c
new file mode 100644
index 0000000..86a0f39
--- /dev/null
+++ b/dialer.c
@@ -0,0 +1,171 @@ 
+/*
+ *  OpenVPN-GUI -- A Windows GUI for OpenVPN.
+ *
+ *  Copyright (C) 2018 Microsoft Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <tchar.h>
+#include <ras.h>
+#include <rasdlg.h>
+#include <raserror.h>
+
+__declspec(dllexport)
+DWORD WINAPI RasCustomDial(
+    HINSTANCE hInstDll __attribute__((unused)),
+    LPRASDIALEXTENSIONS lpRasDialExtensions __attribute__((unused)),
+    LPWSTR lpszPhonebook __attribute__((unused)),
+    LPRASDIALPARAMSW lpRasDialParams __attribute__((unused)),
+    DWORD dwNotifierType __attribute__((unused)),
+    LPVOID lpvNotifier __attribute__((unused)),
+    LPHRASCONN lphRasConn __attribute__((unused)),
+    DWORD dwFlags __attribute__((unused)))
+{
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+/* Copied from OpenVPN-GUI main.c */
+static const TCHAR OpenVPNGuiClassName[] = _T("OpenVPN-GUI");
+
+/* Copied from OpenVPN-GUI tray.h */
+#define IDM_CONNECTMENU         300
+
+static const TCHAR WindowCaption[] = _T("Walrus VPN");
+
+__declspec(dllexport)
+BOOL WINAPI RasCustomDialDlg(
+    HINSTANCE hInstDll __attribute__((unused)),
+    DWORD dwFlags __attribute__((unused)),
+    LPWSTR lpszwPhonebook,
+    LPWSTR lpszwEntry,
+    LPWSTR lpszwPhoneNumber __attribute__((unused)),
+    LPRASDIALDLG lpInfo,
+    PVOID pVoid __attribute__((unused)))
+{
+    HWND window = FindWindow(OpenVPNGuiClassName, NULL);
+    if (NULL == window)
+    {
+        MessageBox(NULL, _T("OpenVPN-GUI is not running. Please launch the GUI."), WindowCaption, MB_OK);
+        lpInfo->dwError = ERROR_UNKNOWN;
+        return FALSE;
+    }
+    else
+    {
+        DWORD result;
+        DWORD entrySize = 0;
+        LPRASENTRYW entry = NULL;
+
+        result = RasGetEntryPropertiesW(lpszwPhonebook, lpszwEntry, NULL, &entrySize, NULL, NULL);
+        if (ERROR_SUCCESS != result && ERROR_BUFFER_TOO_SMALL != result)
+        {
+            MessageBox(NULL, _T("Could not get size of VPN entry"), WindowCaption, MB_OK);
+            lpInfo->dwError = result;
+            return FALSE;
+        }
+
+        entry = (LPRASENTRYW)malloc(entrySize);
+        if (NULL == entry)
+        {
+            lpInfo->dwError = ERROR_OUTOFMEMORY;
+            return FALSE;
+        }
+
+        memset(entry, 0, entrySize);
+        entry->dwSize = sizeof(RASENTRYW);
+
+        result = RasGetEntryPropertiesW(lpszwPhonebook, lpszwEntry, entry, &entrySize, NULL, NULL);
+        if (ERROR_SUCCESS != result)
+        {
+            MessageBox(NULL, _T("Could not get VPN entry"), WindowCaption, MB_OK);
+            lpInfo->dwError = result;
+            free(entry);
+            return FALSE;
+        }
+
+        /* Convert the number in the local phone number field to get the offset. */
+        int offset = _wtoi(entry->szLocalPhoneNumber);
+
+        /* Sanity check: There should not be more than 10 entries, and the value should never be negative.*/
+        if (0 > offset || 10 < offset)
+        {
+            MessageBox(NULL, _T("Offset is invalid number"), WindowCaption, MB_OK);
+            lpInfo->dwError = ERROR_UNKNOWN;
+            free(entry);
+            return FALSE;
+        }
+
+        if (0 == offset)
+        {
+            /* 0 is also used for an error condition. If that's the case, check that the string is actually
+             * a zero.
+             */
+            if (entry->szLocalPhoneNumber[0] != L'0' && entry->szLocalPhoneNumber[1] != L'\0')
+            {
+                MessageBox(NULL, _T("Offset not recognized as a number"), WindowCaption, MB_OK);
+                lpInfo->dwError = ERROR_UNKNOWN;
+                free(entry);
+                return FALSE;
+            }
+        }
+
+        /* No longer need entry at this point. */
+        free(entry);
+
+        if (FALSE == PostMessage(window, WM_COMMAND, IDM_CONNECTMENU + offset, 0))
+        {
+            MessageBox(NULL, _T("Could not communicate with OpenVPN-GUI"), WindowCaption, MB_OK);
+            lpInfo->dwError = GetLastError();
+            return FALSE;
+        }
+        else
+        {
+            return TRUE;
+        }
+    }
+}
+
+__declspec(dllexport)
+DWORD WINAPI RasCustomHangUp(
+    HRASCONN hRasConn __attribute__((unused)))
+{
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+__declspec(dllexport)
+BOOL WINAPI RasCustomEntryDlg(HINSTANCE hInstDll __attribute__((unused)),
+    LPWSTR lpszwPhonebook __attribute__((unused)),
+    LPWSTR lpszwEntry __attribute__((unused)),
+    LPRASENTRYDLG lpInfo,
+    DWORD dwFlags __attribute__((unused)))
+{
+    lpInfo->dwError = ERROR_CALL_NOT_IMPLEMENTED;
+    return FALSE;
+}
+
+__declspec(dllexport)
+DWORD CALLBACK RasCustomDeleteEntryNotify(
+    LPCTSTR lpszPhonebook __attribute__((unused)),
+    LPCTSTR lpszEntry __attribute__((unused)),
+    DWORD   dwFlags __attribute__((unused)))
+{
+    return ERROR_SUCCESS;
+}
diff --git a/tray.c b/tray.c
index 1e1dc2e..9ce27a0 100644
--- a/tray.c
+++ b/tray.c
@@ -3,6 +3,7 @@ 
  *
  *  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
  *                2010 Heiko Hund <heikoh@users.sf.net>
+ *  Portions Copyright (C) 2018 Microsoft Corporation
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,6 +29,8 @@ 
#include <shellapi.h>
#include <tchar.h>
#include <time.h>
+#include <ras.h>
+#include <raserror.h>

#include "tray.h"
#include "service.h"
@@ -47,6 +50,116 @@  HMENU hMenuService;
NOTIFYICONDATA ni;
extern options_t o;

+static const TCHAR VpnEntryPrefix[] = _T("OpenVPN ");
+static const TCHAR WindowCaption[] = _T("OpenVPN-GUI");
+
+/* Delete OpenVPN entries from Windows networking/VPN flyout */
+void
+ClearNetworkFlyout()
+{
+    DWORD result = ERROR_SUCCESS;
+    LPRASENTRYNAME entryName = NULL;
+    DWORD entryNameSize = 0;
+    DWORD entryCount = 0;
+
+    /* Determine memory required */
+    result = RasEnumEntries(NULL, NULL, NULL, &entryNameSize, &entryCount);
+    if (ERROR_BUFFER_TOO_SMALL != result)
+    {
+        /* Anything else is unexpected. */
+        MessageBox(NULL, _T("ClearNetworkFlyout: Could not get memory needed for RAS entries"), WindowCaption, MB_OK);
+        return;
+    }
+
+    entryName = (LPRASENTRYNAME)malloc(entryNameSize);
+    if (NULL == entryName)
+    {
+        /* No memory! */
+        MessageBox(NULL, _T("ClearNetworkFlyout: No memory allocating entry name"), WindowCaption, MB_OK);
+        return;
+    }
+
+    entryName[0].dwSize = sizeof(RASENTRYNAME);
+
+    result = RasEnumEntries(NULL, NULL, entryName, &entryNameSize, &entryCount);
+    if (ERROR_SUCCESS != result)
+    {
+        MessageBox(NULL, _T("ClearNetworkFlyout: Could not enumerate RAS entries"), WindowCaption, MB_OK);
+        free(entryName);
+        return;
+    }
+
+    for (DWORD i = 0; i < entryCount; i++)
+    {
+        if ((entryName[i].dwFlags == REN_User) &&
+            (0 == _tcsncmp(VpnEntryPrefix, entryName[i].szEntryName, _countof(VpnEntryPrefix) - 1)))
+        {
+            /* TODO: Retrieve the entry and verify that it references our custom dialer DLL? RasEnumEntries doesn't
+             * give us this information but we could retrieve the entry and check. This would keep us from purging any
+             * entries which for some inexplicable reason started with the VpnEntryPrefix string.
+             */
+            result = RasDeleteEntry(NULL, entryName[i].szEntryName);
+            if (ERROR_SUCCESS != result)
+            {
+                MessageBox(NULL, _T("ClearNetworkFlyout: Failed to delete entry"), WindowCaption, MB_OK);
+                /* Continue processing; don't return. */
+            }
+        }
+    }
+
+    free(entryName);
+
+    return;
+}
+
+static const TCHAR DialerFileName[] = _T("libopenvpndialer-0.dll");
+static const TCHAR DeviceName[] = _T("TAP-Windows Adapter V9");
+
+/* Create VPN flyout entry for a new connection */
+static void
+CreateNetworkFlyoutEntry(const connection_t *c, int number)
+{
+    DWORD result = ERROR_SUCCESS;
+    RASENTRY entry;
+    TCHAR entryName[RAS_MaxEntryName + 1];
+
+    memset(&entry, 0, sizeof(entry));
+    entry.dwSize = sizeof(entry);
+    _tcsncpy(entry.szDeviceType, RASDT_Vpn, _countof(RASDT_Vpn));
+    _tcsncpy(entry.szDeviceName, DeviceName, _countof(DeviceName));
+
+    entry.dwfOptions = RASEO_Custom;
+    /* Take the exe_path, strip off everything after the last backslash, and append DialerFileName */
+    TCHAR* lastBackslash = _tcsrchr(o.exe_path, _T('\\'));
+    if (NULL == lastBackslash)
+    {
+        MessageBox(NULL, _T("CreateNetworkFlyoutEntry: No last backslash found"), WindowCaption, MB_OK);
+        return;
+    }
+    _tcsncpy(entry.szCustomDialDll, o.exe_path, (lastBackslash - o.exe_path + 1));
+    /* Check for possible overrun */
+    if (_tcslen(entry.szCustomDialDll) + _countof(DialerFileName) >= _countof(entry.szCustomDialDll))
+    {
+        MessageBox(NULL, _T("CreateNetworkFlyoutEntry: Not enough space for custom dialer DLL filename"), WindowCaption, MB_OK);
+        return;
+    }
+    _tcsncat(entry.szCustomDialDll, DialerFileName, _countof(DialerFileName));
+
+    /* Use the local phone number space to store the entry number for the custom dialer to use. */
+    _sntprintf_0(entry.szLocalPhoneNumber, _T("%d"), number);
+    entry.dwType = RASET_Vpn;
+    entry.dwEncryptionType = ET_Optional;
+
+    _sntprintf_0(entryName, _T("%s%s"), VpnEntryPrefix, c->config_name);
+    result = RasSetEntryProperties(NULL, entryName, &entry, sizeof(entry), NULL, 0);
+    if (ERROR_SUCCESS != result)
+    {
+        TCHAR message[512];
+        _sntprintf_0(message, _T("CreateNetworkFlyoutEntry: Could not RasSetEntryProperties: %lu"), result);
+        MessageBox(NULL, message, WindowCaption, MB_OK);
+        return;
+    }
+}

/* Create popup menus */
void
@@ -92,6 +205,7 @@  CreatePopupMenus()
         AppendMenu(hMenu, MF_STRING ,IDM_CLOSE, LoadLocalizedString(IDS_MENU_CLOSE));

         SetMenuStatus(&o.conn[0],  o.conn[0].state);
+        CreateNetworkFlyoutEntry(&o.conn[0], 0);
     }
     else {
         /* Create Main menu with all connections */
@@ -135,6 +249,7 @@  CreatePopupMenus()
#endif

             SetMenuStatus(&o.conn[i], o.conn[i].state);
+            CreateNetworkFlyoutEntry(&o.conn[i], i);
         }
     }

@@ -152,6 +267,7 @@  DestroyPopupMenus()

     DestroyMenu(hMenuService);
     DestroyMenu(hMenu);
+    ClearNetworkFlyout();
}

@@ -218,6 +334,7 @@  void
OnDestroyTray()
{
     DestroyMenu(hMenu);
+    ClearNetworkFlyout();
     Shell_NotifyIcon(NIM_DELETE, &ni);
}

diff --git a/tray.h b/tray.h
index 1ce5e07..f5a9ff4 100644
--- a/tray.h
+++ b/tray.h
@@ -3,6 +3,7 @@ 
  *
  *  Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
  *                2010 Heiko Hund <heikoh@users.sf.net>
+ *  Portions Copyright (C) 2018 Microsoft Corporation
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -51,5 +52,6 @@  void SetMenuStatus(connection_t *, conn_state_t);
void SetServiceMenuStatus();
void ShowTrayBalloon(TCHAR *, TCHAR *);
void CheckAndSetTrayIcon();
+void ClearNetworkFlyout();

#endif