blob: 92eb6f01f4a9a51f643f76fab3b17bca3910366f [file] [log] [blame]
// Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
// For companies(Austin,TX): If you would like to get my resume, send an email.
//
// The source is free, but if you want to use it, mention my name and e-mail
// address
//
///////////////////////////////////////////////////////////////////////////////
//
// SystemInfo.cpp v1.1
//
// History:
//
// Date Version Description
// ----------------------------------------------------------------------------
// 10/16/00 1.0 Initial version
// 11/09/00 1.1 NT4 doesn't like if we bother the System process fix :)
// SystemInfoUtils::GetDeviceFileName() fix (subst drives
// added)
// NT Major version added to INtDLL class
//
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include "SystemInfo.h"
#include <sstream>
using std::stringstream;
#ifndef WINNT
#error You need Windows NT to use this source code. Define WINNT!
#endif
///////////////////////////////////////////////////////////////////////////////
//
// SystemInfoUtils
//
///////////////////////////////////////////////////////////////////////////////
// From wide char string to string
void SystemInfoUtils::LPCWSTR2string( LPCWSTR strW, string& str )
{
#ifdef UNICODE
// if it is already UNICODE, no problem
str = strW;
#else
str = _T("");
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;
}
str = pBuffer;
delete [] pBuffer;
#endif
}
// From wide char string to unicode
void SystemInfoUtils::Unicode2string( UNICODE_STRING* strU, string& str )
{
if ( *(DWORD*)strU != 0 )
LPCWSTR2string( (LPCWSTR)strU->Buffer, str );
else
str = _T("");
}
// From device file name to DOS filename
BOOL SystemInfoUtils::GetFsFileName( LPCTSTR lpDeviceFileName,
string& fsFileName )
{
BOOL rc = FALSE;
TCHAR lpDeviceName[0x1000];
TCHAR lpDrive[3] = _T("A:");
// Iterating through the drive letters
for ( TCHAR actDrive = _T('A'); actDrive <= _T('Z'); actDrive++ ) {
lpDrive[0] = actDrive;
// Query the device for the drive letter
if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 ) {
// Network drive?
if ( _tcsnicmp( _T("\\Device\\LanmanRedirector\\"),
lpDeviceName, 25 ) == 0 ) {
//Mapped network drive
char cDriveLetter;
DWORD dwParam;
TCHAR lpSharedName[0x1000];
if ( _stscanf( lpDeviceName,
_T("\\Device\\LanmanRedirector\\;%c:%d\\%s"),
&cDriveLetter,
&dwParam,
lpSharedName ) != 3 )
continue;
_tcscpy( lpDeviceName,
_T("\\Device\\LanmanRedirector\\") );
_tcscat( lpDeviceName, lpSharedName );
}
// Is this the drive letter we are looking for?
if ( _tcsnicmp( lpDeviceName, lpDeviceFileName,
_tcslen( lpDeviceName ) ) == 0 )
{
fsFileName = lpDrive;
fsFileName += (LPCTSTR)( lpDeviceFileName
+ _tcslen( lpDeviceName ) );
rc = TRUE;
break;
}
}
}
return rc;
}
// From DOS file name to device file name
BOOL SystemInfoUtils::GetDeviceFileName( LPCTSTR lpFsFileName,
string& deviceFileName )
{
BOOL rc = FALSE;
TCHAR lpDrive[3];
// Get the drive letter
// unfortunetaly it works only with DOS file names
_tcsncpy( lpDrive, lpFsFileName, 2 );
lpDrive[2] = _T('\0');
TCHAR lpDeviceName[0x1000];
// Query the device for the drive letter
if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 )
{
// Subst drive?
if ( _tcsnicmp( _T("\\??\\"), lpDeviceName, 4 ) == 0 )
{
deviceFileName = lpDeviceName + 4;
deviceFileName += lpFsFileName + 2;
return TRUE;
}
else
// Network drive?
if ( _tcsnicmp( _T("\\Device\\LanmanRedirector\\"),
lpDeviceName, 25 ) == 0 ) {
//Mapped network drive
char cDriveLetter;
DWORD dwParam;
TCHAR lpSharedName[0x1000];
if ( _stscanf( lpDeviceName,
_T("\\Device\\LanmanRedirector\\;%c:%d\\%s"),
&cDriveLetter,
&dwParam,
lpSharedName ) != 3 )
return FALSE;
_tcscpy( lpDeviceName,
_T("\\Device\\LanmanRedirector\\") );
_tcscat( lpDeviceName, lpSharedName );
}
_tcscat( lpDeviceName, lpFsFileName + 2 );
deviceFileName = lpDeviceName;
rc = TRUE;
}
return rc;
}
//Get NT version
DWORD SystemInfoUtils::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;
}
///////////////////////////////////////////////////////////////////////////////
//
// INtDll
//
///////////////////////////////////////////////////////////////////////////////
INtDll::PNtQuerySystemInformation INtDll::NtQuerySystemInformation = NULL;
INtDll::PNtQueryObject INtDll::NtQueryObject = NULL;
INtDll::PNtQueryInformationThread INtDll::NtQueryInformationThread = NULL;
INtDll::PNtQueryInformationFile INtDll::NtQueryInformationFile = NULL;
INtDll::PNtQueryInformationProcess INtDll::NtQueryInformationProcess = NULL;
DWORD INtDll::dwNTMajorVersion = SystemInfoUtils::GetNTMajorVersion();
BOOL INtDll::NtDllStatus = INtDll::Init();
BOOL INtDll::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") );
return NtQuerySystemInformation != NULL &&
NtQueryObject != NULL &&
NtQueryInformationThread != NULL &&
NtQueryInformationFile != NULL &&
NtQueryInformationProcess != NULL;
}
///////////////////////////////////////////////////////////////////////////////
//
// SystemProcessInformation
//
///////////////////////////////////////////////////////////////////////////////
SystemProcessInformation::SystemProcessInformation( BOOL bRefresh )
{
m_pBuffer = (UCHAR*)VirtualAlloc ((void*)0x100000,
BufferSize,
MEM_COMMIT,
PAGE_READWRITE);
if ( bRefresh )
Refresh();
}
SystemProcessInformation::~SystemProcessInformation()
{
VirtualFree( m_pBuffer, 0, MEM_RELEASE );
}
BOOL SystemProcessInformation::Refresh()
{
m_ProcessInfos.clear();
m_pCurrentProcessInfo = NULL;
if ( !NtDllStatus || m_pBuffer == NULL )
return FALSE;
// query the process information
if ( INtDll::NtQuerySystemInformation( 5, m_pBuffer, BufferSize, NULL )
!= 0 )
return FALSE;
DWORD currentProcessID = GetCurrentProcessId(); //Current Process ID
SYSTEM_PROCESS_INFORMATION* pSysProcess =
(SYSTEM_PROCESS_INFORMATION*)m_pBuffer;
do
{
// fill the process information map
m_ProcessInfos[pSysProcess->dUniqueProcessId] = pSysProcess;
// we found this process
if ( pSysProcess->dUniqueProcessId == currentProcessID )
m_pCurrentProcessInfo = pSysProcess;
// get the next process information block
if ( pSysProcess->dNext != 0 )
pSysProcess = (SYSTEM_PROCESS_INFORMATION*)
((UCHAR*)pSysProcess + pSysProcess->dNext);
else
pSysProcess = NULL;
} while ( pSysProcess != NULL );
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// SystemThreadInformation
//
///////////////////////////////////////////////////////////////////////////////
SystemThreadInformation::SystemThreadInformation( DWORD pID, BOOL bRefresh )
{
m_processId = pID;
if ( bRefresh )
Refresh();
}
BOOL SystemThreadInformation::Refresh()
{
// Get the Thread objects ( set the filter to "Thread" )
SystemHandleInformation hi( m_processId );
BOOL rc = hi.SetFilter( _T("Thread"), TRUE );
m_ThreadInfos.clear();
if ( !rc )
return FALSE;
THREAD_INFORMATION ti;
// Iterating through the found Thread objects
for (list<SystemHandleInformation::SYSTEM_HANDLE>::iterator iter = hi.m_HandleInfos.begin(); iter != hi.m_HandleInfos.end(); iter++) {
SystemHandleInformation::SYSTEM_HANDLE& h = *iter;
ti.ProcessId = h.ProcessID;
ti.ThreadHandle = (HANDLE)h.HandleNumber;
// This is one of the threads we are lokking for
if ( SystemHandleInformation::GetThreadId( ti.ThreadHandle,
ti.ThreadId, ti.ProcessId ) )
m_ThreadInfos.push_back( ti );
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// SystemHandleInformation
//
///////////////////////////////////////////////////////////////////////////////
SystemHandleInformation::SystemHandleInformation( DWORD pID, BOOL bRefresh,
LPCTSTR lpTypeFilter )
{
m_processId = pID;
// Set the filter
SetFilter( lpTypeFilter, bRefresh );
}
SystemHandleInformation::~SystemHandleInformation()
{
}
BOOL SystemHandleInformation::SetFilter( LPCTSTR lpTypeFilter, BOOL bRefresh )
{
// Set the filter ( default = all objects )
m_strTypeFilter = lpTypeFilter == NULL ? _T("") : lpTypeFilter;
return bRefresh ? Refresh() : TRUE;
}
const string& SystemHandleInformation::GetFilter()
{
return m_strTypeFilter;
}
BOOL SystemHandleInformation::IsSupportedHandle( SYSTEM_HANDLE& handle )
{
//Here you can filter the handles you don't want in the Handle list
// Windows 2000 supports everything :)
if ( dwNTMajorVersion >= 5 )
return TRUE;
//NT4 System process doesn't like if we bother his internal security :)
if ( handle.ProcessID == 2 && handle.HandleType == 16 )
return FALSE;
return TRUE;
}
BOOL SystemHandleInformation::Refresh()
{
DWORD size = 0x2000;
DWORD needed = 0;
DWORD i = 0;
BOOL ret = TRUE;
string strType;
m_HandleInfos.clear();
if ( !INtDll::NtDllStatus )
return FALSE;
// Allocate the memory for the buffer
SYSTEM_HANDLE_INFORMATION* pSysHandleInformation =
(SYSTEM_HANDLE_INFORMATION*)
VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE );
if ( pSysHandleInformation == NULL )
return FALSE;
// Query the needed buffer size for the objects ( system wide )
if ( INtDll::NtQuerySystemInformation( 16, pSysHandleInformation,
size, &needed ) != 0 )
{
if ( needed == 0 )
{
ret = FALSE;
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 FALSE;
// Query the objects ( system wide )
if ( INtDll::NtQuerySystemInformation( 16, pSysHandleInformation,
size, NULL ) != 0 )
{
ret = FALSE;
goto cleanup;
}
// Iterating through the objects
for ( i = 0; i < pSysHandleInformation->Count; i++ )
{
if ( !IsSupportedHandle( pSysHandleInformation->Handles[i] ) )
continue;
// ProcessId filtering check
if ( pSysHandleInformation->Handles[i].ProcessID ==
m_processId || m_processId == (DWORD)-1 ) {
BOOL bAdd = FALSE;
if ( m_strTypeFilter == _T("") )
bAdd = TRUE;
else
{
// Type filtering
GetTypeToken( (HANDLE)pSysHandleInformation
->Handles[i].HandleNumber,
strType,
pSysHandleInformation
->Handles[i].ProcessID );
bAdd = strType == m_strTypeFilter;
}
// That's it. We found one.
if ( bAdd )
{
pSysHandleInformation->Handles[i].HandleType =
(WORD)(pSysHandleInformation
->Handles[i].HandleType % 256);
m_HandleInfos.push_back( pSysHandleInformation
->Handles[i] );
}
}
}
cleanup:
if ( pSysHandleInformation != NULL )
VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
return ret;
}
HANDLE SystemHandleInformation::OpenProcess( DWORD processId )
{
// Open the process for handle duplication
return ::OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
}
HANDLE SystemHandleInformation::DuplicateHandle( HANDLE hProcess,
HANDLE hRemote )
{
HANDLE hDup = NULL;
// Duplicate the remote handle for our process
::DuplicateHandle( hProcess, hRemote, GetCurrentProcess(), &hDup,
0, FALSE, DUPLICATE_SAME_ACCESS );
return hDup;
}
//Information functions
BOOL SystemHandleInformation::GetTypeToken( HANDLE h, string& str,
DWORD processId )
{
ULONG size = 0x2000;
UCHAR* lpBuffer = NULL;
BOOL ret = FALSE;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( !NtDllStatus )
return FALSE;
if ( remote )
{
// Open the remote process
hRemoteProcess = OpenProcess( processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate the handle
handle = DuplicateHandle( hRemoteProcess, h );
}
else
handle = h;
// Query the info size
INtDll::NtQueryObject( handle, 2, NULL, 0, &size );
lpBuffer = new UCHAR[size];
// Query the info size ( type )
if ( INtDll::NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 )
{
str = _T("");
SystemInfoUtils::LPCWSTR2string( (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;
}
BOOL SystemHandleInformation::GetType( HANDLE h, WORD& type, DWORD processId )
{
string strType;
type = OB_TYPE_UNKNOWN;
if ( !GetTypeToken( h, strType, processId ) )
return FALSE;
return GetTypeFromTypeToken( strType.c_str(), type );
}
BOOL SystemHandleInformation::GetTypeFromTypeToken( LPCTSTR typeToken,
WORD& type )
{
const WORD count = 27;
string constStrTypes[count] = {
_T(""), _T(""), _T("Directory"), _T("SymbolicLink"),
_T("Token"), _T("Process"), _T("Thread"), _T("Unknown7"),
_T("Event"), _T("EventPair"), _T("Mutant"), _T("Unknown11"),
_T("Semaphore"), _T("Timer"), _T("Profile"),
_T("WindowStation"), _T("Desktop"), _T("Section"), _T("Key"),
_T("Port"), _T("WaitablePort"), _T("Unknown21"),
_T("Unknown22"), _T("Unknown23"), _T("Unknown24"),
_T("IoCompletion"), _T("File") };
type = OB_TYPE_UNKNOWN;
for ( WORD i = 1; i < count; i++ )
if ( constStrTypes[i] == typeToken )
{
type = i;
return TRUE;
}
return FALSE;
}
BOOL SystemHandleInformation::GetName( HANDLE handle, string& str, DWORD processId )
{
WORD type = 0;
if ( !GetType( handle, type, processId ) )
return FALSE;
return GetNameByType( handle, type, str, processId );
}
BOOL SystemHandleInformation::GetNameByType( HANDLE h, WORD type, string& str, DWORD processId )
{
ULONG size = 0x2000;
UCHAR* lpBuffer = NULL;
BOOL ret = FALSE;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
DWORD dwId = 0;
if ( !NtDllStatus )
return FALSE;
if ( remote )
{
hRemoteProcess = OpenProcess( processId );
if ( hRemoteProcess == NULL )
return FALSE;
handle = DuplicateHandle( hRemoteProcess, h );
}
else
handle = h;
stringstream hex;
// let's be happy, handle is in our process space, so query the infos :)
switch( type )
{
case OB_TYPE_PROCESS:
GetProcessId( handle, dwId );
hex << "PID: 0x" << std::hex << dwId;
str = hex.str();
ret = TRUE;
goto cleanup;
break;
case OB_TYPE_THREAD:
GetThreadId( handle, dwId );
hex << "TID: 0x" << std::hex << dwId;
ret = TRUE;
goto cleanup;
break;
case OB_TYPE_FILE:
ret = GetFileName( handle, str );
// access denied :(
if ( ret && str == _T("") )
goto cleanup;
break;
};
INtDll::NtQueryObject ( handle, 1, NULL, 0, &size );
// let's try to use the default
if ( size == 0 )
size = 0x2000;
lpBuffer = new UCHAR[size];
if ( INtDll::NtQueryObject( handle, 1, lpBuffer, size, NULL ) == 0 )
{
SystemInfoUtils::Unicode2string( (UNICODE_STRING*)lpBuffer, str );
ret = TRUE;
}
cleanup:
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
if ( lpBuffer != NULL )
delete [] lpBuffer;
return ret;
}
//Thread related functions
BOOL SystemHandleInformation::GetThreadId( HANDLE h, DWORD& threadID, DWORD processId )
{
SystemThreadInformation::BASIC_THREAD_INFORMATION ti;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( !NtDllStatus )
return FALSE;
if ( remote )
{
// Open process
hRemoteProcess = OpenProcess( processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate handle
handle = DuplicateHandle( hRemoteProcess, h );
}
else
handle = h;
// Get the thread information
if ( INtDll::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;
}
//Process related functions
BOOL SystemHandleInformation::GetProcessPath( HANDLE h, string& strPath, DWORD remoteProcessId )
{
h; strPath; remoteProcessId;
stringstream number;
number << remoteProcessId;
strPath = number.str();
return TRUE;
}
BOOL SystemHandleInformation::GetProcessId( HANDLE h, DWORD& processId, DWORD remoteProcessId )
{
BOOL ret = FALSE;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = remoteProcessId != GetCurrentProcessId();
SystemProcessInformation::PROCESS_BASIC_INFORMATION pi;
ZeroMemory( &pi, sizeof(pi) );
processId = 0;
if ( !NtDllStatus )
return FALSE;
if ( remote )
{
// Open process
hRemoteProcess = OpenProcess( remoteProcessId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate handle
handle = DuplicateHandle( hRemoteProcess, h );
}
else
handle = h;
// Get the process information
if ( INtDll::NtQueryInformationProcess( handle, 0, &pi, sizeof(pi), NULL) == 0 )
{
processId = pi.UniqueProcessId;
ret = TRUE;
}
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
return ret;
}
//File related functions
void SystemHandleInformation::GetFileNameThread( PVOID pParam )
{
// This thread function for getting the filename
// if access denied, we hang up in this function,
// so if it times out we just kill this thread
GetFileNameThreadParam* p = (GetFileNameThreadParam*)pParam;
UCHAR lpBuffer[0x1000];
DWORD iob[2];
p->rc = INtDll::NtQueryInformationFile( p->hFile, iob, lpBuffer, sizeof(lpBuffer), 9 );
if ( p->rc == 0 )
*p->pName = (const char *)lpBuffer;
}
BOOL SystemHandleInformation::GetFileName( HANDLE h, string& str, DWORD processId )
{
BOOL ret= FALSE;
HANDLE hThread = NULL;
GetFileNameThreadParam tp;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( !NtDllStatus )
return FALSE;
if ( remote )
{
// Open process
hRemoteProcess = OpenProcess( processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate handle
handle = DuplicateHandle( hRemoteProcess, h );
}
else
handle = h;
tp.hFile = handle;
tp.pName = &str;
tp.rc = 0;
// Let's start the thread to get the file name
hThread = (HANDLE)_beginthread( GetFileNameThread, 0, &tp );
if ( hThread == NULL )
{
ret = FALSE;
goto cleanup;
}
// Wait for finishing the thread
if ( WaitForSingleObject( hThread, 100 ) == WAIT_TIMEOUT )
{
// Access denied
// Terminate the thread
TerminateThread( hThread, 0 );
str = _T("");
ret = TRUE;
}
else
ret = ( tp.rc == 0 );
cleanup:
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////
//
// SystemModuleInformation
//
//////////////////////////////////////////////////////////////////////////////////////
SystemModuleInformation::SystemModuleInformation( DWORD pID, BOOL bRefresh )
{
m_processId = pID;
if ( bRefresh )
Refresh();
}
void SystemModuleInformation::GetModuleListForProcess( DWORD processID )
{
DWORD i = 0;
DWORD cbNeeded = 0;
HMODULE* hModules = NULL;
MODULE_INFO moduleInfo;
// Open process to read to query the module list
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
if ( hProcess == NULL )
goto cleanup;
//Get the number of modules
if ( !(*m_EnumProcessModules)( hProcess, NULL, 0, &cbNeeded ) )
goto cleanup;
hModules = new HMODULE[ cbNeeded / sizeof( HMODULE ) ];
//Get module handles
if ( !(*m_EnumProcessModules)( hProcess, hModules, cbNeeded, &cbNeeded ) )
goto cleanup;
for ( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ )
{
moduleInfo.ProcessId = processID;
moduleInfo.Handle = hModules[i];
//Get module full paths
if ( (*m_GetModuleFileNameEx)( hProcess, hModules[i], moduleInfo.FullPath, _MAX_PATH ) )
m_ModuleInfos.push_back( moduleInfo );
}
cleanup:
if ( hModules != NULL )
delete [] hModules;
if ( hProcess != NULL )
CloseHandle( hProcess );
}
BOOL SystemModuleInformation::Refresh()
{
BOOL rc = FALSE;
m_EnumProcessModules = NULL;
m_GetModuleFileNameEx = NULL;
m_ModuleInfos.clear();
//Load Psapi.dll
HINSTANCE hDll = LoadLibrary( "PSAPI.DLL" );
if ( hDll == NULL )
{
rc = FALSE;
goto cleanup;
}
//Get Psapi.dll functions
m_EnumProcessModules = (PEnumProcessModules)GetProcAddress( hDll, "EnumProcessModules" );
m_GetModuleFileNameEx = (PGetModuleFileNameEx)GetProcAddress( hDll,
#ifdef UNICODE
"GetModuleFileNameExW" );
#else
"GetModuleFileNameExA" );
#endif
if ( m_GetModuleFileNameEx == NULL || m_EnumProcessModules == NULL )
{
rc = FALSE;
goto cleanup;
}
// Everey process or just a particular one
if ( m_processId != -1 )
// For a particular one
GetModuleListForProcess( m_processId );
else
{
// Get teh process list
DWORD pID;
SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p = NULL;
SystemProcessInformation pi( TRUE );
if ( pi.m_ProcessInfos.empty() )
{
rc = FALSE;
goto cleanup;
}
// Iterating through the processes and get the module list
for (map<DWORD, SystemProcessInformation::SYSTEM_PROCESS_INFORMATION *>::iterator iter = pi.m_ProcessInfos.begin(); iter != pi.m_ProcessInfos.end(); iter++) {
pID = iter->first;
p = iter->second;
GetModuleListForProcess( pID );
}
}
rc = TRUE;
cleanup:
//Free psapi.dll
if ( hDll != NULL )
FreeLibrary( hDll );
return rc;
}
//////////////////////////////////////////////////////////////////////////////////////
//
// SystemWindowInformation
//
//////////////////////////////////////////////////////////////////////////////////////
SystemWindowInformation::SystemWindowInformation( DWORD pID, BOOL bRefresh )
{
m_processId = pID;
if ( bRefresh )
Refresh();
}
BOOL SystemWindowInformation::Refresh()
{
m_WindowInfos.clear();
// Enumerating the windows
EnumWindows( EnumerateWindows, (LPARAM)this );
return TRUE;
}
BOOL CALLBACK SystemWindowInformation::EnumerateWindows( HWND hwnd, LPARAM lParam )
{
SystemWindowInformation* _this = (SystemWindowInformation*)lParam;
WINDOW_INFO wi;
wi.hWnd = hwnd;
GetWindowThreadProcessId(hwnd, &wi.ProcessId ) ;
// Filtering by process ID
if ( _this->m_processId == -1 || _this->m_processId == wi.ProcessId )
{
GetWindowText( hwnd, wi.Caption, MaxCaptionSize );
// That is we are looking for
if ( GetLastError() == 0 )
_this->m_WindowInfos.push_back( wi );
}
return TRUE;
};