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.

468 lines
12 KiB

  1. //
  2. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: client.c
  5. //
  6. // PURPOSE: This program is a command line program to get process or pool statistics
  7. //
  8. //
  9. // AUTHOR:
  10. // Anitha Panapakkam -
  11. //
  12. #include <windows.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <io.h>
  16. #include <rpc.h>
  17. #include "relstat.h"
  18. #define MEMSNAP 1
  19. #define POOLSNAP 2
  20. int iFlag = -1;
  21. FILE* LogFile=NULL; // log file handle
  22. RPC_BINDING_HANDLE Binding;
  23. void Usage(void)
  24. {
  25. printf("Usage:\n"
  26. "\t-n <server addr> - Defaults to local machine\n"
  27. "\t-m - memsnap \n"
  28. "\t-p - poolsnap \n"
  29. "\t<logfile> = memsnap.log by default\n"
  30. );
  31. exit(1);
  32. }
  33. VOID PrintError( RPC_STATUS status)
  34. {
  35. LPVOID lpMsgBuf;
  36. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  37. NULL,
  38. status,
  39. MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  40. (LPTSTR) &lpMsgBuf,
  41. 0,
  42. NULL );
  43. printf("%s\n", lpMsgBuf);
  44. if( LogFile ) {
  45. fprintf(LogFile,"!error=%s\n",lpMsgBuf);
  46. }
  47. LocalFree( lpMsgBuf );
  48. return;
  49. }
  50. void ProcessInfo();
  51. void PooltagInfo();
  52. //
  53. // FUNCTION: main
  54. //
  55. // PURPOSE: Parses arguments and binds to the server.
  56. //
  57. // PARAMETERS:
  58. // argc - number of command line arguments
  59. // argv - array of command line arguments
  60. //
  61. // RETURN VALUE:
  62. // Program exit code.
  63. //
  64. //
  65. int _cdecl main(int argc, char *argv[])
  66. {
  67. SYSTEMTIME SystemTime;
  68. char *serverAddress = NULL;
  69. char *protocol = "ncacn_np";
  70. UINT iIterations = 100;
  71. unsigned char *stringBinding;
  72. RPC_STATUS status;
  73. ULONG SecurityLevel = RPC_C_AUTHN_LEVEL_NONE;
  74. ULONG ulBuildNumber=0;
  75. ULONG ulTickCount = 0;
  76. PCHAR pszFileName;
  77. INT iArg;
  78. pszFileName = &"memsnap.log";
  79. argc--;
  80. argv++;
  81. while(argc)
  82. {
  83. if( (argv[0][0] == '-' ) || (argv[0][0] == '/') )
  84. {
  85. switch(argv[0][1])
  86. {
  87. case 'n':
  88. if (argc < 2)
  89. {
  90. Usage();
  91. }
  92. serverAddress = argv[1];
  93. //printf("%s server\n",serverAddress);
  94. argc--;
  95. argv++;
  96. break;
  97. case 'm':
  98. iFlag = MEMSNAP;
  99. break;
  100. case 'p':
  101. iFlag = POOLSNAP;
  102. break;
  103. case 't':
  104. if (argc < 2)
  105. {
  106. Usage();
  107. }
  108. protocol = argv[1];
  109. argc--;
  110. argv++;
  111. break;
  112. default:
  113. Usage();
  114. break;
  115. }
  116. }
  117. else
  118. { // must be the log filename
  119. pszFileName= argv[0];
  120. }
  121. argc--;
  122. argv++;
  123. }
  124. if( (iFlag != POOLSNAP) && (iFlag != MEMSNAP) ) {
  125. Usage();
  126. }
  127. //
  128. // Open the output file
  129. //
  130. LogFile= fopen( pszFileName, "a" );
  131. if( LogFile == NULL ) {
  132. printf("Error opening file %s\n",pszFileName);
  133. exit(-1);
  134. }
  135. //
  136. // print file header once
  137. //
  138. if (_filelength(_fileno(LogFile)) == 0 ) {
  139. if( iFlag == MEMSNAP ) {
  140. fprintf(LogFile,"Process ID Proc.Name Wrkng.Set PagedPool NonPgdPl Pagefile Commit Handles Threads" " GdiObjs UserObjs" );
  141. }
  142. if( iFlag == POOLSNAP ) {
  143. fprintf(LogFile," Tag Type Allocs Frees Diff Bytes Per Alloc");
  144. }
  145. }
  146. //
  147. // Blank line separates different snaps
  148. //
  149. fprintf( LogFile, "\n" );
  150. //
  151. // Bind to the RPC interface
  152. //
  153. status = RpcStringBindingCompose(0,
  154. protocol,
  155. serverAddress,
  156. 0,
  157. 0,
  158. &stringBinding);
  159. if (status != RPC_S_OK)
  160. {
  161. printf("RpcStringBindingCompose failed - %d\n", status);
  162. PrintError(status);
  163. return(1);
  164. }
  165. status = RpcBindingFromStringBinding(stringBinding, &Binding);
  166. if (status != RPC_S_OK)
  167. {
  168. printf("RpcBindingFromStringBinding failed - %d\n", status);
  169. PrintError(status);
  170. return(1);
  171. }
  172. status =
  173. RpcBindingSetAuthInfo(Binding,
  174. 0,
  175. SecurityLevel,
  176. RPC_C_AUTHN_WINNT,
  177. 0,
  178. 0
  179. );
  180. if (status != RPC_S_OK)
  181. {
  182. printf("RpcBindingSetAuthInfo failed - %d\n", status);
  183. PrintError(status);
  184. return(1);
  185. }
  186. //
  187. // Output the tagging information after the title (sortlog types file by first line)
  188. //
  189. if( iFlag == MEMSNAP ) {
  190. fprintf(LogFile,"!LogType=memsnap\n");
  191. }
  192. if( iFlag == POOLSNAP ) {
  193. fprintf(LogFile,"!LogType=poolsnap\n");
  194. }
  195. if( serverAddress == NULL ) {
  196. CHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  197. DWORD dwSize= sizeof(szComputerName);
  198. if( GetComputerName( szComputerName, &dwSize ) ) {
  199. fprintf(LogFile,"!ComputerName=%s\n",szComputerName);
  200. }
  201. // No output if no computer name available...
  202. }
  203. else {
  204. fprintf(LogFile,"!ComputerName=%s\n",serverAddress);
  205. }
  206. status = RelStatBuildNumber(Binding, &ulBuildNumber);
  207. if (status != ERROR_SUCCESS)
  208. {
  209. printf("RelStatBuildNumber failed %d\n", status);
  210. PrintError(status);
  211. }
  212. else
  213. {
  214. fprintf(LogFile, "!buildnumber=%d \n", ulBuildNumber);
  215. }
  216. // SystemTime (UTC not local time)
  217. GetSystemTime(&SystemTime);
  218. fprintf(LogFile,"!SystemTime=%02i\\%02i\\%04i %02i:%02i:%02i.%04i (GMT)\n",
  219. SystemTime.wMonth,
  220. SystemTime.wDay,
  221. SystemTime.wYear,
  222. SystemTime.wHour,
  223. SystemTime.wMinute,
  224. SystemTime.wSecond,
  225. SystemTime.wMilliseconds);
  226. status = RelStatTickCount(Binding, &ulTickCount);
  227. if (status != ERROR_SUCCESS)
  228. {
  229. printf("RelStatTickCount failed %d\n", status);
  230. PrintError(status);
  231. }
  232. else
  233. {
  234. fprintf(LogFile,"!TickCount=%d\n", ulTickCount);
  235. }
  236. //
  237. // Finally, output the requested process or pool information
  238. //
  239. if (iFlag == MEMSNAP) {
  240. ProcessInfo();
  241. }
  242. if (iFlag == POOLSNAP) {
  243. PooltagInfo();
  244. }
  245. //
  246. // Cleanup
  247. //
  248. status = RpcBindingFree(&Binding);
  249. status = RpcStringFree(&stringBinding);
  250. fclose(LogFile);
  251. return(0);
  252. }
  253. void ProcessInfo()
  254. {
  255. PRELSTAT_PROCESS_INFO pRelStatProcessInfo=NULL;
  256. DWORD dwResult;
  257. ULONG dwNumProcesses,i;
  258. LONG Pid = -1;
  259. dwResult = RelStatProcessInfo(Binding,
  260. Pid,
  261. &dwNumProcesses,
  262. &pRelStatProcessInfo);
  263. if (dwResult != ERROR_SUCCESS) {
  264. printf("RelstatProcessInfo error: %d\n",dwResult);
  265. fprintf(LogFile,"!error:RelStatProcessInfo call failed!\n");
  266. fprintf(LogFile,"!error:RelstatProcessInfo error: %d\n",dwResult);
  267. PrintError(dwResult);
  268. }
  269. else {
  270. // printf("Number of Processes = %u\n", dwNumProcesses);
  271. for(i=0; i< dwNumProcesses; i++)
  272. {
  273. #if 0
  274. printf(
  275. "%p%20ws%10u%10u%10u%10u%10u%10u%10u\n",
  276. pRelStatProcessInfo[i].UniqueProcessId,
  277. pRelStatProcessInfo[i].szImageName,
  278. pRelStatProcessInfo[i].WorkingSetSize,
  279. pRelStatProcessInfo[i].QuotaPagedPoolUsage,
  280. pRelStatProcessInfo[i].QuotaNonPagedPoolUsage,
  281. pRelStatProcessInfo[i].PagefileUsage,
  282. pRelStatProcessInfo[i].PrivatePageCount,
  283. pRelStatProcessInfo[i].HandleCount,
  284. pRelStatProcessInfo[i].NumberOfThreads,
  285. pRelStatProcessInfo[i].GdiHandleCount,
  286. pRelStatProcessInfo[i].UsrHandleCount
  287. );
  288. #endif
  289. fprintf(LogFile,
  290. "%10u%20ws%10u%10u%10u%10u%10u%10u%10u%10u%10u\n",
  291. pRelStatProcessInfo[i].UniqueProcessId,
  292. pRelStatProcessInfo[i].szImageName,
  293. pRelStatProcessInfo[i].WorkingSetSize,
  294. pRelStatProcessInfo[i].QuotaPagedPoolUsage,
  295. pRelStatProcessInfo[i].QuotaNonPagedPoolUsage,
  296. pRelStatProcessInfo[i].PagefileUsage,
  297. pRelStatProcessInfo[i].PrivatePageCount,
  298. pRelStatProcessInfo[i].HandleCount,
  299. pRelStatProcessInfo[i].NumberOfThreads,
  300. pRelStatProcessInfo[i].GdiHandleCount,
  301. pRelStatProcessInfo[i].UsrHandleCount
  302. );
  303. if (pRelStatProcessInfo[i].szImageName) {
  304. MIDL_user_free(pRelStatProcessInfo[i].szImageName);
  305. }
  306. }
  307. }
  308. if (pRelStatProcessInfo) {
  309. MIDL_user_free(pRelStatProcessInfo);
  310. }
  311. pRelStatProcessInfo = NULL;
  312. return;
  313. }
  314. void PooltagInfo()
  315. {
  316. CHAR* pszFormat;
  317. DWORD dwResult;
  318. ULONG i,dwNumTags;
  319. PRELSTAT_POOLTAG_INFO pRelStatPoolInfo=NULL;
  320. PRELSTAT_POOLTAG_INFO ptr;
  321. LPSTR szTagName=TEXT("*");
  322. UCHAR szTag[5];
  323. //call the RelstatPooltagInfo api to get the pooltag information
  324. dwResult = RelStatPoolTagInfo(Binding,
  325. szTagName,
  326. &dwNumTags,
  327. &pRelStatPoolInfo);
  328. if (dwResult != ERROR_SUCCESS) {
  329. printf("RelstatPoolTagInfo error: %d\n",dwResult);
  330. fprintf(LogFile,"!error:RelStatPoolTagInfo call failed!\n");
  331. fprintf(LogFile,"!error:RelstatPoolTagInfo error: %d\n",dwResult);
  332. PrintError(dwResult);
  333. }
  334. else {
  335. for(i=0;i<dwNumTags;i++) {
  336. memcpy(szTag,pRelStatPoolInfo[i].Tag,4);
  337. szTag[4] = '\0';
  338. pszFormat=
  339. #ifdef _WIN64
  340. " %4s %5s %18I64d %18I64d %16I64d %14I64d %12I64d\n",
  341. #else
  342. " %4s %5s %9ld %9ld %8ld %7ld %6ld\n",
  343. #endif
  344. ptr= &pRelStatPoolInfo[i];
  345. if( ptr->PagedAllocs != 0 ) {
  346. ULONG Diff= ptr->PagedAllocs - ptr->PagedFrees;
  347. fprintf(LogFile, pszFormat,
  348. szTag,
  349. "Paged",
  350. ptr->PagedAllocs,
  351. ptr->PagedFrees,
  352. Diff,
  353. ptr->PagedUsed,
  354. ptr->PagedUsed/(Diff?Diff:1)
  355. );
  356. }
  357. if( ptr->NonPagedAllocs != 0 ) {
  358. ULONG Diff= ptr->NonPagedAllocs - ptr->NonPagedFrees;
  359. fprintf(LogFile, pszFormat,
  360. szTag,
  361. "Nonp",
  362. ptr->NonPagedAllocs,
  363. ptr->NonPagedFrees,
  364. Diff,
  365. ptr->NonPagedUsed,
  366. ptr->NonPagedUsed/(Diff?Diff:1)
  367. );
  368. }
  369. }
  370. }
  371. if (pRelStatPoolInfo) {
  372. MIDL_user_free(pRelStatPoolInfo);
  373. }
  374. pRelStatPoolInfo = NULL;
  375. return;
  376. }
  377. void * __RPC_USER MIDL_user_allocate(size_t size)
  378. {
  379. return(HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, size));
  380. }
  381. void __RPC_USER MIDL_user_free( void *pointer)
  382. {
  383. HeapFree(GetProcessHeap(), 0, pointer);
  384. }