diff options
Diffstat (limited to '')
-rw-r--r-- | installer/msi.c | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/installer/msi.c b/installer/msi.c deleted file mode 100644 index 348ef42..0000000 --- a/installer/msi.c +++ /dev/null @@ -1,266 +0,0 @@ -/* 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; -} |