1+ #include < ntstatus.h>
2+ #define WIN32_NO_STATUS
3+
14#include " Platform/Platform.h"
5+ #include " Platform/PlatformCommon.h"
26#include " Util/TextUtils.h"
37#include " Log.h"
48#include " WindowsHelpers.h"
59#include " tf2_bot_detector_winrt.h"
610
711#include < mh/error/ensure.hpp>
12+ #include < mh/error/exception_details.hpp>
813#include < mh/text/codecvt.hpp>
914#include < mh/text/format.hpp>
1015#include < mh/text/formatters/error_code.hpp>
1116#include < mh/text/stringops.hpp>
1217
1318#define WIN32_LEAN_AND_MEAN 1
1419#include < Windows.h>
15- #include < minappmodel.h>
1620#include < Shlobj.h>
17- #include < versionhelpers .h>
21+ #include < winternl .h>
1822
1923using namespace tf2_bot_detector ;
2024using namespace std ::string_view_literals;
@@ -35,73 +39,6 @@ static std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id)
3539 return retVal;
3640}
3741
38- static void * GetProcAddressHelper (const wchar_t * moduleName, const char * symbolName, bool isCritical = false , MH_SOURCE_LOCATION_AUTO(location))
39- {
40- if (!moduleName)
41- throw std::invalid_argument (" moduleName was nullptr" );
42- if (!moduleName[0 ])
43- throw std::invalid_argument (" moduleName was empty" );
44- if (!symbolName)
45- throw std::invalid_argument (" symbolName was nullptr" );
46- if (!symbolName[0 ])
47- throw std::invalid_argument (" symbolName was empty" );
48-
49- HMODULE moduleHandle = GetModuleHandleW (moduleName);
50- if (!moduleHandle)
51- {
52- auto err = GetLastError ();
53- throw std::system_error (err, std::system_category (), mh::format (" Failed to GetModuleHandle({})" , mh::change_encoding<char >(moduleName)));
54- }
55-
56- auto address = GetProcAddress (moduleHandle, symbolName);
57- if (!address)
58- {
59- auto err = GetLastError ();
60- auto ec = std::error_code (err, std::system_category ());
61-
62- auto msg = mh::format (" {}: Failed to find function {} in {}" , location, symbolName, mh::change_encoding<char >(moduleName));
63-
64- if (!isCritical)
65- DebugLogWarning (location, " {}: {}" , msg, ec);
66- else
67- throw std::system_error (ec, msg);
68- }
69-
70- return address;
71- }
72-
73- namespace tf2_bot_detector
74- {
75- static const std::wstring& GetCurrentPackageFamilyName ()
76- {
77- static const std::wstring s_CurrentPackageFamilyName = []() -> std::wstring
78- {
79- WCHAR name[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1 ];
80- UINT32 nameLength = UINT32 (std::size (name));
81-
82- using func_type = LONG (*)(UINT32* packageFamilyNameLength, PWSTR packageFamilyName);
83-
84- const auto func = reinterpret_cast <func_type>(GetProcAddressHelper (L" Kernel32.dll" , " GetCurrentPackageFamilyName" , true ));
85-
86- const auto errc = func (&nameLength, name);
87-
88- switch (errc)
89- {
90- case ERROR_SUCCESS:
91- return std::wstring (name, nameLength > 0 ? (nameLength - 1 ) : 0 );
92- case APPMODEL_ERROR_NO_PACKAGE:
93- return {};
94- case ERROR_INSUFFICIENT_BUFFER:
95- throw std::runtime_error (mh::format (" {}: Buffer too small" , __FUNCTION__));
96- default :
97- throw std::runtime_error (mh::format (" {}: Unknown error {}" , __FUNCTION__, errc));
98- }
99- }();
100-
101- return s_CurrentPackageFamilyName;
102- }
103- }
104-
10542namespace
10643{
10744 class FallbackWinRTInterface final : public tf2_bot_detector::WinRT
@@ -119,21 +56,59 @@ namespace
11956 {
12057 return std::filesystem::temp_directory_path ();
12158 }
59+ std::wstring GetCurrentPackageFamilyName () const override
60+ {
61+ return {};
62+ }
63+ const mh::exception_details_handler& GetWinRTExceptionDetailsHandler () const override
64+ {
65+ assert (!" This should never be called in the first place" );
66+
67+ class Handler final : public mh::exception_details_handler
68+ {
69+ public:
70+ bool try_handle (const std::exception_ptr& e, mh::exception_details& details) const noexcept override
71+ {
72+ return false ;
73+ }
74+ } static const s_Handler;
75+
76+ return s_Handler;
77+ }
12278 };
12379}
12480
81+ static bool IsReallyWindows10OrGreater ()
82+ {
83+ using RtlGetVersionFn = NTSTATUS (*)(PRTL_OSVERSIONINFOW lpVersionInformation);
84+
85+ static const auto s_RtlGetVersionFn = reinterpret_cast <RtlGetVersionFn>(
86+ tf2_bot_detector::Platform::GetProcAddressHelper (" ntdll.dll" , " RtlGetVersion" , true ));
87+
88+ RTL_OSVERSIONINFOW info{};
89+ info.dwOSVersionInfoSize = sizeof (info);
90+ const auto result = s_RtlGetVersionFn (&info);
91+ assert (result == STATUS_SUCCESS);
92+
93+ return info.dwMajorVersion >= 10 ;
94+ }
95+
12596static const tf2_bot_detector::WinRT* GetWinRTInterface ()
12697{
12798 struct WinRTHelper
12899 {
129100 WinRTHelper ()
130101 {
131- constexpr wchar_t WINRT_DLL_NAME[] = L " tf2_bot_detector_winrt.dll" ;
132- m_Module = mh_ensure (LoadLibraryW (WINRT_DLL_NAME));
102+ constexpr char WINRT_DLL_NAME[] = " tf2_bot_detector_winrt.dll" ;
103+ m_Module = mh_ensure (LoadLibraryA (WINRT_DLL_NAME));
133104
134105 CreateWinRTInterfaceFn func = reinterpret_cast <CreateWinRTInterfaceFn>(GetProcAddressHelper (WINRT_DLL_NAME, " CreateWinRTInterface" ));
135106
136107 m_WinRT.reset (func ());
108+
109+ struct DummyType {};
110+ m_ExceptionDetailsHandler = mh::exception_details::add_handler (
111+ typeid (DummyType), m_WinRT->GetWinRTExceptionDetailsHandler ());
137112 }
138113 WinRTHelper (WinRTHelper&& other) noexcept :
139114 m_Module (std::exchange(other.m_Module, nullptr )),
@@ -167,19 +142,24 @@ static const tf2_bot_detector::WinRT* GetWinRTInterface()
167142
168143 HMODULE m_Module{};
169144 std::unique_ptr<WinRT> m_WinRT;
145+ mh::exception_details::handler m_ExceptionDetailsHandler;
170146 };
171147
172- static std::optional<WinRTHelper> s_Helper = []() -> std::optional<WinRTHelper>
148+ static const tf2_bot_detector::WinRT* s_Value = []() -> const tf2_bot_detector::WinRT*
173149 {
174- std::optional<WinRTHelper> helper;
175- if (IsWindows10OrGreater ())
176- helper.emplace ();
177-
178- return std::move (helper);
150+ if (IsReallyWindows10OrGreater ())
151+ {
152+ static WinRTHelper s_Helper;
153+ return s_Helper.m_WinRT .get ();
154+ }
155+ else
156+ {
157+ static const FallbackWinRTInterface s_FallbackInterface;
158+ return &s_FallbackInterface;
159+ }
179160 }();
180- static const FallbackWinRTInterface s_FallbackInterface;
181161
182- return s_Helper. has_value () ? s_Helper-> m_WinRT . get () : &s_FallbackInterface ;
162+ return s_Value ;
183163}
184164
185165std::filesystem::path tf2_bot_detector::Platform::GetCurrentExeDir ()
@@ -199,7 +179,7 @@ std::filesystem::path tf2_bot_detector::Platform::GetCurrentExeDir()
199179
200180std::filesystem::path tf2_bot_detector::Platform::GetLegacyAppDataDir ()
201181{
202- auto packageFamilyName = GetCurrentPackageFamilyName ();
182+ auto packageFamilyName = GetWinRTInterface ()-> GetCurrentPackageFamilyName ();
203183 if (packageFamilyName.empty ())
204184 return {};
205185
0 commit comments