]> repos.lx-s.de Git - winmute.git/commitdiff
Started implementing updater
authorlx-s <lx-s@users.noreply.github.com>
Mon, 18 Dec 2023 19:29:30 +0000 (20:29 +0100)
committerlx-s <lx-s@users.noreply.github.com>
Mon, 18 Dec 2023 19:29:30 +0000 (20:29 +0100)
WinMute/UpdateChecker.cpp [new file with mode: 0644]
WinMute/UpdateChecker.h [new file with mode: 0644]
WinMute/WMSettings.cpp
WinMute/WMSettings.h
WinMute/WinMain.cpp
WinMute/WinMute.vcxproj
WinMute/WinMute.vcxproj.filters
WinMute/common.h

diff --git a/WinMute/UpdateChecker.cpp b/WinMute/UpdateChecker.cpp
new file mode 100644 (file)
index 0000000..131c378
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ WinMute
+           Copyright (c) 2023, Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the author nor the names of its contributors may
+      be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "common.h"
+
+class HInternetHolder {
+public:
+   HInternetHolder(HINTERNET hInternet)
+      : hInternet_(hInternet)
+   {}
+   ~HInternetHolder()
+   {
+      if (hInternet_ != nullptr) {
+         WinHttpCloseHandle(hInternet_);
+      }
+   }
+   operator HINTERNET()
+   {
+      return hInternet_;
+   }
+private:
+   HINTERNET hInternet_;
+};
+
+
+UpdateChecker::UpdateChecker(const WMSettings &settings):
+   settings_(settings)
+{
+
+}
+
+UpdateChecker::~UpdateChecker()
+{
+
+}
+
+bool UpdateChecker::ShouldUpdate(std::wstring& , std::wstring& ) const
+{
+   //if (!IsUpdateCheckEnabled()) {
+     // return false;
+   //}
+
+   WMLog &log = WMLog::GetInstance();
+   HInternetHolder hSession = WinHttpOpen(
+      L"WinMute",
+      WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY,
+      WINHTTP_NO_PROXY_NAME,
+      WINHTTP_NO_PROXY_BYPASS,
+      WINHTTP_FLAG_SECURE_DEFAULTS);
+   if (hSession == nullptr) {
+      log.WriteWindowsError(L"WinHttpOpen", GetLastError());
+      return false;
+   }
+
+   HInternetHolder hConnect = WinHttpConnect(
+      hSession,
+      L"raw.githubusercontent.com",
+      INTERNET_DEFAULT_HTTPS_PORT,
+      0);
+   if (hConnect == nullptr) {
+      log.WriteWindowsError(L"WinHttpConnect", GetLastError());
+      return false;
+   }
+
+#ifdef _DEBUG
+   const wchar_t *updateFileUrl = L"/lx-s/WinMute/dev/CURRENT_VERSION";
+#else
+   const wchar_t *updateFileUrl = L"/lx-s/WinMute/main/CURRENT_VERSION";
+#endif
+   HInternetHolder hRequest = WinHttpOpenRequest(
+      hConnect,
+      L"GET",
+      updateFileUrl,
+      nullptr,
+      WINHTTP_NO_REFERER,
+      WINHTTP_DEFAULT_ACCEPT_TYPES,
+      WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE);
+
+   if (hRequest == nullptr) {
+      log.WriteWindowsError(L"WinHttpConnect", GetLastError());
+      return false;
+   }
+
+   bool result = WinHttpSendRequest(
+         hRequest,
+         WINHTTP_NO_ADDITIONAL_HEADERS,
+         0,
+         WINHTTP_NO_REQUEST_DATA,
+         0,
+         0,
+         0);
+
+   if (!result) {
+      log.WriteWindowsError(L"WinHttpSendRequest", GetLastError());
+      return false;
+   }
+
+   result = WinHttpReceiveResponse(hRequest, nullptr);
+   if (!result) {
+      log.WriteWindowsError(L"WinHttpReceiveResponse", GetLastError());
+      return false;
+   }
+
+   DWORD statusCode = 0;
+   DWORD statusCodeSize = static_cast<DWORD>(sizeof(statusCode));
+   result = WinHttpQueryHeaders(
+      hRequest,
+      WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+      WINHTTP_HEADER_NAME_BY_INDEX,
+      reinterpret_cast<LPVOID>(&statusCode),
+      &statusCodeSize,
+      WINHTTP_NO_HEADER_INDEX);
+   if (!result) {
+      log.WriteWindowsError(L"WinHttpQueryHeaders(WINHTTP_QUERY_STATUS_CODE)", GetLastError());
+      return false;
+   } else if (statusCode != HTTP_STATUS_OK) {
+      log.Write(L"Update-Server returned HTTP %d", HTTP_STATUS_OK);
+      return false;
+   }
+
+   std::string versionFileContents;
+   for (;;) {
+      DWORD availBytes = 0;
+      if (!WinHttpQueryDataAvailable(hRequest, &availBytes)) {
+         log.WriteWindowsError(L"WinHttpQueryDataAvailable", GetLastError());
+         return false;
+      }
+      if (availBytes == 0) {
+         break;
+      }
+      std::string chunk(availBytes, ' ');
+      DWORD byRead = 0;
+      if (!WinHttpReadData(hRequest, reinterpret_cast<LPVOID>(&chunk[0]), availBytes, &byRead)) {
+         log.WriteWindowsError(L"WinHttpReadData", GetLastError());
+         return false;
+      }
+      versionFileContents.append(chunk.begin(), chunk.begin() + byRead);
+   }
+
+   // Check contents of version file
+   return true;
+}
+
+bool UpdateChecker::IsUpdateCheckEnabled() const
+{
+   const auto updateCheckSetting = settings_.QueryValue(SettingsKey::CHECK_FOR_UPDATE);
+   if (updateCheckSetting == static_cast<int>(UpdateCheckInterval::DISABLED)) {
+      return false;
+   }
+
+   wchar_t thisExePath[MAX_PATH * 2];
+   const DWORD thisExePathSize = ARRAY_SIZE(thisExePath);
+   const DWORD thisPathLen = GetModuleFileNameW(nullptr, thisExePath, thisExePathSize);
+   if (thisPathLen == 0 || (thisPathLen == thisExePathSize && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
+      WMLog::GetInstance().WriteWindowsError(L"GetModuleFileNameW", ERROR_INSUFFICIENT_BUFFER);
+      return false;
+   }
+   fs::path updateDisableFile{ thisExePath };
+   updateDisableFile.replace_filename(L"update-check-disabled");
+   if (fs::exists(updateDisableFile)) {
+      return false;
+   }
+
+   return true;
+}
diff --git a/WinMute/UpdateChecker.h b/WinMute/UpdateChecker.h
new file mode 100644 (file)
index 0000000..378760c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ WinMute
+           Copyright (c) 2023, Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the author nor the names of its contributors may
+      be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "WMSettings.h"
+
+enum class UpdateCheckInterval : int {
+   DISABLED = 0,
+   ON_STARTUP = 1,
+};
+
+class UpdateChecker {
+public:
+   explicit UpdateChecker(const WMSettings& settings);
+   ~UpdateChecker();
+
+   bool ShouldUpdate(std::wstring& curVersion, std::wstring& newVersion) const;
+   std::wstring GetUpdateURL() const;
+private:
+   UpdateChecker(const UpdateChecker &) = delete;
+   UpdateChecker &operator=(const UpdateChecker &) = delete;
+   UpdateChecker(const UpdateChecker &&) = delete;
+   UpdateChecker &operator=(const UpdateChecker &&) = delete;
+
+   bool IsUpdateCheckEnabled() const;
+
+   bool ExtractVersion(HINTERNET hRequest) const;
+
+   const WMSettings &settings_;
+};
index aaf4c62e59b41303c43ce707c71afd230bfd2f38..09438ccbe380835fa9549c4fc043d398198eb506 100644 (file)
@@ -122,6 +122,9 @@ static const wchar_t* KeyToStr(SettingsKey key)
    case SettingsKey::APP_LANGUAGE:
       keyStr = L"AppLanguage";
       break;
+   case SettingsKey::CHECK_FOR_UPDATE:
+      keyStr = L"CheckForUpdate";
+      break;
    }
    return keyStr;
 }
@@ -171,6 +174,8 @@ static DWORD GetDefaultSetting(SettingsKey key)
       return 0;
    case SettingsKey::APP_LANGUAGE:
       return 0;
+   case SettingsKey::CHECK_FOR_UPDATE:
+      return 0;
    }
    return 0;
 }
index af5b56178986fca83871d01ade6d20e8222d0f6c..c0e929dd18fd6148fd7eb3bfca8961346c9726c1 100644 (file)
@@ -65,6 +65,7 @@ enum class SettingsKey {
    , NOTIFICATIONS_ENABLED
    , LOGGING_ENABLED
    , APP_LANGUAGE
+   , CHECK_FOR_UPDATE
 };
 
 class WMSettings {
index e5f9a9f0b7899c9c7a1cb0aefb5aa85b16030842..42ad448cf9827fd60951c804f7ecb6651bc4041d 100644 (file)
@@ -97,6 +97,10 @@ int WINAPI wWinMain(
       return FALSE;
    }
 
+   UpdateChecker updateChecker(settings);
+   std::wstring w1, w2;
+   updateChecker.ShouldUpdate(w1, w2);
+
    LoadLanguage(settings, i18n);
 
    HANDLE hMutex = CreateMutexW(nullptr, TRUE, L"LxSystemsWinMuteRunOnce");
index 52f2d236b5caaa7b559f73db1aff795183485917..1a2356a19d73fea44c836b1d7f8d228017033a36 100644 (file)
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Advapi32.lib;Winhttp.lib;Bthprops.lib;comsuppwd.lib;comctl32.lib;strsafe.lib;UxTheme.lib;Winmm.lib;Wlanapi.lib;WtsApi32.lib;Shell32.lib;Version.lib;Gdi32.lib</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Advapi32.lib;Winhttp.lib;Bthprops.lib;comsuppwd.lib;comctl32.lib;strsafe.lib;UxTheme.lib;Winmm.lib;Wlanapi.lib;WtsApi32.lib;Shell32.lib;Version.lib;Gdi32.lib</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>Bthprops.lib;comsuppwd.lib;comctl32.lib;strsafe.lib;UxTheme.lib;Winmm.lib;Wlanapi.lib;WtsApi32.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Advapi32.lib;Winhttp.lib;Bthprops.lib;comsuppwd.lib;comctl32.lib;strsafe.lib;UxTheme.lib;Winmm.lib;Wlanapi.lib;WtsApi32.lib;Shell32.lib;Version.lib;Gdi32.lib</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>Bthprops.lib;comsuppwd.lib;comctl32.lib;strsafe.lib;UxTheme.lib;Winmm.lib;Wlanapi.lib;WtsApi32.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Advapi32.lib;Winhttp.lib;Bthprops.lib;comsuppwd.lib;comctl32.lib;strsafe.lib;UxTheme.lib;Winmm.lib;Wlanapi.lib;WtsApi32.lib;Shell32.lib;Version.lib;Gdi32.lib</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
     <ClInclude Include="common.h" />
     <ClInclude Include="libs\json.hpp" />
     <ClInclude Include="resource.h" />
+    <ClInclude Include="UpdateChecker.h" />
     <ClInclude Include="WiFiDetector.h" />
     <ClInclude Include="WMi18n.h" />
     <ClInclude Include="WMLog.h" />
     <ClCompile Include="Settings_ManageEndpointsDlg.cpp" />
     <ClCompile Include="Settings_MuteDlg.cpp" />
     <ClCompile Include="Settings_WifiDlg.cpp" />
+    <ClCompile Include="UpdateChecker.cpp" />
     <ClCompile Include="WifiDetector.cpp" />
     <ClCompile Include="WMi18n.cpp" />
     <ClCompile Include="WMLog.cpp" />
index 7514fe5047e669fedb08d2c53fbf6a9ee54e6ffe..10f4ab5e3edd2ceafede16e3af8f104b92f4d06f 100644 (file)
     <ClInclude Include="libs\json.hpp">
       <Filter>Source Files\_External</Filter>
     </ClInclude>
+    <ClInclude Include="UpdateChecker.h">
+      <Filter>Source Files\Base\Settings</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="WinMute.rc">
     <ClCompile Include="Settings_GeneralDlg.cpp">
       <Filter>Source Files\UI\Dialogs\Settings</Filter>
     </ClCompile>
-    <ClCompile Include="AboutDlg.cpp">
-      <Filter>Source Files\UI\Dialogs</Filter>
-    </ClCompile>
     <ClCompile Include="Settings_MuteDlg.cpp">
       <Filter>Source Files\UI\Dialogs\Settings</Filter>
     </ClCompile>
     <ClCompile Include="WMi18n.cpp">
       <Filter>Source Files\Base\Settings</Filter>
     </ClCompile>
+    <ClCompile Include="UpdateChecker.cpp">
+      <Filter>Source Files\Base\Settings</Filter>
+    </ClCompile>
+    <ClCompile Include="AboutDlg.cpp">
+      <Filter>Source Files\UI\Dialogs\Settings</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\Translations\lang-de.json">
index 6ef6ca7e8f89b7aae6141e1c811db862fe940a4e..eb2d32702f40d9de9b4ccdd1b9455f67ed78502c 100644 (file)
@@ -58,19 +58,20 @@ POSSIBILITY OF SUCH DAMAGE.
 #include <algorithm>
 #include <array>
 #include <cassert>
-#include <span>
 #include <chrono>
 #include <cstdarg>
 #include <filesystem>
-#include <optional>
 #include <fstream>
 #include <iterator>
 #include <locale>
+#include <map>
 #include <memory>
-#include <string_view>
+#include <optional>
+#include <span>
 #include <string>
+#include <string_view>
+#include <type_traits>
 #include <unordered_map>
-#include <map>
 #include <vector>
 
 namespace fs = std::filesystem;
@@ -79,6 +80,7 @@ namespace fs = std::filesystem;
 #include <windowsx.h>
 #include <commctrl.h>
 #include <WtsApi32.h>
+#include <winhttp.h>
 #include <dbt.h>
 #include <Bthdef.h>
 #include <Bthsdpdef.h>
@@ -103,6 +105,7 @@ namespace fs = std::filesystem;
 #include "WMi18n.h"
 #include "WMSettings.h"
 #include "WMLog.h"
+#include "UpdateChecker.h"
 #include "TrayIcon.h"
 #include "WinAudio.h"
 #include "MuteControl.h"
@@ -112,7 +115,6 @@ namespace fs = std::filesystem;
 #include "WinMute.h"
 #include "VersionHelper.h"
 
-
 // Utility
 void PrintWindowsError(const wchar_t *functionName, DWORD lastError = -1);
 bool GetWinMuteVersion(std::wstring &versNumber);