diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-01-16 09:35:07 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-01-16 09:35:07 +0100 |
| commit | 346f4e99320d1aa38bea05d8dd8559416983048c (patch) | |
| tree | 9eab945fcb90389cceb0a91c54a20c8c4bae8a60 /windows/nsis-plugins/src | |
| parent | d0927bbedd19501bbd9e877b977b69e3a08af2d0 (diff) | |
| parent | 815a4ef023c9639d946998b0d06f3011efbad732 (diff) | |
| download | mullvadvpn-346f4e99320d1aa38bea05d8dd8559416983048c.tar.xz mullvadvpn-346f4e99320d1aa38bea05d8dd8559416983048c.zip | |
Merge branch 'log-wintun'
Diffstat (limited to 'windows/nsis-plugins/src')
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/dllmain.cpp | 11 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/msiutil.cpp | 210 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/msiutil.def | 6 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/msiutil.vcxproj | 122 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/msiutil.vcxproj.filters | 15 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/stdafx.cpp | 8 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/stdafx.h | 16 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/msiutil/targetver.h | 12 |
8 files changed, 400 insertions, 0 deletions
diff --git a/windows/nsis-plugins/src/msiutil/dllmain.cpp b/windows/nsis-plugins/src/msiutil/dllmain.cpp new file mode 100644 index 0000000000..a5a44613dd --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/dllmain.cpp @@ -0,0 +1,11 @@ +#include "stdafx.h" +#include <windows.h> + +BOOL APIENTRY DllMain(HMODULE, DWORD reason, LPVOID) +{ + // + // Avoid doing work in DllMain since the loader lock is held + // + + return TRUE; +} diff --git a/windows/nsis-plugins/src/msiutil/msiutil.cpp b/windows/nsis-plugins/src/msiutil/msiutil.cpp new file mode 100644 index 0000000000..4374832505 --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/msiutil.cpp @@ -0,0 +1,210 @@ +#include "stdafx.h" +#include <msi.h> +#include <windows.h> +#include <nsis/pluginapi.h> +#include "../error.h" +#include <log/log.h> +#include <libcommon/string.h> +#include <stdexcept> + +namespace +{ + +std::wstring PopString() +{ + // + // NSIS functions popstring() and popstringn() require that you definitely size the buffer + // before popping the string. Let's do it ourselves instead. + // + + if (!g_stacktop || !*g_stacktop) + { + throw std::runtime_error("NSIS variable stack is corrupted"); + } + + stack_t *th = *g_stacktop; + + std::wstring copy(th->text); + + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + + return copy; +} + +EXTERN_C IMAGE_DOS_HEADER __ImageBase; + +void PinDll() +{ + // + // Apparently NSIS loads and unloads the plugin module for EVERY call it makes to the plugin. + // This makes it kind of difficult to maintain state. + // + // We can work around this by incrementing the module reference count. + // When NSIS calls FreeLibrary() the reference count decrements and becomes one. + // + + wchar_t self[MAX_PATH]; + + if (0 == GetModuleFileNameW((HINSTANCE)&__ImageBase, self, _countof(self))) + { + throw std::runtime_error("Failed to pin plugin module"); + } + + // + // For some reason, NSIS frees this particular DLL more times than it loads it + // so we have to up the reference count significantly. + // + for (int i = 0; i < 100; ++i) + { + LoadLibraryW(self); + } +} + +int WINAPI InstallerHandler( + LPVOID context, + UINT type, + LPCWSTR message +) +{ + PluginLog(message); + // return 0 to pass it on to the installer + return 0; +} + +} // anonymous namespace + + +// +// SilentInstall "installer.msi" +// +// Performs a silent install and logs the results. +// +// Return: Empty string and NsisStatus::SUCCESS on success. +// Otherwise an error string and NsisStatus::GENERAL_ERROR. +// + +void __declspec(dllexport) NSISCALL SilentInstall +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + const auto msiFile = PopString(); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr); + MsiSetExternalUIW( + InstallerHandler, + INSTALLLOGMODE_INFO | + INSTALLLOGMODE_WARNING | + INSTALLLOGMODE_ERROR | + INSTALLLOGMODE_FATALEXIT | + INSTALLLOGMODE_OUTOFDISKSPACE | + INSTALLLOGMODE_RMFILESINUSE | + INSTALLLOGMODE_FILESINUSE, + nullptr + ); + + const auto installResult = MsiInstallProductW( + msiFile.c_str(), + L"ACTION=INSTALL " + L"REBOOT=ReallySuppress" + ); + + if (ERROR_SUCCESS != installResult) + { + std::wstringstream ss; + ss << L"Install failed: " << installResult; + pushstring(ss.str().c_str()); + pushint(NsisStatus::GENERAL_ERROR); + } + + pushstring(L""); + pushint(NsisStatus::SUCCESS); + } + catch (std::exception & err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(NsisStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(NsisStatus::GENERAL_ERROR); + } +} + +// +// SilentUninstall "installer.msi" +// +// Performs a silent uninstall and logs the results. +// +// Return: Empty string and NsisStatus::SUCCESS on success. +// Otherwise an error string and NsisStatus::GENERAL_ERROR. +// + +void __declspec(dllexport) NSISCALL SilentUninstall +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + const auto msiFile = PopString(); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr); + MsiSetExternalUIW( + InstallerHandler, + INSTALLLOGMODE_INFO | + INSTALLLOGMODE_WARNING | + INSTALLLOGMODE_ERROR | + INSTALLLOGMODE_FATALEXIT | + INSTALLLOGMODE_OUTOFDISKSPACE | + INSTALLLOGMODE_RMFILESINUSE | + INSTALLLOGMODE_FILESINUSE, + nullptr + ); + + const auto installResult = MsiInstallProductW( + msiFile.c_str(), + L"REMOVE=ALL " + L"REBOOT=ReallySuppress" + ); + + if (ERROR_SUCCESS != installResult) + { + std::wstringstream ss; + ss << L"Install failed: " << installResult; + pushstring(ss.str().c_str()); + pushint(NsisStatus::GENERAL_ERROR); + } + + pushstring(L""); + pushint(NsisStatus::SUCCESS); + } + catch (std::exception & err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(NsisStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(NsisStatus::GENERAL_ERROR); + } +} diff --git a/windows/nsis-plugins/src/msiutil/msiutil.def b/windows/nsis-plugins/src/msiutil/msiutil.def new file mode 100644 index 0000000000..115bce87d3 --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/msiutil.def @@ -0,0 +1,6 @@ +LIBRARY msiutil + +EXPORTS + +SilentInstall +SilentUninstall diff --git a/windows/nsis-plugins/src/msiutil/msiutil.vcxproj b/windows/nsis-plugins/src/msiutil/msiutil.vcxproj new file mode 100644 index 0000000000..ce8d2bed6e --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/msiutil.vcxproj @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>16.0</VCProjectVersion> + <ProjectGuid>{83487059-2549-4DF9-A785-A4FD5211234B}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>msiutil</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir> + <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir> + <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;_DEBUG;MSIUTIL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <AdditionalIncludeDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../../../windows-libraries/src/;$(ProjectDir)../</AdditionalIncludeDirectories> + <LanguageStandard>stdcpplatest</LanguageStandard> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/nsis/;$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories> + <AdditionalDependencies>msi.lib;log.lib;libcommon.lib;pluginapi-x86-unicode.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries> + <ModuleDefinitionFile>msiutil.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;NDEBUG;MSIUTIL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <AdditionalIncludeDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../../../windows-libraries/src/;$(ProjectDir)../</AdditionalIncludeDirectories> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <LanguageStandard>stdcpplatest</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/nsis/;$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories> + <AdditionalDependencies>msi.lib;log.lib;libcommon.lib;pluginapi-x86-unicode.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries> + <ModuleDefinitionFile>msiutil.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="stdafx.h" /> + <ClInclude Include="targetver.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp" /> + <ClCompile Include="msiutil.cpp" /> + <ClCompile Include="stdafx.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + </ClCompile> + </ItemGroup> + <ItemGroup> + <None Include="msiutil.def" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/windows/nsis-plugins/src/msiutil/msiutil.vcxproj.filters b/windows/nsis-plugins/src/msiutil/msiutil.vcxproj.filters new file mode 100644 index 0000000000..6c14c6af21 --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/msiutil.vcxproj.filters @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClInclude Include="stdafx.h" /> + <ClInclude Include="targetver.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp" /> + <ClCompile Include="stdafx.cpp" /> + <ClCompile Include="msiutil.cpp" /> + </ItemGroup> + <ItemGroup> + <None Include="msiutil.def" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/windows/nsis-plugins/src/msiutil/stdafx.cpp b/windows/nsis-plugins/src/msiutil/stdafx.cpp new file mode 100644 index 0000000000..3b6341d106 --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// driverlogic.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/windows/nsis-plugins/src/msiutil/stdafx.h b/windows/nsis-plugins/src/msiutil/stdafx.h new file mode 100644 index 0000000000..f3a07375c7 --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/stdafx.h @@ -0,0 +1,16 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include <windows.h> + + + +// TODO: reference additional headers your program requires here diff --git a/windows/nsis-plugins/src/msiutil/targetver.h b/windows/nsis-plugins/src/msiutil/targetver.h new file mode 100644 index 0000000000..ae4a5c032c --- /dev/null +++ b/windows/nsis-plugins/src/msiutil/targetver.h @@ -0,0 +1,12 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include <WinSDKVer.h> + +#define _WIN32_WINNT _WIN32_WINNT_WIN7 + +#include <SDKDDKVer.h> |
