Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

287 lines
7.3 KiB

///////////////////////////////////////////////////////////////////////
// Microsoft Windows //
// Copyright(c) Microsoft Corp., 1998 //
///////////////////////////////////////////////////////////////////////
//
// processs ID related routines
//
#include "inetcplp.h"
#include <tchar.h>
#include "psapi.h"
#include "tlhelp32.h"
#include "process.h"
CProcessInfo::CProcessInfo()
{
_fNT = IsOS(OS_NT4ORGREATER);
// init w95 func pointers
_lpfnCreateToolhelp32Snapshot = NULL;
_lpfnProcess32First = NULL;
_lpfnProcess32Next = NULL;
// init NT func pointers
_hPsapiDLL = NULL;
_lpfnEnumProcesses = NULL;
_lpfnGetModuleBaseName = NULL;
// process info array
_pProcInfoArray = NULL;
_nAlloced = 0;
_iProcInfoCount = 0;
}
CProcessInfo::~CProcessInfo()
{
if(_pProcInfoArray)
LocalFree(_pProcInfoArray);
if(_hPsapiDLL)
FreeLibrary (_hPsapiDLL);
}
#define ALLOC_STEP 50
HRESULT CProcessInfo::MakeRoomForInfoArray(int n)
{
HRESULT hr = S_OK;
if (n > _nAlloced)
{
PROCESSINFO *p;
int nSaved = _nAlloced;
while(n > _nAlloced)
_nAlloced += ALLOC_STEP;
if (!_pProcInfoArray)
{
p = (PROCESSINFO *)LocalAlloc(LPTR, sizeof(PROCESSINFO)*_nAlloced);
}
else
{
p = (PROCESSINFO *)LocalReAlloc(_pProcInfoArray,
sizeof(PROCESSINFO)*_nAlloced,
LMEM_MOVEABLE|LMEM_ZEROINIT);
}
if (p)
_pProcInfoArray = p;
else
{
hr = E_FAIL;
_nAlloced = nSaved;
}
}
return hr;
}
HRESULT CProcessInfo::EnsureProcessInfo()
{
HRESULT hr = S_OK;
if (!_pProcInfoArray)
{
if (_fNT)
{
NTCreateProcessList();
}
else
{
W95CreateProcessList();
}
}
return hr;
}
HRESULT CProcessInfo::GetExeNameFromPID(DWORD dwPID, LPTSTR szFile, int cchFile)
{
HRESULT hr;
hr = EnsureProcessInfo();
if (hr == S_OK)
{
for (int i = 0; i < _iProcInfoCount; i++)
{
if (_pProcInfoArray[i].dwPID == dwPID)
{
_tcsncpy(szFile, _pProcInfoArray[i].szExeName, cchFile);
break;
}
}
}
return hr;
}
HRESULT CProcessInfo::NTCreateProcessList()
// Testing routine to see if we can get Process IDs.
{
HRESULT hr = E_FAIL;
hr = NTInitPsapi();
if (hr == S_OK)
{
UINT iIndex;
DWORD aProcesses[100], cbNeeded;
if (_lpfnEnumProcesses((DWORD * )aProcesses, sizeof(aProcesses), (DWORD *)&cbNeeded))
{
// Calculate how many process IDs were returned
DWORD cProcesses = cbNeeded / sizeof(DWORD);
hr = MakeRoomForInfoArray(cProcesses);
if (S_OK == hr)
{
// Spit out the information for each ID
for ( iIndex = 0; iIndex < cProcesses; iIndex++ )
{
hr = NTFillProcessList(aProcesses[iIndex], iIndex);
}
if (hr == S_OK)
_iProcInfoCount = iIndex;
}
}
}
return hr;
}
HRESULT CProcessInfo::NTInitPsapi()
{
HRESULT hr;
// First, load the NT specific library, PSAPI.DLL.
if (!_hPsapiDLL)
_hPsapiDLL = LoadLibrary(TEXT("PSAPI.DLL"));
if (_hPsapiDLL)
{
_lpfnEnumProcesses
= (LPFNENUMPROCESSES)GetProcAddress(_hPsapiDLL, "EnumProcesses");
_lpfnGetModuleBaseName
= (LPFNGETMODULEBASENAMEW)GetProcAddress(_hPsapiDLL, "GetModuleBaseNameW");
}
Assert(_lpfnEnumProcesses && _lpfnGetModuleBaseName);
hr = (_lpfnEnumProcesses
&& _lpfnGetModuleBaseName) ? S_OK : E_FAIL;
return hr;
}
HRESULT CProcessInfo::NTFillProcessList(DWORD dwProcessID, int iIndex)
{
HRESULT hr = E_FAIL;
TCHAR szProcessName[MAX_PATH] = TEXT("unknown");
int i = -1;
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID );
if ( hProcess )
{
DWORD dw = _lpfnGetModuleBaseName( hProcess, NULL, szProcessName, sizeof(szProcessName) );
if (dw > 0)
hr = S_OK;
CloseHandle (hProcess);
}
if (hr == S_OK)
{
// Add PID and associated .EXE file info to list...
_pProcInfoArray[iIndex].dwPID = dwProcessID;
_tcsncpy (_pProcInfoArray[iIndex].szExeName, szProcessName,
ARRAYSIZE(_pProcInfoArray[iIndex].szExeName));
}
return hr;
}
HRESULT CProcessInfo::W95CreateProcessList()
{
HRESULT hr = E_FAIL;
if (S_OK == W95InitToolhelp32())
{
hr = W95FillProcessList();
}
return (hr);
}
HRESULT CProcessInfo::W95InitToolhelp32()
// Win95 specific, sets up the things we need to get the process IDs.
{
HRESULT hr = E_FAIL;
HMODULE hKernel = NULL;
// Obtain a module handle to KERNEL so that we can get the addresses of
// the 32-bit Toolhelp functions we need.
hKernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
if (hKernel)
{
_lpfnCreateToolhelp32Snapshot =
(CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");
_lpfnProcess32First = (PROCESSWALK)GetProcAddress(hKernel, "Process32First");
_lpfnProcess32Next = (PROCESSWALK)GetProcAddress(hKernel, "Process32Next");
// All of our addresses must be non-NULL in order for us to be
// successful. If even one of these addresses is NULL, then we
// must fail because we won't be able to walk one of the lists
// we need to.
if (_lpfnProcess32First && _lpfnProcess32Next && _lpfnCreateToolhelp32Snapshot)
hr = S_OK;
}
return (hr);
}
#ifdef UNICODE
#undef PROCESSENTRY32
#endif // !UNICODE
HRESULT CProcessInfo::W95FillProcessList()
// Fills in the array of process info, and also set the count of the items
{
HRESULT hr = E_FAIL;
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
// Take a snapshot of all processes currently in the system.
hProcessSnap = _lpfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == (HANDLE)-1)
return hr;
// Size of the PROCESSENTRY32 structure must be filled out before use.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of processes and for each process, get information
// to display.
if (_lpfnProcess32First(hProcessSnap, &pe32))
{
int iIndex = 0;
do // Add PID and associated .EXE file info to list...
{
hr = MakeRoomForInfoArray(iIndex+1);
if (hr != S_OK)
break;
_pProcInfoArray[iIndex].dwPID = pe32.th32ProcessID;
LPSTR pszFile = PathFindFileNameA(pe32.szExeFile);
if (pszFile)
{
SHAnsiToUnicode( pszFile, _pProcInfoArray[iIndex].szExeName,
ARRAYSIZE(_pProcInfoArray[iIndex].szExeName));
}
iIndex++;
}
while (_lpfnProcess32Next(hProcessSnap, &pe32));
_iProcInfoCount = iIndex; // takes care of the last failure
hr = S_OK;
}
CloseHandle (hProcessSnap);
return hr;
}