#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000)
#define SystemProcessesAndThreadsInformation 5 // 功能号
#define NTAPI __stdcall
// 线程状态的枚举常量
typedef enum _THREAD_STATE
{
StateInitialized , // 初始化状态
StateReady , // 准备状态
StateRunning , // 运行状态
StateStandby , //
StateTerminated , //关闭
StateWait , // 等待
StateTransition , // 切换???
StateUnknown
}THREAD_STATE;
// 线程处于等待的原因的枚举常量
typedef enum _KWAIT_REASON
{
Executive ,
FreePage ,
PageIn ,
PoolAllocation ,
DelayExecution ,
Suspended ,
UserRequest ,
WrExecutive ,
WrFreePage ,
WrPageIn ,
WrPoolAllocation ,
WrDelayExecution ,
WrSuspended ,
WrUserRequest ,
WrEventPair ,
WrQueue ,
WrLpcReceive ,
WrLpcReply ,
WrVirtualMemory ,
WrPageOut ,
WrRendezvous ,
Spare2 ,
Spare3 ,
Spare4 ,
Spare5 ,
Spare6 ,
WrKernel ,
MaximumWaitReason
}KWAIT_REASON;
typedef LONG NTSTATUS;
typedef LONG KPRIORITY;
typedef struct _CLIENT_ID
{
DWORD UniqueProcess;
DWORD UniqueThread;
} CLIENT_ID , *PCLIENT_ID;
typedef struct _VM_COUNTERS
{
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
// 线程信息结构体
typedef struct _SYSTEM_THREAD_INFORMATION
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State; // 状态,是THREAD_STATE枚举类型中的一个值
LONG WaitReason; //等待原因, KWAIT_REASON中的一个值
} SYSTEM_THREAD_INFORMATION , *PSYSTEM_THREAD_INFORMATION;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING , *PUNICODE_STRING;
// 进程信息结构体
typedef struct _SYSTEM_PROCESS_INFORMATION
{
ULONG NextEntryDelta; // 指向下一个结构体的指针
ULONG ThreadCount; // 本进程的总线程数
ULONG Reserved1[ 6 ]; // 保留
LARGE_INTEGER CreateTime; // 进程的创建时间
LARGE_INTEGER UserTime; // 在用户层的使用时间
LARGE_INTEGER KernelTime; // 在内核层的使用时间
UNICODE_STRING ProcessName; // 进程名
KPRIORITY BasePriority; //
ULONG ProcessId; // 进程ID
ULONG InheritedFromProcessId;
ULONG HandleCount; // 进程的句柄总数
ULONG Reserved2[ 2 ]; // 保留
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD_INFORMATION Threads[ 5 ]; // 子线程信息数组
}SYSTEM_PROCESS_INFORMATION , *PSYSTEM_PROCESS_INFORMATION;
// NtQuerySystemInformation 函数的原型
// 由于该没有导出,所以得自己定义函数的原型
typedef DWORD (WINAPI* PQUERYSYSTEM)( UINT , PVOID , DWORD , PDWORD);
/*
※※* 函数名 : IsThreadSuspend
※※* 功 能 : 获取线程是被是否被挂起
※※* 返回值 : int 1: 表示线程被挂起 , 0: 表示线程正常。 -1 未知状态
※※* 形 参 : DWORD dwThreadID 要验证的线程的ID
※※* 形 参 : wchar_t * szProcessName 表示线程所在的进程名
*/
int IsThreadSuspend( DWORD dwProcessID , DWORD dwThreadID)
{
int nRet = 0;
NTSTATUS Status = 0;
PQUERYSYSTEM NtQuerySystemInformation = NULL;
PSYSTEM_PROCESS_INFORMATION pInfo = { 0 };
// 获取函数地址
NtQuerySystemInformation = (PQUERYSYSTEM)
GetProcAddress(LoadLibrary(L "ntdll.dll" ) , "NtQuerySystemInformation" );
DWORD dwSize = 0;
// 获取信息所需的缓冲区大小
Status = NtQuerySystemInformation(SystemProcessesAndThreadsInformation , //要获取的信息的类型
NULL , // 用于接收信息的缓冲区
0 , // 缓冲区大小
&dwSize
);
// 申请缓冲区
char* pBuff = new char [ dwSize ];
pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuff ;
if (pInfo == NULL)
return -1;
// 再次调用函数, 获取信息
Status = NtQuerySystemInformation(SystemProcessesAndThreadsInformation , //要获取的信息的类型
pInfo , // 用于接收信息的缓冲区
dwSize , // 缓冲区大小
&dwSize
);
if (!NT_SUCCESS(Status)) { /*如果函数执行失败*/
printf ( "失败\n" );
delete [] pInfo;
return -1;
}
// 遍历结构体,找到对应的进程
while (1) {
// 判断是否还有下一个进程
if (pInfo->NextEntryDelta == 0)
break ;
// 判断是否找到了ID
if (pInfo->ProcessId == dwProcessID) {
// 找到该进程下的对应的线程,也就是遍历所有线程
for ( DWORD i = 0; i < pInfo->ThreadCount ; i++) {
if (pInfo->Threads[ i ].ClientId.UniqueThread == dwThreadID) { //找到线程
//如果线程被挂起
if (pInfo->Threads[ i ].State == StateWait
&& pInfo->Threads[ i ].WaitReason == Suspended) {
nRet = 1;
break ;
}
}
}
break ;
}
// 迭代到下一个节点
pInfo = (PSYSTEM_PROCESS_INFORMATION)((( PUCHAR )pInfo) + pInfo->NextEntryDelta);
}
delete [] pBuff;
return nRet;
}
/*
※※* 函数名 : IsThreadAlive
※※* 功 能 : 判断线程是否被终止 , 如果终止返回FALSE,如果还活着返回TRUE
※※* 返回值 : BOOL
※※* 形 参 : DWORD dwThreadID 线程ID
*/
BOOL IsThreadAlive( DWORD dwThreadID)
{
BOOL bRet = FALSE;
DWORD ExitCode = 0;
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION , FALSE , dwThreadID);
if (hThread != NULL) {
if (GetExitCodeThread(hThread , &ExitCode)) {
if (ExitCode == STILL_ACTIVE)
bRet = TRUE;
}
CloseHandle(hThread);
}
return bRet;
}
int main()
{
BOOL bRET = IsThreadSuspend(2640 , 1111);
if (bRET) {
printf ( " 2320线程被挂起了!" );
}
|