www.pudn.com > remote_thread.zip > ntthread.cpp


/*  Remote Run Library 
    Copyright (C) 2001, Sting Feng(冯越) 
 
    This program is free software; you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by 
    the Free Software Foundation; either version 2 of the License, or 
    (at your option) any later version. 
 
    This program is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    GNU General Public License for more details. 
 
    You should have received a copy of the GNU General Public License 
    along with this program; if not, write to the Free Software 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
	The author of this program may be contacted at fenny@163.net. */ 
 
 
#include  
#include "ntthread.h" 
 
 
//------------------------------- 
// Get NT version 
//------------------------------- 
static DWORD GetNTMajorVersion() 
{ 
	OSVERSIONINFOEX osvi; 
	BOOL bOsVersionInfoEx; 
 
 
	//------------------------------------------------------------------- 
	// Try calling GetVersionEx using the OSVERSIONINFOEX structure, 
	// which is supported on Windows 2000. 
	// If that fails, try using the OSVERSIONINFO structure. 
	//------------------------------------------------------------------- 
	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); 
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 
 
	bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi); 
 
	if( bOsVersionInfoEx == 0 ) 
	{ 
		//----------------------------------------------------- 
		// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. 
		//----------------------------------------------------- 
 
		osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); 
		if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )  
			return FALSE; 
	} 
 
	return osvi.dwMajorVersion; 
} 
 
 
//---------------------------------------------------------------- 
// 调用NtQuerySystemInformation枚举所有线程 
//---------------------------------------------------------------- 
BOOL NtThread::EnumThread(DWORD processId, DWORD* ptid, DWORD* pnMaxCount) 
{ 
	if( pnMaxCount == NULL || *pnMaxCount == 0 ) return FALSE; 
	 
	BOOL retval = FALSE; 
	SYSTEM_PROCESS_INFORMATION* pSysProcess; 
	HMODULE hNtDll = ::GetModuleHandleW( L"ntdll.dll" ); 
	if( hNtDll == NULL ) 
		return retval; 
 
 
	PNtQuerySystemInformation fnNtQuerySystemInformation = 
			(PNtQuerySystemInformation)GetProcAddress( hNtDll, 
										"NtQuerySystemInformation" ); 
	if( fnNtQuerySystemInformation == NULL ) 
		return retval; 
 
	const DWORD BufferSize = 0x10000; 
	UCHAR* pBufferBase = (UCHAR*)VirtualAlloc (NULL, 
						BufferSize,  
						MEM_COMMIT, 
						PAGE_READWRITE); 
	if( pBufferBase == NULL ) 
		return retval; 
 
	// query the process information 
	if ( fnNtQuerySystemInformation( 5, pBufferBase, BufferSize, NULL ) != 0 ) 
		goto cleanup; 
 
	pSysProcess = (SYSTEM_PROCESS_INFORMATION*)pBufferBase; 
	do  
	{ 
 
		if( processId == pSysProcess->dUniqueProcessId ) 
		{ 
			DWORD dwNTMajorVersion = GetNTMajorVersion(); 
			SYSTEM_THREAD* ti; 
			if( dwNTMajorVersion < 5 ) 
				ti = (SYSTEM_THREAD*)(pSysProcess+1); 
			else 
				ti = (SYSTEM_THREAD*)( (PSYSTEM_PROCESS_INFORMATION_2K)(pSysProcess+1) ); 
 
			if( *pnMaxCount > pSysProcess->dThreadCount ) 
				*pnMaxCount = pSysProcess->dThreadCount; 
 
 
			//------------------------------------------- 
			// 保存结果 
			//------------------------------------------- 
			for(DWORD i = 0; i < *pnMaxCount; i++, ti++) 
			{ 
				ptid[i] = (DWORD)ti->ClientId.UniqueThread; 
			} 
 
			retval = TRUE; 
			break; 
		} 
 
		//------------------------------------------ 
		// get the next process information block 
		//------------------------------------------ 
		if ( pSysProcess->dNext != 0 ) 
			pSysProcess = (SYSTEM_PROCESS_INFORMATION*)((UCHAR*)pSysProcess + pSysProcess->dNext); 
		else 
			pSysProcess = NULL; 
 
	} while ( pSysProcess != NULL ); 
 
 
cleanup: 
	if( pBufferBase != NULL ) 
		::VirtualFree( pBufferBase, 0, MEM_RELEASE ); 
	return retval; 
} 
 
 
//------------------------------------------------- 
// 调用NtOpenThread从线程ID得到线程handle, 
// windows 2000下也可以调用OpenThread。 
//------------------------------------------------- 
HANDLE NtThread::NtOpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD threadId, DWORD processId ) 
{ 
	HMODULE hNtDll = ::GetModuleHandle( L"ntdll.dll" ); 
	if( hNtDll == NULL ) 
		return NULL; 
 
	PNtOpenThread fnNtOpenThread = 
			(PNtOpenThread)GetProcAddress( hNtDll, 
										"NtOpenThread" ); 
	if( fnNtOpenThread == NULL ) 
		return NULL; 
 
	OPEN_PROCESS_THREAD ot = {0}; 
	CLIENT_ID id = {0}; 
	HANDLE hThread = NULL; 
 
	ot.cbSize = sizeof( ot ); 
	ot.bInheritHandle = (bInheritHandle!=0) ? 1 : 0; 
	 
	id.UniqueProcess = (HANDLE)processId; 
	id.UniqueThread = (HANDLE)threadId; 
 
	//--------------------------------- 
	// Let's get it 
	//--------------------------------- 
	fnNtOpenThread( &hThread, dwDesiredAccess, &ot, &id ); 
	return hThread; 
}