From 6b44dce713178695c21a30cd99dff5a0e758d885 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 09:12:53 +0100 Subject: [PATCH 01/19] Add *.vcxproj.user and SDV output files to .gitignore Signed-off-by: Simon Rozman --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 79a041a..8bb20fa 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,8 @@ src/Release src/Debug src/x64 src/arm64 +src/smvbuild.log +src/smvstats.txt +src/tap0901.DVL.XML .vs +*.vcxproj.user From 2387067b385cb759ef53020c5dd8503af641ff59 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 09:25:34 +0100 Subject: [PATCH 02/19] MSM: Introduce installer.dll project Signed-off-by: Simon Rozman --- msm/dllmain.cpp | 19 ++++ msm/framework.h | 5 + msm/installer.sln | 31 +++++++ msm/installer.vcxproj | 169 ++++++++++++++++++++++++++++++++++ msm/installer.vcxproj.filters | 33 +++++++ msm/pch.cpp | 5 + msm/pch.h | 13 +++ 7 files changed, 275 insertions(+) create mode 100644 msm/dllmain.cpp create mode 100644 msm/framework.h create mode 100644 msm/installer.sln create mode 100644 msm/installer.vcxproj create mode 100644 msm/installer.vcxproj.filters create mode 100644 msm/pch.cpp create mode 100644 msm/pch.h diff --git a/msm/dllmain.cpp b/msm/dllmain.cpp new file mode 100644 index 0000000..f266597 --- /dev/null +++ b/msm/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/msm/framework.h b/msm/framework.h new file mode 100644 index 0000000..54b83e9 --- /dev/null +++ b/msm/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include diff --git a/msm/installer.sln b/msm/installer.sln new file mode 100644 index 0000000..a1af6f8 --- /dev/null +++ b/msm/installer.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29806.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer.vcxproj", "{EC4CC979-0D50-4A42-8068-451F0B1F6DC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x64.ActiveCfg = Debug|x64 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x64.Build.0 = Debug|x64 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x86.ActiveCfg = Debug|Win32 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x86.Build.0 = Debug|Win32 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x64.ActiveCfg = Release|x64 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x64.Build.0 = Release|x64 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x86.ActiveCfg = Release|Win32 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {48A3A05A-974D-46A4-8CFD-94089BC4D8CF} + EndGlobalSection +EndGlobal diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj new file mode 100644 index 0000000..b1f67d9 --- /dev/null +++ b/msm/installer.vcxproj @@ -0,0 +1,169 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0} + Win32Proj + installer + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + true + WIN32;_DEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + false + + + + + Use + Level3 + true + _DEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + false + + + + + Use + Level3 + true + true + true + WIN32;NDEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + true + false + + + + + Use + Level3 + true + true + true + NDEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + true + false + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/msm/installer.vcxproj.filters b/msm/installer.vcxproj.filters new file mode 100644 index 0000000..bd9682f --- /dev/null +++ b/msm/installer.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/msm/pch.cpp b/msm/pch.cpp new file mode 100644 index 0000000..64b7eef --- /dev/null +++ b/msm/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/msm/pch.h b/msm/pch.h new file mode 100644 index 0000000..885d5d6 --- /dev/null +++ b/msm/pch.h @@ -0,0 +1,13 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here +#include "framework.h" + +#endif //PCH_H From 208d50b85758aa485551c377e18d5ab064f0e488 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 11:21:47 +0100 Subject: [PATCH 03/19] MSM: Switch to static RTL MSI custom actions must not depend on MSVC RTL presence. Signed-off-by: Simon Rozman --- msm/installer.vcxproj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index b1f67d9..d623ebc 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -82,6 +82,16 @@ false + + + MultiThreadedDebug + + + + + MultiThreaded + + Use From f3c8053e4f634ea845b1bd3dd64bf59109841e61 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 11:49:30 +0100 Subject: [PATCH 04/19] MSM: Refactor .vcxproj Most of the project settings apply to all configurations and platforms. Signed-off-by: Simon Rozman --- msm/installer.vcxproj | 80 ++++++++----------------------------------- 1 file changed, 15 insertions(+), 65 deletions(-) diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index d623ebc..3958027 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -70,49 +70,18 @@ - + true - - true - - - false - - + false - - - MultiThreadedDebug - - - - - MultiThreaded - - - - - Use - Level3 - true - WIN32;_DEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h - - - Windows - true - false - - - + Use Level3 true - _DEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h @@ -122,44 +91,28 @@ false - + - Use - Level3 - true - true - true - WIN32;NDEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h + _DEBUG;%(PreprocessorDefinitions) + MultiThreadedDebug - - Windows - true - true - true - false - - + - Use - Level3 + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded true true - true - NDEBUG;INSTALLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h - Windows true true - true - false + + + + @@ -167,10 +120,7 @@ - Create - Create - Create - Create + Create From 9e7700adb02500d86073fe19aa8ac35bac146c2c Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 11:51:48 +0100 Subject: [PATCH 05/19] MSM: Enable ARM64 building Signed-off-by: Simon Rozman --- msm/installer.sln | 6 ++++++ msm/installer.vcxproj | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/msm/installer.sln b/msm/installer.sln index a1af6f8..1cef0b7 100644 --- a/msm/installer.sln +++ b/msm/installer.sln @@ -7,16 +7,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer.vcxp EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|ARM64.Build.0 = Debug|ARM64 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x64.ActiveCfg = Debug|x64 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x64.Build.0 = Debug|x64 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x86.ActiveCfg = Debug|Win32 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Debug|x86.Build.0 = Debug|Win32 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|ARM64.ActiveCfg = Release|ARM64 + {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|ARM64.Build.0 = Release|ARM64 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x64.ActiveCfg = Release|x64 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x64.Build.0 = Release|x64 {EC4CC979-0D50-4A42-8068-451F0B1F6DC0}.Release|x86.ActiveCfg = Release|Win32 diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index 3958027..dfabd6c 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -1,10 +1,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -45,6 +53,12 @@ v142 Unicode + + DynamicLibrary + true + v142 + Unicode + DynamicLibrary false @@ -52,6 +66,13 @@ true Unicode + + DynamicLibrary + false + v142 + true + Unicode + @@ -66,9 +87,15 @@ + + + + + + true @@ -111,8 +138,10 @@ + + From 9bdc76da8a9f6f3245e678c723e1c38eaaa0d2ad Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 11:54:18 +0100 Subject: [PATCH 06/19] MSM: .gitignore MSVC output folders Signed-off-by: Simon Rozman --- msm/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 msm/.gitignore diff --git a/msm/.gitignore b/msm/.gitignore new file mode 100644 index 0000000..b1f96b7 --- /dev/null +++ b/msm/.gitignore @@ -0,0 +1,4 @@ +/ARM64 +/Debug +/Release +/x64 From 19132ceff2d199a5b48ca4e28270ad6041941522 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 11:58:01 +0100 Subject: [PATCH 07/19] MSM: Switch from C++ to C Signed-off-by: Simon Rozman --- msm/{dllmain.cpp => dllmain.c} | 7 ++----- msm/installer.vcxproj | 3 +-- msm/installer.vcxproj.filters | 4 ++-- msm/{pch.cpp => pch.c} | 0 4 files changed, 5 insertions(+), 9 deletions(-) rename msm/{dllmain.cpp => dllmain.c} (64%) rename msm/{pch.cpp => pch.c} (100%) diff --git a/msm/dllmain.cpp b/msm/dllmain.c similarity index 64% rename from msm/dllmain.cpp rename to msm/dllmain.c index f266597..e684a52 100644 --- a/msm/dllmain.cpp +++ b/msm/dllmain.c @@ -1,10 +1,8 @@ // dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) +BOOL APIENTRY +DllMain(_In_ HMODULE hModule, _In_ DWORD ul_reason_for_call, _In_opt_ LPVOID lpReserved) { switch (ul_reason_for_call) { @@ -16,4 +14,3 @@ BOOL APIENTRY DllMain( HMODULE hModule, } return TRUE; } - diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index dfabd6c..b90f44f 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -147,8 +147,7 @@ - - + Create diff --git a/msm/installer.vcxproj.filters b/msm/installer.vcxproj.filters index bd9682f..5ddb5eb 100644 --- a/msm/installer.vcxproj.filters +++ b/msm/installer.vcxproj.filters @@ -23,10 +23,10 @@ - + Source Files - + Source Files diff --git a/msm/pch.cpp b/msm/pch.c similarity index 100% rename from msm/pch.cpp rename to msm/pch.c From d6e648bec2fdabefd409fa5a72d2791ebfef9bef Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 12:04:06 +0100 Subject: [PATCH 08/19] MSM: Import Wintun driver installer and adopt it for general use Signed-off-by: Simon Rozman --- COPYING | 9 +- buildtap.py | 2 + msm/.gitignore | 1 + msm/dllmain.c | 7 +- msm/exports.def | 3 + msm/framework.h | 16 + msm/installation.c | 561 ++++++++++++++++++++++++++++++++++ msm/installation.h | 23 ++ msm/installer.vcxproj | 28 ++ msm/installer.vcxproj.filters | 22 ++ msm/msi.c | 262 ++++++++++++++++ msm/pch.h | 3 + msm/resource.rc.in | 12 + 13 files changed, 944 insertions(+), 5 deletions(-) create mode 100644 msm/exports.def create mode 100644 msm/installation.c create mode 100644 msm/installation.h create mode 100644 msm/msi.c create mode 100644 msm/resource.rc.in diff --git a/COPYING b/COPYING index a2dbdb8..742e272 100644 --- a/COPYING +++ b/COPYING @@ -4,10 +4,11 @@ tap-windows6 license The source and object code of the tap-windows6 project is Copyright (C) 2002-2014 OpenVPN Technologies, Inc. The NSIS installer is Copyright (C) 2014 OpenVPN Technologies, -Inc. and (C) 2012 Alon Bar-Lev. Both are released under the -GPL version 2. See COPYRIGHT.GPL for the full GPL license. -The licensors also make the following statement borrowed -from the SPICE project: +Inc. and (C) 2012 Alon Bar-Lev. The installer.dll MSI helper +is Copyright (C) 2018-2019 WireGuard LLC. All are released +under the GPL version 2. See COPYRIGHT.GPL for the full GPL +license. The licensors also make the following statement +borrowed from the SPICE project: With respect to binaries built using the Microsoft(R) Windows Driver Kit (WDK), GPLv2 does not extend to any code diff --git a/buildtap.py b/buildtap.py index 78f9587..1807e3e 100644 --- a/buildtap.py +++ b/buildtap.py @@ -14,6 +14,7 @@ def __init__(self, opt): raise ValueError("source directory undefined") self.top = os.path.realpath(opt.src) # top-level dir self.src = os.path.join(self.top, 'src') # src/openvpn dir + self.msm = os.path.join(self.top, 'msm') # msm dir if opt.tapinstall: self.top_tapinstall = os.path.realpath(opt.tapinstall) # tapinstall dir devcon_project_file = os.path.join(self.top_tapinstall, "devcon.sln") @@ -197,6 +198,7 @@ def config_tap(self): self.preprocess(kv, os.path.join(self.src, "OemVista.inf")) self.preprocess(kv, os.path.join(self.src, "tap-windows6.vcxproj")) self.preprocess(kv, os.path.join(self.src, "config.h")) + self.preprocess(kv, os.path.join(self.msm, "resource.rc")) # build a "msbuild" file using (E)WDK def build_ewdk(self, project_file, arch): diff --git a/msm/.gitignore b/msm/.gitignore index b1f96b7..ca802a1 100644 --- a/msm/.gitignore +++ b/msm/.gitignore @@ -2,3 +2,4 @@ /Debug /Release /x64 +/resource.rc diff --git a/msm/dllmain.c b/msm/dllmain.c index e684a52..13d5556 100644 --- a/msm/dllmain.c +++ b/msm/dllmain.c @@ -1,4 +1,8 @@ -// dllmain.cpp : Defines the entry point for the DLL application. +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + #include "pch.h" BOOL APIENTRY @@ -7,6 +11,7 @@ DllMain(_In_ HMODULE hModule, _In_ DWORD ul_reason_for_call, _In_opt_ LPVOID lpR switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: + ResourceModule = hModule; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: diff --git a/msm/exports.def b/msm/exports.def new file mode 100644 index 0000000..1d1d617 --- /dev/null +++ b/msm/exports.def @@ -0,0 +1,3 @@ +EXPORTS + MsiEvaluate + MsiProcess diff --git a/msm/framework.h b/msm/framework.h index 54b83e9..b423cda 100644 --- a/msm/framework.h +++ b/msm/framework.h @@ -3,3 +3,19 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include diff --git a/msm/installation.c b/msm/installation.c new file mode 100644 index 0000000..00d7b4e --- /dev/null +++ b/msm/installation.c @@ -0,0 +1,561 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + +#include "pch.h" + +#pragma warning(disable : 4100) /* unreferenced formal parameter */ +#pragma warning(disable : 4204) /* nonstandard: non-constant aggregate initializer */ +#pragma warning(disable : 4221) /* nonstandard: address of automatic in initializer */ + +#define DRIVER_SYS TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(".sys") + +typedef struct _SP_DEVINFO_DATA_LIST +{ + SP_DEVINFO_DATA Data; + struct _SP_DEVINFO_DATA_LIST *Next; +} SP_DEVINFO_DATA_LIST; + +static VOID +NopLogger(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *LogLine) +{ +} + +static LoggerFunction Logger = NopLogger; + +VOID +SetLogger(_In_ LoggerFunction NewLogger) +{ + Logger = NewLogger; +} + +static VOID +PrintError(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *Prefix) +{ + DWORD ErrorCode = GetLastError(); + TCHAR *SystemMessage = NULL, *FormattedMessage = NULL; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, + HRESULT_FROM_SETUPAPI(ErrorCode), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (VOID *)&SystemMessage, + 0, + NULL); + FormatMessage( + FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + SystemMessage ? TEXT("%1: %3(Code 0x%2!08X!)") : TEXT("%1: Code 0x%2!08X!"), + 0, + 0, + (VOID *)&FormattedMessage, + 0, + (va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)ErrorCode, (DWORD_PTR)SystemMessage }); + if (FormattedMessage) + Logger(Level, FormattedMessage); + LocalFree(FormattedMessage); + LocalFree(SystemMessage); +} + +HINSTANCE ResourceModule; + +static BOOL IsDriverLoaded(VOID) +{ + DWORD RequiredSize = 0, CurrentSize = 0; + VOID **Drivers = NULL; + BOOL Found = FALSE; + for (;;) + { + if (!EnumDeviceDrivers(Drivers, CurrentSize, &RequiredSize)) + goto out; + if (CurrentSize == RequiredSize) + break; + free(Drivers); + Drivers = malloc(RequiredSize); + if (!Drivers) + goto out; + CurrentSize = RequiredSize; + } + TCHAR BaseName[_countof(DRIVER_SYS)]; + for (DWORD i = CurrentSize / sizeof(Drivers[0]); i-- > 0;) + { + if (GetDeviceDriverBaseName(Drivers[i], BaseName, _countof(BaseName)) == _countof(DRIVER_SYS) - 1 && + !_tcsicmp(BaseName, DRIVER_SYS)) + { + Found = TRUE; + goto out; + } + } +out: + free(Drivers); + return Found; +} + +static BOOL EnsureDriverUnloaded(VOID) +{ + BOOL Loaded; + for (int i = 0; (Loaded = IsDriverLoaded()) != 0 && i < 300; ++i) + Sleep(50); + return !Loaded; +} + +static BOOL +CopyResource( + _In_ const TCHAR *DestinationPath, + _In_opt_ SECURITY_ATTRIBUTES *SecurityAttributes, + _In_ const TCHAR *ResourceName) +{ + HRSRC FoundResource = FindResource(ResourceModule, ResourceName, RT_RCDATA); + if (!FoundResource) + return FALSE; + DWORD SizeResource = SizeofResource(ResourceModule, FoundResource); + if (!SizeResource) + return FALSE; + HGLOBAL LoadedResource = LoadResource(ResourceModule, FoundResource); + if (!LoadedResource) + return FALSE; + LPVOID LockedResource = LockResource(LoadedResource); + if (!LockedResource) + return FALSE; + HANDLE DestinationHandle = CreateFile( + DestinationPath, + GENERIC_WRITE, + 0, + SecurityAttributes, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, + NULL); + if (DestinationHandle == INVALID_HANDLE_VALUE) + return FALSE; + DWORD BytesWritten; + BOOL Ret = + WriteFile(DestinationHandle, LockedResource, SizeResource, &BytesWritten, NULL) && BytesWritten == SizeResource; + CloseHandle(DestinationHandle); + return Ret; +} + +static BOOL +InstallDriverCertificate(const TCHAR *SignedResource) +{ + DWORD LastError = ERROR_SUCCESS; + Logger(LOG_INFO, TEXT("Trusting code signing certificate")); + BOOL Ret = TRUE; + HRSRC FoundResource = FindResource(ResourceModule, SignedResource, RT_RCDATA); + if (!FoundResource) + return FALSE; + DWORD SizeResource = SizeofResource(ResourceModule, FoundResource); + if (!SizeResource) + return FALSE; + HGLOBAL LoadedResource = LoadResource(ResourceModule, FoundResource); + if (!LoadedResource) + return FALSE; + LPVOID LockedResource = LockResource(LoadedResource); + if (!LockedResource) + return FALSE; + const CERT_BLOB CertBlob = { .cbData = SizeResource, .pbData = LockedResource }; + HCERTSTORE QueriedStore; + if (!CryptQueryObject( + CERT_QUERY_OBJECT_BLOB, + &CertBlob, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_FORMAT_FLAG_ALL, + 0, + 0, + 0, + 0, + &QueriedStore, + 0, + NULL)) + return FALSE; + HCERTSTORE TrustedStore = + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, TEXT("TrustedPublisher")); + if (!TrustedStore) + { + LastError = GetLastError(); + goto cleanupQueriedStore; + } + LPSTR CodeSigningOid[] = { szOID_PKIX_KP_CODE_SIGNING }; + CERT_ENHKEY_USAGE EnhancedUsage = { .cUsageIdentifier = 1, .rgpszUsageIdentifier = CodeSigningOid }; + for (const CERT_CONTEXT *CertContext = NULL; (CertContext = CertFindCertificateInStore( + QueriedStore, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, + CERT_FIND_ENHKEY_USAGE, + &EnhancedUsage, + CertContext)) != NULL;) + { + CERT_EXTENSION *Ext = CertFindExtension( + szOID_BASIC_CONSTRAINTS2, CertContext->pCertInfo->cExtension, CertContext->pCertInfo->rgExtension); + CERT_BASIC_CONSTRAINTS2_INFO Constraints; + DWORD Size = sizeof(Constraints); + if (Ext && + CryptDecodeObjectEx( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + szOID_BASIC_CONSTRAINTS2, + Ext->Value.pbData, + Ext->Value.cbData, + 0, + NULL, + &Constraints, + &Size) && + !Constraints.fCA) + Ret &= CertAddCertificateContextToStore(TrustedStore, CertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL); + if (!Ret) + LastError = LastError ? LastError : GetLastError(); + } + CertCloseStore(TrustedStore, 0); +cleanupQueriedStore: + CertCloseStore(QueriedStore, 0); + SetLastError(LastError); + return Ret; +} + +/* We can't use RtlGetVersion, because appcompat's aclayers.dll shims it to report Vista + * when run from MSI context. So, we instead use the undocumented RtlGetNtVersionNumbers. + * + * Another way would be reading from the PEB directly: + * ((DWORD *)NtCurrentTeb()->ProcessEnvironmentBlock)[sizeof(void *) == 8 ? 70 : 41] + * Or just read from KUSER_SHARED_DATA the same way on 32-bit and 64-bit: + * *(DWORD *)0x7FFE026C + */ +extern VOID NTAPI +RtlGetNtVersionNumbers(_Out_opt_ DWORD *MajorVersion, _Out_opt_ DWORD *MinorVersion, _Out_opt_ DWORD *BuildNumber); + +static BOOL +InstallDriver(BOOL UpdateExisting) +{ + DWORD LastError = ERROR_SUCCESS; + TCHAR WindowsDirectory[MAX_PATH]; + if (!GetWindowsDirectory(WindowsDirectory, _countof(WindowsDirectory))) + return FALSE; + TCHAR WindowsTempDirectory[MAX_PATH]; + if (!PathCombine(WindowsTempDirectory, WindowsDirectory, TEXT("Temp"))) + return FALSE; + UCHAR RandomBytes[32] = { 0 }; +#pragma warning(suppress : 6387) + if (!RtlGenRandom(RandomBytes, sizeof(RandomBytes))) + return FALSE; + TCHAR RandomSubDirectory[sizeof(RandomBytes) * 2 + 1]; + for (int i = 0; i < sizeof(RandomBytes); ++i) + _stprintf_s(&RandomSubDirectory[i * 2], 3, TEXT("%02x"), RandomBytes[i]); + TCHAR RandomTempSubDirectory[MAX_PATH]; + if (!PathCombine(RandomTempSubDirectory, WindowsTempDirectory, RandomSubDirectory)) + return FALSE; + SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SecurityAttributes) }; + if (!ConvertStringSecurityDescriptorToSecurityDescriptor( + TEXT("O:SYD:P(A;;GA;;;SY)"), SDDL_REVISION_1, &SecurityAttributes.lpSecurityDescriptor, NULL)) + return FALSE; + BOOL Ret = CreateDirectory(RandomTempSubDirectory, &SecurityAttributes); + if (!Ret) + goto cleanupFree; + + TCHAR CatPath[MAX_PATH] = { 0 }; + if (!PathCombine(CatPath, RandomTempSubDirectory, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(".cat"))) + goto cleanupFree; + TCHAR SysPath[MAX_PATH] = { 0 }; + if (!PathCombine(SysPath, RandomTempSubDirectory, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(".sys"))) + goto cleanupFree; + TCHAR InfPath[MAX_PATH] = { 0 }; + if (!PathCombine(InfPath, RandomTempSubDirectory, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(".inf"))) + goto cleanupFree; + + BOOL UseWHQL = FALSE; + DWORD MajorVersion; + RtlGetNtVersionNumbers(&MajorVersion, NULL, NULL); + UseWHQL = MajorVersion >= 10; + if (!UseWHQL && !InstallDriverCertificate(TEXT("driver.sys"))) + PrintError(LOG_WARN, TEXT("Unable to install code signing certificate")); + + Logger(LOG_INFO, TEXT("Copying resources to temporary path")); + Ret = CopyResource(CatPath, &SecurityAttributes, UseWHQL ? TEXT("driver-whql.cat") : TEXT("driver.cat")) && + CopyResource(SysPath, &SecurityAttributes, UseWHQL ? TEXT("driver-whql.sys") : TEXT("driver.sys")) && + CopyResource(InfPath, &SecurityAttributes, UseWHQL ? TEXT("driver-whql.inf") : TEXT("driver.inf")); + if (!Ret) + goto cleanupDelete; + + Logger(LOG_INFO, TEXT("Installing driver")); + Ret = SetupCopyOEMInf(InfPath, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL); + BOOL RebootRequired = FALSE; + if (UpdateExisting && + !UpdateDriverForPlugAndPlayDevices( + NULL, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID), InfPath, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &RebootRequired)) + PrintError(LOG_WARN, TEXT("Could not update existing adapters")); + if (RebootRequired) + Logger(LOG_WARN, TEXT("A reboot might be required")); + +cleanupDelete: + LastError = GetLastError(); + DeleteFile(CatPath); + DeleteFile(SysPath); + DeleteFile(InfPath); + RemoveDirectory(RandomTempSubDirectory); +cleanupFree: + LastError = LastError ? LastError : GetLastError(); + LocalFree(SecurityAttributes.lpSecurityDescriptor); + SetLastError(LastError); + return Ret; +} + +static BOOL RemoveDriver(VOID) +{ + BOOL Ret = FALSE; + HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, 0); + if (!DeviceInfoSet) + return FALSE; + if (!SetupDiBuildDriverInfoList(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER)) + goto cleanupDeviceInfoSet; + Ret = TRUE; + for (DWORD EnumIndex = 0;; ++EnumIndex) + { + SP_DRVINFO_DATA DriverInfo = { .cbSize = sizeof(DriverInfo) }; + if (!SetupDiEnumDriverInfo(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER, EnumIndex, &DriverInfo)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + goto cleanupDriverInfoList; + } + DWORD RequiredSize; + if (SetupDiGetDriverInfoDetail(DeviceInfoSet, NULL, &DriverInfo, NULL, 0, &RequiredSize) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto cleanupDriverInfoList; + PSP_DRVINFO_DETAIL_DATA DriverDetail = calloc(1, RequiredSize); + if (!DriverDetail) + goto cleanupDriverInfoList; + DriverDetail->cbSize = sizeof(*DriverDetail); + if (!SetupDiGetDriverInfoDetail(DeviceInfoSet, NULL, &DriverInfo, DriverDetail, RequiredSize, &RequiredSize)) + { + free(DriverDetail); + goto cleanupDriverInfoList; + } + if (!_tcsicmp(DriverDetail->HardwareID, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID))) + { + PathStripPath(DriverDetail->InfFileName); + Logger(LOG_INFO, TEXT("Removing existing driver")); + if (!SetupUninstallOEMInf(DriverDetail->InfFileName, SUOI_FORCEDELETE, NULL)) + { + PrintError(LOG_ERR, TEXT("Unable to remove existing driver")); + Ret = FALSE; + } + } + free(DriverDetail); + } + +cleanupDriverInfoList: + SetupDiDestroyDriverInfoList(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER); +cleanupDeviceInfoSet: + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + return Ret; +} + +static BOOL +IsOurAdapter(_In_ HDEVINFO DeviceInfoSet, _Inout_ SP_DEVINFO_DATA *DeviceInfo) +{ + BOOL Found = FALSE; + if (!SetupDiBuildDriverInfoList(DeviceInfoSet, DeviceInfo, SPDIT_COMPATDRIVER)) + return FALSE; + for (DWORD EnumIndex = 0;; ++EnumIndex) + { + SP_DRVINFO_DATA DriverInfo = { .cbSize = sizeof(SP_DRVINFO_DATA) }; + if (!SetupDiEnumDriverInfo(DeviceInfoSet, DeviceInfo, SPDIT_COMPATDRIVER, EnumIndex, &DriverInfo)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + continue; + } + DWORD RequiredSize; + if (SetupDiGetDriverInfoDetail(DeviceInfoSet, DeviceInfo, &DriverInfo, NULL, 0, &RequiredSize) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + continue; + PSP_DRVINFO_DETAIL_DATA DriverDetail = calloc(1, RequiredSize); + if (!DriverDetail) + continue; + DriverDetail->cbSize = sizeof(*DriverDetail); + if (SetupDiGetDriverInfoDetail( + DeviceInfoSet, DeviceInfo, &DriverInfo, DriverDetail, RequiredSize, &RequiredSize) && + !_tcsicmp(DriverDetail->HardwareID, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID))) + { + free(DriverDetail); + Found = TRUE; + break; + } + free(DriverDetail); + } + SetupDiDestroyDriverInfoList(DeviceInfoSet, DeviceInfo, SPDIT_COMPATDRIVER); + return Found; +} + +static BOOL +DisableOurAdapters(_In_ HDEVINFO DeviceInfoSet, _Inout_ SP_DEVINFO_DATA_LIST **DisabledAdapters) +{ + SP_PROPCHANGE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER), + .InstallFunction = DIF_PROPERTYCHANGE }, + .StateChange = DICS_DISABLE, + .Scope = DICS_FLAG_GLOBAL }; + BOOL Ret = TRUE; + DWORD LastError = ERROR_SUCCESS; + for (DWORD EnumIndex = 0;; ++EnumIndex) + { + SP_DEVINFO_DATA_LIST *DeviceNode = malloc(sizeof(SP_DEVINFO_DATA_LIST)); + if (!DeviceNode) + return FALSE; + DeviceNode->Data.cbSize = sizeof(SP_DEVINFO_DATA); + if (!SetupDiEnumDeviceInfo(DeviceInfoSet, EnumIndex, &DeviceNode->Data)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + { + free(DeviceNode); + break; + } + goto cleanupDeviceInfoData; + } + if (!IsOurAdapter(DeviceInfoSet, &DeviceNode->Data)) + goto cleanupDeviceInfoData; + + ULONG Status, ProblemCode; + if (CM_Get_DevNode_Status(&Status, &ProblemCode, DeviceNode->Data.DevInst, 0) != CR_SUCCESS || + ((Status & DN_HAS_PROBLEM) && ProblemCode == CM_PROB_DISABLED)) + goto cleanupDeviceInfoData; + + Logger(LOG_INFO, TEXT("Disabling existing adapter")); + if (!SetupDiSetClassInstallParams( + DeviceInfoSet, &DeviceNode->Data, &Params.ClassInstallHeader, sizeof(Params)) || + !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DeviceInfoSet, &DeviceNode->Data)) + { + PrintError(LOG_WARN, TEXT("Unable to disable existing adapter")); + LastError = LastError ? LastError : GetLastError(); + Ret = FALSE; + goto cleanupDeviceInfoData; + } + + DeviceNode->Next = *DisabledAdapters; + *DisabledAdapters = DeviceNode; + continue; + + cleanupDeviceInfoData: + free(&DeviceNode->Data); + } + SetLastError(LastError); + return Ret; +} + +static BOOL +RemoveOurAdapters(_In_ HDEVINFO DeviceInfoSet) +{ + SP_REMOVEDEVICE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER), + .InstallFunction = DIF_REMOVE }, + .Scope = DI_REMOVEDEVICE_GLOBAL }; + BOOL Ret = TRUE; + DWORD LastError = ERROR_SUCCESS; + for (DWORD EnumIndex = 0;; ++EnumIndex) + { + SP_DEVINFO_DATA DeviceInfo = { .cbSize = sizeof(SP_DEVINFO_DATA) }; + if (!SetupDiEnumDeviceInfo(DeviceInfoSet, EnumIndex, &DeviceInfo)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + continue; + } + if (!IsOurAdapter(DeviceInfoSet, &DeviceInfo)) + continue; + + Logger(LOG_INFO, TEXT("Removing existing adapter")); + if (!SetupDiSetClassInstallParams(DeviceInfoSet, &DeviceInfo, &Params.ClassInstallHeader, sizeof(Params)) || + !SetupDiCallClassInstaller(DIF_REMOVE, DeviceInfoSet, &DeviceInfo)) + { + PrintError(LOG_WARN, TEXT("Unable to remove existing adapter")); + LastError = LastError ? LastError : GetLastError(); + Ret = FALSE; + } + } + SetLastError(LastError); + return Ret; +} + +static BOOL +EnableOurAdapters(_In_ HDEVINFO DeviceInfoSet, _In_ SP_DEVINFO_DATA_LIST *AdaptersToEnable) +{ + SP_PROPCHANGE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER), + .InstallFunction = DIF_PROPERTYCHANGE }, + .StateChange = DICS_ENABLE, + .Scope = DICS_FLAG_GLOBAL }; + BOOL Ret = TRUE; + DWORD LastError = ERROR_SUCCESS; + + for (SP_DEVINFO_DATA_LIST *DeviceNode = AdaptersToEnable; DeviceNode; DeviceNode = DeviceNode->Next) + { + Logger(LOG_INFO, TEXT("Enabling existing adapter")); + if (!SetupDiSetClassInstallParams( + DeviceInfoSet, &DeviceNode->Data, &Params.ClassInstallHeader, sizeof(Params)) || + !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DeviceInfoSet, &DeviceNode->Data)) + { + LastError = LastError ? LastError : GetLastError(); + PrintError(LOG_WARN, TEXT("Unable to enable existing adapter")); + Ret = FALSE; + } + } + SetLastError(LastError); + return Ret; +} + +BOOL InstallOrUpdate(VOID) +{ + BOOL Ret = FALSE; + HDEVINFO DeviceInfoSet = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); + if (DeviceInfoSet == INVALID_HANDLE_VALUE) + { + PrintError(LOG_ERR, TEXT("Failed to get present class devices")); + return FALSE; + } + SP_DEVINFO_DATA_LIST *ExistingAdapters = NULL; + if (IsDriverLoaded()) + { + DisableOurAdapters(DeviceInfoSet, &ExistingAdapters); + Logger(LOG_INFO, TEXT("Waiting for driver to unload from kernel")); + if (!EnsureDriverUnloaded()) + Logger(LOG_WARN, TEXT("Unable to unload driver, which means a reboot will likely be required")); + } + if (!RemoveDriver()) + { + PrintError(LOG_ERR, TEXT("Failed to uninstall old drivers")); + goto cleanupAdapters; + } + if (!InstallDriver(!!ExistingAdapters)) + { + PrintError(LOG_ERR, TEXT("Failed to install driver")); + goto cleanupAdapters; + } + Logger(LOG_INFO, TEXT("Installation successful")); + Ret = TRUE; + +cleanupAdapters: + if (ExistingAdapters) + { + EnableOurAdapters(DeviceInfoSet, ExistingAdapters); + while (ExistingAdapters) + { + SP_DEVINFO_DATA_LIST *Next = ExistingAdapters->Next; + free(ExistingAdapters); + ExistingAdapters = Next; + } + } + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + return Ret; +} + +BOOL Uninstall(VOID) +{ + HDEVINFO DeviceInfoSet = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); + if (DeviceInfoSet == INVALID_HANDLE_VALUE) + { + PrintError(LOG_ERR, TEXT("Failed to get present class devices")); + return FALSE; + } + RemoveOurAdapters(DeviceInfoSet); + BOOL Ret = RemoveDriver(); + if (!Ret) + PrintError(LOG_ERR, TEXT("Failed to uninstall driver")); + else + Logger(LOG_INFO, TEXT("Uninstallation successful")); + return Ret; +} diff --git a/msm/installation.h b/msm/installation.h new file mode 100644 index 0000000..e5ce781 --- /dev/null +++ b/msm/installation.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + +#pragma once + +#include + +typedef enum _LOGGER_LEVEL +{ + LOG_INFO = 0, + LOG_WARN, + LOG_ERR +} LOGGER_LEVEL; +typedef VOID (*LoggerFunction)(_In_ LOGGER_LEVEL, _In_ const TCHAR *); +VOID +SetLogger(_In_ LoggerFunction NewLogger); + +BOOL InstallOrUpdate(VOID); +BOOL Uninstall(VOID); + +extern HINSTANCE ResourceModule; diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index b90f44f..f2b8233 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -114,6 +114,8 @@ Windows + Cfgmgr32.lib;Crypt32.lib;Msi.lib;Newdev.lib;ntdll.lib;Setupapi.lib;Shlwapi.lib;%(AdditionalDependencies) + exports.def true false @@ -136,6 +138,21 @@ true + + + ..\dist\i386 + + + + + ..\dist\amd64 + + + + + ..\dist\arm64 + + @@ -144,13 +161,24 @@ + + + + Create + + + + + + + diff --git a/msm/installer.vcxproj.filters b/msm/installer.vcxproj.filters index 5ddb5eb..a8d538b 100644 --- a/msm/installer.vcxproj.filters +++ b/msm/installer.vcxproj.filters @@ -21,13 +21,35 @@ Header Files + + Header Files + + + Source Files + Source Files Source Files + + Source Files + + + + + Resource Files + + + + + Source Files + + + Resource Files + \ No newline at end of file diff --git a/msm/msi.c b/msm/msi.c new file mode 100644 index 0000000..3f99e80 --- /dev/null +++ b/msm/msi.c @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + +#include "pch.h" + +#pragma warning(disable : 4100) /* unreferenced formal parameter */ + +static MSIHANDLE MsiHandle; + +#define ANCHOR_COMPONENT TEXT("{B668D4C7-ABB3-485A-B8DF-D34200489A43}") +#define PROCESS_ACTION TEXT("Process") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) +#define ACTION_INSTALL TEXT("/Action=Install") +#define ACTION_INSTALL_SEPERATOR TEXT('-') +#define ACTION_INSTALL_SEPERATORS TEXT("-%s-%s-%s") +#define ACTION_UNINSTALL TEXT("/Action=Uninstall") +#define PROPERTY_INSTALLER_HASH TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("InstallerHash") +#define PROPERTY_INSTALLER_BUILDTIME TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("InstallerBuildtime") +#define PROPERTY_VERSION TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("Version") +#define REGKEY_DRIVER TEXT("Software\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) +#define REGKEY_INSTALLER_HASH TEXT("InstallerHash") +#define REGKEY_INSTALLER_BUILDTIME TEXT("InstallerBuildtime") +#define REGKEY_VERSION TEXT("Version") + +static VOID +MsiLogger(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *LogLine) +{ + MSIHANDLE Record = MsiCreateRecord(2); + if (!Record) + return; + TCHAR *Template; + INSTALLMESSAGE Type; + switch (Level) + { + case LOG_INFO: + Template = TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(": [1]"); + Type = INSTALLMESSAGE_INFO; + break; + case LOG_WARN: + Template = TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(" warning: [1]"); + Type = INSTALLMESSAGE_INFO; + break; + case LOG_ERR: + Template = TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(" error: [1]"); + Type = INSTALLMESSAGE_ERROR; + break; + default: + goto cleanup; + } + MsiRecordSetString(Record, 0, Template); + MsiRecordSetString(Record, 1, LogLine); + MsiProcessMessage(MsiHandle, Type, Record); +cleanup: + MsiCloseHandle(Record); +} + +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 UINT64 +ParseVersion(_In_ const TCHAR *Version) +{ + ULONG Major = 0, Minor = 0, Revision = 0, Build = 0; + _stscanf_s(Version, TEXT("%u.%u.%u.%u"), &Major, &Minor, &Revision, &Build); + return ((UINT64)Major << 48) | ((UINT64)Minor << 32) | ((UINT64)Revision << 16) | ((UINT64)Build << 0); +} + +_Success_(return ) +static BOOL +Newer(_In_ MSIHANDLE Handle, _In_ BOOL SkipHashComparison, _Out_ TCHAR *InstallAction, _In_ SIZE_T InstallActionSize) +{ + INT64 NewTime, OldTime; + UINT64 NewVersion, OldVersion; + TCHAR NewHash[0x100], OldHash[0x100], NewTimeString[0x100], OldTimeString[0x100], NewVersionString[0x100], + OldVersionString[0x100]; + DWORD Size, Type; + HKEY Key; + BOOL Ret = TRUE; + + Size = _countof(NewHash); + if (MsiGetProperty(Handle, PROPERTY_INSTALLER_HASH, NewHash, &Size) != ERROR_SUCCESS) + return FALSE; + Size = _countof(NewTimeString); + if (MsiGetProperty(Handle, PROPERTY_INSTALLER_BUILDTIME, NewTimeString, &Size) != ERROR_SUCCESS) + return FALSE; + NewTime = _tstoll(NewTimeString); + Size = _countof(NewVersionString); + if (MsiGetProperty(Handle, PROPERTY_VERSION, NewVersionString, &Size) != ERROR_SUCCESS) + return FALSE; + NewVersion = ParseVersion(NewVersionString); + + _stprintf_s( + InstallAction, + InstallActionSize, + ACTION_INSTALL ACTION_INSTALL_SEPERATORS, + NewHash, + NewTimeString, + NewVersionString); + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_DRIVER, 0, KEY_READ, &Key) != ERROR_SUCCESS) + return TRUE; + Size = sizeof(OldHash); + if (RegQueryValueEx(Key, REGKEY_INSTALLER_HASH, NULL, &Type, (LPBYTE)OldHash, &Size) != ERROR_SUCCESS || + Type != REG_SZ) + goto cleanup; + Size = sizeof(OldTimeString); + if (RegQueryValueEx(Key, REGKEY_INSTALLER_BUILDTIME, NULL, &Type, (LPBYTE)OldTimeString, &Size) != ERROR_SUCCESS || + Type != REG_SZ) + goto cleanup; + OldTime = _tstoll(OldTimeString); + Size = sizeof(OldVersionString); + if (RegQueryValueEx(Key, REGKEY_VERSION, NULL, &Type, (LPBYTE)OldVersionString, &Size) != ERROR_SUCCESS || + Type != REG_SZ) + goto cleanup; + OldVersion = ParseVersion(OldVersionString); + + Ret = NewVersion >= OldVersion && NewTime >= OldTime && (SkipHashComparison || _tcscmp(NewHash, OldHash)); + +cleanup: + RegCloseKey(Key); + return Ret; +} + +UINT __stdcall MsiEvaluate(MSIHANDLE Handle) +{ + MsiHandle = Handle; + SetLogger(MsiLogger); + BOOL IsComInitialized = SUCCEEDED(CoInitialize(NULL)); + UINT Ret = ERROR_INSTALL_FAILURE; + MSIHANDLE View = 0, Record = 0, Database = MsiGetActiveDatabase(Handle); + if (!Database) + goto cleanup; + Ret = MsiDatabaseOpenView( + Database, TEXT("SELECT `Component` FROM `Component` WHERE `ComponentId` = '" ANCHOR_COMPONENT TEXT("'")), &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; + TCHAR ComponentName[0x1000]; + DWORD Size = _countof(ComponentName); + Ret = MsiRecordGetString(Record, 1, ComponentName, &Size); + if (Ret != ERROR_SUCCESS) + goto cleanup; + INSTALLSTATE InstallState, ActionState; + Ret = MsiGetComponentState(Handle, ComponentName, &InstallState, &ActionState); + if (Ret != ERROR_SUCCESS) + goto cleanup; + TCHAR InstallAction[0x400]; + if ((IsReInstalling(InstallState, ActionState) || IsInstalling(InstallState, ActionState)) && + Newer(Handle, IsReInstalling(InstallState, ActionState), InstallAction, _countof(InstallAction))) + Ret = MsiSetProperty(Handle, PROCESS_ACTION, InstallAction); + else if (IsUninstalling(InstallState, ActionState)) + Ret = MsiSetProperty(Handle, PROCESS_ACTION, ACTION_UNINSTALL); + if (Ret != ERROR_SUCCESS) + goto cleanup; + + Ret = MsiDoAction(Handle, TEXT("DisableRollback")); + +cleanup: + if (View) + MsiCloseHandle(View); + if (Record) + MsiCloseHandle(Record); + if (Database) + MsiCloseHandle(Database); + if (IsComInitialized) + CoUninitialize(); + return Ret; +} + +static BOOL +WriteRegKeys(_In_ TCHAR *Values) +{ + TCHAR *Hash, *Time, *Version; + Hash = Values; + Time = _tcschr(Hash, ACTION_INSTALL_SEPERATOR); + if (!Time) + return FALSE; + *Time++ = TEXT('\0'); + Version = _tcschr(Time, ACTION_INSTALL_SEPERATOR); + if (!Version) + return FALSE; + *Version++ = TEXT('\0'); + + HKEY Key; + if (RegCreateKeyEx( + HKEY_LOCAL_MACHINE, REGKEY_DRIVER, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &Key, NULL) != + ERROR_SUCCESS) + return FALSE; + BOOL Ret = + RegSetValueEx( + Key, REGKEY_INSTALLER_HASH, 0, REG_SZ, (LPBYTE)Hash, ((DWORD)_tcslen(Hash) + 1) * sizeof(*Hash)) == + ERROR_SUCCESS && + RegSetValueEx( + Key, REGKEY_INSTALLER_BUILDTIME, 0, REG_SZ, (LPBYTE)Time, ((DWORD)_tcslen(Time) + 1) * sizeof(*Time)) == + ERROR_SUCCESS && + RegSetValueEx( + Key, REGKEY_VERSION, 0, REG_SZ, (LPBYTE)Version, ((DWORD)_tcslen(Version) + 1) * sizeof(*Version)) == + ERROR_SUCCESS; + RegCloseKey(Key); + return Ret; +} + +UINT __stdcall MsiProcess(MSIHANDLE Handle) +{ + MsiHandle = Handle; + SetLogger(MsiLogger); + BOOL IsComInitialized = SUCCEEDED(CoInitialize(NULL)); + DWORD LastError = ERROR_SUCCESS; + BOOL Ret = FALSE; + TCHAR Value[0x1000], *RegValues; + DWORD Size = _countof(Value); + LastError = MsiGetProperty(Handle, TEXT("CustomActionData"), Value, &Size); + if (LastError != ERROR_SUCCESS) + goto cleanup; + if ((RegValues = _tcschr(Value, ACTION_INSTALL_SEPERATOR)) != NULL) + *RegValues++ = TEXT('\0'); + if (!_tcscmp(Value, ACTION_INSTALL)) + { + Ret = InstallOrUpdate(); + if (RegValues && Ret) + Ret = WriteRegKeys(RegValues); + } + else if (!_tcscmp(Value, ACTION_UNINSTALL)) + { + Ret = Uninstall(); + if (Ret) + RegDeleteKeyEx(HKEY_LOCAL_MACHINE, REGKEY_DRIVER, 0, 0); + } + else + Ret = TRUE; + LastError = GetLastError(); +cleanup: + if (IsComInitialized) + CoUninitialize(); + return Ret ? ERROR_SUCCESS : LastError ? LastError : ERROR_INSTALL_FAILED; +} diff --git a/msm/pch.h b/msm/pch.h index 885d5d6..feb7f88 100644 --- a/msm/pch.h +++ b/msm/pch.h @@ -9,5 +9,8 @@ // add headers that you want to pre-compile here #include "framework.h" +#include "installation.h" + +#include "../src/config.h" #endif //PCH_H diff --git a/msm/resource.rc.in b/msm/resource.rc.in new file mode 100644 index 0000000..cdd9b8f --- /dev/null +++ b/msm/resource.rc.in @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + +driver.inf RCDATA "OemVista.inf" +driver.cat RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" +driver.sys RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" + +driver-whql.inf RCDATA "win10\\OemVista.inf" +driver-whql.cat RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" +driver-whql.sys RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" From 5a2332743d6db9bd344720c765c17c85875cfab6 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 13:00:20 +0100 Subject: [PATCH 09/19] MSM: ARM64 is always Windows 10 Signed-off-by: Simon Rozman --- msm/installation.c | 8 ++++++++ msm/installer.vcxproj | 12 ++++++++++++ msm/resource.rc.in | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/msm/installation.c b/msm/installation.c index 00d7b4e..83f21d4 100644 --- a/msm/installation.c +++ b/msm/installation.c @@ -261,9 +261,17 @@ InstallDriver(BOOL UpdateExisting) goto cleanupFree; BOOL UseWHQL = FALSE; +#if defined(HAVE_EV) && defined(HAVE_WHQL) DWORD MajorVersion; RtlGetNtVersionNumbers(&MajorVersion, NULL, NULL); UseWHQL = MajorVersion >= 10; +#elif defined(HAVE_EV) + UseWHQL = FALSE; +#elif defined(HAVE_WHQL) + UseWHQL = TRUE; +#else + #error No driver available +#endif if (!UseWHQL && !InstallDriverCertificate(TEXT("driver.sys"))) PrintError(LOG_WARN, TEXT("Unable to install code signing certificate")); diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index f2b8233..b38ad41 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -139,18 +139,30 @@ + + HAVE_EV;HAVE_WHQL;%(PreprocessorDefinitions) + ..\dist\i386 + HAVE_EV;HAVE_WHQL;%(PreprocessorDefinitions) + + HAVE_EV;HAVE_WHQL;%(PreprocessorDefinitions) + ..\dist\amd64 + HAVE_EV;HAVE_WHQL;%(PreprocessorDefinitions) + + HAVE_WHQL;%(PreprocessorDefinitions) + ..\dist\arm64 + HAVE_WHQL;%(PreprocessorDefinitions) diff --git a/msm/resource.rc.in b/msm/resource.rc.in index cdd9b8f..a789215 100644 --- a/msm/resource.rc.in +++ b/msm/resource.rc.in @@ -3,10 +3,14 @@ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. */ +#ifdef HAVE_EV driver.inf RCDATA "OemVista.inf" driver.cat RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" driver.sys RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" +#endif +#ifdef HAVE_WHQL driver-whql.inf RCDATA "win10\\OemVista.inf" driver-whql.cat RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" driver-whql.sys RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" +#endif From 23f0e4ad549d60a22b32bac2998ba7d6cd31817b Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Mar 2020 19:21:16 +0100 Subject: [PATCH 10/19] MSM: Add support for MSM building Signed-off-by: Simon Rozman --- .gitignore | 1 + README.rst | 2 ++ buildtap.py | 18 +++++++++++- msm/.gitignore | 2 +- msm/config.props.in | 28 ++++++++++++++++++ msm/installer.vcxproj | 53 ++++++++++++++++++++++++++++++++++- msm/installer.vcxproj.filters | 3 -- msm/installer.wxs | 51 +++++++++++++++++++++++++++++++++ msm/msi.c | 10 +++---- msm/resource.rc | 14 +++++++++ msm/resource.rc.in | 16 ----------- 11 files changed, 171 insertions(+), 27 deletions(-) create mode 100644 msm/config.props.in create mode 100644 msm/installer.wxs create mode 100644 msm/resource.rc delete mode 100644 msm/resource.rc.in diff --git a/.gitignore b/.gitignore index 8bb20fa..c31418d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ dist/** *.pyc *.tar.gz tap-windows-*.exe +tap-windows-*.msm # builttap.py-generated files src/config.h diff --git a/README.rst b/README.rst index 02ff0db..11b256e 100644 --- a/README.rst +++ b/README.rst @@ -20,6 +20,7 @@ The prerequisites for building are: - Git (not strictly required, but useful for running commands using bundled bash shell) - MakeNSIS (optional) - Prebuilt tapinstall.exe binaries (optional) +- WiX Toolset (optional) Make sure you add Python's install directory (usually c:\\python27) to the PATH environment variable. @@ -44,6 +45,7 @@ View build script options:: --sdk=SDK SDK to use for building: ewdk or wdk, default=ewdk --sign sign the driver files -p, --package generate an NSIS installer from the compiled files + -m, --package-msm generate a MSM installer from the compiled files --cert=CERT Common name of code signing certificate, default=openvpn --certfile=CERTFILE Path to the code signing certificate diff --git a/buildtap.py b/buildtap.py index 1807e3e..99ed812 100644 --- a/buildtap.py +++ b/buildtap.py @@ -198,7 +198,7 @@ def config_tap(self): self.preprocess(kv, os.path.join(self.src, "OemVista.inf")) self.preprocess(kv, os.path.join(self.src, "tap-windows6.vcxproj")) self.preprocess(kv, os.path.join(self.src, "config.h")) - self.preprocess(kv, os.path.join(self.msm, "resource.rc")) + self.preprocess(kv, os.path.join(self.msm, "config.props")) # build a "msbuild" file using (E)WDK def build_ewdk(self, project_file, arch): @@ -334,6 +334,18 @@ def package(self): if self.codesign: self.sign(installer_file) + # build MSM installer + def package_msm(self): + self.config_tap() + project_file = os.path.join(self.msm, "installer.vcxproj") + for arch in ("i386", "amd64"): #self.architectures_supported + print("***** BUILD MSM arch=%s" % (arch,)) + self.run_ewdk('msbuild.exe %s /t:MSM /p:Configuration=%s /p:Platform=%s' % ( + project_file, + self.configuration, + self.architecture_platform_map[arch] + )) + # like find . | sort def enum_tree(self, dir): data = [] @@ -484,6 +496,8 @@ def sign_verify_ti(self, arch): default=False, help="sign the driver files") op.add_option("-p", "--package", action="store_true", dest="package", help="generate an NSIS installer from the compiled files") + op.add_option("-m", "--package-msm", action="store_true", dest="package_msm", + help="generate a MSM installer from the compiled files") op.add_option("--cert", dest="cert", metavar="CERT", default=cert, help="Common name of code signing certificate, default=%s" % (cert,)) @@ -513,3 +527,5 @@ def sign_verify_ti(self, arch): btw.build() if opt.package: btw.package() + if opt.package_msm: + btw.package_msm() diff --git a/msm/.gitignore b/msm/.gitignore index ca802a1..f65a118 100644 --- a/msm/.gitignore +++ b/msm/.gitignore @@ -2,4 +2,4 @@ /Debug /Release /x64 -/resource.rc +/config.props diff --git a/msm/config.props.in b/msm/config.props.in new file mode 100644 index 0000000..f753a29 --- /dev/null +++ b/msm/config.props.in @@ -0,0 +1,28 @@ + + + + + @PRODUCT_NAME@ + @PRODUCT_PUBLISHER@ + @PRODUCT_VERSION@ + @PRODUCT_VERSION_RESOURCE@ + @PRODUCT_TAP_WIN_COMPONENT_ID@ + @PRODUCT_TAP_WIN_MAJOR@ + @PRODUCT_TAP_WIN_MINOR@ + @PRODUCT_TAP_WIN_REVISION@ + @PRODUCT_TAP_WIN_BUILD@ + @PRODUCT_TAP_WIN_PROVIDER@ + @PRODUCT_TAP_WIN_CHARACTERISTICS@ + @PRODUCT_TAP_WIN_DEVICE_DESCRIPTION@ + @PRODUCT_TAP_WIN_RELDATE@ + + $(WixCandleFlags) -dPRODUCT_NAME="@PRODUCT_NAME@" + $(WixCandleFlags) -dPRODUCT_PUBLISHER="@PRODUCT_PUBLISHER@" + $(WixCandleFlags) -dPRODUCT_VERSION="@PRODUCT_VERSION@" + $(WixCandleFlags) -dPRODUCT_TAP_WIN_COMPONENT_ID="@PRODUCT_TAP_WIN_COMPONENT_ID@" + + diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index b38ad41..017d387 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -34,6 +34,18 @@ 10.0 + + x86 + i386 + + + x64 + amd64 + + + arm64 + arm64 + DynamicLibrary true @@ -80,28 +92,43 @@ + + + + + + + + $(WixCandleFlags) -nologo -arch $(WixArch) -dPLATFORM=$(Platform) -sw1086 + $(WixLightFlags) -nologo -b output_dir="$(OutDir.TrimEnd('\'))" -spdb -sw1076 -sw1079 + $(OutDir) + tap-windows + .msm + true false + ..\ + tap-windows-$(ProductVersion)-I$(ProductTapWinBuild)-$(OpenVPNPlatform) @@ -112,6 +139,9 @@ true pch.h + + DRIVER_INF=OemVista.inf;DRIVER_CAT=$(ProductTapWinComponentId).cat;DRIVER_SYS=$(ProductTapWinComponentId).sys;DRIVER_INF_WHQL=win10\\OemVista.inf;DRIVER_CAT_WHQL=win10\\$(ProductTapWinComponentId).cat;DRIVER_SYS_WHQL=win10\\$(ProductTapWinComponentId).sys;%(PreprocessorDefinitions) + Windows Cfgmgr32.lib;Crypt32.lib;Msi.lib;Newdev.lib;ntdll.lib;Setupapi.lib;Shlwapi.lib;%(AdditionalDependencies) @@ -189,9 +219,30 @@ - + + $(MSMDependsOn);WixCompile;WixLink + WixClean;$(CleanDependsOn) + + + + + + + $(WixCandleFlags) -dINSTALLER_LIBRARY_HASH=@(InstallerLibraryHash->Metadata('FileHash')) -dINSTALLER_LIBRARY_TIME=$([System.IO.File]::GetLastWriteTime('$(OutDir)$(TargetName)$(TargetExt)').Ticks) + + + + + + + + + + + + \ No newline at end of file diff --git a/msm/installer.vcxproj.filters b/msm/installer.vcxproj.filters index a8d538b..3f5136f 100644 --- a/msm/installer.vcxproj.filters +++ b/msm/installer.vcxproj.filters @@ -48,8 +48,5 @@ Source Files - - Resource Files - \ No newline at end of file diff --git a/msm/installer.wxs b/msm/installer.wxs new file mode 100644 index 0000000..c24a800 --- /dev/null +++ b/msm/installer.wxs @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msm/msi.c b/msm/msi.c index 3f99e80..9b39c7c 100644 --- a/msm/msi.c +++ b/msm/msi.c @@ -9,15 +9,15 @@ static MSIHANDLE MsiHandle; -#define ANCHOR_COMPONENT TEXT("{B668D4C7-ABB3-485A-B8DF-D34200489A43}") -#define PROCESS_ACTION TEXT("Process") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) +#define ANCHOR_COMPONENT TEXT("{B937EFA3-CE00-4E5B-86C8-8CB67A32D448}") +#define PROCESS_ACTION TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("_Process") #define ACTION_INSTALL TEXT("/Action=Install") #define ACTION_INSTALL_SEPERATOR TEXT('-') #define ACTION_INSTALL_SEPERATORS TEXT("-%s-%s-%s") #define ACTION_UNINSTALL TEXT("/Action=Uninstall") -#define PROPERTY_INSTALLER_HASH TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("InstallerHash") -#define PROPERTY_INSTALLER_BUILDTIME TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("InstallerBuildtime") -#define PROPERTY_VERSION TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("Version") +#define PROPERTY_INSTALLER_HASH TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("_InstallerHash") +#define PROPERTY_INSTALLER_BUILDTIME TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("_InstallerBuildtime") +#define PROPERTY_VERSION TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT("_Version") #define REGKEY_DRIVER TEXT("Software\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) #define REGKEY_INSTALLER_HASH TEXT("InstallerHash") #define REGKEY_INSTALLER_BUILDTIME TEXT("InstallerBuildtime") diff --git a/msm/resource.rc b/msm/resource.rc new file mode 100644 index 0000000..05118d4 --- /dev/null +++ b/msm/resource.rc @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + +#ifndef _M_ARM64 +driver.inf RCDATA DRIVER_INF +driver.cat RCDATA DRIVER_CAT +driver.sys RCDATA DRIVER_SYS +#endif + +driver-whql.inf RCDATA DRIVER_INF_WHQL +driver-whql.cat RCDATA DRIVER_CAT_WHQL +driver-whql.sys RCDATA DRIVER_SYS_WHQL diff --git a/msm/resource.rc.in b/msm/resource.rc.in deleted file mode 100644 index a789215..0000000 --- a/msm/resource.rc.in +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. - */ - -#ifdef HAVE_EV -driver.inf RCDATA "OemVista.inf" -driver.cat RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" -driver.sys RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" -#endif - -#ifdef HAVE_WHQL -driver-whql.inf RCDATA "win10\\OemVista.inf" -driver-whql.cat RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" -driver-whql.sys RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" -#endif From bc1fe6a5084cfb9d3b9f86648d69b6bb1fd3f050 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 4 Mar 2020 13:45:14 +0100 Subject: [PATCH 11/19] MSM: Install include\tap-windows.h Signed-off-by: Simon Rozman --- msm/installer.vcxproj | 2 +- msm/installer.wxs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index 017d387..f09dd62 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -117,7 +117,7 @@ $(WixCandleFlags) -nologo -arch $(WixArch) -dPLATFORM=$(Platform) -sw1086 - $(WixLightFlags) -nologo -b output_dir="$(OutDir.TrimEnd('\'))" -spdb -sw1076 -sw1079 + $(WixLightFlags) -nologo -b output_dir="$(OutDir.TrimEnd('\'))" -b dist_dir="..\dist" -spdb -sw1076 -sw1079 $(OutDir) tap-windows .msm diff --git a/msm/installer.wxs b/msm/installer.wxs index c24a800..3c7fe78 100644 --- a/msm/installer.wxs +++ b/msm/installer.wxs @@ -24,6 +24,12 @@ Value="1" KeyPath="yes" /> + + + + + + From 0ce84931f54eaad4f5b9fae2f54bbd517b0e1ad4 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 4 Mar 2020 14:07:04 +0100 Subject: [PATCH 12/19] MSM: Fix resource rebuilding When RCDATA file path was authored using a defined constant the MSBuild failed to resolve dependency. This skipped rebuilding the resources when driver files changed. Signed-off-by: Simon Rozman --- buildtap.py | 1 + msm/.gitignore | 1 + msm/installer.vcxproj | 4 +--- msm/installer.vcxproj.filters | 3 +++ msm/resource.rc | 14 -------------- msm/resource.rc.in | 16 ++++++++++++++++ 6 files changed, 22 insertions(+), 17 deletions(-) delete mode 100644 msm/resource.rc create mode 100644 msm/resource.rc.in diff --git a/buildtap.py b/buildtap.py index 99ed812..0ebd75a 100644 --- a/buildtap.py +++ b/buildtap.py @@ -199,6 +199,7 @@ def config_tap(self): self.preprocess(kv, os.path.join(self.src, "tap-windows6.vcxproj")) self.preprocess(kv, os.path.join(self.src, "config.h")) self.preprocess(kv, os.path.join(self.msm, "config.props")) + self.preprocess(kv, os.path.join(self.msm, "resource.rc")) # build a "msbuild" file using (E)WDK def build_ewdk(self, project_file, arch): diff --git a/msm/.gitignore b/msm/.gitignore index f65a118..b3080ae 100644 --- a/msm/.gitignore +++ b/msm/.gitignore @@ -3,3 +3,4 @@ /Release /x64 /config.props +/resource.rc diff --git a/msm/installer.vcxproj b/msm/installer.vcxproj index f09dd62..c60dbf0 100644 --- a/msm/installer.vcxproj +++ b/msm/installer.vcxproj @@ -139,9 +139,6 @@ true pch.h - - DRIVER_INF=OemVista.inf;DRIVER_CAT=$(ProductTapWinComponentId).cat;DRIVER_SYS=$(ProductTapWinComponentId).sys;DRIVER_INF_WHQL=win10\\OemVista.inf;DRIVER_CAT_WHQL=win10\\$(ProductTapWinComponentId).cat;DRIVER_SYS_WHQL=win10\\$(ProductTapWinComponentId).sys;%(PreprocessorDefinitions) - Windows Cfgmgr32.lib;Crypt32.lib;Msi.lib;Newdev.lib;ntdll.lib;Setupapi.lib;Shlwapi.lib;%(AdditionalDependencies) @@ -219,6 +216,7 @@ + diff --git a/msm/installer.vcxproj.filters b/msm/installer.vcxproj.filters index 3f5136f..a8d538b 100644 --- a/msm/installer.vcxproj.filters +++ b/msm/installer.vcxproj.filters @@ -48,5 +48,8 @@ Source Files + + Resource Files + \ No newline at end of file diff --git a/msm/resource.rc b/msm/resource.rc deleted file mode 100644 index 05118d4..0000000 --- a/msm/resource.rc +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. - */ - -#ifndef _M_ARM64 -driver.inf RCDATA DRIVER_INF -driver.cat RCDATA DRIVER_CAT -driver.sys RCDATA DRIVER_SYS -#endif - -driver-whql.inf RCDATA DRIVER_INF_WHQL -driver-whql.cat RCDATA DRIVER_CAT_WHQL -driver-whql.sys RCDATA DRIVER_SYS_WHQL diff --git a/msm/resource.rc.in b/msm/resource.rc.in new file mode 100644 index 0000000..a789215 --- /dev/null +++ b/msm/resource.rc.in @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved. + */ + +#ifdef HAVE_EV +driver.inf RCDATA "OemVista.inf" +driver.cat RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" +driver.sys RCDATA "@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" +#endif + +#ifdef HAVE_WHQL +driver-whql.inf RCDATA "win10\\OemVista.inf" +driver-whql.cat RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.cat" +driver-whql.sys RCDATA "win10\\@PRODUCT_TAP_WIN_COMPONENT_ID@.sys" +#endif From 21bc482f21f7524b2e25c6828fb7483e71381bad Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 4 Mar 2020 14:36:12 +0100 Subject: [PATCH 13/19] MSM: Match .inf filename The .cat catalog file references .inf and .sys files. Therefore, we need to use original driver filenames. Signed-off-by: Simon Rozman --- msm/installation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msm/installation.c b/msm/installation.c index 83f21d4..6b89eb5 100644 --- a/msm/installation.c +++ b/msm/installation.c @@ -257,7 +257,7 @@ InstallDriver(BOOL UpdateExisting) if (!PathCombine(SysPath, RandomTempSubDirectory, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(".sys"))) goto cleanupFree; TCHAR InfPath[MAX_PATH] = { 0 }; - if (!PathCombine(InfPath, RandomTempSubDirectory, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) TEXT(".inf"))) + if (!PathCombine(InfPath, RandomTempSubDirectory, TEXT("OemVista.inf"))) goto cleanupFree; BOOL UseWHQL = FALSE; From ac95cf7761bf34967dc0cca0776aca7964534503 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 4 Mar 2020 15:01:25 +0100 Subject: [PATCH 14/19] MSM: Fix hardware ID usage TAP-Windows6 is using root-enumerated default HWID. Signed-off-by: Simon Rozman --- msm/installation.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/msm/installation.c b/msm/installation.c index 6b89eb5..76cc696 100644 --- a/msm/installation.c +++ b/msm/installation.c @@ -60,6 +60,13 @@ PrintError(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *Prefix) HINSTANCE ResourceModule; +static BOOL IsOurDriver(const TCHAR *HardwareID) +{ + return + !_tcsicmp(HardwareID, TEXT("root\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID)) || + !_tcsicmp(HardwareID, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID)); +} + static BOOL IsDriverLoaded(VOID) { DWORD RequiredSize = 0, CurrentSize = 0; @@ -287,7 +294,7 @@ InstallDriver(BOOL UpdateExisting) BOOL RebootRequired = FALSE; if (UpdateExisting && !UpdateDriverForPlugAndPlayDevices( - NULL, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID), InfPath, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &RebootRequired)) + NULL, TEXT("root\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID), InfPath, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &RebootRequired)) PrintError(LOG_WARN, TEXT("Could not update existing adapters")); if (RebootRequired) Logger(LOG_WARN, TEXT("A reboot might be required")); @@ -336,7 +343,7 @@ static BOOL RemoveDriver(VOID) free(DriverDetail); goto cleanupDriverInfoList; } - if (!_tcsicmp(DriverDetail->HardwareID, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID))) + if (IsOurDriver(DriverDetail->HardwareID)) { PathStripPath(DriverDetail->InfFileName); Logger(LOG_INFO, TEXT("Removing existing driver")); @@ -381,7 +388,7 @@ IsOurAdapter(_In_ HDEVINFO DeviceInfoSet, _Inout_ SP_DEVINFO_DATA *DeviceInfo) DriverDetail->cbSize = sizeof(*DriverDetail); if (SetupDiGetDriverInfoDetail( DeviceInfoSet, DeviceInfo, &DriverInfo, DriverDetail, RequiredSize, &RequiredSize) && - !_tcsicmp(DriverDetail->HardwareID, TEXT(PRODUCT_TAP_WIN_COMPONENT_ID))) + IsOurDriver(DriverDetail->HardwareID)) { free(DriverDetail); Found = TRUE; From 2217a970b6745cbadcd9a232bd7cf73f1781d54e Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 4 Mar 2020 16:59:52 +0100 Subject: [PATCH 15/19] MSM: Use catalog file for signing certificate extraction The .sys file of the driver does not need to be digitally signed. It is the .cat file that Windows is checking for complete driver .inf+.sys+ .cat bundle. Signed-off-by: Simon Rozman --- msm/installation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msm/installation.c b/msm/installation.c index 76cc696..6427a1e 100644 --- a/msm/installation.c +++ b/msm/installation.c @@ -279,7 +279,7 @@ InstallDriver(BOOL UpdateExisting) #else #error No driver available #endif - if (!UseWHQL && !InstallDriverCertificate(TEXT("driver.sys"))) + if (!UseWHQL && !InstallDriverCertificate(TEXT("driver.cat"))) PrintError(LOG_WARN, TEXT("Unable to install code signing certificate")); Logger(LOG_INFO, TEXT("Copying resources to temporary path")); From 32da3c10e5c7e222c3e3ee2b934b50b455a7b331 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Thu, 5 Mar 2020 09:15:58 +0100 Subject: [PATCH 16/19] MSM: Ask MSI to restart should upgrading the driver report it so Signed-off-by: Simon Rozman --- msm/installation.c | 10 ++++++---- msm/installation.h | 2 +- msm/msi.c | 5 ++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/msm/installation.c b/msm/installation.c index 6427a1e..c435c05 100644 --- a/msm/installation.c +++ b/msm/installation.c @@ -230,7 +230,7 @@ extern VOID NTAPI RtlGetNtVersionNumbers(_Out_opt_ DWORD *MajorVersion, _Out_opt_ DWORD *MinorVersion, _Out_opt_ DWORD *BuildNumber); static BOOL -InstallDriver(BOOL UpdateExisting) +InstallDriver(_In_ BOOL UpdateExisting, _Inout_ BOOL *IsRebootRequired) { DWORD LastError = ERROR_SUCCESS; TCHAR WindowsDirectory[MAX_PATH]; @@ -296,8 +296,10 @@ InstallDriver(BOOL UpdateExisting) !UpdateDriverForPlugAndPlayDevices( NULL, TEXT("root\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID), InfPath, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &RebootRequired)) PrintError(LOG_WARN, TEXT("Could not update existing adapters")); - if (RebootRequired) + if (RebootRequired) { Logger(LOG_WARN, TEXT("A reboot might be required")); + *IsRebootRequired = TRUE; + } cleanupDelete: LastError = GetLastError(); @@ -513,7 +515,7 @@ EnableOurAdapters(_In_ HDEVINFO DeviceInfoSet, _In_ SP_DEVINFO_DATA_LIST *Adapte return Ret; } -BOOL InstallOrUpdate(VOID) +BOOL InstallOrUpdate(_Inout_ BOOL *IsRebootRequired) { BOOL Ret = FALSE; HDEVINFO DeviceInfoSet = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); @@ -535,7 +537,7 @@ BOOL InstallOrUpdate(VOID) PrintError(LOG_ERR, TEXT("Failed to uninstall old drivers")); goto cleanupAdapters; } - if (!InstallDriver(!!ExistingAdapters)) + if (!InstallDriver(!!ExistingAdapters, IsRebootRequired)) { PrintError(LOG_ERR, TEXT("Failed to install driver")); goto cleanupAdapters; diff --git a/msm/installation.h b/msm/installation.h index e5ce781..4b5c007 100644 --- a/msm/installation.h +++ b/msm/installation.h @@ -17,7 +17,7 @@ typedef VOID (*LoggerFunction)(_In_ LOGGER_LEVEL, _In_ const TCHAR *); VOID SetLogger(_In_ LoggerFunction NewLogger); -BOOL InstallOrUpdate(VOID); +BOOL InstallOrUpdate(_Inout_ BOOL *IsRebootRequired); BOOL Uninstall(VOID); extern HINSTANCE ResourceModule; diff --git a/msm/msi.c b/msm/msi.c index 9b39c7c..14ce2ed 100644 --- a/msm/msi.c +++ b/msm/msi.c @@ -242,9 +242,12 @@ UINT __stdcall MsiProcess(MSIHANDLE Handle) *RegValues++ = TEXT('\0'); if (!_tcscmp(Value, ACTION_INSTALL)) { - Ret = InstallOrUpdate(); + BOOL RebootRequired = FALSE; + Ret = InstallOrUpdate(&RebootRequired); if (RegValues && Ret) Ret = WriteRegKeys(RegValues); + if (RebootRequired) + MsiSetMode(Handle, MSIRUNMODE_REBOOTATEND, TRUE); } else if (!_tcscmp(Value, ACTION_UNINSTALL)) { From 149f31afd73570c937868eb86cba3751d868937d Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Sat, 7 Mar 2020 07:54:36 +0100 Subject: [PATCH 17/19] MSM: Document the packaging Signed-off-by: Simon Rozman --- README.rst | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 11b256e..c677362 100644 --- a/README.rst +++ b/README.rst @@ -20,7 +20,7 @@ The prerequisites for building are: - Git (not strictly required, but useful for running commands using bundled bash shell) - MakeNSIS (optional) - Prebuilt tapinstall.exe binaries (optional) -- WiX Toolset (optional) +- Visual Studio 2019 and WiX Toolset for MSM packaging (optional) Make sure you add Python's install directory (usually c:\\python27) to the PATH environment variable. @@ -212,6 +212,60 @@ any attempt to timestamp the driver will fail. For this reason configure your outbound proxy server before starting the build. Note that the command prompt also needs to be restarted to make use of new proxy settings. +MSM packaging +------------- + +In order to build the MSM packages build and sign the driver first: + +- Build the TAP driver with buildtap.py and "-b" flag. +- EV-sign the drivers +- WHQL/Attestation-sign the drivers + +Place the signed drivers in a directory structure under tap-windows6 +directory. Each platform directory should contain the EV-signed driver with a +"win10" subdirectory containing WHQL/Attestation signed driver for that +platform: +:: + dist + ├── amd64 + │ ├── win10 + │ │ ├── OemVista.inf + │ │ ├── tap0901.cat + │ │ └── tap0901.sys + │ ├── OemVista.inf + │ ├── tap0901.cat + │ └── tap0901.sys + ├── arm64 + │ ├── win10 + │ │ ├── OemVista.inf + │ │ ├── tap0901.cat + │ │ └── tap0901.sys + │ └── (Note: EV-signed driver for arm64 is not used.) + └── i386 + ├── win10 + │ ├── OemVista.inf + │ ├── tap0901.cat + │ └── tap0901.sys + ├── OemVista.inf + ├── tap0901.cat + └── tap0901.sys + +Building MSM packages requires Visual Studio 2019 (EWDK is not sufficient) and +the WiX Toolset installed. In a Developer Command Prompt for Visual Studio +2019, run: +:: + $ python buildtap.py -m --sdk=wdk + +This will compile the installer.dll file with embedded drivers and package it +as a platform-dependent tap-windows--.msm files. + +As the WiX Toolset does not support the arm64 platform yet, only amd64 and +i386 MSM files are built. + +Optional: Consider EV-signing the MSM packages before deploying them. Thou, +MSM signature is ignored when merging MSM into MSI package, users get a choice +to validate the integrity of the downloaded MSM packages manually. + License ------- From a7cee83c43623b086203f37a54d0a3a77ca9f2d5 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Sun, 8 Mar 2020 10:23:38 +0100 Subject: [PATCH 18/19] README.rst: Unify literal blocks to their minimized form Signed-off-by: Simon Rozman --- README.rst | 59 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/README.rst b/README.rst index c677362..2adb812 100644 --- a/README.rst +++ b/README.rst @@ -70,17 +70,17 @@ Building tapinstall (optional) ------------------------------ The easiest way to build tapinstall is to clone the Microsoft driver samples -and copy the source for devcon.exe into the tap-windows6 tree. Using PowerShell: -:: - git clone https://github.com/Microsoft/Windows-driver-samples - Copy-Item -Recurse Windows-driver-samples/setup/devcon tap-windows6 - cd tap-windows6 - python.exe buildtap.py -b --ti=devcon +and copy the source for devcon.exe into the tap-windows6 tree. Using PowerShell:: + + $ git clone https://github.com/Microsoft/Windows-driver-samples + $ Copy-Item -Recurse Windows-driver-samples/setup/devcon tap-windows6 + $ cd tap-windows6 + $ python.exe buildtap.py -b --ti=devcon The build system also supports reuse of pre-built tapinstall.exe executables. To make sure the buildsystem finds the executables, create the following -directory structure under tap-windows6 directory: -:: +directory structure under tap-windows6 directory:: + devcon ├── Release │ └── devcon.exe @@ -132,9 +132,8 @@ The recommended procedure is to use pre-built, cross-signed devcon.exe and use the WDK-generated key for signing the driver. First setup the directory with prebuilt devcon as described above. -Then run the build with the --hlk option: +Then run the build with the --hlk option:: -:: $ python.exe buildtap.py -c -b --ti=devcon-prebuilt --hlk Release signing @@ -159,20 +158,20 @@ run as Administrator; according to Microsoft documentation Inf2Cat, which Cross-Sign.ps1 uses to create (unsigned) catalog files, needs to run with administrator privileges. -First produce cross-signed drivers and installers (Windows 7/8/8.1/Server 2012r2): -:: - $ python.exe buildtap.py -c -b --ti=devcon - $ sign\Cross-Sign.ps1 -SourceDir dist -Force - $ python.exe buildtap.py -p --ti=devcon - $ Get-Item tap-windows*.exe|sign\Sign-File.ps1 +First produce cross-signed drivers and installers (Windows 7/8/8.1/Server 2012r2):: + + $ python.exe buildtap.py -c -b --ti=devcon + $ sign\Cross-Sign.ps1 -SourceDir dist -Force + $ python.exe buildtap.py -p --ti=devcon + $ Get-Item tap-windows*.exe|sign\Sign-File.ps1 Note that the "-Force" option for Cross-Sign.ps1 is *required* except in the unlikely case you're appending a signature. -Next produce a driver submission cabinet files for attestation signing: -:: - $ sign\Create-DriverSubmission.ps1 - $ Get-ChildItem -Path disk1|sign\Sign-File.ps1 +Next produce a driver submission cabinet files for attestation signing:: + + $ sign\Create-DriverSubmission.ps1 + $ Get-ChildItem -Path disk1|sign\Sign-File.ps1 Three architecture-specific (i386, amd64, arm64) cabinet files are created. Submit these to Windows Dev Center for attestation signing. Take care to only @@ -180,12 +179,12 @@ request signatures applicable for each architecture. After downloading the attestation-signed drivers as zip files put them into a temporary directory under the tap-windows6 directory. Then extract the drivers -into the "dist" directory, produce an installer and sign it: -:: - $ cd tap-windows6 - $ Get-ChildItem -Path tempdir -Filter "*.zip"|sign\Extract-DriverSubmission.ps1 - $ python.exe buildtap.py -p --ti=devcon - $ Get-Item tap-windows*.exe|sign\Sign-File.ps1 +into the "dist" directory, produce an installer and sign it:: + + $ cd tap-windows6 + $ Get-ChildItem -Path tempdir -Filter "*.zip"|sign\Extract-DriverSubmission.ps1 + $ python.exe buildtap.py -p --ti=devcon + $ Get-Item tap-windows*.exe|sign\Sign-File.ps1 Note that these steps will fail unless cross-signed tapinstall.exe is present in each architecture-specific directory (i386, amd64, arm64) under the "dist" @@ -224,8 +223,8 @@ In order to build the MSM packages build and sign the driver first: Place the signed drivers in a directory structure under tap-windows6 directory. Each platform directory should contain the EV-signed driver with a "win10" subdirectory containing WHQL/Attestation signed driver for that -platform: -:: +platform:: + dist ├── amd64 │ ├── win10 @@ -252,8 +251,8 @@ platform: Building MSM packages requires Visual Studio 2019 (EWDK is not sufficient) and the WiX Toolset installed. In a Developer Command Prompt for Visual Studio -2019, run: -:: +2019, run:: + $ python buildtap.py -m --sdk=wdk This will compile the installer.dll file with embedded drivers and package it From ebe7d2404f8544ee56655a3d891c27e93dc37ae8 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 9 Mar 2020 19:48:52 +0100 Subject: [PATCH 19/19] MSM: Upgrade root\tap0901 and tap0901 adapters tapinstall/devcon.exe creates tap0901 adapters, tapctl.exe creates root\ tap0901. Both use the same driver. Both adapters should upgrade when we update the driver. Signed-off-by: Simon Rozman --- msm/installation.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/msm/installation.c b/msm/installation.c index c435c05..f62d1e3 100644 --- a/msm/installation.c +++ b/msm/installation.c @@ -31,10 +31,21 @@ SetLogger(_In_ LoggerFunction NewLogger) } static VOID -PrintError(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *Prefix) +PrintError(_In_ LOGGER_LEVEL Level, _In_z_ const TCHAR *Prefix, ...) { DWORD ErrorCode = GetLastError(); - TCHAR *SystemMessage = NULL, *FormattedMessage = NULL; + TCHAR *Message = NULL, *SystemMessage = NULL, *FormattedMessage = NULL; + va_list Args; + va_start(Args, Prefix); + FormatMessage( + FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, + Prefix, + 0, + 0, + (VOID *)&Message, + 0, + &Args); + va_end(Args); FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, @@ -51,11 +62,12 @@ PrintError(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *Prefix) 0, (VOID *)&FormattedMessage, 0, - (va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)ErrorCode, (DWORD_PTR)SystemMessage }); + (va_list *)(DWORD_PTR[]){ (DWORD_PTR)Message, (DWORD_PTR)ErrorCode, (DWORD_PTR)SystemMessage }); if (FormattedMessage) Logger(Level, FormattedMessage); LocalFree(FormattedMessage); LocalFree(SystemMessage); + LocalFree(Message); } HINSTANCE ResourceModule; @@ -291,14 +303,20 @@ InstallDriver(_In_ BOOL UpdateExisting, _Inout_ BOOL *IsRebootRequired) Logger(LOG_INFO, TEXT("Installing driver")); Ret = SetupCopyOEMInf(InfPath, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL); - BOOL RebootRequired = FALSE; - if (UpdateExisting && - !UpdateDriverForPlugAndPlayDevices( - NULL, TEXT("root\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID), InfPath, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &RebootRequired)) - PrintError(LOG_WARN, TEXT("Could not update existing adapters")); - if (RebootRequired) { - Logger(LOG_WARN, TEXT("A reboot might be required")); - *IsRebootRequired = TRUE; + static const TCHAR *HwID[] = { + TEXT("root\\") TEXT(PRODUCT_TAP_WIN_COMPONENT_ID), + TEXT(PRODUCT_TAP_WIN_COMPONENT_ID) + }; + for (int i = 0; i < _countof(HwID); ++i) { + BOOL RebootRequired = FALSE; + if (UpdateExisting && + !UpdateDriverForPlugAndPlayDevices( + NULL, HwID[i], InfPath, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &RebootRequired)) + PrintError(LOG_WARN, TEXT("Could not update existing %1 adapters"), HwID[i]); + if (RebootRequired) { + Logger(LOG_WARN, TEXT("A reboot might be required")); + *IsRebootRequired = TRUE; + } } cleanupDelete: