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.

2173 lines
97 KiB

  1. /*======================================================================================//
  2. | //
  3. |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated. All rights reserved. //
  4. | //
  5. |Description: //
  6. | //
  7. | Windows 2000 Process Control command line utility //
  8. | //
  9. |Created: //
  10. | //
  11. | Jarl McDonald 07-98 //
  12. | //
  13. |Revision History: //
  14. | //
  15. | Jarl McDonald Spring, 1999 Completed version 1.0 changes //
  16. | //
  17. |=======================================================================================*/
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <stddef.h>
  21. #include <tchar.h>
  22. #include <shellapi.h>
  23. #include "resource.h"
  24. #include "..\Library\ProcConAPI.h"
  25. //=======================================================================================
  26. // Macros...
  27. //=======================================================================================
  28. #define ENTRY_COUNT(x) (int)((sizeof(x) / sizeof(x[0])))
  29. #define SPACE TEXT(' ')
  30. //=======================================================================================
  31. // enums, typedefs, etc....
  32. //=======================================================================================
  33. enum _HELP_FLAGS {
  34. HELP_LIST = 0x01,
  35. HELP_MGMT = 0x02,
  36. HELP_ALIAS = 0x04,
  37. } HELP_FLAGS;
  38. typedef enum _switches { // Do not localize these...
  39. COMPUTER_NAME = TEXT('c'),
  40. BUFFER_SIZE = TEXT('b'),
  41. INTERACTIVE = TEXT('i'),
  42. FILE_INPUT = TEXT('f'),
  43. ADMIN_DUMPREST = TEXT('x'),
  44. OP_ADD = TEXT('a'),
  45. OP_REP = TEXT('r'),
  46. OP_DEL = TEXT('d'),
  47. OP_SWAP = TEXT('s'),
  48. OP_LIST = TEXT('l'),
  49. OP_UPDATE = TEXT('u'),
  50. OP_COMMENT = TEXT('*'),
  51. OP_KILL = TEXT('k'),
  52. OP_HELP = TEXT('?'),
  53. OP_HELP2 = TEXT('h'),
  54. DATA_GROUP = TEXT('g'),
  55. DATA_PROC = TEXT('p'),
  56. DATA_NAME = TEXT('n'),
  57. DATA_DUMPREST = TEXT(';'),
  58. DATA_SERVICE = TEXT('v'),
  59. DATA_MEDIATOR = TEXT('m'),
  60. SUB_DEFS = TEXT('d'),
  61. SUB_SUMMARY = TEXT('s'),
  62. SUB_LIST = TEXT('l'),
  63. SUB_FULLNAMES = TEXT('f'),
  64. SUB_RUNNING = TEXT('r'),
  65. SUB_ONLY = TEXT('o'),
  66. };
  67. typedef enum _defSwitches { // Do not localize these...
  68. DEF_FLAGS = TEXT('f'),
  69. DEF_PRIO = TEXT('p'),
  70. DEF_AFF = TEXT('a'),
  71. DEF_WS = TEXT('w'),
  72. DEF_SCHED = TEXT('s'),
  73. DEF_DESC = TEXT('d'),
  74. DEF_PROCTIME = TEXT('t'),
  75. DEF_GROUPTIME = TEXT('u'),
  76. DEF_GROUPMEM = TEXT('n'),
  77. DEF_PROCMEM = TEXT('m'),
  78. DEF_PROCCOUNT = TEXT('c'),
  79. DEF_BRKAWAY = TEXT('b'),
  80. DEF_SILENTBRKAWAY = TEXT('q'),
  81. DEF_DIEONUHEX = TEXT('x'),
  82. DEF_CLOSEONEMPTY = TEXT('y'),
  83. DEF_MSGONGRPTIME = TEXT('z'),
  84. DEF_GROUP = TEXT('g'),
  85. DEF_VARDATA = TEXT('v'),
  86. DEF_PROF = TEXT('r'),
  87. };
  88. typedef enum _groupListSwitches { // Do not localize these...
  89. GL_ALL = TEXT('a'),
  90. GL_BASE = TEXT('b'),
  91. GL_IO = TEXT('i'),
  92. GL_MEMORY = TEXT('m'),
  93. GL_PROCESS = TEXT('p'),
  94. GL_TIME = TEXT('t'),
  95. };
  96. typedef enum _colJustify {
  97. PCCOL_JUST_CENTER = 1,
  98. PCCOL_JUST_LEFT,
  99. PCCOL_JUST_RIGHT
  100. };
  101. typedef struct _PCTableDef {
  102. PCULONG32 longStringID, shortStringID;
  103. PCULONG32 longMinLen, shortMinLen;
  104. PCULONG32 justification;
  105. TCHAR rowFmt[32];
  106. } PCTableDef;
  107. //=======================================================================================
  108. // Global data...
  109. //=======================================================================================
  110. static TCHAR SUB_DefSummaryList[] = { SUB_DEFS, SUB_SUMMARY, SUB_LIST, 0 };
  111. static int pCode[] = { PCPrioIdle, PCPrioIdle, PCPrioNormal, PCPrioHigh,
  112. PCPrioRealTime, PCPrioAboveNormal, PCPrioBelowNormal };
  113. // L ("Low") is a synonym for idle prio class. Do not localize these...
  114. static TCHAR pNames[] = TEXT("LINHRAB");
  115. TCHAR oldTarget[MAX_PATH] = TEXT("\0");
  116. TCHAR target[MAX_PATH] = TEXT(".");
  117. PCid targId = 0;
  118. PCINT32 oldBuffer = 0;
  119. PCINT32 buffer = 64500;
  120. BOOL convertError = FALSE;
  121. BOOL interact = FALSE;
  122. FILE *inFile = NULL;
  123. TCHAR inFileName[MAX_PATH];
  124. FILE *adminFile = NULL;
  125. TCHAR adminFileName[MAX_PATH];
  126. PCNameRule nameRules[PC_MAX_BUF_SIZE / sizeof(PCNameRule)];
  127. PCSystemInfo sysInfo;
  128. HMODULE moduleUs = GetModuleHandle( NULL );
  129. TCHAR cmdPrompt[32];
  130. BOOL gListShowBase, gListShowIO, gListShowMem, gListShowProc, gListShowTime, gShowFmtProcTime, gShowFullNames;
  131. PCULONG32 colWidth[32], colOffset[32], tableWidth;
  132. TCHAR colHead[2048];
  133. TCHAR colDash[2048];
  134. TCHAR rowData[2048];
  135. TCHAR sepChar = 0;
  136. //=======================================================================================
  137. // function prototypes....
  138. //=======================================================================================
  139. static int GetNextCommand ( FILE *readMe, TCHAR **list );
  140. static int DoCommands ( int argct, TCHAR **argList );
  141. static int DoDumpRestore ( FILE *adminFile, BOOL dump );
  142. static int cFileError ( BOOL dump );
  143. static void DispDumpComment ( FILE *adminFile, PCULONG32 msgID, PCINT32 count = 0 );
  144. static void DumpMgmtParms ( MGMT_PARMS &mgt, PCINT16 len, TCHAR *data );
  145. static void DoMediatorControl( TCHAR **pArgs, PCUINT32 pArgCt );
  146. static TCHAR *GetOpName ( TCHAR code );
  147. static TCHAR *GetDataName ( TCHAR code, TCHAR subCode );
  148. static TCHAR *GetDataSubName ( TCHAR code );
  149. static PC_MGMT_FLAGS GetMgtFlags( TCHAR *txt );
  150. static void PrintHelp ( PCUINT32 flags, BOOL isGrp = TRUE, PCUINT32 msgId = 0 );
  151. static void PrintLine ( TCHAR *data, PCUINT32 nlCount );
  152. static void ShowNameRules ( PCNameRule *rule, PCINT32 count, PCINT32 index = 0 );
  153. static void ShowGrpDetail ( PCJobDetail &grpDetail );
  154. static void ShowProcDetail ( PCProcDetail &procDetail );
  155. static void ShowGrpSummary ( PCJobSummary *list, PCINT32 count, BOOL isFirst = TRUE, int totcnt = 0 );
  156. static void ShowProcSummary ( PCProcSummary *list, PCINT32 count, BOOL isFirst = TRUE, int totcnt = 0 );
  157. static void ShowGrpList ( PCJobListItem *list, PCINT32 count, BOOL isFirst = TRUE, int totcnt = 0 );
  158. static void ShowProcList ( PCProcListItem *list, PCINT32 count, BOOL isFirst = TRUE, int totcnt = 0 );
  159. static void ShowGrpListWithBase( PCJobListItem *list, PCINT32 count, BOOL isFirst );
  160. static void ShowGrpListWithIo ( PCJobListItem *list, PCINT32 count, BOOL isFirst );
  161. static void ShowGrpListWithMem ( PCJobListItem *list, PCINT32 count, BOOL isFirst );
  162. static void ShowGrpListWithProc( PCJobListItem *list, PCINT32 count, BOOL isFirst );
  163. static void ShowGrpListWithTime( PCJobListItem *list, PCINT32 count, BOOL isFirst );
  164. static void ShowMgmtParms ( MGMT_PARMS &parm, BOOL isGrp );
  165. static void ShowMgmtParmsAsList( PCTableDef *table, PCULONG32 entries, PCULONG32 first, MGMT_PARMS &parm, BOOL isGrp );
  166. static void ShowVariableData ( short len, TCHAR *data );
  167. static void ShowListFlags ( PC_LIST_FLAGS flags, TCHAR out[8] );
  168. static void ShowMgmtFlags ( TCHAR flags[16], PC_MGMT_FLAGS mFlags, BOOL compact = FALSE );
  169. static void ShowSysInfo ( PCSystemInfo &sysInfo, BOOL versionOnly = TRUE );
  170. static void ShowSysParms ( PCSystemParms &sysParms );
  171. static int ShowHelp ( TCHAR **pArgs, PCUINT32 pArgCt );
  172. static void ShowCLIHelp ( void );
  173. static void ShowDetailHelp ( TCHAR **pArgs, PCUINT32 pArgCt );
  174. static void BuildSystemParms ( PCSystemParms &newParms, TCHAR **pArgs, PCUINT32 pArgCt );
  175. static void BuildNameRule ( PCNameRule &newRule, TCHAR **pArgs, PCUINT32 pArgCt );
  176. static void BuildGrpDetail ( PCJobDetail &newDetail, TCHAR **pArgs, PCUINT32 pArgCt );
  177. static void BuildProcDetail ( PCProcDetail &newDetail, TCHAR **pArgs, PCUINT32 pArgCt );
  178. static void BuildGrpSummary ( PCJobSummary &newSummary, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags );
  179. static void BuildProcSummary ( PCProcSummary &newSummary, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags );
  180. static void BuildGrpListItem ( PCJobListItem &newListItem, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags );
  181. static void BuildProcListItem ( PCProcListItem &newListItem, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags );
  182. static void BuildMgmtParms ( MGMT_PARMS &parm, TCHAR **pArgs, PCUINT32 pArgCt,
  183. JOB_NAME grpHere = NULL, PCINT16 *len = NULL, TCHAR *var = NULL );
  184. static void BuildTableHeader ( PCTableDef *table, PCULONG32 entries, BOOL printIt = TRUE );
  185. static void InsertTableData ( PCTableDef *table, PCULONG32 index, TCHAR *dataItem, BOOL printIt );
  186. static void MergeGroupDetail ( PCJobDetail &newDet, PCJobDetail &oldDet );
  187. static void MergeProcDetail ( PCProcDetail &newDet, PCProcDetail &oldDet );
  188. //=======================================================================================
  189. // Simple functions....
  190. //=======================================================================================
  191. #define TOOLMSG_ERR_BUFF_SIZE 4096
  192. static LPTSTR GetErrorText( PCUINT32 error, LPTSTR buf, PCUINT32 size )
  193. {
  194. static TCHAR *errBuf;
  195. PCUINT32 dwRet = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE + FORMAT_MESSAGE_FROM_SYSTEM +
  196. FORMAT_MESSAGE_IGNORE_INSERTS + FORMAT_MESSAGE_ALLOCATE_BUFFER,
  197. NULL, error, 0, (TCHAR *) &errBuf, 0, NULL );
  198. if ( !dwRet )
  199. _sntprintf( buf, size, TEXT("No message text for error 0x%lx, format error 0x%lx"), error, GetLastError());
  200. else {
  201. _tcsncpy( buf, errBuf, size );
  202. LocalFree( errBuf );
  203. while ( --dwRet && (buf[dwRet] == TEXT('\n') || buf[dwRet] == TEXT('\r') || buf[dwRet] == TEXT('.')) )
  204. buf[dwRet] = TEXT('\0');
  205. }
  206. return buf;
  207. }
  208. static int ToolMsg( PCUINT32 msgId, VOID *arg1 = NULL, PCINT32 err = ERROR_SUCCESS,
  209. VOID *arg2 = NULL, VOID *arg3 = NULL, VOID *arg4 = NULL,
  210. VOID *arg5 = NULL, VOID *arg6 = NULL, VOID *arg7 = NULL,
  211. VOID *arg8 = NULL, VOID *arg9 = NULL, VOID *arg10 = NULL,
  212. VOID *arg11 = NULL ) {
  213. PCUINT32 nlCt = err == ERROR_SUCCESS? 1 : 0;
  214. TCHAR *mBuf;
  215. TCHAR eBuf[TOOLMSG_ERR_BUFF_SIZE], errBuf[TOOLMSG_ERR_BUFF_SIZE];
  216. char *ptrs[16];
  217. ptrs[0] = (char *) arg1;
  218. ptrs[1] = (char *) arg2;
  219. ptrs[2] = (char *) arg3;
  220. ptrs[3] = (char *) arg4;
  221. ptrs[4] = (char *) arg5;
  222. ptrs[5] = (char *) arg6;
  223. ptrs[6] = (char *) arg7;
  224. ptrs[7] = (char *) arg8;
  225. ptrs[8] = (char *) arg9;
  226. ptrs[9] = (char *) arg10;
  227. ptrs[10] = (char *) arg11;
  228. PCUINT32 dwRet = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE + FORMAT_MESSAGE_ARGUMENT_ARRAY +
  229. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  230. NULL, msgId, 0, (TCHAR *) &mBuf, 0, ptrs );
  231. if ( !dwRet ) {
  232. PCUINT32 msgErr = GetLastError();
  233. _stprintf( eBuf, TEXT("Message 0x%lx not found, message error is: %s."),
  234. msgId, GetErrorText( msgErr, errBuf, TOOLMSG_ERR_BUFF_SIZE ));
  235. PrintLine( eBuf, nlCt );
  236. }
  237. else {
  238. while ( --dwRet && (mBuf[dwRet] == TEXT('\n') || mBuf[dwRet] == TEXT('\r')) )
  239. mBuf[dwRet] = TEXT('\0');
  240. if ( err != ERROR_SUCCESS && dwRet && mBuf[dwRet] == TEXT('.') )
  241. mBuf[dwRet] = TEXT('\0');
  242. PrintLine( mBuf, nlCt );
  243. LocalFree( mBuf );
  244. }
  245. if ( err != ERROR_SUCCESS ) {
  246. _stprintf( eBuf, TEXT(": %s (0x%lx)."), GetErrorText( err, errBuf, TOOLMSG_ERR_BUFF_SIZE ), err );
  247. PrintLine( eBuf, 1 );
  248. }
  249. return err != ERROR_SUCCESS? err : ERROR_INVALID_PARAMETER;
  250. }
  251. static int ToolMsg( PCUINT32 msgId, int arg1 ) {
  252. return ToolMsg( msgId, IntToPtr(arg1) );
  253. }
  254. static unsigned __int64 GetValue( TCHAR *data, unsigned __int64 limitValue ) {
  255. BOOL hex = *data == TEXT('0') && _totlower(*(data + 1)) == TEXT('x');
  256. if ( hex ) data += 2;
  257. unsigned __int64 factor, result = 0, mult = 1;
  258. ULONG digitMult = hex? 16 : 10;
  259. for ( __int64 len = (__int64) _tcslen( data ) - 1; len >= 0; --len ) {
  260. TCHAR c = _totlower( *(data + len) );
  261. if ( hex && (c >= TEXT('a') && c <= TEXT('f')) )
  262. factor = mult * (c - TEXT('a') + 10);
  263. else if ( c >= TEXT('0') && c <= TEXT('9') )
  264. factor = mult * (c - TEXT('0'));
  265. else {
  266. ToolMsg( hex? PCCLIMSG_INVALID_HEX_DIGIT : PCCLIMSG_INVALID_DEC_DIGIT, data + len );
  267. convertError = TRUE;
  268. continue;
  269. }
  270. if ( limitValue - result < factor ) {
  271. ToolMsg( PCCLIMSG_NUM_TOO_LARGE, data );
  272. convertError = TRUE;
  273. return limitValue;
  274. }
  275. else {
  276. result += factor;
  277. mult *= digitMult;
  278. }
  279. }
  280. return result;
  281. }
  282. static int GetInteger( TCHAR *data ) {
  283. return (int) GetValue( data, 0x000000007fffffff );
  284. }
  285. static __int64 GetInteger64( TCHAR *data ) {
  286. return (__int64) GetValue( data, 0x7fffffffffffffff );
  287. }
  288. static unsigned __int64 GetUInteger64( TCHAR *data ) {
  289. return GetValue( data, 0xffffffffffffffff );
  290. }
  291. static int GetPriority( TCHAR *data ) {
  292. TCHAR *c = _tcschr( pNames, _totupper( *data ) );
  293. if ( c ) return pCode[ c - pNames ];
  294. else return 0;
  295. }
  296. static TCHAR ShowPriority( int data ) {
  297. for ( int i = 0; i < ENTRY_COUNT(pCode); ++i )
  298. if ( data == pCode[i] ) return pNames[i];
  299. return TEXT(' ');
  300. }
  301. static BOOL IsSwitch( TCHAR c ) {
  302. return c == TEXT('-') || c == TEXT('/');
  303. }
  304. //=======================================================================================
  305. // Main...
  306. //=======================================================================================
  307. int _cdecl main( void ) {
  308. int argct, retCode = 0;
  309. BOOL haveCmd = TRUE, firstPass = TRUE;
  310. for ( TCHAR *cmdLine = GetCommandLineW(); haveCmd; haveCmd = GetNextCommand( inFile, &cmdLine ) ) {
  311. TCHAR **argList = CommandLineToArgvW( cmdLine, &argct );
  312. if (argList) {
  313. if ( firstPass || !**argList ) retCode = DoCommands( argct - 1, argList + 1 );
  314. else retCode = DoCommands( argct, argList );
  315. GlobalFree( argList );
  316. }
  317. firstPass = FALSE;
  318. }
  319. if ( targId ) PCClose( targId );
  320. if ( inFile ) fclose( inFile );
  321. return retCode;
  322. }
  323. //=======================================================================================
  324. // Processing functions...
  325. //=======================================================================================
  326. int GetNextCommand( FILE *readMe, TCHAR **cmd ) {
  327. static TCHAR cmdLine[1024];
  328. char cmdBuf[1024];
  329. TCHAR *p = NULL;
  330. if ( interact ) {
  331. PrintLine( cmdPrompt, 0 );
  332. if ( gets( cmdBuf ) ) {
  333. OemToChar( cmdBuf, cmdLine );
  334. p = *cmdLine? cmdLine : NULL;
  335. }
  336. }
  337. else if ( readMe ) {
  338. for ( ;; ) {
  339. p = _fgetts( cmdLine, ENTRY_COUNT(cmdLine), readMe );
  340. if ( !p ) break;
  341. // MS RAID: #375579 - last character dropped when reading from file
  342. size_t l = _tcscspn(p,TEXT("\r\n"));
  343. *(p + l) = 0;
  344. if ( *p ) break;
  345. }
  346. }
  347. *cmd = p;
  348. return p != NULL;
  349. }
  350. int DoCommands( int argct, TCHAR **argList ) {
  351. PCINT32 numRules, updateCtr;
  352. TCHAR opCode = OP_LIST;
  353. TCHAR dataObj = 0;
  354. TCHAR dataSubObj = 0;
  355. PCINT32 index = 0;
  356. TCHAR **pArgs = NULL;
  357. PCUINT32 pArgCt = 0;
  358. BOOL restIsData = FALSE, getListData = FALSE,
  359. doDump = FALSE, doRestore = FALSE;
  360. PCUINT32 listFlags = 0;
  361. TCHAR sub;
  362. gShowFullNames = convertError = FALSE;
  363. // Process parameters until end of parameters...
  364. for ( int i = 0; i < argct; ++i ) {
  365. TCHAR *arg = *argList++;
  366. if ( *arg == 0xfeff || *arg == 0xfffe ) ++arg; // ignore 'This is Unicode' prefix
  367. if ( !IsSwitch( *arg ) )
  368. return ToolMsg( PCCLIMSG_SWITCH_EXPECTED, arg );
  369. TCHAR swChar = *++arg;
  370. switch ( swChar ) {
  371. case COMPUTER_NAME:
  372. if ( *(arg + 1) ) return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  373. if ( ++i >= argct )
  374. return ToolMsg( PCCLIMSG_ARG_MISSING, --arg );
  375. _tcscpy( target, *argList++);
  376. break;
  377. case BUFFER_SIZE:
  378. if ( *(arg + 1) ) return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  379. if ( ++i >= argct )
  380. return ToolMsg( PCCLIMSG_ARG_MISSING, --arg );
  381. buffer = 1024 * GetInteger( *argList++ );
  382. if ( convertError )
  383. return ToolMsg( PCCLIMSG_BUF_SIZE, --arg, PCERROR_INVALID_PARAMETER );
  384. break;
  385. case INTERACTIVE:
  386. if ( *(arg + 1) ) return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  387. if ( inFile ) {
  388. fclose( inFile );
  389. ToolMsg( PCCLIMSG_CMD_FILE_CLOSED, inFileName );
  390. }
  391. if ( !LoadString( moduleUs, CLI_PROMPT, cmdPrompt, ENTRY_COUNT(cmdPrompt) ) )
  392. _tcscpy( cmdPrompt, TEXT(">: ") );
  393. inFile = NULL;
  394. interact = TRUE;
  395. return 0;
  396. break;
  397. case FILE_INPUT:
  398. if ( *(arg + 1) ) return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  399. if ( ++i >= argct )
  400. return ToolMsg( PCCLIMSG_ARG_MISSING, --arg );
  401. if ( inFile ) {
  402. fclose( inFile );
  403. ToolMsg( PCCLIMSG_CMD_FILE_CLOSED, inFileName );
  404. }
  405. _tcscpy( inFileName, *argList++);
  406. inFile = _tfopen( inFileName, TEXT("rb") );
  407. if ( !inFile )
  408. return ToolMsg( PCCLIMSG_CMD_FILE_OPEN_FAIL, inFileName );
  409. else {
  410. char buf[1024];
  411. TCHAR *opType;
  412. int rdct = (int) fread( buf, sizeof(char), sizeof(buf), inFile );
  413. if ( IsTextUnicode( buf, rdct, NULL ) ) opType = TEXT("rb");
  414. else opType = TEXT("r");
  415. fclose( inFile );
  416. inFile = _tfopen( inFileName, opType );
  417. if ( !inFile )
  418. return ToolMsg( PCCLIMSG_CMD_FILE_OPEN_FAIL, inFileName );
  419. }
  420. ToolMsg( PCCLIMSG_CMD_FILE_OPEN_SUCCESS, inFileName );
  421. interact = FALSE;
  422. return 0;
  423. break;
  424. case ADMIN_DUMPREST:
  425. if ( *(arg + 1) == TEXT('d') ) doDump = TRUE;
  426. else if ( *(arg + 1) == TEXT('r') ) doRestore = TRUE;
  427. else return ToolMsg( PCCLIMSG_ADMIN_OP_UNKNOWN, --arg );
  428. if ( ++i >= argct )
  429. return ToolMsg( PCCLIMSG_ARG_MISSING, --arg );
  430. _tcscpy( adminFileName, *argList++);
  431. adminFile = _tfopen( adminFileName, doDump? TEXT("wb") : TEXT("rb") );
  432. if ( !adminFile )
  433. return ToolMsg( doDump? PCCLIMSG_DUMP_FILE_OPEN_FAIL : PCCLIMSG_REST_FILE_OPEN_FAIL, adminFileName );
  434. ToolMsg( doDump? PCCLIMSG_DUMP_FILE_OPEN_SUCCESS : PCCLIMSG_REST_FILE_OPEN_SUCCESS, adminFileName );
  435. restIsData = TRUE;
  436. dataObj = dataSubObj = DATA_DUMPREST;
  437. opCode = doDump? TEXT(';') : TEXT(':');
  438. break;
  439. case OP_ADD:
  440. case OP_REP:
  441. case OP_DEL:
  442. case OP_SWAP:
  443. case OP_LIST:
  444. case OP_UPDATE:
  445. case OP_KILL: {
  446. for ( int i = 1; *(arg + i); ++i ) {
  447. if ( *(arg + i) == SUB_LIST ) getListData = TRUE;
  448. else if ( *(arg + i) == SUB_FULLNAMES ) gShowFullNames = TRUE;
  449. else return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  450. }
  451. if ( opCode != OP_LIST && opCode != swChar )
  452. return ToolMsg( PCCLIMSG_OPERATION_CONFLICT, --arg );
  453. opCode = swChar;
  454. break;
  455. }
  456. case OP_COMMENT:
  457. return 0;
  458. break;
  459. case OP_HELP:
  460. case OP_HELP2:
  461. if ( *(arg + 1) ) return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  462. opCode = OP_HELP;
  463. restIsData = TRUE;
  464. break;
  465. case DATA_GROUP:
  466. dataObj = swChar;
  467. sub = *(arg + 1);
  468. if ( !sub ) sub = SUB_LIST;
  469. else for ( int i = 2; *(arg + i); ++i ) {
  470. if ( *(arg + i) == SUB_RUNNING ) listFlags |= PC_LIST_ONLY_RUNNING;
  471. else if ( *(arg + i) == SUB_ONLY ) listFlags |= PC_LIST_MATCH_ONLY;
  472. else if ( *(arg + i) == SUB_FULLNAMES ) gShowFullNames = TRUE;
  473. else return ToolMsg( PCCLIMSG_SWITCH_SUFFIX_UNKNOWN, (void *) *(arg + i) );
  474. }
  475. if ( _tcschr( SUB_DefSummaryList, sub ) )
  476. dataSubObj = sub;
  477. else return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  478. restIsData = TRUE;
  479. break;
  480. case DATA_PROC:
  481. dataObj = swChar;
  482. sub = *(arg + 1);
  483. if ( !sub ) sub = SUB_LIST;
  484. else for ( int i = 2; *(arg + i); ++i ) {
  485. if ( *(arg + i) == SUB_RUNNING ) listFlags |= PC_LIST_ONLY_RUNNING;
  486. else if ( *(arg + i) == SUB_ONLY ) listFlags |= PC_LIST_MATCH_ONLY;
  487. else if ( *(arg + i) == SUB_FULLNAMES ) gShowFullNames = TRUE;
  488. else return ToolMsg( PCCLIMSG_SWITCH_SUFFIX_UNKNOWN, (void *) *(arg + i) );
  489. }
  490. if ( _tcschr( SUB_DefSummaryList, sub ) )
  491. dataSubObj = sub;
  492. else return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  493. restIsData = TRUE;
  494. break;
  495. case DATA_NAME:
  496. dataObj = swChar;
  497. if ( ++i < argct ) {
  498. index = GetInteger( *argList++ );
  499. if ( convertError )
  500. return ToolMsg( PCCLIMSG_INVALID_ALIAS_INDEX, *--argList );
  501. }
  502. restIsData = TRUE;
  503. break;
  504. case DATA_SERVICE:
  505. case DATA_MEDIATOR:
  506. dataObj = swChar;
  507. restIsData = TRUE;
  508. break;
  509. default:
  510. return ToolMsg( PCCLIMSG_SWITCH_UNKNOWN, --arg );
  511. break;
  512. } // end switch
  513. if ( restIsData ) {
  514. pArgs = argList;
  515. pArgCt = (argct > i) ? argct - i - 1 : 0;
  516. break;
  517. }
  518. }
  519. //-------------------------------------------------------------------------------------------//
  520. // Short circuit remainder of processing if help requested...
  521. if ( opCode == OP_HELP )
  522. return ShowHelp( pArgs, pArgCt );
  523. //-------------------------------------------------------------------------------------------//
  524. // Perform correctness checks on supplied data...
  525. if ( !dataObj )
  526. return ToolMsg( PCCLIMSG_NO_OBJECT_NAME );
  527. if ( opCode == OP_SWAP && dataObj != DATA_NAME )
  528. return ToolMsg( PCCLIMSG_SWAP_NOT_ACCEPTABLE );
  529. if ( dataObj != DATA_NAME && dataSubObj == SUB_SUMMARY && opCode != OP_LIST )
  530. return ToolMsg( PCCLIMSG_SUMMARY_LIST_NOT_SPECIFIED, GetOpName(opCode) );
  531. if ( dataObj != DATA_NAME && dataSubObj == SUB_LIST && opCode != OP_LIST && opCode != OP_KILL )
  532. return ToolMsg( PCCLIMSG_LIST_LIST_NOT_SPECIFIED, GetOpName(opCode) );
  533. if ( dataObj == DATA_NAME && opCode == OP_UPDATE )
  534. return ToolMsg( PCCLIMSG_ALIAS_VERB_CONFLICT, GetOpName(opCode) );
  535. if ( dataObj == DATA_SERVICE && opCode != OP_LIST && opCode != OP_REP )
  536. return ToolMsg( PCCLIMSG_CONTROL_VERB_CONFLICT, GetOpName(opCode) );
  537. if ( dataObj == DATA_MEDIATOR && opCode != OP_LIST )
  538. return ToolMsg( PCCLIMSG_MEDIATOR_VERB_CONFLICT, GetOpName(opCode) );
  539. //-------------------------------------------------------------------------------------------//
  540. // Connect to the target and quit if fails, else give action description...
  541. if ( _tcscmp( target, oldTarget ) || buffer != oldBuffer ) {
  542. if ( *oldTarget ) PCClose( targId );
  543. ToolMsg( PCCLIMSG_CONNECTING, target, ERROR_SUCCESS, IntToPtr(buffer), IntToPtr(buffer) );
  544. targId = PCOpen( target, NULL, buffer );
  545. if ( !targId ) {
  546. *oldTarget = 0;
  547. oldBuffer = 0;
  548. return ToolMsg( PCCLIMSG_CONNECT_FAILED, target, PCGetLastError( targId ) );
  549. }
  550. ToolMsg( PCCLIMSG_CONNECT_SUCCESS, target );
  551. _tcscpy( oldTarget, target );
  552. oldBuffer = buffer;
  553. if ( PCGetServiceInfo( targId, &sysInfo, sizeof(sysInfo) ) )
  554. ShowSysInfo( sysInfo );
  555. else
  556. ToolMsg( PCCLIMSG_SERVICE_QUERY_FAILED, target, PCGetLastError( targId ) );
  557. }
  558. if ( dataObj == DATA_NAME )
  559. ToolMsg( PCCLIMSG_PERFORMING_ALIAS_OP, GetOpName(opCode), ERROR_SUCCESS,
  560. GetDataName(dataObj, dataSubObj), IntToPtr(index) );
  561. else if ( dataObj == DATA_MEDIATOR )
  562. ToolMsg( PCCLIMSG_PERFORMING_MEDIATOR_OP, pArgCt? *pArgs : TEXT("???") );
  563. else if ( dataObj != DATA_DUMPREST )
  564. ToolMsg( PCCLIMSG_PERFORMING_OTHER_OP, GetOpName(opCode), ERROR_SUCCESS,
  565. GetDataName(dataObj, dataSubObj) );
  566. //-------------------------------------------------------------------------------------------//
  567. // Prepare and perform the requested action...
  568. BOOL rc;
  569. if ( !sepChar ) {
  570. TCHAR sepCharBuf[256];
  571. if ( !LoadString( moduleUs, COLHEAD_SEPARATOR_CHAR, sepCharBuf, ENTRY_COUNT(sepCharBuf) ) )
  572. sepChar = TEXT('-');
  573. else sepChar = sepCharBuf[0];
  574. }
  575. switch ( dataObj ) {
  576. case DATA_GROUP: {
  577. if ( dataSubObj == SUB_DEFS ) {
  578. PCJobSummary grpSummaryEntry;
  579. TCHAR detail[2000], detail2[2000]; // space for detail with variable data too
  580. PCJobDetail *grpDetail = (PCJobDetail *) detail;
  581. grpDetail->vLength = sizeof(detail) - offsetof( PCJobDetail, vLength );
  582. BuildGrpDetail( *grpDetail, pArgs, pArgCt );
  583. if ( !convertError ) switch ( opCode ) {
  584. case OP_REP:
  585. case OP_UPDATE:
  586. memcpy( detail2, detail, sizeof (PCProcDetail) );
  587. if ( PCGetJobDetail( targId, (PCJobDetail *) detail2, sizeof(detail2), &updateCtr ) ) {
  588. if ( opCode == OP_UPDATE ) MergeGroupDetail( *grpDetail, (PCJobDetail &) detail2 );
  589. rc = PCReplJobDetail( targId, grpDetail, updateCtr, getListData? &grpSummaryEntry : NULL );
  590. if ( rc && getListData ) ShowGrpSummary( &grpSummaryEntry, 1 );
  591. }
  592. break;
  593. case OP_ADD:
  594. rc = PCAddJobDetail( targId, grpDetail, getListData? &grpSummaryEntry : NULL );
  595. if ( rc && getListData ) ShowGrpSummary( &grpSummaryEntry, 1 );
  596. break;
  597. case OP_DEL:
  598. PCDeleteJobDetail( targId, grpDetail );
  599. break;
  600. case OP_LIST:
  601. grpDetail->vLength = sizeof(detail) - offsetof( PCJobDetail, vLength );
  602. if ( PCGetJobDetail( targId, grpDetail, sizeof(detail), &updateCtr ) )
  603. ShowGrpDetail( *grpDetail );
  604. break;
  605. } // end switch op code within group data
  606. break;
  607. }
  608. else if ( dataSubObj == SUB_SUMMARY ) {
  609. PCUINT32 totCount = 0, entryCount = buffer / sizeof(PCJobSummary);
  610. PCJobSummary *grpSummary = new PCJobSummary[entryCount];
  611. if ( !grpSummary )
  612. return ToolMsg( PCCLIMSG_NOT_ENOUGH_MEMORY );
  613. BuildGrpSummary( *grpSummary, pArgs, pArgCt, &listFlags );
  614. if ( !convertError ) for ( BOOL moreData = TRUE, isFirst = TRUE; moreData; isFirst = FALSE ) {
  615. PCINT32 count = PCGetJobSummary( targId, grpSummary, entryCount * sizeof(PCJobSummary), listFlags );
  616. moreData = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  617. totCount += count;
  618. if ( count >= 0 ) ShowGrpSummary( grpSummary, count, isFirst, moreData? -1 : totCount );
  619. if ( count > 0 ) _tcsncpy( grpSummary[0].jobName, grpSummary[count - 1].jobName, JOB_NAME_LEN );
  620. }
  621. delete [] grpSummary;
  622. }
  623. // Not an operation on definition or summary so is either kill or list...
  624. else {
  625. if ( opCode == OP_KILL ) {
  626. JOB_NAME groupName;
  627. memset( groupName, 0, sizeof(groupName) );
  628. if ( pArgCt ) _tcsncpy( groupName, *pArgs, JOB_NAME_LEN );
  629. PCKillJob( targId, groupName );
  630. }
  631. // Must be list...
  632. else {
  633. PCUINT32 totCount = 0, entryCount = buffer / sizeof(PCJobListItem);
  634. PCJobListItem *grpListItem = new PCJobListItem[entryCount];
  635. if ( !grpListItem )
  636. return ToolMsg( PCCLIMSG_NOT_ENOUGH_MEMORY );
  637. BuildGrpListItem( *grpListItem, pArgs, pArgCt, &listFlags );
  638. if ( !convertError ) for ( BOOL moreData = TRUE, isFirst = TRUE; moreData; isFirst = FALSE ) {
  639. PCINT32 count = PCGetJobList( targId, grpListItem, entryCount * sizeof(PCJobListItem), listFlags );
  640. moreData = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  641. totCount += count;
  642. if ( count >= 0 ) ShowGrpList( grpListItem, count, isFirst, moreData? -1 : totCount );
  643. if ( count > 0 ) _tcsncpy( grpListItem[0].jobName, grpListItem[--count].jobName, JOB_NAME_LEN );
  644. }
  645. delete [] grpListItem;
  646. }
  647. }
  648. break;
  649. }
  650. //-------------------------------------------------------------------------------------------//
  651. case DATA_PROC: {
  652. if ( dataSubObj == SUB_DEFS ) {
  653. PCProcSummary procSummaryEntry;
  654. TCHAR detail[2000], detail2[2000]; // space for detail with variable data too
  655. PCProcDetail *procDetail = (PCProcDetail *) detail;
  656. procDetail->vLength = sizeof(detail) - offsetof( PCProcDetail, vLength );
  657. BuildProcDetail( *procDetail, pArgs, pArgCt );
  658. if ( !convertError ) switch ( opCode ) {
  659. case OP_REP:
  660. case OP_UPDATE:
  661. memcpy( detail2, detail, sizeof (PCProcDetail) );
  662. if ( PCGetProcDetail( targId, (PCProcDetail *) detail2, sizeof(detail2), &updateCtr ) ) {
  663. if ( opCode == OP_UPDATE ) MergeProcDetail( *procDetail, (PCProcDetail &) detail2 );
  664. BOOL rc = PCReplProcDetail( targId, procDetail, updateCtr, getListData? &procSummaryEntry : NULL );
  665. if ( rc && getListData )
  666. ShowProcSummary( &procSummaryEntry, 1 );
  667. }
  668. break;
  669. case OP_ADD:
  670. if ( getListData )
  671. ShowProcSummary( &procSummaryEntry, PCAddProcDetail( targId, procDetail, &procSummaryEntry ) );
  672. else
  673. PCAddProcDetail( targId, procDetail );
  674. break;
  675. case OP_DEL:
  676. PCDeleteProcDetail( targId, procDetail );
  677. break;
  678. case OP_LIST:
  679. procDetail->vLength = sizeof(detail) - offsetof( PCProcDetail, vLength );
  680. if ( PCGetProcDetail( targId, procDetail, sizeof(detail), &updateCtr ) )
  681. ShowProcDetail( *procDetail );
  682. break;
  683. } // end switch op code within proc data
  684. break;
  685. }
  686. else if ( dataSubObj == SUB_SUMMARY ) {
  687. PCUINT32 totCount = 0, entryCount = buffer / sizeof(PCProcSummary);
  688. PCProcSummary *procSummary = new PCProcSummary[entryCount];
  689. if ( !procSummary )
  690. return ToolMsg( PCCLIMSG_NOT_ENOUGH_MEMORY );
  691. BuildProcSummary( *procSummary, pArgs, pArgCt, &listFlags );
  692. if ( !convertError ) for ( BOOL moreData = TRUE, isFirst = TRUE; moreData; isFirst = FALSE ) {
  693. PCINT32 count = PCGetProcSummary( targId, procSummary, entryCount * sizeof(PCProcSummary), listFlags );
  694. moreData = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  695. totCount += count;
  696. if ( count >= 0 ) ShowProcSummary( procSummary, count, isFirst, moreData? -1 : totCount );
  697. if ( count > 0 ) _tcsncpy( procSummary[0].procName, procSummary[--count].procName, PROC_NAME_LEN );
  698. }
  699. delete [] procSummary;
  700. }
  701. else {
  702. if ( opCode == OP_KILL ) {
  703. PID_VALUE pid = 0;
  704. TIME_VALUE create = 0x777deadfeeb1e777;
  705. if ( pArgCt > 0 ) pid = GetUInteger64( *pArgs++ );
  706. if ( pArgCt > 1 ) create = GetInteger64( *pArgs );
  707. if ( !convertError )
  708. PCKillProcess( targId, pid, create );
  709. }
  710. else {
  711. PCUINT32 totCount = 0, entryCount = buffer / sizeof(PCProcListItem);
  712. PCProcListItem *procListItem = new PCProcListItem[entryCount];
  713. if ( !procListItem )
  714. return ToolMsg( PCCLIMSG_NOT_ENOUGH_MEMORY );
  715. BuildProcListItem( *procListItem, pArgs, pArgCt, &listFlags );
  716. if ( !convertError ) for ( BOOL moreData = TRUE, isFirst = TRUE; moreData; isFirst = FALSE ) {
  717. PCINT32 count = PCGetProcList( targId, procListItem, entryCount * sizeof(PCProcListItem), listFlags );
  718. moreData = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  719. totCount += count;
  720. if ( count >= 0 ) ShowProcList( procListItem, count, isFirst, moreData? -1 : totCount );
  721. if ( count > 0 ) {
  722. _tcsncpy( procListItem[0].procName, procListItem[--count].procName, PROC_NAME_LEN );
  723. procListItem[0].procStats.pid = procListItem[count].procStats.pid;
  724. }
  725. }
  726. delete [] procListItem;
  727. }
  728. }
  729. break;
  730. }
  731. //-------------------------------------------------------------------------------------------//
  732. case DATA_NAME:
  733. // Prime update counter and get buffer full of names, then execute verb...
  734. numRules = PCGetNameRules( targId, nameRules, sizeof(nameRules),
  735. opCode == OP_LIST? index : 0, &updateCtr );
  736. switch ( opCode ) {
  737. case OP_ADD:
  738. case OP_REP: {
  739. PCNameRule newRule;
  740. BuildNameRule( newRule, pArgs, pArgCt );
  741. if ( convertError ) break;
  742. if ( getListData ) {
  743. numRules = (opCode == OP_ADD)?
  744. PCAddNameRule( targId, &newRule, index, updateCtr, nameRules, sizeof(nameRules), 0 ) :
  745. PCReplNameRule( targId, &newRule, index, updateCtr, nameRules, sizeof(nameRules), 0 );
  746. ShowNameRules( nameRules, numRules );
  747. }
  748. else
  749. numRules = (opCode == OP_ADD)?
  750. PCAddNameRule( targId, &newRule, index, updateCtr ) :
  751. PCReplNameRule( targId, &newRule, index, updateCtr );
  752. break;
  753. }
  754. case OP_DEL:
  755. if ( getListData ) {
  756. numRules = PCDeleteNameRule( targId, index, updateCtr, nameRules, sizeof(nameRules), 0 );
  757. ShowNameRules( nameRules, numRules );
  758. }
  759. else
  760. PCDeleteNameRule( targId, index, updateCtr );
  761. break;
  762. case OP_LIST:
  763. ShowNameRules( nameRules, numRules, index );
  764. break;
  765. case OP_SWAP:
  766. if ( getListData ) {
  767. numRules = PCSwapNameRules( targId, index, updateCtr, nameRules, sizeof(nameRules), 0 );
  768. ShowNameRules( nameRules, numRules );
  769. }
  770. else
  771. PCSwapNameRules( targId, index, updateCtr );
  772. break;
  773. } // end switch op code for data names
  774. break;
  775. //-------------------------------------------------------------------------------------------//
  776. case DATA_SERVICE:
  777. switch ( opCode ) {
  778. case OP_REP:
  779. PCSystemParms sysParms;
  780. BuildSystemParms( sysParms, pArgs, pArgCt );
  781. if ( !convertError )
  782. PCSetServiceParms( targId, &sysParms, sizeof(sysInfo) );
  783. break;
  784. case OP_LIST:
  785. if ( PCGetServiceInfo( targId, &sysInfo, sizeof(sysInfo) ) )
  786. ShowSysInfo( sysInfo, FALSE );
  787. break;
  788. } // end switch op code for data names
  789. break;
  790. //-------------------------------------------------------------------------------------------//
  791. case DATA_MEDIATOR:
  792. DoMediatorControl( pArgs, pArgCt );
  793. break;
  794. //-------------------------------------------------------------------------------------------//
  795. case DATA_DUMPREST: // Perform complete dump or restore of data base
  796. int err = DoDumpRestore( adminFile, doDump ); // file already open
  797. fflush( adminFile ); // flush data
  798. if ( !err && ferror( adminFile ) )
  799. err = cFileError( doDump ); // show stream was errored out
  800. fclose( adminFile ); // done with file
  801. if ( err ) {
  802. ToolMsg( PCCLIMSG_DUMP_RESTORE_FAILED );
  803. return err;
  804. }
  805. break;
  806. } // end switch data obj
  807. PCINT32 err = convertError? PCERROR_INVALID_PARAMETER : PCGetLastError( targId );
  808. if ( err )
  809. ToolMsg( PCCLIMSG_REQUEST_FAILED, NULL, err );
  810. else
  811. ToolMsg( PCCLIMSG_REQUEST_SUCCESSFUL );
  812. return err;
  813. }
  814. //-------------------------------------------------------------------------------------------//
  815. static void DoMediatorControl( TCHAR **pArgs, PCUINT32 pArgCt ) {
  816. PCINT32 ctlCmd = PCCFLAG_SIGNATURE;
  817. if ( pArgCt > 0 ) {
  818. if ( !_tcsicmp( *pArgs, TEXT("stop") ) ) ctlCmd |= PCCFLAG_STOP_MEDIATOR; // do not localize
  819. else if ( !_tcsicmp( *pArgs, TEXT("start") ) ) ctlCmd |= PCCFLAG_START_MEDIATOR; // do not localize
  820. else if ( _tcsicmp( *pArgs, TEXT("restart") ) ) { // do not localize
  821. ToolMsg( PCCLIMSG_MEDIATOR_ACTION_UNKNOWN, *pArgs );
  822. return;
  823. }
  824. }
  825. else {
  826. ToolMsg( PCCLIMSG_MEDIATOR_ACTION_MISSING );
  827. return;
  828. }
  829. if ( pArgCt > 1 )
  830. ToolMsg( PCCLIMSG_MEDIATOR_ACTION_IGNORED, *pArgs );
  831. if ( !_tcsicmp( *pArgs, TEXT("restart") ) ) {
  832. if ( !PCControlFunction( targId, ctlCmd | PCCFLAG_STOP_MEDIATOR ) )
  833. ToolMsg( PCCLIMSG_MEDIATOR_CONTROL_ERROR, NULL, PCGetLastError( targId ) );
  834. else {
  835. Sleep( 100 );
  836. if ( !PCControlFunction( targId, ctlCmd | PCCFLAG_START_MEDIATOR ) )
  837. ToolMsg( PCCLIMSG_MEDIATOR_CONTROL_ERROR, NULL, PCGetLastError( targId ) );
  838. }
  839. }
  840. else if ( !PCControlFunction( targId, ctlCmd ) )
  841. ToolMsg( PCCLIMSG_MEDIATOR_CONTROL_ERROR, NULL, PCGetLastError( targId ) );
  842. }
  843. //-------------------------------------------------------------------------------------------//
  844. static void DispDumpComment( FILE *adminFile, PCULONG32 msgID, PCINT32 count ) {
  845. TCHAR *fileCmnt;
  846. if ( !FormatMessage( FORMAT_MESSAGE_FROM_HMODULE + FORMAT_MESSAGE_ARGUMENT_ARRAY +
  847. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  848. NULL, msgID, 0, (TCHAR *) &fileCmnt, 0, (char **) &count ) )
  849. _ftprintf( adminFile, TEXT("-%c <message formatting failed>...\n"), OP_COMMENT );
  850. else {
  851. _ftprintf( adminFile, TEXT("-%c%s"), OP_COMMENT, fileCmnt );
  852. LocalFree( fileCmnt );
  853. }
  854. }
  855. static int cFileError( BOOL dump ) {
  856. _tperror( dump? TEXT("dump file error") : TEXT("restore file error") );
  857. return PCCLIMSG_REQUEST_FAILED;
  858. }
  859. static int DoDumpRestore( FILE *adminFile, BOOL dump ) {
  860. PCNameRule nameRules[100];
  861. PCProcSummary procRules[100];
  862. PCJobSummary grpRules[100];
  863. char detail[8192]; // detail buffer
  864. // Dump operation...
  865. if ( dump ) {
  866. // Dump process alias rules...
  867. DispDumpComment( adminFile, PCCLIMSG_DUMPCOMMENT_BEGIN_ALIASES );
  868. BOOL moreRules = TRUE;
  869. PCINT32 totalRules = 0;
  870. for ( PCINT32 index = 0, numRules; moreRules; index += numRules ) {
  871. numRules = PCGetNameRules( targId, nameRules, sizeof(nameRules), index );
  872. if ( numRules < 0 ) return PCGetLastError( targId );
  873. moreRules = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  874. totalRules += numRules;
  875. for ( PCINT32 i = 0; i < (moreRules? numRules : numRules - 1); ++i ) {
  876. _ftprintf( adminFile, TEXT(" -%c -%c %ld %c \"%s\" \"%s\" \"%s\"\n"),
  877. OP_ADD, DATA_NAME, index + i,
  878. nameRules[i].matchType, nameRules[i].matchString,
  879. nameRules[i].procName, nameRules[i].description );
  880. }
  881. }
  882. DispDumpComment( adminFile, PCCLIMSG_DUMPCOMMENT_END_ALIASES, totalRules - 1 );
  883. if ( ferror( adminFile ) ) return cFileError( dump ); // see if stream was errored out
  884. // Dump group rules...
  885. DispDumpComment( adminFile, PCCLIMSG_DUMPCOMMENT_BEGIN_GROUPS );
  886. moreRules = TRUE;
  887. totalRules = 0;
  888. memset( grpRules, 0, sizeof(grpRules) );
  889. PCJobDetail *grpDet = (PCJobDetail *) detail;
  890. while ( moreRules ) {
  891. memcpy( &grpRules[0], &grpRules[ENTRY_COUNT(grpRules) - 1], sizeof(grpRules[0]) );
  892. numRules = PCGetJobSummary( targId, grpRules, sizeof(grpRules) );
  893. if ( numRules < 0 ) return PCGetLastError( targId );
  894. totalRules += numRules;
  895. moreRules = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  896. for ( PCINT32 i = 0; i < numRules; ++i ) {
  897. memcpy( grpDet, &grpRules[i], sizeof(grpRules[i] ) );
  898. if ( PCGetJobDetail( targId, grpDet, sizeof(detail) ) ) {
  899. _ftprintf( adminFile, TEXT(" -%c -%c%c \"%s\""),
  900. OP_ADD, DATA_GROUP, SUB_DEFS, grpDet->base.jobName );
  901. DumpMgmtParms( grpDet->base.mgmtParms, grpDet->vLength, grpDet->vData );
  902. }
  903. else return PCGetLastError( targId );
  904. }
  905. }
  906. DispDumpComment( adminFile, PCCLIMSG_DUMPCOMMENT_END_GROUPS, totalRules );
  907. if ( ferror( adminFile ) ) return cFileError( dump ); // see if stream was errored out
  908. // Dump process rules...
  909. DispDumpComment( adminFile, PCCLIMSG_DUMPCOMMENT_BEGIN_PROCESSES );
  910. moreRules = TRUE;
  911. totalRules = 0;
  912. memset( procRules, 0, sizeof(procRules) );
  913. PCProcDetail *procDet = (PCProcDetail *) detail;
  914. while ( moreRules ) {
  915. memcpy( &procRules[0], &procRules[ENTRY_COUNT(procRules) - 1], sizeof(procRules[0]) );
  916. numRules = PCGetProcSummary( targId, procRules, sizeof(procRules) );
  917. if ( numRules < 0 ) return PCGetLastError( targId );
  918. totalRules += numRules;
  919. moreRules = PCGetLastError( targId ) == PCERROR_MORE_DATA;
  920. for ( PCINT32 i = 0; i < numRules; ++i ) {
  921. memcpy( procDet, &procRules[i], sizeof(procRules[i] ) );
  922. if ( PCGetProcDetail( targId, procDet, sizeof(detail) ) ) {
  923. _ftprintf( adminFile, TEXT(" -%c -%c%c \"%s\""),
  924. OP_ADD, DATA_PROC, SUB_DEFS, procDet->base.procName );
  925. if ( *procDet->base.memberOfJobName )
  926. _ftprintf( adminFile, TEXT(" -%c \"%s\""), DATA_GROUP, procDet->base.memberOfJobName );
  927. DumpMgmtParms( procDet->base.mgmtParms, procDet->vLength, procDet->vData );
  928. }
  929. else return PCGetLastError( targId );
  930. }
  931. }
  932. DispDumpComment( adminFile, PCCLIMSG_DUMPCOMMENT_END_PROCESSES, totalRules );
  933. if ( ferror( adminFile ) ) return cFileError( dump ); // see if stream was errored out
  934. }
  935. else {
  936. int argct;
  937. BOOL haveCmd;
  938. TCHAR *cmdLine;
  939. PCINT32 ctlCmd = PCCFLAG_SIGNATURE +
  940. PCCFLAG_DELALL_NAME_RULES + PCCFLAG_DELALL_PROC_DEFS + PCCFLAG_DELALL_JOB_DEFS;
  941. if ( !PCControlFunction( targId, ctlCmd ) )
  942. return ToolMsg( PCCLIMSG_RESTORE_CLEAR_ERROR, NULL, PCGetLastError( targId ) );
  943. else {
  944. BOOL saveInteract = interact;
  945. interact = FALSE;
  946. int retCode;
  947. for ( haveCmd = GetNextCommand( adminFile, &cmdLine );
  948. haveCmd;
  949. haveCmd = GetNextCommand( adminFile, &cmdLine ) ) {
  950. if ( ferror( adminFile ) ) return cFileError( dump );
  951. TCHAR **argList = CommandLineToArgvW( cmdLine, &argct );
  952. if ( !**argList ) retCode = DoCommands( argct - 1, argList + 1 );
  953. else retCode = DoCommands( argct, argList );
  954. GlobalFree( argList );
  955. }
  956. interact = saveInteract;
  957. }
  958. }
  959. return ERROR_SUCCESS;
  960. }
  961. static void DumpMgmtParms( MGMT_PARMS &mgt, PCINT16 len, TCHAR *data ) {
  962. TCHAR flags[16];
  963. ShowMgmtFlags( flags, mgt.mFlags, TRUE );
  964. if ( *flags )
  965. _ftprintf( adminFile, TEXT(" -%c %s"), DEF_FLAGS, flags );
  966. if ( mgt.affinity )
  967. _ftprintf( adminFile, TEXT(" -%c 0x%I64x"), DEF_AFF, mgt.affinity );
  968. if ( mgt.priority )
  969. _ftprintf( adminFile, TEXT(" -%c %c"), DEF_PRIO, ShowPriority( mgt.priority ) );
  970. if ( mgt.minWS || mgt.maxWS )
  971. _ftprintf( adminFile, TEXT(" -%c %I64u %I64u"), DEF_WS, mgt.minWS / 1024, mgt.maxWS / 1024 );
  972. if ( mgt.schedClass )
  973. _ftprintf( adminFile, TEXT(" -%c %lu"), DEF_SCHED, mgt.schedClass );
  974. if ( mgt.jobMemoryLimit )
  975. _ftprintf( adminFile, TEXT(" -%c %I64u"), DEF_GROUPMEM, mgt.jobMemoryLimit / 1024 );
  976. if ( mgt.procMemoryLimit )
  977. _ftprintf( adminFile, TEXT(" -%c %I64u"), DEF_PROCMEM, mgt.procMemoryLimit / 1024 );
  978. if ( mgt.jobTimeLimitCNS )
  979. _ftprintf( adminFile, TEXT(" -%c %I64u"), DEF_GROUPTIME, mgt.jobTimeLimitCNS / 10000 );
  980. if ( mgt.procTimeLimitCNS )
  981. _ftprintf( adminFile, TEXT(" -%c %I64u"), DEF_PROCTIME, mgt.procTimeLimitCNS / 10000 );
  982. if ( mgt.procCountLimit )
  983. _ftprintf( adminFile, TEXT(" -%c %lu"), DEF_PROCCOUNT, mgt.procCountLimit );
  984. if ( *mgt.description )
  985. _ftprintf( adminFile, TEXT(" -%c \"%s\""), DEF_DESC, mgt.description );
  986. if ( len )
  987. _ftprintf( adminFile, TEXT(" -%c \"%*s\""), DEF_VARDATA, len / sizeof(TCHAR) - 1, data );
  988. _ftprintf( adminFile, TEXT("\n") );
  989. }
  990. static void InsertTableData( PCTableDef *table, PCULONG32 index, TCHAR *dataItem, BOOL printIt ) {
  991. PCULONG32 leftSkip = 0, dataLen = min( _tcslen( dataItem ), colWidth[index] );
  992. switch ( table[index].justification ) {
  993. case PCCOL_JUST_RIGHT: leftSkip = colWidth[index] - dataLen; break;
  994. case PCCOL_JUST_LEFT: leftSkip = 0; break;
  995. case PCCOL_JUST_CENTER: leftSkip = (colWidth[index] - dataLen) / 2; break;
  996. }
  997. _tcsncpy( rowData + colOffset[index] + leftSkip, dataItem, dataLen );
  998. if ( printIt ) {
  999. rowData[tableWidth] = 0;
  1000. PrintLine( rowData, 1 );
  1001. }
  1002. }
  1003. static void BuildTableHeader( PCTableDef *table, PCULONG32 entries, BOOL printIt ) {
  1004. PCULONG32 leftSkip = 0, widthCol, widthHead, offset = 0;
  1005. wmemset( colHead, SPACE, ENTRY_COUNT(colHead) );
  1006. wmemset( colDash, SPACE, ENTRY_COUNT(colDash) );
  1007. for ( PCULONG32 i = 0; i < entries; ++i ) {
  1008. TCHAR head[512];
  1009. if ( !LoadString( moduleUs,
  1010. gShowFullNames? table[i].longStringID : table[i].shortStringID,
  1011. head, ENTRY_COUNT(head) )
  1012. )
  1013. _tcscpy( head, TEXT("(load-fail)") );
  1014. widthHead = (PCULONG32) _tcslen( head );
  1015. widthCol = max( widthHead, gShowFullNames? table[i].longMinLen : table[i].shortMinLen );
  1016. switch ( table[i].justification ) {
  1017. case PCCOL_JUST_RIGHT: leftSkip = widthCol - widthHead; break;
  1018. case PCCOL_JUST_LEFT: leftSkip = 0; break;
  1019. case PCCOL_JUST_CENTER: leftSkip = (widthCol - widthHead) / 2; break;
  1020. }
  1021. _tcsncpy( colHead + offset + leftSkip, head, widthHead );
  1022. _tcsnset( colDash + offset, sepChar, widthCol );
  1023. colWidth[i] = widthCol;
  1024. colOffset[i] = offset;
  1025. offset += widthCol + 1;
  1026. }
  1027. tableWidth = offset;
  1028. colHead[tableWidth] = 0;
  1029. colDash[tableWidth] = 0;
  1030. if ( printIt ) {
  1031. PrintLine( colHead, 1 );
  1032. PrintLine( colDash, 1 );
  1033. }
  1034. }
  1035. static void ShowNameRules( PCNameRule *rule, PCINT32 count, PCINT32 index ) {
  1036. static PCTableDef aliasTable[] = {
  1037. { COLHEAD_ALIAS_RULE_NUMBER, COLHEAD_ALIAS_RULE_NUMBER, 4, 4, PCCOL_JUST_RIGHT, TEXT("%ld") },
  1038. { COLHEAD_ALIAS_MATCH_TYPE, COLHEAD_ALIAS_MATCH_TYPE, 10, 10, PCCOL_JUST_CENTER, TEXT("%c") },
  1039. { COLHEAD_ALIAS_MATCH_DATA_LONG, COLHEAD_ALIAS_MATCH_DATA_SHORT, MATCH_STRING_LEN, 24, PCCOL_JUST_LEFT, TEXT("%s") },
  1040. { COLHEAD_ALIAS_NAME_LONG, COLHEAD_ALIAS_NAME_SHORT, PROC_NAME_LEN, 21, PCCOL_JUST_LEFT, TEXT("%s") },
  1041. { COLHEAD_ALIAS_DESCRIPTION_LONG,COLHEAD_ALIAS_DESCRIPTION_SHORT, NAME_DESCRIPTION_LEN, 55, PCCOL_JUST_LEFT, TEXT("%s") }
  1042. };
  1043. if ( count < 0 ) return;
  1044. // Build and display table headers (and set global table parameters)...
  1045. BuildTableHeader( aliasTable, ENTRY_COUNT(aliasTable) );
  1046. // Build and display each data row...
  1047. PCINT32 TotRules = 0;
  1048. for ( ;; ) {
  1049. TotRules += count;
  1050. for ( PCINT32 i = 0; i < count; ++i, ++rule ) {
  1051. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1052. // Insert each data item into row...
  1053. for ( PCINT32 j = 0; j < ENTRY_COUNT(aliasTable); ++j ) {
  1054. TCHAR dataItem[256];
  1055. // Get formatted data...
  1056. switch ( j ) {
  1057. case 0: _stprintf( dataItem, aliasTable[j].rowFmt, index + i ); break;
  1058. case 1: _stprintf( dataItem, aliasTable[j].rowFmt, rule->matchType ); break;
  1059. case 2: _stprintf( dataItem, aliasTable[j].rowFmt, rule->matchString ); break;
  1060. case 3: _stprintf( dataItem, aliasTable[j].rowFmt, rule->procName ); break;
  1061. case 4: _stprintf( dataItem, aliasTable[j].rowFmt, rule->description ); break;
  1062. }
  1063. // Insert data into row, print if last item...
  1064. InsertTableData( aliasTable, j, dataItem, j == ENTRY_COUNT(aliasTable) - 1 );
  1065. }
  1066. }
  1067. if ( PCGetLastError( targId ) == PCERROR_MORE_DATA ) {
  1068. index += count;
  1069. rule = nameRules;
  1070. count = PCGetNameRules( targId, nameRules, sizeof(nameRules), index );
  1071. }
  1072. else break;
  1073. }
  1074. // Display table suffix...
  1075. PrintLine( colDash, 1 );
  1076. PrintHelp( HELP_ALIAS, FALSE );
  1077. // Show count of rules retrieved...
  1078. ToolMsg( PCCLIMSG_RETRIEVED_ALIAS_RULES_LIST, TotRules );
  1079. }
  1080. static TCHAR *GetOpName( TCHAR code ) {
  1081. static TCHAR result[128];
  1082. static struct { TCHAR op; PCULONG32 strID; } opNames[] = {
  1083. { OP_ADD, VERB_NAME_ADD },
  1084. { OP_REP, VERB_NAME_REPLACE },
  1085. { OP_DEL, VERB_NAME_DELETE },
  1086. { OP_SWAP, VERB_NAME_SWAP },
  1087. { OP_LIST, VERB_NAME_LIST },
  1088. { OP_UPDATE, VERB_NAME_UPDATE },
  1089. { OP_KILL, VERB_NAME_KILL },
  1090. { TEXT(';'), VERB_NAME_DUMP },
  1091. { TEXT(':'), VERB_NAME_RESTORE },
  1092. };
  1093. for ( PCUINT32 i = 0; i < ENTRY_COUNT(opNames) && code != opNames[i].op; ++i ) ;
  1094. if ( i >= ENTRY_COUNT(opNames) || !LoadString( moduleUs, opNames[i].strID, result, ENTRY_COUNT(result) ) )
  1095. _tcscpy( result, TEXT("<err>") );
  1096. return result;
  1097. }
  1098. static TCHAR *GetDataName( TCHAR code, TCHAR subCode ) {
  1099. static TCHAR result[128];
  1100. static struct { TCHAR op; PCULONG32 strID; } dNames[] = {
  1101. { DATA_NAME, DATA_NAME_ALIAS },
  1102. { DATA_GROUP, DATA_NAME_GROUP },
  1103. { DATA_PROC, DATA_NAME_PROCESS },
  1104. { DATA_SERVICE, DATA_NAME_VERSION },
  1105. { DATA_MEDIATOR,DATA_NAME_MEDIATOR },
  1106. { TEXT(';'), DATA_NAME_PROCCON },
  1107. };
  1108. for ( PCUINT32 i = 0; i < ENTRY_COUNT(dNames) && code != dNames[i].op; ++i ) ;
  1109. if ( i >= ENTRY_COUNT(dNames) || !LoadString( moduleUs, dNames[i].strID, result, ENTRY_COUNT(result) ) )
  1110. _tcscpy( result, TEXT("<err>") );
  1111. else {
  1112. _tcscat( result, TEXT(" ") );
  1113. _tcscat( result, GetDataSubName( subCode ) );
  1114. }
  1115. return result;
  1116. }
  1117. static TCHAR *GetDataSubName( TCHAR code ) {
  1118. static TCHAR result[128];
  1119. static struct { TCHAR op; PCULONG32 strID; } sNames[] = {
  1120. { SUB_DEFS, SUBDATA_NAME_DEFINITION },
  1121. { SUB_SUMMARY, SUBDATA_NAME_SUMMARY },
  1122. { SUB_LIST, SUBDATA_NAME_LIST },
  1123. { TEXT(';'), SUBDATA_NAME_PROCCON_DATA },
  1124. };
  1125. for ( PCUINT32 i = 0; i < ENTRY_COUNT(sNames) && code != sNames[i].op; ++i ) ;
  1126. if ( i >= ENTRY_COUNT(sNames) )
  1127. _tcscpy( result, TEXT("") );
  1128. else if ( !LoadString( moduleUs, sNames[i].strID, result, ENTRY_COUNT(result) ) )
  1129. _tcscpy( result, TEXT("<err>") );
  1130. return result;
  1131. }
  1132. static void ShowListFlags( PC_LIST_FLAGS flags, TCHAR out[8] ) {
  1133. for ( PCUINT32 i = 0; i < 6; ++i ) out[i] = TEXT('.');
  1134. out[6] = 0;
  1135. if ( flags & PCLFLAG_IS_RUNNING ) out[0] = TEXT('R');
  1136. if ( flags & PCLFLAG_IS_DEFINED ) out[1] = TEXT('D');
  1137. if ( flags & PCLFLAG_IS_MANAGED ) out[2] = TEXT('M');
  1138. if ( flags & PCLFLAG_HAS_NAME_RULE ) out[3] = TEXT('N');
  1139. if ( flags & PCLFLAG_HAS_MEMBER_OF_JOB ) out[4] = TEXT('G');
  1140. if ( flags & PCLFLAG_IS_IN_A_JOB ) out[5] = TEXT('I');
  1141. }
  1142. static void FormatTime( TCHAR *str, int strLen, TIME_VALUE time )
  1143. {
  1144. SYSTEMTIME systime, localsystime;
  1145. if ( FileTimeToSystemTime( (FILETIME *) &time, &systime ) &&
  1146. SystemTimeToTzSpecificLocalTime( NULL, &systime, &localsystime ) ) {
  1147. int len = GetDateFormat( LOCALE_USER_DEFAULT, 0, &localsystime, NULL, str, strLen - 1 );
  1148. if ( len ) {
  1149. str[len - 1 ] = SPACE;
  1150. GetTimeFormat( LOCALE_USER_DEFAULT, 0, &localsystime, NULL, &str[len], strLen - len - 1);
  1151. }
  1152. }
  1153. else
  1154. str[0] = 0;
  1155. }
  1156. static void ShowProcList( PCProcListItem *list, PCINT32 count, BOOL isFirst, int totcnt ) {
  1157. static PCTableDef procTable[] = {
  1158. { COLHEAD_PROCLIST_FLAGS, COLHEAD_PROCLIST_FLAGS, 6, 6, PCCOL_JUST_LEFT, TEXT("%s") },
  1159. { COLHEAD_PROCLIST_PID, COLHEAD_PROCLIST_PID, 5, 5, PCCOL_JUST_RIGHT, TEXT("%.0I64u") },
  1160. { COLHEAD_PROCLIST_PROCESS_ALIAS_LONG, COLHEAD_PROCLIST_PROCESS_ALIAS_SHORT, PROC_NAME_LEN, 20, PCCOL_JUST_LEFT, TEXT("%s") },
  1161. { COLHEAD_PROCLIST_IMAGE_NAME_LONG, COLHEAD_PROCLIST_IMAGE_NAME_SHORT, IMAGE_NAME_LEN, 16, PCCOL_JUST_LEFT, TEXT("%s") },
  1162. { COLHEAD_PROCLIST_MEMBER_OF_GROUP_LONG,COLHEAD_PROCLIST_MEMBER_OF_GROUP_SHORT, JOB_NAME_LEN, 16, PCCOL_JUST_LEFT, TEXT("%s") },
  1163. { COLHEAD_PROCLIST_PRIORITY, COLHEAD_PROCLIST_PRIORITY, 3, 3, PCCOL_JUST_CENTER,TEXT("%c") },
  1164. { COLHEAD_PROCLIST_AFFINITY, COLHEAD_PROCLIST_AFFINITY, 18, 18, PCCOL_JUST_CENTER,TEXT("0x%016I64x") },
  1165. { COLHEAD_PROCLIST_USER_TIME, COLHEAD_PROCLIST_USER_TIME, 9, 9, PCCOL_JUST_RIGHT, TEXT("%I64d") },
  1166. { COLHEAD_PROCLIST_KERNEL_TIME, COLHEAD_PROCLIST_KERNEL_TIME, 9, 9, PCCOL_JUST_RIGHT, TEXT("%I64d") },
  1167. { COLHEAD_PROCLIST_CREATE_TIME, COLHEAD_PROCLIST_CREATE_TIME, 23, 23, PCCOL_JUST_LEFT, TEXT("%s") },
  1168. };
  1169. if ( count < 0 ) return;
  1170. if ( isFirst )
  1171. BuildTableHeader( procTable, ENTRY_COUNT(procTable) );
  1172. TCHAR flags[8], fmtCreateTime[512];
  1173. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1174. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1175. if ( gShowFmtProcTime && list->procStats.createTime )
  1176. FormatTime( fmtCreateTime, ENTRY_COUNT(fmtCreateTime), list->procStats.createTime );
  1177. else if ( list->procStats.createTime )
  1178. _stprintf( fmtCreateTime, TEXT("%I64d"), list->procStats.createTime );
  1179. else
  1180. _stprintf( fmtCreateTime, TEXT(" ") );
  1181. ShowListFlags( list->lFlags, flags );
  1182. // Insert each data item into row...
  1183. PCINT32 lastRow = (list->lFlags & PCLFLAG_IS_RUNNING) ? ENTRY_COUNT(procTable) : 3;
  1184. for ( PCINT32 j = 0; j < lastRow; ++j ) {
  1185. TCHAR dataItem[256];
  1186. // Get formatted data...
  1187. switch ( j ) {
  1188. case 0: _stprintf( dataItem, procTable[j].rowFmt, flags ); break;
  1189. case 1: _stprintf( dataItem, procTable[j].rowFmt, list->procStats.pid ); break;
  1190. case 2: _stprintf( dataItem, procTable[j].rowFmt, list->procName ); break;
  1191. case 3: _stprintf( dataItem, procTable[j].rowFmt, list->imageName ); break;
  1192. case 4: _stprintf( dataItem, procTable[j].rowFmt, list->jobName ); break;
  1193. case 5: _stprintf( dataItem, procTable[j].rowFmt, ShowPriority( list->actualPriority ) ); break;
  1194. case 6: _stprintf( dataItem, procTable[j].rowFmt, list->actualAffinity ); break;
  1195. case 7: _stprintf( dataItem, procTable[j].rowFmt, list->procStats.TotalUserTime / 10000 ); break;
  1196. case 8: _stprintf( dataItem, procTable[j].rowFmt, list->procStats.TotalKernelTime / 10000 ); break;
  1197. case 9: _stprintf( dataItem, procTable[j].rowFmt, fmtCreateTime ); break;
  1198. }
  1199. // Insert data into row, print if last item...
  1200. InsertTableData( procTable, j, dataItem, j == lastRow - 1 );
  1201. }
  1202. }
  1203. // Display table suffix...
  1204. if ( totcnt >= 0 ) {
  1205. PrintLine( colDash, 1 );
  1206. PrintHelp( HELP_LIST, FALSE );
  1207. ToolMsg( PCCLIMSG_RETRIEVED_PROCESS_LIST, totcnt );
  1208. }
  1209. }
  1210. static void ShowGrpList( PCJobListItem *list, PCINT32 count, BOOL isFirst, int totcnt ) {
  1211. if ( count < 0 ) return;
  1212. if ( gListShowBase ) {
  1213. PrintLine( NULL, 1 );
  1214. ShowGrpListWithBase( list, count, isFirst );
  1215. if ( totcnt >= 0 ) PrintLine( colDash, 1 );
  1216. }
  1217. if ( gListShowIO ) {
  1218. PrintLine( NULL, 1 );
  1219. ShowGrpListWithIo( list, count, isFirst );
  1220. if ( totcnt >= 0 ) PrintLine( colDash, 1 );
  1221. }
  1222. if ( gListShowMem ) {
  1223. PrintLine( NULL, 1 );
  1224. ShowGrpListWithMem( list, count, isFirst );
  1225. if ( totcnt >= 0 ) PrintLine( colDash, 1 );
  1226. }
  1227. if ( gListShowProc ) {
  1228. PrintLine( NULL, 1 );
  1229. ShowGrpListWithProc( list, count, isFirst );
  1230. if ( totcnt >= 0 ) PrintLine( colDash, 1 );
  1231. }
  1232. if ( gListShowTime ) {
  1233. PrintLine( NULL, 1 );
  1234. ShowGrpListWithTime( list, count, isFirst );
  1235. if ( totcnt >= 0 ) PrintLine( colDash, 1 );
  1236. }
  1237. if ( totcnt >= 0 ) {
  1238. PrintHelp( HELP_LIST );
  1239. ToolMsg( PCCLIMSG_RETRIEVED_GROUP_LIST, totcnt );
  1240. }
  1241. }
  1242. static void ShowGrpListWithBase( PCJobListItem *list, PCINT32 count, BOOL isFirst ) {
  1243. static PCTableDef baseProcTable[] = {
  1244. { COLHEAD_BASEPROCDATA_FLAGS, COLHEAD_BASEPROCDATA_FLAGS, 8, 8, PCCOL_JUST_LEFT, TEXT("%s") },
  1245. { COLHEAD_BASEPROCDATA_GROUP_NAME_LONG, COLHEAD_BASEPROCDATA_GROUP_NAME_SHORT, JOB_NAME_LEN, 34, PCCOL_JUST_LEFT, TEXT("%s") },
  1246. { COLHEAD_BASEPROCDATA_PRIORITY, COLHEAD_BASEPROCDATA_PRIORITY, 8, 8, PCCOL_JUST_CENTER,TEXT("%c") },
  1247. { COLHEAD_BASEPROCDATA_AFFINITY, COLHEAD_BASEPROCDATA_AFFINITY, 18, 18, PCCOL_JUST_CENTER,TEXT("0x%016I64x") },
  1248. { COLHEAD_BASEPROCDATA_SCHED_CLASS, COLHEAD_BASEPROCDATA_SCHED_CLASS, 9, 9, PCCOL_JUST_CENTER,TEXT("%lu") },
  1249. };
  1250. if ( isFirst )
  1251. BuildTableHeader( baseProcTable, ENTRY_COUNT(baseProcTable) );
  1252. TCHAR flags[8];
  1253. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1254. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1255. ShowListFlags( list->lFlags, flags );
  1256. // Insert each data item into row...
  1257. PCINT32 lastRow = (list->lFlags & PCLFLAG_IS_RUNNING) ? ENTRY_COUNT(baseProcTable) : 2;
  1258. for ( PCINT32 j = 0; j < lastRow; ++j ) {
  1259. TCHAR dataItem[256];
  1260. // Get formatted data...
  1261. switch ( j ) {
  1262. case 0: _stprintf( dataItem, baseProcTable[j].rowFmt, flags ); break;
  1263. case 1: _stprintf( dataItem, baseProcTable[j].rowFmt, list->jobName ); break;
  1264. case 2: _stprintf( dataItem, baseProcTable[j].rowFmt, ShowPriority( list->actualPriority ) ); break;
  1265. case 3: _stprintf( dataItem, baseProcTable[j].rowFmt, list->actualAffinity ); break;
  1266. case 4: _stprintf( dataItem, baseProcTable[j].rowFmt, list->actualSchedClass ); break;
  1267. }
  1268. // Insert data into row, print if last item...
  1269. InsertTableData( baseProcTable, j, dataItem, j == lastRow - 1 );
  1270. }
  1271. }
  1272. }
  1273. static void ShowGrpListWithIo( PCJobListItem *list, PCINT32 count, BOOL isFirst ) {
  1274. static PCTableDef ioProcTable[] = {
  1275. { COLHEAD_BASEPROCDATA_FLAGS, COLHEAD_BASEPROCDATA_FLAGS, 8, 8, PCCOL_JUST_LEFT, TEXT("%s") },
  1276. { COLHEAD_BASEPROCDATA_GROUP_NAME_LONG, COLHEAD_BASEPROCDATA_GROUP_NAME_SHORT, JOB_NAME_LEN, 34, PCCOL_JUST_LEFT, TEXT("%s") },
  1277. { COLHEAD_IO_PROCDATA_READ_OPS, COLHEAD_IO_PROCDATA_READ_OPS, 8, 8, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1278. { COLHEAD_IO_PROCDATA_WRITE_OPS, COLHEAD_IO_PROCDATA_WRITE_OPS, 8, 8, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1279. { COLHEAD_IO_PROCDATA_OTHER_OPS, COLHEAD_IO_PROCDATA_OTHER_OPS, 8, 8, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1280. { COLHEAD_IO_PROCDATA_READ_BYTES, COLHEAD_IO_PROCDATA_READ_BYTES, 10, 10, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1281. { COLHEAD_IO_PROCDATA_WRITE_BYTES, COLHEAD_IO_PROCDATA_WRITE_BYTES, 10, 10, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1282. { COLHEAD_IO_PROCDATA_OTHER_BYTES, COLHEAD_IO_PROCDATA_OTHER_BYTES, 10, 10, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1283. };
  1284. if ( isFirst )
  1285. BuildTableHeader( ioProcTable, ENTRY_COUNT(ioProcTable) );
  1286. TCHAR flags[8];
  1287. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1288. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1289. ShowListFlags( list->lFlags, flags );
  1290. // Insert each data item into row...
  1291. PCINT32 lastRow = (list->lFlags & PCLFLAG_IS_RUNNING) ? ENTRY_COUNT(ioProcTable) : 2;
  1292. for ( PCINT32 j = 0; j < lastRow; ++j ) {
  1293. TCHAR dataItem[256];
  1294. // Get formatted data...
  1295. switch ( j ) {
  1296. case 0: _stprintf( dataItem, ioProcTable[j].rowFmt, flags ); break;
  1297. case 1: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobName ); break;
  1298. case 2: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobStats.ReadOperationCount ); break;
  1299. case 3: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobStats.WriteOperationCount ); break;
  1300. case 4: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobStats.OtherOperationCount ); break;
  1301. case 5: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobStats.ReadTransferCount ); break;
  1302. case 6: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobStats.WriteTransferCount ); break;
  1303. case 7: _stprintf( dataItem, ioProcTable[j].rowFmt, list->jobStats.OtherTransferCount ); break;
  1304. }
  1305. // Insert data into row, print if last item...
  1306. InsertTableData( ioProcTable, j, dataItem, j == lastRow - 1 );
  1307. }
  1308. }
  1309. }
  1310. static void ShowGrpListWithMem( PCJobListItem *list, PCINT32 count, BOOL isFirst ) {
  1311. static PCTableDef memProcTable[] = {
  1312. { COLHEAD_BASEPROCDATA_FLAGS, COLHEAD_BASEPROCDATA_FLAGS, 8, 8, PCCOL_JUST_LEFT, TEXT("%s") },
  1313. { COLHEAD_BASEPROCDATA_GROUP_NAME_LONG, COLHEAD_BASEPROCDATA_GROUP_NAME_SHORT, JOB_NAME_LEN, 34, PCCOL_JUST_LEFT, TEXT("%s") },
  1314. { COLHEAD_MEM_PROCDATA_PAGE_FAULTS, COLHEAD_MEM_PROCDATA_PAGE_FAULTS, 12, 12, PCCOL_JUST_RIGHT, TEXT("%lu") },
  1315. { COLHEAD_MEM_PROCDATA_PEAK_PROC, COLHEAD_MEM_PROCDATA_PEAK_PROC, 18, 18, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1316. { COLHEAD_MEM_PROCDATA_PEAK_GROUP, COLHEAD_MEM_PROCDATA_PEAK_GROUP, 18, 18, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1317. };
  1318. if ( isFirst )
  1319. BuildTableHeader( memProcTable, ENTRY_COUNT(memProcTable) );
  1320. TCHAR flags[8];
  1321. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1322. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1323. ShowListFlags( list->lFlags, flags );
  1324. // Insert each data item into row...
  1325. PCINT32 lastRow = (list->lFlags & PCLFLAG_IS_RUNNING) ? ENTRY_COUNT(memProcTable) : 2;
  1326. for ( PCINT32 j = 0; j < lastRow; ++j ) {
  1327. TCHAR dataItem[256];
  1328. // Get formatted data...
  1329. switch ( j ) {
  1330. case 0: _stprintf( dataItem, memProcTable[j].rowFmt, flags ); break;
  1331. case 1: _stprintf( dataItem, memProcTable[j].rowFmt, list->jobName ); break;
  1332. case 2: _stprintf( dataItem, memProcTable[j].rowFmt, list->jobStats.ReadOperationCount ); break;
  1333. case 3: _stprintf( dataItem, memProcTable[j].rowFmt, list->jobStats.WriteOperationCount ); break;
  1334. case 4: _stprintf( dataItem, memProcTable[j].rowFmt, list->jobStats.OtherOperationCount ); break;
  1335. }
  1336. // Insert data into row, print if last item...
  1337. InsertTableData( memProcTable, j, dataItem, j == lastRow - 1 );
  1338. }
  1339. }
  1340. }
  1341. static void ShowGrpListWithProc( PCJobListItem *list, PCINT32 count, BOOL isFirst ) {
  1342. static PCTableDef procProcTable[] = {
  1343. { COLHEAD_BASEPROCDATA_FLAGS, COLHEAD_BASEPROCDATA_FLAGS, 8, 8, PCCOL_JUST_LEFT, TEXT("%s") },
  1344. { COLHEAD_BASEPROCDATA_GROUP_NAME_LONG, COLHEAD_BASEPROCDATA_GROUP_NAME_SHORT, JOB_NAME_LEN, 34, PCCOL_JUST_LEFT, TEXT("%s") },
  1345. { COLHEAD_PROC_PROCDATA_CURR_PROCS, COLHEAD_PROC_PROCDATA_CURR_PROCS, 12, 12, PCCOL_JUST_RIGHT, TEXT("%lu") },
  1346. { COLHEAD_PROC_PROCDATA_TERM_PROCS, COLHEAD_PROC_PROCDATA_TERM_PROCS, 12, 12, PCCOL_JUST_RIGHT, TEXT("%lu") },
  1347. { COLHEAD_PROC_PROCDATA_TOTAL_PROCS, COLHEAD_PROC_PROCDATA_TOTAL_PROCS, 12, 12, PCCOL_JUST_RIGHT, TEXT("%lu") },
  1348. };
  1349. if ( isFirst )
  1350. BuildTableHeader( procProcTable, ENTRY_COUNT(procProcTable) );
  1351. TCHAR flags[8];
  1352. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1353. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1354. ShowListFlags( list->lFlags, flags );
  1355. // Insert each data item into row...
  1356. PCINT32 lastRow = (list->lFlags & PCLFLAG_IS_RUNNING) ? ENTRY_COUNT(procProcTable) : 2;
  1357. for ( PCINT32 j = 0; j < lastRow; ++j ) {
  1358. TCHAR dataItem[256];
  1359. // Get formatted data...
  1360. switch ( j ) {
  1361. case 0: _stprintf( dataItem, procProcTable[j].rowFmt, flags ); break;
  1362. case 1: _stprintf( dataItem, procProcTable[j].rowFmt, list->jobName ); break;
  1363. case 2: _stprintf( dataItem, procProcTable[j].rowFmt, list->jobStats.ActiveProcesses ); break;
  1364. case 3: _stprintf( dataItem, procProcTable[j].rowFmt, list->jobStats.TotalTerminatedProcesses ); break;
  1365. case 4: _stprintf( dataItem, procProcTable[j].rowFmt, list->jobStats.TotalProcesses ); break;
  1366. }
  1367. // Insert data into row, print if last item...
  1368. InsertTableData( procProcTable, j, dataItem, j == lastRow - 1 );
  1369. }
  1370. }
  1371. }
  1372. static void ShowGrpListWithTime( PCJobListItem *list, PCINT32 count, BOOL isFirst ) {
  1373. static PCTableDef timeProcTable[] = {
  1374. { COLHEAD_BASEPROCDATA_FLAGS, COLHEAD_BASEPROCDATA_FLAGS, 8, 8, PCCOL_JUST_LEFT, TEXT("%s") },
  1375. { COLHEAD_BASEPROCDATA_GROUP_NAME_LONG, COLHEAD_BASEPROCDATA_GROUP_NAME_SHORT, JOB_NAME_LEN, 34, PCCOL_JUST_LEFT, TEXT("%s") },
  1376. { COLHEAD_TIME_PROCDATA_USER_TIME, COLHEAD_TIME_PROCDATA_USER_TIME, 12, 12, PCCOL_JUST_RIGHT, TEXT("%I64d") },
  1377. { COLHEAD_TIME_PROCDATA_KERNEL_TIME, COLHEAD_TIME_PROCDATA_KERNEL_TIME, 12, 12, PCCOL_JUST_RIGHT, TEXT("%I64d") },
  1378. { COLHEAD_TIME_PROCDATA_USER_INTVL, COLHEAD_TIME_PROCDATA_USER_INTVL, 12, 12, PCCOL_JUST_RIGHT, TEXT("%I64d") },
  1379. { COLHEAD_TIME_PROCDATA_KERNEL_INTVL, COLHEAD_TIME_PROCDATA_KERNEL_INTVL, 12, 12, PCCOL_JUST_RIGHT, TEXT("%I64d") },
  1380. };
  1381. if ( isFirst )
  1382. BuildTableHeader( timeProcTable, ENTRY_COUNT(timeProcTable) );
  1383. TCHAR flags[8];
  1384. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1385. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1386. ShowListFlags( list->lFlags, flags );
  1387. // Insert each data item into row...
  1388. PCINT32 lastRow = (list->lFlags & PCLFLAG_IS_RUNNING) ? ENTRY_COUNT(timeProcTable) : 2;
  1389. for ( PCINT32 j = 0; j < lastRow; ++j ) {
  1390. TCHAR dataItem[256];
  1391. // Get formatted data...
  1392. switch ( j ) {
  1393. case 0: _stprintf( dataItem, timeProcTable[j].rowFmt, flags ); break;
  1394. case 1: _stprintf( dataItem, timeProcTable[j].rowFmt, list->jobName ); break;
  1395. case 2: _stprintf( dataItem, timeProcTable[j].rowFmt, list->jobStats.TotalUserTime / 10000 ); break;
  1396. case 3: _stprintf( dataItem, timeProcTable[j].rowFmt, list->jobStats.TotalKernelTime / 10000 ); break;
  1397. case 4: _stprintf( dataItem, timeProcTable[j].rowFmt, list->jobStats.ThisPeriodTotalUserTime / 10000 ); break;
  1398. case 5: _stprintf( dataItem, timeProcTable[j].rowFmt, list->jobStats.ThisPeriodTotalKernelTime / 10000 ); break;
  1399. }
  1400. // Insert data into row, print if last item...
  1401. InsertTableData( timeProcTable, j, dataItem, j == lastRow - 1 );
  1402. }
  1403. }
  1404. }
  1405. static void ShowGrpSummary( PCJobSummary *list, PCINT32 count, BOOL isFirst, int totcnt ) {
  1406. static PCTableDef grpSummTable[] = {
  1407. { COLHEAD_GRPSUMMARY_GRPNAME_LONG, COLHEAD_GRPSUMMARY_GRPNAME_SHORT, JOB_NAME_LEN, 20, PCCOL_JUST_LEFT, TEXT("%s") },
  1408. { COLHEAD_GRPSUMMARY_FLAGS, COLHEAD_GRPSUMMARY_FLAGS, 15, 15, PCCOL_JUST_LEFT, TEXT("%s") },
  1409. { COLHEAD_GRPSUMMARY_AFFINITY, COLHEAD_GRPSUMMARY_AFFINITY, 18, 18, PCCOL_JUST_CENTER, TEXT("0x%016I64x") },
  1410. { COLHEAD_GRPSUMMARY_PRIORITY, COLHEAD_GRPSUMMARY_PRIORITY, 3, 3, PCCOL_JUST_CENTER, TEXT("%c") },
  1411. { COLHEAD_GRPSUMMARY_SCHDCLASS, COLHEAD_GRPSUMMARY_SCHDCLASS, 4, 4, PCCOL_JUST_CENTER, TEXT("%lu") },
  1412. { COLHEAD_GRPSUMMARY_PROCESS_MEMORY, COLHEAD_GRPSUMMARY_PROCESS_MEMORY, 9, 9, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1413. { COLHEAD_GRPSUMMARY_GROUP_MEMORY, COLHEAD_GRPSUMMARY_GROUP_MEMORY, 9, 9, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1414. { COLHEAD_GRPSUMMARY_PROCESS_TIME, COLHEAD_GRPSUMMARY_PROCESS_TIME, 11, 11, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1415. { COLHEAD_GRPSUMMARY_GROUP_TIME, COLHEAD_GRPSUMMARY_GROUP_TIME, 11, 11, PCCOL_JUST_RIGHT, TEXT("%I64u") },
  1416. { COLHEAD_GRPSUMMARY_PROCESS_COUNT, COLHEAD_GRPSUMMARY_PROCESS_COUNT, 12, 12, PCCOL_JUST_RIGHT, TEXT("%u") },
  1417. { COLHEAD_GRPSUMMARY_WORKSET_MIN, COLHEAD_GRPSUMMARY_WORKSET_MIN, 7, 7, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1418. { COLHEAD_GRPSUMMARY_WORKSET_MAX, COLHEAD_GRPSUMMARY_WORKSET_MAX, 7, 7, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1419. };
  1420. if ( count < 0 ) return;
  1421. if ( isFirst )
  1422. BuildTableHeader( grpSummTable, ENTRY_COUNT(grpSummTable) );
  1423. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1424. // Clear and insert group name into row...
  1425. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1426. InsertTableData( grpSummTable, 0, list->jobName, FALSE );
  1427. // Add remining group summary data items...
  1428. ShowMgmtParmsAsList( grpSummTable, ENTRY_COUNT(grpSummTable), 1, list->mgmtParms, TRUE );
  1429. }
  1430. if ( totcnt >= 0 ) {
  1431. PrintLine( colDash, 1 );
  1432. PrintHelp( HELP_MGMT );
  1433. ToolMsg( PCCLIMSG_RETRIEVED_GROUP_SUMMARY_LIST, totcnt );
  1434. }
  1435. }
  1436. static void ShowProcSummary( PCProcSummary *list, PCINT32 count, BOOL isFirst, int totcnt ) {
  1437. static PCTableDef procSummTable[] = {
  1438. { COLHEAD_PROCSUMMARY_PROCNAME_LONG, COLHEAD_PROCSUMMARY_PROCNAME_SHORT, PROC_NAME_LEN, 21, PCCOL_JUST_LEFT, TEXT("%s") },
  1439. { COLHEAD_PROCSUMMARY_GRPNAME_LONG, COLHEAD_PROCSUMMARY_GRPNAME_SHORT, JOB_NAME_LEN, 20, PCCOL_JUST_LEFT, TEXT("%s") },
  1440. { COLHEAD_PROCSUMMARY_FLAGS, COLHEAD_PROCSUMMARY_FLAGS, 15, 15, PCCOL_JUST_LEFT, TEXT("%s") },
  1441. { COLHEAD_PROCSUMMARY_AFFINITY, COLHEAD_PROCSUMMARY_AFFINITY, 18, 18, PCCOL_JUST_CENTER, TEXT("0x%016I64x") },
  1442. { COLHEAD_PROCSUMMARY_PRIORITY, COLHEAD_PROCSUMMARY_PRIORITY, 3, 3, PCCOL_JUST_CENTER, TEXT("%c") },
  1443. { COLHEAD_PROCSUMMARY_WORKSET_MIN, COLHEAD_PROCSUMMARY_WORKSET_MIN, 7, 7, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1444. { COLHEAD_PROCSUMMARY_WORKSET_MAX, COLHEAD_PROCSUMMARY_WORKSET_MAX, 7, 7, PCCOL_JUST_RIGHT, TEXT("%I64uK") },
  1445. };
  1446. if ( count < 0 ) return;
  1447. if ( isFirst )
  1448. BuildTableHeader( procSummTable, ENTRY_COUNT(procSummTable) );
  1449. for ( PCINT32 i = 0; i < count; ++i, ++list ) {
  1450. // Clear and insert process and group names into row...
  1451. wmemset( rowData, SPACE, ENTRY_COUNT(rowData) );
  1452. InsertTableData( procSummTable, 0, list->procName, FALSE );
  1453. InsertTableData( procSummTable, 1, list->memberOfJobName, FALSE );
  1454. // Add remining group summary data items...
  1455. ShowMgmtParmsAsList( procSummTable, ENTRY_COUNT(procSummTable), 2, list->mgmtParms, FALSE );
  1456. }
  1457. if ( totcnt >= 0 ) {
  1458. PrintLine( colDash, 1 );
  1459. PrintHelp( HELP_MGMT, FALSE, PCCLIMSG_NOTE_PROCESS_RULES_MAY_NOT_APPLY );
  1460. ToolMsg( PCCLIMSG_RETRIEVED_PROCESS_SUMMARY_LIST, totcnt );
  1461. }
  1462. }
  1463. static void ShowMgmtParmsAsList( PCTableDef *table,
  1464. PCULONG32 entries,
  1465. PCULONG32 first,
  1466. MGMT_PARMS &parm,
  1467. BOOL isGrp ) {
  1468. TCHAR flags[16], dataItem[256];
  1469. ShowMgmtFlags( flags, parm.mFlags );
  1470. for ( PCULONG32 j = first; j < entries; ++j ) {
  1471. // Get formatted data...
  1472. if ( isGrp ) switch ( j ) {
  1473. case 1: _stprintf( dataItem, table[j].rowFmt, flags ); break;
  1474. case 2: _stprintf( dataItem, table[j].rowFmt, parm.affinity ); break;
  1475. case 3: _stprintf( dataItem, table[j].rowFmt, ShowPriority( parm.priority ) ); break;
  1476. case 4: _stprintf( dataItem, table[j].rowFmt, parm.schedClass ); break;
  1477. case 5: _stprintf( dataItem, table[j].rowFmt, parm.procMemoryLimit / 1024 ); break;
  1478. case 6: _stprintf( dataItem, table[j].rowFmt, parm.jobMemoryLimit / 1024 ); break;
  1479. case 7: _stprintf( dataItem, table[j].rowFmt, parm.procTimeLimitCNS / 10000 ); break;
  1480. case 8: _stprintf( dataItem, table[j].rowFmt, parm.jobTimeLimitCNS / 10000 ); break;
  1481. case 9: _stprintf( dataItem, table[j].rowFmt, parm.procCountLimit ); break;
  1482. case 10:_stprintf( dataItem, table[j].rowFmt, parm.minWS / 1024 ); break;
  1483. case 11:_stprintf( dataItem, table[j].rowFmt, parm.maxWS / 1024 ); break;
  1484. }
  1485. else switch (j ) {
  1486. case 2: _stprintf( dataItem, table[j].rowFmt, flags ); break;
  1487. case 3: _stprintf( dataItem, table[j].rowFmt, parm.affinity ); break;
  1488. case 4: _stprintf( dataItem, table[j].rowFmt, ShowPriority( parm.priority ) ); break;
  1489. case 5: _stprintf( dataItem, table[j].rowFmt, parm.minWS / 1024 ); break;
  1490. case 6: _stprintf( dataItem, table[j].rowFmt, parm.maxWS / 1024 ); break;
  1491. }
  1492. // Insert data into row, print if last item...
  1493. InsertTableData( table, j, dataItem, j == entries - 1 );
  1494. }
  1495. }
  1496. static void ShowGrpDetail( PCJobDetail &grpDetail ) {
  1497. ToolMsg( PCCLIMSG_GROUP_DETAIL_HEADER, grpDetail.base.jobName );
  1498. ShowMgmtParms( grpDetail.base.mgmtParms, TRUE );
  1499. ShowVariableData( grpDetail.vLength, grpDetail.vData );
  1500. PrintHelp( HELP_MGMT );
  1501. }
  1502. static void ShowProcDetail( PCProcDetail &procDetail ) {
  1503. ToolMsg( PCCLIMSG_PROCESS_DETAIL_HEADER, procDetail.base.procName, ERROR_SUCCESS,
  1504. procDetail.base.memberOfJobName );
  1505. ShowMgmtParms( procDetail.base.mgmtParms, FALSE );
  1506. ShowVariableData( procDetail.vLength, procDetail.vData );
  1507. PrintHelp( HELP_MGMT, FALSE );
  1508. }
  1509. static void PrintLine( TCHAR *data, PCUINT32 nlCount ) {
  1510. DWORD numWritten;
  1511. static HANDLE stdOut = INVALID_HANDLE_VALUE;
  1512. if (stdOut == INVALID_HANDLE_VALUE) {
  1513. stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  1514. }
  1515. if ( data ) {
  1516. DWORD len = _tcslen(data);
  1517. if (! WriteConsole(stdOut,
  1518. data,
  1519. len,
  1520. &numWritten,
  1521. 0)) {
  1522. WriteFile(stdOut,
  1523. data,
  1524. len * sizeof(TCHAR),
  1525. &numWritten,
  1526. NULL);
  1527. }
  1528. }
  1529. if ( nlCount ) {
  1530. for ( PCUINT32 i = 0; i < nlCount; ++i )
  1531. if (! WriteConsole(stdOut,
  1532. TEXT("\n"),
  1533. 1,
  1534. &numWritten,
  1535. 0)) {
  1536. WriteFile(stdOut,
  1537. TEXT("\n"),
  1538. sizeof(TCHAR),
  1539. &numWritten,
  1540. NULL);
  1541. }
  1542. }
  1543. }
  1544. static void PrintHelp( PCUINT32 flags, BOOL isGrp, PCUINT32 msgId ) {
  1545. if ( flags & HELP_LIST ) ToolMsg( PCCLIMSG_LIST_FLAGS_EXPLAIN );
  1546. else if ( flags & HELP_ALIAS ) ToolMsg( PCCLIMSG_ALIAS_FLAGS_EXPLAIN );
  1547. else if ( flags & HELP_MGMT ) ToolMsg( isGrp? PCCLIMSG_GROUP_FLAGS_EXPLAIN :
  1548. PCCLIMSG_PROCESS_FLAGS_EXPLAIN );
  1549. if ( msgId ) ToolMsg( msgId );
  1550. }
  1551. static void BuildSystemParms( PCSystemParms &newParms, TCHAR **pArgs, PCUINT32 pArgCt ) {
  1552. memset( &newParms, 0, sizeof(newParms) );
  1553. if ( pArgCt > 0 ) newParms.manageIntervalSeconds = GetInteger( *pArgs++ );
  1554. if ( pArgCt > 1 ) newParms.timeoutValueMs = GetInteger( *pArgs++ );
  1555. }
  1556. static void BuildNameRule( PCNameRule &newRule, TCHAR **pArgs, PCUINT32 pArgCt ) {
  1557. memset( &newRule, 0, sizeof(newRule) );
  1558. if ( pArgCt > 0 ) newRule.matchType = **pArgs++;
  1559. if ( pArgCt > 1 ) _tcsncpy( newRule.matchString, *pArgs++, MATCH_STRING_LEN );
  1560. if ( pArgCt > 2 ) _tcsncpy( newRule.procName, *pArgs++, PROC_NAME_LEN );
  1561. if ( pArgCt > 3 ) _tcsncpy( newRule.description, *pArgs, NAME_DESCRIPTION_LEN );
  1562. }
  1563. static void MergeManagmentParms( MGMT_PARMS &newParms, MGMT_PARMS &oldParms ) {
  1564. newParms.mFlags |= oldParms.mFlags;
  1565. if ( !newParms.affinity ) newParms.affinity = oldParms.affinity;
  1566. if ( !newParms.jobMemoryLimit ) newParms.jobMemoryLimit = oldParms.jobMemoryLimit;
  1567. if ( !newParms.jobTimeLimitCNS ) newParms.jobTimeLimitCNS = oldParms.jobTimeLimitCNS;
  1568. if ( !newParms.maxWS ) newParms.maxWS = oldParms.maxWS;
  1569. if ( !newParms.minWS ) newParms.minWS = oldParms.minWS;
  1570. if ( !newParms.priority ) newParms.priority = oldParms.priority;
  1571. if ( !newParms.procCountLimit ) newParms.procCountLimit = oldParms.procCountLimit;
  1572. if ( !newParms.procMemoryLimit ) newParms.procMemoryLimit = oldParms.procMemoryLimit;
  1573. if ( !newParms.procTimeLimitCNS ) newParms.procTimeLimitCNS = oldParms.procTimeLimitCNS;
  1574. if ( newParms.schedClass > 9 ) newParms.schedClass = oldParms.schedClass;
  1575. if ( !*newParms.description ) memcpy( newParms.description, oldParms.description, sizeof(newParms.description) );
  1576. if ( !*newParms.profileName ) memcpy( newParms.profileName, oldParms.profileName, sizeof(newParms.profileName) );
  1577. }
  1578. static void MergeGroupDetail( PCJobDetail &newDet, PCJobDetail &oldDet ) {
  1579. if ( !newDet.vLength && oldDet.vLength ) {
  1580. newDet.vLength = oldDet.vLength;
  1581. memcpy( newDet.vData, oldDet.vData, newDet.vLength );
  1582. }
  1583. MergeManagmentParms( newDet.base.mgmtParms, oldDet.base.mgmtParms );
  1584. }
  1585. static void MergeProcDetail( PCProcDetail &newDet, PCProcDetail &oldDet ) {
  1586. if ( !newDet.vLength && oldDet.vLength ) {
  1587. newDet.vLength = oldDet.vLength;
  1588. memcpy( newDet.vData, oldDet.vData, newDet.vLength );
  1589. }
  1590. if ( !*newDet.base.memberOfJobName )
  1591. memcpy( newDet.base.memberOfJobName, oldDet.base.memberOfJobName, sizeof(newDet.base.memberOfJobName) );
  1592. MergeManagmentParms( newDet.base.mgmtParms, oldDet.base.mgmtParms );
  1593. }
  1594. static void BuildGrpDetail( PCJobDetail &newDetail, TCHAR **pArgs, PCUINT32 pArgCt ) {
  1595. memset( &newDetail, 0, offsetof(PCJobDetail, vLength) );
  1596. if ( pArgCt > 0 ) _tcsncpy( newDetail.base.jobName, *pArgs, JOB_NAME_LEN );
  1597. if ( pArgCt > 1 ) BuildMgmtParms( newDetail.base.mgmtParms, pArgs + 1, pArgCt - 1, NULL,
  1598. &newDetail.vLength, newDetail.vData );
  1599. else newDetail.vLength = 0;
  1600. }
  1601. static void BuildProcDetail( PCProcDetail &newDetail, TCHAR **pArgs, PCUINT32 pArgCt ) {
  1602. memset( &newDetail, 0, offsetof(PCProcDetail, vLength) );
  1603. if ( pArgCt > 0 ) _tcsncpy( newDetail.base.procName, *pArgs++, PROC_NAME_LEN );
  1604. if ( pArgCt > 1 ) BuildMgmtParms( newDetail.base.mgmtParms, pArgs, pArgCt - 1,
  1605. newDetail.base.memberOfJobName, &newDetail.vLength, newDetail.vData );
  1606. else newDetail.vLength = 0;
  1607. }
  1608. static void BuildGrpSummary( PCJobSummary &newSummary, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags ) {
  1609. memset( &newSummary, 0, sizeof(newSummary) );
  1610. if ( pArgCt > 0 ) {
  1611. _tcsncpy( newSummary.jobName, *pArgs++, JOB_NAME_LEN );
  1612. *listFlags |= PC_LIST_STARTING_WITH;
  1613. }
  1614. if ( pArgCt > 1 ) BuildMgmtParms( newSummary.mgmtParms, pArgs, pArgCt - 1 );
  1615. }
  1616. static void BuildProcSummary( PCProcSummary &newSummary, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags ) {
  1617. memset( &newSummary, 0, sizeof(newSummary) );
  1618. if ( pArgCt > 0 ) {
  1619. _tcsncpy( newSummary.procName, *pArgs++, PROC_NAME_LEN );
  1620. *listFlags |= PC_LIST_STARTING_WITH;
  1621. }
  1622. if ( pArgCt > 1 ) BuildMgmtParms( newSummary.mgmtParms, pArgs, pArgCt - 1, newSummary.memberOfJobName );
  1623. }
  1624. static void BuildGrpListItem( PCJobListItem &newListItem, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags ) {
  1625. memset( &newListItem, 0, sizeof(newListItem) );
  1626. gListShowBase = gListShowIO = gListShowMem = gListShowProc = gListShowTime = FALSE;
  1627. for ( PCUINT32 i = 0; i < pArgCt; ++i, ++pArgs ) {
  1628. if ( !IsSwitch( **pArgs ) ) {
  1629. _tcsncpy( newListItem.jobName, *pArgs, JOB_NAME_LEN );
  1630. *listFlags |= PC_LIST_STARTING_WITH;
  1631. }
  1632. else switch ( (*pArgs)[1] ) {
  1633. case GL_ALL:
  1634. gListShowTime = gListShowBase = gListShowIO = gListShowMem = gListShowProc = TRUE; break;
  1635. case GL_BASE: gListShowBase = TRUE; break;
  1636. case GL_IO: gListShowIO = TRUE; break;
  1637. case GL_MEMORY: gListShowMem = TRUE; break;
  1638. case GL_PROCESS: gListShowProc = TRUE; break;
  1639. case GL_TIME: gListShowTime = TRUE; break;
  1640. default:
  1641. ToolMsg( PCCLIMSG_GROUP_LIST_FLAG_UNKNOWN, *pArgs );
  1642. }
  1643. }
  1644. if ( !gListShowIO && !gListShowMem && !gListShowProc && !gListShowTime )
  1645. gListShowBase = TRUE;
  1646. }
  1647. static void BuildProcListItem( PCProcListItem &newListItem, TCHAR **pArgs, PCUINT32 pArgCt, PCUINT32 *listFlags ) {
  1648. memset( &newListItem, 0, sizeof(newListItem) );
  1649. gShowFmtProcTime = FALSE;
  1650. while ( pArgCt > 0 ) {
  1651. if ( IsSwitch( **pArgs) ) {
  1652. if ( *(*pArgs + 1) == DATA_GROUP && pArgCt > 1 ) {
  1653. _tcsncpy( newListItem.jobName, *++pArgs, JOB_NAME_LEN );
  1654. ++pArgs;
  1655. pArgCt -= 2;
  1656. *listFlags |= PC_LIST_MEMBERS_OF;
  1657. }
  1658. else if ( *(*pArgs + 1) == TEXT('t') ) {
  1659. gShowFmtProcTime = TRUE;
  1660. ++pArgs;
  1661. --pArgCt;
  1662. }
  1663. else {
  1664. ToolMsg( PCCLIMSG_PROCESS_LIST_FLAG_UNKNOWN, *pArgs );
  1665. break;
  1666. }
  1667. }
  1668. else {
  1669. _tcsncpy( newListItem.procName, *pArgs++, PROC_NAME_LEN );
  1670. --pArgCt;
  1671. if ( pArgCt > 0 && !IsSwitch( **pArgs) ) {
  1672. newListItem.procStats.pid = GetUInteger64( *pArgs++ );
  1673. --pArgCt;
  1674. }
  1675. *listFlags |= PC_LIST_STARTING_WITH;
  1676. }
  1677. }
  1678. if ( pArgCt ) ToolMsg( PCCLIMSG_PROCESS_LIST_FLAG_IGNORED, *pArgs );
  1679. }
  1680. static void BuildMgmtParms( MGMT_PARMS &parm,
  1681. TCHAR **pArgs,
  1682. PCUINT32 pArgCt,
  1683. JOB_NAME grpHere,
  1684. PCINT16 *len,
  1685. TCHAR *var ) {
  1686. PCUINT32 inLen = len? *len : 0;
  1687. if ( len ) *len = 0;
  1688. parm.schedClass = 99; // set 'net set' value. Needed because 0 is a valid setting.
  1689. for ( ; pArgCt > 1; pArgCt -= 2 ) {
  1690. if ( !IsSwitch( **pArgs ) ) {
  1691. ToolMsg( PCCLIMSG_UNKNOWN_DEF_SWITCH_IGNORED, *pArgs );
  1692. return;
  1693. }
  1694. if ( IsSwitch( **(pArgs + 1) ) ) {
  1695. ToolMsg( PCCLIMSG_ARG_MISSING_WITH_IGNORE, *pArgs );
  1696. return;
  1697. }
  1698. switch ( *(*pArgs++ + 1) ) {
  1699. case DEF_PRIO:
  1700. parm.priority = GetPriority( *pArgs++ );
  1701. if ( !parm.priority )
  1702. ToolMsg( PCCLIMSG_UNKNOWN_PRIORITY_IGNORED, *(pArgs - 1) );
  1703. break;
  1704. case DEF_AFF:
  1705. parm.affinity = GetUInteger64( *pArgs++ );
  1706. break;
  1707. case DEF_WS:
  1708. if ( pArgCt > 2 ) {
  1709. parm.minWS = GetValue( *pArgs++, MAXLONG - 1 ) * 1024; // Limit to match snap-in's limit
  1710. if ( !IsSwitch( **pArgs ) )
  1711. parm.maxWS = GetValue( *pArgs++, MAXLONG - 1 ) * 1024; // Limit to match snap-in's limit
  1712. else {
  1713. parm.minWS = 0;
  1714. ToolMsg( PCCLIMSG_WS_MAX_MISSING, *(pArgs - 1) );
  1715. return;
  1716. }
  1717. --pArgCt;
  1718. }
  1719. break;
  1720. case DEF_SCHED:
  1721. parm.schedClass = GetInteger( *pArgs++ );
  1722. break;
  1723. case DEF_FLAGS:
  1724. parm.mFlags = GetMgtFlags( *pArgs++ );
  1725. break;
  1726. case DEF_PROCTIME:
  1727. parm.procTimeLimitCNS = GetInteger64( *pArgs++ ) * 10000;
  1728. break;
  1729. case DEF_GROUP:
  1730. if ( grpHere ) _tcsncpy( grpHere, *pArgs++, JOB_NAME_LEN );
  1731. else
  1732. ToolMsg( PCCLIMSG_GROUP_NAME_NOT_APPLICABLE );
  1733. break;
  1734. case DEF_GROUPTIME:
  1735. parm.jobTimeLimitCNS = GetInteger64( *pArgs++ ) * 10000;
  1736. break;
  1737. case DEF_GROUPMEM:
  1738. parm.jobMemoryLimit = GetValue( *pArgs++, MAXLONG - 1 ) * 1024; // Limit to match snap-in's limit
  1739. break;
  1740. case DEF_PROCMEM:
  1741. parm.procMemoryLimit = GetValue( *pArgs++, MAXLONG - 1 ) * 1024; // Limit to match snap-in's limit
  1742. break;
  1743. case DEF_PROCCOUNT:
  1744. parm.procCountLimit = (ULONG) GetValue( *pArgs++, MAXLONG - 1 ); // Limit to match snap-in's limit
  1745. break;
  1746. case DEF_BRKAWAY:
  1747. parm.mFlags |= PCMFLAG_SET_PROC_BREAKAWAY_OK;
  1748. break;
  1749. case DEF_SILENTBRKAWAY:
  1750. parm.mFlags |= PCMFLAG_SET_SILENT_BREAKAWAY;
  1751. break;
  1752. case DEF_DIEONUHEX:
  1753. parm.mFlags |= PCMFLAG_SET_DIE_ON_UH_EXCEPTION;
  1754. break;
  1755. case DEF_CLOSEONEMPTY:
  1756. parm.mFlags |= PCMFLAG_END_JOB_WHEN_EMPTY;
  1757. break;
  1758. case DEF_MSGONGRPTIME:
  1759. parm.mFlags |= PCMFLAG_MSG_ON_JOB_TIME_LIMIT_HIT;
  1760. break;
  1761. case DEF_PROF:
  1762. _tcsncpy( parm.profileName, *pArgs++, PROFILE_NAME_LEN );
  1763. break;
  1764. case DEF_DESC:
  1765. _tcsncpy( parm.description, *pArgs++, RULE_DESCRIPTION_LEN );
  1766. break;
  1767. case DEF_VARDATA:
  1768. if ( inLen ) {
  1769. *len = (PCINT16) min( (_tcslen( *pArgs ) + 1), inLen / sizeof(TCHAR) );
  1770. if ( *len ) _tcsncpy( var, *pArgs, *len );
  1771. *len *= sizeof(TCHAR); // convert to bytes as per definition of field
  1772. }
  1773. *pArgs++;
  1774. break;
  1775. default:
  1776. ToolMsg( PCCLIMSG_UNKNOWN_DEF_SWITCH_IGNORED, *--pArgs );
  1777. return;
  1778. break;
  1779. }
  1780. }
  1781. if ( pArgCt )
  1782. ToolMsg( PCCLIMSG_INCOMPLETE_DEFINITION_IGNORED, *pArgs );
  1783. }
  1784. static PC_MGMT_FLAGS GetMgtFlags( TCHAR *txt ) {
  1785. PC_MGMT_FLAGS flgs = 0;
  1786. for ( TCHAR *d = txt; *d; ++d ) {
  1787. TCHAR c = _totlower( *d );
  1788. if ( c == DEF_GROUP ) flgs |= PCMFLAG_APPLY_JOB_MEMBERSHIP;
  1789. else if ( c == DEF_AFF ) flgs |= PCMFLAG_APPLY_AFFINITY;
  1790. else if ( c == DEF_PRIO ) flgs |= PCMFLAG_APPLY_PRIORITY;
  1791. else if ( c == DEF_WS ) flgs |= PCMFLAG_APPLY_WS_MINMAX;
  1792. else if ( c == DEF_SCHED ) flgs |= PCMFLAG_APPLY_SCHEDULING_CLASS;
  1793. else if ( c == DEF_PROCTIME ) flgs |= PCMFLAG_APPLY_PROC_TIME_LIMIT;
  1794. else if ( c == DEF_GROUPTIME ) flgs |= PCMFLAG_APPLY_JOB_TIME_LIMIT;
  1795. else if ( c == DEF_GROUPMEM ) flgs |= PCMFLAG_APPLY_JOB_MEMORY_LIMIT;
  1796. else if ( c == DEF_PROCMEM ) flgs |= PCMFLAG_APPLY_PROC_MEMORY_LIMIT;
  1797. else if ( c == DEF_PROCCOUNT ) flgs |= PCMFLAG_APPLY_PROC_COUNT_LIMIT;
  1798. else if ( c == DEF_BRKAWAY ) flgs |= PCMFLAG_SET_PROC_BREAKAWAY_OK;
  1799. else if ( c == DEF_SILENTBRKAWAY ) flgs |= PCMFLAG_SET_SILENT_BREAKAWAY;
  1800. else if ( c == DEF_DIEONUHEX ) flgs |= PCMFLAG_SET_DIE_ON_UH_EXCEPTION;
  1801. else if ( c == DEF_CLOSEONEMPTY ) flgs |= PCMFLAG_END_JOB_WHEN_EMPTY;
  1802. else if ( c == DEF_MSGONGRPTIME ) flgs |= PCMFLAG_MSG_ON_JOB_TIME_LIMIT_HIT;
  1803. }
  1804. return flgs;
  1805. }
  1806. static void ShowMgmtParms( MGMT_PARMS &parm, BOOL isGrp ) {
  1807. TCHAR flags[16];
  1808. ShowMgmtFlags( flags, parm.mFlags );
  1809. if ( isGrp )
  1810. ToolMsg( PCCLIMSG_GROUP_DETAIL_PARAMETERS, flags, ERROR_SUCCESS,
  1811. (VOID *) parm.affinity, (VOID *) ShowPriority( parm.priority ),
  1812. IntToPtr(parm.schedClass),
  1813. (VOID *) (parm.procMemoryLimit / 1024), (VOID *) (parm.jobMemoryLimit / 1024),
  1814. (VOID *) (parm.procTimeLimitCNS / 10000), (VOID *) (parm.jobTimeLimitCNS / 10000),
  1815. IntToPtr(parm.procCountLimit),
  1816. (VOID *) (parm.minWS / 1024), (VOID *) (parm.maxWS / 1024) );
  1817. else
  1818. ToolMsg( PCCLIMSG_PROCESS_DETAIL_PARAMETERS, flags, ERROR_SUCCESS,
  1819. (VOID *) parm.affinity, (VOID *) ShowPriority( parm.priority ),
  1820. (VOID *) (parm.minWS / 1024), (VOID *) (parm.maxWS / 1024) );
  1821. if ( *parm.description )
  1822. ToolMsg( PCCLIMSG_DETAIL_DESCRIPTION_TEXT, parm.description );
  1823. }
  1824. static void ShowVariableData( short len, TCHAR *data ) {
  1825. if ( len )
  1826. ToolMsg( PCCLIMSG_DETAIL_VARIABLE_TEXT, IntToPtr(len), ERROR_SUCCESS, IntToPtr(len / 2), data );
  1827. }
  1828. static void ShowMgmtFlags( TCHAR flags[16], PC_MGMT_FLAGS mFlags, BOOL compact ) {
  1829. for ( PCUINT32 i = 0; i < 16; ++i ) flags[i] = TEXT('.');
  1830. flags[15] = 0;
  1831. if ( mFlags & PCMFLAG_APPLY_JOB_MEMBERSHIP ) flags[0] = _totupper(DEF_GROUP);
  1832. if ( mFlags & PCMFLAG_APPLY_PRIORITY ) flags[1] = _totupper(DEF_PRIO);
  1833. if ( mFlags & PCMFLAG_APPLY_AFFINITY ) flags[2] = _totupper(DEF_AFF);
  1834. if ( mFlags & PCMFLAG_APPLY_SCHEDULING_CLASS ) flags[3] = _totupper(DEF_SCHED);
  1835. if ( mFlags & PCMFLAG_APPLY_WS_MINMAX ) flags[4] = _totupper(DEF_WS);
  1836. if ( mFlags & PCMFLAG_SET_PROC_BREAKAWAY_OK ) flags[5] = _totupper(DEF_BRKAWAY);
  1837. if ( mFlags & PCMFLAG_SET_SILENT_BREAKAWAY ) flags[6] = _totupper(DEF_SILENTBRKAWAY);
  1838. if ( mFlags & PCMFLAG_SET_DIE_ON_UH_EXCEPTION ) flags[7] = _totupper(DEF_DIEONUHEX);
  1839. if ( mFlags & PCMFLAG_END_JOB_WHEN_EMPTY ) flags[8] = _totupper(DEF_CLOSEONEMPTY);
  1840. if ( mFlags & PCMFLAG_MSG_ON_JOB_TIME_LIMIT_HIT ) flags[9] = _totupper(DEF_MSGONGRPTIME);
  1841. if ( mFlags & PCMFLAG_APPLY_PROC_MEMORY_LIMIT ) flags[10] = _totupper(DEF_PROCMEM);
  1842. if ( mFlags & PCMFLAG_APPLY_JOB_MEMORY_LIMIT ) flags[11] = _totupper(DEF_GROUPMEM);
  1843. if ( mFlags & PCMFLAG_APPLY_JOB_TIME_LIMIT ) flags[12] = _totupper(DEF_GROUPTIME);
  1844. if ( mFlags & PCMFLAG_APPLY_PROC_TIME_LIMIT ) flags[13] = _totupper(DEF_PROCTIME);
  1845. if ( mFlags & PCMFLAG_APPLY_PROC_COUNT_LIMIT ) flags[14] = _totupper(DEF_PROCCOUNT);
  1846. if ( compact ) {
  1847. for ( PCUINT32 j = 0, i = 0; i < 15; ++i )
  1848. if ( flags[i] != TEXT('.') ) flags[j++] = flags[i];
  1849. flags[j] = 0;
  1850. }
  1851. }
  1852. static void ShowSysInfo( PCSystemInfo &sysInfo, BOOL versionOnly ) {
  1853. if ( versionOnly )
  1854. ToolMsg( PCCLIMSG_SERVICE_VERSION_SHORT, sysInfo.productVersion, ERROR_SUCCESS,
  1855. sysInfo.fileVersion, sysInfo.fileFlags );
  1856. else {
  1857. ToolMsg( PCCLIMSG_SERVICE_VERSION_LONG, sysInfo.productVersion, ERROR_SUCCESS,
  1858. sysInfo.fileVersion, sysInfo.fileFlags, IntToPtr(sysInfo.fixedSignature) );
  1859. ToolMsg( PCCLIMSG_SERVICE_VERSION_BINARY, IntToPtr(sysInfo.fixedFileVersionMS),
  1860. ERROR_SUCCESS, IntToPtr(sysInfo.fixedFileVersionLS),
  1861. IntToPtr(sysInfo.fixedProductVersionMS), IntToPtr(sysInfo.fixedProductVersionLS),
  1862. IntToPtr(sysInfo.fixedFileOS),
  1863. IntToPtr(sysInfo.fixedFileType), IntToPtr(sysInfo.fixedFileSubtype) );
  1864. ToolMsg( PCCLIMSG_MEDIATOR_VERSION_LONG, sysInfo.medProductVersion, ERROR_SUCCESS,
  1865. sysInfo.medFileVersion, sysInfo.medFileFlags );
  1866. ShowSysParms( sysInfo.sysParms );
  1867. }
  1868. }
  1869. static void ShowSysParms( PCSystemParms &sysParms ) {
  1870. ToolMsg( PCCLIMSG_SYSTEM_PARAMETERS, IntToPtr(sysParms.numberOfProcessors), ERROR_SUCCESS,
  1871. (VOID *) sysParms.processorMask, IntToPtr(sysParms.memoryPageSize),
  1872. IntToPtr(sysParms.manageIntervalSeconds), IntToPtr(sysParms.timeoutValueMs) );
  1873. }
  1874. static int ShowHelp( TCHAR **pArgs, PCUINT32 pArgCt ) {
  1875. if ( !pArgCt ) ShowCLIHelp();
  1876. else ShowDetailHelp( pArgs, pArgCt );
  1877. return 0;
  1878. }
  1879. static void ShowCLIHelp( void ) {
  1880. ToolMsg( PCCLIMSG_COMMAND_HELP, (VOID *) (PC_MIN_BUF_SIZE / 1024), ERROR_SUCCESS,
  1881. (VOID *) (PC_MAX_BUF_SIZE / 1024) );
  1882. }
  1883. static void ShowDetailHelp( TCHAR **pArgs, PCUINT32 pArgCt ) {
  1884. for ( ; pArgCt > 0; --pArgCt, ++pArgs ) {
  1885. int i = 0;
  1886. TCHAR code = (*pArgs)[i++];
  1887. if ( IsSwitch( code ) && (*pArgs)[i] ) code = (*pArgs)[i++];
  1888. TCHAR subCode = (*pArgs)[i++];
  1889. switch ( code ) {
  1890. case BUFFER_SIZE:
  1891. ToolMsg( PCCLIMSG_SWITCH_b_HELP, (VOID *) (PC_MIN_BUF_SIZE / 1024), ERROR_SUCCESS,
  1892. (VOID *) (PC_MAX_BUF_SIZE / 1024) );
  1893. break;
  1894. case COMPUTER_NAME: ToolMsg( PCCLIMSG_SWITCH_c_HELP ); break;
  1895. case INTERACTIVE: ToolMsg( PCCLIMSG_SWITCH_i_HELP ); break;
  1896. case FILE_INPUT: ToolMsg( PCCLIMSG_SWITCH_f_HELP ); break;
  1897. case ADMIN_DUMPREST:ToolMsg( PCCLIMSG_SWITCH_x_HELP ); break;
  1898. case OP_ADD: ToolMsg( PCCLIMSG_SWITCH_a_HELP ); break;
  1899. case OP_REP: ToolMsg( PCCLIMSG_SWITCH_r_HELP ); break;
  1900. case OP_UPDATE: ToolMsg( PCCLIMSG_SWITCH_u_HELP ); break;
  1901. case OP_DEL: ToolMsg( PCCLIMSG_SWITCH_d_HELP ); break;
  1902. case OP_SWAP: ToolMsg( PCCLIMSG_SWITCH_s_HELP ); break;
  1903. case OP_LIST: ToolMsg( PCCLIMSG_SWITCH_l_HELP ); break;
  1904. case OP_KILL: ToolMsg( PCCLIMSG_SWITCH_k_HELP ); break;
  1905. case OP_COMMENT: ToolMsg( PCCLIMSG_SWITCH_COMMENT_HELP ); break;
  1906. case OP_HELP: ToolMsg( PCCLIMSG_SWITCH_HELP_HELP ); break;
  1907. case DATA_GROUP:
  1908. switch ( subCode ) {
  1909. case SUB_LIST:
  1910. case 0: ToolMsg( PCCLIMSG_SWITCH_gl_HELP ); break;
  1911. case SUB_SUMMARY: ToolMsg( PCCLIMSG_SWITCH_gs_HELP ); break;
  1912. case SUB_DEFS: ToolMsg( PCCLIMSG_SWITCH_gd_HELP ); break;
  1913. default:
  1914. ToolMsg( PCCLIMSG_GROUP_SUBLIST_HELP_UNKNOWN, (VOID *) subCode, ERROR_SUCCESS,
  1915. (VOID *) SUB_DEFS, (VOID *) SUB_SUMMARY, (VOID *) SUB_LIST );
  1916. break;
  1917. }
  1918. break;
  1919. case DATA_PROC:
  1920. switch ( subCode ) {
  1921. case SUB_LIST:
  1922. case 0: ToolMsg( PCCLIMSG_SWITCH_pl_HELP ); break;
  1923. case SUB_SUMMARY: ToolMsg( PCCLIMSG_SWITCH_ps_HELP ); break;
  1924. case SUB_DEFS: ToolMsg( PCCLIMSG_SWITCH_pd_HELP ); break;
  1925. default:
  1926. ToolMsg( PCCLIMSG_PROCESS_SUBLIST_HELP_UNKNOWN, (VOID *) subCode, ERROR_SUCCESS,
  1927. (VOID *) SUB_DEFS, (VOID *) SUB_SUMMARY, (VOID *) SUB_LIST );
  1928. break;
  1929. }
  1930. break;
  1931. case DATA_NAME: ToolMsg( PCCLIMSG_SWITCH_n_HELP ); break;
  1932. case DATA_SERVICE: ToolMsg( PCCLIMSG_SWITCH_v_HELP ); break;
  1933. case DATA_MEDIATOR: ToolMsg( PCCLIMSG_SWITCH_m_HELP ); break;
  1934. default:
  1935. ToolMsg( PCCLIMSG_HELP_UNKNOWN, (VOID *) code );
  1936. return;
  1937. }
  1938. }
  1939. }