shell prompt should not beep and only show MSYSTEM when non-standard.
[msysgit.git] / src / WhoUses / SystemInfo.cpp
blob92eb6f01f4a9a51f643f76fab3b17bca3910366f
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 <stdio.h>
27 #include "SystemInfo.h"
30 #include <sstream>
31 using std::stringstream;
33 #ifndef WINNT
34 #error You need Windows NT to use this source code. Define WINNT!
35 #endif
37 ///////////////////////////////////////////////////////////////////////////////
39 // SystemInfoUtils
41 ///////////////////////////////////////////////////////////////////////////////
43 // From wide char string to string
44 void SystemInfoUtils::LPCWSTR2string( LPCWSTR strW, string& str )
46 #ifdef UNICODE
47 // if it is already UNICODE, no problem
48 str = strW;
49 #else
50 str = _T("");
52 TCHAR* actChar = (TCHAR*)strW;
54 if ( actChar == _T('\0') )
55 return;
57 ULONG len = wcslen(strW) + 1;
58 TCHAR* pBuffer = new TCHAR[ len ];
59 TCHAR* pNewStr = pBuffer;
61 while ( len-- )
63 *(pNewStr++) = *actChar;
64 actChar += 2;
67 str = pBuffer;
69 delete [] pBuffer;
70 #endif
73 // From wide char string to unicode
74 void SystemInfoUtils::Unicode2string( UNICODE_STRING* strU, string& str )
76 if ( *(DWORD*)strU != 0 )
77 LPCWSTR2string( (LPCWSTR)strU->Buffer, str );
78 else
79 str = _T("");
82 // From device file name to DOS filename
83 BOOL SystemInfoUtils::GetFsFileName( LPCTSTR lpDeviceFileName,
84 string& fsFileName )
86 BOOL rc = FALSE;
88 TCHAR lpDeviceName[0x1000];
89 TCHAR lpDrive[3] = _T("A:");
91 // Iterating through the drive letters
92 for ( TCHAR actDrive = _T('A'); actDrive <= _T('Z'); actDrive++ ) {
93 lpDrive[0] = actDrive;
95 // Query the device for the drive letter
96 if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 ) {
97 // Network drive?
98 if ( _tcsnicmp( _T("\\Device\\LanmanRedirector\\"),
99 lpDeviceName, 25 ) == 0 ) {
100 //Mapped network drive
102 char cDriveLetter;
103 DWORD dwParam;
105 TCHAR lpSharedName[0x1000];
107 if ( _stscanf( lpDeviceName,
108 _T("\\Device\\LanmanRedirector\\;%c:%d\\%s"),
109 &cDriveLetter,
110 &dwParam,
111 lpSharedName ) != 3 )
112 continue;
114 _tcscpy( lpDeviceName,
115 _T("\\Device\\LanmanRedirector\\") );
116 _tcscat( lpDeviceName, lpSharedName );
119 // Is this the drive letter we are looking for?
120 if ( _tcsnicmp( lpDeviceName, lpDeviceFileName,
121 _tcslen( lpDeviceName ) ) == 0 )
123 fsFileName = lpDrive;
124 fsFileName += (LPCTSTR)( lpDeviceFileName
125 + _tcslen( lpDeviceName ) );
127 rc = TRUE;
129 break;
134 return rc;
137 // From DOS file name to device file name
138 BOOL SystemInfoUtils::GetDeviceFileName( LPCTSTR lpFsFileName,
139 string& deviceFileName )
141 BOOL rc = FALSE;
142 TCHAR lpDrive[3];
144 // Get the drive letter
145 // unfortunetaly it works only with DOS file names
146 _tcsncpy( lpDrive, lpFsFileName, 2 );
147 lpDrive[2] = _T('\0');
149 TCHAR lpDeviceName[0x1000];
151 // Query the device for the drive letter
152 if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 )
154 // Subst drive?
155 if ( _tcsnicmp( _T("\\??\\"), lpDeviceName, 4 ) == 0 )
157 deviceFileName = lpDeviceName + 4;
158 deviceFileName += lpFsFileName + 2;
160 return TRUE;
162 else
163 // Network drive?
164 if ( _tcsnicmp( _T("\\Device\\LanmanRedirector\\"),
165 lpDeviceName, 25 ) == 0 ) {
166 //Mapped network drive
168 char cDriveLetter;
169 DWORD dwParam;
171 TCHAR lpSharedName[0x1000];
173 if ( _stscanf( lpDeviceName,
174 _T("\\Device\\LanmanRedirector\\;%c:%d\\%s"),
175 &cDriveLetter,
176 &dwParam,
177 lpSharedName ) != 3 )
178 return FALSE;
180 _tcscpy( lpDeviceName,
181 _T("\\Device\\LanmanRedirector\\") );
182 _tcscat( lpDeviceName, lpSharedName );
185 _tcscat( lpDeviceName, lpFsFileName + 2 );
187 deviceFileName = lpDeviceName;
189 rc = TRUE;
192 return rc;
195 //Get NT version
196 DWORD SystemInfoUtils::GetNTMajorVersion()
198 OSVERSIONINFOEX osvi;
199 BOOL bOsVersionInfoEx;
201 // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
202 // which is supported on Windows 2000.
204 // If that fails, try using the OSVERSIONINFO structure.
206 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
207 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
209 bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
211 if( bOsVersionInfoEx == 0 )
213 // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
215 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
216 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
217 return FALSE;
220 return osvi.dwMajorVersion;
223 ///////////////////////////////////////////////////////////////////////////////
225 // INtDll
227 ///////////////////////////////////////////////////////////////////////////////
228 INtDll::PNtQuerySystemInformation INtDll::NtQuerySystemInformation = NULL;
229 INtDll::PNtQueryObject INtDll::NtQueryObject = NULL;
230 INtDll::PNtQueryInformationThread INtDll::NtQueryInformationThread = NULL;
231 INtDll::PNtQueryInformationFile INtDll::NtQueryInformationFile = NULL;
232 INtDll::PNtQueryInformationProcess INtDll::NtQueryInformationProcess = NULL;
233 DWORD INtDll::dwNTMajorVersion = SystemInfoUtils::GetNTMajorVersion();
235 BOOL INtDll::NtDllStatus = INtDll::Init();
237 BOOL INtDll::Init()
239 // Get the NtDll function pointers
240 NtQuerySystemInformation = (PNtQuerySystemInformation)
241 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
242 _T("NtQuerySystemInformation") );
244 NtQueryObject = (PNtQueryObject)
245 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
246 _T("NtQueryObject") );
248 NtQueryInformationThread = (PNtQueryInformationThread)
249 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
250 _T("NtQueryInformationThread") );
252 NtQueryInformationFile = (PNtQueryInformationFile)
253 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
254 _T("NtQueryInformationFile") );
256 NtQueryInformationProcess = (PNtQueryInformationProcess)
257 GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
258 _T("NtQueryInformationProcess") );
260 return NtQuerySystemInformation != NULL &&
261 NtQueryObject != NULL &&
262 NtQueryInformationThread != NULL &&
263 NtQueryInformationFile != NULL &&
264 NtQueryInformationProcess != NULL;
267 ///////////////////////////////////////////////////////////////////////////////
269 // SystemProcessInformation
271 ///////////////////////////////////////////////////////////////////////////////
273 SystemProcessInformation::SystemProcessInformation( BOOL bRefresh )
275 m_pBuffer = (UCHAR*)VirtualAlloc ((void*)0x100000,
276 BufferSize,
277 MEM_COMMIT,
278 PAGE_READWRITE);
280 if ( bRefresh )
281 Refresh();
284 SystemProcessInformation::~SystemProcessInformation()
286 VirtualFree( m_pBuffer, 0, MEM_RELEASE );
289 BOOL SystemProcessInformation::Refresh()
291 m_ProcessInfos.clear();
292 m_pCurrentProcessInfo = NULL;
294 if ( !NtDllStatus || m_pBuffer == NULL )
295 return FALSE;
297 // query the process information
298 if ( INtDll::NtQuerySystemInformation( 5, m_pBuffer, BufferSize, NULL )
299 != 0 )
300 return FALSE;
302 DWORD currentProcessID = GetCurrentProcessId(); //Current Process ID
304 SYSTEM_PROCESS_INFORMATION* pSysProcess =
305 (SYSTEM_PROCESS_INFORMATION*)m_pBuffer;
308 // fill the process information map
309 m_ProcessInfos[pSysProcess->dUniqueProcessId] = pSysProcess;
311 // we found this process
312 if ( pSysProcess->dUniqueProcessId == currentProcessID )
313 m_pCurrentProcessInfo = pSysProcess;
315 // get the next process information block
316 if ( pSysProcess->dNext != 0 )
317 pSysProcess = (SYSTEM_PROCESS_INFORMATION*)
318 ((UCHAR*)pSysProcess + pSysProcess->dNext);
319 else
320 pSysProcess = NULL;
322 } while ( pSysProcess != NULL );
324 return TRUE;
327 ///////////////////////////////////////////////////////////////////////////////
329 // SystemThreadInformation
331 ///////////////////////////////////////////////////////////////////////////////
333 SystemThreadInformation::SystemThreadInformation( DWORD pID, BOOL bRefresh )
335 m_processId = pID;
337 if ( bRefresh )
338 Refresh();
341 BOOL SystemThreadInformation::Refresh()
343 // Get the Thread objects ( set the filter to "Thread" )
344 SystemHandleInformation hi( m_processId );
345 BOOL rc = hi.SetFilter( _T("Thread"), TRUE );
347 m_ThreadInfos.clear();
349 if ( !rc )
350 return FALSE;
352 THREAD_INFORMATION ti;
354 // Iterating through the found Thread objects
355 for (list<SystemHandleInformation::SYSTEM_HANDLE>::iterator iter = hi.m_HandleInfos.begin(); iter != hi.m_HandleInfos.end(); iter++) {
356 SystemHandleInformation::SYSTEM_HANDLE& h = *iter;
358 ti.ProcessId = h.ProcessID;
359 ti.ThreadHandle = (HANDLE)h.HandleNumber;
361 // This is one of the threads we are lokking for
362 if ( SystemHandleInformation::GetThreadId( ti.ThreadHandle,
363 ti.ThreadId, ti.ProcessId ) )
364 m_ThreadInfos.push_back( ti );
367 return TRUE;
370 ///////////////////////////////////////////////////////////////////////////////
372 // SystemHandleInformation
374 ///////////////////////////////////////////////////////////////////////////////
376 SystemHandleInformation::SystemHandleInformation( DWORD pID, BOOL bRefresh,
377 LPCTSTR lpTypeFilter )
379 m_processId = pID;
381 // Set the filter
382 SetFilter( lpTypeFilter, bRefresh );
385 SystemHandleInformation::~SystemHandleInformation()
389 BOOL SystemHandleInformation::SetFilter( LPCTSTR lpTypeFilter, BOOL bRefresh )
391 // Set the filter ( default = all objects )
392 m_strTypeFilter = lpTypeFilter == NULL ? _T("") : lpTypeFilter;
394 return bRefresh ? Refresh() : TRUE;
397 const string& SystemHandleInformation::GetFilter()
399 return m_strTypeFilter;
402 BOOL SystemHandleInformation::IsSupportedHandle( SYSTEM_HANDLE& handle )
404 //Here you can filter the handles you don't want in the Handle list
406 // Windows 2000 supports everything :)
407 if ( dwNTMajorVersion >= 5 )
408 return TRUE;
410 //NT4 System process doesn't like if we bother his internal security :)
411 if ( handle.ProcessID == 2 && handle.HandleType == 16 )
412 return FALSE;
414 return TRUE;
417 BOOL SystemHandleInformation::Refresh()
419 DWORD size = 0x2000;
420 DWORD needed = 0;
421 DWORD i = 0;
422 BOOL ret = TRUE;
423 string strType;
425 m_HandleInfos.clear();
427 if ( !INtDll::NtDllStatus )
428 return FALSE;
430 // Allocate the memory for the buffer
431 SYSTEM_HANDLE_INFORMATION* pSysHandleInformation =
432 (SYSTEM_HANDLE_INFORMATION*)
433 VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE );
435 if ( pSysHandleInformation == NULL )
436 return FALSE;
438 // Query the needed buffer size for the objects ( system wide )
439 if ( INtDll::NtQuerySystemInformation( 16, pSysHandleInformation,
440 size, &needed ) != 0 )
442 if ( needed == 0 )
444 ret = FALSE;
445 goto cleanup;
448 // The size was not enough
449 VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
451 pSysHandleInformation = (SYSTEM_HANDLE_INFORMATION*)
452 VirtualAlloc( NULL, size = needed + 256,
453 MEM_COMMIT, PAGE_READWRITE );
456 if ( pSysHandleInformation == NULL )
457 return FALSE;
459 // Query the objects ( system wide )
460 if ( INtDll::NtQuerySystemInformation( 16, pSysHandleInformation,
461 size, NULL ) != 0 )
463 ret = FALSE;
464 goto cleanup;
467 // Iterating through the objects
468 for ( i = 0; i < pSysHandleInformation->Count; i++ )
470 if ( !IsSupportedHandle( pSysHandleInformation->Handles[i] ) )
471 continue;
473 // ProcessId filtering check
474 if ( pSysHandleInformation->Handles[i].ProcessID ==
475 m_processId || m_processId == (DWORD)-1 ) {
476 BOOL bAdd = FALSE;
478 if ( m_strTypeFilter == _T("") )
479 bAdd = TRUE;
480 else
482 // Type filtering
483 GetTypeToken( (HANDLE)pSysHandleInformation
484 ->Handles[i].HandleNumber,
485 strType,
486 pSysHandleInformation
487 ->Handles[i].ProcessID );
489 bAdd = strType == m_strTypeFilter;
492 // That's it. We found one.
493 if ( bAdd )
495 pSysHandleInformation->Handles[i].HandleType =
496 (WORD)(pSysHandleInformation
497 ->Handles[i].HandleType % 256);
499 m_HandleInfos.push_back( pSysHandleInformation
500 ->Handles[i] );
506 cleanup:
508 if ( pSysHandleInformation != NULL )
509 VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
511 return ret;
514 HANDLE SystemHandleInformation::OpenProcess( DWORD processId )
516 // Open the process for handle duplication
517 return ::OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
520 HANDLE SystemHandleInformation::DuplicateHandle( HANDLE hProcess,
521 HANDLE hRemote )
523 HANDLE hDup = NULL;
525 // Duplicate the remote handle for our process
526 ::DuplicateHandle( hProcess, hRemote, GetCurrentProcess(), &hDup,
527 0, FALSE, DUPLICATE_SAME_ACCESS );
529 return hDup;
532 //Information functions
533 BOOL SystemHandleInformation::GetTypeToken( HANDLE h, string& str,
534 DWORD processId )
536 ULONG size = 0x2000;
537 UCHAR* lpBuffer = NULL;
538 BOOL ret = FALSE;
540 HANDLE handle;
541 HANDLE hRemoteProcess = NULL;
542 BOOL remote = processId != GetCurrentProcessId();
544 if ( !NtDllStatus )
545 return FALSE;
547 if ( remote )
549 // Open the remote process
550 hRemoteProcess = OpenProcess( processId );
552 if ( hRemoteProcess == NULL )
553 return FALSE;
555 // Duplicate the handle
556 handle = DuplicateHandle( hRemoteProcess, h );
558 else
559 handle = h;
561 // Query the info size
562 INtDll::NtQueryObject( handle, 2, NULL, 0, &size );
564 lpBuffer = new UCHAR[size];
566 // Query the info size ( type )
567 if ( INtDll::NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 )
569 str = _T("");
570 SystemInfoUtils::LPCWSTR2string( (LPCWSTR)(lpBuffer+0x60),
571 str );
573 ret = TRUE;
576 if ( remote )
578 if ( hRemoteProcess != NULL )
579 CloseHandle( hRemoteProcess );
581 if ( handle != NULL )
582 CloseHandle( handle );
585 if ( lpBuffer != NULL )
586 delete [] lpBuffer;
588 return ret;
591 BOOL SystemHandleInformation::GetType( HANDLE h, WORD& type, DWORD processId )
593 string strType;
595 type = OB_TYPE_UNKNOWN;
597 if ( !GetTypeToken( h, strType, processId ) )
598 return FALSE;
600 return GetTypeFromTypeToken( strType.c_str(), type );
603 BOOL SystemHandleInformation::GetTypeFromTypeToken( LPCTSTR typeToken,
604 WORD& type )
606 const WORD count = 27;
607 string constStrTypes[count] = {
608 _T(""), _T(""), _T("Directory"), _T("SymbolicLink"),
609 _T("Token"), _T("Process"), _T("Thread"), _T("Unknown7"),
610 _T("Event"), _T("EventPair"), _T("Mutant"), _T("Unknown11"),
611 _T("Semaphore"), _T("Timer"), _T("Profile"),
612 _T("WindowStation"), _T("Desktop"), _T("Section"), _T("Key"),
613 _T("Port"), _T("WaitablePort"), _T("Unknown21"),
614 _T("Unknown22"), _T("Unknown23"), _T("Unknown24"),
615 _T("IoCompletion"), _T("File") };
617 type = OB_TYPE_UNKNOWN;
619 for ( WORD i = 1; i < count; i++ )
620 if ( constStrTypes[i] == typeToken )
622 type = i;
623 return TRUE;
626 return FALSE;
629 BOOL SystemHandleInformation::GetName( HANDLE handle, string& str, DWORD processId )
631 WORD type = 0;
633 if ( !GetType( handle, type, processId ) )
634 return FALSE;
636 return GetNameByType( handle, type, str, processId );
639 BOOL SystemHandleInformation::GetNameByType( HANDLE h, WORD type, string& str, DWORD processId )
641 ULONG size = 0x2000;
642 UCHAR* lpBuffer = NULL;
643 BOOL ret = FALSE;
645 HANDLE handle;
646 HANDLE hRemoteProcess = NULL;
647 BOOL remote = processId != GetCurrentProcessId();
648 DWORD dwId = 0;
650 if ( !NtDllStatus )
651 return FALSE;
653 if ( remote )
655 hRemoteProcess = OpenProcess( processId );
657 if ( hRemoteProcess == NULL )
658 return FALSE;
660 handle = DuplicateHandle( hRemoteProcess, h );
662 else
663 handle = h;
665 stringstream hex;
666 // let's be happy, handle is in our process space, so query the infos :)
667 switch( type )
669 case OB_TYPE_PROCESS:
670 GetProcessId( handle, dwId );
672 hex << "PID: 0x" << std::hex << dwId;
673 str = hex.str();
675 ret = TRUE;
676 goto cleanup;
677 break;
679 case OB_TYPE_THREAD:
680 GetThreadId( handle, dwId );
682 hex << "TID: 0x" << std::hex << dwId;
684 ret = TRUE;
685 goto cleanup;
686 break;
688 case OB_TYPE_FILE:
689 ret = GetFileName( handle, str );
691 // access denied :(
692 if ( ret && str == _T("") )
693 goto cleanup;
694 break;
698 INtDll::NtQueryObject ( handle, 1, NULL, 0, &size );
700 // let's try to use the default
701 if ( size == 0 )
702 size = 0x2000;
704 lpBuffer = new UCHAR[size];
706 if ( INtDll::NtQueryObject( handle, 1, lpBuffer, size, NULL ) == 0 )
708 SystemInfoUtils::Unicode2string( (UNICODE_STRING*)lpBuffer, str );
709 ret = TRUE;
712 cleanup:
714 if ( remote )
716 if ( hRemoteProcess != NULL )
717 CloseHandle( hRemoteProcess );
719 if ( handle != NULL )
720 CloseHandle( handle );
723 if ( lpBuffer != NULL )
724 delete [] lpBuffer;
726 return ret;
729 //Thread related functions
730 BOOL SystemHandleInformation::GetThreadId( HANDLE h, DWORD& threadID, DWORD processId )
732 SystemThreadInformation::BASIC_THREAD_INFORMATION ti;
733 HANDLE handle;
734 HANDLE hRemoteProcess = NULL;
735 BOOL remote = processId != GetCurrentProcessId();
737 if ( !NtDllStatus )
738 return FALSE;
740 if ( remote )
742 // Open process
743 hRemoteProcess = OpenProcess( processId );
745 if ( hRemoteProcess == NULL )
746 return FALSE;
748 // Duplicate handle
749 handle = DuplicateHandle( hRemoteProcess, h );
751 else
752 handle = h;
754 // Get the thread information
755 if ( INtDll::NtQueryInformationThread( handle, 0, &ti, sizeof(ti), NULL ) == 0 )
756 threadID = ti.ThreadId;
758 if ( remote )
760 if ( hRemoteProcess != NULL )
761 CloseHandle( hRemoteProcess );
763 if ( handle != NULL )
764 CloseHandle( handle );
767 return TRUE;
770 //Process related functions
771 BOOL SystemHandleInformation::GetProcessPath( HANDLE h, string& strPath, DWORD remoteProcessId )
773 h; strPath; remoteProcessId;
775 stringstream number;
776 number << remoteProcessId;
777 strPath = number.str();
779 return TRUE;
782 BOOL SystemHandleInformation::GetProcessId( HANDLE h, DWORD& processId, DWORD remoteProcessId )
784 BOOL ret = FALSE;
785 HANDLE handle;
786 HANDLE hRemoteProcess = NULL;
787 BOOL remote = remoteProcessId != GetCurrentProcessId();
788 SystemProcessInformation::PROCESS_BASIC_INFORMATION pi;
790 ZeroMemory( &pi, sizeof(pi) );
791 processId = 0;
793 if ( !NtDllStatus )
794 return FALSE;
796 if ( remote )
798 // Open process
799 hRemoteProcess = OpenProcess( remoteProcessId );
801 if ( hRemoteProcess == NULL )
802 return FALSE;
804 // Duplicate handle
805 handle = DuplicateHandle( hRemoteProcess, h );
807 else
808 handle = h;
810 // Get the process information
811 if ( INtDll::NtQueryInformationProcess( handle, 0, &pi, sizeof(pi), NULL) == 0 )
813 processId = pi.UniqueProcessId;
814 ret = TRUE;
817 if ( remote )
819 if ( hRemoteProcess != NULL )
820 CloseHandle( hRemoteProcess );
822 if ( handle != NULL )
823 CloseHandle( handle );
826 return ret;
829 //File related functions
830 void SystemHandleInformation::GetFileNameThread( PVOID pParam )
832 // This thread function for getting the filename
833 // if access denied, we hang up in this function,
834 // so if it times out we just kill this thread
835 GetFileNameThreadParam* p = (GetFileNameThreadParam*)pParam;
837 UCHAR lpBuffer[0x1000];
838 DWORD iob[2];
840 p->rc = INtDll::NtQueryInformationFile( p->hFile, iob, lpBuffer, sizeof(lpBuffer), 9 );
842 if ( p->rc == 0 )
843 *p->pName = (const char *)lpBuffer;
846 BOOL SystemHandleInformation::GetFileName( HANDLE h, string& str, DWORD processId )
848 BOOL ret= FALSE;
849 HANDLE hThread = NULL;
850 GetFileNameThreadParam tp;
851 HANDLE handle;
852 HANDLE hRemoteProcess = NULL;
853 BOOL remote = processId != GetCurrentProcessId();
855 if ( !NtDllStatus )
856 return FALSE;
858 if ( remote )
860 // Open process
861 hRemoteProcess = OpenProcess( processId );
863 if ( hRemoteProcess == NULL )
864 return FALSE;
866 // Duplicate handle
867 handle = DuplicateHandle( hRemoteProcess, h );
869 else
870 handle = h;
872 tp.hFile = handle;
873 tp.pName = &str;
874 tp.rc = 0;
876 // Let's start the thread to get the file name
877 hThread = (HANDLE)_beginthread( GetFileNameThread, 0, &tp );
879 if ( hThread == NULL )
881 ret = FALSE;
882 goto cleanup;
885 // Wait for finishing the thread
886 if ( WaitForSingleObject( hThread, 100 ) == WAIT_TIMEOUT )
888 // Access denied
889 // Terminate the thread
890 TerminateThread( hThread, 0 );
892 str = _T("");
894 ret = TRUE;
896 else
897 ret = ( tp.rc == 0 );
899 cleanup:
901 if ( remote )
903 if ( hRemoteProcess != NULL )
904 CloseHandle( hRemoteProcess );
906 if ( handle != NULL )
907 CloseHandle( handle );
910 return ret;
913 //////////////////////////////////////////////////////////////////////////////////////
915 // SystemModuleInformation
917 //////////////////////////////////////////////////////////////////////////////////////
919 SystemModuleInformation::SystemModuleInformation( DWORD pID, BOOL bRefresh )
921 m_processId = pID;
923 if ( bRefresh )
924 Refresh();
927 void SystemModuleInformation::GetModuleListForProcess( DWORD processID )
929 DWORD i = 0;
930 DWORD cbNeeded = 0;
931 HMODULE* hModules = NULL;
932 MODULE_INFO moduleInfo;
934 // Open process to read to query the module list
935 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
937 if ( hProcess == NULL )
938 goto cleanup;
940 //Get the number of modules
941 if ( !(*m_EnumProcessModules)( hProcess, NULL, 0, &cbNeeded ) )
942 goto cleanup;
944 hModules = new HMODULE[ cbNeeded / sizeof( HMODULE ) ];
946 //Get module handles
947 if ( !(*m_EnumProcessModules)( hProcess, hModules, cbNeeded, &cbNeeded ) )
948 goto cleanup;
950 for ( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ )
952 moduleInfo.ProcessId = processID;
953 moduleInfo.Handle = hModules[i];
955 //Get module full paths
956 if ( (*m_GetModuleFileNameEx)( hProcess, hModules[i], moduleInfo.FullPath, _MAX_PATH ) )
957 m_ModuleInfos.push_back( moduleInfo );
960 cleanup:
961 if ( hModules != NULL )
962 delete [] hModules;
964 if ( hProcess != NULL )
965 CloseHandle( hProcess );
968 BOOL SystemModuleInformation::Refresh()
970 BOOL rc = FALSE;
971 m_EnumProcessModules = NULL;
972 m_GetModuleFileNameEx = NULL;
974 m_ModuleInfos.clear();
976 //Load Psapi.dll
977 HINSTANCE hDll = LoadLibrary( "PSAPI.DLL" );
979 if ( hDll == NULL )
981 rc = FALSE;
982 goto cleanup;
985 //Get Psapi.dll functions
986 m_EnumProcessModules = (PEnumProcessModules)GetProcAddress( hDll, "EnumProcessModules" );
988 m_GetModuleFileNameEx = (PGetModuleFileNameEx)GetProcAddress( hDll,
989 #ifdef UNICODE
990 "GetModuleFileNameExW" );
991 #else
992 "GetModuleFileNameExA" );
993 #endif
995 if ( m_GetModuleFileNameEx == NULL || m_EnumProcessModules == NULL )
997 rc = FALSE;
998 goto cleanup;
1001 // Everey process or just a particular one
1002 if ( m_processId != -1 )
1003 // For a particular one
1004 GetModuleListForProcess( m_processId );
1005 else
1007 // Get teh process list
1008 DWORD pID;
1009 SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p = NULL;
1010 SystemProcessInformation pi( TRUE );
1012 if ( pi.m_ProcessInfos.empty() )
1014 rc = FALSE;
1015 goto cleanup;
1018 // Iterating through the processes and get the module list
1019 for (map<DWORD, SystemProcessInformation::SYSTEM_PROCESS_INFORMATION *>::iterator iter = pi.m_ProcessInfos.begin(); iter != pi.m_ProcessInfos.end(); iter++) {
1020 pID = iter->first;
1021 p = iter->second;
1022 GetModuleListForProcess( pID );
1026 rc = TRUE;
1028 cleanup:
1030 //Free psapi.dll
1031 if ( hDll != NULL )
1032 FreeLibrary( hDll );
1034 return rc;
1037 //////////////////////////////////////////////////////////////////////////////////////
1039 // SystemWindowInformation
1041 //////////////////////////////////////////////////////////////////////////////////////
1043 SystemWindowInformation::SystemWindowInformation( DWORD pID, BOOL bRefresh )
1045 m_processId = pID;
1047 if ( bRefresh )
1048 Refresh();
1051 BOOL SystemWindowInformation::Refresh()
1053 m_WindowInfos.clear();
1055 // Enumerating the windows
1056 EnumWindows( EnumerateWindows, (LPARAM)this );
1058 return TRUE;
1061 BOOL CALLBACK SystemWindowInformation::EnumerateWindows( HWND hwnd, LPARAM lParam )
1063 SystemWindowInformation* _this = (SystemWindowInformation*)lParam;
1064 WINDOW_INFO wi;
1066 wi.hWnd = hwnd;
1067 GetWindowThreadProcessId(hwnd, &wi.ProcessId ) ;
1069 // Filtering by process ID
1070 if ( _this->m_processId == -1 || _this->m_processId == wi.ProcessId )
1072 GetWindowText( hwnd, wi.Caption, MaxCaptionSize );
1074 // That is we are looking for
1075 if ( GetLastError() == 0 )
1076 _this->m_WindowInfos.push_back( wi );
1079 return TRUE;