summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-02-17 13:27:23 +0100
committerDavid Lönnhager <david.l@mullvad.net>2021-02-17 13:27:23 +0100
commiteb497836502753fca300f84dca9d810bf733ab7e (patch)
treeba3919abe53fbb2022396e77215527a25e450e98
parent9f1eeca0791459be6d62bfd7ea687fdfc4833dc8 (diff)
parentd513426b9d2b7d1616300d2ce6fdbf3e2dbb02c0 (diff)
downloadmullvadvpn-eb497836502753fca300f84dca9d810bf733ab7e.tar.xz
mullvadvpn-eb497836502753fca300f84dca9d810bf733ab7e.zip
Merge branch 'improve-KB2921916-check'
-rw-r--r--CHANGELOG.md1
-rw-r--r--dist-assets/windows/installer.nsh19
-rw-r--r--windows/nsis-plugins/nsis-plugins.sln9
-rw-r--r--windows/nsis-plugins/src/osinfo/dllmain.cpp11
-rw-r--r--windows/nsis-plugins/src/osinfo/osinfo.cpp45
-rw-r--r--windows/nsis-plugins/src/osinfo/osinfo.def5
-rw-r--r--windows/nsis-plugins/src/osinfo/osinfo.vcxproj124
-rw-r--r--windows/nsis-plugins/src/osinfo/osinfo.vcxproj.filters19
-rw-r--r--windows/nsis-plugins/src/osinfo/stdafx.cpp8
-rw-r--r--windows/nsis-plugins/src/osinfo/stdafx.h16
-rw-r--r--windows/nsis-plugins/src/osinfo/targetver.h12
-rw-r--r--windows/nsis-plugins/src/osinfo/update.cpp97
-rw-r--r--windows/nsis-plugins/src/osinfo/update.h11
13 files changed, 374 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 236800d178..c89daa4b0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -51,6 +51,7 @@ Line wrap the file at 100 chars. Th
#### Windows
- Fix failure when Wintun adapter name conflicts with that of a non-Wintun adapter.
+- Fix detection of SetupAPI patch when not installed by KB2921916.
## [2021.1] - 2021-02-10
diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh
index 7d30b158fe..6c8f32c2c0 100644
--- a/dist-assets/windows/installer.nsh
+++ b/dist-assets/windows/installer.nsh
@@ -22,6 +22,11 @@
!define MULLVAD_GENERAL_ERROR 0
!define MULLVAD_SUCCESS 1
+# Return codes for KB2921916 check
+!define PATCH_ERROR 0
+!define PATCH_PRESENT 1
+!define PATCH_MISSING 2
+
# Return codes from driverlogic
!define DL_ADAPTER_NOT_FOUND -2
!define DL_GENERAL_ERROR -1
@@ -89,15 +94,21 @@
log::Log "InstallWin7Hotfix()"
- nsExec::ExecToStack '"$SYSDIR\cmd.exe" /c ""$SYSDIR\wbem\wmic.exe" qfe get hotfixid | "$SYSDIR\find.exe" "KB2921916""'
+ osinfo::HasWindows7Sha2Fix
Pop $0
Pop $1
- ${If} $0 == 0
- log::Log "KB2921916 is already installed"
+ ${If} $0 == ${PATCH_PRESENT}
+ log::Log "KB2921916 is already installed or superseded"
Goto InstallWin7Hotfix_return_success
${EndIf}
+ ${If} $0 == ${PATCH_ERROR}
+ log::LogWithDetails "Detection of KB2921916 failed" $1
+ MessageBox MB_OK "Detection of KB2921916 failed"
+ Goto InstallWin7Hotfix_return_abort
+ ${EndIf}
+
MessageBox MB_ICONINFORMATION|MB_YESNO "Windows hotfix KB2921916 must be installed for this app to work. Continue?" IDNO InstallWin7Hotfix_return_abort
log::Log "Extracting KB2921916"
@@ -115,6 +126,8 @@
${If} $0 == 3010
MessageBox MB_OK "You may need to restart your computer for the patch to take effect."
${Else}
+ StrCpy $R0 "Failed to install the hotfix: error $0"
+ log::Log $R0
MessageBox MB_OK "Failed to install the hotfix."
Goto InstallWin7Hotfix_return_abort
${EndIf}
diff --git a/windows/nsis-plugins/nsis-plugins.sln b/windows/nsis-plugins/nsis-plugins.sln
index 487b4bebf4..102a73eb08 100644
--- a/windows/nsis-plugins/nsis-plugins.sln
+++ b/windows/nsis-plugins/nsis-plugins.sln
@@ -43,6 +43,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msiutil", "src\msiutil\msiu
{1344152F-2BAD-4198-8E51-31AAC32BFBB2} = {1344152F-2BAD-4198-8E51-31AAC32BFBB2}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osinfo", "src\osinfo\osinfo.vcxproj", "{5ECCC4BC-599B-4F49-8D8F-63A2CF64764F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@@ -81,6 +86,10 @@ Global
{83487059-2549-4DF9-A785-A4FD5211234B}.Debug|x86.Build.0 = Debug|Win32
{83487059-2549-4DF9-A785-A4FD5211234B}.Release|x86.ActiveCfg = Release|Win32
{83487059-2549-4DF9-A785-A4FD5211234B}.Release|x86.Build.0 = Release|Win32
+ {5ECCC4BC-599B-4F49-8D8F-63A2CF64764F}.Debug|x86.ActiveCfg = Debug|Win32
+ {5ECCC4BC-599B-4F49-8D8F-63A2CF64764F}.Debug|x86.Build.0 = Debug|Win32
+ {5ECCC4BC-599B-4F49-8D8F-63A2CF64764F}.Release|x86.ActiveCfg = Release|Win32
+ {5ECCC4BC-599B-4F49-8D8F-63A2CF64764F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/windows/nsis-plugins/src/osinfo/dllmain.cpp b/windows/nsis-plugins/src/osinfo/dllmain.cpp
new file mode 100644
index 0000000000..f11c65c519
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/dllmain.cpp
@@ -0,0 +1,11 @@
+#include "stdafx.h"
+#include <windows.h>
+
+BOOL APIENTRY DllMain(HMODULE, DWORD, LPVOID)
+{
+ //
+ // Avoid doing work in DllMain since the loader lock is held
+ //
+
+ return TRUE;
+}
diff --git a/windows/nsis-plugins/src/osinfo/osinfo.cpp b/windows/nsis-plugins/src/osinfo/osinfo.cpp
new file mode 100644
index 0000000000..f80a4b2b26
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/osinfo.cpp
@@ -0,0 +1,45 @@
+#include <stdafx.h>
+#include "../error.h"
+#include "update.h"
+#include <libcommon/string.h>
+#include <windows.h>
+#include <nsis/pluginapi.h>
+#include <functional>
+#include <vector>
+
+enum PatchStatus
+{
+ PATCH_ERROR = 0,
+ PATCH_PRESENT,
+ PATCH_MISSING
+};
+
+void __declspec(dllexport) NSISCALL HasWindows7Sha2Fix
+(
+ HWND hwndParent,
+ int string_size,
+ LPTSTR variables,
+ stack_t** stacktop,
+ extra_parameters* extra,
+ ...
+)
+{
+ EXDLL_INIT();
+
+ try
+ {
+ const auto success = update::HasSetupApiSha2Fix();
+ pushstring(L"");
+ pushint(success ? PatchStatus::PATCH_PRESENT : PatchStatus::PATCH_MISSING);
+ }
+ catch (const std::exception& err)
+ {
+ pushstring(common::string::ToWide(err.what()).c_str());
+ pushint(PatchStatus::PATCH_ERROR);
+ }
+ catch (...)
+ {
+ pushstring(L"Unspecified error");
+ pushint(PatchStatus::PATCH_ERROR);
+ }
+}
diff --git a/windows/nsis-plugins/src/osinfo/osinfo.def b/windows/nsis-plugins/src/osinfo/osinfo.def
new file mode 100644
index 0000000000..ec18cc35e8
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/osinfo.def
@@ -0,0 +1,5 @@
+LIBRARY osinfo
+
+EXPORTS
+
+HasWindows7Sha2Fix
diff --git a/windows/nsis-plugins/src/osinfo/osinfo.vcxproj b/windows/nsis-plugins/src/osinfo/osinfo.vcxproj
new file mode 100644
index 0000000000..6935bdb2a7
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/osinfo.vcxproj
@@ -0,0 +1,124 @@
+<?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>{5ECCC4BC-599B-4F49-8D8F-63A2CF64764F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>osinfo</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;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../../../windows-libraries/src/</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>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>osinfo.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;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(ProjectDir)../../../../dist-assets/binaries/x86_64-pc-windows-msvc/;$(ProjectDir)../../../windows-libraries/src/</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>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>osinfo.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="update.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="update.cpp" />
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="osinfo.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="osinfo.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/osinfo/osinfo.vcxproj.filters b/windows/nsis-plugins/src/osinfo/osinfo.vcxproj.filters
new file mode 100644
index 0000000000..6b31d70d05
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/osinfo.vcxproj.filters
@@ -0,0 +1,19 @@
+<?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" />
+ <ClInclude Include="cleaningops.h" />
+ <ClInclude Include="os.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="os.cpp" />
+ <ClCompile Include="stdafx.cpp" />
+ <ClCompile Include="cleaningops.cpp" />
+ <ClCompile Include="os.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="os.def" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/windows/nsis-plugins/src/osinfo/stdafx.cpp b/windows/nsis-plugins/src/osinfo/stdafx.cpp
new file mode 100644
index 0000000000..3b6341d106
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/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/osinfo/stdafx.h b/windows/nsis-plugins/src/osinfo/stdafx.h
new file mode 100644
index 0000000000..f3a07375c7
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/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/osinfo/targetver.h b/windows/nsis-plugins/src/osinfo/targetver.h
new file mode 100644
index 0000000000..ae4a5c032c
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/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/nsis-plugins/src/osinfo/update.cpp b/windows/nsis-plugins/src/osinfo/update.cpp
new file mode 100644
index 0000000000..4f33310236
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/update.cpp
@@ -0,0 +1,97 @@
+#include <stdafx.h>
+#include "update.h"
+#include <libcommon/error.h>
+#include <libcommon/filesystem.h>
+#include <libcommon/memory.h>
+#include <algorithm>
+#include <fstream>
+#include <filesystem>
+
+namespace
+{
+
+// Jason found this to be a reliable marker of the signature check fix:
+// https://git.zx2c4.com/wireguard-windows/tree/installer/customactions.c#n145
+const char PATCH_MARKER[] = "Signature Hash";
+
+}
+
+namespace update
+{
+
+bool HasSetupApiSha2Fix()
+{
+ common::memory::ScopeDestructor destructor;
+
+ common::fs::ScopedNativeFileSystem nativeFileSystem;
+
+ const auto systemDir = common::fs::GetKnownFolderPath(FOLDERID_System, KF_FLAG_DEFAULT, NULL);
+ const auto setupApiPath = std::filesystem::path(systemDir).append(L"setupapi.dll");
+
+ const auto setupApiHandle = CreateFileW(
+ setupApiPath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ nullptr,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ nullptr
+ );
+
+ if (INVALID_HANDLE_VALUE == setupApiHandle)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "CreateFileW");
+ }
+
+ destructor += [=]() {
+ CloseHandle(setupApiHandle);
+ };
+
+ const auto mapping = CreateFileMappingW(setupApiHandle, nullptr, PAGE_READONLY, 0, 0, nullptr);
+
+ if (nullptr == mapping)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "CreateFileMappingW");
+ }
+
+ destructor += [=]() {
+ CloseHandle(mapping);
+ };
+
+ const auto bytes = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+
+ if (nullptr == bytes)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "MapViewOfFile");
+ }
+
+ destructor += [=]() {
+ UnmapViewOfFile(bytes);
+ };
+
+ MEMORY_BASIC_INFORMATION meminfo;
+
+ if (0 == VirtualQuery(bytes, &meminfo, sizeof(meminfo)))
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "VirtualQuery");
+ }
+
+ constexpr auto PATCH_MARKER_SIZE = sizeof(PATCH_MARKER) - 1;
+
+ if (meminfo.RegionSize < PATCH_MARKER_SIZE)
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i <= meminfo.RegionSize - PATCH_MARKER_SIZE; i++)
+ {
+ if (0 == memcmp((void*)((char*)bytes + i), PATCH_MARKER, PATCH_MARKER_SIZE))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+}
diff --git a/windows/nsis-plugins/src/osinfo/update.h b/windows/nsis-plugins/src/osinfo/update.h
new file mode 100644
index 0000000000..ae33258b56
--- /dev/null
+++ b/windows/nsis-plugins/src/osinfo/update.h
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace update
+{
+
+// Checks whether SHA-2 signatures can be verified correctly
+// on Windows 7. Without this patch, the driver cannot be
+// installed from a service.
+bool HasSetupApiSha2Fix();
+
+}