systeminfo.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. #include "winutils.h"
  18. #include <psapi.h>
  19. #include <PowrProf.h>
  20. #include <pdh.h>
  21. #include <pdhmsg.h>
  22. #ifdef PSAPI_VERSION
  23. #undef PSAPI_VERSION
  24. #endif
  25. #define PSAPI_VERSION 1
  26. #pragma comment(lib, "psapi.lib")
  27. #pragma comment(lib, "Powrprof.lib")
  28. #pragma comment(lib, "pdh.lib")
  29. CONST PWSTR COUNTER_PATH_NET_READ_ALL = L"\\Network Interface(*)\\Bytes Received/Sec";
  30. CONST PWSTR COUNTER_PATH_NET_WRITE_ALL = L"\\Network Interface(*)\\Bytes Sent/Sec";
  31. CONST PWSTR COUNTER_PATH_DISK_READ_ALL = L"\\LogicalDisk(*)\\Disk Read Bytes/sec";
  32. CONST PWSTR COUNTER_PATH_DISK_WRITE_ALL = L"\\LogicalDisk(*)\\Disk Write Bytes/sec";
  33. typedef struct _PROCESSOR_POWER_INFORMATION {
  34. ULONG Number;
  35. ULONG MaxMhz;
  36. ULONG CurrentMhz;
  37. ULONG MhzLimit;
  38. ULONG MaxIdleState;
  39. ULONG CurrentIdleState;
  40. } PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
  41. //----------------------------------------------------------------------------
  42. // Function: SystemInfo
  43. //
  44. // Description:
  45. // Returns the resource information about the machine
  46. //
  47. // Returns:
  48. // EXIT_SUCCESS: On success
  49. // EXIT_FAILURE: otherwise
  50. int SystemInfo()
  51. {
  52. size_t vmemSize, vmemFree, memSize, memFree;
  53. PERFORMANCE_INFORMATION memInfo;
  54. SYSTEM_INFO sysInfo;
  55. FILETIME idleTimeFt, kernelTimeFt, userTimeFt;
  56. ULARGE_INTEGER idleTime, kernelTime, userTime;
  57. ULONGLONG cpuTimeMs;
  58. size_t size;
  59. LPBYTE pBuffer;
  60. PROCESSOR_POWER_INFORMATION const *ppi;
  61. ULONGLONG cpuFrequencyKhz;
  62. NTSTATUS status;
  63. LONGLONG diskRead, diskWrite, netRead, netWrite;
  64. ZeroMemory(&memInfo, sizeof(PERFORMANCE_INFORMATION));
  65. memInfo.cb = sizeof(PERFORMANCE_INFORMATION);
  66. if(!GetPerformanceInfo(&memInfo, sizeof(PERFORMANCE_INFORMATION)))
  67. {
  68. ReportErrorCode(L"GetPerformanceInfo", GetLastError());
  69. return EXIT_FAILURE;
  70. }
  71. vmemSize = memInfo.CommitLimit*memInfo.PageSize;
  72. vmemFree = vmemSize - memInfo.CommitTotal*memInfo.PageSize;
  73. memSize = memInfo.PhysicalTotal*memInfo.PageSize;
  74. memFree = memInfo.PhysicalAvailable*memInfo.PageSize;
  75. GetSystemInfo(&sysInfo);
  76. if(!GetSystemTimes(&idleTimeFt, &kernelTimeFt, &userTimeFt))
  77. {
  78. ReportErrorCode(L"GetSystemTimes", GetLastError());
  79. return EXIT_FAILURE;
  80. }
  81. idleTime.HighPart = idleTimeFt.dwHighDateTime;
  82. idleTime.LowPart = idleTimeFt.dwLowDateTime;
  83. kernelTime.HighPart = kernelTimeFt.dwHighDateTime;
  84. kernelTime.LowPart = kernelTimeFt.dwLowDateTime;
  85. userTime.HighPart = userTimeFt.dwHighDateTime;
  86. userTime.LowPart = userTimeFt.dwLowDateTime;
  87. cpuTimeMs = (kernelTime.QuadPart - idleTime.QuadPart + userTime.QuadPart)/10000;
  88. // allocate buffer to get info for each processor
  89. size = sysInfo.dwNumberOfProcessors * sizeof(PROCESSOR_POWER_INFORMATION);
  90. pBuffer = (BYTE*) LocalAlloc(LPTR, size);
  91. if(!pBuffer)
  92. {
  93. ReportErrorCode(L"LocalAlloc", GetLastError());
  94. return EXIT_FAILURE;
  95. }
  96. status = CallNtPowerInformation(ProcessorInformation, NULL, 0, pBuffer, (long)size);
  97. if(0 != status)
  98. {
  99. fwprintf_s(stderr, L"Error in CallNtPowerInformation. Err:%d\n", status);
  100. LocalFree(pBuffer);
  101. return EXIT_FAILURE;
  102. }
  103. ppi = (PROCESSOR_POWER_INFORMATION const *)pBuffer;
  104. cpuFrequencyKhz = ppi->MaxMhz*1000;
  105. LocalFree(pBuffer);
  106. status = GetDiskAndNetwork(&diskRead, &diskWrite, &netRead, &netWrite);
  107. if(0 != status)
  108. {
  109. fwprintf_s(stderr, L"Error in GetDiskAndNetwork. Err:%d\n", status);
  110. return EXIT_FAILURE;
  111. }
  112. fwprintf_s(stdout, L"%Iu,%Iu,%Iu,%Iu,%u,%I64u,%I64u,%I64d,%I64d,%I64d,%I64d\n", vmemSize, memSize,
  113. vmemFree, memFree, sysInfo.dwNumberOfProcessors, cpuFrequencyKhz, cpuTimeMs,
  114. diskRead, diskWrite, netRead, netWrite);
  115. return EXIT_SUCCESS;
  116. }
  117. void SystemInfoUsage()
  118. {
  119. fwprintf(stdout, L"\
  120. Usage: systeminfo\n\
  121. Prints machine information on stdout\n\
  122. Comma separated list of the following values.\n\
  123. VirtualMemorySize(bytes),PhysicalMemorySize(bytes),\n\
  124. FreeVirtualMemory(bytes),FreePhysicalMemory(bytes),\n\
  125. NumberOfProcessors,CpuFrequency(Khz),\n\
  126. CpuTime(MilliSec,Kernel+User),\n\
  127. DiskRead(bytes),DiskWrite(bytes),\n\
  128. NetworkRead(bytes),NetworkWrite(bytes)\n");
  129. }
  130. int GetDiskAndNetwork(LONGLONG* diskRead, LONGLONG* diskWrite, LONGLONG* netRead, LONGLONG* netWrite)
  131. {
  132. int ret = EXIT_SUCCESS;
  133. PDH_STATUS status = ERROR_SUCCESS;
  134. PDH_HQUERY hQuery = NULL;
  135. PDH_HCOUNTER hCounterNetRead = NULL;
  136. PDH_HCOUNTER hCounterNetWrite = NULL;
  137. PDH_HCOUNTER hCounterDiskRead = NULL;
  138. PDH_HCOUNTER hCounterDiskWrite = NULL;
  139. DWORD i;
  140. if(status = PdhOpenQuery(NULL, 0, &hQuery))
  141. {
  142. fwprintf_s(stderr, L"PdhOpenQuery failed with 0x%x.\n", status);
  143. ret = EXIT_FAILURE;
  144. goto cleanup;
  145. }
  146. // Add each one of the counters with wild cards
  147. if(status = PdhAddCounter(hQuery, COUNTER_PATH_NET_READ_ALL, 0, &hCounterNetRead))
  148. {
  149. fwprintf_s(stderr, L"PdhAddCounter %s failed with 0x%x.\n", COUNTER_PATH_NET_READ_ALL, status);
  150. ret = EXIT_FAILURE;
  151. goto cleanup;
  152. }
  153. if(status = PdhAddCounter(hQuery, COUNTER_PATH_NET_WRITE_ALL, 0, &hCounterNetWrite))
  154. {
  155. fwprintf_s(stderr, L"PdhAddCounter %s failed with 0x%x.\n", COUNTER_PATH_NET_WRITE_ALL, status);
  156. ret = EXIT_FAILURE;
  157. goto cleanup;
  158. }
  159. if(status = PdhAddCounter(hQuery, COUNTER_PATH_DISK_READ_ALL, 0, &hCounterDiskRead))
  160. {
  161. fwprintf_s(stderr, L"PdhAddCounter %s failed with 0x%x.\n", COUNTER_PATH_DISK_READ_ALL, status);
  162. ret = EXIT_FAILURE;
  163. goto cleanup;
  164. }
  165. if(status = PdhAddCounter(hQuery, COUNTER_PATH_DISK_WRITE_ALL, 0, &hCounterDiskWrite))
  166. {
  167. fwprintf_s(stderr, L"PdhAddCounter %s failed with 0x%x.\n", COUNTER_PATH_DISK_WRITE_ALL, status);
  168. ret = EXIT_FAILURE;
  169. goto cleanup;
  170. }
  171. if(status = PdhCollectQueryData(hQuery))
  172. {
  173. fwprintf_s(stderr, L"PdhCollectQueryData() failed with 0x%x.\n", status);
  174. ret = EXIT_FAILURE;
  175. goto cleanup;
  176. }
  177. // Read and aggregate counters
  178. status = ReadTotalCounter(hCounterNetRead, netRead);
  179. if(ERROR_SUCCESS != status)
  180. {
  181. fwprintf_s(stderr, L"ReadTotalCounter(Network Read): Error 0x%x.\n", status);
  182. ret = EXIT_FAILURE;
  183. }
  184. status = ReadTotalCounter(hCounterNetWrite, netWrite);
  185. if(ERROR_SUCCESS != status)
  186. {
  187. fwprintf_s(stderr, L"ReadTotalCounter(Network Write): Error 0x%x.\n", status);
  188. ret = EXIT_FAILURE;
  189. }
  190. status = ReadTotalCounter(hCounterDiskRead, diskRead);
  191. if(ERROR_SUCCESS != status)
  192. {
  193. fwprintf_s(stderr, L"ReadTotalCounter(Disk Read): Error 0x%x.\n", status);
  194. ret = EXIT_FAILURE;
  195. }
  196. status = ReadTotalCounter(hCounterDiskWrite, diskWrite);
  197. if(ERROR_SUCCESS != status)
  198. {
  199. fwprintf_s(stderr, L"ReadTotalCounter(Disk Write): Error 0x%x.\n", status);
  200. ret = EXIT_FAILURE;
  201. }
  202. cleanup:
  203. if (hQuery)
  204. {
  205. status = PdhCloseQuery(hQuery);
  206. }
  207. return ret;
  208. }
  209. PDH_STATUS ReadTotalCounter(PDH_HCOUNTER hCounter, LONGLONG* ret)
  210. {
  211. PDH_STATUS status = ERROR_SUCCESS;
  212. DWORD i = 0;
  213. DWORD dwBufferSize = 0;
  214. DWORD dwItemCount = 0;
  215. PDH_RAW_COUNTER_ITEM *pItems = NULL;
  216. // Initialize output
  217. *ret = 0;
  218. // Get the required size of the pItems buffer
  219. status = PdhGetRawCounterArray(hCounter, &dwBufferSize, &dwItemCount, NULL);
  220. if (PDH_MORE_DATA == status)
  221. {
  222. pItems = (PDH_RAW_COUNTER_ITEM *) malloc(dwBufferSize);
  223. if (pItems)
  224. {
  225. // Actually query the counter
  226. status = PdhGetRawCounterArray(hCounter, &dwBufferSize, &dwItemCount, pItems);
  227. if (ERROR_SUCCESS == status) {
  228. for (i = 0; i < dwItemCount; i++) {
  229. if (wcscmp(L"_Total", pItems[i].szName) == 0) {
  230. *ret = pItems[i].RawValue.FirstValue;
  231. break;
  232. } else {
  233. *ret += pItems[i].RawValue.FirstValue;
  234. }
  235. }
  236. } else {
  237. *ret = -1;
  238. goto cleanup;
  239. }
  240. // Reset structures
  241. free(pItems);
  242. pItems = NULL;
  243. dwBufferSize = dwItemCount = 0;
  244. } else {
  245. *ret = -1;
  246. status = PDH_NO_DATA;
  247. goto cleanup;
  248. }
  249. } else {
  250. *ret = -1;
  251. goto cleanup;
  252. }
  253. cleanup:
  254. if (pItems) {
  255. free(pItems);
  256. }
  257. return status;
  258. }