1
0
Fork 0

Merge pull request #3668 from torusrxxx/patch000000fd

Upgrade _WIN32_WINNT to Windows 7
This commit is contained in:
Duncan Ogilvie 2025-08-17 18:02:49 +02:00 committed by GitHub
commit c84549a8ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 138 additions and 416 deletions

1
CMakeLists.txt generated
View File

@ -442,6 +442,7 @@ target_link_libraries(dbg PRIVATE
Shlwapi
Ws2_32
Wininet
Iphlpapi
)
if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x86

View File

@ -105,6 +105,7 @@ private-link-libraries = [
"Shlwapi",
"Ws2_32",
"Wininet",
"Iphlpapi",
]
x86.private-link-libraries = [
"src/dbg/dbghelp/dbghelp_x86.lib",

View File

@ -403,27 +403,14 @@ void WaitForMultipleThreadsTermination(const HANDLE* hThread, int count, DWORD t
duint GetThreadCount()
{
duint threadCount = std::thread::hardware_concurrency();
typedef BOOL(WINAPI * GetLogicalProcessorInformationEx_t)(
LOGICAL_PROCESSOR_RELATIONSHIP,
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX,
PDWORD
);
static auto p_GetLogicalProcessorInformationEx = (GetLogicalProcessorInformationEx_t)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetLogicalProcessorInformationEx");
if(p_GetLogicalProcessorInformationEx == nullptr)
{
return threadCount;
}
DWORD length = 0;
if(p_GetLogicalProcessorInformationEx(RelationAll, nullptr, &length) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
if(GetLogicalProcessorInformationEx(RelationAll, nullptr, &length) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return threadCount;
}
std::vector<uint8_t> buffer(length);
if(!p_GetLogicalProcessorInformationEx(RelationAll, (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)buffer.data(), &length))
if(!GetLogicalProcessorInformationEx(RelationAll, (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)buffer.data(), &length))
{
return threadCount;
}

View File

@ -1,11 +1,7 @@
#pragma once
#ifndef _WIN32_WINNT
#ifdef _WIN64
#define _WIN32_WINNT 0x0502 // XP x64 is version 5.2
#else
#define _WIN32_WINNT 0x0501
#endif
#define _WIN32_WINNT 0x0601 // XP x64 is version 5.2, Vista is version 6.0, Windows 7 is version 6.1
#endif // _WIN32_WINNT
#ifdef WINVER // Overwrite WINVER if given on command line
@ -14,7 +10,7 @@
#define WINVER _WIN32_WINNT
#ifndef _WIN32_IE
#define _WIN32_IE 0x0500
#define _WIN32_IE _WIN32_IE_WIN7
#endif //_WIN32_IE
#include "ntdll/ntdll.h"

View File

@ -76,19 +76,11 @@ class SearchTimer
public:
SearchTimer()
{
if(!LPFN_GetTickCount64)
LPFN_GetTickCount64 = (ULONGLONG(*)())GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetTickCount64");
if(LPFN_GetTickCount64)
ticks = LPFN_GetTickCount64();
else
ticks = GetTickCount();
ticks = GetTickCount64();
}
void StopTimer()
{
if(LPFN_GetTickCount64)
ticks = LPFN_GetTickCount64() - ticks;
else
ticks = GetTickCount() - ticks;
ticks = GetTickCount64() - ticks;
}
DWORD GetTicks()
{
@ -96,9 +88,7 @@ public:
}
private:
ULONGLONG ticks;
static ULONGLONG(*LPFN_GetTickCount64)();
};
ULONGLONG(*SearchTimer::LPFN_GetTickCount64)() = nullptr;
bool cbInstrFind(int argc, char* argv[])
{

View File

@ -468,12 +468,7 @@ namespace Exprfunc
duint gettickcount()
{
#ifdef _WIN64
static auto GTC64 = (ULONGLONG(*)())GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetTickCount64");
if(GTC64)
return GTC64();
#endif //_WIN64
return GetTickCount();
return (duint)GetTickCount64();
}
duint rdtsc()

View File

@ -163,36 +163,15 @@ bool HandlesGetName(HANDLE remoteHandle, String & name, String & typeName)
}
else if(strcmp(typeName.c_str(), "Thread") == 0)
{
auto getTidPid = [](HANDLE hThread, DWORD & TID, DWORD & PID)
{
static auto pGetThreadId = (DWORD(__stdcall*)(HANDLE))GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetThreadId");
static auto pGetProcessIdOfThread = (DWORD(__stdcall*)(HANDLE))GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetProcessIdOfThread");
if(pGetThreadId != NULL && pGetProcessIdOfThread != NULL) //Vista or Server 2003 only
{
TID = pGetThreadId(hThread);
PID = pGetProcessIdOfThread(hThread);
}
else //Windows XP
{
THREAD_BASIC_INFORMATION threadInfo;
ULONG threadInfoSize = 0;
NTSTATUS isok = NtQueryInformationThread(hThread, ThreadBasicInformation, &threadInfo, sizeof(threadInfo), &threadInfoSize);
if(NT_SUCCESS(isok))
{
TID = (DWORD)(duint)threadInfo.ClientId.UniqueThread;
PID = (DWORD)(duint)threadInfo.ClientId.UniqueProcess;
}
}
};
DWORD TID, PID;
getTidPid(hLocalHandle, TID, PID);
auto TID = GetThreadId(hLocalHandle);
auto PID = GetProcessIdOfThread(hLocalHandle);
if(TID == 0 || PID == 0) //The first time could fail because the process didn't specify query permissions.
{
HANDLE hLocalQueryHandle;
if(DuplicateHandle(hProcess, remoteHandle, GetCurrentProcess(), &hLocalQueryHandle, THREAD_QUERY_INFORMATION, FALSE, 0))
{
getTidPid(hLocalQueryHandle, TID, PID);
TID = GetThreadId(hLocalQueryHandle);
PID = GetProcessIdOfThread(hLocalQueryHandle);
CloseHandle(hLocalQueryHandle);
}
}

View File

@ -1,11 +1,7 @@
#pragma once
#ifndef _WIN32_WINNT
#ifdef _WIN64
#define _WIN32_WINNT 0x0502 // XP x64 is version 5.2
#else
#define _WIN32_WINNT 0x0501
#endif
#define _WIN32_WINNT 0x0601 // XP x64 is version 5.2, Vista is version 6.0, Windows 7 is version 6.1
#endif // _WIN32_WINNT
#ifdef WINVER // Overwrite WINVER if given on command line
@ -14,7 +10,7 @@
#define WINVER _WIN32_WINNT
#ifndef _WIN32_IE
#define _WIN32_IE 0x0500
#define _WIN32_IE _WIN32_IE_WIN7
#endif //_WIN32_IE
#ifdef __cplusplus

View File

@ -1,195 +1,102 @@
#include "tcpconnections.h"
#include <WS2tcpip.h>
typedef enum
{
DBG_MIB_TCP_STATE_CLOSED = 1,
DBG_MIB_TCP_STATE_LISTEN = 2,
DBG_MIB_TCP_STATE_SYN_SENT = 3,
DBG_MIB_TCP_STATE_SYN_RCVD = 4,
DBG_MIB_TCP_STATE_ESTAB = 5,
DBG_MIB_TCP_STATE_FIN_WAIT1 = 6,
DBG_MIB_TCP_STATE_FIN_WAIT2 = 7,
DBG_MIB_TCP_STATE_CLOSE_WAIT = 8,
DBG_MIB_TCP_STATE_CLOSING = 9,
DBG_MIB_TCP_STATE_LAST_ACK = 10,
DBG_MIB_TCP_STATE_TIME_WAIT = 11,
DBG_MIB_TCP_STATE_DELETE_TCB = 12,
} DBG_MIB_TCP_STATE;
#include <iphlpapi.h>
static const char* TcpStateToString(unsigned int State)
{
switch(State)
{
case DBG_MIB_TCP_STATE_CLOSED:
case MIB_TCP_STATE_CLOSED:
return "CLOSED";
case DBG_MIB_TCP_STATE_LISTEN:
case MIB_TCP_STATE_LISTEN:
return "LISTEN";
case DBG_MIB_TCP_STATE_SYN_SENT:
case MIB_TCP_STATE_SYN_SENT:
return "SYN-SENT";
case DBG_MIB_TCP_STATE_SYN_RCVD:
case MIB_TCP_STATE_SYN_RCVD:
return "SYN-RECEIVED";
case DBG_MIB_TCP_STATE_ESTAB:
case MIB_TCP_STATE_ESTAB:
return "ESTABLISHED";
case DBG_MIB_TCP_STATE_FIN_WAIT1:
case MIB_TCP_STATE_FIN_WAIT1:
return "FIN-WAIT-1";
case DBG_MIB_TCP_STATE_FIN_WAIT2:
case MIB_TCP_STATE_FIN_WAIT2:
return "FIN-WAIT-2";
case DBG_MIB_TCP_STATE_CLOSE_WAIT:
case MIB_TCP_STATE_CLOSE_WAIT:
return "CLOSE-WAIT";
case DBG_MIB_TCP_STATE_CLOSING:
case MIB_TCP_STATE_CLOSING:
return "CLOSING";
case DBG_MIB_TCP_STATE_LAST_ACK:
case MIB_TCP_STATE_LAST_ACK:
return "LAST-ACK";
case DBG_MIB_TCP_STATE_TIME_WAIT:
case MIB_TCP_STATE_TIME_WAIT:
return "TIME-WAIT";
case DBG_MIB_TCP_STATE_DELETE_TCB:
case MIB_TCP_STATE_DELETE_TCB:
return "DELETE-TCB";
default:
return "UNKNOWN";
}
}
typedef enum
{
DbgTcpConnectionOffloadStateInHost,
DbgTcpConnectionOffloadStateOffloading,
DbgTcpConnectionOffloadStateOffloaded,
DbgTcpConnectionOffloadStateUploading,
DbgTcpConnectionOffloadStateMax
} DBG_TCP_CONNECTION_OFFLOAD_STATE, *PTCP_CONNECTION_OFFLOAD_STATE;
typedef struct _DBG_MIB_TCPROW2
{
DWORD dwState;
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwRemoteAddr;
DWORD dwRemotePort;
DWORD dwOwningPid;
DBG_TCP_CONNECTION_OFFLOAD_STATE dwOffloadState;
} DBG_MIB_TCPROW2, *PDBG_MIB_TCPROW2;
typedef struct _DBG_MIB_TCPTABLE2
{
DWORD dwNumEntries;
DBG_MIB_TCPROW2 table[1];
} DBG_MIB_TCPTABLE2, *PDBG_MIB_TCPTABLE2;
typedef struct _DBG_IN6_ADDR
{
union
{
UCHAR Byte[16];
USHORT Word[8];
} u;
} DBG_IN6_ADDR, * PDBG_IN6_ADDR, FAR* LPDBG_IN6_ADDR;
typedef struct _MIB_TCP6ROW2
{
DBG_IN6_ADDR LocalAddr;
DWORD dwLocalScopeId;
DWORD dwLocalPort;
DBG_IN6_ADDR RemoteAddr;
DWORD dwRemoteScopeId;
DWORD dwRemotePort;
DWORD State;
DWORD dwOwningPid;
DBG_TCP_CONNECTION_OFFLOAD_STATE dwOffloadState;
} DBG_MIB_TCP6ROW2, *PDBG_MIB_TCP6ROW2;
typedef struct _DBG_MIB_TCP6TABLE2
{
DWORD dwNumEntries;
DBG_MIB_TCP6ROW2 table[1];
} DBG_MIB_TCP6TABLE2, *PDBG_MIB_TCP6TABLE2;
typedef ULONG(WINAPI* GETTCPTABLE2)(PDBG_MIB_TCPTABLE2 TcpTable, PULONG SizePointer, BOOL Order);
typedef ULONG(WINAPI* GETTCP6TABLE2)(PDBG_MIB_TCP6TABLE2 TcpTable, PULONG SizePointer, BOOL Order);
typedef PCTSTR(WINAPI* INETNTOPW)(INT Family, PVOID pAddr, wchar_t* pStringBuf, size_t StringBufSize);
bool TcpEnumConnections(duint pid, std::vector<TCPCONNECTIONINFO> & connections)
{
// The following code is modified from code sample at MSDN.GetTcpTable2
static auto hIpHlp = LoadLibraryW(L"iphlpapi.dll");
if(!hIpHlp)
return false;
// To ensure WindowsXP compatibility we won't link them statically
static auto pGetTcpTable2 = GETTCPTABLE2(GetProcAddress(hIpHlp, "GetTcpTable2"));
static auto pGetTcp6Table2 = GETTCP6TABLE2(GetProcAddress(hIpHlp, "GetTcp6Table2"));
static auto pInetNtopW = INETNTOPW(GetProcAddress(GetModuleHandleW(L"ws2_32.dll"), "InetNtopW"));
if(!pInetNtopW)
return false;
TCPCONNECTIONINFO info;
wchar_t AddrBuffer[TCP_ADDR_SIZE] = L"";
if(pGetTcpTable2)
ULONG ulSize = 0;
// Make an initial call to GetTcpTable2 to get the necessary size into the ulSize variable
if(GetTcpTable2(nullptr, &ulSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
{
ULONG ulSize = 0;
// Make an initial call to GetTcpTable2 to get the necessary size into the ulSize variable
if(pGetTcpTable2(nullptr, &ulSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
Memory<MIB_TCPTABLE2*> pTcpTable(ulSize);
// Make a second call to GetTcpTable2 to get the actual data we require
if(GetTcpTable2(pTcpTable(), &ulSize, TRUE) == NO_ERROR)
{
Memory<DBG_MIB_TCPTABLE2*> pTcpTable(ulSize);
// Make a second call to GetTcpTable2 to get the actual data we require
if(pGetTcpTable2(pTcpTable(), &ulSize, TRUE) == NO_ERROR)
for(auto i = 0; i < int(pTcpTable()->dwNumEntries); i++)
{
for(auto i = 0; i < int(pTcpTable()->dwNumEntries); i++)
{
auto & entry = pTcpTable()->table[i];
if(entry.dwOwningPid != pid)
continue;
auto & entry = pTcpTable()->table[i];
if(entry.dwOwningPid != pid)
continue;
info.State = entry.dwState;
strcpy_s(info.StateText, TcpStateToString(info.State));
info.State = entry.dwState;
strcpy_s(info.StateText, TcpStateToString(info.State));
struct in_addr IpAddr;
IpAddr.S_un.S_addr = u_long(entry.dwLocalAddr);
pInetNtopW(AF_INET, &IpAddr, AddrBuffer, TCP_ADDR_SIZE);
strcpy_s(info.LocalAddress, StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.LocalPort = ntohs(u_short(entry.dwLocalPort));
struct in_addr IpAddr;
IpAddr.S_un.S_addr = u_long(entry.dwLocalAddr);
InetNtopW(AF_INET, &IpAddr, AddrBuffer, TCP_ADDR_SIZE);
strcpy_s(info.LocalAddress, StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.LocalPort = ntohs(u_short(entry.dwLocalPort));
IpAddr.S_un.S_addr = u_long(entry.dwRemoteAddr);
pInetNtopW(AF_INET, &IpAddr, AddrBuffer, TCP_ADDR_SIZE);
strcpy_s(info.RemoteAddress, StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.RemotePort = ntohs(u_short(entry.dwRemotePort));
IpAddr.S_un.S_addr = u_long(entry.dwRemoteAddr);
InetNtopW(AF_INET, &IpAddr, AddrBuffer, TCP_ADDR_SIZE);
strcpy_s(info.RemoteAddress, StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.RemotePort = ntohs(u_short(entry.dwRemotePort));
connections.push_back(info);
}
connections.push_back(info);
}
}
}
if(pGetTcp6Table2)
ulSize = 0;
// Make an initial call to GetTcp6Table2 to get the necessary size into the ulSize variable
if(GetTcp6Table2(nullptr, &ulSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
{
ULONG ulSize = 0;
// Make an initial call to GetTcp6Table2 to get the necessary size into the ulSize variable
if(pGetTcp6Table2(nullptr, &ulSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
Memory<MIB_TCP6TABLE2*> pTcp6Table(ulSize);
// Make a second call to GetTcpTable2 to get the actual data we require
if(GetTcp6Table2(pTcp6Table(), &ulSize, TRUE) == NO_ERROR)
{
Memory<DBG_MIB_TCP6TABLE2*> pTcp6Table(ulSize);
// Make a second call to GetTcpTable2 to get the actual data we require
if(pGetTcp6Table2(pTcp6Table(), &ulSize, TRUE) == NO_ERROR)
for(auto i = 0; i < int(pTcp6Table()->dwNumEntries); i++)
{
for(auto i = 0; i < int(pTcp6Table()->dwNumEntries); i++)
{
auto & entry = pTcp6Table()->table[i];
if(entry.dwOwningPid != pid)
continue;
auto & entry = pTcp6Table()->table[i];
if(entry.dwOwningPid != pid)
continue;
info.State = entry.State;
strcpy_s(info.StateText, TcpStateToString(info.State));
info.State = entry.State;
strcpy_s(info.StateText, TcpStateToString(info.State));
pInetNtopW(AF_INET6, &entry.LocalAddr, AddrBuffer, TCP_ADDR_SIZE);
sprintf_s(info.LocalAddress, "[%s]", StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.LocalPort = ntohs(u_short(entry.dwLocalPort));
InetNtopW(AF_INET6, &entry.LocalAddr, AddrBuffer, TCP_ADDR_SIZE);
sprintf_s(info.LocalAddress, "[%s]", StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.LocalPort = ntohs(u_short(entry.dwLocalPort));
pInetNtopW(AF_INET6, &entry.RemoteAddr, AddrBuffer, TCP_ADDR_SIZE);
sprintf_s(info.RemoteAddress, "[%s]", StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.RemotePort = ntohs(u_short(entry.dwRemotePort));
InetNtopW(AF_INET6, &entry.RemoteAddr, AddrBuffer, TCP_ADDR_SIZE);
sprintf_s(info.RemoteAddress, "[%s]", StringUtils::Utf16ToUtf8(AddrBuffer).c_str());
info.RemotePort = ntohs(u_short(entry.dwRemotePort));
connections.push_back(info);
}
connections.push_back(info);
}
}
}

View File

@ -12,16 +12,6 @@
static std::unordered_map<DWORD, THREADINFO> threadList;
static std::unordered_map<DWORD, THREADWAITREASON> threadWaitReasons;
// Function pointer for dynamic linking. Do not link statically for Windows XP compatibility.
// TODO: move this function definition out of thread.cpp
BOOL(WINAPI* pQueryThreadCycleTime)(HANDLE ThreadHandle, PULONG64 CycleTime) = nullptr;
BOOL WINAPI QueryThreadCycleTimeUnsupported(HANDLE ThreadHandle, PULONG64 CycleTime)
{
*CycleTime = 0;
return TRUE;
}
void ThreadCreate(CREATE_THREAD_DEBUG_INFO* CreateThread)
{
THREADINFO curInfo;
@ -328,9 +318,7 @@ DWORD ThreadGetId(HANDLE Thread)
}
// Wasn't found, check with Windows
typedef DWORD (WINAPI * GETTHREADID)(HANDLE hThread);
static GETTHREADID _GetThreadId = (GETTHREADID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetThreadId");
return _GetThreadId ? _GetThreadId(Thread) : 0;
return GetThreadId(Thread);
}
int ThreadSuspendAll()
@ -393,16 +381,9 @@ ULONG64 ThreadQueryCycleTime(HANDLE hThread)
{
ULONG64 CycleTime;
// Initialize function pointer
if(pQueryThreadCycleTime == nullptr)
{
pQueryThreadCycleTime = (BOOL(WINAPI*)(HANDLE, PULONG64))GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "QueryThreadCycleTime");
if(pQueryThreadCycleTime == nullptr)
pQueryThreadCycleTime = QueryThreadCycleTimeUnsupported;
}
if(!pQueryThreadCycleTime(hThread, &CycleTime))
if(!QueryThreadCycleTime(hThread, &CycleTime))
CycleTime = 0;
return CycleTime;
}

View File

@ -50,18 +50,10 @@ void waitdeinitialize()
}
bool SectionLockerGlobal::m_Initialized = false;
bool SectionLockerGlobal::m_SRWLocks = false;
CacheAligned<SRWLOCK> SectionLockerGlobal::m_srwLocks[SectionLock::LockLast];
SectionLockerGlobal::owner_info SectionLockerGlobal::m_exclusiveOwner[SectionLock::LockLast];
CacheAligned<CRITICAL_SECTION> SectionLockerGlobal::m_crLocks[SectionLock::LockLast];
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_InitializeSRWLock;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockShared;
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockShared;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockExclusive;
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockExclusive;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockShared;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockExclusive;
CacheAligned<SRWLOCK> SectionLockerGlobal::m_srwLocks[SectionLock::LockLast];
SectionLockerGlobal::owner_info SectionLockerGlobal::m_exclusiveOwner[SectionLock::LockLast];
DWORD SectionLockerGlobal::m_guiMainThreadId;
void SectionLockerGlobal::Initialize()
@ -74,40 +66,11 @@ void SectionLockerGlobal::Initialize()
// This gets called on the same thread as the GUI
m_guiMainThreadId = GetCurrentThreadId();
// Attempt to read the SRWLock API
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
m_InitializeSRWLock = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "InitializeSRWLock");
m_AcquireSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockShared");
m_TryAcquireSRWLockShared = (TRYSRWLOCKFUNCTION)GetProcAddress(hKernel32, "TryAcquireSRWLockShared");
m_AcquireSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockExclusive");
m_TryAcquireSRWLockExclusive = (TRYSRWLOCKFUNCTION)GetProcAddress(hKernel32, "TryAcquireSRWLockExclusive");
m_ReleaseSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockShared");
m_ReleaseSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockExclusive");
// Destroy previous data if any existed
memset(m_srwLocks, 0, sizeof(m_srwLocks));
m_SRWLocks = m_InitializeSRWLock &&
m_AcquireSRWLockShared &&
m_TryAcquireSRWLockShared &&
m_AcquireSRWLockExclusive &&
m_TryAcquireSRWLockExclusive &&
m_ReleaseSRWLockShared &&
m_ReleaseSRWLockExclusive;
if(m_SRWLocks) // Prefer SRWLocks
{
// Destroy previous data if any existed
memset(m_srwLocks, 0, sizeof(m_srwLocks));
for(int i = 0; i < ARRAYSIZE(m_srwLocks); i++)
m_InitializeSRWLock(&m_srwLocks[i]);
}
else // Fall back to critical sections otherwise
{
// Destroy previous data if any existed
memset(m_crLocks, 0, sizeof(m_crLocks));
for(int i = 0; i < ARRAYSIZE(m_crLocks); i++)
InitializeCriticalSection(&m_crLocks[i]);
}
for(int i = 0; i < ARRAYSIZE(m_srwLocks); i++)
InitializeSRWLock(&m_srwLocks[i]);
m_Initialized = true;
}
@ -117,30 +80,14 @@ void SectionLockerGlobal::Deinitialize()
if(!m_Initialized)
return;
if(m_SRWLocks)
for(int i = 0; i < ARRAYSIZE(m_srwLocks); i++)
{
for(int i = 0; i < ARRAYSIZE(m_srwLocks); i++)
{
// Wait for the lock's ownership to be released
m_AcquireSRWLockExclusive(&m_srwLocks[i]);
m_ReleaseSRWLockExclusive(&m_srwLocks[i]);
// Wait for the lock's ownership to be released
AcquireSRWLockExclusive(&m_srwLocks[i]);
ReleaseSRWLockExclusive(&m_srwLocks[i]);
// Invalidate data
memset(&m_srwLocks[i], 0, sizeof(SRWLOCK));
}
}
else
{
for(int i = 0; i < ARRAYSIZE(m_crLocks); i++)
{
// Wait for the lock's ownership to be released
EnterCriticalSection(&m_crLocks[i]);
LeaveCriticalSection(&m_crLocks[i]);
// Delete critical section
DeleteCriticalSection(&m_crLocks[i]);
memset(&m_crLocks[i], 0, sizeof(CRITICAL_SECTION));
}
// Invalidate data
memset(&m_srwLocks[i], 0, sizeof(SRWLOCK));
}
m_Initialized = false;

View File

@ -104,110 +104,77 @@ private:
static void AcquireLock()
{
auto threadId = GetCurrentThreadId();
if(m_SRWLocks)
auto srwLock = &m_srwLocks[LockIndex];
if(Shared)
{
auto srwLock = &m_srwLocks[LockIndex];
if(Shared)
{
if(m_exclusiveOwner[LockIndex].threadId == threadId)
return;
if(ProcessGuiEvents && threadId == m_guiMainThreadId)
{
while(!m_TryAcquireSRWLockShared(srwLock))
GuiProcessEvents();
}
else
{
m_AcquireSRWLockShared(srwLock);
}
return;
}
if(m_exclusiveOwner[LockIndex].threadId == threadId)
{
assert(m_exclusiveOwner[LockIndex].count > 0);
m_exclusiveOwner[LockIndex].count++;
return;
}
if(ProcessGuiEvents && threadId == m_guiMainThreadId)
{
while(!m_TryAcquireSRWLockExclusive(srwLock))
while(!TryAcquireSRWLockShared(srwLock))
GuiProcessEvents();
}
else
{
m_AcquireSRWLockExclusive(srwLock);
AcquireSRWLockShared(srwLock);
}
return;
}
assert(m_exclusiveOwner[LockIndex].threadId == 0);
assert(m_exclusiveOwner[LockIndex].count == 0);
m_exclusiveOwner[LockIndex].threadId = threadId;
m_exclusiveOwner[LockIndex].count = 1;
if(m_exclusiveOwner[LockIndex].threadId == threadId)
{
assert(m_exclusiveOwner[LockIndex].count > 0);
m_exclusiveOwner[LockIndex].count++;
return;
}
if(ProcessGuiEvents && threadId == m_guiMainThreadId)
{
while(!TryAcquireSRWLockExclusive(srwLock))
GuiProcessEvents();
}
else
{
auto cr = &m_crLocks[LockIndex];
if(ProcessGuiEvents && threadId == m_guiMainThreadId)
{
while(!TryEnterCriticalSection(cr))
GuiProcessEvents();
}
else
{
EnterCriticalSection(cr);
}
AcquireSRWLockExclusive(srwLock);
}
assert(m_exclusiveOwner[LockIndex].threadId == 0);
assert(m_exclusiveOwner[LockIndex].count == 0);
m_exclusiveOwner[LockIndex].threadId = threadId;
m_exclusiveOwner[LockIndex].count = 1;
}
template<SectionLock LockIndex, bool Shared>
static void ReleaseLock()
{
if(m_SRWLocks)
if(Shared)
{
if(Shared)
{
if(m_exclusiveOwner[LockIndex].threadId == GetCurrentThreadId())
return;
m_ReleaseSRWLockShared(&m_srwLocks[LockIndex]);
if(m_exclusiveOwner[LockIndex].threadId == GetCurrentThreadId())
return;
}
assert(m_exclusiveOwner[LockIndex].count && m_exclusiveOwner[LockIndex].threadId);
m_exclusiveOwner[LockIndex].count--;
if(m_exclusiveOwner[LockIndex].count == 0)
{
m_exclusiveOwner[LockIndex].threadId = 0;
m_ReleaseSRWLockExclusive(&m_srwLocks[LockIndex]);
}
ReleaseSRWLockShared(&m_srwLocks[LockIndex]);
return;
}
else
assert(m_exclusiveOwner[LockIndex].count && m_exclusiveOwner[LockIndex].threadId);
m_exclusiveOwner[LockIndex].count--;
if(m_exclusiveOwner[LockIndex].count == 0)
{
LeaveCriticalSection(&m_crLocks[LockIndex]);
m_exclusiveOwner[LockIndex].threadId = 0;
ReleaseSRWLockExclusive(&m_srwLocks[LockIndex]);
}
}
typedef void (WINAPI* SRWLOCKFUNCTION)(PSRWLOCK SWRLock);
typedef BOOLEAN(WINAPI* TRYSRWLOCKFUNCTION)(PSRWLOCK SWRLock);
static bool m_Initialized;
static bool m_SRWLocks;
struct DBG_ALIGNAS(64) owner_info { DWORD threadId; size_t count; };
static owner_info m_exclusiveOwner[SectionLock::LockLast];
static CacheAligned<SRWLOCK> m_srwLocks[SectionLock::LockLast];
static CacheAligned<CRITICAL_SECTION> m_crLocks[SectionLock::LockLast];
static SRWLOCKFUNCTION m_InitializeSRWLock;
static SRWLOCKFUNCTION m_AcquireSRWLockShared;
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockShared;
static SRWLOCKFUNCTION m_AcquireSRWLockExclusive;
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockExclusive;
static SRWLOCKFUNCTION m_ReleaseSRWLockShared;
static SRWLOCKFUNCTION m_ReleaseSRWLockExclusive;
static DWORD m_guiMainThreadId;
};

View File

@ -77,10 +77,10 @@ void Bridge::throttleUpdateSlot(GUIMSG msg)
// NOTE: This is running synchronously on the UI thread
auto lastUpdate = mLastUpdates[msg];
auto now = GetTickCount();
auto elapsed = now - lastUpdate;
const auto interval = 100;
if(lastUpdate > 0 && elapsed < interval)
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastUpdate);
const auto interval = (std::chrono::milliseconds)100;
if(elapsed < interval)
{
//qDebug() << "Delay update:" << msg2str(msg);
QTimer* timer = mUpdateTimers[msg];
@ -110,7 +110,7 @@ void Bridge::throttleUpdateSlot(GUIMSG msg)
void Bridge::doUpdate(GUIMSG msg)
{
auto start = GetTickCount();
auto start = std::chrono::steady_clock::now();
switch(msg)
{
@ -187,9 +187,9 @@ void Bridge::doUpdate(GUIMSG msg)
}
// Log potentially bottlenecked updates
auto now = GetTickCount();
auto elapsed = now - start;
if(elapsed > 5)
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
if(elapsed > (std::chrono::milliseconds)5)
{
//qDebug() << "[DebugMonitor]" << msg2str(msg) << elapsed << "ms";
}
@ -1132,17 +1132,8 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa
__declspec(dllexport) const char* _gui_translate_text(const char* source)
{
if(TLS_TranslatedStringMap)
{
QByteArray translatedUtf8 = QCoreApplication::translate("DBG", source).toUtf8();
// Boom... VS does not support "thread_local"... and cannot use "__declspec(thread)" in a DLL... https://blogs.msdn.microsoft.com/oldnewthing/20101122-00/?p=12233
// Simulating Thread Local Storage with a map...
DWORD ThreadId = GetCurrentThreadId();
TranslatedStringStorage & TranslatedString = (*TLS_TranslatedStringMap)[ThreadId];
TranslatedString.Data[translatedUtf8.size()] = 0; // Set the string terminator first.
memcpy(TranslatedString.Data, translatedUtf8.constData(), std::min((size_t)translatedUtf8.size(), sizeof(TranslatedString.Data) - 1)); // Then copy the string safely.
return TranslatedString.Data; // Don't need to free this memory. But this pointer should be used immediately to reduce race condition.
}
else // Translators are not initialized yet.
return source;
QByteArray translatedUtf8 = QCoreApplication::translate("DBG", source).toUtf8();
TLS_TranslatedString.Data[translatedUtf8.size()] = 0; // Set the string terminator first.
memcpy(TLS_TranslatedString.Data, translatedUtf8.constData(), std::min((size_t)translatedUtf8.size(), sizeof(TLS_TranslatedString.Data) - 1)); // Then copy the string safely.
return TLS_TranslatedString.Data; // Don't need to free this memory. But this pointer should be used immediately to reduce race condition.
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <chrono>
#include <QObject>
#include <QWidget>
#include <QMutex>
@ -202,7 +203,7 @@ private:
duint mBridgeResults[BridgeResult::Last];
DWORD mMainThreadId = 0;
volatile bool mDbgStopped = false;
QMap<GUIMSG, DWORD> mLastUpdates;
QMap<GUIMSG, std::chrono::steady_clock::time_point> mLastUpdates;
QMap<GUIMSG, QTimer*> mUpdateTimers;
QZydis* mDisasm = nullptr;
};

View File

@ -137,15 +137,6 @@ HandlesView::HandlesView(QWidget* parent) : QWidget(parent)
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcuts()));
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(dbgStateChanged(DBGSTATE)));
#ifdef _WIN32 // This is only supported on Windows Vista or greater
if(!IsWindowsVistaOrGreater())
#endif //_WIN32
{
mTcpConnectionsTable->setRowCount(1);
mTcpConnectionsTable->setCellContent(0, 0, tr("TCP Connection enumeration is only available on Windows Vista or greater."));
mTcpConnectionsTable->reloadData();
}
mWindowsTable->setAccessibleName(tr("Windows"));
mHandlesTable->setAccessibleName(tr("Handles"));
mTcpConnectionsTable->setAccessibleName(tr("TCP Connections"));

View File

@ -62,9 +62,8 @@ bool MyApplication::notify(QObject* receiver, QEvent* event)
static Configuration* mConfiguration;
char gCurrentLocale[MAX_SETTING_SIZE] = "";
// Boom... VS does not support "thread_local"... and cannot use "__declspec(thread)" in a DLL... https://blogs.msdn.microsoft.com/oldnewthing/20101122-00/?p=12233
// Simulating Thread Local Storage with a map...
std::map<DWORD, TranslatedStringStorage>* TLS_TranslatedStringMap; //key = Thread Id, value = Translate Buffer
thread_local TranslatedStringStorage TLS_TranslatedString;
static bool isValidLocale(const QString & locale)
{
@ -168,8 +167,6 @@ int main(int argc, char* argv[])
if(x64dbgTranslator.load(QString("x64dbg_%1").arg(gCurrentLocale), path))
application.installTranslator(&x64dbgTranslator);
TLS_TranslatedStringMap = new std::map<DWORD, TranslatedStringStorage>();
// load config file + set config font
mConfiguration = new Configuration;
application.setFont(ConfigFont("Application"));
@ -230,12 +227,6 @@ int main(int argc, char* argv[])
#endif
delete mainWindow;
mConfiguration->save(); //save config on exit
{
//delete tls
auto temp = TLS_TranslatedStringMap;
TLS_TranslatedStringMap = nullptr;
delete temp;
}
//TODO free Zydis/config/bridge and prevent use after free.

View File

@ -27,7 +27,8 @@ struct TranslatedStringStorage
{
char Data[4096];
};
extern std::map<DWORD, TranslatedStringStorage>* TLS_TranslatedStringMap;
extern thread_local TranslatedStringStorage TLS_TranslatedString;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
class MyEventFilter : public QAbstractNativeEventFilter