社区
进程/线程/DLL
帖子详情
关于线程
lolin
2000-11-22 09:15:00
知道进程句柄怎样取得其下所有线程的句柄?急!
...全文
512
9
打赏
收藏
关于线程
知道进程句柄怎样取得其下所有线程的句柄?急!
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
9 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
singlerace
2000-11-26
打赏
举报
回复
ntddk.h里有部分说明
lolin
2000-11-24
打赏
举报
回复
虽然还未试,但很厉害。佩服、佩服!值得给100分!
不过我还有一点不太明白,以NT等开头的应是MS未文档载明的函数,
不知singlerace兄是从哪知道它的参数及功能的?(有些唐突,但真的忍不住很想知道)
非常感激你,真的!
singlerace
2000-11-23
打赏
举报
回复
简单调用Mine_OpenThread就可以了,当然用完后记得CloseHandle
singlerace
2000-11-23
打赏
举报
回复
在NT下是可以的。我已经试成功了。
用了ntdll.dll里的3个函数:
NtQuerySystemInformation,
NtQueryObject,
NtQueryInformationThread
不光得到线程handle,还可以在系统范围枚举所进程、线程、内核句柄。
回复人:singlerace(2000-11-10 12:15:00 ) 得0分
#include <windows.h>
#include <stdio.h>
#include <TCHAR.h>
typedef DWORD (WINAPI *PNtQueryObject)( HANDLE, DWORD, VOID*, DWORD, VOID* );
typedef DWORD (WINAPI *PNtQuerySystemInformation)( DWORD, VOID*, DWORD, ULONG* );
typedef DWORD (WINAPI *PNtQueryInformationThread)(HANDLE, ULONG, PVOID, DWORD, DWORD* );
typedef DWORD (WINAPI *PNtQueryInformationFile)(HANDLE, PVOID, PVOID, DWORD, DWORD );
typedef DWORD (WINAPI *PNtQueryInformationProcess)(HANDLE, DWORD, PVOID, DWORD, PVOID );
typedef struct _THREAD_INFORMATION
{
DWORD ProcessId;
DWORD ThreadId;
HANDLE ThreadHandle;
} THREAD_INFORMATION;
typedef struct _BASIC_THREAD_INFORMATION {
DWORD u1;
DWORD u2;
DWORD u3;
DWORD ThreadId;
DWORD u5;
DWORD u6;
DWORD u7;
} BASIC_THREAD_INFORMATION;
enum {
OB_TYPE_UNKNOWN = 0,
OB_TYPE_TYPE = 1,
OB_TYPE_DIRECTORY,
OB_TYPE_SYMBOLIC_LINK,
OB_TYPE_TOKEN,
OB_TYPE_PROCESS,
OB_TYPE_THREAD,
OB_TYPE_UNKNOWN_7,
OB_TYPE_EVENT,
OB_TYPE_EVENT_PAIR,
OB_TYPE_MUTANT,
OB_TYPE_UNKNOWN_11,
OB_TYPE_SEMAPHORE,
OB_TYPE_TIMER,
OB_TYPE_PROFILE,
OB_TYPE_WINDOW_STATION,
OB_TYPE_DESKTOP,
OB_TYPE_SECTION,
OB_TYPE_KEY,
OB_TYPE_PORT,
OB_TYPE_WAITABLE_PORT,
OB_TYPE_UNKNOWN_21,
OB_TYPE_UNKNOWN_22,
OB_TYPE_UNKNOWN_23,
OB_TYPE_UNKNOWN_24,
//OB_TYPE_CONTROLLER,
//OB_TYPE_DEVICE,
//OB_TYPE_DRIVER,
OB_TYPE_IO_COMPLETION,
OB_TYPE_FILE
} SystemHandleType;
typedef struct _SYSTEM_HANDLE
{
DWORD ProcessID;
WORD HandleType;
WORD HandleNumber;
DWORD KernelAddress;
DWORD Flags;
} SYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
DWORD Count;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION;
PNtQuerySystemInformation NtQuerySystemInformation = NULL;
PNtQueryObject NtQueryObject = NULL;
PNtQueryInformationThread NtQueryInformationThread = NULL;
PNtQueryInformationFile NtQueryInformationFile = NULL;
PNtQueryInformationProcess NtQueryInformationProcess = NULL;
BOOL Init();
BOOL NtDllStatus = Init();
// Enable the SeDebugPrivilege
static void EnableDebugPriv( void )
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
// enable the SeDebugPrivilege
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
_tprintf( _T("OpenProcessToken() failed, Error = %d SeDebugPrivilege is not available.\n") , GetLastError() );
return;
}
if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
{
_tprintf( _T("LookupPrivilegeValue() failed, Error = %d SeDebugPrivilege is not available.\n"), GetLastError() );
CloseHandle( hToken );
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
_tprintf( _T("AdjustTokenPrivileges() failed, Error = %d SeDebugPrivilege is not available.\n"), GetLastError() );
CloseHandle( hToken );
}
static BOOL Init()
{
// Get the NtDll function pointers
NtQuerySystemInformation = (PNtQuerySystemInformation)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQuerySystemInformation") );
NtQueryObject = (PNtQueryObject)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryObject") );
NtQueryInformationThread = (PNtQueryInformationThread)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryInformationThread") );
NtQueryInformationFile = (PNtQueryInformationFile)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryInformationFile") );
NtQueryInformationProcess = (PNtQueryInformationProcess)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryInformationProcess") );
EnableDebugPriv();
return NtQuerySystemInformation != NULL &&
NtQueryObject != NULL &&
NtQueryInformationThread != NULL &&
NtQueryInformationFile != NULL &&
NtQueryInformationProcess != NULL;
}
void LPCWSTR2CString( LPCWSTR strW, LPTSTR str )
{
#ifdef UNICODE
// if it is already UNICODE, no problem
wcscpy(strW, str);
#else
str[0] = _T('\0');
TCHAR* actChar = (TCHAR*)strW;
if ( actChar == _T('\0') )
return;
ULONG len = wcslen(strW) + 1;
TCHAR* pBuffer = new TCHAR[ len ];
TCHAR* pNewStr = pBuffer;
while ( len-- )
{
*(pNewStr++) = *actChar;
actChar += 2;
}
_tcscpy(str, pBuffer);
delete [] pBuffer;
#endif
}
//Information functions
static BOOL GetTypeToken( HANDLE h, LPTSTR str, DWORD processId )
{
ULONG size = 0x2000;
UCHAR* lpBuffer = NULL;
BOOL ret = FALSE;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( remote )
{
// Open the remote process
hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate the handle
handle = NULL;
DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS );
}
else
handle = h;
// Query the info size
NtQueryObject( handle, 2, NULL, 0, &size );
lpBuffer = new UCHAR[size];
// Query the info size ( type )
if ( NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 )
{
str[0] = _T('\0');
LPCWSTR2CString( (LPCWSTR)(lpBuffer+0x60), str );
ret = TRUE;
}
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
if ( lpBuffer != NULL )
delete [] lpBuffer;
return ret;
}
//Thread related functions
static BOOL GetThreadId( HANDLE h, DWORD& threadID, DWORD processId )
{
BASIC_THREAD_INFORMATION ti;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( remote )
{
// Open process
hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate handle
handle = NULL;
DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS );
}
else
handle = h;
// Get the thread information
if ( NtQueryInformationThread( handle, 0, &ti, sizeof(ti), NULL ) == 0 )
threadID = ti.ThreadId;
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
return TRUE;
}
HANDLE Mine_OpenThread(DWORD dwProcessId, DWORD dwThreadId)
{
DWORD size = 0x2000;
DWORD needed = 0;
DWORD i = 0;
TCHAR szFilter[] = _T("Thread");
TCHAR szType[500];
THREAD_INFORMATION ti;
HANDLE h = NULL;
if ( !NtDllStatus )
return NULL;
// Allocate the memory for the buffer
SYSTEM_HANDLE_INFORMATION* pSysHandleInformation = (SYSTEM_HANDLE_INFORMATION*)
VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE );
if ( pSysHandleInformation == NULL )
return NULL;
// Query the needed buffer size for the objects ( system wide )
if ( NtQuerySystemInformation( 16, pSysHandleInformation, size, &needed ) != 0 )
{
if ( needed == 0 )
goto cleanup;
// The size was not enough
VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
pSysHandleInformation = (SYSTEM_HANDLE_INFORMATION*)
VirtualAlloc( NULL, size = needed + 256, MEM_COMMIT, PAGE_READWRITE );
}
if ( pSysHandleInformation == NULL )
return NULL;
// Query the objects ( system wide )
if ( NtQuerySystemInformation( 16, pSysHandleInformation, size, NULL ) != 0 )
goto cleanup;
// Iterating through the objects
for ( i = 0; i < pSysHandleInformation->Count; i++ )
{
// ProcessId filtering check
if ( pSysHandleInformation->Handles[i].ProcessID == dwProcessId || dwProcessId == (DWORD)-1 )
{
// Type filtering
GetTypeToken( (HANDLE)pSysHandleInformation->Handles[i].HandleNumber, szType, pSysHandleInformation->Handles[i].ProcessID );
if( _tcsicmp( szType, szFilter ) == 0 )
{
ti.ProcessId = pSysHandleInformation->Handles[i].ProcessID;
ti.ThreadHandle = (HANDLE)pSysHandleInformation->Handles[i].HandleNumber;
// ThreadId filtering check
if(GetThreadId( ti.ThreadHandle, ti.ThreadId, ti.ProcessId ) && ti.ThreadId == dwThreadId)
{
if(dwProcessId != GetCurrentProcessId())
{
// Open remote process
HANDLE hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, dwProcessId );
if ( hRemoteProcess == NULL )
goto cleanup;
// Duplicate handle
DuplicateHandle( hRemoteProcess, ti.ThreadHandle, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS );
CloseHandle( hRemoteProcess );
}
else
DuplicateHandle( GetCurrentProcess(), ti.ThreadHandle, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS );
break;
}
ti.ThreadHandle = NULL;
}
}
}
cleanup:
if ( pSysHandleInformation != NULL )
VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
return h;
}
singlerace
2000-11-23
打赏
举报
回复
可以从线程id得到线程句柄的,当然也可以操纵它,比如TerminateThread。
wjf
2000-11-22
打赏
举报
回复
msdn的例子里有Process view的源程序,不妨看看!
wjf
2000-11-22
打赏
举报
回复
要句柄干什么?
记得曾经讨论过,线程的句柄除了创建时能得到之外,其他情况下几乎不可能得到!
你要句柄无非是为了操纵他,请记住要在进程空间外单独操纵线程几乎不可能。
net_worm
2000-11-22
打赏
举报
回复
强制转换呀……
lolin
2000-11-22
打赏
举报
回复
我已看过,但只有如何取得线程ID,不知怎样将ID转化为HANDLE!
Python编程之多
线程
与网络编程
这是Tom老师精心讲解python关于网络编程和在python中使用多
线程
的一门课程。同学们学完这门课程之后,能够使用python与服务器进行通信,同学们也能自己开发爬虫,等关于python项目的开发
java
线程
说法错误的是什么_【多选题】在java程序中,下列关于
线程
的说法错误的是() A.
线程
启动调用start方法 B.
线程
的主体是run方法 C.
线程
运行中调用sleep方法可以进入阻塞...
【多选题】在java程序中,下列关于
线程
的说法错误的是()A.
线程
启动调用start方法 B.
线程
的主体是run方法 C.
线程
运行中调用sleep方法可以进入阻塞状态 D. 定义
线程
只能通过定义类继承Thread类的方法更多相关问题等截面直杆受轴向拉力F作用发生拉伸变形。已知横截面面积为A,以下给出的横截面上的正应下列选项中,()是现代市场经济中各行各业所呼唤的一个基本原则,也是人际关系建立...
下列关于
线程
调度的叙述中,错误的是()。
下列关于
线程
调度的叙述中,错误的是()。 正确答案: B E 你的答案: A E F (错误) 调用
线程
的sleep()方法,可以使比当前
线程
优先级低的
线程
获得运行机会 调用
线程
的yeild()方法,只会使与当前
线程
相同优先级的
线程
获得运行机会 当有比当前
线程
的优先级高的
线程
出现时,高优先级
线程
将抢占CPU并运行 一个
线程
由于某些原因进入阻
关于
线程
访问另外一个
线程
的变量问题
关于
线程
访问另外一个
线程
的变量问题 之前帮别人调错,遇到一个错误,就是一个
线程
A访问另外一个
线程
B的成员变量,并且
线程
A在构造方法中有
线程
B的引用,但是无论
线程
A怎么获取
线程
B的成员变量都是 null,但是在
线程
B初始化中已经给成员变量赋值了。 后面解决了很久,没解决出来,然后刚好看到了 指令重排序问题 ,下面我们来看一个例子 public class Test { int a = 0; boolean flag = false; public void writer(){
下列关于
线程
调度的叙述中,错误的是()。----阿里巴巴2015校招研发在线
下列关于
线程
调度的叙述中,错误的是()。 正确答案: B E 你的答案: A E F (错误) 调用
线程
的sleep()方法,可以使比当前
线程
优先级低的
线程
获得运行机会 调用
线程
的yeild()方法,只会使与当前
线程
相同优先级的
线程
获得运行机会 当有比当前
线程
的优先级高的
线程
出现时,高优先级
线程
将抢占CPU并运行 一个
线程
由于某些原因进入阻
进程/线程/DLL
15,471
社区成员
49,182
社区内容
发帖
与我相关
我的任务
进程/线程/DLL
VC/MFC 进程/线程/DLL
复制链接
扫一扫
分享
社区描述
VC/MFC 进程/线程/DLL
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章