diff options
| author | David Lönnhager <david.l@mullvad.net> | 2019-10-03 17:54:57 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2019-10-03 17:54:57 +0200 |
| commit | 49cbb178cf7b775a6352b311867d1f01d2eca274 (patch) | |
| tree | caace7bbd49b05ea1606525a158f2288349c771d /windows | |
| parent | 14bbfaa52ad1b3bfd2917d0aa79ce7a4dacfc9cd (diff) | |
| parent | 7f8496df28ce29dad6fc2a4f785f43a816995f0f (diff) | |
| download | mullvadvpn-49cbb178cf7b775a6352b311867d1f01d2eca274.tar.xz mullvadvpn-49cbb178cf7b775a6352b311867d1f01d2eca274.zip | |
Merge branch 'winpathfix'
Diffstat (limited to 'windows')
| -rw-r--r-- | windows/nsis-plugins/nsis-plugins.sln | 6 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/dllmain.cpp | 11 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/pathedit.cpp | 214 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/pathedit.def | 6 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/pathedit.vcxproj | 122 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/pathedit.vcxproj.filters | 15 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/stdafx.cpp | 8 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/stdafx.h | 16 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/pathedit/targetver.h | 12 | ||||
| m--------- | windows/windows-libraries | 0 |
10 files changed, 410 insertions, 0 deletions
diff --git a/windows/nsis-plugins/nsis-plugins.sln b/windows/nsis-plugins/nsis-plugins.sln index fdcf8eed34..6c2499cf4d 100644 --- a/windows/nsis-plugins/nsis-plugins.sln +++ b/windows/nsis-plugins/nsis-plugins.sln @@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tray", "src\tray\tray.vcxpr {1344152F-2BAD-4198-8E51-31AAC32BFBB2} = {1344152F-2BAD-4198-8E51-31AAC32BFBB2} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pathedit", "src\pathedit\pathedit.vcxproj", "{EF53BD9F-6D69-42BB-8635-958531776283}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -61,6 +63,10 @@ Global {E3E05654-D5D6-4D39-A9B4-BB14B012C5FF}.Debug|x86.Build.0 = Debug|Win32 {E3E05654-D5D6-4D39-A9B4-BB14B012C5FF}.Release|x86.ActiveCfg = Release|Win32 {E3E05654-D5D6-4D39-A9B4-BB14B012C5FF}.Release|x86.Build.0 = Release|Win32 + {EF53BD9F-6D69-42BB-8635-958531776283}.Debug|x86.ActiveCfg = Debug|Win32 + {EF53BD9F-6D69-42BB-8635-958531776283}.Debug|x86.Build.0 = Debug|Win32 + {EF53BD9F-6D69-42BB-8635-958531776283}.Release|x86.ActiveCfg = Release|Win32 + {EF53BD9F-6D69-42BB-8635-958531776283}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/windows/nsis-plugins/src/pathedit/dllmain.cpp b/windows/nsis-plugins/src/pathedit/dllmain.cpp new file mode 100644 index 0000000000..a5a44613dd --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/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/pathedit/pathedit.cpp b/windows/nsis-plugins/src/pathedit/pathedit.cpp new file mode 100644 index 0000000000..fda83d779e --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/pathedit.cpp @@ -0,0 +1,214 @@ +// pathedit.cpp : Defines the exported functions for the DLL application. +// + +#include "stdafx.h" +#include <windows.h> +#include <libcommon/string.h> +#include <libcommon/registry/registry.h> +#include <libcommon/registry/registrypath.h> +#include <libcommon/registry/registrykey.h> +#include <libcommon/error.h> +#include <nsis/pluginapi.h> +#include <string> + +// Suppress warnings caused by broken legacy code +#pragma warning (push) +#pragma warning (disable: 4005) +#include <nsis/pluginapi.h> +#pragma warning (pop) + +using namespace common::registry; +using ValueStringType = RegistryKey::ValueStringType; +using common::string::Lower; + +static const wchar_t pathKeyName[] = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"; +static const wchar_t pathValName[] = L"Path"; + +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; +} + +std::vector<std::wstring>::const_iterator FindSysPath(const std::vector<std::wstring> &pathTokens, const std::wstring &path) +{ + const std::wstring lowerPath = Lower(path); + + return std::find_if( + pathTokens.begin(), + pathTokens.end(), + [&lowerPath](const std::wstring &elem) + { + return Lower(elem).compare(lowerPath) == 0; + } + ); +} + +bool SysPathExists(const std::wstring &allPaths, const std::wstring &pathToFind) +{ + auto pathTokens = common::string::Tokenize(allPaths, L";"); + return FindSysPath(pathTokens, pathToFind) != pathTokens.end(); +} +} // anonymous namespace + +// +// AddSysEnvPath "path" +// +// Adds "path" to the system PATH environment variable, +// or does nothing if it already exists. +// +// Example usage: +// +// AddSysEnvPath "C:\path\to\directory" +// + +enum class EnvPathStatus +{ + GENERAL_ERROR = 0, + SUCCESS +}; + +void __declspec(dllexport) NSISCALL AddSysEnvPath +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + const auto pathToAppend = PopString(); + + auto pathRegKey = Registry::OpenKey( + HKEY_LOCAL_MACHINE, + pathKeyName, + true, + RegistryView::Force64 + ); + auto path = pathRegKey->readString(pathValName, ValueStringType::ExpandableString); + + if (SysPathExists(path, pathToAppend)) + { + pushstring(L""); + pushint(EnvPathStatus::SUCCESS); + return; + } + + if (!path.empty()) + { + path.append(L";"); + } + path.append(pathToAppend); + + pathRegKey->writeValue(pathValName, path, ValueStringType::ExpandableString); + + THROW_GLE_IF( + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"Environment"), + 0, + "SendNotifyMessage" + ); + + pushstring(L""); + pushint(EnvPathStatus::SUCCESS); + } + catch (const std::exception &err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(EnvPathStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(EnvPathStatus::GENERAL_ERROR); + } +} + +// +// RemoveSysEnvPath "path" +// +// Removes "path" to the system PATH environment variable, +// or does nothing if it doesn't exist. +// +// Example usage: +// +// RemoveSysEnvPath "C:\path\to\directory" +// + +void __declspec(dllexport) NSISCALL RemoveSysEnvPath +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + const auto pathToRemove = PopString(); + + auto pathRegKey = Registry::OpenKey( + HKEY_LOCAL_MACHINE, + pathKeyName, + true, + RegistryView::Force64 + ); + auto path = pathRegKey->readString(pathValName, ValueStringType::ExpandableString); + + // remove value if it exists in PATH + auto pathTokens = common::string::Tokenize(path, L";"); + auto match = FindSysPath(pathTokens, pathToRemove); + if (match != pathTokens.end()) + { + pathTokens.erase(match); + path = common::string::Join(pathTokens, L";"); + pathRegKey->writeValue(pathValName, path, ValueStringType::ExpandableString); + + THROW_GLE_IF( + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"Environment"), + 0, + "SendNotifyMessage" + ); + } + + pushstring(L""); + pushint(EnvPathStatus::SUCCESS); + } + catch (const std::exception &err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(EnvPathStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(EnvPathStatus::GENERAL_ERROR); + } +} diff --git a/windows/nsis-plugins/src/pathedit/pathedit.def b/windows/nsis-plugins/src/pathedit/pathedit.def new file mode 100644 index 0000000000..44cbd573f0 --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/pathedit.def @@ -0,0 +1,6 @@ +LIBRARY pathedit + +EXPORTS + +AddSysEnvPath +RemoveSysEnvPath diff --git a/windows/nsis-plugins/src/pathedit/pathedit.vcxproj b/windows/nsis-plugins/src/pathedit/pathedit.vcxproj new file mode 100644 index 0000000000..b69cd1e62c --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/pathedit.vcxproj @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.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>15.0</VCProjectVersion> + <ProjectGuid>{EF53BD9F-6D69-42BB-8635-958531776283}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>pathedit</RootNamespace> + <WindowsTargetPlatformVersion>10.0.16299.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>v141</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</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;PATHEDIT_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>iphlpapi.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>pathedit.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;PATHEDIT_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>iphlpapi.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>pathedit.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="stdafx.h" /> + <ClInclude Include="targetver.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp" /> + <ClCompile Include="pathedit.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="pathedit.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/pathedit/pathedit.vcxproj.filters b/windows/nsis-plugins/src/pathedit/pathedit.vcxproj.filters new file mode 100644 index 0000000000..7fc25a5247 --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/pathedit.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="pathedit.cpp" /> + </ItemGroup> + <ItemGroup> + <None Include="pathedit.def" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/windows/nsis-plugins/src/pathedit/stdafx.cpp b/windows/nsis-plugins/src/pathedit/stdafx.cpp new file mode 100644 index 0000000000..3b6341d106 --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/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/pathedit/stdafx.h b/windows/nsis-plugins/src/pathedit/stdafx.h new file mode 100644 index 0000000000..f3a07375c7 --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/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/pathedit/targetver.h b/windows/nsis-plugins/src/pathedit/targetver.h new file mode 100644 index 0000000000..ae4a5c032c --- /dev/null +++ b/windows/nsis-plugins/src/pathedit/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> diff --git a/windows/windows-libraries b/windows/windows-libraries -Subproject ca2c530673c4cfe1dfbafe115508fe3ba284e34 +Subproject 57b2caeaae9d1250070a951e3dff25c029cce97 |
