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.

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