From 4674f45dd3a9418a62374c378ade42e2bc7c9a18 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Sun, 27 Aug 2023 17:43:29 +0100 Subject: [PATCH] [*] Support for further Win32 API degradation / historical OSes / emulators --- Aurora.json | 7 +- Include/Aurora/Runtime.hpp | 1 + Source/AuProcAddresses.NT.cpp | 20 ++- Source/AuProcAddresses.NT.hpp | 142 ++++++++++++++++++++- Source/Debug/Demangle.cpp | 15 ++- Source/Debug/ExceptionWatcher.Win32.cpp | 19 ++- Source/Debug/Stack.Win32.cpp | 45 ++++--- Source/IO/Net/AuNetAdapter.NT.cpp | 158 ++++++++++++++++++++---- Source/Process/AuProcess.cpp | 14 ++- Source/SWInfo/AuSWInfo.NT.cpp | 16 ++- 10 files changed, 377 insertions(+), 60 deletions(-) diff --git a/Aurora.json b/Aurora.json index 9c1cc41a..e5d2af46 100644 --- a/Aurora.json +++ b/Aurora.json @@ -59,15 +59,10 @@ }, "then": { "links": [ - "Bcrypt.lib", - "UxTheme.lib", "Aux_ulib.lib", - "Dbghelp.lib", "ws2_32.lib", "Ntdll.lib", - "wintrust.lib", - "Winmm.lib", - "Iphlpapi.lib" + "Winmm.lib" ] } }, diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index 40b1db87..efd7c295 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -337,6 +337,7 @@ namespace Aurora @warning: 0 = 3 * 1024 * 1024 */ + bool bWin32VerifyTrustFailMissingAPI { true }; // just to not be annoying in the future }; struct ThreadingConfig diff --git a/Source/AuProcAddresses.NT.cpp b/Source/AuProcAddresses.NT.cpp index 04feaa18..dcf582cf 100644 --- a/Source/AuProcAddresses.NT.cpp +++ b/Source/AuProcAddresses.NT.cpp @@ -31,6 +31,9 @@ namespace Aurora ADD_LOAD_LIB(Theme); ADD_LOAD_LIB(Shell); ADD_LOAD_LIB(PSAPILegacy); + ADD_LOAD_LIB(DbgHelper); + ADD_LOAD_LIB(WinTrust); + ADD_LOAD_LIB(IPHelper); #define ADD_GET_PROC(name, proc) \ if (h ## name) \ @@ -88,6 +91,7 @@ namespace Aurora ADD_GET_PROC(Nt, NtQueryInformationProcess) ADD_GET_PROC(Nt, NtNotifyChangeDirectoryFile) ADD_GET_PROC(Nt, NtTerminateProcess) + ADD_GET_PROC(Nt, VerSetConditionMask) ADD_GET_PROC_BI(Kernel32, KernelBase, VirtualAlloc2) ADD_GET_PROC_BI(Kernel32, KernelBase, MapViewOfFile3) @@ -110,19 +114,33 @@ namespace Aurora ADD_GET_PROC(Kernel32, LCIDToLocaleName) ADD_GET_PROC(Kernel32, GetLocaleInfoW) ADD_GET_PROC(Kernel32, GetThreadId) + ADD_GET_PROC(Kernel32, VerifyVersionInfoW) ADD_GET_PROC_BI2(Kernel32, PSAPILegacy, K32GetProcessMemoryInfo, GetProcessMemoryInfo) ADD_GET_PROC(Sync, WaitOnAddress) ADD_GET_PROC(Sync, WakeByAddressSingle) ADD_GET_PROC(Sync, WakeByAddressAll) - + + ADD_GET_PROC(DbgHelper, UnDecorateSymbolName) + ADD_GET_PROC(DbgHelper, MiniDumpWriteDump) + ADD_GET_PROC(DbgHelper, SymInitialize) + ADD_GET_PROC(DbgHelper, SymGetModuleBase64) + ADD_GET_PROC(DbgHelper, SymGetLineFromAddr64) + ADD_GET_PROC(DbgHelper, SymFunctionTableAccess64) + ADD_GET_PROC(DbgHelper, StackWalk64) + ADD_GET_PROC(WS2, GetAddrInfoExW) ADD_GET_PROC(WS2, GetAddrInfoExCancel) ADD_GET_PROC(WS2, FreeAddrInfoExW) ADD_GET_PROC(WS2, getaddrinfo) ADD_GET_PROC(WS2, freeaddrinfo) + ADD_GET_PROC(WinTrust, WinVerifyTrust) + + ADD_GET_PROC(IPHelper, GetAdaptersAddresses) + ADD_GET_PROC(IPHelper, GetAdaptersInfo) + ADD_GET_PROC(AdvancedApi, CryptAcquireContextW) ADD_GET_PROC(AdvancedApi, CryptReleaseContext) ADD_GET_PROC(AdvancedApi, CryptGenRandom) diff --git a/Source/AuProcAddresses.NT.hpp b/Source/AuProcAddresses.NT.hpp index 1ba7de93..d3b3db66 100644 --- a/Source/AuProcAddresses.NT.hpp +++ b/Source/AuProcAddresses.NT.hpp @@ -8,6 +8,30 @@ #pragma once struct _PROCESS_MEMORY_COUNTERS; +struct _tagSTACKFRAME64; +struct _MINIDUMP_EXCEPTION_INFORMATION; +struct _MINIDUMP_USER_STREAM_INFORMATION; +struct _IMAGEHLP_LINE64; +struct _tagADDRESS64; +struct _MINIDUMP_CALLBACK_INFORMATION; +struct _MIB_IPADDRTABLE; +struct _IP_ADAPTER_INFO; +enum _MINIDUMP_TYPE; + +#if defined(AURORA_COMPILER_MSVC) + struct _IP_ADAPTER_ADDRESSES_LH; + struct _IP_ADAPTER_ADDRESSES_XP; + #if (NTDDI_VERSION >= NTDDI_VISTA) + typedef _IP_ADAPTER_ADDRESSES_LH IP_ADAPTER_ADDRESSES; + typedef _IP_ADAPTER_ADDRESSES_LH *PIP_ADAPTER_ADDRESSES; + #elif (NTDDI_VERSION >= NTDDI_WINXP) + typedef _IP_ADAPTER_ADDRESSES_XP IP_ADAPTER_ADDRESSES; + typedef _IP_ADAPTER_ADDRESSES_XP *PIP_ADAPTER_ADDRESSES; + #else + typedef _IP_ADAPTER_ADDRESSES_XP IP_ADAPTER_ADDRESSES; + typedef _IP_ADAPTER_ADDRESSES_XP *PIP_ADAPTER_ADDRESSES; + #endif +#endif namespace Aurora { @@ -23,7 +47,10 @@ namespace Aurora static const wchar_t *kThemeDllName { L"UxTheme.dll" }; static const wchar_t *kShellDllName { L"Shell32.dll" }; static const wchar_t *kPSAPILegacyDllName { L"psapi.dll" }; - + static const wchar_t *kDbgHelperDllName { L"dbghelp.dll" }; + static const wchar_t *kWinTrustDllName { L"WINTRUST.dll" }; + static const wchar_t *kIPHelperDllName { L"IPHLPAPI.dll" }; + struct WIN32_MEMORY_RANGE_ENTRY2 { PVOID VirtualAddress; @@ -275,6 +302,18 @@ namespace Aurora ); #endif + inline ULONGLONG(__stdcall *pVerSetConditionMask)( + ULONGLONG ConditionMask, + DWORD TypeMask, + BYTE Condition + ); + + inline BOOL(__stdcall *pVerifyVersionInfoW)( + LPOSVERSIONINFOEXW dwTypeMask, + DWORD TypeMask, + DWORDLONG dwlConditionMask + ); + inline HRESULT(__stdcall *pSetWindowTheme)( HWND hwnd, LPCWSTR pszSubAppName, @@ -351,6 +390,107 @@ namespace Aurora PWSTR * ppszPath ); + // dbghelp + + inline DWORD(__stdcall *pUnDecorateSymbolName)( + PCSTR name, + PSTR outputString, + DWORD maxStringLength, + DWORD flags + ); + + inline BOOL(__stdcall *pMiniDumpWriteDump)( + HANDLE hProcess, + DWORD ProcessId, + HANDLE hFile, + enum _MINIDUMP_TYPE DumpType, + _MINIDUMP_EXCEPTION_INFORMATION * ExceptionParam, + _MINIDUMP_USER_STREAM_INFORMATION * UserStreamParam, + _MINIDUMP_CALLBACK_INFORMATION * CallbackParam + ); + + inline BOOL(__stdcall *pSymInitialize)( + HANDLE hProcess, + PCSTR UserSearchPath, + BOOL fInvadeProcess + ); + + inline DWORD64(__stdcall *pSymGetModuleBase64)( + HANDLE hProcess, + DWORD64 qwAddr + ); + + inline BOOL(__stdcall *pSymGetLineFromAddr64)( + HANDLE hProcess, + DWORD64 qwAddr, + PDWORD pdwDisplacement, + _IMAGEHLP_LINE64 * Line64 + ); + + inline PVOID(__stdcall *pSymFunctionTableAccess64)( + HANDLE hProcess, + DWORD64 AddrBase + ); + + typedef BOOL(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)( + HANDLE hProcess, + DWORD64 qwBaseAddress, + PVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead + ); + + typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( + HANDLE hProcess, + DWORD64 AddrBase + ); + + typedef DWORD64(__stdcall *PGET_MODULE_BASE_ROUTINE64)( + HANDLE hProcess, + DWORD64 Address + ); + + typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)( + HANDLE hProcess, + HANDLE hThread, + _tagADDRESS64 * lpaddr + ); + + inline BOOL(__stdcall *pStackWalk64)( + DWORD MachineType, + HANDLE hProcess, + HANDLE hThread, + _tagSTACKFRAME64 * StackFrame, + PVOID ContextRecord, + PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress + ); + + // WINTRUST + + inline BOOL(__stdcall *pWinVerifyTrust)( + HWND hwnd, + GUID * pgActionID, + LPVOID pWVTData + ); + + // IP Helper + + inline ULONG(__stdcall *pGetAdaptersAddresses)( + ULONG Family, + ULONG Flags, + PVOID Reserved, + IP_ADAPTER_ADDRESSES *AdapterAddresses, + PULONG SizePointer + ); + + inline ULONG(__stdcall *pGetAdaptersInfo)( + _IP_ADAPTER_INFO * AdapterInfo, + PULONG SizePointer + ); + inline bool gUseNativeWaitMutex {}; inline bool gUseNativeWaitCondvar {}; inline bool gUseNativeWaitSemapahore {}; diff --git a/Source/Debug/Demangle.cpp b/Source/Debug/Demangle.cpp index 9d435a15..1baca002 100644 --- a/Source/Debug/Demangle.cpp +++ b/Source/Debug/Demangle.cpp @@ -51,13 +51,20 @@ namespace Aurora::Debug // On failure, the undecorated name is assigned the dname docorated name, which is offset by +1 (the '?' or '_' hint) if (strcmp(pInfo->_UndecoratedName, pInfo->_DecoratedName + 1) == 0) { - auto characters = UnDecorateSymbolName(pName.c_str(), poll.name, AuArraySize(poll.name), UNDNAME_32_BIT_DECODE); - if (!characters) + if (pUnDecorateSymbolName) + { + auto characters = pUnDecorateSymbolName(pName.c_str(), poll.name, AuArraySize(poll.name), UNDNAME_32_BIT_DECODE); + if (!characters) + { + return ret; + } + + ret.type = AuString(poll.name, characters); + } + else { return ret; } - - ret.type = AuString(poll.name, characters); } #else diff --git a/Source/Debug/ExceptionWatcher.Win32.cpp b/Source/Debug/ExceptionWatcher.Win32.cpp index 4f0f2bc2..432ef4c7 100644 --- a/Source/Debug/ExceptionWatcher.Win32.cpp +++ b/Source/Debug/ExceptionWatcher.Win32.cpp @@ -390,7 +390,12 @@ namespace Aurora::Debug goto miniDumpOut; } - ok = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)flags, &info, nullptr, nullptr); + if (!pMiniDumpWriteDump) + { + goto miniDumpOut; + } + + ok = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)flags, &info, nullptr, nullptr); if (!ok) { AuLogWarn("Couldn't write minidump: {:x}", GetLastError()); @@ -473,7 +478,12 @@ namespace Aurora::Debug goto miniMiniDumpOut; } - ok = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)flags, &info, nullptr, nullptr); + if (!pMiniDumpWriteDump) + { + goto miniMiniDumpOut; + } + + ok = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)flags, &info, nullptr, nullptr); if (!ok) { AuLogWarn("Couldn't write minidump: {:x}", GetLastError()); @@ -499,7 +509,10 @@ namespace Aurora::Debug static void CacheInternalBuildSymbols() { #if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG) - SymInitialize(GetCurrentProcess(), NULL, TRUE); + if (pSymInitialize) + { + pSymInitialize(GetCurrentProcess(), NULL, TRUE); + } #endif } diff --git a/Source/Debug/Stack.Win32.cpp b/Source/Debug/Stack.Win32.cpp index 0dec15bd..cf5d76a9 100644 --- a/Source/Debug/Stack.Win32.cpp +++ b/Source/Debug/Stack.Win32.cpp @@ -65,25 +65,29 @@ namespace Aurora::Debug for (ULONG frame = 0; ; frame++) { StackTraceEntry frameCurrent; + bool bResult {}; - auto result = StackWalk64 - ( - #if defined(AURORA_ARCH_X64) - IMAGE_FILE_MACHINE_AMD64, - #else - IMAGE_FILE_MACHINE_I386, - #endif - INVALID_HANDLE_VALUE, - INVALID_HANDLE_VALUE, - &stack, - &cpy, - NULL, - SymFunctionTableAccess64, - SymGetModuleBase64, - NULL - ); + if (pSymGetModuleBase64 && pStackWalk64) + { + bResult = pStackWalk64 + ( + #if defined(AURORA_ARCH_X64) + IMAGE_FILE_MACHINE_AMD64, + #else + IMAGE_FILE_MACHINE_I386, + #endif + INVALID_HANDLE_VALUE, + INVALID_HANDLE_VALUE, + &stack, + &cpy, + NULL, + pSymFunctionTableAccess64, + pSymGetModuleBase64, + NULL + ); + } - if (!result) + if (!bResult) { break; } @@ -109,9 +113,12 @@ namespace Aurora::Debug line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - if (SymGetLineFromAddr64(process, stack.AddrPC.Offset, &disp, &line)) + if (pSymGetLineFromAddr64) { - frameCurrent.file = AuMakeTuple(line.FileName, line.LineNumber, 0); + if (pSymGetLineFromAddr64(process, stack.AddrPC.Offset, &disp, &line)) + { + frameCurrent.file = AuMakeTuple(line.FileName, line.LineNumber, 0); + } } #endif diff --git a/Source/IO/Net/AuNetAdapter.NT.cpp b/Source/IO/Net/AuNetAdapter.NT.cpp index fbed92ab..8409fc5e 100644 --- a/Source/IO/Net/AuNetAdapter.NT.cpp +++ b/Source/IO/Net/AuNetAdapter.NT.cpp @@ -35,22 +35,28 @@ namespace Aurora::IO::Net } #if defined(AURORA_PLATFORM_WIN32) - AuSPtr GetAddressesForFamily(ULONG uFamily) + + AuSPtr GetAddressesForFamilyXP(ULONG uFamily) { static const auto kDefSize = 15 * 1024; - AuSPtr pAddresses; + if (!pGetAdaptersAddresses) + { + return {}; + } + + AuSPtr pAddresses; DWORD outBufLen { kDefSize }; DWORD dwRetVal; - DWORD dwFlags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS; + DWORD dwFlags = AuSwInfo::IsWindowsXPSP1OrGreater() ? GAA_FLAG_INCLUDE_PREFIX : 0; DWORD dwIterations {}; do { - pAddresses = AuReinterpretCast(AuMakeSharedArray(kDefSize)); + pAddresses = AuReinterpretCast(AuMakeSharedArray(kDefSize)); SysAssert(pAddresses); - dwRetVal = ::GetAdaptersAddresses(uFamily, dwFlags, NULL, pAddresses.get(), &outBufLen); + dwRetVal = pGetAdaptersAddresses(uFamily, dwFlags, NULL, (IP_ADAPTER_ADDRESSES *)(pAddresses.get()), &outBufLen); if (dwRetVal == 0) { @@ -70,10 +76,54 @@ namespace Aurora::IO::Net } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (dwIterations < 5)); - return dwRetVal == NO_ERROR ? pAddresses : AuSPtr {}; + return dwRetVal == NO_ERROR ? pAddresses : AuSPtr {}; + } + + AuSPtr GetAddressesForFamilyLH(ULONG uFamily) + { + static const auto kDefSize = 15 * 1024; + + if (!pGetAdaptersAddresses) + { + return {}; + } + + AuSPtr pAddresses; + DWORD outBufLen { kDefSize }; + DWORD dwRetVal; + + DWORD dwFlags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS; + DWORD dwIterations {}; + do + { + pAddresses = AuReinterpretCast(AuMakeSharedArray(kDefSize)); + SysAssert(pAddresses); + + dwRetVal = pGetAdaptersAddresses(uFamily, dwFlags, NULL, (IP_ADAPTER_ADDRESSES *)(pAddresses.get()), &outBufLen); + + if (dwRetVal == 0) + { + break; + } + else if (dwRetVal != ERROR_BUFFER_OVERFLOW) + { + } + else + { + SysPushErrorNet("Fail"); + break; + } + + dwIterations++; + + } + while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (dwIterations < 5)); + + return dwRetVal == NO_ERROR ? pAddresses : AuSPtr {}; } - AU_NOINLINE void AddressesToList(AuSPtr pAddresses, AuList> &adaptersOut) + template + AU_NOINLINE void AddressesToList(AuSPtr pAddresses, AuList> &adaptersOut) { auto pCurrAddresses = pAddresses.get(); @@ -125,18 +175,29 @@ namespace Aurora::IO::Net adapter.anycast = ep.ip; } - - auto pGateway = pCurrAddresses->FirstGatewayAddress; - if (pGateway) + if constexpr (!AuIsSame_v) { - NetEndpoint ep; - if (pGateway->Address.iSockaddrLength <= sizeof(ep.hint)) + auto pGateway = pCurrAddresses->FirstGatewayAddress; + if (pGateway) { - AuMemcpy(ep.hint, pGateway->Address.lpSockaddr, pGateway->Address.iSockaddrLength); - DeoptimizeEndpoint(ep); - } + NetEndpoint ep; + if (pGateway->Address.iSockaddrLength <= sizeof(ep.hint)) + { + AuMemcpy(ep.hint, pGateway->Address.lpSockaddr, pGateway->Address.iSockaddrLength); + DeoptimizeEndpoint(ep); + } - adapter.gateway = ep.ip; + adapter.gateway = ep.ip; + } + } + + if (adapter.address.ip == EIPProtocol::eIPProtocolV4) + { + adapter.index = pCurrAddresses->IfIndex; + } + else + { + adapter.index = adaptersOut.size(); } auto pDnsServers = pCurrAddresses->FirstDnsServerAddress; @@ -153,7 +214,7 @@ namespace Aurora::IO::Net adapter.dns.push_back(ep.ip); } - while (pDnsServers = pDnsServers->Next); + while ((pDnsServers = pDnsServers->Next)); } adaptersOut.push_back(pAdapter); @@ -162,14 +223,69 @@ namespace Aurora::IO::Net } } + static void FixupXPGatewaysIPv4() + { + IP_ADAPTER_INFO info[128]; + DWORD size { sizeof(info) }; + IP_ADAPTER_INFO *pAdapter {}; + + if (!pGetAdaptersInfo) + { + return; + } + + ULONG error; + if ((error = pGetAdaptersInfo(info, &size)) != NO_ERROR) + { + if (error == ERROR_NO_DATA) + { + return; + } + + SysPushErrorNet("GetAdaptersInfo failed"); + return; + } + + if (size == 0) + { + return; + } + + auto pIPAddrTable = info; + while (pIPAddrTable) + { + for (auto &pAdapter : gIpv4Adapters) + { + auto pAdapterEx = AuStaticCast(pAdapter); + if (pAdapterEx->device == AuString(pIPAddrTable->AdapterName)) + { + pAdapterEx->gateway = IPAddress(pIPAddrTable->GatewayList.IpAddress.String); + } + } + + pIPAddrTable = pIPAddrTable->Next; + } + } + #endif static void PrecacheAdapters() { - auto pAdaptersV4 = GetAddressesForFamily(AF_INET); - auto pAdaptersV6 = GetAddressesForFamily(AF_INET6); - AddressesToList(pAdaptersV4, gIpv4Adapters); - AddressesToList(pAdaptersV6, gIpv6Adapters); + if (!AuSwInfo::IsWindowsVistaOrGreater()) + { + auto pAdaptersV4 = GetAddressesForFamilyXP(AF_INET); + auto pAdaptersV6 = GetAddressesForFamilyXP(AF_INET6); + AddressesToList(pAdaptersV4, gIpv4Adapters); + AddressesToList(pAdaptersV6, gIpv6Adapters); + FixupXPGatewaysIPv4(); + } + else + { + auto pAdaptersV4 = GetAddressesForFamilyLH(AF_INET); + auto pAdaptersV6 = GetAddressesForFamilyLH(AF_INET6); + AddressesToList(pAdaptersV4, gIpv4Adapters); + AddressesToList(pAdaptersV6, gIpv6Adapters); + } } AuList> NetAdapter::GetIPv4s() diff --git a/Source/Process/AuProcess.cpp b/Source/Process/AuProcess.cpp index dd847528..389574c9 100644 --- a/Source/Process/AuProcess.cpp +++ b/Source/Process/AuProcess.cpp @@ -190,9 +190,14 @@ namespace Aurora::Process // Set pFile. WinTrustData.pFile = &FileData; + if (!pWinVerifyTrust) + { + return gRuntimeConfig.debug.bWin32VerifyTrustFailMissingAPI; + } + // WinVerifyTrust verifies signatures as specified by the GUID // and Wintrust_Data. - lStatus = WinVerifyTrust( + lStatus = pWinVerifyTrust( NULL, &WVTPolicyGUID, &WinTrustData); @@ -245,7 +250,12 @@ namespace Aurora::Process WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE; - lStatus = WinVerifyTrust( + if (!pWinVerifyTrust) + { + return gRuntimeConfig.debug.bWin32VerifyTrustFailMissingAPI; + } + + lStatus = pWinVerifyTrust( NULL, &WVTPolicyGUID, &WinTrustData); diff --git a/Source/SWInfo/AuSWInfo.NT.cpp b/Source/SWInfo/AuSWInfo.NT.cpp index a09f3c9c..423d78d7 100644 --- a/Source/SWInfo/AuSWInfo.NT.cpp +++ b/Source/SWInfo/AuSWInfo.NT.cpp @@ -25,10 +25,20 @@ namespace Aurora::SWInfo static bool IsWindowsEnterpriseBranch() { - OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, VER_SUITE_ENTERPRISE, 0, 0}; - DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_SUITENAME, VER_EQUAL); + if (!pVerifyVersionInfoW) + { + return false; + } - return !VerifyVersionInfoW(&osvi, VER_SUITENAME, dwlConditionMask); + if (!pVerSetConditionMask) + { + return false; + } + + OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, VER_SUITE_ENTERPRISE, 0, 0}; + DWORDLONG const dwlConditionMask = pVerSetConditionMask(0, VER_SUITENAME, VER_EQUAL); + + return !pVerifyVersionInfoW(&osvi, VER_SUITENAME, dwlConditionMask); } auline bool Win32ReadRegistry(HKEY hKey, const wchar_t *pWideKey, AuString &strValue)