Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1152 lines
38 KiB

  1. // *********************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // parse.cpp
  8. //
  9. // Abstract:
  10. //
  11. // This module implements the command-line parsing and validating the filters
  12. //
  13. // Author:
  14. //
  15. // Sunil G.V.N. Murali ([email protected]) 24-Nov-2000
  16. //
  17. // Revision History:
  18. //
  19. // Sunil G.V.N. Murali ([email protected]) 24-Nov-2000 : Created It.
  20. //
  21. // *********************************************************************************
  22. #include "pch.h"
  23. #include "tasklist.h"
  24. #define MAX_OPERATOR_STRING 101
  25. #define MAX_FILTER_PROP_STRING 256
  26. //
  27. // local function prototypes
  28. //
  29. BOOL
  30. TimeFieldsToElapsedTime(
  31. IN LPCWSTR pwszTime,
  32. IN LPCWSTR pwszToken,
  33. OUT ULONG& ulElapsedTime
  34. );
  35. DWORD
  36. FilterUserName(
  37. IN LPCWSTR pwszProperty,
  38. IN LPCWSTR pwszOperator,
  39. IN LPCWSTR pwszValue,
  40. IN LPVOID pData,
  41. IN TARRAY arrRow
  42. );
  43. DWORD
  44. FilterCPUTime(
  45. IN LPCWSTR pwszProperty,
  46. IN LPCWSTR pwszOperator,
  47. IN LPCWSTR pwszValue,
  48. IN LPVOID pData,
  49. IN TARRAY arrRow
  50. );
  51. BOOL
  52. CTaskList::ProcessOptions(
  53. IN DWORD argc,
  54. IN LPCTSTR argv[]
  55. )
  56. /*++
  57. Routine Description:
  58. processes and validates the command line inputs
  59. Arguments:
  60. [ in ] argc : no. of input arguments specified
  61. [ in ] argv : input arguments specified at command prompt
  62. Return Value:
  63. TRUE : if inputs are valid
  64. FALSE : if inputs were errorneously specified
  65. --*/
  66. {
  67. // local variables
  68. BOOL bNoHeader = FALSE;
  69. PTCMDPARSER2 pcmdOptions = NULL;
  70. WCHAR szFormat[ 64 ] = NULL_STRING;
  71. // temporary local variables
  72. PTCMDPARSER2 pOption = NULL;
  73. PTCMDPARSER2 pOptionServer = NULL;
  74. PTCMDPARSER2 pOptionUserName = NULL;
  75. PTCMDPARSER2 pOptionPassword = NULL;
  76. //
  77. // prepare the command options
  78. pcmdOptions = ( PTCMDPARSER2 )AllocateMemory( sizeof( TCMDPARSER2 ) * MAX_OPTIONS );
  79. if ( NULL == pcmdOptions )
  80. {
  81. SetLastError( ( DWORD )E_OUTOFMEMORY );
  82. SaveLastError();
  83. return FALSE;
  84. }
  85. // initialize to ZERO's
  86. SecureZeroMemory( pcmdOptions, MAX_OPTIONS * sizeof( TCMDPARSER2 ) );
  87. // -?
  88. pOption = pcmdOptions + OI_USAGE;
  89. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  90. pOption->dwType = CP_TYPE_BOOLEAN;
  91. pOption->pwszOptions = OPTION_USAGE;
  92. pOption->dwCount = 1;
  93. pOption->dwActuals = 0;
  94. pOption->dwFlags = CP_USAGE;
  95. pOption->pValue = &m_bUsage;
  96. pOption->dwLength = 0;
  97. // -s
  98. pOption = pcmdOptions + OI_SERVER;
  99. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  100. pOption->dwType = CP_TYPE_TEXT;
  101. pOption->pwszOptions = OPTION_SERVER;
  102. pOption->dwCount = 1;
  103. pOption->dwActuals = 0;
  104. pOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  105. pOption->pValue = NULL;
  106. pOption->dwLength = 0;
  107. // -u
  108. pOption = pcmdOptions + OI_USERNAME;
  109. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  110. pOption->dwType = CP_TYPE_TEXT;
  111. pOption->pwszOptions = OPTION_USERNAME;
  112. pOption->dwCount = 1;
  113. pOption->dwActuals = 0;
  114. pOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  115. pOption->pValue = NULL;
  116. pOption->dwLength = 0;
  117. // -p
  118. pOption = pcmdOptions + OI_PASSWORD;
  119. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  120. pOption->dwType = CP_TYPE_TEXT;
  121. pOption->pwszOptions = OPTION_PASSWORD;
  122. pOption->dwCount = 1;
  123. pOption->dwActuals = 0;
  124. pOption->dwFlags = CP2_ALLOCMEMORY | CP2_ALLOCMEMORY | CP2_VALUE_OPTIONAL;
  125. pOption->pValue = NULL;
  126. pOption->dwLength = 0;
  127. // -fi
  128. pOption = pcmdOptions + OI_FILTER;
  129. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  130. pOption->dwType = CP_TYPE_TEXT;
  131. pOption->pwszOptions = OPTION_FILTER;
  132. pOption->dwCount = 0;
  133. pOption->dwActuals = 0;
  134. pOption->dwFlags = CP_TYPE_TEXT | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  135. pOption->pValue = &m_arrFilters;
  136. pOption->dwLength = 0;
  137. // -fo
  138. pOption = pcmdOptions + OI_FORMAT;
  139. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  140. pOption->dwType = CP_TYPE_TEXT;
  141. pOption->pwszOptions = OPTION_FORMAT;
  142. pOption->pwszValues = GetResString(IDS_OVALUES_FORMAT);
  143. pOption->dwCount = 1;
  144. pOption->dwActuals = 0;
  145. pOption->dwFlags = CP2_MODE_VALUES | CP2_VALUE_TRIMINPUT|
  146. CP2_VALUE_NONULL;
  147. pOption->pValue = szFormat;
  148. pOption->dwLength = MAX_STRING_LENGTH;
  149. // -nh
  150. pOption = pcmdOptions + OI_NOHEADER;
  151. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  152. pOption->dwType = CP_TYPE_BOOLEAN;
  153. pOption->pwszOptions = OPTION_NOHEADER;
  154. pOption->pwszValues = NULL;
  155. pOption->dwCount = 1;
  156. pOption->dwActuals = 0;
  157. pOption->dwFlags = 0;
  158. pOption->pValue = &bNoHeader;
  159. pOption->dwLength = 0;
  160. // -v
  161. pOption = pcmdOptions + OI_VERBOSE;
  162. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  163. pOption->dwType = CP_TYPE_BOOLEAN;
  164. pOption->pwszOptions = OPTION_VERBOSE;
  165. pOption->pwszValues = NULL;
  166. pOption->dwCount = 1;
  167. pOption->dwActuals = 0;
  168. pOption->dwFlags = 0;
  169. pOption->pValue = &m_bVerbose;
  170. pOption->dwLength = 0;
  171. // -svc
  172. pOption = pcmdOptions + OI_SVC;
  173. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  174. pOption->dwType = CP_TYPE_BOOLEAN;
  175. pOption->pwszOptions = OPTION_SVC;
  176. pOption->pwszValues = NULL;
  177. pOption->dwCount = 1;
  178. pOption->dwActuals = 0;
  179. pOption->dwFlags = 0;
  180. pOption->pValue = &m_bAllServices;
  181. pOption->dwLength = 0;
  182. // -m
  183. pOption = pcmdOptions + OI_MODULES;
  184. StringCopyA( pOption->szSignature, "PARSER2\0", 8 );
  185. pOption->dwType = CP_TYPE_TEXT;
  186. pOption->pwszOptions = OPTION_MODULES;
  187. pOption->dwCount = 1;
  188. pOption->dwActuals = 0;
  189. pOption->dwFlags = CP2_VALUE_OPTIONAL | CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  190. pOption->pValue = NULL;
  191. pOption->dwLength = 0;
  192. //
  193. // do the parsing
  194. if ( DoParseParam2( argc, argv, -1, MAX_OPTIONS, pcmdOptions, 0 ) == FALSE )
  195. {
  196. FreeMemory( (LPVOID * )&pcmdOptions ); // clear memory
  197. return FALSE; // invalid syntax
  198. }
  199. //
  200. // now, check the mutually exclusive options
  201. pOptionServer = pcmdOptions + OI_SERVER;
  202. pOptionUserName = pcmdOptions + OI_USERNAME;
  203. pOptionPassword = pcmdOptions + OI_PASSWORD;
  204. try
  205. {
  206. // release the buffers
  207. m_strServer = (LPWSTR)pOptionServer->pValue;
  208. m_strUserName = (LPWSTR)pOptionUserName->pValue;
  209. m_strPassword = (LPWSTR)pOptionPassword->pValue;
  210. if( NULL == (LPWSTR)pOptionPassword->pValue )
  211. {
  212. m_strPassword = L"*";
  213. }
  214. m_strModules = (LPWSTR)pcmdOptions[ OI_MODULES ].pValue;
  215. FreeMemory( &pOptionServer->pValue );
  216. FreeMemory( &pOptionUserName->pValue );
  217. FreeMemory( &pOptionPassword->pValue );
  218. FreeMemory( &( pcmdOptions[ OI_MODULES ].pValue ) );
  219. // check the usage option
  220. if ( TRUE == m_bUsage )
  221. { // -? is specified.
  222. if( 2 < argc )
  223. {
  224. // no other options are accepted along with -? option
  225. SetLastError( ( DWORD )MK_E_SYNTAX );
  226. SetReason( ERROR_INVALID_USAGE_REQUEST );
  227. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  228. return FALSE;
  229. }
  230. else
  231. {
  232. // should not do the furthur validations
  233. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  234. return TRUE;
  235. }
  236. }
  237. // Without -s, -u and -p should not be specified.
  238. // With -s, -u can be specified, but without -u, -p should not be specified.
  239. if( 0 != pOptionServer->dwActuals )
  240. {
  241. if( ( 0 == pOptionUserName->dwActuals ) && ( 0 != pOptionPassword->dwActuals ) )
  242. {
  243. // invalid syntax
  244. SetReason( ERROR_PASSWORD_BUT_NOUSERNAME );
  245. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  246. return FALSE; // indicate failure
  247. }
  248. }
  249. else
  250. { // -s is not specified.
  251. if( 0 != pOptionUserName->dwActuals )
  252. { // -u without -s.
  253. // invalid syntax
  254. SetReason( ERROR_USERNAME_BUT_NOMACHINE );
  255. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  256. return FALSE; // indicate failure
  257. }
  258. else
  259. { // -p without -s.
  260. if( 0 != pOptionPassword->dwActuals )
  261. {
  262. // invalid syntax
  263. SetReason( ERROR_PASSWORD_BUT_NOUSERNAME );
  264. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  265. return FALSE; // indicate failure
  266. }
  267. }
  268. }
  269. // check whether user has specified modules or not
  270. if ( 0 != pcmdOptions[ OI_MODULES ].dwActuals )
  271. {
  272. // user has specified modules information
  273. m_bAllModules = TRUE;
  274. m_bNeedModulesInfo = TRUE;
  275. // now need to check whether user specified value or not this option
  276. if ( 0 != m_strModules.GetLength() )
  277. {
  278. // sub-local variales
  279. CHString str;
  280. LONG lPos = 0;
  281. // validate the modules .. direct filter
  282. // if should not have '*' character in between
  283. lPos = m_strModules.Find( L"*" );
  284. if ( ( -1 != lPos ) && ( 0 != m_strModules.Mid( lPos + 1 ).GetLength() ) )
  285. {
  286. SetReason( ERROR_M_CHAR_AFTER_WILDCARD );
  287. FreeMemory( (LPVOID * )&pcmdOptions );
  288. return FALSE;
  289. }
  290. // if the wildcard is not specified, it means user is looking for just a particular module name
  291. // so, do not show the modules info instead show the filtered regular information
  292. // if the filter specified is not just '*' add a custom filter
  293. if ( 0 != m_strModules.Compare( L"*" ) )
  294. {
  295. // prepare the search string
  296. str.Format( FMT_MODULES_FILTER, m_strModules );
  297. // add the value to the filters list
  298. if ( -1 == DynArrayAppendString( m_arrFilters, str, 0 ) )
  299. {
  300. SetLastError( ( DWORD )E_OUTOFMEMORY );
  301. SaveLastError();
  302. FreeMemory( (LPVOID * )&pcmdOptions );
  303. return FALSE;
  304. }
  305. }
  306. else
  307. {
  308. // user specified just '*' ... clear the contents
  309. m_strModules.Empty();
  310. }
  311. }
  312. }
  313. // determine the format in which the process information has to be displayed
  314. // Validation on 'm_dwFormat' variable is done at 'DoParseParam2'.
  315. m_dwFormat = SR_FORMAT_TABLE;
  316. // By default TABLE format is taken.
  317. if ( 0 == StringCompare( szFormat, TEXT_FORMAT_LIST, TRUE, 0 ) )
  318. { // List
  319. m_dwFormat = SR_FORMAT_LIST;
  320. }
  321. else
  322. {
  323. if ( 0 == StringCompare( szFormat, TEXT_FORMAT_CSV, TRUE, 0 ) )
  324. { // CSV
  325. m_dwFormat = SR_FORMAT_CSV;
  326. }
  327. }
  328. // -nh option is not valid of LIST format
  329. if ( ( TRUE == bNoHeader ) && ( SR_FORMAT_LIST == m_dwFormat ) )
  330. {
  331. // invalid syntax
  332. SetReason( ERROR_NH_NOTSUPPORTED );
  333. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  334. return FALSE; // indicate failure
  335. }
  336. // identify output format
  337. if ( TRUE == bNoHeader )
  338. {
  339. m_dwFormat |= SR_NOHEADER; // do not display the header
  340. }
  341. // determine whether we need to get the services / username info or not
  342. {
  343. DWORD dwMutuallyExclusive = 0;
  344. // -svc is specified.
  345. if( TRUE == m_bAllServices )
  346. {
  347. dwMutuallyExclusive += 1;
  348. m_bNeedServicesInfo = TRUE;
  349. }
  350. // -m is specified.
  351. if( TRUE == m_bAllModules )
  352. {
  353. dwMutuallyExclusive += 1;
  354. }
  355. // -v is specified.
  356. if( TRUE == m_bVerbose )
  357. {
  358. dwMutuallyExclusive += 1;
  359. m_bNeedWindowTitles = TRUE;
  360. m_bNeedUserContextInfo = TRUE;
  361. }
  362. // -svc, -m and -v should not appear together.
  363. if ( ( 0 != dwMutuallyExclusive ) && ( 1 < dwMutuallyExclusive ) )
  364. {
  365. // invalid syntax
  366. SetReason( ERROR_M_SVC_V_CANNOTBECOUPLED );
  367. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  368. return FALSE; // indicate failure
  369. }
  370. }
  371. // check whether caller should accept the password or not
  372. // if user has specified -s (or) -u and no "-p", then utility should accept password
  373. // the user will be prompter for the password only if establish connection
  374. // is failed without the credentials information
  375. if ( 0 != pOptionPassword->dwActuals)
  376. {
  377. if( 0 == m_strPassword.Compare( L"*" ) )
  378. {
  379. // user wants the utility to prompt for the password before trying to connect
  380. m_bNeedPassword = TRUE;
  381. }
  382. else
  383. {
  384. if( NULL == (LPCWSTR)m_strPassword )
  385. {
  386. m_strPassword = L"*";
  387. // user wants the utility to prompt for the password before trying to connect
  388. m_bNeedPassword = TRUE;
  389. }
  390. }
  391. }
  392. else
  393. {
  394. // utility needs to try to connect first and if it fails then prompt for the password
  395. m_bNeedPassword = TRUE;
  396. m_strPassword.Empty();
  397. }
  398. }
  399. catch( CHeap_Exception )
  400. {
  401. SetLastError( ( DWORD )E_OUTOFMEMORY );
  402. SaveLastError();
  403. FreeMemory( (LPVOID * )&pcmdOptions );
  404. return FALSE;
  405. }
  406. // command-line parsing is successfull
  407. FreeMemory( (LPVOID * )&pcmdOptions ); // clear the cmd parser config info
  408. return TRUE;
  409. }
  410. BOOL
  411. CTaskList::ValidateFilters(
  412. void
  413. )
  414. /*++
  415. Routine Description:
  416. validates the filter information specified with -filter option
  417. Arguments:
  418. NONE
  419. Return Value:
  420. TRUE : if filters are appropriately specified
  421. FALSE : if filters are errorneously specified
  422. --*/
  423. {
  424. // local variables
  425. LONG lIndex = -1;
  426. BOOL bResult = FALSE;
  427. PTFILTERCONFIG pConfig = NULL;
  428. //
  429. // prepare the filter structure
  430. // sessionname
  431. pConfig = m_pfilterConfigs + FI_SESSIONNAME;
  432. pConfig->dwColumn = CI_SESSIONNAME;
  433. pConfig->dwFlags = F_TYPE_TEXT | F_MODE_PATTERN;
  434. pConfig->pFunction = NULL;
  435. pConfig->pFunctionData = NULL;
  436. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  437. StringCopy( pConfig->szProperty, FILTER_SESSIONNAME, MAX_FILTER_PROP_STRING );
  438. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  439. // status
  440. pConfig = m_pfilterConfigs + FI_STATUS;
  441. pConfig->dwColumn = CI_STATUS;
  442. pConfig->dwFlags = F_TYPE_TEXT | F_MODE_VALUES;
  443. pConfig->pFunction = NULL;
  444. pConfig->pFunctionData = NULL;
  445. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  446. StringCopy( pConfig->szProperty, FILTER_STATUS, MAX_FILTER_PROP_STRING );
  447. StringCopy( pConfig->szValues, FVALUES_STATUS, MAX_FILTER_PROP_STRING );
  448. // imagename
  449. pConfig = m_pfilterConfigs + FI_IMAGENAME;
  450. pConfig->dwColumn = CI_IMAGENAME;
  451. pConfig->dwFlags = F_TYPE_TEXT | F_MODE_PATTERN;
  452. pConfig->pFunction = NULL;
  453. pConfig->pFunctionData = NULL;
  454. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  455. StringCopy( pConfig->szProperty, FILTER_IMAGENAME, MAX_FILTER_PROP_STRING );
  456. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  457. // pid
  458. pConfig = m_pfilterConfigs + FI_PID;
  459. pConfig->dwColumn = CI_PID;
  460. pConfig->dwFlags = F_TYPE_UNUMERIC;
  461. pConfig->pFunction = NULL;
  462. pConfig->pFunctionData = NULL;
  463. StringCopy( pConfig->szOperators, OPERATORS_NUMERIC, MAX_OPERATOR_STRING );
  464. StringCopy( pConfig->szProperty, FILTER_PID, MAX_FILTER_PROP_STRING );
  465. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  466. // session
  467. pConfig = m_pfilterConfigs + FI_SESSION;
  468. pConfig->dwColumn = CI_SESSION;
  469. pConfig->dwFlags = F_TYPE_UNUMERIC;
  470. pConfig->pFunction = NULL;
  471. pConfig->pFunctionData = NULL;
  472. StringCopy( pConfig->szOperators, OPERATORS_NUMERIC, MAX_OPERATOR_STRING );
  473. StringCopy( pConfig->szProperty, FILTER_SESSION, MAX_FILTER_PROP_STRING );
  474. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  475. // cputime
  476. pConfig = m_pfilterConfigs + FI_CPUTIME;
  477. pConfig->dwColumn = CI_CPUTIME;
  478. pConfig->dwFlags = F_TYPE_CUSTOM;
  479. pConfig->pFunction = FilterCPUTime;
  480. pConfig->pFunctionData = ( LPVOID) ((LPCWSTR) m_strTimeSep);
  481. StringCopy( pConfig->szOperators, OPERATORS_NUMERIC, MAX_OPERATOR_STRING );
  482. StringCopy( pConfig->szProperty, FILTER_CPUTIME, MAX_FILTER_PROP_STRING );
  483. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  484. // memusage
  485. pConfig = m_pfilterConfigs + FI_MEMUSAGE;
  486. pConfig->dwColumn = CI_MEMUSAGE;
  487. pConfig->dwFlags = F_TYPE_UNUMERIC;
  488. pConfig->pFunction = NULL;
  489. pConfig->pFunctionData = NULL;
  490. StringCopy( pConfig->szOperators, OPERATORS_NUMERIC, MAX_OPERATOR_STRING );
  491. StringCopy( pConfig->szProperty, FILTER_MEMUSAGE, MAX_FILTER_PROP_STRING );
  492. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  493. // username
  494. pConfig = m_pfilterConfigs + FI_USERNAME;
  495. pConfig->dwColumn = CI_USERNAME;
  496. pConfig->dwFlags = F_TYPE_CUSTOM;
  497. pConfig->pFunction = FilterUserName;
  498. pConfig->pFunctionData = NULL;
  499. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  500. StringCopy( pConfig->szProperty, FILTER_USERNAME, MAX_FILTER_PROP_STRING );
  501. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  502. // services
  503. pConfig = m_pfilterConfigs + FI_SERVICES;
  504. pConfig->dwColumn = CI_SERVICES;
  505. pConfig->dwFlags = F_TYPE_TEXT | F_MODE_PATTERN | F_MODE_ARRAY;
  506. pConfig->pFunction = NULL;
  507. pConfig->pFunctionData = NULL;
  508. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  509. StringCopy( pConfig->szProperty, FILTER_SERVICES, MAX_FILTER_PROP_STRING );
  510. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  511. // windowtitle
  512. pConfig = m_pfilterConfigs + FI_WINDOWTITLE;
  513. pConfig->dwColumn = CI_WINDOWTITLE;
  514. pConfig->dwFlags = F_TYPE_TEXT | F_MODE_PATTERN;
  515. pConfig->pFunction = NULL;
  516. pConfig->pFunctionData = NULL;
  517. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  518. StringCopy( pConfig->szProperty, FILTER_WINDOWTITLE, MAX_FILTER_PROP_STRING );
  519. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  520. // modules
  521. pConfig = m_pfilterConfigs + FI_MODULES;
  522. pConfig->dwColumn = CI_MODULES;
  523. pConfig->dwFlags = F_TYPE_TEXT | F_MODE_PATTERN | F_MODE_ARRAY;
  524. pConfig->pFunction = NULL;
  525. pConfig->pFunctionData = NULL;
  526. StringCopy( pConfig->szOperators, OPERATORS_STRING, MAX_OPERATOR_STRING );
  527. StringCopy( pConfig->szProperty, FILTER_MODULES, MAX_FILTER_PROP_STRING );
  528. StringCopy( pConfig->szValues, NULL_STRING, MAX_FILTER_PROP_STRING );
  529. //
  530. // validate the filter
  531. bResult = ParseAndValidateFilter( MAX_FILTERS,
  532. m_pfilterConfigs, m_arrFilters, &m_arrFiltersEx );
  533. // check the filter validation result
  534. if ( FALSE == bResult )
  535. {
  536. return FALSE;
  537. }
  538. // find out whether user has requested for the tasks to be filtered
  539. // on user context and/or services are not ... if yes, set the appropriate flags
  540. // this check is being done to increase the performance of the utility
  541. // NOTE: we will be using the parsed filters info for doing this
  542. // window titles
  543. if ( FALSE == m_bNeedWindowTitles )
  544. {
  545. // find out if the filter property exists in this row
  546. // NOTE:-
  547. // filter property do exists in the seperate indexes only.
  548. // refer to the logic of validating the filters in common functionality
  549. lIndex = DynArrayFindStringEx( m_arrFiltersEx,
  550. F_PARSED_INDEX_PROPERTY, FILTER_WINDOWTITLE, TRUE, 0 );
  551. if ( -1 != lIndex )
  552. {
  553. m_bNeedWindowTitles = TRUE;
  554. }
  555. }
  556. // status
  557. if ( FALSE == m_bNeedWindowTitles )
  558. {
  559. //
  560. // we will getting the status an application with the help of window title only
  561. // so, though we search for the STATUS filter, we will make use of the same window titles flag
  562. //
  563. // find out if the filter property exists in this row
  564. // NOTE:-
  565. // filter property do exists in the seperate indexes only.
  566. // refer to the logic of validating the filters in common functionality
  567. lIndex = DynArrayFindStringEx( m_arrFiltersEx,
  568. F_PARSED_INDEX_PROPERTY, FILTER_STATUS, TRUE, 0 );
  569. if ( -1 != lIndex )
  570. {
  571. m_bNeedWindowTitles = TRUE;
  572. }
  573. }
  574. // user context
  575. if ( FALSE == m_bNeedUserContextInfo )
  576. {
  577. // find out if the filter property exists in this row
  578. // NOTE:-
  579. // filter property do exists in the seperate indexes only.
  580. // refer to the logic of validating the filters in common functionality
  581. lIndex = DynArrayFindStringEx( m_arrFiltersEx,
  582. F_PARSED_INDEX_PROPERTY, FILTER_USERNAME, TRUE, 0 );
  583. if ( -1 != lIndex )
  584. {
  585. m_bNeedUserContextInfo = TRUE;
  586. }
  587. }
  588. // services info
  589. if ( FALSE == m_bNeedServicesInfo )
  590. {
  591. // find out if the filter property exists in this row
  592. // NOTE:-
  593. // filter property do exists in the seperate indexes only.
  594. // refer to the logic of validating the filters in common functionality
  595. lIndex = DynArrayFindStringEx( m_arrFiltersEx,
  596. F_PARSED_INDEX_PROPERTY, FILTER_SERVICES, TRUE, 0 );
  597. if ( -1 != lIndex )
  598. {
  599. m_bNeedServicesInfo = TRUE;
  600. }
  601. }
  602. // modules info
  603. if ( FALSE == m_bNeedModulesInfo )
  604. {
  605. // find out if the filter property exists in this row
  606. // NOTE:-
  607. // filter property do exists in the seperate indexes only.
  608. // refer to the logic of validating the filters in common functionality
  609. lIndex = DynArrayFindStringEx( m_arrFiltersEx,
  610. F_PARSED_INDEX_PROPERTY, FILTER_MODULES, TRUE, 0 );
  611. if ( -1 != lIndex )
  612. {
  613. m_bNeedModulesInfo = TRUE;
  614. }
  615. }
  616. //
  617. // do the filter optimization by adding the wmi properties to the query
  618. //
  619. // NOTE: as the 'handle' property of the Win32_Process class is string type
  620. // we cannot include that in the wmi query for optimization. So make use
  621. // of the ProcessId property
  622. LONG lCount = 0;
  623. CHString strBuffer;
  624. BOOL bOptimized = FALSE;
  625. LPCWSTR pwszValue = NULL;
  626. LPCWSTR pwszClause = NULL;
  627. LPCWSTR pwszProperty = NULL;
  628. LPCWSTR pwszOperator = NULL;
  629. try
  630. {
  631. // first clause .. and init
  632. m_strQuery = WMI_PROCESS_QUERY;
  633. pwszClause = WMI_QUERY_FIRST_CLAUSE;
  634. // get the no. of filters
  635. lCount = DynArrayGetCount( m_arrFiltersEx );
  636. // traverse thru all the filters and do the optimization
  637. for( LONG i = 0; i < lCount; i++ )
  638. {
  639. // assume this filter will not be delete / not useful for optimization
  640. bOptimized = FALSE;
  641. // get the property, operator and value
  642. pwszValue = DynArrayItemAsString2( m_arrFiltersEx, i, F_PARSED_INDEX_VALUE );
  643. pwszProperty = DynArrayItemAsString2( m_arrFiltersEx, i, F_PARSED_INDEX_PROPERTY );
  644. pwszOperator = DynArrayItemAsString2( m_arrFiltersEx, i, F_PARSED_INDEX_OPERATOR );
  645. if ( ( NULL == pwszProperty ) ||
  646. ( NULL == pwszOperator ) ||
  647. ( NULL == pwszValue ) )
  648. {
  649. SetLastError( ( DWORD )STG_E_UNKNOWN );
  650. SaveLastError();
  651. return FALSE;
  652. }
  653. //
  654. // based on the property do optimization needed
  655. // get the mathematically equivalent operator
  656. pwszOperator = FindOperator( pwszOperator );
  657. // process id
  658. if ( 0 == StringCompare( FILTER_PID, pwszProperty, TRUE, 0 ) )
  659. {
  660. // convert the value into numeric
  661. DWORD dwProcessId = AsLong( pwszValue, 10 );
  662. strBuffer.Format( L" %s %s %s %d",
  663. pwszClause, WIN32_PROCESS_PROPERTY_PROCESSID, pwszOperator, dwProcessId );
  664. // need to be optimized
  665. bOptimized = TRUE;
  666. }
  667. // session id
  668. else if ( 0 == StringCompare( FILTER_SESSION, pwszProperty, TRUE, 0 ) )
  669. {
  670. // convert the value into numeric
  671. DWORD dwSession = AsLong( pwszValue, 10 );
  672. strBuffer.Format( L" %s %s %s %d",
  673. pwszClause, WIN32_PROCESS_PROPERTY_SESSION, pwszOperator, dwSession );
  674. // need to be optimized
  675. bOptimized = TRUE;
  676. }
  677. // image name
  678. else if ( 0 == StringCompare( FILTER_IMAGENAME, pwszProperty, TRUE, 0 ) )
  679. {
  680. // check if wild card is specified or not
  681. // if wild card is specified, this filter cannot be optimized
  682. if ( NULL == wcschr( pwszValue, _T( '*' ) ) )
  683. {
  684. // no conversions needed
  685. strBuffer.Format( L" %s %s %s '%s'",
  686. pwszClause, WIN32_PROCESS_PROPERTY_IMAGENAME, pwszOperator, pwszValue );
  687. // need to be optimized
  688. bOptimized = TRUE;
  689. }
  690. }
  691. // mem usage
  692. else if ( 0 == StringCompare( FILTER_MEMUSAGE, pwszProperty, TRUE, 0 ) )
  693. {
  694. // convert the value into numeric
  695. ULONG ulMemUsage = AsLong( pwszValue, 10 ) * 1024;
  696. strBuffer.Format( L" %s %s %s %lu",
  697. pwszClause, WIN32_PROCESS_PROPERTY_MEMUSAGE, pwszOperator, ulMemUsage );
  698. // need to be optimized
  699. bOptimized = TRUE;
  700. }
  701. // check if property is optimizable ... if yes ... remove
  702. if ( TRUE == bOptimized )
  703. {
  704. // change the clause and append the current query
  705. m_strQuery += strBuffer;
  706. pwszClause = WMI_QUERY_SECOND_CLAUSE;
  707. // remove property and update the iterator variables
  708. DynArrayRemove( m_arrFiltersEx, i );
  709. i--;
  710. lCount--;
  711. }
  712. }
  713. }
  714. catch( CHeap_Exception )
  715. {
  716. SetLastError( ( DWORD )E_OUTOFMEMORY );
  717. SaveLastError();
  718. bResult = FALSE;
  719. }
  720. // return the filter validation result
  721. return bResult;
  722. }
  723. BOOL
  724. TimeFieldsToElapsedTime(
  725. IN LPCWSTR pwszTime,
  726. IN LPCWSTR pwszToken,
  727. OUT ULONG& ulElapsedTime
  728. )
  729. /*++
  730. Routine Description:
  731. Retrieve elapsed time.
  732. Arguments:
  733. [ in ] pwszTime : Contains time string.
  734. [ in ] pwszToken : Contains time seperator.
  735. [ out ] ulElapsedTime : Contains elapsed time.
  736. Return Value:
  737. TRUE if success else FAIL is returned.
  738. --*/
  739. {
  740. // local variables
  741. ULONG ulValue = 0;
  742. LPCWSTR pwszField = NULL;
  743. WCHAR szTemp[ 64 ] = NULL_STRING;
  744. DWORD dwNext = 0, dwLength = 0, dwCount = 0;
  745. // check the input
  746. if ( ( NULL == pwszTime ) ||
  747. ( NULL == pwszToken ) )
  748. {
  749. return FALSE;
  750. }
  751. // start parsing the time info
  752. dwNext = 0;
  753. dwCount = 0;
  754. ulElapsedTime = 0;
  755. do
  756. {
  757. // search for the needed token
  758. pwszField = FindString( pwszTime, pwszToken, dwNext );
  759. if ( NULL == pwszField )
  760. {
  761. // check whether some more text exists in the actual string or not
  762. if ( dwNext >= StringLength( pwszTime, 0 ) )
  763. {
  764. break; // no more info found
  765. }
  766. // get the last info
  767. StringCopy( szTemp, pwszTime + dwNext, SIZE_OF_ARRAY( szTemp ) );
  768. dwLength = StringLength( szTemp, 0 ); // update the length
  769. }
  770. else
  771. {
  772. // determine the length of numeric value and get the numeric value
  773. dwLength = StringLength( pwszTime, 0 ) - StringLength( pwszField, 0 ) - dwNext;
  774. // check the length info
  775. if ( dwLength > SIZE_OF_ARRAY( szTemp ) )
  776. {
  777. return FALSE;
  778. }
  779. // get the current info
  780. StringCopy( szTemp, pwszTime + dwNext, dwLength ); // +1 for NULL character
  781. }
  782. // update the count of fields we are getting
  783. dwCount++;
  784. // check whether this field is numeric or not
  785. if ( ( 0 == StringLength( szTemp, 0 ) ) ||
  786. ( FALSE == IsNumeric( szTemp, 10, FALSE ) ) )
  787. {
  788. return FALSE;
  789. }
  790. // from second token onwards, values greater than 59 are not allowed
  791. ulValue = AsLong( szTemp, 10 );
  792. if ( ( 1 < dwCount ) && ( 50 < ulValue ) )
  793. {
  794. return FALSE;
  795. }
  796. // update the elapsed time
  797. ulElapsedTime = ( ulElapsedTime + ulValue ) * (( dwCount < 3 ) ? 60 : 1);
  798. // position to the next information start
  799. dwNext += dwLength + StringLength( pwszToken, 0 );
  800. } while ( ( NULL != pwszField ) && ( 3 > dwCount ) );
  801. // check the no. of time field we got .. we should have got 3 .. if not, error
  802. if ( ( NULL != pwszField ) || ( 3 != dwCount ) )
  803. {
  804. return FALSE;
  805. }
  806. // so everything went right ... return success
  807. return TRUE;
  808. }
  809. DWORD
  810. FilterCPUTime(
  811. IN LPCWSTR pwszProperty,
  812. IN LPCWSTR pwszOperator,
  813. IN LPCWSTR pwszValue,
  814. IN LPVOID pData,
  815. IN TARRAY arrRow
  816. )
  817. /*++
  818. Routine Description:
  819. Filter process to display with resepect their CPU time.
  820. Arguments:
  821. [ in ] pwszProperty : Contains property value as 'CPUTIME'.
  822. [ in ] pwszOperator : Contains operator as 'gt'or 'lt' or 'ge' or 'le'.
  823. [ in ] pwszValue : Contains value to filter.
  824. [ in ] pData : Contains data to compare.
  825. [ in ] arrRow : Contains item value to filter.
  826. Return Value:
  827. DWORD
  828. --*/
  829. {
  830. // local variables
  831. ULONG ulCPUTime = 0;
  832. ULONG ulElapsedTime = 0;
  833. LPCWSTR pwszCPUTime = NULL;
  834. // if the arrRow parameter is NULL, we need to validate the filter
  835. if ( NULL == arrRow )
  836. {
  837. // check if there are any arthemtic sysbols before the cputime value starts
  838. if ( ( NULL != pwszValue ) && ( 1 < StringLength( pwszValue, 0 ) ) )
  839. {
  840. if ( ( L'-' == pwszValue[ 0 ] ) || ( L'+' == pwszValue[ 0 ] ) )
  841. {
  842. return F_FILTER_INVALID;
  843. }
  844. }
  845. // validate the filter value and return the result
  846. if ( FALSE == TimeFieldsToElapsedTime( pwszValue, L":", ulElapsedTime ) )
  847. {
  848. return F_FILTER_INVALID;
  849. }
  850. else
  851. {
  852. return F_FILTER_VALID;
  853. }
  854. }
  855. // get the filter value
  856. TimeFieldsToElapsedTime( pwszValue, L":", ulElapsedTime );
  857. // get the record value
  858. pwszCPUTime = DynArrayItemAsString( arrRow, TASK_CPUTIME );
  859. if ( NULL == pwszCPUTime )
  860. {
  861. return F_RESULT_REMOVE;
  862. }
  863. // convert the record value into elapsed time value
  864. TimeFieldsToElapsedTime( pwszCPUTime, (LPCWSTR) pData, ulCPUTime );
  865. // return the result
  866. if ( ulCPUTime == ulElapsedTime )
  867. {
  868. return MASK_EQ;
  869. }
  870. else
  871. {
  872. if ( ulCPUTime < ulElapsedTime )
  873. {
  874. return MASK_LT;
  875. }
  876. else
  877. {
  878. if ( ulCPUTime > ulElapsedTime )
  879. {
  880. return MASK_GT;
  881. }
  882. }
  883. }
  884. // no way flow coming here .. still
  885. return F_RESULT_REMOVE;
  886. }
  887. DWORD
  888. FilterUserName(
  889. IN LPCWSTR pwszProperty,
  890. IN LPCWSTR pwszOperator,
  891. IN LPCWSTR pwszValue,
  892. IN LPVOID pData,
  893. IN TARRAY arrRow
  894. )
  895. /*++
  896. Routine Description:
  897. Filter process to display with resepect their Username.
  898. Arguments:
  899. [ in ] pwszProperty : Contains property value as 'USERNAME'.
  900. [ in ] pwszOperator : Contains operator as 'eq' or 'ne'.
  901. [ in ] pwszValue : Contains value to filter.
  902. [ in ] pData : Contains data to compare.
  903. [ in ] arrRow : Contains item value to filter.
  904. Return Value:
  905. DWORD
  906. --*/
  907. {
  908. // local variables
  909. LONG lResult = 0;
  910. LONG lWildCardPos = 0;
  911. LPCWSTR pwszTemp = NULL;
  912. LPCWSTR pwszSearch = NULL;
  913. BOOL bOnlyUserName = FALSE;
  914. LPCWSTR pwszUserName = NULL;
  915. // check the inputs
  916. if ( ( NULL == pwszProperty ) ||
  917. ( NULL == pwszOperator ) ||
  918. ( NULL == pwszValue ) )
  919. {
  920. return F_FILTER_INVALID;
  921. }
  922. // if the arrRow parameter is NULL, we need to validate the filter
  923. if ( NULL == arrRow )
  924. {
  925. // nothing is there to validate ... just check the length
  926. // and ensure that so text is present and the value should not be just '*'
  927. // NOTE: the common functionality will give the value after doing left and right trim
  928. if ( ( 0 == StringLength( pwszValue, 0 ) ) || ( 0 == StringCompare( pwszValue, L"*", TRUE, 0 ) ) )
  929. {
  930. return F_FILTER_INVALID;
  931. }
  932. // the wild card character is allowed only at the end
  933. pwszTemp = _tcschr( pwszValue, L'*' );
  934. if ( ( NULL != pwszTemp ) && ( 0 != StringLength( pwszTemp + 1, 0 ) ) )
  935. {
  936. return F_FILTER_INVALID;
  937. }
  938. // filter is valid
  939. return F_FILTER_VALID;
  940. }
  941. // find the position of the wild card in the supplied user name
  942. lWildCardPos = 0;
  943. pwszTemp = _tcschr( pwszValue, L'*' );
  944. if ( NULL != pwszTemp )
  945. {
  946. // determine the wild card position
  947. lWildCardPos = StringLength( pwszValue, 0 ) - StringLength( pwszTemp, 0 );
  948. // special case:
  949. // if the pattern is just asterisk, which means that all the
  950. // information needs to passed thru the filter but there is no chance for
  951. // this situation as specifying only '*' is being treated as invalid filter
  952. if ( 0 == lWildCardPos )
  953. {
  954. return F_FILTER_INVALID;
  955. }
  956. }
  957. // search for the domain and user name seperator ...
  958. // if domain name is not specified, comparision will be done only with the user name
  959. bOnlyUserName = FALSE;
  960. pwszTemp = _tcschr( pwszValue, L'\\' );
  961. if ( NULL == pwszTemp )
  962. {
  963. bOnlyUserName = TRUE;
  964. }
  965. // get the user name from the info
  966. pwszUserName = DynArrayItemAsString( arrRow, TASK_USERNAME );
  967. if ( NULL == pwszUserName )
  968. {
  969. return F_RESULT_REMOVE;
  970. }
  971. // based the search criteria .. meaning whether to search along with the domain or
  972. // only user name, the seach string will be decided
  973. pwszSearch = pwszUserName;
  974. if ( TRUE == bOnlyUserName )
  975. {
  976. // search for the domain and user name seperation character
  977. pwszTemp = _tcschr( pwszUserName, L'\\' );
  978. // position to the next character
  979. if ( NULL != pwszTemp )
  980. {
  981. pwszSearch = pwszTemp + 1;
  982. }
  983. }
  984. // validate the search string
  985. if ( NULL == pwszSearch )
  986. {
  987. return F_RESULT_REMOVE;
  988. }
  989. // now do the comparision
  990. lResult = StringCompare( pwszSearch, pwszValue, TRUE, lWildCardPos );
  991. //
  992. // now determine the result value
  993. if ( 0 == lResult )
  994. {
  995. return MASK_EQ;
  996. }
  997. else
  998. {
  999. if ( 0 > lResult )
  1000. {
  1001. return MASK_LT;
  1002. }
  1003. if ( 0 < lResult )
  1004. {
  1005. return MASK_GT;
  1006. }
  1007. }
  1008. // never come across this situation ... still
  1009. return F_RESULT_REMOVE;
  1010. }
  1011. VOID
  1012. CTaskList::Usage(
  1013. void
  1014. )
  1015. /*++
  1016. Routine Description:
  1017. This function fetches usage information from resource file and shows it.
  1018. Arguments:
  1019. NONE
  1020. Return Value:
  1021. NONE
  1022. --*/
  1023. {
  1024. // local variables
  1025. DWORD dw = 0;
  1026. // start displaying the usage
  1027. ShowMessage( stdout, L"\n" );
  1028. for( dw = ID_HELP_START; dw <= ID_HELP_END; dw++ )
  1029. {
  1030. ShowMessage( stdout, GetResString( dw ) );
  1031. }
  1032. }