DWORD GetThreadSuspendCount(CONST DWORD& dwTid)
{
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, dwTid);
if(!hThread){
return 0;
}
CONST DWORD STATUS_SUCCESS = 0;
typedef enum _THREADINFOCLASS
{
ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION
ThreadTimes, // q: KERNEL_USER_TIMES
ThreadPriority, // s: KPRIORITY
ThreadBasePriority, // s: LONG
ThreadAffinityMask, // s: KAFFINITY
ThreadImpersonationToken, // s: HANDLE
ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY)
ThreadEnableAlignmentFaultFixup, // s: BOOLEAN
ThreadEventPair,
ThreadQuerySetWin32StartAddress, // q: PVOID
ThreadZeroTlsCell, // 10
ThreadPerformanceCount, // q: LARGE_INTEGER
ThreadAmILastThread, // q: ULONG
ThreadIdealProcessor, // s: ULONG
ThreadPriorityBoost, // qs: ULONG
ThreadSetTlsArrayAddress,
ThreadIsIoPending, // q: ULONG
ThreadHideFromDebugger, // s: void
ThreadBreakOnTermination, // qs: ULONG
ThreadSwitchLegacyState,
ThreadIsTerminated, // q: ULONG // 20
ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION
ThreadIoPriority, // qs: IO_PRIORITY_HINT
ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION
ThreadPagePriority, // q: ULONG
ThreadActualBasePriority,
ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT)
ThreadCSwitchMon,
ThreadCSwitchPmu,
ThreadWow64Context, // q: WOW64_CONTEXT
ThreadGroupInformation, // q: GROUP_AFFINITY // 30
ThreadUmsInformation, // q: THREAD_UMS_INFORMATION
ThreadCounterProfiling,
ThreadIdealProcessorEx, // q: PROCESSOR_NUMBER
ThreadCpuAccountingInformation, // since WIN8
ThreadSuspendCount, // since WINBLUE
ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD
ThreadContainerId, // q: GUID
ThreadNameInformation, // qs: THREAD_NAME_INFORMATION
ThreadSelectedCpuSets,
ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40
ThreadActualGroupAffinity, // since THRESHOLD2
ThreadDynamicCodePolicyInfo,
ThreadExplicitCaseSensitivity,
ThreadWorkOnBehalfTicket,
ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2
ThreadDbgkWerReportActive,
ThreadAttachContainer,
MaxThreadInfoClass
} THREADINFOCLASS;
typedef LONG (WINAPI *NtQueryInformationThreadProc)(
_In_ HANDLE ThreadHandle,
_In_ THREADINFOCLASS ThreadInformationClass,
_Inout_ PVOID ThreadInformation,
_In_ ULONG ThreadInformationLength,
_Out_opt_ PULONG ReturnLength
);
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
if(!hNtdll){
return 0;
}
DWORD dwRes;
NtQueryInformationThreadProc NtQueryInformationThread = (NtQueryInformationThreadProc)GetProcAddress(hNtdll, "NtQueryInformationThread");
if(!NtQueryInformationThread){
return 0;
}
NTSTATUS status = NtQueryInformationThread(hThread, ThreadSuspendCount, &dwRes, sizeof(dwRes), NULL);
if(STATUS_SUCCESS == status && dwRes > 0){
return dwRes;
}
return 0;
}