// // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. // // MODULE: client.c // // PURPOSE: This program is a command line program to get process or pool statistics // // // AUTHOR: // Anitha Panapakkam - // #include #include #include #include #include #include "relstat.h" #define MEMSNAP 1 #define POOLSNAP 2 int iFlag = -1; FILE* LogFile=NULL; // log file handle RPC_BINDING_HANDLE Binding; void Usage(void) { printf("Usage:\n" "\t-n - Defaults to local machine\n" "\t-m - memsnap \n" "\t-p - poolsnap \n" "\t = memsnap.log by default\n" ); exit(1); } VOID PrintError( RPC_STATUS status) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, status, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR) &lpMsgBuf, 0, NULL ); printf("%s\n", lpMsgBuf); if( LogFile ) { fprintf(LogFile,"!error=%s\n",lpMsgBuf); } LocalFree( lpMsgBuf ); return; } void ProcessInfo(); void PooltagInfo(); // // FUNCTION: main // // PURPOSE: Parses arguments and binds to the server. // // PARAMETERS: // argc - number of command line arguments // argv - array of command line arguments // // RETURN VALUE: // Program exit code. // // int _cdecl main(int argc, char *argv[]) { SYSTEMTIME SystemTime; char *serverAddress = NULL; char *protocol = "ncacn_np"; UINT iIterations = 100; unsigned char *stringBinding; RPC_STATUS status; ULONG SecurityLevel = RPC_C_AUTHN_LEVEL_NONE; ULONG ulBuildNumber=0; ULONG ulTickCount = 0; PCHAR pszFileName; INT iArg; pszFileName = &"memsnap.log"; argc--; argv++; while(argc) { if( (argv[0][0] == '-' ) || (argv[0][0] == '/') ) { switch(argv[0][1]) { case 'n': if (argc < 2) { Usage(); } serverAddress = argv[1]; //printf("%s server\n",serverAddress); argc--; argv++; break; case 'm': iFlag = MEMSNAP; break; case 'p': iFlag = POOLSNAP; break; case 't': if (argc < 2) { Usage(); } protocol = argv[1]; argc--; argv++; break; default: Usage(); break; } } else { // must be the log filename pszFileName= argv[0]; } argc--; argv++; } if( (iFlag != POOLSNAP) && (iFlag != MEMSNAP) ) { Usage(); } // // Open the output file // LogFile= fopen( pszFileName, "a" ); if( LogFile == NULL ) { printf("Error opening file %s\n",pszFileName); exit(-1); } // // print file header once // if (_filelength(_fileno(LogFile)) == 0 ) { if( iFlag == MEMSNAP ) { fprintf(LogFile,"Process ID Proc.Name Wrkng.Set PagedPool NonPgdPl Pagefile Commit Handles Threads" " GdiObjs UserObjs" ); } if( iFlag == POOLSNAP ) { fprintf(LogFile," Tag Type Allocs Frees Diff Bytes Per Alloc"); } } // // Blank line separates different snaps // fprintf( LogFile, "\n" ); // // Bind to the RPC interface // status = RpcStringBindingCompose(0, protocol, serverAddress, 0, 0, &stringBinding); if (status != RPC_S_OK) { printf("RpcStringBindingCompose failed - %d\n", status); PrintError(status); return(1); } status = RpcBindingFromStringBinding(stringBinding, &Binding); if (status != RPC_S_OK) { printf("RpcBindingFromStringBinding failed - %d\n", status); PrintError(status); return(1); } status = RpcBindingSetAuthInfo(Binding, 0, SecurityLevel, RPC_C_AUTHN_WINNT, 0, 0 ); if (status != RPC_S_OK) { printf("RpcBindingSetAuthInfo failed - %d\n", status); PrintError(status); return(1); } // // Output the tagging information after the title (sortlog types file by first line) // if( iFlag == MEMSNAP ) { fprintf(LogFile,"!LogType=memsnap\n"); } if( iFlag == POOLSNAP ) { fprintf(LogFile,"!LogType=poolsnap\n"); } if( serverAddress == NULL ) { CHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1]; DWORD dwSize= sizeof(szComputerName); if( GetComputerName( szComputerName, &dwSize ) ) { fprintf(LogFile,"!ComputerName=%s\n",szComputerName); } // No output if no computer name available... } else { fprintf(LogFile,"!ComputerName=%s\n",serverAddress); } status = RelStatBuildNumber(Binding, &ulBuildNumber); if (status != ERROR_SUCCESS) { printf("RelStatBuildNumber failed %d\n", status); PrintError(status); } else { fprintf(LogFile, "!buildnumber=%d \n", ulBuildNumber); } // SystemTime (UTC not local time) GetSystemTime(&SystemTime); fprintf(LogFile,"!SystemTime=%02i\\%02i\\%04i %02i:%02i:%02i.%04i (GMT)\n", SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds); status = RelStatTickCount(Binding, &ulTickCount); if (status != ERROR_SUCCESS) { printf("RelStatTickCount failed %d\n", status); PrintError(status); } else { fprintf(LogFile,"!TickCount=%d\n", ulTickCount); } // // Finally, output the requested process or pool information // if (iFlag == MEMSNAP) { ProcessInfo(); } if (iFlag == POOLSNAP) { PooltagInfo(); } // // Cleanup // status = RpcBindingFree(&Binding); status = RpcStringFree(&stringBinding); fclose(LogFile); return(0); } void ProcessInfo() { PRELSTAT_PROCESS_INFO pRelStatProcessInfo=NULL; DWORD dwResult; ULONG dwNumProcesses,i; LONG Pid = -1; dwResult = RelStatProcessInfo(Binding, Pid, &dwNumProcesses, &pRelStatProcessInfo); if (dwResult != ERROR_SUCCESS) { printf("RelstatProcessInfo error: %d\n",dwResult); fprintf(LogFile,"!error:RelStatProcessInfo call failed!\n"); fprintf(LogFile,"!error:RelstatProcessInfo error: %d\n",dwResult); PrintError(dwResult); } else { // printf("Number of Processes = %u\n", dwNumProcesses); for(i=0; i< dwNumProcesses; i++) { #if 0 printf( "%p%20ws%10u%10u%10u%10u%10u%10u%10u\n", pRelStatProcessInfo[i].UniqueProcessId, pRelStatProcessInfo[i].szImageName, pRelStatProcessInfo[i].WorkingSetSize, pRelStatProcessInfo[i].QuotaPagedPoolUsage, pRelStatProcessInfo[i].QuotaNonPagedPoolUsage, pRelStatProcessInfo[i].PagefileUsage, pRelStatProcessInfo[i].PrivatePageCount, pRelStatProcessInfo[i].HandleCount, pRelStatProcessInfo[i].NumberOfThreads, pRelStatProcessInfo[i].GdiHandleCount, pRelStatProcessInfo[i].UsrHandleCount ); #endif fprintf(LogFile, "%10u%20ws%10u%10u%10u%10u%10u%10u%10u%10u%10u\n", pRelStatProcessInfo[i].UniqueProcessId, pRelStatProcessInfo[i].szImageName, pRelStatProcessInfo[i].WorkingSetSize, pRelStatProcessInfo[i].QuotaPagedPoolUsage, pRelStatProcessInfo[i].QuotaNonPagedPoolUsage, pRelStatProcessInfo[i].PagefileUsage, pRelStatProcessInfo[i].PrivatePageCount, pRelStatProcessInfo[i].HandleCount, pRelStatProcessInfo[i].NumberOfThreads, pRelStatProcessInfo[i].GdiHandleCount, pRelStatProcessInfo[i].UsrHandleCount ); if (pRelStatProcessInfo[i].szImageName) { MIDL_user_free(pRelStatProcessInfo[i].szImageName); } } } if (pRelStatProcessInfo) { MIDL_user_free(pRelStatProcessInfo); } pRelStatProcessInfo = NULL; return; } void PooltagInfo() { CHAR* pszFormat; DWORD dwResult; ULONG i,dwNumTags; PRELSTAT_POOLTAG_INFO pRelStatPoolInfo=NULL; PRELSTAT_POOLTAG_INFO ptr; LPSTR szTagName=TEXT("*"); UCHAR szTag[5]; //call the RelstatPooltagInfo api to get the pooltag information dwResult = RelStatPoolTagInfo(Binding, szTagName, &dwNumTags, &pRelStatPoolInfo); if (dwResult != ERROR_SUCCESS) { printf("RelstatPoolTagInfo error: %d\n",dwResult); fprintf(LogFile,"!error:RelStatPoolTagInfo call failed!\n"); fprintf(LogFile,"!error:RelstatPoolTagInfo error: %d\n",dwResult); PrintError(dwResult); } else { for(i=0;iPagedAllocs != 0 ) { ULONG Diff= ptr->PagedAllocs - ptr->PagedFrees; fprintf(LogFile, pszFormat, szTag, "Paged", ptr->PagedAllocs, ptr->PagedFrees, Diff, ptr->PagedUsed, ptr->PagedUsed/(Diff?Diff:1) ); } if( ptr->NonPagedAllocs != 0 ) { ULONG Diff= ptr->NonPagedAllocs - ptr->NonPagedFrees; fprintf(LogFile, pszFormat, szTag, "Nonp", ptr->NonPagedAllocs, ptr->NonPagedFrees, Diff, ptr->NonPagedUsed, ptr->NonPagedUsed/(Diff?Diff:1) ); } } } if (pRelStatPoolInfo) { MIDL_user_free(pRelStatPoolInfo); } pRelStatPoolInfo = NULL; return; } void * __RPC_USER MIDL_user_allocate(size_t size) { return(HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, size)); } void __RPC_USER MIDL_user_free( void *pointer) { HeapFree(GetProcessHeap(), 0, pointer); }