Add WhoUses, a program to determine which processes access a given file
[msysgit.git] / src / WhoUses / SystemInfo.cpp
blob1585cba5ed65c6d3c26360ea90b9d11beaf6562c
1 // Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
2 // For companies(Austin,TX): If you would like to get my resume, send an email.
3 //
4 // The source is free, but if you want to use it, mention my name and e-mail
5 // address
6 //
7 ///////////////////////////////////////////////////////////////////////////////
8 //
9 // SystemInfo.cpp v1.1
11 // History:
12 //
13 // Date Version Description
14 // ----------------------------------------------------------------------------
15 // 10/16/00 1.0 Initial version
16 // 11/09/00 1.1 NT4 doesn't like if we bother the System process fix :)
17 // SystemInfoUtils::GetDeviceFileName() fix (subst drives
18 // added)
19 // NT Major version added to INtDLL class
21 ///////////////////////////////////////////////////////////////////////////////
23 #include <windows.h>
24 #include <process.h>
25 #include <tchar.h>
26 #include "SystemInfo.h"
29 #include <sstream>
30 using std::stringstream;
32 #ifndef WINNT
33 #error You need Windows NT to use this source code. Define WINNT!
34 #endif
36 ///////////////////////////////////////////////////////////////////////////////
38 // SystemInfoUtils
40 ///////////////////////////////////////////////////////////////////////////////
42 // From wide char string to string
43 void SystemInfoUtils::LPCWSTR2string( LPCWSTR strW, string& str )
45 #ifdef UNICODE
46 // if it is already UNICODE, no problem
47 str = strW;
48 #else
49 str = _T("");
51 TCHAR* actChar = (TCHAR*)strW;
53 if ( actChar == _T('\0') )
54 return;
56 ULONG len = wcslen(strW) + 1;
57 TCHAR* pBuffer = new TCHAR[ len ];
58 TCHAR* pNewStr = pBuffer;
60 while ( len-- )
62 *(pNewStr++) = *actChar;
63 actChar += 2;
66 str = pBuffer;
68 delete [] pBuffer;
69 #endif
72 // From wide char string to unicode
73 void SystemInfoUtils::Unicode2string( UNICODE_STRING* strU, string& str )
75 if ( *(DWORD*)strU != 0 )
76 LPCWSTR2string( (LPCWSTR)strU->Buffer, str );
77 else
78 str = _T("");
81 // From device file name to DOS filename
82 BOOL SystemInfoUtils::GetFsFileName( LPCTSTR lpDeviceFileName,
83 string& fsFileName )
85 BOOL rc = FALSE;
87 TCHAR lpDeviceName[0x1000];
88 TCHAR lpDrive[3] = _T("A:");
90 // Iterating through the drive letters
91 for ( TCHAR actDrive = _T('A'); actDrive <= _T('Z'); actDrive++ ) {
92 lpDrive[0] = actDrive;
94 // Query the device for the drive letter
95 if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 ) {
96 // Network drive?
97 if ( _tcsnicmp( _T("\\Device\\LanmanRedirector\\"),
98 lpDeviceName, 25 ) == 0 ) {
99 //Mapped network drive
101 char cDriveLetter;
102 DWORD dwParam;
104 TCHAR lpSharedName[0x1000];
106 if ( _stscanf( lpDeviceName,
107 _T("\\Device\\LanmanRedirector\\;%c:%d\\%s"),
108 &cDriveLetter,
109 &dwParam,
110 lpSharedName ) != 3 )
111 continue;
113 _tcscpy( lpDeviceName,
114 _T("\\Device\\LanmanRedirector\\") );
115 _tcscat( lpDeviceName, lpSharedName );
118 // Is this the drive letter we are looking for?
119 if ( _tcsnicmp( lpDeviceName, lpDeviceFileName,
120 _tcslen( lpDeviceName ) ) == 0 )
122 fsFileName = lpDrive;
123 fsFileName += (LPCTSTR)( lpDeviceFileName
124 + _tcslen( lpDeviceName ) );
126 rc = TRUE;
128 break;
133 return rc;
136 // From DOS file name to device file name
137 BOOL SystemInfoUtils::GetDeviceFileName( LPCTSTR lpFsFileName,
138 string& deviceFileName )
140 BOOL rc = FALSE;
141 TCHAR lpDrive[3];
143 // Get the drive letter
144 // unfortunetaly it works only with DOS file names
145 _tcsncpy( lpDrive, lpFsFileName, 2 );
146 lpDrive[2] = _T('\0');
148 TCHAR lpDeviceName[0x1000];
150 // Query the device for the drive letter
151 if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 )
153 // Subst drive?
154 if ( _tcsnicmp( _T("\\??\\"), lpDeviceName, 4 ) == 0 )
156 deviceFileName = lpDeviceName + 4;
157 deviceFileName += lpFsFileName + 2;
159 return TRUE;
161 else
162 // Network drive?
163 if ( _tcsnicmp( _T("\\Device\\LanmanRedirector\\"),
164 lpDeviceName, 25 ) == 0 ) {
165 //Mapped network drive
167 char cDriveLetter;
168 DWORD dwParam;
170 TCHAR lpSharedName[0x1000];
172 if ( _stscanf( lpDeviceName,
173 _T("\\Device\\LanmanRedirector\\;%c:%d\\%s"),
174 &cDriveLetter,
175 &dwParam,
176 lpSharedName ) != 3 )
177 return FALSE;
179 _tcscpy( lpDeviceName,
180 _T("\\Device\\LanmanRedirector\\") );
181 _tcscat( lpDeviceName, lpSharedName );
184 _tcscat( lpDeviceName, lpFsFileName + 2 );
186 deviceFileName = lpDeviceName;
188 rc = TRUE;
191 return rc;
194 //Get NT version
195 DWORD SystemInfoUtils::GetNTMajorVersion()
197 OSVERSIONINFOEX osvi;
198 BOOL bOsVersionInfoEx;
200 // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
201 // which is supported on Windows 2000.
203 // If that fails, try using the OSVERSIONINFO structure.
205 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
206 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
208 bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
210 if( bOsVersionInfoEx == 0 )
212 // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
214 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
215 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
216 return FALSE;
219 return osvi.dwMajorVersion;
222 ///////////////////////////////////////////////////////////////////////////////
224 // INtDll
226 ///////////////////////////////////////////////////////////////////////////////
227 INtDll::PNtQuerySystemInformation INtDll::NtQuerySystemInformation = NULL;
228 INtDll::PNtQueryObject INtDll::NtQueryObject = NULL;
229 INtDll::PNtQueryInformationThread INtDll::NtQueryInformationThread = NULL;
230 INtDll::PNtQueryInformationFile INtDll::NtQueryInformationFile = NULL;
231 INtDll::PNtQueryInformationProcess INtDll::NtQueryInformationProcess = NULL;
232 DWORD INtDll::dwNTMajorVersion = SystemInfoUtils::GetNTMajorVersion();
234 BOOL INtDll::NtDllStatus = INtDll::Init();
236 BOOL INtDll::Init()
238 // Get the NtDll function pointers
239 NtQuerySystemInformation = (PNtQuerySystemInformation)
240 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
241 _T("NtQuerySystemInformation") );
243 NtQueryObject = (PNtQueryObject)
244 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
245 _T("NtQueryObject") );
247 NtQueryInformationThread = (PNtQueryInformationThread)
248 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
249 _T("NtQueryInformationThread") );
251 NtQueryInformationFile = (PNtQueryInformationFile)
252 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
253 _T("NtQueryInformationFile") );
255 NtQueryInformationProcess = (PNtQueryInformationProcess)
256 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
257 _T("NtQueryInformationProcess") );
259 return NtQuerySystemInformation != NULL &&
260 NtQueryObject != NULL &&
261 NtQueryInformationThread != NULL &&
262 NtQueryInformationFile != NULL &&
263 NtQueryInformationProcess != NULL;
266 ///////////////////////////////////////////////////////////////////////////////
268 // SystemProcessInformation
270 ///////////////////////////////////////////////////////////////////////////////
272 SystemProcessInformation::SystemProcessInformation( BOOL bRefresh )
274 m_pBuffer = (UCHAR*)VirtualAlloc ((void*)0x100000,
275 BufferSize,
276 MEM_COMMIT,
277 PAGE_READWRITE);
279 if ( bRefresh )
280 Refresh();
283 SystemProcessInformation::~SystemProcessInformation()
285 VirtualFree( m_pBuffer, 0, MEM_RELEASE );
288 BOOL SystemProcessInformation::Refresh()
290 m_ProcessInfos.clear();
291 m_pCurrentProcessInfo = NULL;
293 if ( !NtDllStatus || m_pBuffer == NULL )
294 return FALSE;
296 // query the process information
297 if ( INtDll::NtQuerySystemInformation( 5, m_pBuffer, BufferSize, NULL )
298 != 0 )
299 return FALSE;
301 DWORD currentProcessID = GetCurrentProcessId(); //Current Process ID
303 SYSTEM_PROCESS_INFORMATION* pSysProcess =
304 (SYSTEM_PROCESS_INFORMATION*)m_pBuffer;
307 // fill the process information map
308 m_ProcessInfos[pSysProcess->dUniqueProcessId] = pSysProcess;
310 // we found this process
311 if ( pSysProcess->dUniqueProcessId == currentProcessID )
312 m_pCurrentProcessInfo = pSysProcess;
314 // get the next process information block
315 if ( pSysProcess->dNext != 0 )
316 pSysProcess = (SYSTEM_PROCESS_INFORMATION*)
317 ((UCHAR*)pSysProcess + pSysProcess->dNext);
318 else
319 pSysProcess = NULL;
321 } while ( pSysProcess != NULL );
323 return TRUE;
326 ///////////////////////////////////////////////////////////////////////////////
328 // SystemThreadInformation
330 ///////////////////////////////////////////////////////////////////////////////
332 SystemThreadInformation::SystemThreadInformation( DWORD pID, BOOL bRefresh )
334 m_processId = pID;
336 if ( bRefresh )
337 Refresh();
340 BOOL SystemThreadInformation::Refresh()
342 // Get the Thread objects ( set the filter to "Thread" )
343 SystemHandleInformation hi( m_processId );
344 BOOL rc = hi.SetFilter( _T("Thread"), TRUE );
346 m_ThreadInfos.clear();
348 if ( !rc )
349 return FALSE;
351 THREAD_INFORMATION ti;
353 // Iterating through the found Thread objects
354 for (list<SystemHandleInformation::SYSTEM_HANDLE>::iterator iter = hi.m_HandleInfos.begin(); iter != hi.m_HandleInfos.end(); iter++) {
355 SystemHandleInformation::SYSTEM_HANDLE& h = *iter;
357 ti.ProcessId = h.ProcessID;
358 ti.ThreadHandle = (HANDLE)h.HandleNumber;
360 // This is one of the threads we are lokking for
361 if ( SystemHandleInformation::GetThreadId( ti.ThreadHandle,
362 ti.ThreadId, ti.ProcessId ) )
363 m_ThreadInfos.push_back( ti );
366 return TRUE;
369 ///////////////////////////////////////////////////////////////////////////////
371 // SystemHandleInformation
373 ///////////////////////////////////////////////////////////////////////////////
375 SystemHandleInformation::SystemHandleInformation( DWORD pID, BOOL bRefresh,
376 LPCTSTR lpTypeFilter )
378 m_processId = pID;
380 // Set the filter
381 SetFilter( lpTypeFilter, bRefresh );
384 SystemHandleInformation::~SystemHandleInformation()
388 BOOL SystemHandleInformation::SetFilter( LPCTSTR lpTypeFilter, BOOL bRefresh )
390 // Set the filter ( default = all objects )
391 m_strTypeFilter = lpTypeFilter == NULL ? _T("") : lpTypeFilter;
393 return bRefresh ? Refresh() : TRUE;
396 const string& SystemHandleInformation::GetFilter()
398 return m_strTypeFilter;
401 BOOL SystemHandleInformation::IsSupportedHandle( SYSTEM_HANDLE& handle )
403 //Here you can filter the handles you don't want in the Handle list
405 // Windows 2000 supports everything :)
406 if ( dwNTMajorVersion >= 5 )
407 return TRUE;
409 //NT4 System process doesn't like if we bother his internal security :)
410 if ( handle.ProcessID == 2 && handle.HandleType == 16 )
411 return FALSE;
413 return TRUE;
416 BOOL SystemHandleInformation::Refresh()
418 DWORD size = 0x2000;
419 DWORD needed = 0;
420 DWORD i = 0;
421 BOOL ret = TRUE;
422 string strType;
424 m_HandleInfos.clear();
426 if ( !INtDll::NtDllStatus )
427 return FALSE;
429 // Allocate the memory for the buffer
430 SYSTEM_HANDLE_INFORMATION* pSysHandleInformation =
431 (SYSTEM_HANDLE_INFORMATION*)
432 VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE );
434 if ( pSysHandleInformation == NULL )
435 return FALSE;
437 // Query the needed buffer size for the objects ( system wide )
438 if ( INtDll::NtQuerySystemInformation( 16, pSysHandleInformation,
439 size, &needed ) != 0 )
441 if ( needed == 0 )
443 ret = FALSE;
444 goto cleanup;
447 // The size was not enough
448 VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
450 pSysHandleInformation = (SYSTEM_HANDLE_INFORMATION*)
451 VirtualAlloc( NULL, size = needed + 256,
452 MEM_COMMIT, PAGE_READWRITE );
455 if ( pSysHandleInformation == NULL )
456 return FALSE;
458 // Query the objects ( system wide )
459 if ( INtDll::NtQuerySystemInformation( 16, pSysHandleInformation,
460 size, NULL ) != 0 )
462 ret = FALSE;
463 goto cleanup;
466 // Iterating through the objects
467 for ( i = 0; i < pSysHandleInformation->Count; i++ )
469 if ( !IsSupportedHandle( pSysHandleInformation->Handles[i] ) )
470 continue;
472 // ProcessId filtering check
473 if ( pSysHandleInformation->Handles[i].ProcessID ==
474 m_processId || m_processId == (DWORD)-1 ) {
475 BOOL bAdd = FALSE;
477 if ( m_strTypeFilter == _T("") )
478 bAdd = TRUE;
479 else
481 // Type filtering
482 GetTypeToken( (HANDLE)pSysHandleInformation
483 ->Handles[i].HandleNumber,
484 strType,
485 pSysHandleInformation
486 ->Handles[i].ProcessID );
488 bAdd = strType == m_strTypeFilter;
491 // That's it. We found one.
492 if ( bAdd )
494 pSysHandleInformation->Handles[i].HandleType =
495 (WORD)(pSysHandleInformation
496 ->Handles[i].HandleType % 256);
498 m_HandleInfos.push_back( pSysHandleInformation
499 ->Handles[i] );
505 cleanup:
507 if ( pSysHandleInformation != NULL )
508 VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
510 return ret;
513 HANDLE SystemHandleInformation::OpenProcess( DWORD processId )
515 // Open the process for handle duplication
516 return ::OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
519 HANDLE SystemHandleInformation::DuplicateHandle( HANDLE hProcess,
520 HANDLE hRemote )
522 HANDLE hDup = NULL;
524 // Duplicate the remote handle for our process
525 ::DuplicateHandle( hProcess, hRemote, GetCurrentProcess(), &hDup,
526 0, FALSE, DUPLICATE_SAME_ACCESS );
528 return hDup;
531 //Information functions
532 BOOL SystemHandleInformation::GetTypeToken( HANDLE h, string& str,
533 DWORD processId )
535 ULONG size = 0x2000;
536 UCHAR* lpBuffer = NULL;
537 BOOL ret = FALSE;
539 HANDLE handle;
540 HANDLE hRemoteProcess = NULL;
541 BOOL remote = processId != GetCurrentProcessId();
543 if ( !NtDllStatus )
544 return FALSE;
546 if ( remote )
548 // Open the remote process
549 hRemoteProcess = OpenProcess( processId );
551 if ( hRemoteProcess == NULL )
552 return FALSE;
554 // Duplicate the handle
555 handle = DuplicateHandle( hRemoteProcess, h );
557 else
558 handle = h;
560 // Query the info size
561 INtDll::NtQueryObject( handle, 2, NULL, 0, &size );
563 lpBuffer = new UCHAR[size];
565 // Query the info size ( type )
566 if ( INtDll::NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 )
568 str = _T("");
569 SystemInfoUtils::LPCWSTR2string( (LPCWSTR)(lpBuffer+0x60),
570 str );
572 ret = TRUE;
575 if ( remote )
577 if ( hRemoteProcess != NULL )
578 CloseHandle( hRemoteProcess );
580 if ( handle != NULL )
581 CloseHandle( handle );
584 if ( lpBuffer != NULL )
585 delete [] lpBuffer;
587 return ret;
590 BOOL SystemHandleInformation::GetType( HANDLE h, WORD& type, DWORD processId )
592 string strType;
594 type = OB_TYPE_UNKNOWN;
596 if ( !GetTypeToken( h, strType, processId ) )
597 return FALSE;
599 return GetTypeFromTypeToken( strType.c_str(), type );
602 BOOL SystemHandleInformation::GetTypeFromTypeToken( LPCTSTR typeToken,
603 WORD& type )
605 const WORD count = 27;
606 string constStrTypes[count] = {
607 _T(""), _T(""), _T("Directory"), _T("SymbolicLink"),
608 _T("Token"), _T("Process"), _T("Thread"), _T("Unknown7"),
609 _T("Event"), _T("EventPair"), _T("Mutant"), _T("Unknown11"),
610 _T("Semaphore"), _T("Timer"), _T("Profile"),
611 _T("WindowStation"), _T("Desktop"), _T("Section"), _T("Key"),
612 _T("Port"), _T("WaitablePort"), _T("Unknown21"),
613 _T("Unknown22"), _T("Unknown23"), _T("Unknown24"),
614 _T("IoCompletion"), _T("File") };
616 type = OB_TYPE_UNKNOWN;
618 for ( WORD i = 1; i < count; i++ )
619 if ( constStrTypes[i] == typeToken )
621 type = i;
622 return TRUE;
625 return FALSE;
628 BOOL SystemHandleInformation::GetName( HANDLE handle, string& str, DWORD processId )
630 WORD type = 0;
632 if ( !GetType( handle, type, processId ) )
633 return FALSE;
635 return GetNameByType( handle, type, str, processId );
638 BOOL SystemHandleInformation::GetNameByType( HANDLE h, WORD type, string& str, DWORD processId )
640 ULONG size = 0x2000;
641 UCHAR* lpBuffer = NULL;
642 BOOL ret = FALSE;
644 HANDLE handle;
645 HANDLE hRemoteProcess = NULL;
646 BOOL remote = processId != GetCurrentProcessId();
647 DWORD dwId = 0;
649 if ( !NtDllStatus )
650 return FALSE;
652 if ( remote )
654 hRemoteProcess = OpenProcess( processId );
656 if ( hRemoteProcess == NULL )
657 return FALSE;
659 handle = DuplicateHandle( hRemoteProcess, h );
661 else
662 handle = h;
664 stringstream hex;
665 // let's be happy, handle is in our process space, so query the infos :)
666 switch( type )
668 case OB_TYPE_PROCESS:
669 GetProcessId( handle, dwId );
671 hex << "PID: 0x" << std::hex << dwId;
672 str = hex.str();
674 ret = TRUE;
675 goto cleanup;
676 break;
678 case OB_TYPE_THREAD:
679 GetThreadId( handle, dwId );
681 hex << "TID: 0x" << std::hex << dwId;
683 ret = TRUE;
684 goto cleanup;
685 break;
687 case OB_TYPE_FILE:
688 ret = GetFileName( handle, str );
690 // access denied :(
691 if ( ret && str == _T("") )
692 goto cleanup;
693 break;
697 INtDll::NtQueryObject ( handle, 1, NULL, 0, &size );
699 // let's try to use the default
700 if ( size == 0 )
701 size = 0x2000;
703 lpBuffer = new UCHAR[size];
705 if ( INtDll::NtQueryObject( handle, 1, lpBuffer, size, NULL ) == 0 )
707 SystemInfoUtils::Unicode2string( (UNICODE_STRING*)lpBuffer, str );
708 ret = TRUE;
711 cleanup:
713 if ( remote )
715 if ( hRemoteProcess != NULL )
716 CloseHandle( hRemoteProcess );
718 if ( handle != NULL )
719 CloseHandle( handle );
722 if ( lpBuffer != NULL )
723 delete [] lpBuffer;
725 return ret;
728 //Thread related functions
729 BOOL SystemHandleInformation::GetThreadId( HANDLE h, DWORD& threadID, DWORD processId )
731 SystemThreadInformation::BASIC_THREAD_INFORMATION ti;
732 HANDLE handle;
733 HANDLE hRemoteProcess = NULL;
734 BOOL remote = processId != GetCurrentProcessId();
736 if ( !NtDllStatus )
737 return FALSE;
739 if ( remote )
741 // Open process
742 hRemoteProcess = OpenProcess( processId );
744 if ( hRemoteProcess == NULL )
745 return FALSE;
747 // Duplicate handle
748 handle = DuplicateHandle( hRemoteProcess, h );
750 else
751 handle = h;
753 // Get the thread information
754 if ( INtDll::NtQueryInformationThread( handle, 0, &ti, sizeof(ti), NULL ) == 0 )
755 threadID = ti.ThreadId;
757 if ( remote )
759 if ( hRemoteProcess != NULL )
760 CloseHandle( hRemoteProcess );
762 if ( handle != NULL )
763 CloseHandle( handle );
766 return TRUE;
769 //Process related functions
770 BOOL SystemHandleInformation::GetProcessPath( HANDLE h, string& strPath, DWORD remoteProcessId )
772 h; strPath; remoteProcessId;
774 stringstream number;
775 number << remoteProcessId;
776 strPath = number.str();
778 return TRUE;
781 BOOL SystemHandleInformation::GetProcessId( HANDLE h, DWORD& processId, DWORD remoteProcessId )
783 BOOL ret = FALSE;
784 HANDLE handle;
785 HANDLE hRemoteProcess = NULL;
786 BOOL remote = remoteProcessId != GetCurrentProcessId();
787 SystemProcessInformation::PROCESS_BASIC_INFORMATION pi;
789 ZeroMemory( &pi, sizeof(pi) );
790 processId = 0;
792 if ( !NtDllStatus )
793 return FALSE;
795 if ( remote )
797 // Open process
798 hRemoteProcess = OpenProcess( remoteProcessId );
800 if ( hRemoteProcess == NULL )
801 return FALSE;
803 // Duplicate handle
804 handle = DuplicateHandle( hRemoteProcess, h );
806 else
807 handle = h;
809 // Get the process information
810 if ( INtDll::NtQueryInformationProcess( handle, 0, &pi, sizeof(pi), NULL) == 0 )
812 processId = pi.UniqueProcessId;
813 ret = TRUE;
816 if ( remote )
818 if ( hRemoteProcess != NULL )
819 CloseHandle( hRemoteProcess );
821 if ( handle != NULL )
822 CloseHandle( handle );
825 return ret;
828 //File related functions
829 void SystemHandleInformation::GetFileNameThread( PVOID pParam )
831 // This thread function for getting the filename
832 // if access denied, we hang up in this function,
833 // so if it times out we just kill this thread
834 GetFileNameThreadParam* p = (GetFileNameThreadParam*)pParam;
836 UCHAR lpBuffer[0x1000];
837 DWORD iob[2];
839 p->rc = INtDll::NtQueryInformationFile( p->hFile, iob, lpBuffer, sizeof(lpBuffer), 9 );
841 if ( p->rc == 0 )
842 *p->pName = (const char *)lpBuffer;
845 BOOL SystemHandleInformation::GetFileName( HANDLE h, string& str, DWORD processId )
847 BOOL ret= FALSE;
848 HANDLE hThread = NULL;
849 GetFileNameThreadParam tp;
850 HANDLE handle;
851 HANDLE hRemoteProcess = NULL;
852 BOOL remote = processId != GetCurrentProcessId();
854 if ( !NtDllStatus )
855 return FALSE;
857 if ( remote )
859 // Open process
860 hRemoteProcess = OpenProcess( processId );
862 if ( hRemoteProcess == NULL )
863 return FALSE;
865 // Duplicate handle
866 handle = DuplicateHandle( hRemoteProcess, h );
868 else
869 handle = h;
871 tp.hFile = handle;
872 tp.pName = &str;
873 tp.rc = 0;
875 // Let's start the thread to get the file name
876 hThread = (HANDLE)_beginthread( GetFileNameThread, 0, &tp );
878 if ( hThread == NULL )
880 ret = FALSE;
881 goto cleanup;
884 // Wait for finishing the thread
885 if ( WaitForSingleObject( hThread, 100 ) == WAIT_TIMEOUT )
887 // Access denied
888 // Terminate the thread
889 TerminateThread( hThread, 0 );
891 str = _T("");
893 ret = TRUE;
895 else
896 ret = ( tp.rc == 0 );
898 cleanup:
900 if ( remote )
902 if ( hRemoteProcess != NULL )
903 CloseHandle( hRemoteProcess );
905 if ( handle != NULL )
906 CloseHandle( handle );
909 return ret;
912 //////////////////////////////////////////////////////////////////////////////////////
914 // SystemModuleInformation
916 //////////////////////////////////////////////////////////////////////////////////////
918 SystemModuleInformation::SystemModuleInformation( DWORD pID, BOOL bRefresh )
920 m_processId = pID;
922 if ( bRefresh )
923 Refresh();
926 void SystemModuleInformation::GetModuleListForProcess( DWORD processID )
928 DWORD i = 0;
929 DWORD cbNeeded = 0;
930 HMODULE* hModules = NULL;
931 MODULE_INFO moduleInfo;
933 // Open process to read to query the module list
934 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
936 if ( hProcess == NULL )
937 goto cleanup;
939 //Get the number of modules
940 if ( !(*m_EnumProcessModules)( hProcess, NULL, 0, &cbNeeded ) )
941 goto cleanup;
943 hModules = new HMODULE[ cbNeeded / sizeof( HMODULE ) ];
945 //Get module handles
946 if ( !(*m_EnumProcessModules)( hProcess, hModules, cbNeeded, &cbNeeded ) )
947 goto cleanup;
949 for ( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ )
951 moduleInfo.ProcessId = processID;
952 moduleInfo.Handle = hModules[i];
954 //Get module full paths
955 if ( (*m_GetModuleFileNameEx)( hProcess, hModules[i], moduleInfo.FullPath, _MAX_PATH ) )
956 m_ModuleInfos.push_back( moduleInfo );
959 cleanup:
960 if ( hModules != NULL )
961 delete [] hModules;
963 if ( hProcess != NULL )
964 CloseHandle( hProcess );
967 BOOL SystemModuleInformation::Refresh()
969 BOOL rc = FALSE;
970 m_EnumProcessModules = NULL;
971 m_GetModuleFileNameEx = NULL;
973 m_ModuleInfos.clear();
975 //Load Psapi.dll
976 HINSTANCE hDll = LoadLibrary( "PSAPI.DLL" );
978 if ( hDll == NULL )
980 rc = FALSE;
981 goto cleanup;
984 //Get Psapi.dll functions
985 m_EnumProcessModules = (PEnumProcessModules)GetProcAddress( hDll, "EnumProcessModules" );
987 m_GetModuleFileNameEx = (PGetModuleFileNameEx)GetProcAddress( hDll,
988 #ifdef UNICODE
989 "GetModuleFileNameExW" );
990 #else
991 "GetModuleFileNameExA" );
992 #endif
994 if ( m_GetModuleFileNameEx == NULL || m_EnumProcessModules == NULL )
996 rc = FALSE;
997 goto cleanup;
1000 // Everey process or just a particular one
1001 if ( m_processId != -1 )
1002 // For a particular one
1003 GetModuleListForProcess( m_processId );
1004 else
1006 // Get teh process list
1007 DWORD pID;
1008 SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p = NULL;
1009 SystemProcessInformation pi( TRUE );
1011 if ( pi.m_ProcessInfos.empty() )
1013 rc = FALSE;
1014 goto cleanup;
1017 // Iterating through the processes and get the module list
1018 for (map<DWORD, SystemProcessInformation::SYSTEM_PROCESS_INFORMATION *>::iterator iter = pi.m_ProcessInfos.begin(); iter != pi.m_ProcessInfos.end(); iter++) {
1019 pID = iter->first;
1020 p = iter->second;
1021 GetModuleListForProcess( pID );
1025 rc = TRUE;
1027 cleanup:
1029 //Free psapi.dll
1030 if ( hDll != NULL )
1031 FreeLibrary( hDll );
1033 return rc;
1036 //////////////////////////////////////////////////////////////////////////////////////
1038 // SystemWindowInformation
1040 //////////////////////////////////////////////////////////////////////////////////////
1042 SystemWindowInformation::SystemWindowInformation( DWORD pID, BOOL bRefresh )
1044 m_processId = pID;
1046 if ( bRefresh )
1047 Refresh();
1050 BOOL SystemWindowInformation::Refresh()
1052 m_WindowInfos.clear();
1054 // Enumerating the windows
1055 EnumWindows( EnumerateWindows, (LPARAM)this );
1057 return TRUE;
1060 BOOL CALLBACK SystemWindowInformation::EnumerateWindows( HWND hwnd, LPARAM lParam )
1062 SystemWindowInformation* _this = (SystemWindowInformation*)lParam;
1063 WINDOW_INFO wi;
1065 wi.hWnd = hwnd;
1066 GetWindowThreadProcessId(hwnd, &wi.ProcessId ) ;
1068 // Filtering by process ID
1069 if ( _this->m_processId == -1 || _this->m_processId == wi.ProcessId )
1071 GetWindowText( hwnd, wi.Caption, MaxCaptionSize );
1073 // That is we are looking for
1074 if ( GetLastError() == 0 )
1075 _this->m_WindowInfos.push_back( wi );
1078 return TRUE;