aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--.editorconfig4
-rw-r--r--.gitignore3
-rw-r--r--installer/exports.def5
-rw-r--r--installer/installation.c654
-rw-r--r--installer/installation.h23
-rw-r--r--installer/installer.vcxproj194
-rw-r--r--installer/installer.vcxproj.filters52
-rw-r--r--installer/installer.wixproj (renamed from wintun.wixproj)47
-rw-r--r--installer/installer.wxs51
-rw-r--r--installer/msi.c266
-rw-r--r--installer/resources.rc48
-rw-r--r--installer/rundll32.c160
-rw-r--r--wintun.c6
-rw-r--r--wintun.proj30
-rw-r--r--wintun.props25
-rw-r--r--wintun.rcbin1892 -> 1073 bytes
-rw-r--r--wintun.sln25
-rw-r--r--wintun.vcxproj15
-rw-r--r--wintun.vcxproj.filters2
-rw-r--r--wintun.wxs136
21 files changed, 1552 insertions, 196 deletions
diff --git a/.clang-format b/.clang-format
index c7d38ff..a77c201 100644
--- a/.clang-format
+++ b/.clang-format
@@ -98,7 +98,7 @@ StatementMacros: [
'__drv_preferredFunction',
'__drv_allocatesMem',
'__drv_freesMem',
- '_Field_size_bytes_',
+ '_Field_size_bytes_',
'_Function_class_',
'_Dispatch_type_'
]
diff --git a/.editorconfig b/.editorconfig
index 6eee1a2..15595b4 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,7 +1,7 @@
-[*.{c,h,inf,rc,wxs}]
+[*.{c,h,inf,rc}]
indent_style = space
indent_style = 4
-[*.{proj,props,vcxproj,wixproj}]
+[*.{proj,props,vcxproj,wixproj,wxs}]
indent_style = space
indent_size = 2
diff --git a/.gitignore b/.gitignore
index fc1043b..7db1686 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,6 @@
# Driver Verification Log
/wintun.DVL.XML
+
+# Temporary files
+*~
diff --git a/installer/exports.def b/installer/exports.def
new file mode 100644
index 0000000..95eafde
--- /dev/null
+++ b/installer/exports.def
@@ -0,0 +1,5 @@
+EXPORTS
+ InstallWintun
+ UninstallWintun
+ MsiEvaluate
+ MsiProcess
diff --git a/installer/installation.c b/installer/installation.c
new file mode 100644
index 0000000..b0644a4
--- /dev/null
+++ b/installer/installation.c
@@ -0,0 +1,654 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#include "installation.h"
+#include <Windows.h>
+#include <NTSecAPI.h>
+#include <SetupAPI.h>
+#include <newdev.h>
+#include <Shlwapi.h>
+#include <Psapi.h>
+#include <sddl.h>
+#include <devguid.h>
+#include <ndisguid.h>
+#include <cfgmgr32.h>
+#include <WinCrypt.h>
+#include <tchar.h>
+#include <stdio.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 */
+
+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 IsWintunLoaded(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 MaybeWintun[11];
+ for (DWORD i = CurrentSize / sizeof(Drivers[0]); i-- > 0;)
+ {
+ if (GetDeviceDriverBaseName(Drivers[i], MaybeWintun, _countof(MaybeWintun)) == 10 &&
+ !_tcsicmp(MaybeWintun, TEXT("wintun.sys")))
+ {
+ Found = TRUE;
+ goto out;
+ }
+ }
+out:
+ free(Drivers);
+ return Found;
+}
+
+static BOOL EnsureWintunUnloaded(VOID)
+{
+ BOOL Loaded;
+ for (int i = 0; (Loaded = IsWintunLoaded()) != 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
+InstallWintunCertificate(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
+InstallWintun(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("wintun.cat")))
+ goto cleanupFree;
+ TCHAR SysPath[MAX_PATH] = { 0 };
+ if (!PathCombine(SysPath, RandomTempSubDirectory, TEXT("wintun.sys")))
+ goto cleanupFree;
+ TCHAR InfPath[MAX_PATH] = { 0 };
+ if (!PathCombine(InfPath, RandomTempSubDirectory, TEXT("wintun.inf")))
+ goto cleanupFree;
+
+ BOOL UseWHQL = FALSE;
+#ifdef HAVE_WHQL
+ DWORD MajorVersion;
+ RtlGetNtVersionNumbers(&MajorVersion, NULL, NULL);
+ UseWHQL = MajorVersion >= 10;
+#endif
+ if (!UseWHQL && !InstallWintunCertificate(TEXT("wintun.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("wintun-whql.cat") : TEXT("wintun.cat")) &&
+ CopyResource(SysPath, &SecurityAttributes, UseWHQL ? TEXT("wintun-whql.sys") : TEXT("wintun.sys")) &&
+ CopyResource(InfPath, &SecurityAttributes, UseWHQL ? TEXT("wintun-whql.inf") : TEXT("wintun.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("Wintun"), 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, which really should not be the case"));
+
+cleanupDelete:
+ LastError = LastError ? LastError : GetLastError();
+ DeleteFile(CatPath);
+ DeleteFile(SysPath);
+ DeleteFile(InfPath);
+ RemoveDirectory(RandomTempSubDirectory);
+cleanupFree:
+ LastError = LastError ? LastError : GetLastError();
+ LocalFree(SecurityAttributes.lpSecurityDescriptor);
+ SetLastError(LastError);
+ return Ret;
+}
+
+static BOOL RemoveWintun(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("wintun")))
+ {
+ 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
+IsWintunAdapter(_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("wintun")))
+ {
+ free(DriverDetail);
+ Found = TRUE;
+ break;
+ }
+ free(DriverDetail);
+ }
+ SetupDiDestroyDriverInfoList(DeviceInfoSet, DeviceInfo, SPDIT_COMPATDRIVER);
+ return Found;
+}
+
+#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
+
+static BOOL
+ForceCloseWintunAdapterHandle(_In_ HDEVINFO DeviceInfoSet, _In_ SP_DEVINFO_DATA *DeviceInfo)
+{
+ DWORD RequiredBytes;
+ if (SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfo, NULL, 0, &RequiredBytes) ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ return FALSE;
+ TCHAR *InstanceId = calloc(sizeof(*InstanceId), RequiredBytes);
+ if (!InstanceId)
+ return FALSE;
+ if (!SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfo, InstanceId, RequiredBytes, &RequiredBytes))
+ return FALSE;
+ TCHAR *InterfaceList = NULL;
+ for (;;)
+ {
+ free(InterfaceList);
+ if (CM_Get_Device_Interface_List_Size(
+ &RequiredBytes, (LPGUID)&GUID_DEVINTERFACE_NET, InstanceId, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) !=
+ CR_SUCCESS)
+ return FALSE;
+ InterfaceList = calloc(sizeof(*InterfaceList), RequiredBytes);
+ if (!InterfaceList)
+ return FALSE;
+ CONFIGRET Ret = CM_Get_Device_Interface_List(
+ (LPGUID)&GUID_DEVINTERFACE_NET,
+ InstanceId,
+ InterfaceList,
+ RequiredBytes,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
+ if (Ret == CR_SUCCESS)
+ break;
+ if (Ret != CR_BUFFER_SMALL)
+ return FALSE;
+ }
+
+ HANDLE NdisHandle = CreateFile(
+ InterfaceList,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ free(InterfaceList);
+ if (NdisHandle == INVALID_HANDLE_VALUE)
+ return FALSE;
+ BOOL Ret = DeviceIoControl(NdisHandle, TUN_IOCTL_FORCE_CLOSE_HANDLES, NULL, 0, NULL, 0, &RequiredBytes, NULL);
+ DWORD LastError = GetLastError();
+ CloseHandle(NdisHandle);
+ SetLastError(LastError);
+ return Ret;
+}
+
+static BOOL
+DisableWintunAdapters(_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 (!IsWintunAdapter(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("Force closing all open handles for existing adapter"));
+ if (!ForceCloseWintunAdapterHandle(DeviceInfoSet, &DeviceNode->Data))
+ PrintError(LOG_WARN, TEXT("Failed to force close adapter handles"));
+ Sleep(200);
+
+ 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
+RemoveWintunAdapters(_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 (!IsWintunAdapter(DeviceInfoSet, &DeviceInfo))
+ continue;
+
+ Logger(LOG_INFO, TEXT("Force closing all open handles for existing adapter"));
+ if (!ForceCloseWintunAdapterHandle(DeviceInfoSet, &DeviceInfo))
+ PrintError(LOG_WARN, TEXT("Failed to force close adapter handles"));
+ Sleep(200);
+
+ 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
+EnableWintunAdapters(_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 (IsWintunLoaded())
+ {
+ DisableWintunAdapters(DeviceInfoSet, &ExistingAdapters);
+ Logger(LOG_INFO, TEXT("Waiting for driver to unload from kernel"));
+ if (!EnsureWintunUnloaded())
+ Logger(LOG_WARN, TEXT("Unable to unload driver, which means a reboot will likely be required"));
+ }
+ if (!RemoveWintun())
+ {
+ PrintError(LOG_ERR, TEXT("Failed to uninstall old drivers"));
+ goto cleanupAdapters;
+ }
+ if (!InstallWintun(!!ExistingAdapters))
+ {
+ PrintError(LOG_ERR, TEXT("Failed to install driver"));
+ goto cleanupAdapters;
+ }
+ Logger(LOG_INFO, TEXT("Installation successful"));
+ Ret = TRUE;
+
+cleanupAdapters:
+ if (ExistingAdapters)
+ {
+ EnableWintunAdapters(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;
+ }
+ RemoveWintunAdapters(DeviceInfoSet);
+ BOOL Ret = RemoveWintun();
+ if (!Ret)
+ PrintError(LOG_ERR, TEXT("Failed to uninstall driver"));
+ else
+ Logger(LOG_INFO, TEXT("Uninstallation successful"));
+ return Ret;
+}
+
+BOOL APIENTRY
+DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ ResourceModule = hinstDLL;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+} \ No newline at end of file
diff --git a/installer/installation.h b/installer/installation.h
new file mode 100644
index 0000000..e5ce781
--- /dev/null
+++ b/installer/installation.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#pragma once
+
+#include <Windows.h>
+
+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/installer/installer.vcxproj b/installer/installer.vcxproj
new file mode 100644
index 0000000..306f05f
--- /dev/null
+++ b/installer/installer.vcxproj
@@ -0,0 +1,194 @@
+<?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|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <ProjectGuid>{D19E6354-A643-4ACC-82D5-B2780BB83475}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>installer</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+ <ProjectName>installer</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <SpectreMitigation>false</SpectreMitigation>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <SpectreMitigation>false</SpectreMitigation>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <SpectreMitigation>false</SpectreMitigation>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <SpectreMitigation>false</SpectreMitigation>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </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" />
+ <Import Project="..\wintun.props" />
+ </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" />
+ <Import Project="..\wintun.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\wintun.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\wintun.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\wintun.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\wintun.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <OutDir>..\$(WintunPlatform)\$(Configuration)\</OutDir>
+ <IntDir>..\$(WintunPlatform)\$(Configuration)\installer-intermediate\</IntDir>
+ <CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <LocalDebuggerCommand>rundll32.exe</LocalDebuggerCommand>
+ <LocalDebuggerCommandArguments>..\$(WintunPlatform)\$(Configuration)\installer.dll,InstallWintun</LocalDebuggerCommandArguments>
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PreprocessorDefinitions>_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="Exists('..\$(WintunPlatform)\$(Configuration)\whql\')">HAVE_WHQL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>..\$(WintunPlatform)\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="Exists('..\$(WintunPlatform)\$(Configuration)\whql\')">HAVE_WHQL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ <AdditionalDependencies>newdev.lib;ntdll.lib;Crypt32.lib;Msi.lib;Setupapi.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
+ <ClCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
+ <ClCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
+ <ItemGroup>
+ <ClCompile Include="installation.c" />
+ <ClCompile Include="msi.c" />
+ <ClCompile Include="rundll32.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resources.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="installation.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="exports.def" />
+ <None Include="installer.wixproj" />
+ <None Include="installer.wxs" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+ <Import Project="..\wintun.vcxproj.user" Condition="exists('..\wintun.vcxproj.user')" />
+ <PropertyGroup>
+ <SigningCertificate Condition="$(SignMode)=='TestSign' And '$(TestCertificate)'!=''">$(TestCertificate)</SigningCertificate>
+ <SigningCertificate Condition="$(SignMode)=='ProductionSign' And '$(ProductionCertificate)'!=''">$(ProductionCertificate)</SigningCertificate>
+ <BuildDependsOn Condition="'$(SigningCertificate)'!='' And '$(TimeStampServer)'!=''">$(BuildDependsOn);SignTarget</BuildDependsOn>
+ <CleanDependsOn>CleanSignTarget;$(CleanDependsOn)</CleanDependsOn>
+ </PropertyGroup>
+ <Target Name="SignTarget" Inputs="$(TargetPath)" Outputs="$(IntermediateOutputPath)$(TargetName).sign">
+ <Exec Command="signtool.exe sign /sha1 &quot;$(SigningCertificate)&quot; /fd sha256 /tr &quot;$(TimeStampServer)&quot; /td sha256 &quot;$(TargetPath)&quot;" />
+ <Touch Files="$(IntermediateOutputPath)$(TargetName).sign" AlwaysCreate="true" />
+ </Target>
+ <Target Name="CleanSignTarget">
+ <Delete Files="$(IntermediateOutputPath)$(TargetName).sign" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/installer/installer.vcxproj.filters b/installer/installer.vcxproj.filters
new file mode 100644
index 0000000..bfbd0ec
--- /dev/null
+++ b/installer/installer.vcxproj.filters
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="MSM">
+ <UniqueIdentifier>{1ae72c39-669d-49e5-85c7-f6956595e079}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="msi.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="installation.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="rundll32.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resources.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="installation.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="exports.def">
+ <Filter>Source Files</Filter>
+ </None>
+ <None Include="installer.wixproj">
+ <Filter>MSM</Filter>
+ </None>
+ <None Include="installer.wxs">
+ <Filter>MSM</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/wintun.wixproj b/installer/installer.wixproj
index 7e8c7f2..69b40a6 100644
--- a/wintun.wixproj
+++ b/installer/installer.wixproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-License-Identifier: GPL-2.0
@@ -7,7 +7,7 @@
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0"
- InitialTargets="EnsureWixToolsetInstalled"
+ InitialTargets="EnsureWixToolsetInstalled;HashInstallerLibrary"
DefaultTargets="Build">
<PropertyGroup>
<Configuration Condition="'$(Configuration)'==''">Release</Configuration>
@@ -18,42 +18,26 @@
<DefineSolutionProperties>false</DefineSolutionProperties>
</PropertyGroup>
- <Import Project="wintun.props"/>
+ <Import Project="..\wintun.props"/>
<PropertyGroup>
- <IntermediateOutputPath>$(WintunPlatform)\$(Configuration)\</IntermediateOutputPath>
- <OutputPath>$(WintunPlatform)\$(Configuration)\</OutputPath>
+ <IntermediateOutputPath>..\$(WintunPlatform)\$(Configuration)\</IntermediateOutputPath>
+ <OutputPath>..\$(WintunPlatform)\$(Configuration)\</OutputPath>
<OutputName>$(ProjectName)</OutputName>
<DefineConstants>WINTUN_VERSION=$(WintunVersion);$(DefineConstants)</DefineConstants>
<SuppressSpecificWarnings>1006;1086;$(SuppressSpecificWarnings)</SuppressSpecificWarnings>
- <LinkerSuppressSpecificWarnings>1103;$(LinkerSuppressSpecificWarnings)</LinkerSuppressSpecificWarnings>
- <SuppressIces>ICE30;$(SuppressIces)</SuppressIces>
- <LinkerAdditionalOptions>-b output_dir="$(IntermediateOutputPath.TrimEnd('\'))" -b whql_dir="$(WintunPlatform)\$(Configuration)\whql" $(LinkerAdditionalOptions)</LinkerAdditionalOptions>
+ <LinkerSuppressSpecificWarnings>1079;1103;$(LinkerSuppressSpecificWarnings)</LinkerSuppressSpecificWarnings>
+ <SuppressIces>ICE30;ICE49;$(SuppressIces)</SuppressIces>
+ <LinkerAdditionalOptions>-b output_dir="$(IntermediateOutputPath.TrimEnd('\'))" $(LinkerAdditionalOptions)</LinkerAdditionalOptions>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<SuppressPdbOutput>true</SuppressPdbOutput>
- <OutputPath>$(DistributionDir)</OutputPath>
+ <OutputPath>..\$(DistributionDir)</OutputPath>
<OutputName>$(ProjectName)-$(WintunPlatform)-$(WintunVersionStr)</OutputName>
</PropertyGroup>
<ItemGroup>
- <Compile Include="wintun.wxs"/>
- </ItemGroup>
- <ItemGroup>
- <WixExtension Include="WixDifxAppExtension">
- <HintPath>$(WixExtDir)\WixDifxAppExtension.dll</HintPath>
- <Name>WixDifxAppExtension</Name>
- </WixExtension>
- <WixExtension Include="WixIIsExtension">
- <HintPath>$(WixExtDir)\WixIIsExtension.dll</HintPath>
- <Name>WixIIsExtension</Name>
- </WixExtension>
- </ItemGroup>
- <ItemGroup>
- <WixLibrary Include="difxapp_$(Platform).wixlib">
- <HintPath>$(WixExtDir)\difxapp_$(Platform).wixlib</HintPath>
- <Name>difxapp</Name>
- </WixLibrary>
+ <Compile Include="installer.wxs"/>
</ItemGroup>
<Import Project="$(MSBuildProjectName).user" Condition="exists('$(MSBuildProjectName).user')"/>
@@ -63,7 +47,16 @@
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/"/>
</Target>
- <Import Project="wintun.vcxproj.user" Condition="exists('wintun.vcxproj.user')"/>
+ <Target Name="HashInstallerLibrary">
+ <GetFileHash Files="$(IntermediateOutputPath)installer.dll" Algorithm="SHA256" HashEncoding="hex">
+ <Output TaskParameter="Items" ItemName="InstallerLibraryHash"/>
+ </GetFileHash>
+ <PropertyGroup>
+ <DefineConstants>$(DefineConstants);INSTALLER_LIBRARY_HASH=@(InstallerLibraryHash->Metadata('FileHash'));INSTALLER_LIBRARY_TIME=$([System.IO.File]::GetLastWriteTime('$(IntermediateOutputPath)installer.dll').Ticks)</DefineConstants>
+ </PropertyGroup>
+ </Target>
+
+ <Import Project="..\wintun.vcxproj.user" Condition="exists('..\wintun.vcxproj.user')"/>
<PropertyGroup>
<SigningCertificate Condition="$(SignMode)=='TestSign' And '$(TestCertificate)'!=''">$(TestCertificate)</SigningCertificate>
<SigningCertificate Condition="$(SignMode)=='ProductionSign' And '$(ProductionCertificate)'!=''">$(ProductionCertificate)</SigningCertificate>
diff --git a/installer/installer.wxs b/installer/installer.wxs
new file mode 100644
index 0000000..f5627dd
--- /dev/null
+++ b/installer/installer.wxs
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ SPDX-License-Identifier: GPL-2.0
+
+ Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+-->
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+ <Module Id="wintun" Language="0" Version="$(var.WINTUN_VERSION)">
+ <Package
+ Id="c28309d9-1954-4f2d-a7d1-228850092460"
+ Description="Wintun Userspace Tunnel"
+ Manufacturer="WireGuard LLC"
+ InstallerVersion="200"
+ InstallPrivileges="elevated"
+ InstallScope="perMachine"
+ ReadOnly="yes"/>
+
+ <Directory Id="TARGETDIR" Name="SourceDir">
+ <Component Guid="b668d4c7-abb3-485a-b8df-d34200489a43">
+ <RegistryValue
+ Root="HKLM"
+ Key="SOFTWARE\Wintun"
+ Type="integer"
+ Value="1"
+ KeyPath="yes"/>
+ </Component>
+ </Directory>
+
+ <Property Id="WintunInstallerHash" Value="$(var.INSTALLER_LIBRARY_HASH)" SuppressModularization="yes"/>
+ <Property Id="WintunInstallerBuildtime" Value="$(var.INSTALLER_LIBRARY_TIME)" SuppressModularization="yes"/>
+ <Property Id="WintunVersion" Value="$(var.WINTUN_VERSION)" SuppressModularization="yes"/>
+
+ <Binary Id="installer.dll" SourceFile="!(bindpath.output_dir)installer.dll"/>
+ <CustomAction Id="EvaluateWintun" SuppressModularization="yes" BinaryKey="installer.dll" DllEntry="MsiEvaluate" Execute="immediate" />
+ <CustomAction Id="ProcessWintun" SuppressModularization="yes" BinaryKey="installer.dll" DllEntry="MsiProcess" Execute="deferred" Impersonate="no" />
+ <InstallExecuteSequence>
+ <Custom Action="EvaluateWintun" After="CostFinalize"/>
+ <Custom Action="ProcessWintun" After="InstallFiles"/>
+ </InstallExecuteSequence>
+
+ <?if $(var.Platform) = "x86"?>
+ <CustomAction Id="WoW64Unsupported" Error="You are attempting to install the 32-bit variant of [ProductName] on a 64-bit operating system, which is not supported. Please install the 64-bit variant instead."/>
+ <InstallExecuteSequence>
+ <Custom Action="WoW64Unsupported" After="LaunchConditions"><![CDATA[VersionNT64]]></Custom>
+ </InstallExecuteSequence>
+ <InstallUISequence>
+ <Custom Action="WoW64Unsupported" After="LaunchConditions"><![CDATA[VersionNT64]]></Custom>
+ </InstallUISequence>
+ <?endif?>
+ </Module>
+</Wix>
diff --git a/installer/msi.c b/installer/msi.c
new file mode 100644
index 0000000..348ef42
--- /dev/null
+++ b/installer/msi.c
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#include "installation.h"
+#include <Windows.h>
+#include <Msi.h>
+#include <MsiQuery.h>
+#include <tchar.h>
+
+#pragma warning(disable : 4100) /* unreferenced formal parameter */
+
+static MSIHANDLE MsiHandle;
+
+#define ANCHOR_COMPONENT TEXT("{B668D4C7-ABB3-485A-B8DF-D34200489A43}")
+#define PROCESS_ACTION TEXT("ProcessWintun")
+#define ACTION_INSTALL TEXT("/WintunAction=Install")
+#define ACTION_INSTALL_SEPERATOR TEXT('-')
+#define ACTION_INSTALL_SEPERATORS TEXT("-%s-%s-%s")
+#define ACTION_UNINSTALL TEXT("/WintunAction=Uninstall")
+#define PROPERTY_INSTALLER_HASH TEXT("WintunInstallerHash")
+#define PROPERTY_INSTALLER_BUILDTIME TEXT("WintunInstallerBuildtime")
+#define PROPERTY_VERSION TEXT("WintunVersion")
+#define REGKEY_WINTUN TEXT("Software\\Wintun")
+#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("Wintun: [1]");
+ Type = INSTALLMESSAGE_INFO;
+ break;
+ case LOG_WARN:
+ Template = TEXT("Wintun warning: [1]");
+ Type = INSTALLMESSAGE_INFO;
+ break;
+ case LOG_ERR:
+ Template = TEXT("Wintun 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_WINTUN, 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 "'"), &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_WINTUN, 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_WINTUN, 0, 0);
+ }
+ else
+ Ret = TRUE;
+ LastError = GetLastError();
+cleanup:
+ if (IsComInitialized)
+ CoUninitialize();
+ return Ret ? ERROR_SUCCESS : LastError ? LastError : ERROR_INSTALL_FAILED;
+}
diff --git a/installer/resources.rc b/installer/resources.rc
new file mode 100644
index 0000000..fd73afd
--- /dev/null
+++ b/installer/resources.rc
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#include <windows.h>
+#include <ntverp.h>
+
+wintun.cat RCDATA "wintun\\wintun.cat"
+wintun.inf RCDATA "wintun\\wintun.inf"
+wintun.sys RCDATA "wintun\\wintun.sys"
+
+#ifdef HAVE_WHQL
+wintun-whql.cat RCDATA "whql\\wintun.cat"
+wintun-whql.inf RCDATA "whql\\wintun.inf"
+wintun-whql.sys RCDATA "whql\\wintun.sys"
+#endif
+
+#define STRINGIZE(x) #x
+#define EXPAND(x) STRINGIZE(x)
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION WINTUN_VERSION_MAJ, WINTUN_VERSION_MIN, 0, 0
+PRODUCTVERSION WINTUN_VERSION_MAJ, WINTUN_VERSION_MIN, 0, 0
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_DLL
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "WireGuard LLC"
+ VALUE "FileDescription", "Wintun Installer Library"
+ VALUE "FileVersion", EXPAND(WINTUN_VERSION_STR)
+ VALUE "InternalName", "installer.dll"
+ VALUE "LegalCopyright", "Copyright \xa9 2018-2019 WireGuard LLC. All Rights Reserved."
+ VALUE "OriginalFilename", "installer.dll"
+ VALUE "ProductName", "Wintun Driver"
+ VALUE "ProductVersion", EXPAND(WINTUN_VERSION_STR)
+ VALUE "Comments", "https://www.wintun.net/"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/installer/rundll32.c b/installer/rundll32.c
new file mode 100644
index 0000000..3a482f1
--- /dev/null
+++ b/installer/rundll32.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#include "installation.h"
+#include <Windows.h>
+#include <tlhelp32.h>
+#include <stdio.h>
+#include <conio.h>
+#include <tchar.h>
+
+#pragma warning(disable : 4100) /* unreferenced formal parameter */
+
+static VOID
+ConsoleLogger(_In_ LOGGER_LEVEL Level, _In_ const TCHAR *LogLine)
+{
+ TCHAR *Template;
+ switch (Level)
+ {
+ case LOG_INFO:
+ Template = TEXT("[+] %s\n");
+ break;
+ case LOG_WARN:
+ Template = TEXT("[-] %s\n");
+ break;
+ case LOG_ERR:
+ Template = TEXT("[!] %s\n");
+ break;
+ default:
+ return;
+ }
+ _ftprintf(stdout, Template, LogLine);
+}
+
+static BOOL ElevateToSystem(VOID)
+{
+ HANDLE ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken;
+ PROCESSENTRY32 ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32) };
+ BOOL Ret;
+ DWORD LastError = ERROR_SUCCESS;
+ TOKEN_PRIVILEGES Privileges = { .PrivilegeCount = 1, .Privileges = { { .Attributes = SE_PRIVILEGE_ENABLED } } };
+ CHAR LocalSystemSid[0x400];
+ DWORD RequiredBytes = sizeof(LocalSystemSid);
+
+ if (!CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes))
+ goto cleanup;
+ struct
+ {
+ TOKEN_USER MaybeLocalSystem;
+ CHAR LargeEnoughForLocalSystem[0x400];
+ } TokenUserBuffer;
+ if (!GetTokenInformation(
+ GetCurrentProcessToken(), TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes))
+ goto cleanup;
+ if (EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
+ return TRUE;
+ if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid))
+ goto cleanup;
+ ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (ProcessSnapshot == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ for (Ret = Process32First(ProcessSnapshot, &ProcessEntry); Ret;
+ LastError = GetLastError(), Ret = Process32Next(ProcessSnapshot, &ProcessEntry))
+ {
+ if (_tcsicmp(ProcessEntry.szExeFile, TEXT("winlogon.exe")))
+ continue;
+ RevertToSelf();
+ if (!ImpersonateSelf(SecurityImpersonation))
+ continue;
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &ThreadToken))
+ continue;
+ if (!AdjustTokenPrivileges(ThreadToken, FALSE, &Privileges, sizeof(Privileges), NULL, NULL))
+ {
+ LastError = GetLastError();
+ CloseHandle(ThreadToken);
+ continue;
+ }
+ CloseHandle(ThreadToken);
+
+ WinlogonProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ProcessEntry.th32ProcessID);
+ if (!WinlogonProcess)
+ continue;
+ if (!OpenProcessToken(WinlogonProcess, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &WinlogonToken))
+ continue;
+ CloseHandle(WinlogonProcess);
+ if (!DuplicateToken(WinlogonToken, SecurityImpersonation, &DuplicatedToken))
+ {
+ LastError = GetLastError();
+ continue;
+ }
+ CloseHandle(WinlogonToken);
+ if (!GetTokenInformation(DuplicatedToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes))
+ goto next;
+ if (SetLastError(ERROR_ACCESS_DENIED), !EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
+ goto next;
+ if (!SetThreadToken(NULL, DuplicatedToken))
+ goto next;
+ CloseHandle(DuplicatedToken);
+ CloseHandle(ProcessSnapshot);
+ SetLastError(ERROR_SUCCESS);
+ return TRUE;
+ next:
+ LastError = GetLastError();
+ CloseHandle(DuplicatedToken);
+ }
+ RevertToSelf();
+ CloseHandle(ProcessSnapshot);
+cleanup:
+ SetLastError(LastError);
+ return FALSE;
+}
+
+static VOID
+RunAsAdministrator(HWND hwnd, TCHAR *Verb, int nCmdShow)
+{
+ TOKEN_ELEVATION Elevation;
+ DWORD Required;
+ if (!GetTokenInformation(GetCurrentProcessToken(), TokenElevation, &Elevation, sizeof(Elevation), &Required))
+ return;
+ if (Elevation.TokenIsElevated)
+ return;
+ TCHAR ProcessPath[MAX_PATH], DllPath[MAX_PATH];
+ if (!GetModuleFileName(NULL, ProcessPath, _countof(ProcessPath)) ||
+ !GetModuleFileName(ResourceModule, DllPath, _countof(DllPath)))
+ return;
+ TCHAR Params[0x1000];
+ _stprintf_s(Params, _countof(Params), TEXT("\"%s\",%s"), DllPath, Verb);
+ ShellExecute(hwnd, TEXT("runas"), ProcessPath, Params, NULL, nCmdShow);
+ exit(0);
+}
+
+static VOID
+Do(BOOL Install, BOOL ShowConsole)
+{
+ if (ShowConsole)
+ {
+ AllocConsole();
+ FILE *Stream;
+ freopen_s(&Stream, "CONOUT$", "w", stdout);
+ }
+ SetLogger(ConsoleLogger);
+ ElevateToSystem();
+ Install ? InstallOrUpdate() : Uninstall();
+ RevertToSelf();
+ _putws(TEXT("\nPress any key to close . . ."));
+ (VOID) _getch();
+}
+
+VOID __stdcall InstallWintun(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
+{
+ RunAsAdministrator(hwnd, TEXT(__FUNCTION__), nCmdShow);
+ Do(TRUE, !!nCmdShow);
+}
+
+VOID __stdcall UninstallWintun(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
+{
+ RunAsAdministrator(hwnd, TEXT(__FUNCTION__) , nCmdShow);
+ Do(FALSE, !!nCmdShow);
+} \ No newline at end of file
diff --git a/wintun.c b/wintun.c
index a889840..0c83d6c 100644
--- a/wintun.c
+++ b/wintun.c
@@ -102,9 +102,9 @@ typedef struct _TUN_REGISTER_RINGS
/* Register rings hosted by the client.
* The lpInBuffer and nInBufferSize parameters of DeviceIoControl() must point to an TUN_REGISTER_RINGS struct.
* Client must wait for this IOCTL to finish before adding packets to the ring. */
-#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820, 0x970, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
+#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
/* Force close all open handles to allow for updating. */
-#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820, 0x971, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
+#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
typedef struct _TUN_CTX
{
@@ -176,7 +176,7 @@ InterlockedSetU(_Inout_ _Interlocked_operand_ ULONG volatile *Target, _In_ ULONG
}
static __forceinline VOID
-InterlockedSetPointer(_Inout_ _Interlocked_operand_ VOID * volatile *Target, _In_opt_ VOID *Value)
+InterlockedSetPointer(_Inout_ _Interlocked_operand_ VOID *volatile *Target, _In_opt_ VOID *Value)
{
*Target = Value;
}
diff --git a/wintun.proj b/wintun.proj
index 7f787a0..2901616 100644
--- a/wintun.proj
+++ b/wintun.proj
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
- SPDX-License-Identifier: MIT
+ SPDX-License-Identifier: GPL-2.0
Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
-->
@@ -45,6 +45,22 @@
</Target>
<!--
+ installer.dll Building
+ -->
+ <Target Name="Installer-x86" DependsOnTargets="Driver-x86"
+ Outputs="x86\Release\installer.dll">
+ <MSBuild Projects="installer\installer.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=Win32"/>
+ </Target>
+ <Target Name="Installer-amd64" DependsOnTargets="Driver-amd64"
+ Outputs="amd64\Release\installer.dll">
+ <MSBuild Projects="installer\installer.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=x64"/>
+ </Target>
+ <Target Name="Installer-arm64" DependsOnTargets="Driver-arm64"
+ Outputs="arm64\Release\installer.dll">
+ <MSBuild Projects="installer\installer.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=ARM64"/>
+ </Target>
+
+ <!--
Static Driver Verifier
-->
<Target Name="SDV" Outputs="$(SDVDir)SDV.DVL.xml;amd64\Release\vc.nativecodeanalysis.all.xml">
@@ -63,10 +79,12 @@
<!--
MSM Building
-->
- <Target Name="MSM-x86" Outputs="$(DistributionDir)wintun-x86-$(WintunVersionStr).msm">
- <MSBuild Projects="wintun.wixproj" Targets="Build" Properties="Configuration=Release;Platform=x86"/>
+ <Target Name="MSM-x86" DependsOnTargets="Installer-x86"
+ Outputs="$(DistributionDir)wintun-x86-$(WintunVersionStr).msm">
+ <MSBuild Projects="installer/installer.wixproj" Targets="Build" Properties="Configuration=Release;Platform=x86"/>
</Target>
- <Target Name="MSM-amd64" Outputs="$(DistributionDir)wintun-amd64-$(WintunVersionStr).msm">
- <MSBuild Projects="wintun.wixproj" Targets="Build" Properties="Configuration=Release;Platform=x64"/>
+ <Target Name="MSM-amd64" DependsOnTargets="Installer-amd64"
+ Outputs="$(DistributionDir)wintun-amd64-$(WintunVersionStr).msm">
+ <MSBuild Projects="installer/installer.wixproj" Targets="Build" Properties="Configuration=Release;Platform=x64"/>
</Target>
</Project>
diff --git a/wintun.props b/wintun.props
index 61ab893..5ca27c5 100644
--- a/wintun.props
+++ b/wintun.props
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
- SPDX-License-Identifier: MIT
+ SPDX-License-Identifier: GPL-2.0
Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
-->
@@ -20,4 +20,25 @@
<DistributionDir>dist\</DistributionDir>
<SDVDir>sdv\</SDVDir>
</PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PreprocessorDefinitions>WINTUN_VERSION_MAJ=$(WintunVersionMaj);WINTUN_VERSION_MIN=$(WintunVersionMin);WINTUN_VERSION_STR="$(WintunVersionStr)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WINTUN_VERSION_MAJ=$(WintunVersionMaj);WINTUN_VERSION_MIN=$(WintunVersionMin);WINTUN_VERSION_STR="$(WintunVersionStr)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ </ItemDefinitionGroup>
</Project>
diff --git a/wintun.rc b/wintun.rc
index d0f3852..7fff283 100644
--- a/wintun.rc
+++ b/wintun.rc
Binary files differ
diff --git a/wintun.sln b/wintun.sln
index 0a423b9..67dd803 100644
--- a/wintun.sln
+++ b/wintun.sln
@@ -1,8 +1,13 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28922.388
MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer\installer.vcxproj", "{D19E6354-A643-4ACC-82D5-B2780BB83475}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F7679B65-2FEC-469A-8BAC-B07BF4439422} = {F7679B65-2FEC-469A-8BAC-B07BF4439422}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wintun", "wintun.vcxproj", "{F7679B65-2FEC-469A-8BAC-B07BF4439422}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3A98F138-EE02-4488-B856-B3C48500BEA8}"
@@ -13,12 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
wintun.props = wintun.props
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "installer", "installer", "{2B5DA7D8-C56A-4E93-BE93-79388A8007AF}"
- ProjectSection(SolutionItems) = preProject
- wintun.wixproj = wintun.wixproj
- wintun.wxs = wintun.wxs
- EndProjectSection
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|amd64 = Debug|amd64
@@ -41,6 +40,18 @@ Global
{F7679B65-2FEC-469A-8BAC-B07BF4439422}.Release|arm64.Build.0 = Release|ARM64
{F7679B65-2FEC-469A-8BAC-B07BF4439422}.Release|x86.ActiveCfg = Release|Win32
{F7679B65-2FEC-469A-8BAC-B07BF4439422}.Release|x86.Build.0 = Release|Win32
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Debug|amd64.ActiveCfg = Debug|x64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Debug|amd64.Build.0 = Debug|x64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Debug|arm64.ActiveCfg = Debug|ARM64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Debug|arm64.Build.0 = Debug|ARM64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Debug|x86.ActiveCfg = Debug|Win32
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Debug|x86.Build.0 = Debug|Win32
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Release|amd64.ActiveCfg = Release|x64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Release|amd64.Build.0 = Release|x64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Release|arm64.ActiveCfg = Release|ARM64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Release|arm64.Build.0 = Release|ARM64
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Release|x86.ActiveCfg = Release|Win32
+ {D19E6354-A643-4ACC-82D5-B2780BB83475}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/wintun.vcxproj b/wintun.vcxproj
index 4d72a65..a8deb98 100644
--- a/wintun.vcxproj
+++ b/wintun.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?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|ARM64">
@@ -124,12 +124,11 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
<ItemDefinitionGroup>
<ClCompile>
- <PreprocessorDefinitions>WINTUN_VERSION_MAJ=$(WintunVersionMaj);WINTUN_VERSION_MIN=$(WintunVersionMin);WINTUN_VERSION_STR="$(WintunVersionStr)";NDIS_MINIPORT_DRIVER=1;NDIS620_MINIPORT=1;NDIS683_MINIPORT=1;NDIS_WDM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>NDIS_MINIPORT_DRIVER=1;NDIS620_MINIPORT=1;NDIS683_MINIPORT=1;NDIS_WDM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<EnablePREfast>true</EnablePREfast>
</ClCompile>
<ResourceCompile>
- <PreprocessorDefinitions>WINTUN_VERSION_MAJ=$(WintunVersionMaj);WINTUN_VERSION_MIN=$(WintunVersionMin);WINTUN_VERSION_STR="$(WintunVersionStr)";NDIS_MINIPORT_DRIVER=1;NDIS620_MINIPORT=1;NDIS683_MINIPORT=1;NDIS_WDM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDIS_MINIPORT_DRIVER=1;NDIS620_MINIPORT=1;NDIS683_MINIPORT=1;NDIS_WDM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<AdditionalDependencies>ndis.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -142,16 +141,10 @@
<Inf>
<TimeStamp>$(WintunVersion)</TimeStamp>
</Inf>
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- </ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>DBG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <Optimization>Disabled</Optimization>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>DBG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -181,4 +174,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/wintun.vcxproj.filters b/wintun.vcxproj.filters
index 5a7e2d9..3e19120 100644
--- a/wintun.vcxproj.filters
+++ b/wintun.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
diff --git a/wintun.wxs b/wintun.wxs
deleted file mode 100644
index be8b755..0000000
--- a/wintun.wxs
+++ /dev/null
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- SPDX-License-Identifier: GPL-2.0
-
- Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
--->
-<?if $(var.Platform) = "x86"?>
- <?define PlatformProgramFilesFolder = "ProgramFilesFolder"?>
-<?else?>
- <?define PlatformProgramFilesFolder = "ProgramFiles64Folder"?>
-<?endif?>
-<Wix
- xmlns="http://schemas.microsoft.com/wix/2006/wi"
- xmlns:diffx="http://schemas.microsoft.com/wix/DifxAppExtension"
- xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension">
- <Module Id="wintun" Language="0" Version="$(var.WINTUN_VERSION)">
- <Package
- Id="c28309d9-1954-4f2d-a7d1-228850092460"
- Description="Wintun Userspace Tunnel"
- Manufacturer="WireGuard LLC"
- InstallerVersion="200"
- InstallPrivileges="elevated"
- InstallScope="perMachine"
- ReadOnly="yes"/>
-
- <Binary Id="wintun.cer" SourceFile="!(bindpath.output_dir)wintun.cer"/>
-
- <Property Id="WINDOWS10_VER_MAJ">
- <RegistrySearch Id="Windows10VersionMaj" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentMajorVersionNumber" Type="raw"/>
- </Property>
-
- <Directory Id="TARGETDIR" Name="SourceDir">
- <Directory Id="WintunFolder">
- <Component Id="wintun.cat.whql" Guid="2f17bc6d-0006-47c4-8ba3-f055d1852558">
- <Condition><![CDATA[WINDOWS10_VER_MAJ]]></Condition>
- <File
- Id="wintun.cat.whql"
- Name="wintun.cat"
- Source="!(bindpath.whql_dir)wintun.cat"
- DefaultVersion="$(var.WINTUN_VERSION)"
- DefaultLanguage="0"/>
- <diffx:Driver
- AddRemovePrograms="no"
- PlugAndPlayPrompt="no"/>
- </Component>
- <Component Id="wintun.cat" Guid="41fbe711-a1af-4b83-8b5d-fc1b112969c1">
- <Condition><![CDATA[NOT WINDOWS10_VER_MAJ]]></Condition>
- <File
- Id="wintun.cat"
- Name="wintun.cat"
- Source="!(bindpath.output_dir)wintun\wintun.cat"
- DefaultVersion="$(var.WINTUN_VERSION)"
- DefaultLanguage="0"/>
- <iis:Certificate
- Id="wintun.cer"
- Name="WireGuard LLC"
- StoreLocation="localMachine"
- StoreName="trustedPublisher"
- BinaryKey="wintun.cer"
- Request="no"/>
- <diffx:Driver
- AddRemovePrograms="no"
- PlugAndPlayPrompt="no"/>
- </Component>
-
- <Component Id="wintun.inf" Guid="c58122b3-c7ba-4207-b68d-a236e371f9ed">
- <File
- Id="wintun.inf"
- Name="wintun.inf"
- Source="!(bindpath.output_dir)wintun\wintun.inf"
- DefaultVersion="$(var.WINTUN_VERSION)"
- DefaultLanguage="0"/>
- </Component>
-
- <Component Id="wintun.sys.whql" Guid="039baa6d-b16b-4dc2-8b86-8bb500f78de0">
- <Condition><![CDATA[WINDOWS10_VER_MAJ]]></Condition>
- <File
- Id="wintun.sys.whql"
- Name="wintun.sys"
- Source="!(bindpath.whql_dir)wintun.sys"
- DefaultVersion="$(var.WINTUN_VERSION)"
- DefaultLanguage="0"/>
- </Component>
- <Component Id="wintun.sys" Guid="d0fde4a4-d228-4803-b57e-76bd8b16cf42">
- <Condition><![CDATA[NOT WINDOWS10_VER_MAJ]]></Condition>
- <File
- Id="wintun.sys"
- Name="wintun.sys"
- Source="!(bindpath.output_dir)wintun\wintun.sys"
- DefaultVersion="$(var.WINTUN_VERSION)"
- DefaultLanguage="0"/>
- </Component>
- </Directory>
- </Directory>
-
- <!--
- The WintunFolder is relocated inside product folder when our module is merged.
- To avoid this, set WintunFolder property to [ProgramFilesFolder]\Wintun explicitly
- in each installer sequence.
- -->
- <Property Id="$(var.PlatformProgramFilesFolder)" SuppressModularization="yes"/><!-- This will produce CNDL1006 and CNDL1086 warnings, but it prevents "[ProgramFiles(64)Folder]" from being modularized to "[ProgramFiles(64)Folder.C28309D9_1954_4F2D_A7D1_228850092460]". -->
- <CustomAction Id="WintunFolder" Property="WintunFolder" Value="[$(var.PlatformProgramFilesFolder)]\Wintun"/>
- <AdminExecuteSequence>
- <Custom Action="WintunFolder" Before="CostInitialize"/>
- </AdminExecuteSequence>
- <AdminUISequence>
- <Custom Action="WintunFolder" Before="CostInitialize"/>
- </AdminUISequence>
- <AdvertiseExecuteSequence>
- <Custom Action="WintunFolder" Before="CostInitialize"/>
- </AdvertiseExecuteSequence>
- <InstallExecuteSequence>
- <Custom Action="WintunFolder" Before="CostInitialize"/>
- </InstallExecuteSequence>
- <InstallUISequence>
- <Custom Action="WintunFolder" Before="CostInitialize"/>
- </InstallUISequence>
-
- <!--
- Prevent WoW64 installations.
- -->
- <?if $(var.Platform) = "x86"?>
- <CustomAction Id="WoW64Unsupported" Error="You are attempting to install the 32-bit variant of [ProductName] on a 64-bit operating system, which is not supported. Please install the 64-bit variant instead."/>
- <InstallExecuteSequence>
- <Custom Action="WoW64Unsupported" After="LaunchConditions"><![CDATA[VersionNT64]]></Custom>
- </InstallExecuteSequence>
- <InstallUISequence>
- <Custom Action="WoW64Unsupported" After="LaunchConditions"><![CDATA[VersionNT64]]></Custom>
- </InstallUISequence>
- <?endif?>
-
- <InstallExecuteSequence>
- <Custom Action="InstallCertificates" Before="MsiProcessDrivers"><![CDATA[VersionNT > 400]]></Custom>
- </InstallExecuteSequence>
- </Module>
-</Wix>