// 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 #include #include #include #include "SystemInfo.h" #include 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; int 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; int 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_dBufferSize(0x10000) { m_pBuffer = (UCHAR*)VirtualAlloc (NULL, m_dBufferSize, 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; while ( 1 ) { // query the process information NTSTATUS result = INtDll::NtQuerySystemInformation( 5, m_pBuffer, m_dBufferSize, NULL ); if ( result == 0 ) break; if ( result != STATUS_INFO_LENGTH_MISMATCH ) { fprintf( stderr, "NtQuerySystemInformation: 0x%x", result ); return FALSE; } VirtualFree( m_pBuffer, 0, MEM_RELEASE ); m_dBufferSize <<= 1; m_pBuffer= (UCHAR*)VirtualAlloc( NULL, m_dBufferSize, MEM_COMMIT, PAGE_READWRITE ); if ( m_pBuffer == NULL ) { fprintf( stderr, "Out of memory!\n" ); 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::iterator iter = hi.m_HandleInfos.begin(); iter != hi.m_HandleInfos.end(); iter++) { SystemHandleInformation::SYSTEM_HANDLE& h = *iter; ti.ProcessId = h.ProcessID; ti.ThreadHandle = (HANDLE)(DWORD_PTR)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 ); while ( 1 ) { if ( pSysHandleInformation == NULL ) return FALSE; // Query the needed buffer size for the objects ( system wide ) DWORD result = INtDll::NtQuerySystemInformation( 16, pSysHandleInformation, size, &needed ); if ( result == 0 ) break; if ( result != STATUS_INFO_LENGTH_MISMATCH ) { fprintf( stderr, "NtQuerySystemInformation: 0x%x\n", result ); 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 ); } // 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)(DWORD_PTR)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::Unicode2string( (UNICODE_STRING *)lpBuffer, 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 ) { 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 != (DWORD)-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::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 == (DWORD)-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; };