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.

1390 lines
39 KiB

  1. // *********************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // ShowTasks.cpp
  8. //
  9. // Abstract:
  10. //
  11. // This module displays the tasks that were retrieved
  12. //
  13. // Author:
  14. //
  15. // Sunil G.V.N. Murali ([email protected]) 25-Nov-2000
  16. //
  17. // Revision History:
  18. //
  19. // Sunil G.V.N. Murali ([email protected]) 25-Nov-2000 : Created It.
  20. //
  21. // *********************************************************************************
  22. #include "pch.h"
  23. #include "wmi.h"
  24. #include "TaskList.h"
  25. //
  26. // define(s) / constants
  27. //
  28. #define MAX_TIMEOUT_RETRIES 300
  29. #define MAX_ENUM_TASKS 5
  30. #define MAX_ENUM_SERVICES 10
  31. #define MAX_ENUM_MODULES 5
  32. #define FMT_KILOBYTE GetResString( IDS_FMT_KILOBYTE )
  33. // structure signatures
  34. #define SIGNATURE_MODULES 9
  35. //
  36. // typedefs
  37. //
  38. typedef struct _tagModulesInfo
  39. {
  40. DWORD dwSignature;
  41. DWORD dwLength;
  42. LPCWSTR pwszModule;
  43. TARRAY arrModules;
  44. } TMODULESINFO, *PTMODULESINFO;
  45. //
  46. // function prototypes
  47. //
  48. #ifndef _WIN64
  49. BOOL EnumLoadedModulesProc( LPSTR lpszModuleName, ULONG ulModuleBase, ULONG ulModuleSize, PVOID pUserData );
  50. #else
  51. BOOL EnumLoadedModulesProc64( LPSTR lpszModuleName, DWORD64 ulModuleBase, ULONG ulModuleSize, PVOID pUserData );
  52. #endif
  53. // ***************************************************************************
  54. // Routine Description:
  55. // show the tasks running
  56. //
  57. // Arguments:
  58. // NONE
  59. //
  60. // Return Value:
  61. // NONE
  62. //
  63. // ***************************************************************************
  64. DWORD CTaskList::Show()
  65. {
  66. // local variables
  67. HRESULT hr;
  68. CHString strStatus;
  69. DWORD dwCount = 0;
  70. DWORD dwFormat = 0;
  71. DWORD dwFilters = 0;
  72. DWORD dwTimeOuts = 0;
  73. ULONG ulReturned = 0;
  74. BOOL bCanExit = FALSE;
  75. IWbemClassObject* pObjects[ MAX_ENUM_TASKS ];
  76. // init the objects to NULL's
  77. for( DWORD dw = 0; dw < MAX_ENUM_TASKS; dw++ )
  78. pObjects[ dw ] = NULL;
  79. // copy the format that has to be displayed into local memory
  80. bCanExit = FALSE;
  81. dwFormat = m_dwFormat;
  82. dwFilters = DynArrayGetCount( m_arrFiltersEx );
  83. // prepare the columns structure to display
  84. PrepareColumns();
  85. // clear the error code ... if any
  86. SetLastError( NO_ERROR );
  87. // dynamically decide whether to hide or show the window title in non-verbose mode
  88. if ( m_bLocalSystem == FALSE && m_bVerbose == TRUE )
  89. ( m_pColumns + CI_WINDOWTITLE )->dwFlags |= SR_HIDECOLUMN;
  90. try
  91. {
  92. // loop thru the process instances
  93. dwTimeOuts = 0;
  94. strStatus = MSG_TASKSINFO;
  95. do
  96. {
  97. // get the object ... wait only for 1 sec at one time ...
  98. hr = m_pEnumObjects->Next( 1000, MAX_ENUM_TASKS, pObjects, &ulReturned );
  99. if ( hr == WBEM_S_FALSE )
  100. {
  101. // we've reached the end of enumeration .. set the flag
  102. bCanExit = TRUE;
  103. }
  104. else if ( hr == WBEM_S_TIMEDOUT )
  105. {
  106. // update the timeouts occured
  107. dwTimeOuts++;
  108. // display the status message
  109. if ( m_hOutput != NULL )
  110. PrintProgressMsg( m_hOutput, strStatus + ((dwTimeOuts % 2 == 0) ? L" --" : L" |"), m_csbi );
  111. // check if max. retries have reached ... if yes better stop
  112. if ( dwTimeOuts > MAX_TIMEOUT_RETRIES )
  113. {
  114. // erase the status messages
  115. if ( m_hOutput != NULL )
  116. PrintProgressMsg( m_hOutput, NULL, m_csbi );
  117. // time out error
  118. SetLastError( ERROR_TIMEOUT );
  119. SaveLastError();
  120. return 0;
  121. }
  122. // still we can do more tries ...
  123. continue;
  124. }
  125. else if ( FAILED( hr ) )
  126. {
  127. // some error has occured ... oooppps
  128. WMISaveError( hr );
  129. SetLastError( STG_E_UNKNOWN );
  130. return 0;
  131. }
  132. // reset the timeout counter
  133. dwTimeOuts = 0;
  134. // erase the status messages
  135. if ( m_hOutput != NULL )
  136. PrintProgressMsg( m_hOutput, NULL, m_csbi );
  137. // loop thru the objects and save the info
  138. for( ULONG ul = 0; ul < ulReturned; ul++ )
  139. {
  140. // retrive and save data
  141. LONG lIndex = DynArrayAppendRow( m_arrTasks, MAX_TASKSINFO );
  142. SaveInformation( lIndex, pObjects[ ul ] );
  143. // we need to release the wmi object
  144. SAFE_RELEASE( pObjects[ ul ] );
  145. }
  146. // filter the results .. before doing first if filters do exist or not
  147. if ( dwFilters != 0 )
  148. FilterResults( MAX_FILTERS, m_pfilterConfigs, m_arrTasks, m_arrFiltersEx );
  149. // now show the tasks ... if exists
  150. if ( DynArrayGetCount( m_arrTasks ) != 0 )
  151. {
  152. // erase status messages if any
  153. PrintProgressMsg( m_hOutput, NULL, m_csbi );
  154. // if the output is not being displayed first time,
  155. // print one blank line in between ONLY FOR LIST FORMAT
  156. if ( dwCount != 0 && ((dwFormat & SR_FORMAT_MASK) == SR_FORMAT_LIST) )
  157. {
  158. ShowMessage( stdout, L"\n" );
  159. }
  160. else if ( dwCount == 0 )
  161. {
  162. // output is being displayed for the first time
  163. ShowMessage( stdout, L"\n" );
  164. }
  165. // show the tasks
  166. ShowResults( MAX_COLUMNS, m_pColumns, dwFormat, m_arrTasks );
  167. // clear the contents and reset
  168. dwCount += DynArrayGetCount( m_arrTasks ); // update count
  169. DynArrayRemoveAll( m_arrTasks );
  170. // to be on safe side, set the apply no heade flag to the format info
  171. dwFormat |= SR_NOHEADER;
  172. // get the next cursor position
  173. if ( m_hOutput != NULL )
  174. GetConsoleScreenBufferInfo( m_hOutput, &m_csbi );
  175. }
  176. } while ( bCanExit == FALSE );
  177. }
  178. catch( ... )
  179. {
  180. SetLastError( E_OUTOFMEMORY );
  181. SaveLastError();
  182. return 0;
  183. }
  184. // erase the status message
  185. PrintProgressMsg( m_hOutput, NULL, m_csbi );
  186. // clear the error
  187. SetLastError( NO_ERROR );
  188. // return the no. of tasks that were shown
  189. return dwCount;
  190. }
  191. // ***************************************************************************
  192. // Routine Description:
  193. //
  194. // Arguments:
  195. //
  196. // Return Value:
  197. // Process id as DWORD
  198. //
  199. // ***************************************************************************
  200. BOOL CTaskList::SaveInformation( LONG lIndex, IWbemClassObject* pWmiObject )
  201. {
  202. // local variables
  203. CHString str;
  204. // object path
  205. PropertyGet( pWmiObject, WIN32_PROCESS_SYSPROPERTY_PATH, str );
  206. DynArraySetString2( m_arrTasks, lIndex, TASK_OBJPATH, str, 0 );
  207. // process id
  208. PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_PROCESSID, m_dwProcessId );
  209. DynArraySetDWORD2( m_arrTasks, lIndex, TASK_PID, m_dwProcessId );
  210. // host name
  211. PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_COMPUTER, str );
  212. DynArraySetString2( m_arrTasks, lIndex, TASK_HOSTNAME, str, 0 );
  213. // image name
  214. PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_IMAGENAME, m_strImageName );
  215. DynArraySetString2( m_arrTasks, lIndex, TASK_IMAGENAME, m_strImageName, 0 );
  216. // status
  217. SetStatus( lIndex, pWmiObject );
  218. // cpu Time
  219. SetCPUTime( lIndex, pWmiObject );
  220. // session id and session name
  221. SetSession( lIndex, pWmiObject );
  222. // mem usage
  223. SetMemUsage( lIndex, pWmiObject );
  224. // user context
  225. SetUserContext( lIndex, pWmiObject );
  226. // window title
  227. SetWindowTitle( lIndex, pWmiObject );
  228. // services
  229. SetServicesInfo( lIndex, pWmiObject );
  230. // modules
  231. SetModulesInfo( lIndex, pWmiObject );
  232. // return
  233. return TRUE;
  234. }
  235. // ***************************************************************************
  236. // Routine Description:
  237. //
  238. // Arguments:
  239. //
  240. // Return Value:
  241. //
  242. // ***************************************************************************
  243. VOID CTaskList::SetUserContext( LONG lIndex, IWbemClassObject* pWmiObject )
  244. {
  245. // local variables
  246. HRESULT hr;
  247. CHString str;
  248. CHString strPath;
  249. CHString strDomain;
  250. CHString strUserName;
  251. IWbemClassObject* pOutParams = NULL;
  252. // set the default value
  253. DynArraySetString2( m_arrTasks, lIndex, TASK_USERNAME, V_NOT_AVAILABLE, 0 );
  254. // check if user name has to be retrieved or not
  255. if ( m_bNeedUserContextInfo == FALSE )
  256. return;
  257. //
  258. // for getting the user first we will try with API
  259. // it at all API fails, we will try to get the same information from WMI
  260. //
  261. try
  262. {
  263. // get the user name
  264. str = V_NOT_AVAILABLE;
  265. if ( LoadUserNameFromWinsta( strDomain, strUserName ) == TRUE )
  266. {
  267. // format the user name
  268. str.Format( L"%s\\%s", strDomain, strUserName );
  269. }
  270. else
  271. {
  272. // user name has to be retrieved - get the path of the current object
  273. hr = PropertyGet( pWmiObject, WIN32_PROCESS_SYSPROPERTY_PATH, strPath );
  274. if ( FAILED( hr ) || strPath.GetLength() == 0 )
  275. return;
  276. // execute the GetOwner method and get the user name
  277. // under which the current process is executing
  278. hr = m_pWbemServices->ExecMethod( _bstr_t( strPath ),
  279. _bstr_t( WIN32_PROCESS_METHOD_GETOWNER ), 0, NULL, NULL, &pOutParams, NULL );
  280. if ( FAILED( hr ) )
  281. return;
  282. // get the domain and user values from out params object
  283. // NOTE: do not check the results
  284. PropertyGet( pOutParams, GETOWNER_RETURNVALUE_DOMAIN, strDomain, L"" );
  285. PropertyGet( pOutParams, GETOWNER_RETURNVALUE_USER, strUserName, L"" );
  286. // get the value
  287. str = V_NOT_AVAILABLE;
  288. if ( strDomain.GetLength() != 0 )
  289. str.Format( L"%s\\%s", strDomain, strUserName );
  290. else if ( strUserName.GetLength() != 0 )
  291. str = strUserName;
  292. }
  293. // the formatted username might contain the UPN format user name
  294. // so ... remove that part
  295. if ( str.Find( L"@" ) != -1 )
  296. {
  297. // sub-local
  298. LONG lPos = 0;
  299. CHString strTemp;
  300. // get the position
  301. lPos = str.Find( L"@" );
  302. strTemp = str.Left( lPos );
  303. str = strTemp;
  304. }
  305. }
  306. catch( ... )
  307. {
  308. return;
  309. }
  310. // save the info
  311. DynArraySetString2( m_arrTasks, lIndex, TASK_USERNAME, str, 0 );
  312. }
  313. // ***************************************************************************
  314. // Routine Description:
  315. //
  316. // Arguments:
  317. //
  318. // Return Value:
  319. //
  320. // ***************************************************************************
  321. VOID CTaskList::SetCPUTime( LONG lIndex, IWbemClassObject* pWmiObject )
  322. {
  323. // local variables
  324. CHString str;
  325. BOOL bResult = FALSE;
  326. ULONGLONG ullCPUTime = 0;
  327. ULONGLONG ullUserTime = 0;
  328. ULONGLONG ullKernelTime = 0;
  329. // get the KernelModeTime value
  330. bResult = PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_KERNELMODETIME, ullKernelTime );
  331. // get the user mode time
  332. bResult = PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_USERMODETIME, ullUserTime );
  333. // calculate the CPU time
  334. ullCPUTime = ullUserTime + ullKernelTime;
  335. // now convert the long time into hours format
  336. TIME_FIELDS time;
  337. ZeroMemory( &time, sizeof( TIME_FIELDS ) );
  338. RtlTimeToElapsedTimeFields ( (LARGE_INTEGER* ) &ullCPUTime, &time );
  339. // convert the days into hours
  340. time.Hour = static_cast<CSHORT>( time.Hour + static_cast<SHORT>( time.Day * 24 ) );
  341. // prepare into time format ( user locale specific time seperator )
  342. str.Format( L"%d%s%02d%s%02d",
  343. time.Hour, m_strTimeSep, time.Minute, m_strTimeSep, time.Second );
  344. // save the info
  345. DynArraySetString2( m_arrTasks, lIndex, TASK_CPUTIME, str, 0 );
  346. }
  347. // ***************************************************************************
  348. // Routine Description:
  349. //
  350. // Arguments:
  351. //
  352. // Return Value:
  353. //
  354. // ***************************************************************************
  355. VOID CTaskList::SetWindowTitle( LONG lIndex, IWbemClassObject* pWmiObject )
  356. {
  357. // local variables
  358. CHString str;
  359. LONG lTemp = 0;
  360. LPCWSTR pwszTemp = NULL;
  361. // get the window details ... window station, desktop, window title
  362. // NOTE: This will work only for local system
  363. lTemp = DynArrayFindDWORDEx( m_arrWindowTitles, CTaskList::twiProcessId, m_dwProcessId );
  364. if ( lTemp != -1 )
  365. {
  366. pwszTemp = DynArrayItemAsString2( m_arrWindowTitles, lTemp, CTaskList::twiTitle );
  367. if ( pwszTemp != NULL )
  368. str = pwszTemp;
  369. }
  370. // save the info
  371. DynArraySetString2( m_arrTasks, lIndex, TASK_WINDOWTITLE, str, 0 );
  372. }
  373. // ***************************************************************************
  374. // Routine Description:
  375. //
  376. // Arguments:
  377. //
  378. // Return Value:
  379. //
  380. // ***************************************************************************
  381. VOID CTaskList::SetStatus( LONG lIndex, IWbemClassObject* pWmiObject )
  382. {
  383. // local variables
  384. DWORD dwThreads = 0;
  385. // set the default value
  386. DynArraySetString2( m_arrTasks, lIndex, TASK_STATUS, V_NOT_AVAILABLE, 0 );
  387. // get the threads count for the process
  388. if ( PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_THREADS, dwThreads ) == FALSE )
  389. return;
  390. // now determine the status
  391. if ( dwThreads > 0 )
  392. DynArraySetString2( m_arrTasks, lIndex, TASK_STATUS, VALUE_RUNNING, 0 );
  393. else
  394. DynArraySetString2( m_arrTasks, lIndex, TASK_STATUS, VALUE_NOTRESPONDING, 0 );
  395. }
  396. // ***************************************************************************
  397. // Routine Description:
  398. //
  399. // Arguments:
  400. //
  401. // Return Value:
  402. //
  403. // ***************************************************************************
  404. VOID CTaskList::SetSession( LONG lIndex, IWbemClassObject* pWmiObject )
  405. {
  406. // local variables
  407. CHString str;
  408. DWORD dwSessionId = 0;
  409. // set the default value
  410. DynArraySetString2( m_arrTasks, lIndex, TASK_SESSION, V_NOT_AVAILABLE, 0 );
  411. DynArraySetString2( m_arrTasks, lIndex, TASK_SESSIONNAME, L"", 0 );
  412. // get the threads count for the process
  413. if ( PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_SESSION, dwSessionId ) == FALSE )
  414. return;
  415. // get the session id in string format
  416. str.Format( L"%d", dwSessionId );
  417. try
  418. {
  419. // save the id
  420. DynArraySetString2( m_arrTasks, lIndex, TASK_SESSION, str, 0 );
  421. // get the session name
  422. if ( m_bLocalSystem == TRUE || ( m_bLocalSystem == FALSE && m_hServer != NULL ) )
  423. {
  424. // sub-local variables
  425. LPWSTR pwsz = NULL;
  426. // get the buffer
  427. pwsz = str.GetBufferSetLength( WINSTATIONNAME_LENGTH + 1 );
  428. // get the name for the session
  429. if ( WinStationNameFromLogonIdW( m_hServer, dwSessionId, pwsz ) == FALSE )
  430. return; // failed in getting the winstation/session name ... return
  431. // release buffer
  432. str.ReleaseBuffer();
  433. // save the session name ... do this only if session name is not empty
  434. if ( str.GetLength() != 0 )
  435. DynArraySetString2( m_arrTasks, lIndex, TASK_SESSIONNAME, str, 0 );
  436. }
  437. }
  438. catch( ... )
  439. {
  440. // simply return
  441. return;
  442. }
  443. }
  444. // ***************************************************************************
  445. // Routine Description:
  446. //
  447. // Arguments:
  448. //
  449. // Return Value:
  450. //
  451. // ***************************************************************************
  452. VOID CTaskList::SetMemUsage( LONG lIndex, IWbemClassObject* pWmiObject )
  453. {
  454. // local variables
  455. CHString str;
  456. LONG lTemp = 0;
  457. NUMBERFMTW nfmtw;
  458. NTSTATUS ntstatus;
  459. ULONGLONG ullMemUsage = 0;
  460. LARGE_INTEGER liTemp = { 0, 0 };
  461. CHAR szTempBuffer[ 33 ] = "\0";
  462. WCHAR wszNumberStr[ 33 ] = L"\0";
  463. try
  464. {
  465. // NOTE:
  466. // ----
  467. // The max. value of
  468. // (2 ^ 64) - 1 = "18,446,744,073,709,600,000 K" (29 chars).
  469. //
  470. // so, the buffer size to store the number is fixed as 32 characters
  471. // which is more than the 29 characters in actuals
  472. // set the default value
  473. DynArraySetString2( m_arrTasks, lIndex, TASK_MEMUSAGE, V_NOT_AVAILABLE, 0 );
  474. // get the KernelModeTime value
  475. if ( PropertyGet( pWmiObject, WIN32_PROCESS_PROPERTY_MEMUSAGE, ullMemUsage ) == FALSE )
  476. return;
  477. // convert the value into K Bytes
  478. ullMemUsage /= 1024;
  479. // now again convert the value from ULONGLONG to string and check the result
  480. liTemp.QuadPart = ullMemUsage;
  481. ntstatus = RtlLargeIntegerToChar( &liTemp, 10, SIZE_OF_ARRAY( szTempBuffer ), szTempBuffer );
  482. if ( ! NT_SUCCESS( ntstatus ) )
  483. return;
  484. // now copy this info into UNICODE buffer
  485. str = szTempBuffer;
  486. //
  487. // prepare to Format the number with commas according to locale conventions.
  488. nfmtw.NumDigits = 0;
  489. nfmtw.LeadingZero = 0;
  490. nfmtw.NegativeOrder = 0;
  491. nfmtw.Grouping = m_dwGroupSep;
  492. nfmtw.lpDecimalSep = m_strGroupThousSep.GetBuffer( m_strGroupThousSep.GetLength() );
  493. nfmtw.lpThousandSep = m_strGroupThousSep.GetBuffer( m_strGroupThousSep.GetLength() );
  494. // convert the value
  495. lTemp = GetNumberFormatW( LOCALE_USER_DEFAULT,
  496. 0, str, &nfmtw, wszNumberStr, SIZE_OF_ARRAY( wszNumberStr ) );
  497. // get the session id in string format
  498. str.Format( FMT_KILOBYTE, wszNumberStr );
  499. // save the id
  500. DynArraySetString2( m_arrTasks, lIndex, TASK_MEMUSAGE, str, 0 );
  501. }
  502. catch( ... )
  503. {
  504. SetLastError( E_OUTOFMEMORY );
  505. SaveLastError();
  506. }
  507. }
  508. // ***************************************************************************
  509. // Routine Description:
  510. //
  511. // Arguments:
  512. //
  513. // Return Value:
  514. //
  515. // ***************************************************************************
  516. VOID CTaskList::SetServicesInfo( LONG lIndex, IWbemClassObject* pWmiObject )
  517. {
  518. // local variables
  519. HRESULT hr;
  520. CHString strQuery;
  521. CHString strService;
  522. ULONG ulReturned = 0;
  523. BOOL bResult = FALSE;
  524. BOOL bCanExit = FALSE;
  525. TARRAY arrServices = NULL;
  526. IEnumWbemClassObject* pEnumServices = NULL;
  527. IWbemClassObject* pObjects[ MAX_ENUM_SERVICES ];
  528. // check whether we need to gather services info or not .. if not skip
  529. if ( m_bNeedServicesInfo == FALSE )
  530. return;
  531. // create array
  532. arrServices = CreateDynamicArray();
  533. if ( arrServices == NULL )
  534. {
  535. SetLastError( E_OUTOFMEMORY );
  536. SaveLastError();
  537. return;
  538. }
  539. //
  540. // for getting the services info first we will try with the one we got from API
  541. // it at all API fails, we will try to get the same information from WMI
  542. //
  543. // check whether API returned services or not
  544. if ( m_pServicesInfo != NULL )
  545. {
  546. // get the service names related to the current process
  547. // identify all the services related to the current process ( based on the PID )
  548. // and save the info
  549. for ( DWORD dw = 0; dw < m_dwServicesCount; dw++ )
  550. {
  551. // compare the PID's
  552. if ( m_dwProcessId == m_pServicesInfo[ dw ].ServiceStatusProcess.dwProcessId )
  553. {
  554. // this service is related with the current process ... store service name
  555. DynArrayAppendString( arrServices, m_pServicesInfo[ dw ].lpServiceName, 0 );
  556. }
  557. }
  558. }
  559. else
  560. {
  561. try
  562. {
  563. // init the objects to NULL's
  564. for( DWORD dw = 0; dw < MAX_ENUM_SERVICES; dw++ )
  565. pObjects[ dw ] = NULL;
  566. // prepare the query
  567. strQuery.Format( WMI_SERVICE_QUERY, m_dwProcessId );
  568. // execute the query
  569. hr = m_pWbemServices->ExecQuery( _bstr_t( WMI_QUERY_TYPE ), _bstr_t( strQuery ),
  570. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumServices );
  571. // check the result
  572. if ( FAILED( hr ) )
  573. _com_issue_error( hr );
  574. // set the security
  575. hr = SetInterfaceSecurity( pEnumServices, m_pAuthIdentity );
  576. if ( FAILED( hr ) )
  577. _com_issue_error( hr );
  578. // loop thru the service instances
  579. do
  580. {
  581. // get the object ... wait
  582. // NOTE: one-by-one
  583. hr = pEnumServices->Next( WBEM_INFINITE, MAX_ENUM_SERVICES, pObjects, &ulReturned );
  584. if ( hr == WBEM_S_FALSE )
  585. {
  586. // we've reached the end of enumeration .. set the flag
  587. bCanExit = TRUE;
  588. }
  589. else if ( hr == WBEM_S_TIMEDOUT || FAILED( hr ) )
  590. {
  591. //
  592. // some error has occured ... oooppps
  593. // exit from the loop
  594. break;
  595. }
  596. // loop thru the objects and save the info
  597. for( ULONG ul = 0; ul < ulReturned; ul++ )
  598. {
  599. // get the value of the property
  600. bResult = PropertyGet( pObjects[ ul ], WIN32_SERVICE_PROPERTY_NAME, strService );
  601. if ( bResult == TRUE )
  602. DynArrayAppendString( arrServices, strService, 0 );
  603. // release the interface
  604. SAFE_RELEASE( pObjects[ ul ] );
  605. }
  606. } while ( bCanExit == FALSE );
  607. }
  608. catch( _com_error& e )
  609. {
  610. // save the error
  611. WMISaveError( e );
  612. }
  613. // release the objects to NULL's
  614. for( DWORD dw = 0; dw < MAX_ENUM_SERVICES; dw++ )
  615. {
  616. // release all the objects
  617. SAFE_RELEASE( pObjects[ dw ] );
  618. }
  619. // now release the enumeration object
  620. SAFE_RELEASE( pEnumServices );
  621. }
  622. // save and return
  623. DynArraySetEx2( m_arrTasks, lIndex, TASK_SERVICES, arrServices );
  624. }
  625. // ***************************************************************************
  626. // Routine Description:
  627. //
  628. // Arguments:
  629. //
  630. // Return Value:
  631. //
  632. // ***************************************************************************
  633. BOOL CTaskList::SetModulesInfo( LONG lIndex, IWbemClassObject* pWmiObject )
  634. {
  635. // local variables
  636. LONG lPos = 0;
  637. BOOL bResult = FALSE;
  638. TARRAY arrModules = NULL;
  639. // check whether we need to get the modules or not
  640. if ( m_bNeedModulesInfo == FALSE )
  641. return TRUE;
  642. // allocate for memory
  643. arrModules = CreateDynamicArray();
  644. if ( arrModules == NULL )
  645. {
  646. SetLastError( E_OUTOFMEMORY );
  647. SaveLastError();
  648. return FALSE;
  649. }
  650. // the way we get the modules information is different for local remote
  651. // so depending that call appropriate function
  652. if ( m_bLocalSystem == TRUE && m_bUseRemote == FALSE )
  653. {
  654. // enumerate the modules for the current process
  655. bResult = LoadModulesOnLocal( lIndex, arrModules );
  656. }
  657. else
  658. {
  659. // identify the modules information for the current process ... remote system
  660. bResult = GetModulesOnRemote( lIndex, arrModules );
  661. }
  662. // check the result
  663. if ( bResult == TRUE )
  664. {
  665. // check if the modules list contains the imagename also. If yes remove that entry
  666. lPos = DynArrayFindString( arrModules, m_strImageName, TRUE, 0 );
  667. if ( lPos != -1 )
  668. {
  669. // remove the entry
  670. DynArrayRemove( arrModules, lPos );
  671. }
  672. }
  673. // save the modules information to the array
  674. // NOTE: irrespective of whether enumeration is success or not we will add the array
  675. DynArraySetEx2( m_arrTasks, lIndex, TASK_MODULES, arrModules );
  676. // return
  677. return bResult;
  678. }
  679. // ***************************************************************************
  680. // Routine Description:
  681. //
  682. // Arguments:
  683. //
  684. // Return Value:
  685. //
  686. // ***************************************************************************
  687. BOOL CTaskList::LoadModulesOnLocal( LONG lIndex, TARRAY arrModules )
  688. {
  689. // local variables
  690. LONG lPos = 0;
  691. BOOL bResult = FALSE;
  692. TMODULESINFO modules;
  693. HANDLE hProcess = NULL;
  694. // check the input values
  695. if ( arrModules == NULL )
  696. return FALSE;
  697. // open the process handle
  698. hProcess = OpenProcess( PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, m_dwProcessId );
  699. if ( hProcess == NULL )
  700. {
  701. return FALSE; // failed in getting the process handle
  702. }
  703. // prepare the modules structure
  704. ZeroMemory( &modules, sizeof( TMODULESINFO ) );
  705. modules.dwSignature = SIGNATURE_MODULES;
  706. modules.dwLength = 0;
  707. modules.arrModules = arrModules;
  708. modules.pwszModule = ((m_strModules.GetLength() != 0) ? (LPCWSTR) m_strModules : NULL);
  709. if ( (lPos = m_strModules.Find( L"*" )) != -1 )
  710. {
  711. modules.dwLength = (DWORD) lPos;
  712. modules.pwszModule = m_strModules;
  713. }
  714. #ifndef _WIN64
  715. bResult = EnumerateLoadedModules( hProcess, EnumLoadedModulesProc, &modules );
  716. #else
  717. bResult = EnumerateLoadedModules64( hProcess, EnumLoadedModulesProc64, &modules );
  718. #endif
  719. // close the process handle .. we dont need this furthur
  720. CloseHandle( hProcess );
  721. hProcess = NULL;
  722. // return
  723. return bResult;
  724. }
  725. // ***************************************************************************
  726. // Routine Description:
  727. //
  728. // Arguments:
  729. //
  730. // Return Value:
  731. //
  732. // ***************************************************************************
  733. BOOL CTaskList::GetModulesOnRemote( LONG lIndex, TARRAY arrModules )
  734. {
  735. // local variables
  736. LONG lPos = 0;
  737. DWORD dwLength = 0;
  738. DWORD dwOffset = 0;
  739. DWORD dwInstance = 0;
  740. PPERF_OBJECT_TYPE pot = NULL;
  741. PPERF_OBJECT_TYPE potImages = NULL;
  742. PPERF_INSTANCE_DEFINITION pidImages = NULL;
  743. PPERF_COUNTER_BLOCK pcbImages = NULL;
  744. PPERF_OBJECT_TYPE potAddressSpace = NULL;
  745. PPERF_INSTANCE_DEFINITION pidAddressSpace = NULL;
  746. PPERF_COUNTER_BLOCK pcbAddressSpace = NULL;
  747. PPERF_COUNTER_DEFINITION pcd = NULL;
  748. // check the input values
  749. if ( arrModules == NULL )
  750. return FALSE;
  751. // check whether the performance object exists or not
  752. // if doesn't exists, get the same using WMI
  753. if ( m_pdb == NULL )
  754. {
  755. // invoke the WMI method
  756. return GetModulesOnRemoteEx( lIndex, arrModules );
  757. }
  758. // get the perf object types
  759. pot = (PPERF_OBJECT_TYPE) ( (LPBYTE) m_pdb + m_pdb->HeaderLength );
  760. for( DWORD dw = 0; dw < m_pdb->NumObjectTypes; dw++ )
  761. {
  762. if ( pot->ObjectNameTitleIndex == 740 )
  763. potImages = pot;
  764. else if ( pot->ObjectNameTitleIndex == 786 )
  765. potAddressSpace = pot;
  766. // move to the next object
  767. dwOffset = pot->TotalByteLength;
  768. if( dwOffset != 0 )
  769. pot = ( (PPERF_OBJECT_TYPE) ((PBYTE) pot + dwOffset));
  770. }
  771. // check whether we got both the object types or not
  772. if ( potImages == NULL || potAddressSpace == NULL )
  773. return FALSE;
  774. // find the offset of the process id in the address space object type
  775. // get the first counter definition of address space object
  776. pcd = (PPERF_COUNTER_DEFINITION) ( (LPBYTE) potAddressSpace + potAddressSpace->HeaderLength);
  777. // loop thru the counters and find the offset
  778. dwOffset = 0;
  779. for( DWORD dw = 0; dw < potAddressSpace->NumCounters; dw++)
  780. {
  781. // 784 is the counter for process id
  782. if ( pcd->CounterNameTitleIndex == 784 )
  783. {
  784. dwOffset = pcd->CounterOffset;
  785. break;
  786. }
  787. // next counter
  788. pcd = ( (PPERF_COUNTER_DEFINITION) ( (LPBYTE) pcd + pcd->ByteLength) );
  789. }
  790. // check whether we got the offset or not
  791. // if not, we are unsuccessful
  792. if ( dwOffset == 0 )
  793. {
  794. // set the error message
  795. SetLastError( ERROR_ACCESS_DENIED );
  796. SaveLastError();
  797. return FALSE;
  798. }
  799. // get the instances
  800. pidImages = (PPERF_INSTANCE_DEFINITION) ( (LPBYTE) potImages + potImages->DefinitionLength );
  801. pidAddressSpace = (PPERF_INSTANCE_DEFINITION) ( (LPBYTE) potAddressSpace + potAddressSpace->DefinitionLength );
  802. // counter blocks
  803. pcbImages = (PPERF_COUNTER_BLOCK) ( (LPBYTE) pidImages + pidImages->ByteLength );
  804. pcbAddressSpace = (PPERF_COUNTER_BLOCK) ( (LPBYTE) pidAddressSpace + pidAddressSpace->ByteLength );
  805. // find the instance number of the process which we are looking for
  806. for( dwInstance = 0; dwInstance < (DWORD) potAddressSpace->NumInstances; dwInstance++ )
  807. {
  808. // sub-local variables
  809. DWORD dwProcessId = 0;
  810. // get the process id
  811. dwProcessId = *((DWORD*) ( (LPBYTE) pcbAddressSpace + dwOffset ));
  812. // now check if this is the process which we are looking for
  813. if ( dwProcessId == m_dwProcessId )
  814. break;
  815. // continue looping thru other instances
  816. pidAddressSpace = (PPERF_INSTANCE_DEFINITION) ( (LPBYTE) pcbAddressSpace + pcbAddressSpace->ByteLength );
  817. pcbAddressSpace = (PPERF_COUNTER_BLOCK) ( (LPBYTE) pidAddressSpace + pidAddressSpace->ByteLength );
  818. }
  819. // check whether we got the instance or not
  820. // if not, there are no modules for this process
  821. if ( dwInstance == potAddressSpace->NumInstances )
  822. return TRUE;
  823. //determine the length of the module name ..
  824. dwLength = 0;
  825. if ( (lPos = m_strModules.Find( L"*" )) != -1 )
  826. dwLength = (DWORD) lPos;
  827. // now based the parent instance, collect all the modules
  828. for( DWORD dw = 0; (LONG) dw < potImages->NumInstances; dw++)
  829. {
  830. // check the parent object instance number
  831. if ( pidImages->ParentObjectInstance == dwInstance )
  832. {
  833. try
  834. {
  835. // sub-local variables
  836. CHString str;
  837. LPWSTR pwszTemp;
  838. // get the buffer
  839. pwszTemp = str.GetBufferSetLength( pidImages->NameLength + 10 ); // +10 to be on safe side
  840. if ( pwszTemp == NULL )
  841. {
  842. SetLastError( E_OUTOFMEMORY );
  843. SaveLastError();
  844. return FALSE;
  845. }
  846. // get the instance name
  847. lstrcpyn( pwszTemp, (LPWSTR) ( (LPBYTE) pidImages + pidImages->NameOffset ), pidImages->NameLength + 1 );
  848. // release buffer
  849. str.ReleaseBuffer();
  850. // check whether this module needs to be added to the list
  851. if ( m_strModules.GetLength() == 0 || StringCompare( str, m_strModules, TRUE, dwLength ) == 0 )
  852. {
  853. // add the info the userdata ( for us we will get that in the form of an array
  854. lIndex = DynArrayAppendString( arrModules, str, 0 );
  855. if ( lIndex == -1 )
  856. {
  857. // append is failed .. this could be because of lack of memory .. stop the enumeration
  858. return FALSE;
  859. }
  860. }
  861. }
  862. catch( ... )
  863. {
  864. SetLastError( E_OUTOFMEMORY );
  865. SaveLastError();
  866. return FALSE;
  867. }
  868. }
  869. // continue looping thru other instances
  870. pidImages = (PPERF_INSTANCE_DEFINITION) ( (LPBYTE) pcbImages + pcbImages->ByteLength );
  871. pcbImages = (PPERF_COUNTER_BLOCK) ( (LPBYTE) pidImages + pidImages->ByteLength );
  872. }
  873. return TRUE;
  874. }
  875. // ***************************************************************************
  876. // Routine Description:
  877. //
  878. // Arguments:
  879. //
  880. // Return Value:
  881. //
  882. // ***************************************************************************
  883. BOOL CTaskList::GetModulesOnRemoteEx( LONG lIndex, TARRAY arrModules )
  884. {
  885. // local variables
  886. HRESULT hr;
  887. LONG lPos = 0;
  888. BOOL bStatus = FALSE;
  889. DWORD dwLength = 0;
  890. CHString strQuery;
  891. CHString strModule;
  892. CHString strMessage;
  893. CHString strFileName;
  894. CHString strExtension;
  895. ULONG ulReturned = 0;
  896. BOOL bResult = FALSE;
  897. BOOL bCanExit = FALSE;
  898. LPCWSTR pwszPath = NULL;
  899. IEnumWbemClassObject* pEnumServices = NULL;
  900. IWbemClassObject* pObjects[ MAX_ENUM_MODULES ];
  901. // check the input values
  902. if ( arrModules == NULL )
  903. return FALSE;
  904. // get the path of the object from the tasks array
  905. pwszPath = DynArrayItemAsString2( m_arrTasks, lIndex, TASK_OBJPATH );
  906. if ( pwszPath == NULL )
  907. return FALSE;
  908. //determine the length of the module name ..
  909. dwLength = 0;
  910. if ( (lPos = m_strModules.Find( L"*" )) != -1 )
  911. dwLength = (DWORD) lPos;
  912. try
  913. {
  914. // init the objects to NULL's
  915. for( DWORD dw = 0; dw < MAX_ENUM_MODULES; dw++ )
  916. pObjects[ dw ] = NULL;
  917. // prepare the query
  918. strQuery.Format( WMI_MODULES_QUERY, pwszPath );
  919. // preare and display the status message
  920. bStatus = TRUE;
  921. strMessage.Format( MSG_MODULESINFO_EX, m_dwProcessId );
  922. PrintProgressMsg( m_hOutput, strMessage + L" --", m_csbi );
  923. // execute the query
  924. hr = m_pWbemServices->ExecQuery( _bstr_t( WMI_QUERY_TYPE ), _bstr_t( strQuery ),
  925. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumServices );
  926. // check the result
  927. if ( FAILED( hr ) )
  928. _com_issue_error( hr );
  929. // set the security
  930. hr = SetInterfaceSecurity( pEnumServices, m_pAuthIdentity );
  931. if ( FAILED( hr ) )
  932. _com_issue_error( hr );
  933. // loop thru the instances
  934. do
  935. {
  936. // get the object ... wait
  937. // NOTE: one-by-one
  938. hr = pEnumServices->Next( WBEM_INFINITE, MAX_ENUM_MODULES, pObjects, &ulReturned );
  939. if ( hr == WBEM_S_FALSE )
  940. {
  941. // we've reached the end of enumeration .. set the flag
  942. bCanExit = TRUE;
  943. }
  944. else if ( hr == WBEM_S_TIMEDOUT || FAILED( hr ))
  945. {
  946. // some error has occured ... oooppps
  947. WMISaveError( hr );
  948. SetLastError( STG_E_UNKNOWN );
  949. break;
  950. }
  951. // reset the counter
  952. bStatus = bStatus ? FALSE : TRUE;
  953. PrintProgressMsg( m_hOutput, strMessage + (( bStatus ) ? L" --" : L" |"), m_csbi );
  954. // loop thru the objects and save the info
  955. for( ULONG ul = 0; ul < ulReturned; ul++ )
  956. {
  957. // get the file name
  958. bResult = PropertyGet( pObjects[ ul ], CIM_DATAFILE_PROPERTY_FILENAME, strFileName );
  959. if ( bResult == FALSE )
  960. continue;
  961. // get the extension
  962. bResult = PropertyGet( pObjects[ ul ], CIM_DATAFILE_PROPERTY_EXTENSION, strExtension );
  963. if ( bResult == FALSE )
  964. continue;
  965. // format the module name
  966. strModule.Format( L"%s.%s", strFileName, strExtension );
  967. // check whether this module needs to be added to the list
  968. if ( m_strModules.GetLength() == 0 || StringCompare( strModule, m_strModules, TRUE, dwLength ) == 0 )
  969. {
  970. // add the info the userdata ( for us we will get that in the form of an array
  971. lIndex = DynArrayAppendString( arrModules, strModule, 0 );
  972. if ( lIndex == -1 )
  973. {
  974. // append is failed .. this could be because of lack of memory .. stop the enumeration
  975. return FALSE;
  976. }
  977. }
  978. // release the interface
  979. SAFE_RELEASE( pObjects[ ul ] );
  980. }
  981. } while ( bCanExit == FALSE );
  982. }
  983. catch( _com_error& e )
  984. {
  985. // save the error
  986. WMISaveError( e );
  987. return FALSE;
  988. }
  989. catch( ... )
  990. {
  991. // out of memory
  992. WMISaveError( E_OUTOFMEMORY );
  993. return FALSE;
  994. }
  995. // release the objects to NULL's
  996. for( DWORD dw = 0; dw < MAX_ENUM_MODULES; dw++ )
  997. {
  998. // release all the objects
  999. SAFE_RELEASE( pObjects[ dw ] );
  1000. }
  1001. // now release the enumeration object
  1002. SAFE_RELEASE( pEnumServices );
  1003. // return
  1004. return TRUE;
  1005. }
  1006. // ***************************************************************************
  1007. // Routine Description:
  1008. //
  1009. // Arguments:
  1010. //
  1011. // Return Value:
  1012. //
  1013. // ***************************************************************************
  1014. #ifndef _WIN64
  1015. BOOL EnumLoadedModulesProc( LPSTR lpszModuleName, ULONG ulModuleBase, ULONG ulModuleSize, PVOID pUserData )
  1016. #else
  1017. BOOL EnumLoadedModulesProc64( LPSTR lpszModuleName, DWORD64 ulModuleBase, ULONG ulModuleSize, PVOID pUserData )
  1018. #endif
  1019. {
  1020. // local variables
  1021. CHString str;
  1022. LONG lIndex = 0;
  1023. TARRAY arrModules = NULL;
  1024. PTMODULESINFO pModulesInfo = NULL;
  1025. // check the input values
  1026. if ( lpszModuleName == NULL || pUserData == NULL )
  1027. return FALSE;
  1028. // check the internal array info
  1029. pModulesInfo = (PTMODULESINFO) pUserData;
  1030. if ( pModulesInfo->dwSignature != SIGNATURE_MODULES || pModulesInfo->arrModules == NULL )
  1031. return FALSE;
  1032. // get the array pointer into the local variable
  1033. arrModules = (TARRAY) pModulesInfo->arrModules;
  1034. try
  1035. {
  1036. // copy the module name into the local string variable
  1037. // ( conversion from multibyte to unicode will automatically take place )
  1038. str = lpszModuleName;
  1039. // check whether this module needs to be added to the list
  1040. if ( pModulesInfo->pwszModule == NULL ||
  1041. StringCompare( str, pModulesInfo->pwszModule, TRUE, pModulesInfo->dwLength ) == 0 )
  1042. {
  1043. // add the info the userdata ( for us we will get that in the form of an array
  1044. lIndex = DynArrayAppendString( arrModules, str, 0 );
  1045. if ( lIndex == -1 )
  1046. {
  1047. // append is failed .. this could be because of lack of memory .. stop the enumeration
  1048. return FALSE;
  1049. }
  1050. }
  1051. }
  1052. catch( ... )
  1053. {
  1054. // out of memory stop the enumeration
  1055. return FALSE;
  1056. }
  1057. // success .. continue the enumeration
  1058. return TRUE;
  1059. }
  1060. // ***************************************************************************
  1061. // Routine Description:
  1062. // prpepares the columns information
  1063. //
  1064. // Arguments:
  1065. // [ in ] bVerbose : informs whether preparation has to be done for verbose display
  1066. // [ out ] pColumns : filled with columns information like, thier o/p type, position,
  1067. // width, heading etc
  1068. // Return Value:
  1069. // NONE
  1070. //
  1071. // ***************************************************************************
  1072. VOID CTaskList::PrepareColumns()
  1073. {
  1074. // local variables
  1075. PTCOLUMNS pCurrentColumn = NULL;
  1076. // host name
  1077. pCurrentColumn = m_pColumns + CI_HOSTNAME;
  1078. pCurrentColumn->dwWidth = COLWIDTH_HOSTNAME;
  1079. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_HIDECOLUMN;
  1080. pCurrentColumn->pFunction = NULL;
  1081. pCurrentColumn->pFunctionData = NULL;
  1082. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1083. lstrcpy( pCurrentColumn->szColumn, COLHEAD_HOSTNAME );
  1084. // status
  1085. pCurrentColumn = m_pColumns + CI_STATUS;
  1086. pCurrentColumn->dwWidth = COLWIDTH_STATUS;
  1087. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_HIDECOLUMN;
  1088. pCurrentColumn->pFunction = NULL;
  1089. pCurrentColumn->pFunctionData = NULL;
  1090. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1091. lstrcpy( pCurrentColumn->szColumn, COLHEAD_STATUS );
  1092. // image name
  1093. pCurrentColumn = m_pColumns + CI_IMAGENAME;
  1094. pCurrentColumn->dwWidth = COLWIDTH_IMAGENAME;
  1095. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_HIDECOLUMN;
  1096. pCurrentColumn->pFunction = NULL;
  1097. pCurrentColumn->pFunctionData = NULL;
  1098. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1099. lstrcpy( pCurrentColumn->szColumn, COLHEAD_IMAGENAME );
  1100. // pid
  1101. pCurrentColumn = m_pColumns + CI_PID;
  1102. pCurrentColumn->dwWidth = COLWIDTH_PID;
  1103. pCurrentColumn->dwFlags = SR_TYPE_NUMERIC | SR_HIDECOLUMN;
  1104. pCurrentColumn->pFunction = NULL;
  1105. pCurrentColumn->pFunctionData = NULL;
  1106. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1107. lstrcpy( pCurrentColumn->szColumn, COLHEAD_PID );
  1108. // session name
  1109. pCurrentColumn = m_pColumns + CI_SESSIONNAME;
  1110. pCurrentColumn->dwWidth = COLWIDTH_SESSIONNAME;
  1111. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_HIDECOLUMN;
  1112. pCurrentColumn->pFunction = NULL;
  1113. pCurrentColumn->pFunctionData = NULL;
  1114. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1115. lstrcpy( pCurrentColumn->szColumn, COLHEAD_SESSIONNAME );
  1116. // session#
  1117. pCurrentColumn = m_pColumns + CI_SESSION;
  1118. pCurrentColumn->dwWidth = COLWIDTH_SESSION;
  1119. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_ALIGN_LEFT | SR_HIDECOLUMN;
  1120. pCurrentColumn->pFunction = NULL;
  1121. pCurrentColumn->pFunctionData = NULL;
  1122. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1123. lstrcpy( pCurrentColumn->szColumn, COLHEAD_SESSION );
  1124. // window name
  1125. pCurrentColumn = m_pColumns + CI_WINDOWTITLE;
  1126. pCurrentColumn->dwWidth = COLWIDTH_WINDOWTITLE;
  1127. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_HIDECOLUMN | SR_SHOW_NA_WHEN_BLANK;
  1128. pCurrentColumn->pFunction = NULL;
  1129. pCurrentColumn->pFunctionData = NULL;
  1130. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1131. lstrcpy( pCurrentColumn->szColumn, COLHEAD_WINDOWTITLE );
  1132. // user name
  1133. pCurrentColumn = m_pColumns + CI_USERNAME;
  1134. pCurrentColumn->dwWidth = COLWIDTH_USERNAME;
  1135. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_HIDECOLUMN;
  1136. pCurrentColumn->pFunction = NULL;
  1137. pCurrentColumn->pFunctionData = NULL;
  1138. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1139. lstrcpy( pCurrentColumn->szColumn, COLHEAD_USERNAME );
  1140. // cpu time
  1141. pCurrentColumn = m_pColumns + CI_CPUTIME;
  1142. pCurrentColumn->dwWidth = COLWIDTH_CPUTIME;
  1143. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_ALIGN_LEFT | SR_HIDECOLUMN;
  1144. pCurrentColumn->pFunction = NULL;
  1145. pCurrentColumn->pFunctionData = NULL;
  1146. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1147. lstrcpy( pCurrentColumn->szColumn, COLHEAD_CPUTIME );
  1148. // mem usage
  1149. pCurrentColumn = m_pColumns + CI_MEMUSAGE;
  1150. pCurrentColumn->dwWidth = COLWIDTH_MEMUSAGE;
  1151. pCurrentColumn->dwFlags = SR_TYPE_STRING | SR_ALIGN_LEFT | SR_HIDECOLUMN;
  1152. pCurrentColumn->pFunction = NULL;
  1153. pCurrentColumn->pFunctionData = NULL;
  1154. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1155. lstrcpy( pCurrentColumn->szColumn, COLHEAD_MEMUSAGE );
  1156. // services
  1157. pCurrentColumn = m_pColumns + CI_SERVICES;
  1158. pCurrentColumn->dwWidth = COLWIDTH_MODULES_WRAP;
  1159. pCurrentColumn->dwFlags = SR_ARRAY | SR_TYPE_STRING | SR_NO_TRUNCATION | SR_HIDECOLUMN | SR_SHOW_NA_WHEN_BLANK;
  1160. pCurrentColumn->pFunction = NULL;
  1161. pCurrentColumn->pFunctionData = NULL;
  1162. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1163. lstrcpy( pCurrentColumn->szColumn, COLHEAD_SERVICES );
  1164. // modules
  1165. pCurrentColumn = m_pColumns + CI_MODULES;
  1166. pCurrentColumn->dwWidth = COLWIDTH_MODULES_WRAP;
  1167. pCurrentColumn->dwFlags = SR_ARRAY | SR_TYPE_STRING | SR_NO_TRUNCATION | SR_HIDECOLUMN | SR_SHOW_NA_WHEN_BLANK;
  1168. pCurrentColumn->pFunction = NULL;
  1169. pCurrentColumn->pFunctionData = NULL;
  1170. lstrcpy( pCurrentColumn->szFormat, NULL_STRING );
  1171. lstrcpy( pCurrentColumn->szColumn, COLHEAD_MODULES );
  1172. //
  1173. // based on the option selected by the user .. show only needed columns
  1174. if ( m_bAllServices == TRUE )
  1175. {
  1176. ( m_pColumns + CI_IMAGENAME )->dwFlags &= ~( SR_HIDECOLUMN );
  1177. ( m_pColumns + CI_PID )->dwFlags &= ~( SR_HIDECOLUMN );
  1178. ( m_pColumns + CI_SERVICES )->dwFlags &= ~( SR_HIDECOLUMN );
  1179. }
  1180. else if ( m_bAllModules == TRUE )
  1181. {
  1182. ( m_pColumns + CI_IMAGENAME )->dwFlags &= ~( SR_HIDECOLUMN );
  1183. ( m_pColumns + CI_PID )->dwFlags &= ~( SR_HIDECOLUMN );
  1184. ( m_pColumns + CI_MODULES )->dwFlags &= ~( SR_HIDECOLUMN );
  1185. }
  1186. else
  1187. {
  1188. // default ... enable min. columns
  1189. ( m_pColumns + CI_IMAGENAME )->dwFlags &= ~( SR_HIDECOLUMN );
  1190. ( m_pColumns + CI_PID )->dwFlags &= ~( SR_HIDECOLUMN );
  1191. ( m_pColumns + CI_SESSIONNAME )->dwFlags &= ~( SR_HIDECOLUMN );
  1192. ( m_pColumns + CI_SESSION )->dwFlags &= ~( SR_HIDECOLUMN );
  1193. ( m_pColumns + CI_MEMUSAGE )->dwFlags &= ~( SR_HIDECOLUMN );
  1194. // check if verbose option is specified .. show other columns
  1195. if ( m_bVerbose == TRUE )
  1196. {
  1197. ( m_pColumns + CI_STATUS )->dwFlags &= ~( SR_HIDECOLUMN );
  1198. ( m_pColumns + CI_USERNAME )->dwFlags &= ~( SR_HIDECOLUMN );
  1199. ( m_pColumns + CI_CPUTIME )->dwFlags &= ~( SR_HIDECOLUMN );
  1200. ( m_pColumns + CI_WINDOWTITLE )->dwFlags &= ~( SR_HIDECOLUMN );
  1201. }
  1202. }
  1203. }