aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/installer
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2019-08-08 09:31:42 +0200
committerSimon Rozman <simon@rozman.si>2019-08-09 11:56:01 +0200
commitb3de85e47aeb27f5c33015026b25adf7edb3bf0e (patch)
tree448050f47add410ef7a75e39f676af910b915c87 /installer
parentinstaller: unify WIREGUARD_-specific WiX variables (diff)
downloadwireguard-windows-b3de85e47aeb27f5c33015026b25adf7edb3bf0e.tar.xz
wireguard-windows-b3de85e47aeb27f5c33015026b25adf7edb3bf0e.zip
installer: port custom actions from JScript to C
Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'installer')
-rw-r--r--installer/build.bat16
-rw-r--r--installer/customactions.c403
-rw-r--r--installer/customactions.js102
-rw-r--r--installer/wireguard.wxs6
4 files changed, 419 insertions, 108 deletions
diff --git a/installer/build.bat b/installer/build.bat
index 35873744..a0a17c27 100644
--- a/installer/build.bat
+++ b/installer/build.bat
@@ -36,8 +36,8 @@ if exist .deps\prepared goto :build
:build
set WIX=%BUILDDIR%.deps\wix\
- call :msi x86 x86 || goto :error
- call :msi amd64 x64 || goto :error
+ call :msi x86 i686 x86 || goto :error
+ call :msi amd64 x86_64 x64 || goto :error
if exist ..\sign.bat call ..\sign.bat
if "%SigningCertificate%"=="" goto :out
if "%TimestampServer%"=="" goto :out
@@ -62,8 +62,18 @@ if exist .deps\prepared goto :build
goto :eof
:msi
+ set OLDPATH2=%PATH%
+ set PATH=%BUILDDIR%..\.deps\%~2-w64-mingw32-native\bin;%PATH%
+ set CC=%~2-w64-mingw32-gcc
+ set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0601 -municode -DUNICODE -D_UNICODE -DNDEBUG
+ set LDFLAGS=-shared -s -Wl,--kill-at -Wl,--major-os-version=6 -Wl,--minor-os-version=1 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=1
+ set LDLIBS=-lmsi -lole32 -lshlwapi
+ if not exist "%~1" mkdir "%~1"
+ echo [+] Compiling custom actions %1
+ %CC% %CFLAGS% %LDFLAGS% -o "%~1\customactions.dll" customactions.c %LDLIBS% || exit /b 1
echo [+] Compiling %1
- "%WIX%bin\candle" %WIX_CANDLE_FLAGS% -dWIREGUARD_PLATFORM="%~1" -out "%~1\wireguard.wixobj" -arch %2 wireguard.wxs || exit /b %errorlevel%
+ "%WIX%bin\candle" %WIX_CANDLE_FLAGS% -dWIREGUARD_PLATFORM="%~1" -out "%~1\wireguard.wixobj" -arch %3 wireguard.wxs || exit /b %errorlevel%
echo [+] Linking %1
"%WIX%bin\light" %WIX_LIGHT_FLAGS% -out "dist\wireguard-%~1-%WIREGUARD_VERSION%.msi" "%~1\wireguard.wixobj" || exit /b %errorlevel%
+ set PATH=%OLDPATH2%
goto :eof
diff --git a/installer/customactions.c b/installer/customactions.c
new file mode 100644
index 00000000..7217fca8
--- /dev/null
+++ b/installer/customactions.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#include <windows.h>
+#include <msi.h>
+#include <msidefs.h>
+#include <msiquery.h>
+#include <shlwapi.h>
+#include <stdbool.h>
+#include <tchar.h>
+
+#define MANAGER_SERVICE_NAME TEXT("WireGuardManager")
+#define TUNNEL_SERVICE_PREFIX TEXT("WireGuardTunnel$")
+#define ENUM_SERVICE_STATUS_PROCESS_SIZE 0x10000
+
+typedef enum
+{
+ LOG_LEVEL_INFO = 0,
+ LOG_LEVEL_WARN,
+ LOG_LEVEL_ERR
+} log_level_t;
+
+static TCHAR *format_message(const TCHAR *template, const DWORD_PTR argv[])
+{
+ TCHAR *formatted_message = NULL;
+ if (!FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ template,
+ 0,
+ 0,
+ (VOID *)&formatted_message,
+ 0,
+ (va_list *)argv))
+ return NULL;
+ return formatted_message;
+}
+
+static void log_message(MSIHANDLE installer, log_level_t level, const TCHAR *log_line)
+{
+ MSIHANDLE record = MsiCreateRecord(2);
+ if (!record)
+ return;
+ TCHAR *template;
+ INSTALLMESSAGE type;
+ switch (level) {
+ case LOG_LEVEL_INFO:
+ template = TEXT("Custom action: [1]");
+ type = INSTALLMESSAGE_INFO;
+ break;
+ case LOG_LEVEL_WARN:
+ template = TEXT("Custom action warning: [1]");
+ type = INSTALLMESSAGE_INFO;
+ break;
+ case LOG_LEVEL_ERR:
+ template = TEXT("Custom action error: [1]");
+ type = INSTALLMESSAGE_ERROR;
+ break;
+ default:
+ goto cleanup;
+ }
+ MsiRecordSetString(record, 0, template);
+ MsiRecordSetString(record, 1, log_line);
+ MsiProcessMessage(installer, type, record);
+cleanup:
+ MsiCloseHandle(record);
+}
+
+static void log_messagef(MSIHANDLE installer, log_level_t level, const TCHAR *template, const DWORD_PTR argv[])
+{
+ TCHAR *formatted_message = format_message(template, argv);
+ if (formatted_message) {
+ log_message(installer, level, formatted_message);
+ LocalFree(formatted_message);
+ }
+}
+
+static void log_error(MSIHANDLE installer, DWORD error_code, const TCHAR *prefix)
+{
+ TCHAR *system_message = NULL;
+ FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL,
+ HRESULT_FROM_SETUPAPI(error_code),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (VOID *)&system_message,
+ 0,
+ NULL);
+ log_messagef(
+ installer,
+ LOG_LEVEL_ERR,
+ system_message ? TEXT("%1: %3(Code 0x%2!08X!)") : TEXT("%1: Code 0x%2!08X!"),
+ (DWORD_PTR[]){ (DWORD_PTR)prefix, error_code, (DWORD_PTR)system_message });
+ LocalFree(system_message);
+}
+
+static void log_errorf(MSIHANDLE installer, DWORD error_code, const TCHAR *template, const DWORD_PTR argv[])
+{
+ TCHAR *formatted_message = format_message(template, argv);
+ if (formatted_message) {
+ log_error(installer, error_code, formatted_message);
+ LocalFree(formatted_message);
+ }
+}
+
+static bool is_valid_tunnel_name(const TCHAR *tunnel_name)
+{
+ for (size_t i = 0; ; i++) {
+ TCHAR c = tunnel_name[i];
+ if (!c)
+ return i > 0;
+ if (i >= 32)
+ return false;
+ if ((c < TEXT('a') || c > TEXT('z')) &&
+ (c < TEXT('A') || c > TEXT('Z')) &&
+ (c < TEXT('0') || c > TEXT('9')) &&
+ c != TEXT('_') &&
+ c != TEXT('=') &&
+ c != TEXT('+') &&
+ c != TEXT('.') &&
+ c != TEXT('-'))
+ return false;
+ }
+}
+
+static void replace_msi_operators(TCHAR *dest, const TCHAR *src, size_t count)
+{
+ for (size_t i = 0; i < count; i++) {
+ TCHAR c = src[i];
+ switch (c) {
+ case 0:
+ dest[i] = 0;
+ return;
+ case TEXT('='):
+ case TEXT('+'):
+ case TEXT('-'):
+ dest[i] = TEXT('_');
+ break;
+ default:
+ dest[i] = c;
+ }
+ }
+}
+
+static bool is_service_started(MSIHANDLE installer, SC_HANDLE scm, const TCHAR *service_name)
+{
+ bool ret = false;
+ SC_HANDLE service = NULL;
+ SERVICE_STATUS_PROCESS service_status;
+ DWORD service_status_size = 0;
+ const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__, (DWORD_PTR)service_name };
+
+ service = OpenService(scm, MANAGER_SERVICE_NAME, SERVICE_QUERY_STATUS);
+ if (!service) {
+ log_errorf(installer, GetLastError(), TEXT("%1!hs!: OpenService failed for service %2"), log_argv);
+ goto cleanup;
+ }
+ if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&service_status, sizeof(service_status), &service_status_size)) {
+ log_errorf(installer, GetLastError(), TEXT("%1!hs!: QueryServiceStatusEx failed for service %2"), log_argv);
+ goto cleanup;
+ }
+ if (service_status.dwCurrentState != SERVICE_STOPPED && service_status.dwCurrentState != SERVICE_STOP_PENDING)
+ ret = true;
+
+cleanup:
+ if (service)
+ CloseServiceHandle(service);
+ return ret;
+}
+
+static UINT insert_service_control(MSIHANDLE installer, MSIHANDLE view, const TCHAR *service_name, bool start)
+{
+ UINT ret = ERROR_INSTALL_FAILURE;
+ MSIHANDLE record = 0;
+ const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__, (DWORD_PTR)service_name };
+ size_t service_name_len;
+ TCHAR *sanitized_service_name = NULL, *service_control_stop = NULL, *service_control_start = NULL;
+ static unsigned int index = 0;
+
+ record = MsiCreateRecord(5);
+ if (!record)
+ goto cleanup;
+
+ service_name_len = _tcslen(service_name) + 1;
+ sanitized_service_name = LocalAlloc(LMEM_FIXED, sizeof(TCHAR) * service_name_len);
+ if (!sanitized_service_name) {
+ ret = GetLastError();
+ log_errorf(installer, ret, TEXT("%1!hs!: LocalAlloc failed for service %2"), log_argv);
+ goto cleanup;
+ }
+ replace_msi_operators(sanitized_service_name, service_name, service_name_len);
+
+ log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: Scheduling stop on upgrade or removal on uninstall of service %2"), log_argv);
+ service_control_stop = format_message(TEXT("stop_%1%2!u!"), (DWORD_PTR[]){ (DWORD_PTR)sanitized_service_name, index++ });
+ if (!service_control_stop) {
+ ret = GetLastError();
+ log_errorf(installer, ret, TEXT("%1!hs!: FormatMessage failed for service %2"), log_argv);
+ goto cleanup;
+ }
+ MsiRecordSetString (record, 1/*ServiceControl*/, service_control_stop);
+ MsiRecordSetString (record, 2/*Name */, service_name);
+ MsiRecordSetInteger(record, 3/*Event */, msidbServiceControlEventStop | msidbServiceControlEventUninstallStop | msidbServiceControlEventUninstallDelete);
+ MsiRecordSetString (record, 4/*Component_ */, TEXT("WireGuardExecutable"));
+ MsiRecordSetInteger(record, 5/*Wait */, 1); /* Waits 30 seconds. */
+ ret = MsiViewExecute(view, record);
+ if (ret != ERROR_SUCCESS) {
+ log_errorf(installer, ret, TEXT("%1!hs!: MsiViewExecute failed for service %2"), log_argv);
+ goto cleanup;
+ }
+ if (!start)
+ goto cleanup;
+
+ log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: Scheduling start on upgrade of service %2"), log_argv);
+ service_control_start = format_message(TEXT("start_%1%2!u!"), (DWORD_PTR[]){ (DWORD_PTR)sanitized_service_name, index++ });
+ if (!service_control_start) {
+ ret = GetLastError();
+ log_errorf(installer, ret, TEXT("%1!hs!: FormatMessage failed for service %2"), log_argv);
+ goto cleanup;
+ }
+ MsiRecordSetString (record, 1/*ServiceControl*/, service_control_start);
+ MsiRecordSetString (record, 2/*Name */, service_name);
+ MsiRecordSetInteger(record, 3/*Event */, msidbServiceControlEventStart);
+ MsiRecordSetString (record, 4/*Component_ */, TEXT("WireGuardExecutable"));
+ MsiRecordSetInteger(record, 5/*Wait */, 0); /* No wait, so that failure to restart again isn't fatal. */
+ ret = MsiViewExecute(view, record);
+ if (ret != ERROR_SUCCESS) {
+ log_errorf(installer, ret, TEXT("%1!hs!: MsiViewExecute failed for service %2"), log_argv);
+ goto cleanup;
+ }
+
+cleanup:
+ if (service_control_start)
+ LocalFree(service_control_start);
+ if (service_control_stop)
+ LocalFree(service_control_stop);
+ if (sanitized_service_name)
+ LocalFree(sanitized_service_name);
+ if (record)
+ MsiCloseHandle(record);
+ return ret;
+}
+
+static bool remove_folder(MSIHANDLE installer, TCHAR path[MAX_PATH])
+{
+ HANDLE find_handle;
+ WIN32_FIND_DATA find_data;
+ TCHAR *path_end;
+ const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__, (DWORD_PTR)path };
+
+ path_end = path + _tcsnlen(path, MAX_PATH);
+ if (!PathAppend(path, TEXT("*.*"))) {
+ log_messagef(installer, LOG_LEVEL_ERR, TEXT("%1!hs!: PathAppend(%2) failed"), log_argv);
+ return false;
+ }
+ find_handle = FindFirstFileEx(path, FindExInfoBasic, &find_data, FindExSearchNameMatch, NULL, 0);
+ if (find_handle == INVALID_HANDLE_VALUE) {
+ log_errorf(installer, GetLastError(), TEXT("%1!hs!: FindFirstFileEx(%2) failed"), log_argv);
+ return false;
+ }
+ do {
+ if (find_data.cFileName[0] == TEXT('.') && (!find_data.cFileName[1] || (find_data.cFileName[1] == TEXT('.') && !find_data.cFileName[2])))
+ continue;
+
+ path_end[0] = 0;
+ if (!PathAppend(path, find_data.cFileName)) {
+ log_messagef(installer, LOG_LEVEL_ERR, TEXT("%1!hs!: PathAppend(%2) failed"), log_argv);
+ continue;
+ }
+
+ if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ remove_folder(installer, path);
+ continue;
+ }
+
+ if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && !SetFileAttributes(path, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY))
+ log_errorf(installer, GetLastError(), TEXT("%1!hs!: SetFileAttributes(%2) failed"), log_argv);
+
+ if (DeleteFile(path))
+ log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: %2 removed"), log_argv);
+ else
+ log_errorf(installer, GetLastError(), TEXT("%1!hs!: DeleteFile(%2) failed"), log_argv);
+ } while (FindNextFile(find_handle, &find_data));
+ FindClose(find_handle);
+
+ path_end[0] = 0;
+ if (RemoveDirectory(path)) {
+ log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: %2 removed"), log_argv);
+ return true;
+ } else {
+ log_errorf(installer, GetLastError(), TEXT("%1!hs!: RemoveDirectory(%2) failed"), log_argv);
+ return false;
+ }
+}
+
+__declspec(dllexport) UINT __stdcall EvaluateWireGuardServices(MSIHANDLE installer)
+{
+ UINT ret = ERROR_INSTALL_FAILURE;
+ BOOL is_com_initialized = SUCCEEDED(CoInitialize(NULL));
+ MSIHANDLE db = 0, view = 0;
+ SC_HANDLE scm = NULL;
+ ENUM_SERVICE_STATUS_PROCESS *service_status = NULL;
+ DWORD service_status_resume = 0;
+ const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__ };
+
+ db = MsiGetActiveDatabase(installer);
+ if (!db) {
+ log_messagef(installer, LOG_LEVEL_ERR, TEXT("%1!hs!: MsiGetActiveDatabase failed"), log_argv);
+ goto cleanup;
+ }
+ ret = MsiDatabaseOpenView(
+ db,
+ TEXT("INSERT INTO `ServiceControl` (`ServiceControl`, `Name`, `Event`, `Component_`, `Wait`) VALUES(?, ?, ?, ?, ?) TEMPORARY"),
+ &view);
+ if (ret != ERROR_SUCCESS) {
+ log_errorf(installer, ret, TEXT("%1!hs!: MsiDatabaseOpenView failed"), log_argv);
+ goto cleanup;
+ }
+ scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
+ if (!scm) {
+ ret = GetLastError();
+ log_errorf(installer, ret, TEXT("%1!hs!: OpenSCManager failed"), log_argv);
+ goto cleanup;
+ }
+
+ insert_service_control(installer, view, MANAGER_SERVICE_NAME, is_service_started(installer, scm, MANAGER_SERVICE_NAME));
+
+ service_status = LocalAlloc(LMEM_FIXED, ENUM_SERVICE_STATUS_PROCESS_SIZE);
+ if (!service_status) {
+ ret = GetLastError();
+ log_errorf(installer, ret, TEXT("%1!hs!: LocalAlloc failed"), log_argv);
+ goto cleanup;
+ }
+ for (bool more_services = true; more_services;) {
+ DWORD service_status_size = 0, service_status_count = 0;
+ if (EnumServicesStatusEx(
+ scm,
+ SC_ENUM_PROCESS_INFO,
+ SERVICE_WIN32,
+ SERVICE_STATE_ALL,
+ (LPBYTE)service_status,
+ ENUM_SERVICE_STATUS_PROCESS_SIZE,
+ &service_status_size,
+ &service_status_count,
+ &service_status_resume,
+ NULL))
+ more_services = false;
+ else {
+ ret = GetLastError();
+ if (ret != ERROR_MORE_DATA) {
+ log_errorf(installer, ret, TEXT("%1!hs!: EnumServicesStatusEx failed"), log_argv);
+ break;
+ }
+ }
+
+ for (DWORD i = 0; i < service_status_count; i++) {
+ if (_tcsnicmp(service_status[i].lpServiceName, TUNNEL_SERVICE_PREFIX, _countof(TUNNEL_SERVICE_PREFIX) - 1) == 0) {
+ const TCHAR *tunnel_name = service_status[i].lpServiceName + _countof(TUNNEL_SERVICE_PREFIX) - 1;
+ if (is_valid_tunnel_name(tunnel_name))
+ insert_service_control(
+ installer,
+ view,
+ service_status[i].lpServiceName,
+ service_status[i].ServiceStatusProcess.dwCurrentState != SERVICE_STOPPED && service_status[i].ServiceStatusProcess.dwCurrentState != SERVICE_STOP_PENDING);
+ }
+ }
+ }
+
+ ret = ERROR_SUCCESS;
+
+cleanup:
+ if (service_status)
+ LocalFree(service_status);
+ if (scm)
+ CloseServiceHandle(scm);
+ if (view)
+ MsiCloseHandle(view);
+ if (db)
+ MsiCloseHandle(db);
+ if (is_com_initialized)
+ CoUninitialize();
+ return ret == ERROR_SUCCESS ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+}
+
+__declspec(dllexport) UINT __stdcall RemoveConfigFolder(MSIHANDLE installer)
+{
+ LSTATUS result;
+ TCHAR path[MAX_PATH];
+
+ result = SHRegGetPath(
+ HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\S-1-5-18"),
+ TEXT("ProfileImagePath"),
+ path,
+ 0);
+ if (result != ERROR_SUCCESS) {
+ log_errorf(installer, result, TEXT("%1!hs!: SHRegGetPath failed"), (DWORD_PTR[]){ (DWORD_PTR)__FUNCTION__ });
+ return ERROR_SUCCESS;
+ }
+ PathAppend(path, TEXT("AppData\\Local\\WireGuard"));
+ remove_folder(installer, path);
+ return ERROR_SUCCESS;
+}
diff --git a/installer/customactions.js b/installer/customactions.js
deleted file mode 100644
index c35774ad..00000000
--- a/installer/customactions.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-var wsh = new ActiveXObject("WScript.Shell");
-var shl = new ActiveXObject("Shell.Application");
-var fso = new ActiveXObject("Scripting.FileSystemObject");
-
-function logMessage(msg) {
- var record = Installer.CreateRecord(1);
- record.StringData(0) = "Custom action: [1]";
- record.StringData(1) = msg.toString();
- Session.Message(0x04000000, record);
-}
-
-// I'd rather use wsh.Exec, so that we can just do ".Stdout.ReadAll()", but
-// this results in a scary flashing command window. The below is the best
-// workaround we can find yet. We'll keep searching for more clever tricks.
-function runWithNoWindowFlash(command) {
- //TODO: Seems pretty unlikely that this temp file is secure...
- var tmpfile = fso.BuildPath(fso.GetSpecialFolder(2), fso.GetTempName());
- try {
- //TODO: Obviously cmd and tmpfile are unescaped here...
- var cmd = fso.BuildPath(fso.GetSpecialFolder(1), "cmd.exe") + " /c " + command + " > \"" + tmpfile + "\"";
- var ret = wsh.Run(cmd, 0, true);
- if (ret != 0) {
- logMessage("Command " + cmd + " exited with error " + ret.toString());
- return "";
- }
- var txt;
- try {
- var file = fso.OpenTextFile(tmpfile, 1);
- txt = file.ReadAll();
- file.Close();
- } catch (e) {
- logMessage("Unable to read temporary file " + tmpfile + " for command " + cmd + ": " + e.message);
- return "";
- }
- return txt;
- } finally {
- try {
- fso.DeleteFile(tmpfile);
- } catch (e) {}
- }
-}
-
-function EvaluateWireGuardServices() {
- var inst = Session.Installer;
- var db = Session.Database;
- var view = db.OpenView("INSERT INTO `ServiceControl` (`ServiceControl`, `Name`, `Event`, `Component_`, `Wait`) VALUES(?, ?, ?, ?, ?) TEMPORARY");
- var rec = inst.CreateRecord(5);
- var serviceKey = "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services";
- var servicePrefix = "WireGuardTunnel$";
- var serviceKeyPrefix = serviceKey + "\\" + servicePrefix;
- var allowedNameFormat = new RegExp("^[a-zA-Z0-9_=+.-]{1,32}$");
- var msiOperators = new RegExp("[=+-]", "g");
- var index = 0;
-
- function insertServiceControl(serviceName) {
- logMessage("Scheduling stop on upgrade or removal on uninstall of service " + serviceName);
- rec.StringData (1/*ServiceControl*/) = "stop_" + serviceName.replace(msiOperators, "_") + (index++).toString();
- rec.StringData (2/*Name */) = serviceName;
- rec.IntegerData(3/*Event */) = 0x2/*msidbServiceControlEventStop*/ | 0x20/*msidbServiceControlEventUninstallStop*/ | 0x80/*msidbServiceControlEventUninstallDelete*/;
- rec.StringData (4/*Component_ */) = "WireGuardExecutable";
- rec.IntegerData(5/*Wait */) = 1; /* Waits 30 seconds. */
- view.Execute(rec);
-
- if (!shl.IsServiceRunning(serviceName))
- return;
-
- logMessage("Scheduling start on upgrade of service " + serviceName);
- rec.StringData (1/*ServiceControl*/) = "start_" + serviceName.replace(msiOperators, "_") + (index++).toString();
- rec.StringData (2/*Name */) = serviceName;
- rec.IntegerData(3/*Event */) = 0x1/*msidbServiceControlEventStart*/;
- rec.StringData (4/*Component_ */) = "WireGuardExecutable";
- rec.IntegerData(5/*Wait */) = 0; /* No wait, so that failure to restart again isn't fatal. */
- view.Execute(rec);
- }
-
- insertServiceControl("WireGuardManager");
-
- var txt = runWithNoWindowFlash(fso.BuildPath(fso.GetSpecialFolder(1), "reg.exe") + " query \"" + serviceKey + "\"");
- var lines = txt.split(new RegExp("\r?\n", "g"));
- for (var i = 0; i < lines.length; ++i) {
- if (lines[i].length > serviceKeyPrefix.length && lines[i].substring(0, serviceKeyPrefix.length) == serviceKeyPrefix) {
- var tunnelName = lines[i].substring(serviceKeyPrefix.length);
- if (tunnelName.match(allowedNameFormat) != null)
- insertServiceControl(servicePrefix + tunnelName);
- }
- }
-}
-
-function RemoveConfigFolder() {
- try {
- var path = wsh.RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\S-1-5-18\\ProfileImagePath");
- path = wsh.ExpandEnvironmentStrings(path.toString());
- fso.DeleteFolder(fso.BuildPath(path, "AppData\\Local\\WireGuard"), true);
- } catch(e) {
- logMessage("Failed to remove configuration on uninstall: " + e.message);
- }
-}
diff --git a/installer/wireguard.wxs b/installer/wireguard.wxs
index dfd12ac5..492422dd 100644
--- a/installer/wireguard.wxs
+++ b/installer/wireguard.wxs
@@ -36,7 +36,7 @@
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Icon Id="wireguard.ico" SourceFile="..\ui\icon\wireguard.ico" />
- <Binary Id="customactions.js" SourceFile="customactions.js" />
+ <Binary Id="customactions.dll" SourceFile="$(var.WIREGUARD_PLATFORM)\customactions.dll" />
<Property Id="ARPPRODUCTICON" Value="wireguard.ico" />
<Property Id="ARPURLINFOABOUT" Value="https://www.wireguard.com/" />
@@ -122,7 +122,7 @@
<!--
Evaluate WireGuard services and populate ServiceControl table
-->
- <CustomAction Id="EvaluateWireGuardServices" BinaryKey="customactions.js" JScriptCall="EvaluateWireGuardServices" />
+ <CustomAction Id="EvaluateWireGuardServices" BinaryKey="customactions.dll" DllEntry="EvaluateWireGuardServices" />
<InstallExecuteSequence>
<Custom Action="EvaluateWireGuardServices" After="FindRelatedProducts" />
</InstallExecuteSequence>
@@ -130,7 +130,7 @@
<!--
Clear out our config folder on uninstall
-->
- <CustomAction Id="RemoveConfigFolder" BinaryKey="customactions.js" JScriptCall="RemoveConfigFolder" Execute="deferred" Impersonate="no" />
+ <CustomAction Id="RemoveConfigFolder" BinaryKey="customactions.dll" DllEntry="RemoveConfigFolder" Execute="deferred" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="RemoveConfigFolder" After="DeleteServices">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
</InstallExecuteSequence>