From patchwork Mon Nov 26 13:28:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Rozman X-Patchwork-Id: 623 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id QHDPOfuP/FtURgAAIUCqbw for ; Mon, 26 Nov 2018 19:29:47 -0500 Received: from proxy1.mail.ord1d.rsapps.net ([172.30.191.6]) by director10.mail.ord1d.rsapps.net with LMTP id SBVaOfuP/FsrJgAApN4f7A ; Mon, 26 Nov 2018 19:29:47 -0500 Received: from smtp31.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy1.mail.ord1d.rsapps.net with LMTP id 6OlOOfuP/FueSAAAasrz9Q ; Mon, 26 Nov 2018 19:29:47 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp31.gate.ord1d.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=rozman.si; dmarc=fail (p=none; dis=none) header.from=rozman.si X-Suspicious-Flag: YES X-Classification-ID: 8abaaabc-f1db-11e8-9c65-525400b3ac8c-1-1 Received: from [216.105.38.7] ([216.105.38.7:34919] helo=lists.sourceforge.net) by smtp31.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 42/CC-23392-AFF8CFB5; Mon, 26 Nov 2018 19:29:46 -0500 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1gRREl-0003Sp-1Z; Tue, 27 Nov 2018 00:28:23 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1gRREj-0003Sh-Mt for openvpn-devel@lists.sourceforge.net; Tue, 27 Nov 2018 00:28:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=RBSxoh32NniBFZPMK5LCCyBvgqLVmc0K3SIIRv/2HMI=; b=QUOd1vmtgR04+FWrP405JKZYv7 6tzyR3fkjOpZynBA1nqquPsbIwXNl6WybUUliQlf+JzuAq6K8IJGMG2uiaMCP+Obze6H3Pz4FxLP9 D5orPIxL+QAb7Q10DSbSPAbmsogPs0chu4MpSrbApMexxY9V1mmP5/5EHDosBc9zoSA8=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=RBSxoh32NniBFZPMK5LCCyBvgqLVmc0K3SIIRv/2HMI=; b=I TLprPobXXLn5XC0ujfto9eZt91NczVSYQEnyY7Z/QYOD8aMK1UzaPRUhXssv4SAsROOVot/Na/zzG bFG4zKyPsO9mLLNXyaT+9nX6tnUUq7LfrmZpjsphbygpNHLQrgSPC0XWXTXFoasr85RCIC6SJx9N7 mKBy8Lks4Ortu9IU=; Received: from pub5.amebis.si ([213.250.55.21]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1gRREg-004sA6-4u for openvpn-devel@lists.sourceforge.net; Tue, 27 Nov 2018 00:28:21 +0000 Received: from gw0.selo.doma (unknown [213.250.22.160]) by pub5.amebis.si (Postfix) with ESMTP id B5E4A203A0; Tue, 27 Nov 2018 01:28:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=rozman.si; s=default; t=1543278490; bh=BxadazhDgkTtaQkdHOsAFiQl7lZmFmrJTznMUlc3rNk=; h=From:To:Cc:Subject:Date:From; b=F2Px7vPtK2duKBO48K48jZxh5qL/6Z2OwzGRlxztG8Oqk4+PgCUqVqBcrErymfXcn FEg7mgsk+gSv9sNkjgiDZgGPQoxg2fe8Rcgrv6DxxcIXc0cufXEV2TQEsnynFuFwwx dcuJ1bPZOIJWyeJmxSdI/I5rYh094esDJWmA3FDU= Received: from s0.selo.doma (s0.selo.doma [IPv6:2a00:ee2:1206:8101::d]) by gw0.selo.doma (Postfix) with ESMTP id 6C33E21D9D8E; Tue, 27 Nov 2018 01:28:10 +0100 (CET) From: Simon Rozman To: openvpn-devel@lists.sourceforge.net Date: Tue, 27 Nov 2018 01:28:08 +0100 Message-Id: <20181127002808.19200-1-simon@rozman.si> X-Mailer: git-send-email 2.19.0.windows.1 MIME-Version: 1.0 X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1gRREg-004sA6-4u Subject: [Openvpn-devel] [PATCH] Add a MSI custom actions to close and relaunch OpenVPN GUI X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This custom actions are used by MSI setup to close OpenVPN GUI before performing an upgrade and relaunch it afterwards. Acked-by: Gert Doering --- src/openvpnmsica/Makefile.am | 2 +- src/openvpnmsica/openvpnmsica.c | 102 ++++++++++++++++++++++++++++++++ src/openvpnmsica/openvpnmsica.h | 25 ++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/src/openvpnmsica/Makefile.am b/src/openvpnmsica/Makefile.am index f4725a53..f00a01d8 100644 --- a/src/openvpnmsica/Makefile.am +++ b/src/openvpnmsica/Makefile.am @@ -41,7 +41,7 @@ libopenvpnmsica_la_CFLAGS = \ -municode -D_UNICODE \ -UNTDDI_VERSION -U_WIN32_WINNT \ -D_WIN32_WINNT=_WIN32_WINNT_VISTA -libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -liphlpapi -lshlwapi -lversion -no-undefined -avoid-version +libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -liphlpapi -lshell32 -lshlwapi -lversion -no-undefined -avoid-version endif libopenvpnmsica_la_SOURCES = \ diff --git a/src/openvpnmsica/openvpnmsica.c b/src/openvpnmsica/openvpnmsica.c index e8988ac8..86434801 100644 --- a/src/openvpnmsica/openvpnmsica.c +++ b/src/openvpnmsica/openvpnmsica.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #ifdef _MSC_VER #pragma comment(lib, "iphlpapi.lib") +#pragma comment(lib, "shell32.lib") #pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "version.lib") #endif @@ -475,6 +477,106 @@ cleanup_CoInitialize: } +UINT __stdcall +CloseOpenVPNGUI(_In_ MSIHANDLE hInstall) +{ +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + UNREFERENCED_PARAMETER(hInstall); /* This CA is does not interact with MSI session (report errors, access properties, tables, etc.). */ + + openvpnmsica_debug_popup(TEXT(__FUNCTION__)); + + /* Find OpenVPN GUI window. */ + HWND hWnd = FindWindow(TEXT("OpenVPN-GUI"), NULL); + if (hWnd) + { + /* Ask it to close and wait for 100ms. Unfortunately, this will succeed only for recent OpenVPN GUI that do not run elevated. */ + SendMessage(hWnd, WM_CLOSE, 0, 0); + Sleep(100); + } + + return ERROR_SUCCESS; +} + + +UINT __stdcall +StartOpenVPNGUI(_In_ MSIHANDLE hInstall) +{ +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + + openvpnmsica_debug_popup(TEXT(__FUNCTION__)); + + UINT uiResult; + BOOL bIsCoInitialized = SUCCEEDED(CoInitialize(NULL)); + + /* Set MSI session handle in TLS. */ + struct openvpnmsica_tls_data *s = (struct openvpnmsica_tls_data *)TlsGetValue(openvpnmsica_tlsidx_session); + s->hInstall = hInstall; + + /* Create and populate a MSI record. */ + MSIHANDLE hRecord = MsiCreateRecord(1); + if (!hRecord) + { + uiResult = ERROR_INVALID_HANDLE; + msg(M_NONFATAL, "%s: MsiCreateRecord failed", __FUNCTION__); + goto cleanup_CoInitialize; + } + uiResult = MsiRecordSetString(hRecord, 0, TEXT("\"[#bin.openvpn_gui.exe]\"")); + if (uiResult != ERROR_SUCCESS) + { + SetLastError(uiResult); /* MSDN does not mention MsiRecordSetString() to set GetLastError(). But we do have an error code. Set last error manually. */ + msg(M_NONFATAL | M_ERRNO, "%s: MsiRecordSetString failed", __FUNCTION__); + goto cleanup_MsiCreateRecord; + } + + /* Format string. */ + TCHAR szStackBuf[MAX_PATH]; + DWORD dwPathSize = _countof(szStackBuf); + LPTSTR szPath = szStackBuf; + uiResult = MsiFormatRecord(hInstall, hRecord, szPath, &dwPathSize); + if (uiResult == ERROR_MORE_DATA) + { + /* Allocate buffer on heap (+1 for terminator), and retry. */ + szPath = (LPTSTR)malloc((++dwPathSize) * sizeof(TCHAR)); + uiResult = MsiFormatRecord(hInstall, hRecord, szPath, &dwPathSize); + } + if (uiResult != ERROR_SUCCESS) + { + SetLastError(uiResult); /* MSDN does not mention MsiFormatRecord() to set GetLastError(). But we do have an error code. Set last error manually. */ + msg(M_NONFATAL | M_ERRNO, "%s: MsiFormatRecord failed", __FUNCTION__); + goto cleanup_malloc_szPath; + } + + /* Launch the OpenVPN GUI. */ + SHELLEXECUTEINFO sei = { + .cbSize = sizeof(SHELLEXECUTEINFO), + .fMask = SEE_MASK_FLAG_NO_UI, /* Don't show error UI, we'll display it. */ + .lpFile = szPath, + .nShow = SW_SHOWNORMAL + }; + if (!ShellExecuteEx(&sei)) + { + uiResult = GetLastError(); + msg(M_NONFATAL | M_ERRNO, "%s: ShellExecuteEx(%s) failed", __FUNCTION__, szPath); + goto cleanup_malloc_szPath; + } + + uiResult = ERROR_SUCCESS; + +cleanup_malloc_szPath: + if (szPath != szStackBuf) + free(szPath); +cleanup_MsiCreateRecord: + MsiCloseHandle(hRecord); +cleanup_CoInitialize: + if (bIsCoInitialized) CoUninitialize(); + return uiResult; +} + + UINT __stdcall EvaluateTAPInterfaces(_In_ MSIHANDLE hInstall) { diff --git a/src/openvpnmsica/openvpnmsica.h b/src/openvpnmsica/openvpnmsica.h index da145062..4ee5c05f 100644 --- a/src/openvpnmsica/openvpnmsica.h +++ b/src/openvpnmsica/openvpnmsica.h @@ -91,6 +91,31 @@ DLLEXP_DECL UINT __stdcall FindTAPInterfaces(_In_ MSIHANDLE hInstall); +/** + * Find OpenVPN GUI window and send it a WM_CLOSE message. + * + * @param hInstall Handle to the installation provided to the DLL custom action + * + * @return ERROR_SUCCESS on success; An error code otherwise + * See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa368072.aspx + */ +DLLEXP_DECL UINT __stdcall +CloseOpenVPNGUI(_In_ MSIHANDLE hInstall); + + +/** + * Launches OpenVPN GUI. It's path is obtained by expanding the `[#bin.openvpn_gui.exe]` + * therefore, its Id field in File table must be "bin.openvpn_gui.exe". + * + * @param hInstall Handle to the installation provided to the DLL custom action + * + * @return ERROR_SUCCESS on success; An error code otherwise + * See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa368072.aspx + */ +DLLEXP_DECL UINT __stdcall +StartOpenVPNGUI(_In_ MSIHANDLE hInstall); + + /** * Evaluate the TAPInterface table of the MSI package database and prepare a list of TAP * interfaces to install/remove.