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;
}