From patchwork Wed Jan 26 22:09:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lev Stipakov X-Patchwork-Id: 2260 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.30.191.6]) by backend41.mail.ord1d.rsapps.net with LMTP id IK84L6th8mE5DgAAqwncew (envelope-from ) for ; Thu, 27 Jan 2022 04:11:07 -0500 Received: from proxy10.mail.ord1d.rsapps.net ([172.30.191.6]) by director8.mail.ord1d.rsapps.net with LMTP id cPxTEqxh8mGRQgAAfY0hYg (envelope-from ) for ; Thu, 27 Jan 2022 04:11:08 -0500 Received: from smtp2.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy10.mail.ord1d.rsapps.net with LMTPS id KDoiEqxh8mFEHgAAfSg8FQ (envelope-from ) for ; Thu, 27 Jan 2022 04:11:08 -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: smtp2.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=gmail.com; dmarc=fail (p=none; dis=none) header.from=gmail.com X-Suspicious-Flag: YES X-Classification-ID: 0fafa69a-7f51-11ec-aec7-5254004a0287-1-1 Received: from [216.105.38.7] ([216.105.38.7:45822] helo=lists.sourceforge.net) by smtp2.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id D8/09-23376-BA162F16; Thu, 27 Jan 2022 04:11:08 -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.94.2) (envelope-from ) id 1nD0n5-0003jh-4g; Thu, 27 Jan 2022 09:10:01 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1nD0n3-0003jO-HH for openvpn-devel@lists.sourceforge.net; Thu, 27 Jan 2022 09:10:00 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=12RRYBZ1pS8iNLqSz0uv/tFczyTt32sWS9ogPkqxQC4=; b=KbdB68y9bQERuUQRLCk7SKaUfd FMMpe9VQ+CClO0RubpKqKjLOnpssziwdacOBoO59JBKeXVwfPhozjywjBq/rJHvK6NzspH6SSoUrV 0zECQBrw9Al8aARkQpMXXez6NMIbMbk1YKOgz30BhJbfaxOwu0JtbNnHh1KHaAgtEDg0=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=12RRYBZ1pS8iNLqSz0uv/tFczyTt32sWS9ogPkqxQC4=; b=HoRLvPvXiWRQQDBVbRZF9SsczP MnwaCL2FqzKKnKAcFn95LaoR7ppi6gfEOe7C8EpWEvOiJ3TVeKcPhAHeHK0sL6nbwEh8ogaO1L0bk t0kj3HP4qjdKpVXP1t/M7VM4E98Ex3ykBGafg4GsYPHqWmt3pZxwqc5sM6Sao488H8GU=; Received: from mail-wr1-f51.google.com ([209.85.221.51]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.92.3) id 1nD0mz-0006jw-UE for openvpn-devel@lists.sourceforge.net; Thu, 27 Jan 2022 09:09:59 +0000 Received: by mail-wr1-f51.google.com with SMTP id f17so3506741wrx.1 for ; Thu, 27 Jan 2022 01:09:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=12RRYBZ1pS8iNLqSz0uv/tFczyTt32sWS9ogPkqxQC4=; b=lGG7ja+bI1JF/ztGbR11du3XCLhI3PN0ykTkkMXw9LAFfcqnMldR9FPICPuUEd7xK9 qeOZkTc0GKKcMzqqRLtAr9glw13KUCLGga/ny00FOsLyDnkTRyTpT3qkCoCCFSShDe0p 2f5iAbdMRxScqeI1K/Yx77zZPkeJ+jXcB02aDKWcZ2VOl8SxblHAGjH1nDhGEvdvbJuF KCA/HdfEek9X5yFkZeinhtMk4o6c+vQbmqQ6OvUWSJ81Nah9Vf1UC8oHK9KL5ipp7076 Fy/6/1SEMMLpNMZN5X/n7VeJJ8FpxvwIn5NxxN+ziIf5Ja9TLUxSK1VOMsdVjbP5GE/K yDvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=12RRYBZ1pS8iNLqSz0uv/tFczyTt32sWS9ogPkqxQC4=; b=vxO/2hGVUQGj2m0UCbo/mjbCQtXCkAFBc6TXWEsxpi7XLXgeIoiBhj0Alclf0jvuks TFPoL8tknIfusYZTKQIf7iYNUK8ze/Vw6RLcwNfU8ldjl7aQa3mxvP2+HDsP2gHKtCiN PMKZKFfwAsbxDR4rBYqDhT2o1tKuhhI2rO6bnVaCEfZT1DXCpQqteswklLr3eOJHHBfb QDElGRTKbe3NW/hA4DNd1LfN0BTWnVgoqUIh5Wf8JnfJ13/06fafDrGOtD75SKY6tHD2 KyHi9wzgW/saBXe/2bg7r/CU+/I9FlSpcM0BwjgdUCSuw9Ef7N21xAs9nXXZIOaeM55p 0HIA== X-Gm-Message-State: AOAM531ikgw1HFWh35L3HMMm/nrvhnXUszMg2GiiOlxsiFP0tFLnSJpE X74Wf/Vb5KXWxiBzs5ZcsSHQtePk4WE= X-Google-Smtp-Source: ABdhPJy1D4Ft0y940mkyARQ5hK99/hZKhROEp/Rz0B8ErqkxQDwHbhku6+QWikvDUmMYf1UC1a4j7g== X-Received: by 2002:a5d:590b:: with SMTP id v11mr2224530wrd.74.1643274590882; Thu, 27 Jan 2022 01:09:50 -0800 (PST) Received: from LAPTOP-4L3N7KFS.localdomain (nat2.panoulu.net. [185.38.2.2]) by smtp.gmail.com with ESMTPSA id s9sm1585018wrr.84.2022.01.27.01.09.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Jan 2022 01:09:50 -0800 (PST) From: Lev Stipakov To: openvpn-devel@lists.sourceforge.net Date: Thu, 27 Jan 2022 11:09:17 +0200 Message-Id: <20220127090917.633-1-lstipakov@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210520093700.133-1-lstipakov@gmail.com> References: <20210520093700.133-1-lstipakov@gmail.com> X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Lev Stipakov Add two custom actions to service ovpn-dco driver installation. - EvaluateDriver Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.221.51 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [lstipakov[at]gmail.com] -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.221.51 listed in wl.mailspike.net] -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-Headers-End: 1nD0mz-0006jw-UE Subject: [Openvpn-devel] [PATCH v2] openvpnmsica: add ovpn-dco custom actions 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: , Cc: Lev Stipakov MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Lev Stipakov Add two custom actions to service ovpn-dco driver installation. - EvaluateDriver Runs under user privileges. Determines what action (install/uninstall) should be performed on ovpn-dco component. - ProcessDriver Runs under SYSTEM privileges. Performs driver (un)installation. During uninstall, all existing adapters with given hwid (ovpn-dco) are removed. The logic is inspired by custom actions from tap-windows6 installer (https://github.com/OpenVPN/tap-windows6/tree/master/msm). Signed-off-by: Lev Stipakov --- v2: fix string conversion warning src/openvpnmsica/Makefile.am | 2 +- src/openvpnmsica/openvpnmsica.c | 348 ++++++++++++++++++++++++++++++++ src/openvpnmsica/openvpnmsica.h | 30 +++ 3 files changed, 379 insertions(+), 1 deletion(-) diff --git a/src/openvpnmsica/Makefile.am b/src/openvpnmsica/Makefile.am index a1a04afe..95482940 100644 --- a/src/openvpnmsica/Makefile.am +++ b/src/openvpnmsica/Makefile.am @@ -42,7 +42,7 @@ libopenvpnmsica_la_CFLAGS = \ -UNTDDI_VERSION -U_WIN32_WINNT \ -D_WIN32_WINNT=_WIN32_WINNT_VISTA \ -Wl,--kill-at -libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -liphlpapi -lshell32 -lshlwapi -lversion -no-undefined -avoid-version +libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -liphlpapi -lshell32 -lshlwapi -lversion -lnewdev -no-undefined -avoid-version endif libopenvpnmsica_la_SOURCES = \ diff --git a/src/openvpnmsica/openvpnmsica.c b/src/openvpnmsica/openvpnmsica.c index 6560751a..40f8459b 100644 --- a/src/openvpnmsica/openvpnmsica.c +++ b/src/openvpnmsica/openvpnmsica.c @@ -43,6 +43,10 @@ #include #include #include +#include +#include +#include +#include #ifdef _MSC_VER #pragma comment(lib, "advapi32.lib") @@ -60,6 +64,12 @@ #define MSICA_ADAPTER_TICK_SIZE (16*1024) /** Amount of tick space to reserve for one TAP/TUN adapter creation/deletition. */ #define FILE_NEED_REBOOT L".ovpn_need_reboot" +#define CMP_OVPN_DCO_INF_GUID L"{4BE20469-2292-4AE2-B953-49AA0DA4165E}" +#define ACTION_ADD_DRIVER L"AddDriver" +#define ACTION_DELETE_DRIVER L"DeleteDriver" +#define ACTION_NOOP L"Noop" +#define FILE_OVPN_DCO_INF L"ovpn-dco.inf" +#define OVPN_DCO_HWID L"ovpn-dco" /** * Joins an argument sequence and sets it to the MSI property. @@ -424,6 +434,11 @@ FindSystemInfo(_In_ MSIHANDLE hInstall) TEXT("Wintun") TEXT("\0"), TEXT("WINTUNADAPTERS"), TEXT("ACTIVEWINTUNADAPTERS")); + find_adapters( + hInstall, + TEXT("ovpn-dco") TEXT("\0"), + TEXT("OVPNDCOAPTERS"), + TEXT("ACTIVEOVPNDCOADAPTERS")); if (bIsCoInitialized) { @@ -1297,3 +1312,336 @@ CheckAndScheduleReboot(_In_ MSIHANDLE hInstall) } return ret; } + +static BOOL +IsInstalling(_In_ INSTALLSTATE InstallState, _In_ INSTALLSTATE ActionState) +{ + return INSTALLSTATE_LOCAL == ActionState || INSTALLSTATE_SOURCE == ActionState || + (INSTALLSTATE_DEFAULT == ActionState && + (INSTALLSTATE_LOCAL == InstallState || INSTALLSTATE_SOURCE == InstallState)); +} + +static BOOL +IsReInstalling(_In_ INSTALLSTATE InstallState, _In_ INSTALLSTATE ActionState) +{ + return (INSTALLSTATE_LOCAL == ActionState || INSTALLSTATE_SOURCE == ActionState || + INSTALLSTATE_DEFAULT == ActionState) && + (INSTALLSTATE_LOCAL == InstallState || INSTALLSTATE_SOURCE == InstallState); +} + +static BOOL +IsUninstalling(_In_ INSTALLSTATE InstallState, _In_ INSTALLSTATE ActionState) +{ + return (INSTALLSTATE_ABSENT == ActionState || INSTALLSTATE_REMOVED == ActionState) && + (INSTALLSTATE_LOCAL == InstallState || INSTALLSTATE_SOURCE == InstallState); +} + +static UINT +GetComponentNameById(_In_ MSIHANDLE hInstall, _In_ LPCTSTR componentId, _Out_ LPTSTR name, DWORD len) +{ + UINT ret = 0; + MSIHANDLE record = 0; + MSIHANDLE view = 0; + + name[len - 1] = '\0'; + + /* Open MSI database. */ + MSIHANDLE db = MsiGetActiveDatabase(hInstall); + if (db == 0) + { + msg(M_NONFATAL, "%s: MsiGetActiveDatabase failed", __FUNCTION__); + ret = ERROR_INVALID_HANDLE; + goto cleanup; + } + + TCHAR cmd[0x400]; + _stprintf_s(cmd, _countof(cmd), L"SELECT `Component` FROM `Component` WHERE `ComponentId` = '%s'", componentId); + + ret = MsiDatabaseOpenView(db, cmd, &view); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + ret = MsiViewExecute(view, 0); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + ret = MsiViewFetch(view, &record); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + ret = MsiRecordGetString(record, 1, name, &len); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + +cleanup: + MsiCloseHandle(view); + MsiCloseHandle(record); + MsiCloseHandle(db); + + return ret; +} + +UINT __stdcall +EvaluateDriver(_In_ MSIHANDLE hInstall) +{ +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + + debug_popup(__FUNCTION__); + + UINT ret; + BOOL bIsCoInitialized = SUCCEEDED(CoInitialize(NULL)); + + OPENVPNMSICA_SAVE_MSI_SESSION(hInstall); + + WCHAR componentName[0x400]; + ret = GetComponentNameById(hInstall, CMP_OVPN_DCO_INF_GUID, componentName, _countof(componentName)); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + INSTALLSTATE InstallState, ActionState; + ret = MsiGetComponentState(hInstall, componentName, &InstallState, &ActionState); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + /* get user-specific temp path, to where we create reboot indication file */ + WCHAR tempPath[MAX_PATH]; + GetTempPath(MAX_PATH, tempPath); + + WCHAR pathToInf[MAX_PATH]; + DWORD pathLen = _countof(pathToInf); + ret = MsiGetProperty(hInstall, L"OVPNDCO", pathToInf, &pathLen); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + TCHAR action[0x400]; + if ((IsReInstalling(InstallState, ActionState) || IsInstalling(InstallState, ActionState))) + { + _stprintf_s(action, _countof(action), L"%s|%s%s|%s", ACTION_ADD_DRIVER, pathToInf, FILE_OVPN_DCO_INF, tempPath); + } + else if (IsUninstalling(InstallState, ActionState)) + { + _stprintf_s(action, _countof(action), L"%s|%s%s|%s", ACTION_DELETE_DRIVER, pathToInf, FILE_OVPN_DCO_INF, tempPath); + } + else + { + _stprintf_s(action, _countof(action), L"%s||", ACTION_NOOP); + } + + ret = MsiSetProperty(hInstall, L"OvpnDcoProcess", action); + +cleanup: + if (bIsCoInitialized) + { + CoUninitialize(); + } + return ret; +} + +static BOOL +GetPublishedDriverName(_In_z_ LPCWSTR hwid, _Out_writes_z_(len) LPWSTR publishedName, _In_ DWORD len) +{ + wcscpy_s(publishedName, len, L""); + + HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, 0); + if (!devInfoSet) + { + return FALSE; + } + BOOL res = FALSE; + if (!SetupDiBuildDriverInfoList(devInfoSet, NULL, SPDIT_CLASSDRIVER)) + { + goto cleanupDeviceInfoSet; + } + for (DWORD idx = 0;; ++idx) + { + SP_DRVINFO_DATA drvInfo = { .cbSize = sizeof(drvInfo) }; + if (!SetupDiEnumDriverInfo(devInfoSet, NULL, SPDIT_CLASSDRIVER, idx, &drvInfo)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + { + break; + } + goto cleanupDriverInfoList; + } + DWORD size; + if (SetupDiGetDriverInfoDetail(devInfoSet, NULL, &drvInfo, NULL, 0, &size) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + goto cleanupDriverInfoList; + } + PSP_DRVINFO_DETAIL_DATA drvDetails = calloc(1, size); + if (!drvDetails) + { + goto cleanupDriverInfoList; + } + drvDetails->cbSize = sizeof(*drvDetails); + if (!SetupDiGetDriverInfoDetail(devInfoSet, NULL, &drvInfo, drvDetails, size, &size)) + { + free(drvDetails); + goto cleanupDriverInfoList; + } + if (_tcscmp(hwid, drvDetails->HardwareID) == 0) + { + PathStripPath(drvDetails->InfFileName); + _tcscpy_s(publishedName, len, drvDetails->InfFileName); + res = TRUE; + break; + } + free(drvDetails); + } + +cleanupDriverInfoList: + SetupDiDestroyDriverInfoList(devInfoSet, NULL, SPDIT_CLASSDRIVER); +cleanupDeviceInfoSet: + SetupDiDestroyDeviceInfoList(devInfoSet); + return res; +} + +static void +DeleteDriver(_In_z_ LPCWSTR pathToTmp) +{ + /* get list of adapters for hwid */ + struct tap_adapter_node* pAdapterList = NULL; + DWORD ret = tap_list_adapters(NULL, OVPN_DCO_HWID, &pAdapterList); + if (ret != ERROR_SUCCESS) + { + msg(M_NONFATAL, "%s", "Failed to get adapter list: %d", __FUNCTION__, ret); + } + + /* delete all adapters */ + BOOL rebootRequired = FALSE; + for (struct tap_adapter_node* pAdapter = pAdapterList; pAdapter != NULL; pAdapter = pAdapter->pNext) + { + BOOL rebootForOneAdapter = FALSE; + tap_delete_adapter(NULL, &pAdapter->guid, &rebootForOneAdapter); + rebootRequired |= rebootForOneAdapter; + } + + /* delete driver */ + WCHAR publishedName[MAX_PATH] = { 0 }; + if (GetPublishedDriverName(OVPN_DCO_HWID, publishedName, _countof(publishedName))) + { + if (!SetupUninstallOEMInf(publishedName, 0, NULL)) + { + msg(M_NONFATAL | M_ERRNO, "%s: SetupUninstallOEMInf(\"%" PRIsLPTSTR "\") failed", __FUNCTION__, publishedName); + } + } + else + { + msg(M_NONFATAL | M_ERRNO, "%s: GetPublishedDriverName(\"%" PRIsLPTSTR "\") failed", __FUNCTION__, OVPN_DCO_HWID); + } + + if (rebootRequired) + { + CreateRebootFile(pathToTmp); + } + + ret = ERROR_SUCCESS; +} + +static UINT +AddDriver(_In_z_ LPCWSTR pathToInf, _In_z_ LPCWSTR pathToTmp) +{ + /* copy driver to driver store */ + if (!SetupCopyOEMInf(pathToInf, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL)) + { + msg(M_NONFATAL | M_ERRNO, "%s: SetupCopyOEMInf(\"%" PRIsLPTSTR "\") failed", __FUNCTION__, pathToInf); + return GetLastError(); + } + + /* update driver for existing devices (if any) */ + BOOL rebootRequired = FALSE; + if (!UpdateDriverForPlugAndPlayDevices(NULL, OVPN_DCO_HWID, pathToInf, INSTALLFLAG_NONINTERACTIVE | INSTALLFLAG_FORCE, &rebootRequired)) + { + /* ERROR_NO_SUCH_DEVINST means that no devices exist, which is normal case - device (adapter) is created at later stage */ + if (GetLastError() != ERROR_NO_SUCH_DEVINST) + { + msg(M_NONFATAL | M_ERRNO, "%s: UpdateDriverForPlugAndPlayDevices(\"%" PRIsLPTSTR "\", \"%" PRIsLPTSTR "\") failed", __FUNCTION__, OVPN_DCO_HWID, pathToInf); + return GetLastError(); + } + } + if (rebootRequired) + { + CreateRebootFile(pathToTmp); + } + + return ERROR_SUCCESS; +} + +UINT __stdcall +ProcessDriver(_In_ MSIHANDLE hInstall) +{ +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + + debug_popup(__FUNCTION__); + + UINT ret = 0; + BOOL bIsCoInitialized = SUCCEEDED(CoInitialize(NULL)); + + OPENVPNMSICA_SAVE_MSI_SESSION(hInstall); + + LPTSTR customData = NULL; + ret = msi_get_string(hInstall, L"CustomActionData", &customData); + if (ret != ERROR_SUCCESS) + { + goto cleanup; + } + + int i = 0; + WCHAR action[0x400] = { 0 }; + WCHAR pathToInf[MAX_PATH] = { 0 }; + WCHAR pathToTmp[MAX_PATH] = { 0 }; + + WCHAR* pos = NULL; + WCHAR* token = wcstok_s(customData, L"|", &pos); + /* action|path_to_inf_file|path_to_tmp_dir */ + while (token) + { + switch (i++) + { + case 0: + wcscpy_s(action, _countof(action), token); + break; + case 1: + wcscpy_s(pathToInf, _countof(pathToInf), token); + break; + case 2: + wcscpy_s(pathToTmp, _countof(pathToTmp), token); + break; + } + token = wcstok_s(NULL, L"|", &pos); + } + + if (wcscmp(action, ACTION_ADD_DRIVER) == 0) + { + AddDriver(pathToInf, pathToTmp); + } + else if (wcscmp(action, ACTION_DELETE_DRIVER) == 0) + { + DeleteDriver(pathToTmp); + } + +cleanup: + if (bIsCoInitialized) + { + CoUninitialize(); + } + return ret; +} \ No newline at end of file diff --git a/src/openvpnmsica/openvpnmsica.h b/src/openvpnmsica/openvpnmsica.h index 8c53de45..a2d2d3f4 100644 --- a/src/openvpnmsica/openvpnmsica.h +++ b/src/openvpnmsica/openvpnmsica.h @@ -88,6 +88,10 @@ extern "C" { * with semicolon delimited list of all installed adapter GUIDs and active adapter GUIDs * respectively. * + * - Finds existing ovpn-dco adapters and set OVPNDCOADAPTERS and ACTIVEOVPNDCOADAPTERS properties + * with semicolon delimited list of all installed adapter GUIDs and active adapter GUIDs + * respectively. + * * @param hInstall Handle to the installation provided to the DLL custom action * * @return ERROR_SUCCESS on success; An error code otherwise @@ -147,6 +151,32 @@ DLLEXP_DECL UINT __stdcall ProcessDeferredAction(_In_ MSIHANDLE hInstall); +/** + * Check what operation shall be performed on ovpn-dco driver + * and set data value (path to inf and user temp dir) for ProcessDriver action. + * + * @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 +EvaluateDriver(_In_ MSIHANDLE hInstall); + + +/** + * Install or uninstall ovpn-dco driver, removing all adapters using that driver. + * If reboot is required, creates reboot indication file in user's temp directory + * + * @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 +ProcessDriver(_In_ MSIHANDLE hInstall); + + /** * Schedule reboot after installation if reboot * indication file is found in user's temp directory