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

  1. ///////////////////////////////////////////////////////////////////////
  2. // Microsoft Windows //
  3. // Copyright(c) Microsoft Corp., 1998 //
  4. ///////////////////////////////////////////////////////////////////////
  5. //
  6. // processs ID related routines
  7. //
  8. #include "inetcplp.h"
  9. #include <tchar.h>
  10. #include "psapi.h"
  11. #include "tlhelp32.h"
  12. #include "process.h"
  13. CProcessInfo::CProcessInfo()
  14. {
  15. _fNT = IsOS(OS_NT4ORGREATER);
  16. // init w95 func pointers
  17. _lpfnCreateToolhelp32Snapshot = NULL;
  18. _lpfnProcess32First = NULL;
  19. _lpfnProcess32Next = NULL;
  20. // init NT func pointers
  21. _hPsapiDLL = NULL;
  22. _lpfnEnumProcesses = NULL;
  23. _lpfnGetModuleBaseName = NULL;
  24. // process info array
  25. _pProcInfoArray = NULL;
  26. _nAlloced = 0;
  27. _iProcInfoCount = 0;
  28. }
  29. CProcessInfo::~CProcessInfo()
  30. {
  31. if(_pProcInfoArray)
  32. LocalFree(_pProcInfoArray);
  33. if(_hPsapiDLL)
  34. FreeLibrary (_hPsapiDLL);
  35. }
  36. #define ALLOC_STEP 50
  37. HRESULT CProcessInfo::MakeRoomForInfoArray(int n)
  38. {
  39. HRESULT hr = S_OK;
  40. if (n > _nAlloced)
  41. {
  42. PROCESSINFO *p;
  43. int nSaved = _nAlloced;
  44. while(n > _nAlloced)
  45. _nAlloced += ALLOC_STEP;
  46. if (!_pProcInfoArray)
  47. {
  48. p = (PROCESSINFO *)LocalAlloc(LPTR, sizeof(PROCESSINFO)*_nAlloced);
  49. }
  50. else
  51. {
  52. p = (PROCESSINFO *)LocalReAlloc(_pProcInfoArray,
  53. sizeof(PROCESSINFO)*_nAlloced,
  54. LMEM_MOVEABLE|LMEM_ZEROINIT);
  55. }
  56. if (p)
  57. _pProcInfoArray = p;
  58. else
  59. {
  60. hr = E_FAIL;
  61. _nAlloced = nSaved;
  62. }
  63. }
  64. return hr;
  65. }
  66. HRESULT CProcessInfo::EnsureProcessInfo()
  67. {
  68. HRESULT hr = S_OK;
  69. if (!_pProcInfoArray)
  70. {
  71. if (_fNT)
  72. {
  73. NTCreateProcessList();
  74. }
  75. else
  76. {
  77. W95CreateProcessList();
  78. }
  79. }
  80. return hr;
  81. }
  82. HRESULT CProcessInfo::GetExeNameFromPID(DWORD dwPID, LPTSTR szFile, int cchFile)
  83. {
  84. HRESULT hr;
  85. hr = EnsureProcessInfo();
  86. if (hr == S_OK)
  87. {
  88. for (int i = 0; i < _iProcInfoCount; i++)
  89. {
  90. if (_pProcInfoArray[i].dwPID == dwPID)
  91. {
  92. _tcsncpy(szFile, _pProcInfoArray[i].szExeName, cchFile);
  93. break;
  94. }
  95. }
  96. }
  97. return hr;
  98. }
  99. HRESULT CProcessInfo::NTCreateProcessList()
  100. // Testing routine to see if we can get Process IDs.
  101. {
  102. HRESULT hr = E_FAIL;
  103. hr = NTInitPsapi();
  104. if (hr == S_OK)
  105. {
  106. UINT iIndex;
  107. DWORD aProcesses[100], cbNeeded;
  108. if (_lpfnEnumProcesses((DWORD * )aProcesses, sizeof(aProcesses), (DWORD *)&cbNeeded))
  109. {
  110. // Calculate how many process IDs were returned
  111. DWORD cProcesses = cbNeeded / sizeof(DWORD);
  112. hr = MakeRoomForInfoArray(cProcesses);
  113. if (S_OK == hr)
  114. {
  115. // Spit out the information for each ID
  116. for ( iIndex = 0; iIndex < cProcesses; iIndex++ )
  117. {
  118. hr = NTFillProcessList(aProcesses[iIndex], iIndex);
  119. }
  120. if (hr == S_OK)
  121. _iProcInfoCount = iIndex;
  122. }
  123. }
  124. }
  125. return hr;
  126. }
  127. HRESULT CProcessInfo::NTInitPsapi()
  128. {
  129. HRESULT hr;
  130. // First, load the NT specific library, PSAPI.DLL.
  131. if (!_hPsapiDLL)
  132. _hPsapiDLL = LoadLibrary(TEXT("PSAPI.DLL"));
  133. if (_hPsapiDLL)
  134. {
  135. _lpfnEnumProcesses
  136. = (LPFNENUMPROCESSES)GetProcAddress(_hPsapiDLL, "EnumProcesses");
  137. _lpfnGetModuleBaseName
  138. = (LPFNGETMODULEBASENAMEW)GetProcAddress(_hPsapiDLL, "GetModuleBaseNameW");
  139. }
  140. Assert(_lpfnEnumProcesses && _lpfnGetModuleBaseName);
  141. hr = (_lpfnEnumProcesses
  142. && _lpfnGetModuleBaseName) ? S_OK : E_FAIL;
  143. return hr;
  144. }
  145. HRESULT CProcessInfo::NTFillProcessList(DWORD dwProcessID, int iIndex)
  146. {
  147. HRESULT hr = E_FAIL;
  148. TCHAR szProcessName[MAX_PATH] = TEXT("unknown");
  149. int i = -1;
  150. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID );
  151. if ( hProcess )
  152. {
  153. DWORD dw = _lpfnGetModuleBaseName( hProcess, NULL, szProcessName, sizeof(szProcessName) );
  154. if (dw > 0)
  155. hr = S_OK;
  156. CloseHandle (hProcess);
  157. }
  158. if (hr == S_OK)
  159. {
  160. // Add PID and associated .EXE file info to list...
  161. _pProcInfoArray[iIndex].dwPID = dwProcessID;
  162. _tcsncpy (_pProcInfoArray[iIndex].szExeName, szProcessName,
  163. ARRAYSIZE(_pProcInfoArray[iIndex].szExeName));
  164. }
  165. return hr;
  166. }
  167. HRESULT CProcessInfo::W95CreateProcessList()
  168. {
  169. HRESULT hr = E_FAIL;
  170. if (S_OK == W95InitToolhelp32())
  171. {
  172. hr = W95FillProcessList();
  173. }
  174. return (hr);
  175. }
  176. HRESULT CProcessInfo::W95InitToolhelp32()
  177. // Win95 specific, sets up the things we need to get the process IDs.
  178. {
  179. HRESULT hr = E_FAIL;
  180. HMODULE hKernel = NULL;
  181. // Obtain a module handle to KERNEL so that we can get the addresses of
  182. // the 32-bit Toolhelp functions we need.
  183. hKernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
  184. if (hKernel)
  185. {
  186. _lpfnCreateToolhelp32Snapshot =
  187. (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");
  188. _lpfnProcess32First = (PROCESSWALK)GetProcAddress(hKernel, "Process32First");
  189. _lpfnProcess32Next = (PROCESSWALK)GetProcAddress(hKernel, "Process32Next");
  190. // All of our addresses must be non-NULL in order for us to be
  191. // successful. If even one of these addresses is NULL, then we
  192. // must fail because we won't be able to walk one of the lists
  193. // we need to.
  194. if (_lpfnProcess32First && _lpfnProcess32Next && _lpfnCreateToolhelp32Snapshot)
  195. hr = S_OK;
  196. }
  197. return (hr);
  198. }
  199. #ifdef UNICODE
  200. #undef PROCESSENTRY32
  201. #endif // !UNICODE
  202. HRESULT CProcessInfo::W95FillProcessList()
  203. // Fills in the array of process info, and also set the count of the items
  204. {
  205. HRESULT hr = E_FAIL;
  206. HANDLE hProcessSnap = NULL;
  207. PROCESSENTRY32 pe32 = {0};
  208. // Take a snapshot of all processes currently in the system.
  209. hProcessSnap = _lpfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  210. if (hProcessSnap == (HANDLE)-1)
  211. return hr;
  212. // Size of the PROCESSENTRY32 structure must be filled out before use.
  213. pe32.dwSize = sizeof(PROCESSENTRY32);
  214. // Walk the snapshot of processes and for each process, get information
  215. // to display.
  216. if (_lpfnProcess32First(hProcessSnap, &pe32))
  217. {
  218. int iIndex = 0;
  219. do // Add PID and associated .EXE file info to list...
  220. {
  221. hr = MakeRoomForInfoArray(iIndex+1);
  222. if (hr != S_OK)
  223. break;
  224. _pProcInfoArray[iIndex].dwPID = pe32.th32ProcessID;
  225. LPSTR pszFile = PathFindFileNameA(pe32.szExeFile);
  226. if (pszFile)
  227. {
  228. SHAnsiToUnicode( pszFile, _pProcInfoArray[iIndex].szExeName,
  229. ARRAYSIZE(_pProcInfoArray[iIndex].szExeName));
  230. }
  231. iIndex++;
  232. }
  233. while (_lpfnProcess32Next(hProcessSnap, &pe32));
  234. _iProcInfoCount = iIndex; // takes care of the last failure
  235. hr = S_OK;
  236. }
  237. CloseHandle (hProcessSnap);
  238. return hr;
  239. }