Leaked source code of windows server 2003
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.

456 lines
13 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. // File: MemStats.cpp
  3. //
  4. // Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Purpose:
  7. // MemStats.cpp: Helper functions that get's the system memory info.
  8. // Borrowed from EricI's memstats app.
  9. //
  10. // History:
  11. // 03/21/01 DennisCh Created
  12. //
  13. //////////////////////////////////////////////////////////////////////
  14. //////////////////////////////////////////////////////////////////////
  15. // Includes
  16. //////////////////////////////////////////////////////////////////////
  17. //
  18. // WIN32 headers
  19. //
  20. //
  21. // Project headers
  22. //
  23. #include "MemStats.h"
  24. #include "NetworkTools.h"
  25. //////////////////////////////////////////////////////////////////////
  26. //
  27. // Globals and statics
  28. //
  29. //////////////////////////////////////////////////////////////////////
  30. BOOL (WINAPI *g_lpfnOpenProcessToken)(HANDLE,DWORD,PHANDLE);
  31. BOOL (WINAPI *g_lpfnLookupPrivilegeValueA)(LPCSTR,LPCSTR,PLUID);
  32. BOOL (WINAPI *g_lpfnAdjustTokenPrivileges)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
  33. PDH_STATUS (WINAPI *g_lpfnPdhOpenQuery)(LPCSTR, DWORD_PTR, HQUERY *);
  34. PDH_STATUS (WINAPI *g_lpfnPdhAddCounter)(HQUERY, LPCSTR, DWORD_PTR, HCOUNTER *);
  35. PDH_STATUS (WINAPI *g_lpfnPdhCollectQueryData)(HQUERY);
  36. PDH_STATUS (WINAPI *g_lpfnPdhGetFormattedCounterValue)(HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE);
  37. PDH_STATUS (WINAPI *g_lpfnPdhRemoveCounter)(HCOUNTER);
  38. PDH_STATUS (WINAPI *g_lpfnPdhCloseQuery)(HQUERY);
  39. ////////////////////////////////////////////////////////////
  40. // Function: InitPdhLibrary()
  41. //
  42. // Purpose:
  43. // Loads and returns a pointer to the PDH module.
  44. //
  45. ////////////////////////////////////////////////////////////
  46. BOOL
  47. InitPdhLibrary(
  48. HMODULE *phPdhLib // [OUT] Pointer to the PDH.DLL module.
  49. )
  50. {
  51. BOOL bRet = FALSE;
  52. *phPdhLib = LoadLibraryA("pdh.dll");
  53. if(!*phPdhLib)
  54. {
  55. goto exit;
  56. }
  57. if(!(g_lpfnPdhOpenQuery = (PDH_STATUS (WINAPI *)(LPCSTR, DWORD_PTR, HQUERY *))GetProcAddress(*phPdhLib,"PdhOpenQueryA") ))
  58. {
  59. goto exit;
  60. }
  61. if(!(g_lpfnPdhAddCounter = (PDH_STATUS (WINAPI *)(HQUERY, LPCSTR, DWORD_PTR, HCOUNTER *))GetProcAddress(*phPdhLib,"PdhAddCounterA") ))
  62. {
  63. goto exit;
  64. }
  65. if(!(g_lpfnPdhCollectQueryData = (PDH_STATUS (WINAPI *)(HQUERY))GetProcAddress(*phPdhLib,"PdhCollectQueryData") ))
  66. {
  67. goto exit;
  68. }
  69. if(!(g_lpfnPdhGetFormattedCounterValue = (PDH_STATUS (WINAPI *)(HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE))GetProcAddress(*phPdhLib,"PdhGetFormattedCounterValue") ))
  70. {
  71. goto exit;
  72. }
  73. if(!(g_lpfnPdhRemoveCounter = (PDH_STATUS (WINAPI *)(HCOUNTER))GetProcAddress(*phPdhLib,"PdhRemoveCounter") ))
  74. {
  75. goto exit;
  76. }
  77. if(!(g_lpfnPdhCloseQuery = (PDH_STATUS (WINAPI *)(HQUERY))GetProcAddress(*phPdhLib,"PdhCloseQuery") ))
  78. {
  79. goto exit;
  80. }
  81. bRet = TRUE;
  82. exit:
  83. return bRet;
  84. }
  85. ////////////////////////////////////////////////////////////
  86. // Function: GetProcCntrs(PROC_CNTRS, INT, CHAR)
  87. //
  88. // Purpose:
  89. // Gets and returns the memory info for a given process.
  90. //
  91. ////////////////////////////////////////////////////////////
  92. BOOL
  93. GetProcCntrs(
  94. PROC_CNTRS *pProcCntrs, // [OUT] process memory counters
  95. INT nIndex, // [IN] The index of the process if there's more than one.
  96. CHAR *szProcess // [IN] Name of the process. ex "iexplore", "explorer"
  97. )
  98. {
  99. BOOL bRet = FALSE;
  100. INT n;
  101. HQUERY hQuery = 0;
  102. HCOUNTER aryHCounter [PROCCOUNTERS] = {0};
  103. PDH_FMT_COUNTERVALUE cntVal;
  104. CHAR myProcessCntrs[PROCCOUNTERS][1024];
  105. DWORD dwPathSize = MAX_PATH;
  106. sprintf(myProcessCntrs[0],"\\Process(%s#%d)\\ID Process",szProcess,nIndex);
  107. sprintf(myProcessCntrs[1],"\\Process(%s#%d)\\Private bytes",szProcess,nIndex);
  108. sprintf(myProcessCntrs[2],"\\Process(%s#%d)\\Handle count",szProcess,nIndex);
  109. sprintf(myProcessCntrs[3],"\\Process(%s#%d)\\Thread count",szProcess,nIndex);
  110. if(!(ERROR_SUCCESS == g_lpfnPdhOpenQuery (0, 0, &hQuery)))
  111. goto exit;
  112. for (n = 0; n < PROCCOUNTERS; n++)
  113. {
  114. if(!(ERROR_SUCCESS == g_lpfnPdhAddCounter (hQuery, myProcessCntrs[n], 0, &aryHCounter[n])))
  115. goto exit;
  116. }
  117. if(!(ERROR_SUCCESS == g_lpfnPdhCollectQueryData(hQuery)))
  118. goto exit;
  119. for (n=0; n < PROCCOUNTERS; n++)
  120. {
  121. if(!(ERROR_SUCCESS == g_lpfnPdhGetFormattedCounterValue (aryHCounter[n],PDH_FMT_LONG,0,&cntVal)))
  122. goto exit;
  123. *((ULONG*)pProcCntrs+n) = cntVal.longValue;
  124. }
  125. bRet = TRUE;
  126. exit:
  127. for(n=0;n<PROCCOUNTERS;n++)
  128. if(aryHCounter[n])
  129. g_lpfnPdhRemoveCounter(aryHCounter[n]);
  130. if(hQuery)
  131. g_lpfnPdhCloseQuery(hQuery);
  132. return bRet;
  133. }
  134. ////////////////////////////////////////////////////////////
  135. // Function: GetInfoForPID(PROC_CNTRS, ULONG, CHAR)
  136. //
  137. // Purpose:
  138. // Gets and returns the memory info for a given process.
  139. // We do this by going through every process with the same
  140. // name and comparing the PIDs.
  141. //
  142. ////////////////////////////////////////////////////////////
  143. BOOL
  144. GetInfoForPID(
  145. PROC_CNTRS *pc, // [OUT] Process memory counters for the PID
  146. ULONG lPID, // [IN] PID for the process to query
  147. CHAR *szProcess // [IN] Process name of the PID to query. ex. "explore", "iexplore". Don't include the extension
  148. )
  149. {
  150. BOOL bRet = TRUE;
  151. INT n = 0;
  152. while(bRet)
  153. {
  154. bRet = GetProcCntrs(pc,n,szProcess);
  155. if(lPID == pc->lPID)
  156. break;
  157. n++;
  158. }
  159. return bRet;
  160. }
  161. ////////////////////////////////////////////////////////////
  162. // Function: GetMemoryCounters(MEM_CNTRS)
  163. //
  164. // Purpose:
  165. // Gets and returns the memory info for the system.
  166. //
  167. ////////////////////////////////////////////////////////////
  168. BOOL
  169. GetMemoryCounters(
  170. MEM_CNTRS *pMemCounters // [OUT] Memory counters for the current machine
  171. )
  172. {
  173. BOOL bRet = FALSE;
  174. HQUERY hQuery = 0;
  175. HCOUNTER aryHCounter[MEMCOUNTERS] = {0};
  176. DWORD dwPathSize = MAX_PATH;
  177. int n;
  178. PDH_FMT_COUNTERVALUE cntVal;
  179. char szAryMemoryCntrs[MEMCOUNTERS][1024];
  180. sprintf(szAryMemoryCntrs[0],"\\Memory\\Committed Bytes");
  181. sprintf(szAryMemoryCntrs[1],"\\Memory\\Commit Limit");
  182. sprintf(szAryMemoryCntrs[2],"\\Memory\\System Code Total Bytes");
  183. sprintf(szAryMemoryCntrs[3],"\\Memory\\System Driver Total Bytes");
  184. sprintf(szAryMemoryCntrs[4],"\\Memory\\Pool Nonpaged Bytes");
  185. sprintf(szAryMemoryCntrs[5],"\\Memory\\Pool Paged Bytes");
  186. sprintf(szAryMemoryCntrs[6],"\\Memory\\Available Bytes");
  187. sprintf(szAryMemoryCntrs[7],"\\Memory\\Cache Bytes");
  188. sprintf(szAryMemoryCntrs[8],"\\Memory\\Free System Page Table Entries");
  189. if(!(ERROR_SUCCESS == g_lpfnPdhOpenQuery (0, 0, &hQuery)))
  190. goto exit;
  191. for (n = 0; n < MEMCOUNTERS; n++)
  192. {
  193. if(!(ERROR_SUCCESS == g_lpfnPdhAddCounter (hQuery, szAryMemoryCntrs[n], 0, &aryHCounter[n])))
  194. {
  195. goto exit;
  196. }
  197. }
  198. if(!(ERROR_SUCCESS == g_lpfnPdhCollectQueryData(hQuery)))
  199. goto exit;
  200. for (n=0; n < MEMCOUNTERS; n++)
  201. {
  202. if(!(ERROR_SUCCESS == g_lpfnPdhGetFormattedCounterValue (aryHCounter[n],PDH_FMT_LONG,0,&cntVal)))
  203. {
  204. goto exit;
  205. }
  206. *((ULONG*)pMemCounters+n) = cntVal.longValue;
  207. }
  208. bRet = TRUE;
  209. exit:
  210. for(n=0;n<MEMCOUNTERS;n++)
  211. {
  212. if(aryHCounter[n])
  213. {
  214. g_lpfnPdhRemoveCounter(aryHCounter[n]);
  215. }
  216. }
  217. if(hQuery)
  218. g_lpfnPdhCloseQuery(hQuery);
  219. return bRet;
  220. }
  221. ////////////////////////////////////////////////////////////
  222. // Function: GetAvailableSystemDriveSpace(long)
  223. //
  224. // Purpose:
  225. // Gets and returns the disk space available on the system drive.
  226. //
  227. ////////////////////////////////////////////////////////////
  228. BOOL
  229. GetAvailableSystemDriveSpace(
  230. long *lAvail // [OUT] Buffer containing the space on the system drive
  231. )
  232. {
  233. BOOL bRet = FALSE;
  234. char szSystemPath[MAX_PATH];
  235. ULARGE_INTEGER FreeBytesAvailable; // bytes available to caller
  236. ULARGE_INTEGER TotalNumberOfBytes; // bytes on disk
  237. ULARGE_INTEGER TotalNumberOfFreeBytes; // free bytes on disk
  238. int i;
  239. DWORD dwFoo = 0;
  240. if(!GetSystemDirectoryA(szSystemPath,sizeof(szSystemPath)))
  241. {
  242. goto exit;
  243. }
  244. //We only want the drive letter
  245. for(i=0; i<1+lstrlenA(szSystemPath); i++)
  246. {
  247. if(szSystemPath[i] == 0)
  248. {
  249. goto exit;
  250. }
  251. if(szSystemPath[i] == '\\')
  252. {
  253. szSystemPath[i+1] = 0;
  254. break;
  255. }
  256. }
  257. if(GetDiskFreeSpaceExA(szSystemPath,&FreeBytesAvailable,&TotalNumberOfBytes,&TotalNumberOfFreeBytes))
  258. {
  259. *lAvail = __int32(TotalNumberOfFreeBytes.QuadPart / 1024 / 1000);
  260. bRet = TRUE;
  261. }
  262. exit:
  263. return bRet;
  264. }
  265. ////////////////////////////////////////////////////////////
  266. // Function: MemStats__SendSystemMemoryLog(LPSTR, DWORD, DWORD)
  267. //
  268. // Purpose:
  269. // Sends a memory log to the Command Server.
  270. // Sends the stressInstance ID and client machine name as part of the POST request.
  271. //
  272. ////////////////////////////////////////////////////////////
  273. BOOL
  274. MemStats__SendSystemMemoryLog(
  275. LPSTR szExeName, // [IN] Name of the process. ex. "explorer", "iexplorer". No extension.
  276. DWORD dwPID, // [IN] PID for the above process
  277. DWORD dwStressInstanceID // [IN] The stress instanceID
  278. )
  279. {
  280. BOOL bRet = FALSE;
  281. HMODULE hPdhLib = NULL;
  282. MEM_CNTRS mc = {0};
  283. long lAvailDriveSpace = 0;
  284. DWORD dwPostDataSize = MAX_PATH*10;
  285. DWORD dwDataFieldSize = 100;
  286. LPSTR szPostData = new CHAR[dwPostDataSize];
  287. LPSTR szDataField = new CHAR[dwDataFieldSize];
  288. LPSTR szFileName = new CHAR[MAX_PATH];
  289. PROC_CNTRS pc;
  290. if(!InitPdhLibrary(&hPdhLib) || !szExeName)
  291. {
  292. goto exit;
  293. }
  294. // Remove the extension from the filename if there is one
  295. ZeroMemory(szFileName, MAX_PATH);
  296. strncpy(szFileName, szExeName, MAX_PATH);
  297. PathRemoveExtensionA(szFileName);
  298. ZeroMemory(szPostData, dwPostDataSize);
  299. ZeroMemory(szDataField, dwDataFieldSize);
  300. // *** !!! need this because NetworkTools__SendLog(...) sends szPost data as fieldname "LogText="
  301. // so we need an & to delimit memory info fields from "real" log text.
  302. strcat(szPostData, "&");
  303. // *************************
  304. // *************************
  305. // ** Get process info
  306. // **
  307. if (szFileName && GetInfoForPID(&pc, dwPID, szFileName))
  308. {
  309. sprintf(szDataField, FIELDNAME__STRESSEXE_HANDLECOUNT, pc.lHandles);
  310. strcat(szPostData, szDataField);
  311. strcat(szPostData, "&");
  312. sprintf(szDataField, FIELDNAME__STRESSEXE_THREADCOUNT, pc.lThreads);
  313. strcat(szPostData, szDataField);
  314. strcat(szPostData, "&");
  315. sprintf(szDataField, FIELDNAME__STRESSEXE_PRIVATEBYTES, pc.lPrivBytes);
  316. strcat(szPostData, szDataField);
  317. strcat(szPostData, "&");
  318. }
  319. // *************************
  320. // *************************
  321. // ** Get system memory info
  322. // **
  323. if (GetMemoryCounters(&mc))
  324. {
  325. sprintf(szDataField, FIELDNAME__MEMORY_COMMITTEDPAGEFILETOTAL, mc.lCommittedBytes/1024);
  326. strcat(szPostData, szDataField);
  327. strcat(szPostData, "&");
  328. sprintf(szDataField, FIELDNAME__MEMORY_AVAILABLEPAGEFILETOTAL, (mc.lCommitLimit - mc.lCommittedBytes)/1024);
  329. strcat(szPostData, szDataField);
  330. strcat(szPostData, "&");
  331. sprintf(szDataField, FIELDNAME__MEMORY_SYSTEMCODETOTAL, mc.lSystemCodeTotalBytes/1024);
  332. strcat(szPostData, szDataField);
  333. strcat(szPostData, "&");
  334. sprintf(szDataField, FIELDNAME__MEMORY_SYSTEMDRIVERTOTAL, mc.lSystemDriverTotalBytes/1024);
  335. strcat(szPostData, szDataField);
  336. strcat(szPostData, "&");
  337. sprintf(szDataField, FIELDNAME__MEMORY_NONPAGEDPOOLTOTAL, mc.lPoolNonpagedBytes/1024);
  338. strcat(szPostData, szDataField);
  339. strcat(szPostData, "&");
  340. sprintf(szDataField, FIELDNAME__MEMORY_PAGEDPOOLTOTAL, mc.lPoolPagedBytes/1024);
  341. strcat(szPostData, szDataField);
  342. strcat(szPostData, "&");
  343. sprintf(szDataField, FIELDNAME__MEMORY_PHYSICAL_MEMORY_AVAILABLE, mc.lAvailableBytes/1024);
  344. strcat(szPostData, szDataField);
  345. strcat(szPostData, "&");
  346. sprintf(szDataField, FIELDNAME__MEMORY_SYSTEMCACHETOTAL, mc.lCacheBytes/1024);
  347. strcat(szPostData, szDataField);
  348. strcat(szPostData, "&");
  349. sprintf(szDataField, FIELDNAME__MEMORY_FREESYSTEM_PAGETABLE_ENTRIES,mc.lFreeSystemPageTableEntries);
  350. strcat(szPostData, szDataField);
  351. strcat(szPostData, "&");
  352. }
  353. // *************************
  354. // *************************
  355. // ** Get disk space info
  356. // **
  357. if (GetAvailableSystemDriveSpace(&lAvailDriveSpace))
  358. {
  359. sprintf(szDataField, FIELDNAME__MEMORY_DISK_SPACE_AVAILABLE, lAvailDriveSpace);
  360. strcat(szPostData, szDataField);
  361. strcat(szPostData, "&");
  362. }
  363. NetworkTools__SendLog(FIELDNAME__LOGTYPE_MEMORY_INFORMATION, szPostData, NULL, dwStressInstanceID);
  364. exit:
  365. // FYI: Recent Whistler main build deadlocks in unload of the PDH library
  366. if(hPdhLib)
  367. {
  368. FreeLibrary(hPdhLib);
  369. }
  370. delete [] szPostData;
  371. delete [] szDataField;
  372. delete [] szFileName;
  373. return 0;
  374. }