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.

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