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.

6691 lines
214 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. smonctrl.cpp
  5. Abstract:
  6. This module handles the graphing window.
  7. --*/
  8. #pragma warning ( disable : 4127 )
  9. #ifndef _LOG_INCLUDE_DATA
  10. #define _LOG_INCLUDE_DATA 0
  11. #endif
  12. //==========================================================================//
  13. // Includes //
  14. //==========================================================================//
  15. #include <limits.h> // for INT_MAX
  16. #include <assert.h>
  17. #include <windows.h> // for Common controls below
  18. #ifdef _WIN32_IE
  19. #if _WIN32_IE < 0x0400
  20. #undef _WIN32_IE
  21. #define _WIN32_IE 0x0400 // for NMTBCUSTOMDRAW
  22. #endif // < 0x0400
  23. #endif // defined
  24. #include <commctrl.h>
  25. #include <htmlhelp.h>
  26. #include <shellapi.h>
  27. #include <pdhp.h>
  28. #include "polyline.h"
  29. #include "cntrtree.h"
  30. #include "utils.h"
  31. #include "commdlg.h"
  32. #include "unihelpr.h"
  33. #include "winperf.h"
  34. #include "pdhmsg.h"
  35. #include "smonmsg.h"
  36. #include "visuals.h"
  37. #include "statbar.h"
  38. #include "snapbar.h"
  39. #include "legend.h"
  40. #include "toolbar.h"
  41. #include "grphdsp.h"
  42. #include "report.h"
  43. #include "browser.h"
  44. #include "appmema.h"
  45. #include "ipropbag.h"
  46. #include "logsrc.h"
  47. #include "smonmsg.h"
  48. #include "smonid.h"
  49. #include "smonctrl.h"
  50. #include "strnoloc.h"
  51. //==========================================================================//
  52. // Constants //
  53. //==========================================================================//
  54. extern CCounterTree g_tree;
  55. extern DWORD g_dwScriptPolicy;
  56. #define DBG_SHOW_STATUS_PRINTS 1
  57. //=============================//
  58. // Graph Class //
  59. //=============================//
  60. static DWORD dwDbgPrintLevel = 0;
  61. static TCHAR szSysmonCtrlWndClass[] = TEXT("SysmonCtrl") ;
  62. static TCHAR LineEndStr[] = TEXT("\n") ;
  63. static TCHAR SpaceStr[] = TEXT(" ");
  64. typedef struct {
  65. CSysmonControl *pCtrl;
  66. PCGraphItem pFirstItem;
  67. } ENUM_ADD_COUNTER_CALLBACK_INFO;
  68. BOOL
  69. APIENTRY
  70. SaveDataDlgHookProc (
  71. HWND hDlg,
  72. UINT iMessage,
  73. WPARAM wParam,
  74. LPARAM lParam
  75. )
  76. {
  77. BOOL bHandled ;
  78. CSysmonControl *pCtrl;
  79. LONG lFilterValue;
  80. BOOL bGoodNumber = FALSE;
  81. UNREFERENCED_PARAMETER (wParam);
  82. // lparam = CSysmonControl class pointer
  83. bHandled = TRUE ;
  84. switch (iMessage) {
  85. case WM_INITDIALOG:
  86. // initialize the filter edit control with the current value
  87. OPENFILENAME *pOfn;
  88. pOfn= (OPENFILENAME *)lParam;
  89. // get the control class pointer from the OPENFILENAME struct
  90. pCtrl = (CSysmonControl *)pOfn->lCustData;
  91. // save the pointer to the control class as a DLG data word
  92. SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR)pCtrl);
  93. lFilterValue = pCtrl->GetSaveDataFilter();
  94. SetDlgItemInt (hDlg, IDC_SAVEDATA_EDIT, (UINT)lFilterValue, FALSE);
  95. // limit reduction to 1/9999 records
  96. SendDlgItemMessage (hDlg, IDC_SAVEDATA_EDIT, EM_LIMITTEXT, (WPARAM)4, (LPARAM)0);
  97. bHandled = TRUE ;
  98. break ;
  99. case WM_DESTROY:
  100. // the user has closed the dialog box so get the relog filter value
  101. // (note: this should be ignored if the user cancels the dialog)
  102. pCtrl = (CSysmonControl *)GetWindowLongPtr (hDlg, DWLP_USER);
  103. lFilterValue = GetDlgItemInt (hDlg, IDC_SAVEDATA_EDIT, &bGoodNumber, FALSE);
  104. if (bGoodNumber) {
  105. pCtrl->SetSaveDataFilter( lFilterValue );
  106. }
  107. bHandled = TRUE ;
  108. break ;
  109. #if 0
  110. TODO. Tempoarily commented out the warning message code, after RC2,
  111. Enable this piece of code
  112. case WM_COMMAND:
  113. if ( (LOWORD(wParam) == IDC_SAVEDATA_EDIT) && (HIWORD(wParam) == EN_CHANGE) )
  114. {
  115. lFilterValue = GetDlgItemInt (hDlg, IDC_SAVEDATA_EDIT, &bGoodNumber, FALSE);
  116. if (bGoodNumber && lFilterValue == 0) {
  117. pCtrl = (CSysmonControl *)GetWindowLongPtr (hDlg, DWLP_USER);
  118. MessageBox(hDlg,
  119. ResourceString(IDS_BAD_INPUT_ERR),
  120. ResourceString(IDS_APP_NAME),
  121. MB_OK | MB_ICONSTOP);
  122. lFilterValue = pCtrl->GetSaveDataFilter();
  123. SetDlgItemInt (hDlg, IDC_SAVEDATA_EDIT, (UINT)lFilterValue, FALSE);
  124. bHandled = TRUE;
  125. }
  126. }
  127. #endif
  128. default:
  129. bHandled = FALSE ;
  130. break;
  131. }
  132. return (bHandled) ;
  133. }
  134. HRESULT
  135. AddCounterCallback (
  136. LPTSTR pszPathName,
  137. DWORD_PTR lpUserData,
  138. DWORD dwFlags
  139. )
  140. {
  141. ENUM_ADD_COUNTER_CALLBACK_INFO *pInfo = (ENUM_ADD_COUNTER_CALLBACK_INFO*)lpUserData;
  142. CSysmonControl *pCtrl = pInfo->pCtrl;
  143. PCGraphItem pGraphItem;
  144. HRESULT hr;
  145. hr = pCtrl->AddSingleCounter(pszPathName, &pGraphItem);
  146. if (SUCCEEDED(hr)) {
  147. if (dwFlags & BROWSE_WILDCARD)
  148. pGraphItem->m_fGenerated = TRUE;
  149. if ( NULL == pInfo->pFirstItem ) {
  150. // Keep the reference count if returning the pointer.
  151. pInfo->pFirstItem = pGraphItem;
  152. } else {
  153. pGraphItem->Release();
  154. }
  155. }
  156. return hr;
  157. }
  158. #pragma warning( disable : 4355 ) // "this" use in initializer list
  159. CSysmonControl::CSysmonControl(
  160. PCPolyline pObj )
  161. : m_OleFont(this),
  162. m_pObj(pObj), // Pointer back to owner.
  163. m_fInitialized(FALSE),
  164. m_fViewInitialized(FALSE),
  165. m_hWnd(NULL),
  166. m_pLegend(NULL),
  167. m_pGraphDisp(NULL),
  168. m_pStatsBar(NULL),
  169. m_pSnapBar(NULL),
  170. m_pReport(NULL),
  171. m_pToolbar(NULL),
  172. m_hQuery(NULL),
  173. m_TimerID(0),
  174. m_fPendingUpdate(FALSE),
  175. m_fPendingSizeChg(FALSE),
  176. m_fPendingFontChg(FALSE),
  177. m_fPendingLogViewChg(FALSE),
  178. m_fPendingLogCntrChg(FALSE),
  179. m_pSelectedItem(NULL),
  180. m_fUIDead(FALSE),
  181. m_fUserMode(FALSE),
  182. m_hAccel(NULL),
  183. m_bLogFileSource(FALSE),
  184. m_bSampleDataLoaded(FALSE),
  185. m_bLoadingCounters(FALSE),
  186. m_bMissedSample(FALSE),
  187. m_bDisplayedMissedSampleMessage(FALSE),
  188. m_bSettingsLoaded(FALSE),
  189. m_szErrorPathList ( NULL ),
  190. m_dwErrorPathListLen ( 0 ),
  191. m_dwErrorPathBufLen ( 0 ),
  192. // Default attributes
  193. m_iColorIndex(0),
  194. m_iWidthIndex(0),
  195. m_iStyleIndex(0),
  196. m_iScaleFactor(INT_MAX),
  197. m_iAppearance(eAppear3D),
  198. m_iBorderStyle(eBorderNone),
  199. m_dZoomFactor(1.0),
  200. m_lcidCurrent ( LOCALE_USER_DEFAULT )
  201. {
  202. PGRAPH_OPTIONS pOptions;
  203. m_LoadedVersion.iMajor = SMONCTRL_MAJ_VERSION;
  204. m_LoadedVersion.iMinor = SMONCTRL_MIN_VERSION;
  205. m_clrBackCtl = GetSysColor(COLOR_BTNFACE);
  206. m_clrFgnd = GetSysColor(COLOR_BTNTEXT);
  207. m_clrBackPlot = GetSysColor(COLOR_WINDOW);
  208. m_clrGrid = RGB(128,128,128); // Medium gray
  209. m_clrTimeBar = RGB(255,0,0); // Red
  210. m_lSaveDataToLogFilterValue = 1; // default save data to log filter is 1
  211. // Init graph parameters
  212. pOptions = &pObj->m_Graph.Options;
  213. pOptions->bLegendChecked = TRUE;
  214. pOptions->bToolbarChecked = TRUE;
  215. pOptions->bLabelsChecked = TRUE;
  216. pOptions->bVertGridChecked = FALSE;
  217. pOptions->bHorzGridChecked = FALSE;
  218. pOptions->bValueBarChecked = TRUE;
  219. pOptions->bManualUpdate = FALSE;
  220. pOptions->bHighlight = FALSE;
  221. pOptions->bReadOnly = FALSE;
  222. pOptions->bMonitorDuplicateInstances = TRUE;
  223. pOptions->bAmbientFont = TRUE;
  224. pOptions->iVertMax = 100;
  225. pOptions->iVertMin = 0;
  226. pOptions->fUpdateInterval = (float)1.0;
  227. pOptions->iDisplayFilter = 1;
  228. pOptions->iDisplayType = sysmonLineGraph;
  229. pOptions->iReportValueType = sysmonDefaultValue;
  230. pOptions->pszGraphTitle = NULL;
  231. pOptions->pszYaxisTitle = NULL;
  232. pOptions->clrBackCtl = ( 0x80000000 | COLOR_BTNFACE );
  233. pOptions->clrGrid = m_clrGrid;
  234. pOptions->clrTimeBar = m_clrTimeBar;
  235. pOptions->clrFore = NULL_COLOR;
  236. pOptions->clrBackPlot = NULL_COLOR;
  237. pOptions->iAppearance = NULL_APPEARANCE;
  238. pOptions->iBorderStyle = eBorderNone;
  239. pOptions->iDataSourceType = sysmonCurrentActivity;
  240. // Init data source info
  241. memset ( &m_DataSourceInfo, 0, sizeof ( m_DataSourceInfo ) );
  242. m_DataSourceInfo.llStartDisp = MIN_TIME_VALUE;
  243. m_DataSourceInfo.llStopDisp = MAX_TIME_VALUE;
  244. // Init collection thread info
  245. m_CollectInfo.hThread = NULL;
  246. m_CollectInfo.hEvent = NULL;
  247. m_CollectInfo.iMode = COLLECT_SUSPEND;
  248. InitializeCriticalSection(&m_CounterDataLock);
  249. // Cache pointer to object's history control
  250. m_pHistCtrl = &pObj->m_Graph.History;
  251. assert ( NULL != pObj );
  252. pObj->m_Graph.LogViewTempStart = MIN_TIME_VALUE;
  253. pObj->m_Graph.LogViewTempStop = MAX_TIME_VALUE;
  254. // Init the log view and time steppers. They might be used before
  255. // SizeComponents is called, for example when a property bag is loaded.
  256. // The width has not been calculated yet, is initialized here
  257. // to an arbitrary number.
  258. pObj->m_Graph.TimeStepper.Init( MAX_GRAPH_SAMPLES, MAX_GRAPH_SAMPLES - 2 );
  259. pObj->m_Graph.LogViewStartStepper.Init( MAX_GRAPH_SAMPLES, MAX_GRAPH_SAMPLES - 2 );
  260. pObj->m_Graph.LogViewStopStepper.Init( MAX_GRAPH_SAMPLES, MAX_GRAPH_SAMPLES - 2 );
  261. m_pHistCtrl->bLogSource = FALSE;
  262. m_pHistCtrl->nMaxSamples = MAX_GRAPH_SAMPLES;
  263. m_pHistCtrl->iCurrent = 0;
  264. m_pHistCtrl->nSamples = 0;
  265. m_pHistCtrl->nBacklog = 0;
  266. // Keep record of current size to avoide unnecessary calls to SizeComponents
  267. SetRect ( &m_rectCurrentClient,0,0,0,0 );
  268. }
  269. BOOL
  270. CSysmonControl::AllocateSubcomponents( void )
  271. {
  272. BOOL bResult = TRUE;
  273. m_pLegend = new CLegend;
  274. m_pGraphDisp = new CGraphDisp;
  275. m_pStatsBar = new CStatsBar;
  276. m_pSnapBar = new CSnapBar;
  277. m_pReport = new CReport;
  278. m_pToolbar = new CSysmonToolbar;
  279. if (!m_pLegend)
  280. bResult = FALSE;
  281. if (!m_pGraphDisp)
  282. bResult = FALSE;
  283. if (!m_pStatsBar)
  284. bResult = FALSE;
  285. if (!m_pSnapBar)
  286. bResult = FALSE;
  287. if (!m_pReport)
  288. bResult = FALSE;
  289. if (!m_pToolbar)
  290. bResult = FALSE;
  291. if (!bResult) {
  292. DeInit();
  293. return bResult;
  294. }
  295. if ( FAILED(m_OleFont.Init()) )
  296. bResult = FALSE;
  297. return bResult;
  298. }
  299. CSysmonControl::~CSysmonControl( void )
  300. {
  301. PCGraphItem pItem;
  302. PCGraphItem pNext;
  303. PCLogFileItem pLogFile;
  304. PCLogFileItem pNextLogFile;
  305. CloseQuery();
  306. DeInit();
  307. DeleteCriticalSection(&m_CounterDataLock);
  308. // Release all graph items
  309. pItem = FirstCounter();
  310. while ( NULL != pItem ) {
  311. pNext = pItem->Next();
  312. pItem->Release();
  313. pItem = pNext;
  314. }
  315. // Release all log file items
  316. pLogFile = FirstLogFile();
  317. while ( NULL != pLogFile ) {
  318. pNextLogFile = pLogFile->Next();
  319. pLogFile->Release();
  320. pLogFile = pNextLogFile;
  321. }
  322. if (m_DataSourceInfo.szSqlDsnName != NULL) {
  323. delete(m_DataSourceInfo.szSqlDsnName);
  324. m_DataSourceInfo.szSqlDsnName = NULL;
  325. }
  326. if (m_DataSourceInfo.szSqlLogSetName != NULL) {
  327. delete(m_DataSourceInfo.szSqlLogSetName);
  328. m_DataSourceInfo.szSqlLogSetName = NULL;
  329. }
  330. if (m_hWnd != NULL)
  331. DestroyWindow(m_hWnd);
  332. if (m_pObj->m_Graph.Options.pszGraphTitle != NULL)
  333. delete(m_pObj->m_Graph.Options.pszGraphTitle);
  334. if (m_pObj->m_Graph.Options.pszYaxisTitle != NULL)
  335. delete(m_pObj->m_Graph.Options.pszYaxisTitle);
  336. ClearErrorPathList();
  337. }
  338. void CSysmonControl::DeInit( void )
  339. {
  340. if (m_pLegend) {
  341. delete m_pLegend;
  342. m_pLegend = NULL;
  343. }
  344. if (m_pGraphDisp) {
  345. delete m_pGraphDisp;
  346. m_pGraphDisp = NULL;
  347. }
  348. if (m_pStatsBar) {
  349. delete m_pStatsBar;
  350. m_pStatsBar = NULL;
  351. }
  352. if (m_pSnapBar) {
  353. delete m_pSnapBar;
  354. m_pSnapBar = NULL;
  355. }
  356. if (m_pReport) {
  357. delete m_pReport;
  358. m_pReport = NULL;
  359. }
  360. if (m_pToolbar) {
  361. delete m_pToolbar;
  362. m_pToolbar = NULL;
  363. }
  364. ClearErrorPathList();
  365. }
  366. void CSysmonControl::ApplyChanges( HDC hAttribDC )
  367. {
  368. if ( m_fPendingUpdate ) {
  369. // Clear the master update flag
  370. m_fPendingUpdate = FALSE;
  371. // set the toolbar state
  372. m_pToolbar->ShowToolbar(m_pObj->m_Graph.Options.bToolbarChecked);
  373. // If log view changed or counters added
  374. // we need to resample the log file
  375. if (m_fPendingLogViewChg || m_fPendingLogCntrChg) {
  376. SampleLogFile(m_fPendingLogViewChg);
  377. // Must init time steppers before calling ResetLogViewTempTimeRange
  378. ResetLogViewTempTimeRange ( );
  379. m_fPendingLogViewChg = FALSE;
  380. m_fPendingLogCntrChg = FALSE;
  381. }
  382. if (m_fPendingFontChg || m_fPendingSizeChg) {
  383. //CalcZoomFactor();
  384. if (m_fPendingFontChg) {
  385. if (NULL != hAttribDC ) {
  386. m_pLegend->ChangeFont(hAttribDC);
  387. m_pStatsBar->ChangeFont(hAttribDC);
  388. m_pGraphDisp->ChangeFont(hAttribDC);
  389. m_fPendingFontChg = FALSE;
  390. }
  391. }
  392. if ( NULL != hAttribDC ) {
  393. SizeComponents( hAttribDC );
  394. m_fPendingSizeChg = FALSE;
  395. }
  396. }
  397. m_pToolbar->SyncToolbar();
  398. }
  399. }
  400. void
  401. CSysmonControl::DrawBorder ( HDC hDC )
  402. {
  403. if ( eBorderSingle == m_iBorderStyle ) {
  404. RECT rectClient;
  405. // Get dimensions of window
  406. GetClientRect (m_hWnd, &rectClient) ;
  407. if ( eAppear3D == m_iAppearance ) {
  408. DrawEdge(hDC, &rectClient, EDGE_RAISED, BF_RECT);
  409. } else {
  410. SelectBrush (hDC, GetStockObject (HOLLOW_BRUSH)) ;
  411. SelectPen (hDC, GetStockObject (BLACK_PEN)) ;
  412. Rectangle (hDC, rectClient.left, rectClient.top, rectClient.right, rectClient.bottom );
  413. }
  414. }
  415. }
  416. void CSysmonControl::Paint ( void )
  417. {
  418. HDC hDC ;
  419. PAINTSTRUCT ps ;
  420. if ( DisplayMissedSampleMessage() ) {
  421. MessageBox(m_hWnd, ResourceString(IDS_SAMPLE_DATA_MISSING), ResourceString(IDS_APP_NAME),
  422. MB_OK | MB_ICONINFORMATION);
  423. }
  424. hDC = BeginPaint (m_hWnd, &ps) ;
  425. ApplyChanges( hDC ) ;
  426. if ( m_fViewInitialized ) {
  427. m_pStatsBar->Draw(hDC, hDC, &ps.rcPaint);
  428. m_pGraphDisp->Draw(hDC, hDC, FALSE, FALSE, &ps.rcPaint);
  429. DrawBorder( hDC );
  430. }
  431. EndPaint (m_hWnd, &ps) ;
  432. }
  433. void
  434. CSysmonControl::OnDblClick(INT x, INT y)
  435. {
  436. if ( REPORT_GRAPH != m_pObj->m_Graph.Options.iDisplayType ) {
  437. PCGraphItem pItem = m_pGraphDisp->GetItem ( x,y );
  438. if ( NULL != pItem ) {
  439. SelectCounter( pItem );
  440. DblClickCounter ( pItem );
  441. }
  442. } else {
  443. assert ( FALSE );
  444. }
  445. }
  446. DWORD
  447. CSysmonControl::ProcessCommandLine ( )
  448. {
  449. DWORD dwStatus = ERROR_SUCCESS;
  450. LPCWSTR pszNext;
  451. LPTSTR pszWmi = NULL;
  452. LPTSTR pszSettings = NULL;
  453. LPWSTR* pszArgList = NULL;
  454. INT iNumArgs;
  455. INT iArgIndex;
  456. LPWSTR pszNextArg = NULL;
  457. LPWSTR pszThisArg = NULL;
  458. TCHAR szFileName[MAX_PATH];
  459. TCHAR szTemp[MAX_PATH];
  460. LPTSTR pszToken = NULL;
  461. HRESULT hr = S_OK;
  462. pszWmi = ResourceString ( IDS_CMDARG_WMI );
  463. pszSettings = ResourceString ( IDS_CMDARG_SETTINGS );
  464. pszNext = GetCommandLineW();
  465. pszArgList = CommandLineToArgvW ( pszNext, &iNumArgs );
  466. if ( NULL != pszArgList ) {
  467. // This code assumes that UNICODE is defined. That is, TCHAR is the
  468. // same size as WCHAR.
  469. // Todo: Define _T constants as L constants
  470. // Todo: Filename, etc. as WCHAR
  471. assert ( sizeof(TCHAR) == sizeof (WCHAR) );
  472. for ( iArgIndex = 0; iArgIndex < iNumArgs; iArgIndex++ ) {
  473. pszNextArg = (LPWSTR)pszArgList[iArgIndex];
  474. pszThisArg = pszNextArg;
  475. while ( 0 != *pszThisArg ) {
  476. if ( *pszThisArg++ == _T('/') ) { // argument found
  477. lstrcpyn ( szTemp, pszThisArg, min(lstrlen(pszThisArg)+1, MAX_PATH ) );
  478. pszToken = _tcstok ( szTemp, _T("/ =\"") );
  479. if ( 0 == lstrcmpi ( pszToken, pszWmi ) ) {
  480. // Ignore PDH errors. The only possible error is that the default data source has
  481. // already been set for this process.
  482. PdhSetDefaultRealTimeDataSource ( DATA_SOURCE_WBEM );
  483. } else if ( 0 == lstrcmpi ( pszToken, pszSettings ) ) {
  484. // Strip the initial non-token characters for string comparison.
  485. pszThisArg = _tcsspnp ( pszNextArg, _T("/ =\"") );
  486. if ( 0 == lstrcmpi ( pszThisArg, pszSettings ) ) {
  487. // Get the next argument (the file name)
  488. iArgIndex++;
  489. pszNextArg = (LPWSTR)pszArgList[iArgIndex];
  490. pszThisArg = pszNextArg;
  491. } else {
  492. // File was created by Windows 2000 perfmon5.exe,
  493. // so file name is part of the arg.
  494. ZeroMemory ( szFileName, sizeof ( szFileName ) );
  495. pszThisArg += lstrlen ( pszSettings );
  496. lstrcpyn ( szFileName, pszThisArg, min(lstrlen(pszThisArg)+1, MAX_PATH ) );
  497. pszThisArg = _tcstok ( szFileName, _T("=\"") );
  498. }
  499. hr = LoadFromFile( pszThisArg, TRUE );
  500. if ( SMON_STATUS_NO_SYSMON_OBJECT != hr ) {
  501. if ( SUCCEEDED ( hr ) ) {
  502. m_bSettingsLoaded = TRUE;
  503. } // else LoadFromFile displays messages for other errors
  504. } else {
  505. // SMON_STATUS_NO_SYSMON_OBJECT == hr
  506. MessageBox(
  507. m_hWnd,
  508. ResourceString(IDS_NOSYSMONOBJECT_ERR ),
  509. ResourceString(IDS_APP_NAME),
  510. MB_OK | MB_ICONERROR);
  511. }
  512. }
  513. }
  514. }
  515. }
  516. }
  517. if ( NULL != pszArgList ) {
  518. GlobalFree ( pszArgList );
  519. }
  520. return dwStatus;
  521. }
  522. HRESULT
  523. CSysmonControl::LoadFromFile ( LPTSTR pszFileName, BOOL bAllData )
  524. {
  525. HRESULT hr = S_OK;
  526. TCHAR szLocalName [MAX_PATH+1];
  527. LPTSTR pFileNameStart;
  528. HANDLE hFindFile;
  529. WIN32_FIND_DATA FindFileInfo;
  530. INT iNameOffset;
  531. lstrcpyn ( szLocalName, pszFileName, MAX_PATH );
  532. pFileNameStart = ExtractFileName (szLocalName) ;
  533. iNameOffset = (INT)(pFileNameStart - szLocalName);
  534. // convert short filename to long NTFS filename if necessary
  535. hFindFile = FindFirstFile ( szLocalName, &FindFileInfo) ;
  536. if (hFindFile && hFindFile != INVALID_HANDLE_VALUE) {
  537. if ( ConfirmSampleDataOverwrite ( ) ) {
  538. DWORD dwMsgStatus = ERROR_SUCCESS;
  539. HANDLE hOpenFile;
  540. INT iCharCount;
  541. // append the file name back to the path name
  542. iCharCount = lstrlen (FindFileInfo.cFileName)+1;
  543. iCharCount = min (iCharCount, ( MAX_PATH - iNameOffset ));
  544. lstrcpyn (&szLocalName[iNameOffset], FindFileInfo.cFileName, iCharCount) ;
  545. FindClose (hFindFile) ;
  546. // Open the file
  547. hOpenFile = CreateFile (
  548. szLocalName,
  549. GENERIC_READ,
  550. 0, // Not shared
  551. NULL, // Security attributes
  552. OPEN_EXISTING,
  553. FILE_ATTRIBUTE_NORMAL,
  554. NULL );
  555. if ( hOpenFile && hOpenFile != INVALID_HANDLE_VALUE ) {
  556. DWORD dwFileSize;
  557. DWORD dwFileSizeHigh;
  558. DWORD dwFileSizeRead;
  559. LPTSTR pszData;
  560. // Read the file contents into a memory buffer.
  561. dwFileSize = GetFileSize ( hOpenFile, &dwFileSizeHigh );
  562. assert ( 0 == dwFileSizeHigh );
  563. pszData = new TCHAR[(dwFileSize + sizeof(TCHAR))/sizeof(TCHAR)];
  564. if ( NULL != pszData ) {
  565. if ( ReadFile ( hOpenFile, pszData, dwFileSize, &dwFileSizeRead, NULL ) ) {
  566. // Paste all settings from the memory buffer.
  567. hr = PasteFromBuffer ( pszData, bAllData );
  568. if ( E_OUTOFMEMORY == hr ) {
  569. dwMsgStatus = ERROR_NOT_ENOUGH_MEMORY;
  570. }
  571. } else {
  572. dwMsgStatus = GetLastError();
  573. hr = HRESULT_FROM_WIN32(dwMsgStatus);
  574. }
  575. delete pszData;
  576. } else {
  577. dwMsgStatus = ERROR_NOT_ENOUGH_MEMORY;
  578. hr = E_OUTOFMEMORY;
  579. }
  580. CloseHandle ( hOpenFile );
  581. } else {
  582. // Return file system error
  583. dwMsgStatus = GetLastError();
  584. hr = HRESULT_FROM_WIN32(dwMsgStatus);
  585. }
  586. if ( ERROR_SUCCESS != dwMsgStatus ) {
  587. TCHAR* pszMessage = NULL;
  588. TCHAR szSystemMessage[MAX_PATH+1];
  589. pszMessage = new TCHAR [lstrlen(szLocalName) + 2*MAX_PATH + 1];
  590. if ( NULL != pszMessage ) {
  591. _stprintf ( pszMessage, ResourceString(IDS_READFILE_ERR), szLocalName );
  592. FormatSystemMessage ( dwMsgStatus, szSystemMessage, MAX_PATH*2 );
  593. lstrcat ( pszMessage, szSystemMessage );
  594. MessageBox(Window(), pszMessage, ResourceString(IDS_APP_NAME),
  595. MB_OK | MB_ICONSTOP);
  596. delete pszMessage;
  597. }
  598. }
  599. }
  600. }
  601. return hr;
  602. }
  603. void
  604. CSysmonControl::OnDropFile ( WPARAM wParam )
  605. {
  606. TCHAR szFileName [MAX_PATH+1];
  607. INT iFileCount = 0;
  608. HRESULT hr = S_OK;
  609. USES_CONVERSION
  610. iFileCount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0) ;
  611. if ( iFileCount > 0 ) {
  612. // we only open the first file for now
  613. DragQueryFile((HDROP) wParam, 0, szFileName, MAX_PATH+1) ;
  614. hr = LoadFromFile ( szFileName, FALSE );
  615. if ( SMON_STATUS_NO_SYSMON_OBJECT == hr ) {
  616. MessageBox(
  617. m_hWnd,
  618. ResourceString(IDS_NOSYSMONOBJECT_ERR ),
  619. ResourceString(IDS_APP_NAME),
  620. MB_OK | MB_ICONERROR);
  621. } // else LoadFromFile displays messages for other errors
  622. }
  623. DragFinish ((HDROP) wParam) ;
  624. }
  625. void
  626. CSysmonControl::DisplayContextMenu(short x, short y)
  627. {
  628. HMENU hMenu;
  629. HMENU hMenuPopup;
  630. RECT clntRect;
  631. int iPosx=0;
  632. int iPosy=0;
  633. int iLocalx;
  634. int iLocaly;
  635. GetWindowRect(m_hWnd,&clntRect);
  636. if (x==0){
  637. iPosx = ((clntRect.right - clntRect.left)/2) ;
  638. }else{
  639. iPosx = x - clntRect.left;
  640. }
  641. if (y==0){
  642. iPosy = ((clntRect.bottom - clntRect.top)/2) ;
  643. }else{
  644. iPosy = y - clntRect.top;
  645. }
  646. iLocalx = clntRect.left + iPosx ;
  647. iLocaly = clntRect.top + iPosy ;
  648. if ( ConfirmSampleDataOverwrite () ) {
  649. if ( !IsReadOnly() ) {
  650. UINT uEnable;
  651. // Get the menu for the pop-up menu from the resource file.
  652. hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_CONTEXT));
  653. if (!hMenu)
  654. return;
  655. // enable/disable SaveData option depending on data source
  656. uEnable = (IsLogSource() ? MF_ENABLED : MF_GRAYED);
  657. uEnable |= MF_BYCOMMAND;
  658. EnableMenuItem (hMenu, IDM_SAVEDATA, uEnable);
  659. // Get the first submenu in it for TrackPopupMenu.
  660. hMenuPopup = GetSubMenu(hMenu, 0);
  661. // Draw and track the "floating" pop-up menu.
  662. TrackPopupMenu(hMenuPopup, TPM_RIGHTBUTTON,
  663. iLocalx, iLocaly, 0, m_hWnd, NULL);
  664. // Destroy the menu.
  665. DestroyMenu(hMenu);
  666. }
  667. }
  668. }
  669. HRESULT CSysmonControl::DisplayProperties ( DISPID dispID )
  670. {
  671. HRESULT hr;
  672. CAUUID caGUID;
  673. OCPFIPARAMS params;
  674. USES_CONVERSION
  675. // Give container a chance to show properties
  676. if (NULL!=m_pObj->m_pIOleControlSite) {
  677. hr=m_pObj->m_pIOleControlSite->ShowPropertyFrame();
  678. if (NOERROR == hr)
  679. return hr;
  680. }
  681. //Put up our property pages.
  682. ZeroMemory ( &params, sizeof ( OCPFIPARAMS ) );
  683. hr = m_pObj->m_pImpISpecifyPP->GetPages(&caGUID);
  684. if (FAILED(hr))
  685. return hr;
  686. params.cbStructSize = sizeof ( OCPFIPARAMS );
  687. params.hWndOwner = m_hWnd;
  688. params.x = 10;
  689. params.y = 10;
  690. params.lpszCaption = T2W(ResourceString(IDS_PROPFRM_TITLE));
  691. params.cObjects = 1;
  692. params.lplpUnk = (IUnknown **)&m_pObj,
  693. params.cPages = caGUID.cElems;
  694. params.lpPages = caGUID.pElems;
  695. params.lcid = m_lcidCurrent;
  696. params.dispidInitialProperty = dispID;
  697. hr = OleCreatePropertyFrameIndirect ( &params );
  698. //Free the GUIDs
  699. CoTaskMemFree((void *)caGUID.pElems);
  700. // Make sure correct window has the focus
  701. AssignFocus();
  702. return hr;
  703. }
  704. HRESULT
  705. CSysmonControl::AddCounter(
  706. LPTSTR pszPath,
  707. PCGraphItem *pGItem)
  708. /*++
  709. Routine Description:
  710. AddCounter returns a pointer to the created counter item, or
  711. to the first created counter item if multiple created for a wildcard
  712. path.
  713. EnumExpandedPath calls the AddCallback function for each new counter.
  714. AddCallback passes the counter path on to the AddSingleCounter method.
  715. Arguments:
  716. None.
  717. Return Value:
  718. None.
  719. --*/
  720. {
  721. HRESULT hr;
  722. ENUM_ADD_COUNTER_CALLBACK_INFO CallbackInfo;
  723. CallbackInfo.pCtrl = this;
  724. CallbackInfo.pFirstItem = NULL;
  725. *pGItem = NULL;
  726. // TodoLogFiles: Handle multiple files
  727. hr = EnumExpandedPath(GetDataSourceHandle(), pszPath, AddCounterCallback, &CallbackInfo);
  728. *pGItem = CallbackInfo.pFirstItem;
  729. return hr;
  730. }
  731. HRESULT
  732. CSysmonControl::AddCounters (
  733. VOID
  734. )
  735. /*++
  736. Routine Description:
  737. AddCounters invokes the counter browser to select new counters.
  738. The browser calls the AddCallback function for each new counter.
  739. AddCallback passes the counter path on to the AddCounter method.
  740. Arguments:
  741. None.
  742. Return Value:
  743. None.
  744. --*/
  745. {
  746. ENUM_ADD_COUNTER_CALLBACK_INFO CallbackInfo;
  747. CallbackInfo.pCtrl = this;
  748. CallbackInfo.pFirstItem = NULL;
  749. HRESULT hr;
  750. // Browse counters (calling AddCallback for each selected counter)
  751. // Todo: Handle multiple files
  752. hr = BrowseCounters(
  753. GetDataSourceHandle(),
  754. PERF_DETAIL_WIZARD,
  755. m_hWnd,
  756. AddCounterCallback,
  757. &CallbackInfo,
  758. m_pObj->m_Graph.Options.bMonitorDuplicateInstances);
  759. // Make sure correct window has the focus
  760. AssignFocus();
  761. return hr;
  762. }
  763. HRESULT
  764. CSysmonControl::SaveAs (
  765. VOID
  766. )
  767. /*++
  768. Routine Description:
  769. SaveAs writes the current configuration to an HTML file.
  770. Arguments:
  771. None.
  772. Return Value:
  773. None.
  774. --*/
  775. {
  776. HRESULT hr = S_OK;
  777. INT iReturn = IDCANCEL;
  778. INT i;
  779. OPENFILENAME ofn;
  780. TCHAR szFileName[MAX_PATH+1];
  781. TCHAR szExt[MAX_PATH+1];
  782. TCHAR szFileFilter[MAX_PATH+1];
  783. TCHAR szDefExtension[MAX_PATH+1];
  784. // Initial directory is the current directory
  785. szFileName[0] = TEXT('\0');
  786. ZeroMemory(szFileFilter, sizeof ( szFileFilter ) );
  787. ZeroMemory(&ofn, sizeof(ofn));
  788. lstrcpy (szFileFilter,(LPTSTR) ResourceString (IDS_HTML_FILE));
  789. lstrcpy (szDefExtension,(LPTSTR) ResourceString (IDS_DEF_EXT));
  790. for( i = 0; szFileFilter[i]; i++ ){
  791. if( szFileFilter[i] == TEXT('|') ){
  792. szFileFilter[i] = 0;
  793. }
  794. }
  795. for( i = 0; szDefExtension[i]; i++ ){
  796. if( szDefExtension[i] == TEXT('|') ){
  797. szDefExtension[i] = 0;
  798. }
  799. }
  800. ofn.lStructSize = sizeof(ofn);
  801. ofn.hwndOwner = Window();
  802. ofn.hInstance = NULL ; // Ignored if no template argument
  803. ofn.lpstrFilter = szFileFilter;
  804. ofn.lpstrDefExt = szDefExtension;
  805. ofn.nFilterIndex = 1; // nFilterIndex is 1-based
  806. ofn.lpstrFile = szFileName;
  807. ofn.nMaxFile = MAX_PATH;
  808. ofn.nMaxFileTitle = 0;
  809. ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  810. iReturn = GetSaveFileName (&ofn);
  811. // Differentiate between *.htm and *.tsv
  812. _tsplitpath(szFileName,NULL,NULL,NULL,szExt);
  813. if ( IDOK == iReturn ) {
  814. // Create a file.
  815. HANDLE hFile;
  816. DWORD dwMsgStatus = ERROR_SUCCESS;
  817. hFile = CreateFile (
  818. szFileName,
  819. GENERIC_READ | GENERIC_WRITE,
  820. 0, // Not shared
  821. NULL, // Security attributes
  822. CREATE_NEW, // Query the user if file already exists.
  823. FILE_ATTRIBUTE_NORMAL,
  824. NULL );
  825. if ( INVALID_HANDLE_VALUE == hFile ) {
  826. DWORD dwCreateError = GetLastError();
  827. if ( ERROR_SUCCESS != dwCreateError ) {
  828. // Confirm file overwrite.
  829. INT iOverwrite = IDNO;
  830. TCHAR* pszMessage = NULL;
  831. pszMessage = new TCHAR [lstrlen(szFileName) + MAX_PATH + 1];
  832. if ( NULL != pszMessage ) {
  833. _stprintf ( pszMessage, ResourceString(IDS_HTML_FILE_OVERWRITE), szFileName );
  834. iOverwrite = MessageBox(
  835. Window(),
  836. pszMessage,
  837. ResourceString(IDS_APP_NAME),
  838. MB_YESNO );
  839. delete pszMessage;
  840. if ( IDYES == iOverwrite ) {
  841. hFile = CreateFile (
  842. szFileName,
  843. GENERIC_READ | GENERIC_WRITE,
  844. 0, // Not shared
  845. NULL, // Security attributes
  846. CREATE_ALWAYS, // Overwrite any existing file.
  847. FILE_ATTRIBUTE_NORMAL,
  848. NULL );
  849. }
  850. }
  851. }
  852. }
  853. if ( INVALID_HANDLE_VALUE != hFile ) {
  854. LPTSTR pszTemp = NULL;
  855. WCHAR szByteOrderMark[2];
  856. BOOL bStatus;
  857. CWaitCursor cursorWait;
  858. // Save the current configuration to the file.
  859. if( (!_tcscmp(szExt,ResourceString(IDS_HTM_EXTENSION)))
  860. || (!_tcscmp(szExt,ResourceString(IDS_HTML_EXTENSION))) ) {
  861. // Html file
  862. szByteOrderMark[0] = 0xFEFF;
  863. szByteOrderMark[1] = 0;
  864. bStatus = FileWrite ( hFile, szByteOrderMark, sizeof(WCHAR) );
  865. if ( bStatus ) {
  866. pszTemp = ResourceString ( IDS_HTML_FILE_HEADER1 );
  867. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  868. }
  869. if ( bStatus ) {
  870. pszTemp = ResourceString ( IDS_HTML_FILE_HEADER2 );
  871. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  872. }
  873. if ( bStatus ) {
  874. DWORD dwByteCount;
  875. pszTemp = NULL;
  876. hr = CopyToBuffer ( pszTemp, dwByteCount );
  877. if ( SUCCEEDED ( hr ) ) {
  878. assert ( NULL != pszTemp );
  879. assert ( 0 != dwByteCount );
  880. bStatus = FileWrite ( hFile, pszTemp, dwByteCount );
  881. delete pszTemp;
  882. } else {
  883. bStatus = FALSE;
  884. SetLastError ( ERROR_OUTOFMEMORY );
  885. }
  886. }
  887. if ( bStatus ) {
  888. pszTemp = ResourceString ( IDS_HTML_FILE_FOOTER );
  889. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  890. }
  891. if ( !bStatus ) {
  892. dwMsgStatus = GetLastError();
  893. }
  894. } else if (!_tcscmp(szExt,ResourceString(IDS_TSV_EXTENSION))){
  895. // Tsv file
  896. bStatus = WriteFileReportHeader(hFile);
  897. if (bStatus){
  898. bStatus = m_pReport->WriteFileReport(hFile);
  899. }
  900. if (!bStatus){
  901. dwMsgStatus = GetLastError();
  902. }
  903. }
  904. bStatus = CloseHandle ( hFile );
  905. } else {
  906. dwMsgStatus = GetLastError();
  907. }
  908. if ( ERROR_SUCCESS != dwMsgStatus ) {
  909. TCHAR* pszMessage = NULL;
  910. TCHAR szSystemMessage[MAX_PATH+1];
  911. pszMessage = new TCHAR [lstrlen(szFileName) + 2*MAX_PATH + 1];
  912. if ( NULL != pszMessage ) {
  913. _stprintf ( pszMessage, ResourceString(IDS_SAVEAS_ERR), szFileName );
  914. FormatSystemMessage ( dwMsgStatus, szSystemMessage, MAX_PATH );
  915. lstrcat ( pszMessage, szSystemMessage );
  916. MessageBox(Window(), pszMessage, ResourceString(IDS_APP_NAME), MB_OK | MB_ICONSTOP);
  917. delete pszMessage;
  918. }
  919. }
  920. } // else ignore if they canceled out
  921. // Make sure correct window has the focus
  922. AssignFocus();
  923. return hr;
  924. }
  925. HRESULT
  926. CSysmonControl::SaveData (
  927. VOID
  928. )
  929. /*++
  930. Routine Description:
  931. SaveData writes the data from the display to a log file for
  932. later input as a data source.
  933. Arguments:
  934. None.
  935. Return Value:
  936. None.
  937. --*/
  938. {
  939. HRESULT hr = S_OK;
  940. INT iReturn = IDCANCEL;
  941. INT i;
  942. OPENFILENAME ofn;
  943. TCHAR szFileName[MAX_PATH+1];
  944. TCHAR szExt[MAX_PATH+1];
  945. TCHAR szFileFilter[MAX_PATH+1];
  946. TCHAR szDefExtension[MAX_PATH+1];
  947. TCHAR szDialogCaption[MAX_PATH+1];
  948. DWORD dwStatus;
  949. LONG lOrigFilterValue;
  950. // Initial directory is the current directory
  951. szFileName[0] = TEXT('\0');
  952. ZeroMemory(szFileFilter, sizeof ( szFileFilter ) );
  953. ZeroMemory(&ofn, sizeof(ofn));
  954. lstrcpy (szFileFilter,(LPTSTR) ResourceString (IDS_LOG_FILE));
  955. lstrcpy (szDefExtension,(LPTSTR) ResourceString (IDS_LOG_FILE_EXTENSION));
  956. lstrcpy (szDialogCaption, (LPTSTR) ResourceString (IDS_SAVE_DATA_CAPTION));
  957. for( i = 0; szFileFilter[i]; i++ ){
  958. if( szFileFilter[i] == TEXT('|') ){
  959. szFileFilter[i] = 0;
  960. }
  961. }
  962. for( i = 0; szDefExtension[i]; i++ ){
  963. if( szDefExtension[i] == TEXT('|') ){
  964. szDefExtension[i] = 0;
  965. }
  966. }
  967. ofn.lStructSize = sizeof(ofn);
  968. ofn.hwndOwner = Window();
  969. ofn.hInstance = GetModuleHandle((LPCTSTR)TEXT("sysmon.ocx")) ; // Ignored if no template argument
  970. ofn.lpstrFilter = szFileFilter;
  971. ofn.lpstrDefExt = szDefExtension;
  972. ofn.nFilterIndex = 1; // nFilterIndex is 1-based
  973. ofn.lpstrFile = szFileName;
  974. ofn.nMaxFile = MAX_PATH;
  975. ofn.nMaxFileTitle = 0;
  976. ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
  977. OFN_OVERWRITEPROMPT | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
  978. ofn.lpstrTitle = szDialogCaption;
  979. ofn.lCustData = (DWORD_PTR)this;
  980. ofn.lpfnHook = (LPOFNHOOKPROC) SaveDataDlgHookProc ;
  981. ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEDATA_DLG) ;
  982. lOrigFilterValue = GetSaveDataFilter ();
  983. iReturn = GetSaveFileName (&ofn);
  984. // Differentiate between *.htm and *.tsv
  985. _tsplitpath(szFileName,NULL,NULL,NULL,szExt);
  986. if ( IDOK == iReturn ) {
  987. DWORD dwOutputLogType = PDH_LOG_TYPE_BINARY;
  988. DWORD dwFilterCount; // copy all records within the timerange
  989. PDH_TIME_INFO TimeInfo;
  990. // get log type from file name
  991. if (ofn.nFileExtension > 0) {
  992. if (ofn.lpstrFile[ofn.nFileExtension] != 0) {
  993. if (lstrcmpi (&ofn.lpstrFile[ofn.nFileExtension-1], ResourceString (IDS_CSV_EXTENSION)) == 0) {
  994. dwOutputLogType = PDH_LOG_TYPE_CSV;
  995. } else if (lstrcmpi (&ofn.lpstrFile[ofn.nFileExtension-1], ResourceString (IDS_TSV_EXTENSION)) == 0) {
  996. dwOutputLogType = PDH_LOG_TYPE_TSV;
  997. } // else use binary log format as default
  998. } // else use binary log format as default
  999. } // else use binary log format as default
  1000. // get timerange for this log
  1001. TimeInfo.StartTime = m_DataSourceInfo.llStartDisp;
  1002. TimeInfo.EndTime = m_DataSourceInfo.llStopDisp;
  1003. dwFilterCount = GetSaveDataFilter();
  1004. //
  1005. // Double check the filter count is not 0
  1006. //
  1007. if (dwFilterCount == 0) {
  1008. dwFilterCount = 1;
  1009. }
  1010. // now relog the data
  1011. dwStatus = RelogLogData (
  1012. ofn.lpstrFile,
  1013. dwOutputLogType,
  1014. TimeInfo,
  1015. dwFilterCount);
  1016. } else {
  1017. // they canceled out so restore filter value
  1018. SetSaveDataFilter (lOrigFilterValue);
  1019. }
  1020. // Make sure correct window has the focus
  1021. AssignFocus();
  1022. return hr;
  1023. }
  1024. DWORD
  1025. CSysmonControl::RelogLogData (
  1026. LPCTSTR szOutputFile,
  1027. DWORD dwOutputLogType,
  1028. PDH_TIME_INFO pdhTimeInfo,
  1029. DWORD dwFilterCount
  1030. )
  1031. {
  1032. DWORD dwNumOutputCounters = 0;
  1033. DWORD dwRecCount = 0;
  1034. DWORD dwFiltered;
  1035. LONG Status = ERROR_SUCCESS;
  1036. PDH_STATUS PdhStatus;
  1037. PDH_RAW_COUNTER RawValue;
  1038. HQUERY hQuery = NULL;
  1039. HLOG hOutLog = NULL;
  1040. HCOUNTER hCounter = NULL;
  1041. HCOUNTER hLastGoodCounter = NULL;
  1042. DWORD dwType;
  1043. DWORD dwOpenMode;
  1044. HLOG hDataSource;
  1045. hDataSource = GetDataSourceHandle();
  1046. Status = PdhStatus = PdhOpenQueryH(hDataSource, 0L, &hQuery);
  1047. if (Status == ERROR_SUCCESS) {
  1048. LPTSTR szCounterPath;
  1049. TCHAR szLocalCounterPathBuffer[MAX_PATH*4];
  1050. TCHAR szParent[MAX_PATH];
  1051. TCHAR szInstance[MAX_PATH];
  1052. DWORD dwBufferSize;
  1053. TCHAR szDebugMsg[1024];
  1054. PDH_COUNTER_PATH_ELEMENTS LocalCounterPath;
  1055. PCMachineNode pMachine;
  1056. PCObjectNode pObject;
  1057. PCInstanceNode pInstance;
  1058. PCCounterNode pCounter;
  1059. BOOL bStatus = TRUE;
  1060. szParent[0] = _T('\0');
  1061. szInstance[0] = _T('\0');
  1062. for (pMachine = CounterTree()->FirstMachine();
  1063. pMachine && TRUE == bStatus;
  1064. pMachine = pMachine->Next()) {
  1065. LocalCounterPath.szMachineName = (LPTSTR)pMachine->Name();
  1066. for (pObject = pMachine->FirstObject();
  1067. pObject && TRUE == bStatus;
  1068. pObject = pObject->Next()) {
  1069. LocalCounterPath.szObjectName = (LPTSTR)pObject->Name();
  1070. // Write the first line of instance (parent) names.
  1071. for (pInstance = pObject->FirstInstance();
  1072. pInstance && TRUE == bStatus;
  1073. pInstance = pInstance->Next()) {
  1074. // If instance has no parent, then the parent name is
  1075. // null, so a tab is written.
  1076. //
  1077. pInstance->GetParentName(szParent);
  1078. if (szParent[0] == 0) {
  1079. LocalCounterPath.szParentInstance = NULL;
  1080. } else {
  1081. LocalCounterPath.szParentInstance = szParent;
  1082. }
  1083. pInstance->GetInstanceName(szInstance);
  1084. if (szInstance[0] == 0) {
  1085. LocalCounterPath.szInstanceName = NULL;
  1086. } else {
  1087. LocalCounterPath.szInstanceName = szInstance;
  1088. }
  1089. // BUGBUG: unless this is defined else
  1090. LocalCounterPath.dwInstanceIndex = 0;
  1091. for (pCounter = pObject->FirstCounter();
  1092. pCounter && TRUE == bStatus;
  1093. pCounter = pCounter->Next()) {
  1094. LocalCounterPath.szCounterName = (LPTSTR)pCounter->Name();
  1095. // then build one from the components
  1096. szCounterPath = szLocalCounterPathBuffer;
  1097. dwBufferSize = sizeof (szLocalCounterPathBuffer) / sizeof (TCHAR);
  1098. memset (szLocalCounterPathBuffer, 0, dwBufferSize * sizeof (TCHAR));
  1099. PdhStatus = PdhMakeCounterPathW(& LocalCounterPath,
  1100. szCounterPath,
  1101. & dwBufferSize,
  1102. 0);
  1103. if (PdhStatus == ERROR_SUCCESS) {
  1104. PdhStatus = PdhAddCounter (hQuery, szCounterPath, 0L, &hCounter);
  1105. if (PdhStatus != ERROR_SUCCESS) {
  1106. if (dwDbgPrintLevel == DBG_SHOW_STATUS_PRINTS) {
  1107. _stprintf (szDebugMsg, (LPCTSTR)TEXT("\nUnable to add \"%s\", error: 0x%8.8x (%d)"), szCounterPath, PdhStatus, PdhStatus);
  1108. OutputDebugString (szDebugMsg);
  1109. }
  1110. } else {
  1111. hLastGoodCounter = hCounter;
  1112. dwNumOutputCounters++;
  1113. if (dwDbgPrintLevel == DBG_SHOW_STATUS_PRINTS) {
  1114. _stprintf (szDebugMsg, (LPCTSTR)TEXT("\nAdded \"%s\", error: 0x%8.8x (%d)"), szCounterPath, PdhStatus, PdhStatus);
  1115. OutputDebugString (szDebugMsg);
  1116. }
  1117. }
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. if ((Status == ERROR_SUCCESS) && (dwNumOutputCounters > 0)) {
  1125. dwOpenMode = PDH_LOG_WRITE_ACCESS | PDH_LOG_CREATE_ALWAYS;
  1126. PdhStatus = PdhOpenLog(szOutputFile,
  1127. dwOpenMode,
  1128. & dwOutputLogType,
  1129. hQuery,
  1130. 0L,
  1131. NULL,
  1132. & hOutLog);
  1133. if (PdhStatus != ERROR_SUCCESS) {
  1134. Status = PdhStatus;
  1135. } else {
  1136. // set query range
  1137. PdhStatus = PdhSetQueryTimeRange (hQuery, &pdhTimeInfo);
  1138. // copy log data to output log
  1139. PdhStatus = PdhUpdateLog (hOutLog, NULL);
  1140. while (PdhStatus == ERROR_SUCCESS) {
  1141. dwRecCount++;
  1142. dwFiltered = 1;
  1143. while ((dwFiltered < dwFilterCount) && (PdhStatus == ERROR_SUCCESS)) {
  1144. PdhStatus = PdhCollectQueryData(hQuery);
  1145. if (PdhStatus == ERROR_SUCCESS) {
  1146. PdhStatus = PdhGetRawCounterValue (
  1147. hLastGoodCounter,
  1148. &dwType,
  1149. &RawValue);
  1150. if (PdhStatus == ERROR_SUCCESS) {
  1151. // check for bogus timestamps as an inidcation we ran off the end of the file
  1152. if ((*(LONGLONG *)&RawValue.TimeStamp == 0) ||
  1153. (*(LONGLONG *)&RawValue.TimeStamp >= pdhTimeInfo.EndTime)){
  1154. PdhStatus = PDH_END_OF_LOG_FILE;
  1155. }
  1156. }
  1157. }
  1158. dwFiltered++;
  1159. }
  1160. if (PdhStatus == ERROR_SUCCESS) {
  1161. PdhStatus = PdhUpdateLog (hOutLog, NULL);
  1162. }
  1163. }
  1164. if ( (PdhStatus == PDH_END_OF_LOG_FILE)
  1165. || (PdhStatus == PDH_NO_MORE_DATA)) {
  1166. PdhStatus = ERROR_SUCCESS;
  1167. }
  1168. // update log catalog while we're at it
  1169. if (dwOutputLogType == PDH_LOG_TYPE_BINARY) {
  1170. PdhStatus = PdhUpdateLogFileCatalog (hOutLog);
  1171. if (PdhStatus != ERROR_SUCCESS) {
  1172. Status = PdhStatus;
  1173. }
  1174. }
  1175. PdhStatus = PdhCloseLog(hOutLog, 0L);
  1176. if (PdhStatus != ERROR_SUCCESS) {
  1177. Status = PdhStatus;
  1178. } else {
  1179. hOutLog = NULL;
  1180. }
  1181. }
  1182. }
  1183. if (hQuery != NULL) {
  1184. PdhStatus = PdhCloseQuery(hQuery);
  1185. if (PdhStatus != ERROR_SUCCESS) {
  1186. Status = PdhStatus;
  1187. } else {
  1188. hQuery = NULL;
  1189. hCounter = NULL;
  1190. }
  1191. }
  1192. return Status;
  1193. }
  1194. BOOL
  1195. CSysmonControl::WriteFileReportHeader(HANDLE hFile){
  1196. BOOL bStatus = TRUE;
  1197. DWORD dwStatus = ERROR_SUCCESS;
  1198. SYSTEMTIME SysTime;
  1199. DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1 ;
  1200. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1201. TCHAR szHeader[6 * MAX_PATH];
  1202. TCHAR szDateTime[MAX_PATH+1];
  1203. LPWSTR szDataSource = NULL;
  1204. TCHAR szTime[MAX_PATH+1];
  1205. TCHAR szDate[MAX_PATH+1];
  1206. TCHAR szValue[MAX_PATH+1];
  1207. DWORD dwValueId = IDS_DEFAULT;
  1208. WCHAR szByteOrderMark[2];
  1209. ULONG ulLogListBufLen = 0;
  1210. // Computer name
  1211. if (!SUCCEEDED(GetComputerName(szComputerName,&dwSize))){
  1212. szComputerName[0] = _T('\0');
  1213. }
  1214. // Current date and time
  1215. GetLocalTime(&SysTime);
  1216. GetTimeFormat (m_lcidCurrent, 0, &SysTime, NULL, szTime, MAX_TIME_CHARS) ;
  1217. GetDateFormat (m_lcidCurrent, DATE_SHORTDATE, &SysTime, NULL, szDate, MAX_DATE_CHARS) ;
  1218. _stprintf(
  1219. szDateTime,
  1220. ResourceString( IDS_REPORT_DATE_TIME ),
  1221. szDate,
  1222. szTime );
  1223. // Report value type
  1224. switch ( m_pObj->m_Graph.Options.iReportValueType ) {
  1225. case sysmonCurrentValue:
  1226. dwValueId = IDS_LAST;
  1227. break;
  1228. case sysmonAverage:
  1229. dwValueId = IDS_AVERAGE;
  1230. break;
  1231. case sysmonMinimum:
  1232. dwValueId = IDS_MINIMUM;
  1233. break;
  1234. case sysmonMaximum:
  1235. dwValueId = IDS_MAXIMUM;
  1236. break;
  1237. default:
  1238. dwValueId = IDS_DEFAULT;
  1239. }
  1240. _stprintf(
  1241. szValue,
  1242. ResourceString ( IDS_REPORT_VALUE_TYPE ),
  1243. ResourceString ( dwValueId ) );
  1244. // Data source
  1245. if ( sysmonCurrentActivity == m_pObj->m_Graph.Options.iDataSourceType ) {
  1246. szDataSource = new WCHAR [MAX_PATH];
  1247. if ( NULL != szDataSource ) {
  1248. lstrcpy(szDataSource,ResourceString(IDS_REPORT_REAL_TIME));
  1249. }
  1250. } else if ( sysmonLogFiles == m_pObj->m_Graph.Options.iDataSourceType ) {
  1251. dwStatus = BuildLogFileList (
  1252. NULL,
  1253. TRUE,
  1254. &ulLogListBufLen );
  1255. szDataSource = (LPWSTR) malloc(ulLogListBufLen * sizeof(WCHAR));
  1256. if ( NULL != szDataSource ) {
  1257. dwStatus = BuildLogFileList (
  1258. szDataSource,
  1259. TRUE,
  1260. &ulLogListBufLen );
  1261. } else {
  1262. dwStatus = ERROR_OUTOFMEMORY;
  1263. }
  1264. } else if ( sysmonSqlLog == m_pObj->m_Graph.Options.iDataSourceType ) {
  1265. dwStatus = FormatSqlDataSourceName (
  1266. m_DataSourceInfo.szSqlDsnName,
  1267. m_DataSourceInfo.szSqlLogSetName,
  1268. NULL,
  1269. &ulLogListBufLen );
  1270. if ( ERROR_SUCCESS == dwStatus ) {
  1271. szDataSource = (LPWSTR) malloc(ulLogListBufLen * sizeof(WCHAR));
  1272. if (szDataSource == NULL) {
  1273. dwStatus = ERROR_OUTOFMEMORY;
  1274. } else {
  1275. dwStatus = FormatSqlDataSourceName (
  1276. m_DataSourceInfo.szSqlDsnName,
  1277. m_DataSourceInfo.szSqlLogSetName,
  1278. szDataSource,
  1279. &ulLogListBufLen );
  1280. }
  1281. }
  1282. }
  1283. // Header
  1284. _stprintf(
  1285. szHeader,
  1286. ResourceString(IDS_REPORT_HEADER),
  1287. szComputerName,
  1288. szDateTime,
  1289. szValue,
  1290. szDataSource );
  1291. if ( NULL != szDataSource ) {
  1292. free ( szDataSource );
  1293. }
  1294. if ( sysmonCurrentActivity == m_pObj->m_Graph.Options.iDataSourceType ) {
  1295. TCHAR szInterval[MAX_PATH+1];
  1296. // Add sample interval for realtime data source.
  1297. _stprintf(
  1298. szInterval,
  1299. ResourceString(IDS_REPORT_INTERVAL),
  1300. m_pObj->m_Graph.Options.fUpdateInterval );
  1301. lstrcat(szHeader,szInterval);
  1302. } else if ( sysmonLogFiles == m_pObj->m_Graph.Options.iDataSourceType
  1303. || sysmonSqlLog == m_pObj->m_Graph.Options.iDataSourceType )
  1304. {
  1305. TCHAR szStartStop[MAX_PATH+1];
  1306. // Add start and stop string for log files or Sql logs.
  1307. FormatDateTime(m_DataSourceInfo.llStartDisp,szDate,szTime);
  1308. _stprintf(
  1309. szStartStop,
  1310. TEXT("%s%s %s\n"),
  1311. ResourceString(IDS_REPORT_LOG_START),
  1312. szDate,
  1313. szTime );
  1314. FormatDateTime(m_DataSourceInfo.llStopDisp,szDate,szTime);
  1315. lstrcat(szStartStop,ResourceString(IDS_REPORT_LOG_STOP));
  1316. FormatDateTime(m_DataSourceInfo.llStopDisp,szDate,szTime);
  1317. lstrcat(szStartStop,szDate);
  1318. lstrcat(szStartStop,SpaceStr);
  1319. lstrcat(szStartStop,szTime);
  1320. lstrcat(szStartStop,LineEndStr);
  1321. lstrcat(szHeader,szStartStop);
  1322. }
  1323. szByteOrderMark[0] = 0xFEFF;
  1324. szByteOrderMark[1] = 0;
  1325. bStatus = FileWrite ( hFile, szByteOrderMark, sizeof(WCHAR) );
  1326. bStatus = FileWrite ( hFile, szHeader, lstrlen (szHeader) * sizeof(TCHAR) );
  1327. return bStatus;
  1328. }
  1329. BOOL CSysmonControl::InitView (HWND hWndParent)
  1330. /*
  1331. Effect: Create the graph window. This window is a child of
  1332. hWndMain and is a container for the graph data,
  1333. graph label, graph legend, and graph status windows.
  1334. Note: We don't worry about the size here, as this window
  1335. will be resized whenever the main window is resized.
  1336. Note: This method initializes the control for rendering.
  1337. */
  1338. {
  1339. PCGraphItem pItem;
  1340. WNDCLASS wc ;
  1341. // Protect against multiple initializations
  1342. if (m_fViewInitialized)
  1343. return TRUE;
  1344. BEGIN_CRITICAL_SECTION
  1345. // Register the window class once
  1346. if (pstrRegisteredClasses[SYSMONCTRL_WNDCLASS] == NULL) {
  1347. wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  1348. wc.lpfnWndProc = (WNDPROC) SysmonCtrlWndProc ;
  1349. wc.hInstance = g_hInstance ;
  1350. wc.cbClsExtra = 0 ;
  1351. wc.cbWndExtra = sizeof (PSYSMONCTRL) ;
  1352. wc.hIcon = NULL ;
  1353. wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
  1354. wc.hbrBackground = NULL ;
  1355. wc.lpszMenuName = NULL ;
  1356. wc.lpszClassName = szSysmonCtrlWndClass ;
  1357. if (RegisterClass (&wc)) {
  1358. pstrRegisteredClasses[SYSMONCTRL_WNDCLASS] = szSysmonCtrlWndClass;
  1359. }
  1360. }
  1361. END_CRITICAL_SECTION
  1362. if (pstrRegisteredClasses[SYSMONCTRL_WNDCLASS] == NULL)
  1363. return FALSE;
  1364. // Create our control window
  1365. m_hWnd = CreateWindow (szSysmonCtrlWndClass, // window class
  1366. NULL, // caption
  1367. WS_CHILD | WS_VISIBLE, // style for window
  1368. 0, 0, // initial position
  1369. m_pObj->m_RectExt.right, // width
  1370. m_pObj->m_RectExt.bottom, // height
  1371. hWndParent, // parent
  1372. NULL, // menu
  1373. g_hInstance, // program instance
  1374. (LPVOID)this) ; // user-supplied data
  1375. if (m_hWnd == NULL) {
  1376. // DWORD err = GetLastError();
  1377. return FALSE;
  1378. }
  1379. DragAcceptFiles (m_hWnd, TRUE) ;
  1380. // Subcomponents are allocated in AllocateSubcomponents
  1381. // Init the legend
  1382. if ( !m_pLegend
  1383. || !m_pGraphDisp
  1384. || !m_pStatsBar
  1385. || !m_pSnapBar
  1386. || !m_pToolbar
  1387. || !m_pReport )
  1388. {
  1389. return FALSE;
  1390. }
  1391. if (!m_pLegend->Init(this, m_hWnd))
  1392. return FALSE;
  1393. // Init the graph display
  1394. if (!m_pGraphDisp->Init(this, &m_pObj->m_Graph))
  1395. return FALSE;
  1396. // Init the statistics bar
  1397. if (!m_pStatsBar->Init(this, m_hWnd))
  1398. return FALSE;
  1399. // Init the snapshot bar
  1400. if (!m_pSnapBar->Init(this, m_hWnd))
  1401. return FALSE;
  1402. if (!m_pToolbar->Init(this, m_hWnd))
  1403. return FALSE;
  1404. // Init the report view
  1405. if (!m_pReport->Init(this, m_hWnd))
  1406. return FALSE;
  1407. m_fViewInitialized = TRUE;
  1408. // If counters are present
  1409. if ((pItem = FirstCounter()) != NULL) {
  1410. // Add counters to the legend and report view
  1411. while (pItem != NULL) {
  1412. m_pLegend->AddItem(pItem);
  1413. m_pReport->AddItem(pItem);
  1414. pItem = pItem->Next();
  1415. }
  1416. if ( NULL != m_pSelectedItem ) {
  1417. SelectCounter(m_pSelectedItem);
  1418. } else {
  1419. SelectCounter(FirstCounter());
  1420. }
  1421. if ( !m_bLogFileSource ) {
  1422. // Pass new time span to statistics bar. This must
  1423. // be done after initializing the stats bar.
  1424. m_pStatsBar->SetTimeSpan (
  1425. m_pObj->m_Graph.Options.fUpdateInterval
  1426. * m_pObj->m_Graph.Options.iDisplayFilter
  1427. * m_pHistCtrl->nMaxSamples );
  1428. }
  1429. }
  1430. // Processing the command line can add counters from the property bag.
  1431. // Add the counters after the counter addition and selection code above so that counters
  1432. // do not get added twice.
  1433. ProcessCommandLine ( );
  1434. return TRUE;
  1435. }
  1436. BOOL CSysmonControl::Init (HWND hWndParent)
  1437. /*
  1438. Effect: Create the graph window. This window is a child of
  1439. hWndMain and is a container for the graph data,
  1440. graph label, graph legend, and graph status windows.
  1441. Note: We don't worry about the size here, as this window
  1442. will be resized whenever the main window is resized.
  1443. */
  1444. {
  1445. PCGraphItem pItem;
  1446. BOOL bResult = TRUE;
  1447. // Protect against multiple initializations
  1448. if (!m_fInitialized) {
  1449. bResult = InitView( hWndParent );
  1450. if ( !m_bSampleDataLoaded ) {
  1451. if ( bResult ) {
  1452. m_fInitialized = TRUE;
  1453. // When loaded from property bag or stream, the log file name is
  1454. // already set. If realtime query, the Pdh query might
  1455. // not have been opened.
  1456. if ( sysmonCurrentActivity == m_pObj->m_Graph.Options.iDataSourceType ) {
  1457. put_DataSourceType ( sysmonCurrentActivity );
  1458. }
  1459. // Load the accelerator table
  1460. m_hAccel = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(ID_SMONACCEL));
  1461. // If counters are present
  1462. if ((pItem = FirstCounter()) != NULL) {
  1463. if ( ERROR_SUCCESS != ActivateQuery() ) {
  1464. m_fInitialized = FALSE;
  1465. return FALSE;
  1466. }
  1467. }
  1468. }
  1469. }
  1470. }
  1471. //sync the toolbar last
  1472. if ( bResult ) {
  1473. m_pToolbar->SyncToolbar();
  1474. }
  1475. return bResult;
  1476. }
  1477. HRESULT CSysmonControl::LoadFromStream(LPSTREAM pIStream)
  1478. {
  1479. typedef struct _DATA_LIST_ELEM
  1480. {
  1481. GRAPHITEM_DATA3 itemData;
  1482. LPWSTR szCounterPath;
  1483. struct _DATA_LIST_ELEM* pNext;
  1484. } DATA_LIST_ELEM, *PDATA_LIST_ELEM;
  1485. HRESULT hr = S_OK;
  1486. ULONG bc;
  1487. GRAPH_OPTIONS *pOptions = &m_pObj->m_Graph.Options;
  1488. RECT RectExt;
  1489. SMONCTRL_VERSION_DATA VersionData;
  1490. LPTSTR szLogFilePath = NULL;
  1491. INT32 iLocalDataSourceType = (INT32)sysmonNullDataSource;
  1492. GRAPHCTRL_DATA3 CtrlData3;
  1493. ENUM_ADD_COUNTER_CALLBACK_INFO CallbackInfo;
  1494. PDATA_LIST_ELEM pFirstElem = NULL;
  1495. PDATA_LIST_ELEM pLastElem = NULL;
  1496. PDATA_LIST_ELEM pNewElem = NULL;
  1497. LPWSTR pszCounterPath = NULL;
  1498. LPTSTR szLocaleBuf = NULL;
  1499. DWORD dwLocaleBufSize = 0;
  1500. LPTSTR pszPath = NULL;
  1501. USES_CONVERSION
  1502. if (g_dwScriptPolicy == URLPOLICY_DISALLOW) {
  1503. return E_ACCESSDENIED;
  1504. }
  1505. if ( !m_bSettingsLoaded ) {
  1506. // Read in parameters
  1507. hr = pIStream->Read(&VersionData, sizeof(VersionData), &bc);
  1508. if (FAILED(hr))
  1509. return hr;
  1510. if (bc != sizeof(VersionData))
  1511. return E_FAIL;
  1512. // The code below assumes that Sysmon version is 3.5.
  1513. assert ( 3 == SMONCTRL_MAJ_VERSION );
  1514. assert ( 6 == SMONCTRL_MIN_VERSION );
  1515. // Read version 3 streams only.
  1516. if ( VersionData.iMajor < SMONCTRL_MAJ_VERSION )
  1517. return E_FAIL;
  1518. // Update the current loaded version number in order
  1519. // to warn the user appropriately when saving to stream.
  1520. m_LoadedVersion.iMajor = VersionData.iMajor;
  1521. m_LoadedVersion.iMinor = VersionData.iMinor;
  1522. assert( 256 == sizeof(CtrlData3) );
  1523. ZeroMemory ( &CtrlData3, sizeof ( CtrlData3 ) );
  1524. hr = pIStream->Read(&CtrlData3, sizeof(CtrlData3), &bc);
  1525. if (FAILED(hr))
  1526. return hr;
  1527. if (bc != sizeof(CtrlData3))
  1528. return E_FAIL;
  1529. // Setup extent info
  1530. SetRect(&RectExt, 0, 0, CtrlData3.iWidth, CtrlData3.iHeight);
  1531. m_pObj->RectConvertMappings(&RectExt, TRUE); // Convert from HIMETRIC
  1532. m_pObj->m_RectExt = RectExt;
  1533. SetCurrentClientRect( &RectExt );
  1534. // Load options settings in graph structure
  1535. pOptions->iVertMax = CtrlData3.iScaleMax;
  1536. pOptions->iVertMin = CtrlData3.iScaleMin;
  1537. pOptions->bLegendChecked = CtrlData3.bLegend;
  1538. pOptions->bToolbarChecked = CtrlData3.bToolbar;
  1539. pOptions->bLabelsChecked = CtrlData3.bLabels;
  1540. pOptions->bHorzGridChecked = CtrlData3.bHorzGrid;
  1541. pOptions->bVertGridChecked = CtrlData3.bVertGrid;
  1542. pOptions->bValueBarChecked = CtrlData3.bValueBar;
  1543. pOptions->bManualUpdate = CtrlData3.bManualUpdate;
  1544. pOptions->bHighlight = CtrlData3.bHighlight; // New for 3.1, default = 0
  1545. pOptions->bReadOnly = CtrlData3.bReadOnly; // New for 3.1+, default = 0
  1546. pOptions->bAmbientFont = CtrlData3.bAmbientFont; // New for 3.3+, new default = 1, but 0 for old files.
  1547. // MonitorDuplicateInstances is new for 3.3, default = 1
  1548. pOptions->bMonitorDuplicateInstances = CtrlData3.bMonitorDuplicateInstances;
  1549. pOptions->fUpdateInterval = CtrlData3.fUpdateInterval;
  1550. pOptions->iDisplayType = CtrlData3.iDisplayType;
  1551. pOptions->clrBackCtl = CtrlData3.clrBackCtl;
  1552. pOptions->clrFore = CtrlData3.clrFore;
  1553. pOptions->clrBackPlot = CtrlData3.clrBackPlot;
  1554. pOptions->iAppearance = CtrlData3.iAppearance;
  1555. pOptions->iBorderStyle = CtrlData3.iBorderStyle;
  1556. pOptions->iReportValueType = CtrlData3.iReportValueType; // New for 3.1+, default = 0
  1557. pOptions->iDisplayFilter = CtrlData3.iDisplayFilter; // New for 3.4, default = 1, 0 is invalid
  1558. iLocalDataSourceType = CtrlData3.iDataSourceType; // New for 3.4, default = 1, 0 is invalid
  1559. // Pre-3.4, set based on presence of log file name
  1560. // Set pOptions->iDataSourceType below
  1561. if ( 0 == pOptions->iDisplayFilter ) {
  1562. // New for 3.4
  1563. assert ( ( SMONCTRL_MIN_VERSION - 2 ) > VersionData.iMinor );
  1564. pOptions->iDisplayFilter = 1;
  1565. }
  1566. if ( ( SMONCTRL_MIN_VERSION - 6 ) < VersionData.iMinor ) {
  1567. // Grid and TimeBar saved to file as of version 3.1.
  1568. pOptions->clrGrid = CtrlData3.clrGrid;
  1569. pOptions->clrTimeBar = CtrlData3.clrTimeBar;
  1570. } else {
  1571. assert ( 0 == VersionData.iMinor );
  1572. pOptions->clrGrid = RGB(128,128,128); // Medium gray
  1573. pOptions->clrTimeBar = RGB(255,0,0); // Red
  1574. }
  1575. if ( (SMONCTRL_MIN_VERSION - 3) > VersionData.iMinor ) {
  1576. // Saved to file as of version 3.3
  1577. pOptions->bMonitorDuplicateInstances = 1;
  1578. }
  1579. // Load font info if not using ambient font
  1580. if ( !pOptions->bAmbientFont ) {
  1581. hr = m_OleFont.LoadFromStream(pIStream);
  1582. if (FAILED(hr))
  1583. return hr;
  1584. }
  1585. // Read titles and log file name
  1586. if ( ( SMONCTRL_MIN_VERSION - 5 ) < VersionData.iMinor ) {
  1587. // As of Version 3.2, title and log file name strings stored as Wide characters
  1588. // Log file name
  1589. hr = WideStringFromStream(pIStream, &szLogFilePath, CtrlData3.nFileNameLen);
  1590. if (FAILED(hr))
  1591. return hr;
  1592. // Graph title
  1593. hr = WideStringFromStream(pIStream, &pOptions->pszGraphTitle, CtrlData3.nGraphTitleLen);
  1594. if (FAILED(hr))
  1595. return hr;
  1596. // Y axis label
  1597. hr = WideStringFromStream(pIStream, &pOptions->pszYaxisTitle, CtrlData3.nYaxisTitleLen);
  1598. if (FAILED(hr))
  1599. return hr;
  1600. } else {
  1601. // Log file name
  1602. hr = StringFromStream(pIStream, &szLogFilePath, CtrlData3.nFileNameLen);
  1603. if (FAILED(hr))
  1604. return hr;
  1605. // Graph title
  1606. hr = StringFromStream(pIStream, &pOptions->pszGraphTitle, CtrlData3.nGraphTitleLen);
  1607. if (FAILED(hr))
  1608. return hr;
  1609. // Y axis label
  1610. hr = StringFromStream(pIStream, &pOptions->pszYaxisTitle, CtrlData3.nYaxisTitleLen);
  1611. if (FAILED(hr))
  1612. return hr;
  1613. }
  1614. // Read display range
  1615. m_DataSourceInfo.llStartDisp = CtrlData3.llStartDisp;
  1616. m_DataSourceInfo.llStopDisp = CtrlData3.llStopDisp;
  1617. // Must put actual data source type after loading display range, before adding counters.
  1618. // Always set data source to null data source before adding data source names.
  1619. hr = put_DataSourceType ( sysmonNullDataSource );
  1620. if ( SUCCEEDED ( hr ) && NULL != szLogFilePath ) {
  1621. assert ( 0 == NumLogFiles() );
  1622. if ( L'\0' != szLogFilePath[0] ) {
  1623. if ( ( SMONCTRL_MIN_VERSION - 1 ) > VersionData.iMinor ) {
  1624. // 3.4 writes a single log file.
  1625. hr = AddSingleLogFile ( szLogFilePath );
  1626. } else {
  1627. // 3.5+ writes a multi_sz
  1628. hr = LoadLogFilesFromMultiSz ( szLogFilePath );
  1629. }
  1630. }
  1631. }
  1632. if ( NULL != szLogFilePath ) {
  1633. delete szLogFilePath;
  1634. }
  1635. // If version < 3.4, set data source type based on presence of log files.
  1636. if ( ( SMONCTRL_MIN_VERSION - 2 ) > VersionData.iMinor ) {
  1637. // DataSourceType is new for 3.4
  1638. if ( 0 == NumLogFiles() ) {
  1639. iLocalDataSourceType = sysmonCurrentActivity;
  1640. } else {
  1641. iLocalDataSourceType = sysmonLogFiles;
  1642. }
  1643. }
  1644. // Set scale max and min
  1645. m_pObj->m_Graph.Scale.SetMaxValue(pOptions->iVertMax);
  1646. m_pObj->m_Graph.Scale.SetMinValue(pOptions->iVertMin);
  1647. // Convert non-null OLE colors to real colors
  1648. if (pOptions->clrFore != NULL_COLOR)
  1649. OleTranslateColor(pOptions->clrFore, NULL, &m_clrFgnd);
  1650. if (pOptions->clrBackPlot != NULL_COLOR)
  1651. OleTranslateColor(pOptions->clrBackPlot, NULL, &m_clrBackPlot);
  1652. // NT 5 Beta 1 BackCtlColor can be NULL.
  1653. if (pOptions->clrBackCtl != NULL_COLOR)
  1654. OleTranslateColor(pOptions->clrBackCtl, NULL, &m_clrBackCtl);
  1655. OleTranslateColor(pOptions->clrGrid, NULL, &m_clrGrid);
  1656. OleTranslateColor(pOptions->clrTimeBar, NULL, &m_clrTimeBar);
  1657. // Handle other ambient properties
  1658. if ( NULL_APPEARANCE != pOptions->iAppearance )
  1659. put_Appearance( pOptions->iAppearance, FALSE );
  1660. if ( NULL_BORDERSTYLE != pOptions->iBorderStyle )
  1661. put_BorderStyle( pOptions->iBorderStyle, FALSE );
  1662. // Read legend data
  1663. hr = m_pLegend->LoadFromStream(pIStream);
  1664. if (FAILED(hr))
  1665. return hr;
  1666. //Load the counters
  1667. hr = S_OK;
  1668. // Load the counters into temporary storage, so that they can be added after the
  1669. // SQL name and future items are loaded
  1670. while (TRUE) {
  1671. pNewElem = new ( DATA_LIST_ELEM );
  1672. if ( NULL != pNewElem ) {
  1673. ZeroMemory ( pNewElem, sizeof ( DATA_LIST_ELEM ) );
  1674. // Add to end of list
  1675. pNewElem->pNext = NULL;
  1676. if ( NULL == pFirstElem ) {
  1677. pFirstElem = pNewElem;
  1678. pLastElem = pFirstElem;
  1679. } else if ( NULL == pLastElem ) {
  1680. pLastElem = pNewElem;
  1681. } else {
  1682. pLastElem->pNext = pNewElem;
  1683. pLastElem = pNewElem;
  1684. }
  1685. // Read in parameters
  1686. hr = pIStream->Read(&pNewElem->itemData, sizeof(GRAPHITEM_DATA3), &bc);
  1687. if ( SUCCEEDED ( hr ) ) {
  1688. if (bc == sizeof(GRAPHITEM_DATA3)) {
  1689. // Stop on null item (indicated by no path name)
  1690. if (pNewElem->itemData.m_nPathLength == 0) {
  1691. break;
  1692. }
  1693. } else {
  1694. hr = E_FAIL;
  1695. }
  1696. }
  1697. } else {
  1698. hr = E_OUTOFMEMORY;
  1699. }
  1700. if ( SUCCEEDED ( hr ) ) {
  1701. if ( ( SMONCTRL_MIN_VERSION - 5 ) < VersionData.iMinor ) {
  1702. // As of Version 3.2, title and log file name strings stored as Wide characters
  1703. // Read in path name
  1704. hr = WideStringFromStream(pIStream, &pszCounterPath, pNewElem->itemData.m_nPathLength);
  1705. } else {
  1706. // Read in path name
  1707. hr = StringFromStream(pIStream, &pszCounterPath, pNewElem->itemData.m_nPathLength);
  1708. }
  1709. }
  1710. if ( SUCCEEDED ( hr ) ) {
  1711. pNewElem->szCounterPath = pszCounterPath;
  1712. pszCounterPath = NULL;
  1713. }
  1714. }
  1715. if ( NULL != pszCounterPath ) {
  1716. delete pszCounterPath;
  1717. pszCounterPath = NULL;
  1718. }
  1719. if ( FAILED ( hr ) ) {
  1720. while ( NULL != pFirstElem ) {
  1721. pNewElem = pFirstElem->pNext;
  1722. if ( NULL != pFirstElem->szCounterPath ) {
  1723. delete pFirstElem->szCounterPath;
  1724. }
  1725. delete pFirstElem;
  1726. pFirstElem = pNewElem;
  1727. }
  1728. return hr;
  1729. }
  1730. // Load SQL names from the stream
  1731. hr = WideStringFromStream(pIStream, &m_DataSourceInfo.szSqlDsnName, CtrlData3.iSqlDsnLen);
  1732. if ( FAILED ( hr ) )
  1733. return hr;
  1734. hr = WideStringFromStream(pIStream, &m_DataSourceInfo.szSqlLogSetName, CtrlData3.iSqlLogSetNameLen);
  1735. if (FAILED(hr))
  1736. return hr;
  1737. // Set the data source
  1738. hr = put_DataSourceType ( iLocalDataSourceType );
  1739. if (FAILED(hr)) {
  1740. if ( SMON_STATUS_LOG_FILE_SIZE_LIMIT == hr ) {
  1741. // TodoLogFiles: Check log file type. Only perfmon and circular
  1742. // binary logs are still limited to 1 GB.
  1743. // TodoLogFiles: Current query is already closed,
  1744. // so what can be done here?
  1745. } else {
  1746. DWORD dwStatus;
  1747. LPWSTR szLogFileList = NULL;
  1748. ULONG ulLogListBufLen= 0;
  1749. if ( sysmonLogFiles == iLocalDataSourceType ) {
  1750. dwStatus = BuildLogFileList (
  1751. NULL,
  1752. TRUE,
  1753. &ulLogListBufLen );
  1754. szLogFileList = (LPWSTR) malloc(ulLogListBufLen * sizeof(WCHAR));
  1755. if ( NULL != szLogFileList ) {
  1756. dwStatus = BuildLogFileList (
  1757. szLogFileList,
  1758. TRUE,
  1759. &ulLogListBufLen );
  1760. }
  1761. }
  1762. dwStatus = DisplayDataSourceError (
  1763. m_hWnd,
  1764. (DWORD)hr,
  1765. iLocalDataSourceType,
  1766. szLogFileList,
  1767. m_DataSourceInfo.szSqlDsnName,
  1768. m_DataSourceInfo.szSqlLogSetName );
  1769. if ( NULL != szLogFileList ) {
  1770. delete szLogFileList;
  1771. }
  1772. }
  1773. }
  1774. m_bLogFileSource = ( sysmonCurrentActivity != m_pObj->m_Graph.Options.iDataSourceType );
  1775. hr = S_OK;
  1776. // Load the counters from the temporary data storage.
  1777. m_bLoadingCounters = TRUE;
  1778. for ( pNewElem = pFirstElem; NULL != pNewElem; pNewElem = pNewElem->pNext ) {
  1779. DWORD dwBufSize;
  1780. LPTSTR pNewBuf;
  1781. PDH_STATUS pdhStatus;
  1782. CallbackInfo.pCtrl = this;
  1783. CallbackInfo.pFirstItem = NULL;
  1784. // Stop on null item (indicated by no path name)
  1785. if ( 0 == pNewElem->itemData.m_nPathLength ) {
  1786. break;
  1787. }
  1788. // Set up properties so AddCounter can use them
  1789. m_clrCounter = pNewElem->itemData.m_rgbColor;
  1790. m_iColorIndex = ColorToIndex (pNewElem->itemData.m_rgbColor);
  1791. m_iWidthIndex = WidthToIndex (pNewElem->itemData.m_iWidth);
  1792. m_iStyleIndex = StyleToIndex (pNewElem->itemData.m_iStyle);
  1793. m_iScaleFactor = pNewElem->itemData.m_iScaleFactor;
  1794. pszPath = pNewElem->szCounterPath;
  1795. //
  1796. // Initialize the locale path buffer
  1797. //
  1798. if (dwLocaleBufSize == 0) {
  1799. dwLocaleBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  1800. szLocaleBuf = (LPTSTR) malloc(dwLocaleBufSize);
  1801. if (szLocaleBuf == NULL) {
  1802. dwLocaleBufSize = 0;
  1803. }
  1804. }
  1805. if (szLocaleBuf != NULL) {
  1806. //
  1807. // Translate counter name from English to Localization
  1808. //
  1809. dwBufSize = dwLocaleBufSize;
  1810. pdhStatus = PdhTranslateLocaleCounter(
  1811. pNewElem->szCounterPath,
  1812. szLocaleBuf,
  1813. &dwBufSize);
  1814. if (pdhStatus == PDH_MORE_DATA) {
  1815. pNewBuf = (LPTSTR) realloc(szLocaleBuf, dwBufSize);
  1816. if (pNewBuf != NULL) {
  1817. szLocaleBuf = pNewBuf;
  1818. dwLocaleBufSize = dwBufSize;
  1819. pdhStatus = PdhTranslateLocaleCounter(
  1820. pNewElem->szCounterPath,
  1821. szLocaleBuf,
  1822. &dwBufSize);
  1823. }
  1824. }
  1825. if (pdhStatus == ERROR_SUCCESS) {
  1826. pszPath = szLocaleBuf;
  1827. }
  1828. }
  1829. // Add new counter to control
  1830. EnumExpandedPath (GetDataSourceHandle(),
  1831. pszPath,
  1832. AddCounterCallback,
  1833. &CallbackInfo );
  1834. }
  1835. if (szLocaleBuf != NULL) {
  1836. free(szLocaleBuf);
  1837. }
  1838. m_bLoadingCounters = FALSE;
  1839. while ( NULL != pFirstElem ) {
  1840. pNewElem = pFirstElem->pNext;
  1841. if ( NULL != pFirstElem->szCounterPath ) {
  1842. delete pFirstElem->szCounterPath;
  1843. }
  1844. delete pFirstElem;
  1845. pFirstElem = pNewElem;
  1846. }
  1847. if ( SMONCTRL_MAJ_VERSION == VersionData.iMajor
  1848. && SMONCTRL_MIN_VERSION == VersionData.iMinor ) {
  1849. m_pObj->m_fDirty=FALSE;
  1850. } else {
  1851. m_pObj->m_fDirty=TRUE;
  1852. }
  1853. if ( SMONCTRL_MIN_VERSION == VersionData.iMinor ) {
  1854. // New for 3.6: Save visuals to the stream
  1855. // These must be loaded after the counters are loaded.
  1856. m_iColorIndex = CtrlData3.iColorIndex;
  1857. m_iWidthIndex = CtrlData3.iWidthIndex;
  1858. m_iStyleIndex = CtrlData3.iStyleIndex;
  1859. }
  1860. } // Settings not loaded yet.
  1861. return hr;
  1862. }
  1863. HRESULT
  1864. CSysmonControl::SaveToStream(LPSTREAM pIStream)
  1865. {
  1866. HRESULT hr = NOERROR;
  1867. DWORD dwStatus = ERROR_SUCCESS;
  1868. GRAPH_OPTIONS *pOptions = &m_pObj->m_Graph.Options;
  1869. RECT RectExt;
  1870. SMONCTRL_VERSION_DATA VersionData;
  1871. LPWSTR pszWideGraphTitle;
  1872. LPWSTR pszWideYaxisTitle;
  1873. PCMachineNode pMachine;
  1874. PCObjectNode pObject;
  1875. PCInstanceNode pInstance;
  1876. PCGraphItem pItem;
  1877. PCCounterNode pCounter;
  1878. ULONG ulLogFileListLen = 0;
  1879. LPWSTR szLogFileList = NULL;
  1880. GRAPHCTRL_DATA3 CtrlData3;
  1881. USES_CONVERSION
  1882. assert( 256 == sizeof(CtrlData3) );
  1883. ZeroMemory( &CtrlData3, 256 );
  1884. //Store extent data in HIMETRIC format
  1885. RectExt = m_pObj->m_RectExt;
  1886. m_pObj->RectConvertMappings(&RectExt, FALSE);
  1887. CtrlData3.iWidth = RectExt.right - RectExt.left;
  1888. CtrlData3.iHeight = RectExt.bottom - RectExt.top;
  1889. // Store options settings in structure
  1890. CtrlData3.iScaleMax = pOptions->iVertMax;
  1891. CtrlData3.iScaleMin = pOptions->iVertMin;
  1892. CtrlData3.bLegend = pOptions->bLegendChecked;
  1893. CtrlData3.bToolbar = pOptions->bToolbarChecked;
  1894. CtrlData3.bLabels = pOptions->bLabelsChecked;
  1895. CtrlData3.bHorzGrid = pOptions->bHorzGridChecked;
  1896. CtrlData3.bVertGrid = pOptions->bVertGridChecked;
  1897. CtrlData3.bValueBar = pOptions->bValueBarChecked;
  1898. CtrlData3.bManualUpdate = pOptions->bManualUpdate;
  1899. CtrlData3.bHighlight = pOptions->bHighlight;
  1900. CtrlData3.bReadOnly = pOptions->bReadOnly;
  1901. CtrlData3.bMonitorDuplicateInstances = pOptions->bMonitorDuplicateInstances;
  1902. CtrlData3.bAmbientFont = pOptions->bAmbientFont;
  1903. CtrlData3.fUpdateInterval = pOptions->fUpdateInterval;
  1904. CtrlData3.iDisplayType = pOptions->iDisplayType;
  1905. CtrlData3.iReportValueType = pOptions->iReportValueType;
  1906. CtrlData3.clrBackCtl = pOptions->clrBackCtl;
  1907. CtrlData3.clrFore = pOptions->clrFore;
  1908. CtrlData3.clrBackPlot = pOptions->clrBackPlot;
  1909. CtrlData3.iAppearance = pOptions->iAppearance;
  1910. CtrlData3.iBorderStyle = pOptions->iBorderStyle;
  1911. CtrlData3.clrGrid = pOptions->clrGrid;
  1912. CtrlData3.clrTimeBar = pOptions->clrTimeBar;
  1913. CtrlData3.iDisplayFilter = pOptions->iDisplayFilter;
  1914. CtrlData3.iDataSourceType = pOptions->iDataSourceType;
  1915. // Store the visuals in pOptions if they become visible
  1916. // via the programming interface.
  1917. CtrlData3.iColorIndex = m_iColorIndex;
  1918. CtrlData3.iWidthIndex = m_iWidthIndex;
  1919. CtrlData3.iStyleIndex = m_iStyleIndex;
  1920. // NT 5 Beta 1 BackColorCtl can be NULL.
  1921. if ( NULL_COLOR == pOptions->clrBackCtl )
  1922. CtrlData3.clrBackCtl = m_clrBackCtl;
  1923. // Save number of samples to keep
  1924. CtrlData3.nSamples = m_pHistCtrl->nMaxSamples;
  1925. // Store Wide string lengths
  1926. pszWideGraphTitle = T2W(pOptions->pszGraphTitle);
  1927. CtrlData3.nGraphTitleLen = (pszWideGraphTitle == NULL) ?
  1928. 0 : lstrlen(pszWideGraphTitle);
  1929. pszWideYaxisTitle = T2W(pOptions->pszYaxisTitle);
  1930. CtrlData3.nYaxisTitleLen = (pszWideYaxisTitle == NULL) ?
  1931. 0 : lstrlen(pszWideYaxisTitle);
  1932. BuildLogFileList ( NULL, FALSE, &ulLogFileListLen );
  1933. CtrlData3.nFileNameLen = (INT32) ulLogFileListLen;
  1934. CtrlData3.iSqlDsnLen = 0;
  1935. if ( NULL != m_DataSourceInfo.szSqlDsnName ) {
  1936. CtrlData3.iSqlDsnLen = lstrlen ( m_DataSourceInfo.szSqlDsnName );
  1937. }
  1938. CtrlData3.iSqlLogSetNameLen = 0;
  1939. if ( NULL != m_DataSourceInfo.szSqlLogSetName ) {
  1940. CtrlData3.iSqlLogSetNameLen = lstrlen ( m_DataSourceInfo.szSqlLogSetName );
  1941. }
  1942. // Store other file info
  1943. CtrlData3.llStartDisp = m_DataSourceInfo.llStartDisp;
  1944. CtrlData3.llStopDisp = m_DataSourceInfo.llStopDisp;
  1945. // Write version info
  1946. VersionData.iMajor = SMONCTRL_MAJ_VERSION;
  1947. VersionData.iMinor = SMONCTRL_MIN_VERSION;
  1948. hr = pIStream->Write(&VersionData, sizeof(VersionData), NULL);
  1949. if (FAILED(hr))
  1950. return hr;
  1951. // Write control data
  1952. hr = pIStream->Write(&CtrlData3, sizeof(CtrlData3), NULL);
  1953. if (FAILED(hr))
  1954. return hr;
  1955. // Write font info if not using ambient font
  1956. if ( !pOptions->bAmbientFont ) {
  1957. hr = m_OleFont.SaveToStream(pIStream, TRUE);
  1958. if (FAILED(hr))
  1959. return hr;
  1960. }
  1961. // Write log file name
  1962. if (CtrlData3.nFileNameLen != 0) {
  1963. szLogFileList = (LPWSTR) malloc(ulLogFileListLen * sizeof(WCHAR));
  1964. if ( NULL != szLogFileList ) {
  1965. dwStatus = BuildLogFileList (
  1966. szLogFileList,
  1967. FALSE,
  1968. &ulLogFileListLen );
  1969. if ( ERROR_SUCCESS != dwStatus ) {
  1970. hr = E_FAIL;
  1971. }
  1972. } else {
  1973. hr = E_OUTOFMEMORY;
  1974. }
  1975. if ( SUCCEEDED ( hr ) ) {
  1976. hr = pIStream->Write(szLogFileList, CtrlData3.nFileNameLen*sizeof(WCHAR), NULL);
  1977. }
  1978. if ( NULL != szLogFileList ) {
  1979. delete szLogFileList;
  1980. szLogFileList = NULL;
  1981. }
  1982. if (FAILED(hr))
  1983. return hr;
  1984. }
  1985. // Write titles
  1986. if (CtrlData3.nGraphTitleLen != 0) {
  1987. hr = pIStream->Write(pszWideGraphTitle, CtrlData3.nGraphTitleLen*sizeof(WCHAR), NULL);
  1988. if (FAILED(hr))
  1989. return hr;
  1990. }
  1991. if (CtrlData3.nYaxisTitleLen != 0) {
  1992. hr = pIStream->Write(pszWideYaxisTitle, CtrlData3.nYaxisTitleLen*sizeof(WCHAR), NULL);
  1993. if (FAILED(hr))
  1994. return hr;
  1995. }
  1996. // Write legend data
  1997. hr = m_pLegend->SaveToStream(pIStream);
  1998. if (FAILED(hr))
  1999. return hr;
  2000. // Save all counter info
  2001. // Explicit counters first, followed by "All Instance" groups
  2002. for ( pMachine = CounterTree()->FirstMachine();
  2003. pMachine;
  2004. pMachine = pMachine->Next()) {
  2005. for ( pObject = pMachine->FirstObject();
  2006. pObject;
  2007. pObject = pObject->Next()) {
  2008. // Clear generated pointer for all object's counters
  2009. for ( pCounter = pObject->FirstCounter();
  2010. pCounter;
  2011. pCounter = pCounter->Next()) {
  2012. pCounter->m_pFirstGenerated = NULL;
  2013. }
  2014. for ( pInstance = pObject->FirstInstance();
  2015. pInstance;
  2016. pInstance = pInstance->Next()) {
  2017. for ( pItem = pInstance->FirstItem();
  2018. pItem;
  2019. pItem = pItem->m_pNextItem) {
  2020. // If item is the first generated one for this counter
  2021. // then save it as the wild card model for this counter
  2022. if (pItem->m_fGenerated) {
  2023. if (pItem->Counter()->m_pFirstGenerated == NULL)
  2024. pItem->Counter()->m_pFirstGenerated = pItem;
  2025. }
  2026. else {
  2027. // else save it explictly
  2028. hr = pItem->SaveToStream(pIStream, FALSE, VersionData.iMajor, VersionData.iMinor);
  2029. if (FAILED(hr))
  2030. return hr;
  2031. }
  2032. }
  2033. }
  2034. // Now go through counters again and store a wildcard path
  2035. // for any that have genererated counters
  2036. for (pCounter = pObject->FirstCounter();
  2037. pCounter;
  2038. pCounter = pCounter->Next()) {
  2039. if (pCounter->m_pFirstGenerated) {
  2040. hr = pCounter->m_pFirstGenerated->SaveToStream(pIStream, TRUE, VersionData.iMajor, VersionData.iMinor);
  2041. if (FAILED(hr))
  2042. return hr;
  2043. }
  2044. }
  2045. }
  2046. }
  2047. // Write null item to mark end of counter items
  2048. hr = CGraphItem::NullItemToStream(pIStream, VersionData.iMajor, VersionData.iMinor);
  2049. // Write Sql data source names
  2050. if (CtrlData3.iSqlDsnLen != 0) {
  2051. hr = pIStream->Write(m_DataSourceInfo.szSqlDsnName, CtrlData3.iSqlDsnLen*sizeof(WCHAR), NULL);
  2052. }
  2053. if (CtrlData3.iSqlLogSetNameLen != 0) {
  2054. hr = pIStream->Write(m_DataSourceInfo.szSqlLogSetName, CtrlData3.iSqlLogSetNameLen*sizeof(WCHAR), NULL);
  2055. }
  2056. return hr;
  2057. }
  2058. HRESULT
  2059. CSysmonControl::LoadLogFilesFromPropertyBag (
  2060. IPropertyBag* pIPropBag,
  2061. IErrorLog* pIErrorLog )
  2062. {
  2063. HRESULT hr = S_OK;
  2064. HRESULT hrErr = S_OK;
  2065. INT iLogFileCount = 0;
  2066. INT iIndex;
  2067. INT iBufSize = 0;
  2068. INT iPrevBufSize = 0;
  2069. LPTSTR pszLogFilePath = NULL;
  2070. INT iLogFilePathBufSize = 0;
  2071. WCHAR szLogFilePropName[32];
  2072. eDataSourceTypeConstant ePrevDataSourceType;
  2073. DWORD dwErrorPathListLen;
  2074. LPCWSTR szErrorPathList = NULL;
  2075. LPWSTR szMessage = NULL;
  2076. get_DataSourceType ( ePrevDataSourceType );
  2077. ClearErrorPathList();
  2078. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszLogFileName, NULL, iBufSize );
  2079. if ( SUCCEEDED(hr) &&
  2080. iBufSize > 0 ) {
  2081. pszLogFilePath = new TCHAR[iBufSize + 1];
  2082. if ( NULL != pszLogFilePath ) {
  2083. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszLogFileName, pszLogFilePath, iBufSize );
  2084. } else {
  2085. hr = E_OUTOFMEMORY;
  2086. }
  2087. if ( SUCCEEDED ( hr ) ) {
  2088. // Always set the log source to null data source before modifying the log file list.
  2089. // TodoLogFiles: This can leave the user with state different than before, in the
  2090. // case of log file load failure.
  2091. hr = put_DataSourceType ( sysmonNullDataSource );
  2092. if ( SUCCEEDED ( hr ) ) {
  2093. assert ( 0 == NumLogFiles() );
  2094. hr = AddSingleLogFile ( pszLogFilePath );
  2095. }
  2096. }
  2097. if ( FAILED ( hr ) && NULL != pszLogFilePath ) {
  2098. hrErr = hr;
  2099. AddToErrorPathList ( pszLogFilePath );
  2100. }
  2101. if ( NULL != pszLogFilePath ) {
  2102. delete pszLogFilePath;
  2103. pszLogFilePath = NULL;
  2104. }
  2105. } else {
  2106. hr = IntegerFromPropertyBag (pIPropBag, pIErrorLog, CGlobalString::m_cszLogFileCount, iLogFileCount );
  2107. if ( SUCCEEDED( hr ) && 0 < iLogFileCount ) {
  2108. assert ( 0 == NumLogFiles() );
  2109. for ( iIndex = 1; iIndex <= iLogFileCount; iIndex++ ) {
  2110. // Todo: log file list error message, as for counters
  2111. // If one of the log files fails to load, continue loading others.
  2112. hr = NOERROR;
  2113. swprintf ( szLogFilePropName, CGlobalString::m_cszLogNameFormat, CGlobalString::m_cszLogFileName, iIndex );
  2114. iPrevBufSize = iBufSize;
  2115. hr = StringFromPropertyBag (
  2116. pIPropBag,
  2117. pIErrorLog,
  2118. szLogFilePropName,
  2119. pszLogFilePath,
  2120. iBufSize );
  2121. if ( iBufSize > iPrevBufSize ) {
  2122. if ( NULL == pszLogFilePath || (iBufSize > iLogFilePathBufSize) ) {
  2123. if ( NULL != pszLogFilePath ) {
  2124. delete pszLogFilePath;
  2125. pszLogFilePath = 0;
  2126. }
  2127. pszLogFilePath = new WCHAR[iBufSize];
  2128. if ( NULL != pszLogFilePath ) {
  2129. iLogFilePathBufSize = iBufSize;
  2130. }
  2131. }
  2132. if ( NULL != pszLogFilePath ) {
  2133. hr = StringFromPropertyBag (
  2134. pIPropBag,
  2135. pIErrorLog,
  2136. szLogFilePropName,
  2137. pszLogFilePath,
  2138. iBufSize );
  2139. } else {
  2140. hr = E_OUTOFMEMORY;
  2141. }
  2142. }
  2143. if ( SUCCEEDED(hr)
  2144. && MAX_PATH >= lstrlen(pszLogFilePath) ) {
  2145. hr = put_DataSourceType ( sysmonNullDataSource );
  2146. if ( SUCCEEDED ( hr ) ) {
  2147. hr = AddSingleLogFile ( pszLogFilePath );
  2148. }
  2149. }
  2150. if ( FAILED ( hr )
  2151. && SMON_STATUS_DUPL_LOG_FILE_PATH != hr )
  2152. {
  2153. if ( S_OK == hrErr ) {
  2154. hrErr = hr;
  2155. }
  2156. AddToErrorPathList ( pszLogFilePath );
  2157. }
  2158. }
  2159. }
  2160. }
  2161. if ( NULL != pszLogFilePath ) {
  2162. delete pszLogFilePath;
  2163. pszLogFilePath = NULL;
  2164. }
  2165. if ( SMON_STATUS_DUPL_LOG_FILE_PATH != hr ) {
  2166. szErrorPathList = GetErrorPathList ( &dwErrorPathListLen );
  2167. if ( NULL != szErrorPathList ) {
  2168. // Report error, but continue.
  2169. szMessage = new WCHAR [dwErrorPathListLen + MAX_PATH];
  2170. if ( NULL != szMessage ) {
  2171. _stprintf ( szMessage, ResourceString(IDS_ADD_LOG_FILE_ERR), szErrorPathList );
  2172. MessageBox (
  2173. m_hWnd,
  2174. szMessage,
  2175. ResourceString(IDS_APP_NAME),
  2176. MB_OK | MB_ICONEXCLAMATION );
  2177. delete szMessage;
  2178. }
  2179. }
  2180. }
  2181. ClearErrorPathList();
  2182. return hrErr;
  2183. }
  2184. HRESULT
  2185. CSysmonControl::LoadCountersFromPropertyBag (
  2186. IPropertyBag* pIPropBag,
  2187. IErrorLog* pIErrorLog,
  2188. BOOL bLoadData )
  2189. {
  2190. HRESULT hr = S_OK;
  2191. HRESULT hrErr = S_OK;
  2192. INT iCounterCount = 0;
  2193. INT iSampleCount = 0;
  2194. INT intValue;
  2195. INT iIndex;
  2196. INT iBufSize = 0;
  2197. INT iPrevBufSize = 0;
  2198. LPTSTR pszCounterPath = NULL;
  2199. INT iCounterPathBufSize = 0;
  2200. TCHAR szSelected[MAX_PATH+1];
  2201. TCHAR szPathPropName[32];
  2202. LPTSTR szEnglishBuf = NULL;
  2203. DWORD dwEnglishBufSize = 0;
  2204. LPTSTR pszPath = NULL;
  2205. DWORD dwBufSize;
  2206. LPTSTR pNewBuf;
  2207. PDH_STATUS pdhStatus;
  2208. PCGraphItem pItem = NULL;
  2209. lstrcpy ( szSelected, L"" );
  2210. hr = IntegerFromPropertyBag (pIPropBag, pIErrorLog, CGlobalString::m_cszCounterCount, iCounterCount );
  2211. if ( SUCCEEDED( hr ) && 0 < iCounterCount ) {
  2212. iBufSize = MAX_PATH+1;
  2213. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszSelected, szSelected, iBufSize );
  2214. if( SUCCEEDED( hr ) ){
  2215. //
  2216. // Initialize the locale path buffer
  2217. //
  2218. if (dwEnglishBufSize == 0) {
  2219. dwEnglishBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  2220. szEnglishBuf = (LPTSTR) malloc(dwEnglishBufSize);
  2221. if (szEnglishBuf == NULL) {
  2222. dwEnglishBufSize = 0;
  2223. }
  2224. }
  2225. if (szEnglishBuf != NULL) {
  2226. //
  2227. // Translate counter name from Localization into English
  2228. //
  2229. dwBufSize = dwEnglishBufSize;
  2230. pdhStatus = PdhTranslate009Counter(
  2231. szSelected,
  2232. szEnglishBuf,
  2233. &dwBufSize);
  2234. if (pdhStatus == PDH_MORE_DATA) {
  2235. pNewBuf = (LPTSTR)realloc(szEnglishBuf, dwBufSize);
  2236. if (pNewBuf != NULL) {
  2237. szEnglishBuf = pNewBuf;
  2238. dwEnglishBufSize = dwBufSize;
  2239. pdhStatus = PdhTranslate009Counter(
  2240. szSelected,
  2241. szEnglishBuf,
  2242. &dwBufSize);
  2243. }
  2244. }
  2245. if (pdhStatus == ERROR_SUCCESS && dwBufSize < sizeof(szSelected) ) {
  2246. lstrcpy(szSelected, szEnglishBuf);
  2247. }
  2248. }
  2249. }
  2250. }
  2251. if ( bLoadData ) {
  2252. hr = IntegerFromPropertyBag (pIPropBag, pIErrorLog, CGlobalString::m_cszSampleCount, iSampleCount );
  2253. if ( SUCCEEDED(hr) && ( 0 < iSampleCount ) ) {
  2254. intValue = 0;
  2255. hr = IntegerFromPropertyBag (pIPropBag, pIErrorLog, CGlobalString::m_cszSampleIndex, intValue );
  2256. if ( SUCCEEDED(hr) && intValue > 0 && intValue <= iSampleCount ) {
  2257. INT iStepNum;
  2258. hr = IntegerFromPropertyBag (
  2259. pIPropBag,
  2260. pIErrorLog,
  2261. CGlobalString::m_cszStepNumber, iStepNum );
  2262. if ( SUCCEEDED(hr) ) {
  2263. // If data has been passed, freeze the view.
  2264. // These values are set only if all three values are present in the property bag.
  2265. put_ManualUpdate( TRUE );
  2266. // MaxSamples hardcoded for NT5
  2267. m_pHistCtrl->nSamples = iSampleCount;
  2268. m_pHistCtrl->iCurrent = intValue;
  2269. m_pObj->m_Graph.TimeStepper.StepTo(iStepNum);
  2270. m_bSampleDataLoaded = TRUE;
  2271. }
  2272. }
  2273. }
  2274. } else {
  2275. iSampleCount = 0;
  2276. }
  2277. iBufSize = 0;
  2278. ClearErrorPathList();
  2279. for ( iIndex = 1; iIndex <= iCounterCount; iIndex++ ) {
  2280. // If one of the counters fails to load, continue loading others.
  2281. hr = NOERROR;
  2282. _stprintf ( szPathPropName, TEXT("%s%05d.Path"), CGlobalString::m_cszCounter, iIndex );
  2283. iPrevBufSize = iBufSize;
  2284. hr = StringFromPropertyBag (
  2285. pIPropBag,
  2286. pIErrorLog,
  2287. szPathPropName,
  2288. pszCounterPath,
  2289. iBufSize );
  2290. if ( iBufSize > iPrevBufSize ) {
  2291. if ( NULL == pszCounterPath || (iBufSize > iCounterPathBufSize) ) {
  2292. if ( NULL != pszCounterPath ) {
  2293. delete pszCounterPath;
  2294. iCounterPathBufSize = 0;
  2295. }
  2296. pszCounterPath = new TCHAR[iBufSize];
  2297. if ( NULL != pszCounterPath ) {
  2298. iCounterPathBufSize = iBufSize;
  2299. }
  2300. }
  2301. if ( NULL != pszCounterPath ) {
  2302. hr = StringFromPropertyBag (
  2303. pIPropBag,
  2304. pIErrorLog,
  2305. szPathPropName,
  2306. pszCounterPath,
  2307. iBufSize );
  2308. } else {
  2309. hr = E_OUTOFMEMORY;
  2310. }
  2311. }
  2312. pszPath = pszCounterPath;
  2313. if ( SUCCEEDED(hr)
  2314. && MAX_PATH >= lstrlen(pszCounterPath) ) {
  2315. //
  2316. // Translate English counter name into localized counter name
  2317. //
  2318. if (dwEnglishBufSize == 0) {
  2319. dwEnglishBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  2320. szEnglishBuf = (LPTSTR) malloc(dwEnglishBufSize);
  2321. if (szEnglishBuf == NULL) {
  2322. dwEnglishBufSize = 0;
  2323. }
  2324. }
  2325. if (szEnglishBuf != NULL) {
  2326. //
  2327. // Translate counter name from English to Localization
  2328. //
  2329. dwBufSize = dwEnglishBufSize;
  2330. pdhStatus = PdhTranslateLocaleCounter(
  2331. pszCounterPath,
  2332. szEnglishBuf,
  2333. &dwBufSize);
  2334. if (pdhStatus == PDH_MORE_DATA) {
  2335. pNewBuf = (LPTSTR) realloc(szEnglishBuf, dwBufSize);
  2336. if (pNewBuf != NULL) {
  2337. szEnglishBuf = pNewBuf;
  2338. dwEnglishBufSize = dwBufSize;
  2339. pdhStatus = PdhTranslateLocaleCounter(
  2340. pszCounterPath,
  2341. szEnglishBuf,
  2342. &dwBufSize);
  2343. }
  2344. }
  2345. if (pdhStatus == ERROR_SUCCESS) {
  2346. pszPath = szEnglishBuf;
  2347. }
  2348. }
  2349. hr = AddCounter ( pszPath, &pItem );
  2350. // Return status of the first failed counter.
  2351. if ( FAILED ( hr ) && SMON_STATUS_DUPL_COUNTER_PATH != hr ) {
  2352. if ( S_OK == hrErr ) {
  2353. hrErr = hr;
  2354. }
  2355. }
  2356. } else {
  2357. hr = E_FAIL;
  2358. if ( S_OK == hrErr ) {
  2359. hrErr = E_FAIL;
  2360. }
  2361. }
  2362. if ( SUCCEEDED(hr) ) {
  2363. assert ( NULL != pItem );
  2364. if ( 0 == lstrcmpi ( pszPath, szSelected ) ) {
  2365. SelectCounter( pItem );
  2366. }
  2367. if ( SUCCEEDED(hr) ) {
  2368. assert ( NULL != pItem );
  2369. // Only pass sample count if all sample properties exist
  2370. // in the property bag.
  2371. hr = pItem->LoadFromPropertyBag (
  2372. pIPropBag,
  2373. pIErrorLog,
  2374. iIndex,
  2375. SMONCTRL_MAJ_VERSION,
  2376. SMONCTRL_MIN_VERSION,
  2377. m_bSampleDataLoaded ? iSampleCount : 0 );
  2378. }
  2379. } else {
  2380. if ( SMON_STATUS_DUPL_COUNTER_PATH != hr ) {
  2381. AddToErrorPathList ( pszPath );
  2382. }
  2383. }
  2384. }
  2385. if (szEnglishBuf != NULL) {
  2386. free(szEnglishBuf);
  2387. }
  2388. if ( NULL != pszCounterPath ) {
  2389. delete pszCounterPath;
  2390. }
  2391. if ( SMON_STATUS_DUPL_COUNTER_PATH != hr ) {
  2392. DWORD dwCounterListLen;
  2393. LPCWSTR szCounterList = NULL;
  2394. szCounterList = GetErrorPathList ( &dwCounterListLen );
  2395. if ( NULL != szCounterList ) {
  2396. TCHAR* pszMessage = NULL;
  2397. // Report error, but continue.
  2398. pszMessage = new WCHAR [dwCounterListLen + MAX_PATH];
  2399. if ( NULL != pszMessage ) {
  2400. _stprintf ( pszMessage, ResourceString(IDS_ADD_COUNTER_ERR), szCounterList );
  2401. MessageBox (
  2402. m_hWnd,
  2403. pszMessage,
  2404. ResourceString(IDS_APP_NAME),
  2405. MB_OK | MB_ICONEXCLAMATION);
  2406. delete pszMessage;
  2407. }
  2408. ClearErrorPathList();
  2409. }
  2410. }
  2411. return hrErr;
  2412. }
  2413. HRESULT
  2414. CSysmonControl::LoadFromPropertyBag (
  2415. IPropertyBag* pIPropBag,
  2416. IErrorLog* pIErrorLog )
  2417. {
  2418. HRESULT hr = S_OK;
  2419. GRAPH_OPTIONS *pOptions = &m_pObj->m_Graph.Options;
  2420. ISystemMonitor *pObj = m_pObj->m_pImpISystemMonitor;
  2421. INT iExtentX;
  2422. INT iExtentY;
  2423. INT intValue;
  2424. BOOL bValue;
  2425. FLOAT fValue;
  2426. OLE_COLOR clrValue;
  2427. INT iBufSize;
  2428. SMONCTRL_VERSION_DATA VersionData;
  2429. INT nLogType = SMON_CTRL_LOG;
  2430. if (g_dwScriptPolicy == URLPOLICY_DISALLOW) {
  2431. return E_ACCESSDENIED;
  2432. }
  2433. // Version info
  2434. VersionData.dwVersion = 0;
  2435. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszVersion, (INT&)VersionData.dwVersion );
  2436. assert ( SMONCTRL_MAJ_VERSION >= VersionData.iMajor );
  2437. m_LoadedVersion.dwVersion = VersionData.dwVersion;
  2438. hr = IntegerFromPropertyBag (pIPropBag, pIErrorLog, CGlobalString::m_cszLogType, nLogType);
  2439. if(SUCCEEDED(hr) && (nLogType == SLQ_TRACE_LOG)) {
  2440. // This is a WMI/WDM event trace log files, bail out immediately.
  2441. //
  2442. MessageBox(m_hWnd,
  2443. ResourceString(IDS_TRACE_LOG_ERR_MSG),
  2444. ResourceString(IDS_APP_NAME),
  2445. MB_OK);
  2446. return NOERROR;
  2447. }
  2448. // When loading properties, continue even if errors. On error, the value will
  2449. // remain default value.
  2450. // Extent data
  2451. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszExtentX, iExtentX );
  2452. if ( SUCCEEDED( hr ) ){
  2453. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszExtentY, iExtentY );
  2454. if ( SUCCEEDED( hr ) ) {
  2455. RECT RectExt;
  2456. SetRect(&RectExt, 0, 0, iExtentX, iExtentY);
  2457. m_pObj->RectConvertMappings(&RectExt, TRUE); // Convert from HIMETRIC
  2458. m_pObj->m_RectExt = RectExt;
  2459. }
  2460. }
  2461. // Options settings. Where possible, options are added through the vtable
  2462. // interface, for validation.
  2463. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszDisplayType, intValue );
  2464. if ( SUCCEEDED(hr) ) {
  2465. hr = pObj->put_DisplayType ( (eDisplayTypeConstant)intValue );
  2466. }
  2467. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszReportValueType, intValue );
  2468. if ( SUCCEEDED(hr) ) {
  2469. hr = pObj->put_ReportValueType ( (eReportValueTypeConstant)intValue );
  2470. }
  2471. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszMaximumScale, intValue );
  2472. if ( SUCCEEDED(hr) ) {
  2473. hr = pObj->put_MaximumScale ( intValue );
  2474. }
  2475. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszMinimumScale, intValue );
  2476. if ( SUCCEEDED(hr) ) {
  2477. hr = pObj->put_MinimumScale ( intValue );
  2478. }
  2479. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszAppearance, intValue );
  2480. if ( SUCCEEDED(hr) ) {
  2481. if ( NULL_COLOR == intValue ) {
  2482. pOptions->iAppearance = intValue;
  2483. } else {
  2484. hr = pObj->put_Appearance ( intValue );
  2485. }
  2486. }
  2487. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszBorderStyle, intValue );
  2488. if ( SUCCEEDED(hr) ) {
  2489. hr = pObj->put_BorderStyle ( intValue );
  2490. }
  2491. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszShowLegend, bValue );
  2492. if ( SUCCEEDED(hr) ) {
  2493. hr = pObj->put_ShowLegend ( (SHORT)bValue );
  2494. }
  2495. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszShowToolBar, bValue );
  2496. if ( SUCCEEDED(hr) ) {
  2497. hr = pObj->put_ShowToolbar ( (SHORT)bValue );
  2498. }
  2499. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszShowValueBar, bValue );
  2500. if ( SUCCEEDED(hr) ) {
  2501. hr = pObj->put_ShowValueBar ( (SHORT)bValue );
  2502. }
  2503. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszShowScaleLabels, bValue );
  2504. if ( SUCCEEDED(hr) ) {
  2505. hr = pObj->put_ShowScaleLabels ( (SHORT)bValue );
  2506. }
  2507. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszShowHorizontalGrid, bValue );
  2508. if ( SUCCEEDED(hr) ) {
  2509. hr = pObj->put_ShowHorizontalGrid ( (SHORT)bValue );
  2510. }
  2511. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszShowVerticalGrid, bValue );
  2512. if ( SUCCEEDED(hr) ) {
  2513. hr = pObj->put_ShowVerticalGrid ( (SHORT)bValue );
  2514. }
  2515. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszHighLight, bValue );
  2516. if ( SUCCEEDED(hr) ) {
  2517. hr = pObj->put_Highlight ( (SHORT)bValue );
  2518. }
  2519. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszManualUpdate, bValue );
  2520. if ( SUCCEEDED(hr) ) {
  2521. hr = pObj->put_ManualUpdate ( (SHORT)bValue );
  2522. }
  2523. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszReadOnly, bValue );
  2524. if ( SUCCEEDED(hr) ) {
  2525. hr = pObj->put_ReadOnly ( (SHORT)bValue );
  2526. }
  2527. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszMonitorDuplicateInstance, bValue );
  2528. if ( SUCCEEDED(hr) ) {
  2529. hr = pObj->put_MonitorDuplicateInstances ( (SHORT)bValue );
  2530. }
  2531. hr = FloatFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszUpdateInterval, fValue );
  2532. if ( SUCCEEDED(hr) ) {
  2533. hr = pObj->put_UpdateInterval ( fValue );
  2534. }
  2535. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszDisplayFilter, intValue );
  2536. if ( SUCCEEDED(hr) ) {
  2537. hr = pObj->put_DisplayFilter ( intValue );
  2538. }
  2539. hr = OleColorFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszBackColorCtl, clrValue );
  2540. if ( SUCCEEDED(hr) ) {
  2541. if ( NULL_COLOR == clrValue ) {
  2542. pOptions->clrBackCtl = clrValue;
  2543. } else {
  2544. hr = pObj->put_BackColorCtl ( clrValue );
  2545. }
  2546. }
  2547. hr = OleColorFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszBackColor, clrValue );
  2548. if ( SUCCEEDED(hr) ) {
  2549. if ( NULL_COLOR == clrValue ) {
  2550. pOptions->clrBackPlot = clrValue;
  2551. } else {
  2552. hr = pObj->put_BackColor ( clrValue );
  2553. }
  2554. }
  2555. hr = OleColorFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszForeColor, clrValue );
  2556. if ( SUCCEEDED(hr) ) {
  2557. if ( NULL_COLOR == clrValue ) {
  2558. pOptions->clrFore = clrValue;
  2559. } else {
  2560. hr = pObj->put_ForeColor ( clrValue );
  2561. }
  2562. }
  2563. hr = OleColorFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszGridColor, clrValue );
  2564. if ( SUCCEEDED(hr) ) {
  2565. hr = pObj->put_GridColor ( clrValue );
  2566. }
  2567. hr = OleColorFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszTimeBarColor, clrValue );
  2568. if ( SUCCEEDED(hr) ) {
  2569. hr = pObj->put_TimeBarColor ( clrValue );
  2570. }
  2571. // Titles
  2572. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszGraphTitle, NULL, iBufSize );
  2573. if ( SUCCEEDED(hr) &&
  2574. iBufSize > 0 ) {
  2575. pOptions->pszGraphTitle = new TCHAR[iBufSize];
  2576. if ( NULL != pOptions->pszGraphTitle ) {
  2577. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszGraphTitle, pOptions->pszGraphTitle, iBufSize );
  2578. }
  2579. }
  2580. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszYAxisLabel, NULL, iBufSize );
  2581. if ( SUCCEEDED(hr) &&
  2582. iBufSize > 0 ) {
  2583. pOptions->pszYaxisTitle = new TCHAR[iBufSize];
  2584. if ( NULL != pOptions->pszYaxisTitle ) {
  2585. hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszYAxisLabel, pOptions->pszYaxisTitle, iBufSize );
  2586. }
  2587. }
  2588. // SQL DSN and logset info
  2589. //
  2590. hr = StringFromPropertyBag(
  2591. pIPropBag, pIErrorLog, CGlobalString::m_cszSqlDsnName, NULL, iBufSize);
  2592. if (SUCCEEDED(hr) && iBufSize > 0) {
  2593. if (m_DataSourceInfo.szSqlDsnName) {
  2594. delete(m_DataSourceInfo.szSqlDsnName);
  2595. m_DataSourceInfo.szSqlDsnName = NULL;
  2596. }
  2597. m_DataSourceInfo.szSqlDsnName = new TCHAR[iBufSize + 1];
  2598. if (m_DataSourceInfo.szSqlDsnName) {
  2599. hr = StringFromPropertyBag(pIPropBag,
  2600. pIErrorLog,
  2601. CGlobalString::m_cszSqlDsnName,
  2602. m_DataSourceInfo.szSqlDsnName,
  2603. iBufSize);
  2604. }
  2605. if (SUCCEEDED(hr)) {
  2606. hr = StringFromPropertyBag(
  2607. pIPropBag, pIErrorLog, CGlobalString::m_cszSqlLogSetName, NULL, iBufSize);
  2608. if (SUCCEEDED(hr) && iBufSize > 0) {
  2609. if (m_DataSourceInfo.szSqlLogSetName) {
  2610. delete(m_DataSourceInfo.szSqlLogSetName);
  2611. m_DataSourceInfo.szSqlLogSetName = NULL;
  2612. }
  2613. m_DataSourceInfo.szSqlLogSetName = new TCHAR[iBufSize + 1];
  2614. if (m_DataSourceInfo.szSqlLogSetName) {
  2615. hr = StringFromPropertyBag(pIPropBag,
  2616. pIErrorLog,
  2617. CGlobalString::m_cszSqlLogSetName,
  2618. m_DataSourceInfo.szSqlLogSetName,
  2619. iBufSize);
  2620. }
  2621. }
  2622. }
  2623. if (SUCCEEDED(hr)) {
  2624. hr = LLTimeFromPropertyBag(pIPropBag,
  2625. pIErrorLog,
  2626. CGlobalString::m_cszLogViewStart,
  2627. m_DataSourceInfo.llStartDisp);
  2628. }
  2629. if (SUCCEEDED(hr)) {
  2630. hr = LLTimeFromPropertyBag(pIPropBag,
  2631. pIErrorLog,
  2632. CGlobalString::m_cszLogViewStop,
  2633. m_DataSourceInfo.llStopDisp);
  2634. }
  2635. }
  2636. // Log file info
  2637. hr = LoadLogFilesFromPropertyBag ( pIPropBag, pIErrorLog );
  2638. // Must put log file name after display range, before adding counters.
  2639. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszDataSourceType, intValue );
  2640. if (FAILED (hr)) {
  2641. // If DataSourceType flag is missing, set data source type based on
  2642. // presence of log files.
  2643. if (NumLogFiles() > 0) {
  2644. intValue = sysmonLogFiles;
  2645. }
  2646. else if ( m_DataSourceInfo.szSqlDsnName && m_DataSourceInfo.szSqlLogSetName ) {
  2647. if ( m_DataSourceInfo.szSqlDsnName[0] != _T('\0') && m_DataSourceInfo.szSqlLogSetName[0] != _T('\0')) {
  2648. intValue = sysmonSqlLog;
  2649. }
  2650. }
  2651. else {
  2652. intValue = sysmonCurrentActivity;
  2653. }
  2654. }
  2655. // Load log view start and stop times if the data source is not realtime.
  2656. if ( sysmonSqlLog == intValue || sysmonLogFiles == intValue ) {
  2657. hr = LLTimeFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszLogViewStart, m_DataSourceInfo.llStartDisp );
  2658. hr = LLTimeFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszLogViewStop, m_DataSourceInfo.llStopDisp );
  2659. }
  2660. hr = pObj->put_DataSourceType ( (eDataSourceTypeConstant)intValue );
  2661. if( FAILED(hr) ) {
  2662. if ( SMON_STATUS_LOG_FILE_SIZE_LIMIT == hr ) {
  2663. // TodoLogFiles: Check log file type. Only perfmon and circular
  2664. // binary logs are still limited to 1 GB.
  2665. // TodoLogFiles: Current query is already closed,
  2666. // so what can be done here?
  2667. } else {
  2668. DWORD dwStatus;
  2669. LPWSTR szLogFileList = NULL;
  2670. ULONG ulLogListBufLen= 0;
  2671. if ( sysmonLogFiles == intValue ) {
  2672. dwStatus = BuildLogFileList (
  2673. NULL,
  2674. TRUE,
  2675. &ulLogListBufLen );
  2676. szLogFileList = (LPWSTR) malloc(ulLogListBufLen * sizeof(WCHAR));
  2677. if ( NULL != szLogFileList ) {
  2678. dwStatus = BuildLogFileList (
  2679. szLogFileList,
  2680. TRUE,
  2681. &ulLogListBufLen );
  2682. }
  2683. }
  2684. dwStatus = DisplayDataSourceError (
  2685. m_hWnd,
  2686. (DWORD)hr,
  2687. intValue,
  2688. szLogFileList,
  2689. m_DataSourceInfo.szSqlDsnName,
  2690. m_DataSourceInfo.szSqlLogSetName );
  2691. if ( NULL != szLogFileList ) {
  2692. delete szLogFileList;
  2693. szLogFileList = NULL;
  2694. }
  2695. }
  2696. }
  2697. // Font info
  2698. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszAmbientFont, bValue );
  2699. if (SUCCEEDED(hr)) {
  2700. pOptions->bAmbientFont = bValue;
  2701. }
  2702. // Load property bag values if they exist, overriding any specified aspect of ambient font.
  2703. hr = m_OleFont.LoadFromPropertyBag ( pIPropBag, pIErrorLog );
  2704. // Legend
  2705. hr = m_pLegend->LoadFromPropertyBag ( pIPropBag, pIErrorLog );
  2706. // Counters
  2707. m_bLoadingCounters = TRUE;
  2708. hr = LoadCountersFromPropertyBag ( pIPropBag, pIErrorLog, TRUE );
  2709. m_bLoadingCounters = FALSE;
  2710. // Load the Visuals after loading all counters.
  2711. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszNextCounterColor, intValue );
  2712. if ( SUCCEEDED(hr) && ( intValue < NumStandardColorIndices() ) ) {
  2713. m_iColorIndex = intValue;
  2714. }
  2715. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszNextCounterWidth, intValue );
  2716. if ( SUCCEEDED(hr) && ( intValue < NumWidthIndices() ) ) {
  2717. m_iWidthIndex = intValue;
  2718. }
  2719. hr = IntegerFromPropertyBag ( pIPropBag, pIErrorLog, CGlobalString::m_cszNextCounterLineStyle, intValue );
  2720. if ( SUCCEEDED(hr) && ( intValue < NumStyleIndices() ) ) {
  2721. m_iStyleIndex = intValue;
  2722. }
  2723. return NOERROR;
  2724. }
  2725. HRESULT
  2726. CSysmonControl::SaveToPropertyBag (
  2727. IPropertyBag* pIPropBag,
  2728. BOOL fSaveAllProps )
  2729. {
  2730. HRESULT hr = NOERROR;
  2731. GRAPH_OPTIONS *pOptions = &m_pObj->m_Graph.Options;
  2732. PCMachineNode pMachine;
  2733. PCObjectNode pObject;
  2734. PCInstanceNode pInstance;
  2735. PCGraphItem pItem;
  2736. PCLogFileItem pLogFile = NULL;
  2737. INT iCounterIndex = 0;
  2738. INT iLogFileIndex = 0;
  2739. RECT RectExt;
  2740. SMONCTRL_VERSION_DATA VersionData;
  2741. WCHAR szLogFileName[16];
  2742. LPTSTR szEnglishBuf = NULL;
  2743. DWORD dwEnglishBufSize = 0;
  2744. LPTSTR pszPath = NULL;
  2745. PDH_STATUS pdhStatus;
  2746. // Version info
  2747. VersionData.iMajor = SMONCTRL_MAJ_VERSION;
  2748. VersionData.iMinor = SMONCTRL_MIN_VERSION;
  2749. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszVersion, VersionData.dwVersion );
  2750. // Extent data in HIMETRIC format
  2751. if ( SUCCEEDED( hr ) ){
  2752. RectExt = m_pObj->m_RectExt;
  2753. m_pObj->RectConvertMappings(&RectExt, FALSE);
  2754. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszExtentX, RectExt.right - RectExt.left );
  2755. if ( SUCCEEDED( hr ) ){
  2756. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszExtentY, RectExt.bottom - RectExt.top );
  2757. }
  2758. }
  2759. // Options settings
  2760. if ( SUCCEEDED( hr ) ){
  2761. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszDisplayType, pOptions->iDisplayType );
  2762. }
  2763. if ( SUCCEEDED( hr ) ){
  2764. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszReportValueType, pOptions->iReportValueType );
  2765. }
  2766. if ( SUCCEEDED( hr ) ){
  2767. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszMaximumScale, pOptions->iVertMax );
  2768. }
  2769. if ( SUCCEEDED( hr ) ){
  2770. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszMinimumScale, pOptions->iVertMin );
  2771. }
  2772. if ( SUCCEEDED( hr ) ){
  2773. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszShowLegend, pOptions->bLegendChecked );
  2774. }
  2775. if ( SUCCEEDED( hr ) ){
  2776. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszShowToolBar, pOptions->bToolbarChecked );
  2777. }
  2778. if ( SUCCEEDED( hr ) ){
  2779. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszShowScaleLabels, pOptions->bLabelsChecked );
  2780. }
  2781. if ( SUCCEEDED( hr ) ){
  2782. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszShowHorizontalGrid, pOptions->bHorzGridChecked );
  2783. }
  2784. if ( SUCCEEDED( hr ) ){
  2785. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszShowVerticalGrid, pOptions->bVertGridChecked );
  2786. }
  2787. if ( SUCCEEDED( hr ) ){
  2788. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszShowValueBar, pOptions->bValueBarChecked );
  2789. }
  2790. if ( SUCCEEDED( hr ) ){
  2791. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszManualUpdate, pOptions->bManualUpdate );
  2792. }
  2793. if ( SUCCEEDED( hr ) ){
  2794. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszHighLight, pOptions->bHighlight );
  2795. }
  2796. if ( SUCCEEDED( hr ) ){
  2797. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszReadOnly, pOptions->bReadOnly );
  2798. }
  2799. if ( SUCCEEDED( hr ) ){
  2800. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszMonitorDuplicateInstance, pOptions->bMonitorDuplicateInstances );
  2801. }
  2802. if ( SUCCEEDED( hr ) ){
  2803. hr = FloatToPropertyBag ( pIPropBag, CGlobalString::m_cszUpdateInterval, pOptions->fUpdateInterval );
  2804. }
  2805. if ( SUCCEEDED( hr ) ){
  2806. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszDisplayFilter, pOptions->iDisplayFilter );
  2807. }
  2808. if ( SUCCEEDED( hr ) ){
  2809. hr = OleColorToPropertyBag ( pIPropBag, CGlobalString::m_cszBackColorCtl, pOptions->clrBackCtl );
  2810. }
  2811. if ( SUCCEEDED( hr ) ){
  2812. hr = OleColorToPropertyBag ( pIPropBag, CGlobalString::m_cszForeColor, pOptions->clrFore );
  2813. }
  2814. if ( SUCCEEDED( hr ) ){
  2815. hr = OleColorToPropertyBag ( pIPropBag, CGlobalString::m_cszBackColor, pOptions->clrBackPlot );
  2816. }
  2817. if ( SUCCEEDED( hr ) ){
  2818. hr = OleColorToPropertyBag ( pIPropBag, CGlobalString::m_cszGridColor, pOptions->clrGrid );
  2819. }
  2820. if ( SUCCEEDED( hr ) ){
  2821. hr = OleColorToPropertyBag ( pIPropBag, CGlobalString::m_cszTimeBarColor, pOptions->clrTimeBar );
  2822. }
  2823. if ( SUCCEEDED( hr ) ){
  2824. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszAppearance, pOptions->iAppearance );
  2825. }
  2826. if ( SUCCEEDED( hr ) ){
  2827. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszBorderStyle, pOptions->iBorderStyle );
  2828. }
  2829. // Visuals are stored directly in the control. Move to pOptions if made part
  2830. // of the programming interface.
  2831. if ( SUCCEEDED( hr ) ){
  2832. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszNextCounterColor, m_iColorIndex );
  2833. }
  2834. if ( SUCCEEDED( hr ) ){
  2835. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszNextCounterWidth, m_iWidthIndex );
  2836. }
  2837. if ( SUCCEEDED( hr ) ){
  2838. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszNextCounterLineStyle, m_iStyleIndex );
  2839. }
  2840. // Titles
  2841. if ( SUCCEEDED( hr ) ){
  2842. hr = StringToPropertyBag ( pIPropBag, CGlobalString::m_cszGraphTitle, pOptions->pszGraphTitle );
  2843. }
  2844. if ( SUCCEEDED( hr ) ){
  2845. hr = StringToPropertyBag ( pIPropBag, CGlobalString::m_cszYAxisLabel, pOptions->pszYaxisTitle );
  2846. }
  2847. // Data source info
  2848. if ( SUCCEEDED( hr ) ){
  2849. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszDataSourceType, pOptions->iDataSourceType );
  2850. }
  2851. if ( SUCCEEDED( hr ) &&
  2852. ( sysmonLogFiles == pOptions->iDataSourceType
  2853. || sysmonSqlLog == pOptions->iDataSourceType ) )
  2854. {
  2855. hr = LLTimeToPropertyBag ( pIPropBag, CGlobalString::m_cszLogViewStart, m_DataSourceInfo.llStartDisp );
  2856. if ( SUCCEEDED( hr ) ){
  2857. hr = LLTimeToPropertyBag ( pIPropBag, CGlobalString::m_cszLogViewStop, m_DataSourceInfo.llStopDisp );
  2858. }
  2859. }
  2860. // SQL data source
  2861. if (SUCCEEDED(hr)) {
  2862. hr = StringToPropertyBag(pIPropBag,
  2863. CGlobalString::m_cszSqlDsnName,
  2864. m_DataSourceInfo.szSqlDsnName);
  2865. }
  2866. if (SUCCEEDED(hr)) {
  2867. hr = StringToPropertyBag(pIPropBag,
  2868. CGlobalString::m_cszSqlLogSetName,
  2869. m_DataSourceInfo.szSqlLogSetName);
  2870. }
  2871. // Log files
  2872. if ( SUCCEEDED( hr ) ){
  2873. iLogFileIndex = 0;
  2874. for (
  2875. pLogFile = FirstLogFile();
  2876. NULL != pLogFile;
  2877. pLogFile = pLogFile->Next() )
  2878. {
  2879. swprintf ( szLogFileName, CGlobalString::m_cszLogNameFormat, CGlobalString::m_cszLogFileName, ++iLogFileIndex );
  2880. hr = StringToPropertyBag ( pIPropBag, szLogFileName, pLogFile->GetPath() );
  2881. }
  2882. if ( SUCCEEDED( hr ) ){
  2883. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszLogFileCount, iLogFileIndex );
  2884. }
  2885. }
  2886. // Font info
  2887. if ( SUCCEEDED( hr ) ){
  2888. hr = BOOLToPropertyBag ( pIPropBag, CGlobalString::m_cszAmbientFont, pOptions->bAmbientFont );
  2889. if ( FAILED( hr ) || !pOptions->bAmbientFont ){
  2890. hr = m_OleFont.SaveToPropertyBag ( pIPropBag, TRUE, fSaveAllProps );
  2891. }
  2892. }
  2893. // Legend
  2894. if ( SUCCEEDED( hr ) ){
  2895. hr = m_pLegend->SaveToPropertyBag ( pIPropBag, TRUE, fSaveAllProps );
  2896. }
  2897. // Save counter count and sample data
  2898. LockCounterData();
  2899. if ( SUCCEEDED( hr ) ){
  2900. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszCounterCount, CounterTree()->NumCounters() );
  2901. }
  2902. if ( SUCCEEDED(hr) ) {
  2903. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszMaximumSamples, m_pHistCtrl->nMaxSamples );
  2904. }
  2905. if ( SUCCEEDED(hr) ) {
  2906. INT iSampleCount;
  2907. if ( !m_fUserMode ) {
  2908. iSampleCount = 0;
  2909. #if !_LOG_INCLUDE_DATA
  2910. } else if ( m_bLogFileSource ) {
  2911. iSampleCount = 0;
  2912. #endif
  2913. } else {
  2914. iSampleCount = m_pHistCtrl->nSamples;
  2915. }
  2916. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszSampleCount, iSampleCount );
  2917. if ( SUCCEEDED(hr) && ( 0 < iSampleCount )) {
  2918. #if _LOG_INCLUDE_DATA
  2919. INT iTemp;
  2920. iTemp = ( 0 < m_pHistCtrl->iCurrent ? m_pHistCtrl->iCurrent : 1 );
  2921. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszSampleIndex, iTemp );
  2922. if ( SUCCEEDED(hr) ) {
  2923. iTemp = ( 0 < m_pObj->m_Graph.TimeStepper.StepNum() ? m_pObj->m_Graph.TimeStepper.StepNum() : 1 );
  2924. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszStepNumber, iTemp );
  2925. }
  2926. #else
  2927. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszSampleIndex, m_pHistCtrl->iCurrent );
  2928. if ( SUCCEEDED(hr) ) {
  2929. hr = IntegerToPropertyBag ( pIPropBag, CGlobalString::m_cszStepNumber, m_pObj->m_Graph.TimeStepper.StepNum() );
  2930. }
  2931. #endif
  2932. }
  2933. }
  2934. for ( pMachine = CounterTree()->FirstMachine();
  2935. pMachine;
  2936. pMachine = pMachine->Next()) {
  2937. for ( pObject = pMachine->FirstObject();
  2938. pObject;
  2939. pObject = pObject->Next()) {
  2940. for ( pInstance = pObject->FirstInstance();
  2941. pInstance;
  2942. pInstance = pInstance->Next()) {
  2943. for ( pItem = pInstance->FirstItem();
  2944. pItem;
  2945. pItem = pItem->m_pNextItem) {
  2946. // Save all counters explicitly, even if wildcard
  2947. iCounterIndex++;
  2948. hr = pItem->SaveToPropertyBag (
  2949. pIPropBag,
  2950. iCounterIndex,
  2951. m_fUserMode,
  2952. SMONCTRL_MAJ_VERSION,
  2953. SMONCTRL_MIN_VERSION);
  2954. if (FAILED(hr))
  2955. return hr;
  2956. }
  2957. }
  2958. }
  2959. }
  2960. assert ( iCounterIndex == CounterTree()->NumCounters() );
  2961. // Selection
  2962. if ( NULL != m_pSelectedItem ) {
  2963. VARIANT vValue;
  2964. DWORD dwBufSize;
  2965. LPTSTR pNewBuf;
  2966. VariantInit( &vValue );
  2967. vValue.vt = VT_BSTR;
  2968. // get this counter path
  2969. hr = m_pSelectedItem->get_Path( &vValue.bstrVal );
  2970. if( SUCCEEDED(hr) ){
  2971. pszPath = vValue.bstrVal;
  2972. //
  2973. // Initialize the locale path buffer
  2974. //
  2975. if (dwEnglishBufSize == 0) {
  2976. dwEnglishBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  2977. szEnglishBuf = (LPTSTR) malloc(dwEnglishBufSize);
  2978. if (szEnglishBuf == NULL) {
  2979. dwEnglishBufSize = 0;
  2980. }
  2981. }
  2982. if (szEnglishBuf != NULL) {
  2983. //
  2984. // Translate counter name from Localization into English
  2985. //
  2986. dwBufSize = dwEnglishBufSize;
  2987. pdhStatus = PdhTranslate009Counter(
  2988. vValue.bstrVal,
  2989. szEnglishBuf,
  2990. &dwBufSize);
  2991. if (pdhStatus == PDH_MORE_DATA) {
  2992. pNewBuf = (LPTSTR)realloc(szEnglishBuf, dwBufSize);
  2993. if (pNewBuf != NULL) {
  2994. szEnglishBuf = pNewBuf;
  2995. dwEnglishBufSize = dwBufSize;
  2996. pdhStatus = PdhTranslate009Counter(
  2997. vValue.bstrVal,
  2998. szEnglishBuf,
  2999. &dwBufSize);
  3000. }
  3001. }
  3002. if (pdhStatus == ERROR_SUCCESS) {
  3003. pszPath = szEnglishBuf;
  3004. }
  3005. }
  3006. if( SUCCEEDED(hr) ) {
  3007. VariantClear( &vValue );
  3008. vValue.bstrVal = SysAllocString( pszPath );
  3009. if( vValue.bstrVal != NULL ){
  3010. vValue.vt = VT_BSTR;
  3011. }
  3012. }else{
  3013. //translation failed, write current value
  3014. hr = ERROR_SUCCESS;
  3015. }
  3016. }
  3017. if ( SUCCEEDED ( hr ) ) {
  3018. hr = pIPropBag->Write(CGlobalString::m_cszSelected, &vValue );
  3019. VariantClear ( &vValue );
  3020. }
  3021. }
  3022. if (szEnglishBuf != NULL) {
  3023. free(szEnglishBuf);
  3024. }
  3025. UnlockCounterData();
  3026. return hr;
  3027. }
  3028. DWORD
  3029. CSysmonControl::InitializeQuery (
  3030. void )
  3031. {
  3032. DWORD dwStat = ERROR_SUCCESS;
  3033. PCGraphItem pItem;
  3034. // Query must be opened before this method is called.
  3035. if ( NULL != m_hQuery ) {
  3036. m_pHistCtrl->nMaxSamples = MAX_GRAPH_SAMPLES;
  3037. m_pHistCtrl->iCurrent = 0;
  3038. m_pHistCtrl->nSamples = 0;
  3039. m_pHistCtrl->nBacklog = 0;
  3040. m_pObj->m_Graph.TimeStepper.Reset();
  3041. m_pObj->m_Graph.LogViewStartStepper.Reset();
  3042. m_pObj->m_Graph.LogViewStopStepper.Reset();
  3043. m_pHistCtrl->bLogSource = m_bLogFileSource;
  3044. } else {
  3045. dwStat = PDH_INVALID_HANDLE;
  3046. }
  3047. if ( ERROR_SUCCESS == dwStat ) {
  3048. // Add counters to the query, to initialize scale factors
  3049. if ((pItem = FirstCounter()) != NULL) {
  3050. while (pItem != NULL) {
  3051. pItem->AddToQuery(m_hQuery);
  3052. pItem = pItem->Next();
  3053. }
  3054. }
  3055. }
  3056. return dwStat;
  3057. }
  3058. DWORD
  3059. CSysmonControl::ActivateQuery (
  3060. void )
  3061. {
  3062. DWORD dwStat = ERROR_SUCCESS;
  3063. DWORD dwThreadID;
  3064. // if real-time source
  3065. if (!IsLogSource()
  3066. && m_fInitialized
  3067. && IsUserMode() ) {
  3068. if ( NULL == m_CollectInfo.hEvent ) {
  3069. // Create a collection event
  3070. if ((m_CollectInfo.hEvent = CreateEvent(NULL, FALSE, 0, NULL)) == NULL) {
  3071. dwStat = GetLastError();
  3072. } else
  3073. // Create the collection thread
  3074. if ( ( m_CollectInfo.hThread
  3075. = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CollectProc, this, 0, &dwThreadID)) == NULL) {
  3076. dwStat = GetLastError();
  3077. }
  3078. if ( ERROR_SUCCESS == dwStat ) {
  3079. SetThreadPriority ( m_CollectInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL );
  3080. }
  3081. }
  3082. if ( ERROR_SUCCESS == dwStat ) {
  3083. // Start the data collection
  3084. if ( FirstCounter() != NULL) {
  3085. SetIntervalTimer();
  3086. }
  3087. }
  3088. }
  3089. if ( ERROR_SUCCESS != dwStat ) {
  3090. // If failure, close query to clean up then exit
  3091. CloseQuery();
  3092. }
  3093. return dwStat;
  3094. }
  3095. void
  3096. CSysmonControl::CloseQuery (
  3097. void )
  3098. {
  3099. PCGraphItem pItem;
  3100. // Terminate the collection thread
  3101. if ( NULL != m_CollectInfo.hThread ) {
  3102. m_CollectInfo.iMode = COLLECT_QUIT;
  3103. SetEvent(m_CollectInfo.hEvent);
  3104. WaitForSingleObject(m_CollectInfo.hThread, INFINITE);
  3105. CloseHandle(m_CollectInfo.hThread);
  3106. m_CollectInfo.hThread = NULL;
  3107. }
  3108. // Release the collection event
  3109. if ( NULL != m_CollectInfo.hEvent ) {
  3110. CloseHandle(m_CollectInfo.hEvent);
  3111. m_CollectInfo.hEvent = NULL;
  3112. }
  3113. LockCounterData();
  3114. // Remove counters from the query
  3115. pItem = FirstCounter();
  3116. while ( NULL != pItem ) {
  3117. pItem->RemoveFromQuery();
  3118. pItem = pItem->Next();
  3119. }
  3120. UnlockCounterData();
  3121. // Delete the query
  3122. if ( NULL != m_hQuery ) {
  3123. PdhCloseQuery ( m_hQuery );
  3124. if ( (m_DataSourceInfo.hDataSource != H_REALTIME_DATASOURCE)
  3125. && (m_DataSourceInfo.hDataSource != H_WBEM_DATASOURCE)) {
  3126. PdhCloseLog(m_DataSourceInfo.hDataSource, 0);
  3127. m_DataSourceInfo.hDataSource = H_REALTIME_DATASOURCE;
  3128. }
  3129. m_hQuery = NULL;
  3130. }
  3131. }
  3132. void CSysmonControl::SizeComponents ( HDC hDC )
  3133. /*
  3134. Effect: Move and show the various components of the graph to
  3135. fill the size (xWidth x yHeight). Take into account
  3136. whether the user wants to show the legend or status
  3137. bars. Also take into account if we have room for these
  3138. items.
  3139. Internals: If the user doesn't want the status or legend windows,
  3140. they aren't shown. Also, if the user wanted the status
  3141. window but not the legend window, the status window is
  3142. not shown.
  3143. We may disregard the user's desire for the legend or
  3144. status bar if there is not room. In particular, a legend
  3145. window has a minimum width (LegendMinWidth ()) and a
  3146. minimum height (LegendMinHeight ()). These values are
  3147. fixed for a given session of perfmon. It also has a
  3148. preferred height, which takes into consideration the
  3149. size of the graph window and the number of items in
  3150. the legend. This value is returned by LegendHeight().
  3151. We don't show the legend if its minimum height would
  3152. take up more than half the graph height.
  3153. If we feel we don't have room for the legend, we don't
  3154. show the status window either.
  3155. See Also: LegendMinWidth, LegendMinHeight, LegendHeight,
  3156. ValuebarHeight.
  3157. Called By: OnSize, any other function that may remove or add one
  3158. of the graph components.
  3159. */
  3160. {
  3161. RECT rectClient;
  3162. RECT rectComponent;
  3163. RECT rectToolbar;
  3164. INT xWidth;
  3165. INT yHeight;
  3166. INT yGraphHeight = 0;
  3167. INT ySnapHeight = 0;
  3168. INT yStatsHeight = 0;
  3169. INT yLegendHeight = 0;
  3170. INT yToolbarHeight = 0;
  3171. #define CTRL_BORDER 10
  3172. // If not inited, there's noting to size
  3173. if (!m_fViewInitialized)
  3174. return;
  3175. // Get dimensions of window
  3176. // GetClientRect (m_hWnd, &rectClient) ;
  3177. // *** - Use extent. It is the 'natural' size of the control.
  3178. // This draws the control correctly when zoom = 100%
  3179. // It also makes print size correct at all zoom levels.
  3180. SetCurrentClientRect ( GetNewClientRect() );
  3181. rectClient = *GetCurrentClientRect();
  3182. switch (m_pObj->m_Graph.Options.iDisplayType) {
  3183. case REPORT_GRAPH:
  3184. // Toolbar
  3185. // Toolbar not available through IViewObect, so leave it out.
  3186. if (m_pObj->m_Graph.Options.bToolbarChecked
  3187. && m_fViewInitialized ) {
  3188. rectToolbar = rectClient;
  3189. // Determine height of toolbar after sizing it, to handle Wrap.
  3190. m_pToolbar->SizeComponents(&rectToolbar);
  3191. yToolbarHeight = m_pToolbar->Height();
  3192. } else {
  3193. memset (&rectToolbar, 0, sizeof(RECT));
  3194. yToolbarHeight = 0;
  3195. }
  3196. if (yToolbarHeight > 0) {
  3197. rectClient.top += yToolbarHeight;
  3198. rectToolbar.bottom = rectToolbar.top + yToolbarHeight;
  3199. }
  3200. // Give report the entire client area except for toolbar
  3201. m_pReport->SizeComponents(&rectClient);
  3202. // Hide the other view components
  3203. SetRect(&rectClient,0,0,0,0);
  3204. m_pGraphDisp->SizeComponents(hDC, &rectClient);
  3205. m_pSnapBar->SizeComponents(&rectClient);
  3206. m_pStatsBar->SizeComponents(&rectClient);
  3207. m_pLegend->SizeComponents(&rectClient);
  3208. break;
  3209. case LINE_GRAPH:
  3210. case BAR_GRAPH:
  3211. // Subtract border area
  3212. rectComponent = rectClient;
  3213. InflateRect(&rectComponent, -CTRL_BORDER, -CTRL_BORDER);
  3214. xWidth = rectComponent.right - rectComponent.left ;
  3215. yHeight = rectComponent.bottom - rectComponent.top ;
  3216. // if the window has no area, forget it
  3217. if (xWidth == 0 || yHeight == 0)
  3218. return ;
  3219. // Reserve top fourth of window for graph
  3220. yGraphHeight = yHeight / 4;
  3221. yHeight -= yGraphHeight;
  3222. // Allocate space to each enabled component
  3223. // Toolbar
  3224. if (m_pObj->m_Graph.Options.bToolbarChecked
  3225. && m_fViewInitialized ) {
  3226. rectToolbar = rectComponent;
  3227. m_pToolbar->SizeComponents(&rectToolbar);
  3228. yToolbarHeight = m_pToolbar->Height();
  3229. } else {
  3230. memset (&rectToolbar, 0, sizeof(RECT));
  3231. yToolbarHeight = 0;
  3232. }
  3233. if (yToolbarHeight > 0) {
  3234. yHeight -= yToolbarHeight;
  3235. rectToolbar.bottom = rectToolbar.top + yToolbarHeight;
  3236. rectComponent.top += yToolbarHeight;
  3237. }
  3238. // Legend (Start with minimum size)
  3239. if (m_pObj->m_Graph.Options.bLegendChecked) {
  3240. yLegendHeight = m_pLegend->MinHeight(yHeight - CTRL_BORDER);
  3241. if (yLegendHeight > 0)
  3242. yHeight -= yLegendHeight + CTRL_BORDER;
  3243. }
  3244. // Statistics bar
  3245. if (m_pObj->m_Graph.Options.bValueBarChecked) {
  3246. yStatsHeight = m_pStatsBar->Height(yHeight - CTRL_BORDER, xWidth);
  3247. if (yStatsHeight > 0)
  3248. yHeight -= yStatsHeight + CTRL_BORDER;
  3249. }
  3250. // Snap bar
  3251. // only if tool bar is not displayed
  3252. if ((m_pObj->m_Graph.Options.bManualUpdate) &&
  3253. (!m_pObj->m_Graph.Options.bToolbarChecked)) {
  3254. ySnapHeight = m_pSnapBar->Height(yHeight - CTRL_BORDER);
  3255. if (ySnapHeight > 0)
  3256. yHeight -= ySnapHeight + CTRL_BORDER;
  3257. }
  3258. // If legend is visible give it a chance to use remaining space
  3259. // Rest goes to graph
  3260. if (yLegendHeight != 0) {
  3261. yHeight += yLegendHeight;
  3262. yLegendHeight = m_pLegend->Height(yHeight);
  3263. yGraphHeight += yHeight - yLegendHeight;
  3264. }
  3265. else
  3266. yGraphHeight += yHeight;
  3267. // Assign rectangle to each component
  3268. // Toolbar assigned earlier, to handle wrap.
  3269. // Graph display
  3270. rectComponent.bottom = rectComponent.top + yGraphHeight;
  3271. m_pGraphDisp->SizeComponents(hDC, &rectComponent);
  3272. rectComponent.top += yGraphHeight + CTRL_BORDER;
  3273. // Snap bar
  3274. rectComponent.bottom = rectComponent.top + ySnapHeight;
  3275. m_pSnapBar->SizeComponents(&rectComponent);
  3276. if (ySnapHeight != 0)
  3277. rectComponent.top += ySnapHeight + CTRL_BORDER;
  3278. // Statistics bar
  3279. rectComponent.bottom = rectComponent.top + yStatsHeight;
  3280. m_pStatsBar->SizeComponents(&rectComponent);
  3281. if (yStatsHeight != 0)
  3282. rectComponent.top += yStatsHeight + CTRL_BORDER;
  3283. // Legend window
  3284. rectComponent.bottom = rectComponent.top + yLegendHeight;
  3285. m_pLegend->SizeComponents(&rectComponent);
  3286. rectComponent.top += yLegendHeight;
  3287. // Force redraw of window
  3288. // Optimize: SizeComponents only called within Paint or Render,
  3289. // so remove this extra window invalidation.
  3290. WindowInvalidate(m_hWnd);
  3291. // Hide report window
  3292. SetRect(&rectClient,0,0,0,0);
  3293. m_pReport->SizeComponents(&rectComponent);
  3294. break;
  3295. }
  3296. }
  3297. void CSysmonControl::put_Highlight(BOOL bState)
  3298. {
  3299. // If no change, just return
  3300. if ( m_pObj->m_Graph.Options.bHighlight == bState )
  3301. return;
  3302. m_pObj->m_Graph.Options.bHighlight = bState;
  3303. // if no selected item, state doesn't matter
  3304. if (m_pSelectedItem == NULL)
  3305. return;
  3306. // Update graph display's highlighted item
  3307. if ( m_pObj->m_Graph.Options.bHighlight )
  3308. m_pGraphDisp->HiliteItem(m_pSelectedItem);
  3309. else
  3310. m_pGraphDisp->HiliteItem(NULL);
  3311. // Cause redraw
  3312. UpdateGraph(UPDGRPH_PLOT);
  3313. }
  3314. void
  3315. CSysmonControl::put_ManualUpdate(BOOL bManual)
  3316. {
  3317. m_pObj->m_Graph.Options.bManualUpdate = bManual;
  3318. if ( m_bSampleDataLoaded ) {
  3319. UpdateCounterValues(FALSE);
  3320. } else {
  3321. SetIntervalTimer();
  3322. UpdateGraph(UPDGRPH_LAYOUT);
  3323. }
  3324. }
  3325. VOID CSysmonControl::AssignFocus (
  3326. VOID
  3327. )
  3328. {
  3329. if (m_pObj->m_Graph.Options.iDisplayType == REPORT_GRAPH)
  3330. SetFocus(m_pReport->Window());
  3331. else
  3332. SetFocus(m_pLegend->Window());
  3333. }
  3334. HRESULT CSysmonControl::TranslateAccelerators( LPMSG pMsg )
  3335. {
  3336. INT iStat;
  3337. if (m_hWnd == NULL || m_hAccel == NULL)
  3338. return S_FALSE;
  3339. // If this is a cursor key down event, process it here, or the container may grab it first
  3340. // I need to be sure that it reaches the legend listbox
  3341. if (pMsg->message == WM_KEYDOWN &&
  3342. ( pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN ||
  3343. pMsg->wParam == VK_HOME || pMsg->wParam == VK_END ) ) {
  3344. ::TranslateMessage(pMsg);
  3345. ::DispatchMessage(pMsg);
  3346. return S_OK;
  3347. }
  3348. iStat = ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg);
  3349. return iStat ? S_OK : S_FALSE;
  3350. }
  3351. //==========================================================================//
  3352. // Message Handlers //
  3353. //==========================================================================//
  3354. BOOL
  3355. CSysmonControl::DisplayHelp ( HWND hwndSelf )
  3356. {
  3357. const INT ciBufCharCount = 2*MAX_PATH + 1;
  3358. TCHAR pszHelpFilePath[ciBufCharCount];
  3359. UINT nLen;
  3360. INT iCharCount;
  3361. if ( NULL != hwndSelf ) {
  3362. nLen = ::GetWindowsDirectory(pszHelpFilePath, ciBufCharCount );
  3363. if ( nLen == 0 ) {
  3364. // Report error.
  3365. }
  3366. iCharCount = (ciBufCharCount - nLen);
  3367. iCharCount = min ( iCharCount, lstrlen(L"\\help\\sysmon.chm") + 1 );
  3368. lstrcpyn(&pszHelpFilePath[nLen], L"\\help\\sysmon.chm", iCharCount );
  3369. HtmlHelp ( hwndSelf, pszHelpFilePath, HH_DISPLAY_TOPIC, 0 );
  3370. }
  3371. return TRUE;
  3372. }
  3373. LRESULT APIENTRY SysmonCtrlWndProc (HWND hWnd,
  3374. UINT uiMsg,
  3375. WPARAM wParam,
  3376. LPARAM lParam)
  3377. {
  3378. RECT rect;
  3379. PSYSMONCTRL pCtrl = (PSYSMONCTRL)GetWindowLongPtr(hWnd ,0);
  3380. INT iUpdate;
  3381. switch (uiMsg) {
  3382. case WM_NOTIFY:
  3383. {
  3384. NMHDR *pnmHdr;
  3385. NMTTDISPINFO *pnmInfo;
  3386. LONG_PTR lStrId;
  3387. pnmHdr = (NMHDR *)lParam;
  3388. switch (pnmHdr->code) {
  3389. case TTN_NEEDTEXT:
  3390. pnmInfo = (NMTTDISPINFO *)lParam;
  3391. // cast ID as a string for this arg
  3392. lStrId = (LONG_PTR)(wParam - IDM_TOOLBAR);
  3393. lStrId += IDS_TB_BASE;
  3394. pnmInfo->lpszText = (LPTSTR)lStrId;
  3395. pnmInfo->hinst = g_hInstance;
  3396. break;
  3397. default:
  3398. return DefWindowProc (hWnd, uiMsg, wParam, lParam);
  3399. }
  3400. }
  3401. break;
  3402. case WM_CREATE:
  3403. pCtrl = (PSYSMONCTRL)((CREATESTRUCT*)lParam)->lpCreateParams;
  3404. SetWindowLongPtr(hWnd,0,(INT_PTR)pCtrl);
  3405. break;
  3406. case WM_DESTROY:
  3407. pCtrl->m_hWnd = NULL;
  3408. break;
  3409. case WM_CONTEXTMENU:
  3410. case WM_LBUTTONDOWN:
  3411. case WM_LBUTTONDBLCLK:
  3412. //We become UI Active with mouse action
  3413. if (!pCtrl->m_fUIDead) {
  3414. pCtrl->m_pObj->UIActivate();
  3415. pCtrl->AssignFocus();
  3416. if (uiMsg == WM_CONTEXTMENU) {
  3417. if (LOWORD(lParam)!= 0xffff || HIWORD(lParam) != 0xffff){
  3418. pCtrl->DisplayContextMenu(LOWORD(lParam), HIWORD(lParam));
  3419. }else{
  3420. pCtrl->DisplayContextMenu(0,0);
  3421. }
  3422. } else if (uiMsg == WM_LBUTTONDBLCLK) {
  3423. pCtrl->OnDblClick(LOWORD(lParam), HIWORD(lParam));
  3424. }
  3425. }
  3426. break;
  3427. case WM_COMMAND:
  3428. if (pCtrl->m_fUIDead)
  3429. break;
  3430. switch (LOWORD(wParam)) {
  3431. case IDM_TB_PROPERTIES:
  3432. pCtrl->DisplayProperties();
  3433. break;
  3434. case IDM_PROPERTIES:
  3435. pCtrl->DisplayProperties ( DISPID_VALUE );
  3436. break;
  3437. case IDM_TB_ADD:
  3438. case IDM_ADDCOUNTERS:
  3439. pCtrl->AddCounters();
  3440. break;
  3441. case IDM_TB_DELETE:
  3442. case IDM_DELETE:
  3443. {
  3444. CWaitCursor cursorWait;
  3445. if (pCtrl->m_pObj->m_Graph.Options.iDisplayType == REPORT_GRAPH) {
  3446. pCtrl->m_pReport->DeleteSelection();
  3447. } else {
  3448. if ( pCtrl->DeleteCounter ( pCtrl->m_pSelectedItem, TRUE ) ) {
  3449. pCtrl->UpdateGraph(UPDGRPH_DELCNTR);
  3450. }
  3451. }
  3452. }
  3453. break;
  3454. case IDM_TB_REALTIME:
  3455. if ( sysmonCurrentActivity != pCtrl->m_pObj->m_Graph.Options.iDataSourceType ) {
  3456. CWaitCursor cursorWait;
  3457. pCtrl->put_DataSourceType ( sysmonCurrentActivity );
  3458. pCtrl->Clear();
  3459. } else {
  3460. // Nothing changed, so resync the toolbar to
  3461. // handle state of realtime button.
  3462. pCtrl->m_pToolbar->SyncToolbar();
  3463. }
  3464. break;
  3465. case IDM_TB_LOGFILE:
  3466. {
  3467. pCtrl->DisplayProperties( DISPID_SYSMON_DATASOURCETYPE );
  3468. // Resync the toolbar in case the log file is invalid.
  3469. pCtrl->m_pToolbar->SyncToolbar();
  3470. }
  3471. break;
  3472. case IDM_SAVEAS:
  3473. pCtrl->SaveAs();
  3474. break;
  3475. case IDM_SAVEDATA:
  3476. pCtrl->SaveData();
  3477. break;
  3478. case IDC_SNAPBTN:
  3479. case IDM_TB_UPDATE:
  3480. case IDM_UPDATE:
  3481. {
  3482. CWaitCursor cursorWait;
  3483. pCtrl->UpdateCounterValues(TRUE);
  3484. }
  3485. break;
  3486. case IDM_TB_CLEAR:
  3487. {
  3488. CWaitCursor cursorWait;
  3489. pCtrl->Clear();
  3490. }
  3491. break;
  3492. case IDM_TB_FREEZE:
  3493. // Confirm the data overwrite before changing the state of the freeze button.
  3494. if ( pCtrl->ConfirmSampleDataOverwrite() ) {
  3495. pCtrl->put_ManualUpdate ( !pCtrl->m_pObj->m_Graph.Options.bManualUpdate );
  3496. } else {
  3497. // Nothing changed, so resync the toolbar to
  3498. // handle state of the freeze button.
  3499. pCtrl->m_pToolbar->SyncToolbar();
  3500. }
  3501. break;
  3502. case IDM_TB_HIGHLIGHT:
  3503. case IDM_HIGHLITE:
  3504. pCtrl->put_Highlight(!pCtrl->m_pObj->m_Graph.Options.bHighlight );
  3505. break;
  3506. case ID_HATCHWINDOW:
  3507. if (HIWORD(wParam) == HWN_RESIZEREQUESTED)
  3508. pCtrl->m_pObj->m_pIOleIPSite->OnPosRectChange((LPRECT)lParam);
  3509. break;
  3510. case IDM_TB_CHART:
  3511. if (pCtrl->m_pObj->m_Graph.Options.iDisplayType != sysmonLineGraph) {
  3512. CWaitCursor cursorWait;
  3513. if (pCtrl->m_pObj->m_Graph.Options.iDisplayType == REPORT_GRAPH)
  3514. iUpdate = UPDGRPH_VIEW;
  3515. else
  3516. iUpdate = UPDGRPH_PLOT;
  3517. pCtrl->m_pObj->m_Graph.Options.iDisplayType = LINE_GRAPH;
  3518. InvalidateRect(pCtrl->m_hWnd, NULL, TRUE);
  3519. pCtrl->UpdateGraph(iUpdate);
  3520. }
  3521. break;
  3522. case IDM_TB_HISTOGRAM:
  3523. if (pCtrl->m_pObj->m_Graph.Options.iDisplayType != sysmonHistogram) {
  3524. CWaitCursor cursorWait;
  3525. if (pCtrl->m_pObj->m_Graph.Options.iDisplayType == REPORT_GRAPH)
  3526. iUpdate = UPDGRPH_VIEW;
  3527. else
  3528. iUpdate = UPDGRPH_PLOT;
  3529. pCtrl->m_pObj->m_Graph.Options.iDisplayType = BAR_GRAPH;
  3530. InvalidateRect(pCtrl->m_hWnd, NULL, TRUE);
  3531. pCtrl->UpdateGraph(iUpdate);
  3532. }
  3533. break;
  3534. case IDM_TB_REPORT:
  3535. if (pCtrl->m_pObj->m_Graph.Options.iDisplayType != sysmonReport) {
  3536. CWaitCursor cursorWait;
  3537. pCtrl->m_pObj->m_Graph.Options.iDisplayType = REPORT_GRAPH;
  3538. InvalidateRect(pCtrl->m_hWnd, NULL, TRUE);
  3539. pCtrl->UpdateGraph(UPDGRPH_VIEW);
  3540. }
  3541. break;
  3542. case IDM_TB_PASTE:
  3543. {
  3544. HRESULT hr = S_OK;
  3545. {
  3546. CWaitCursor cursorWait;
  3547. hr = pCtrl->Paste();
  3548. }
  3549. if ( SMON_STATUS_NO_SYSMON_OBJECT == hr ) {
  3550. MessageBox(
  3551. pCtrl->m_hWnd,
  3552. ResourceString(IDS_NOSYSMONOBJECT_ERR ),
  3553. ResourceString(IDS_APP_NAME),
  3554. MB_OK | MB_ICONERROR);
  3555. }
  3556. }
  3557. break;
  3558. case IDM_TB_COPY:
  3559. {
  3560. CWaitCursor cursorWait;
  3561. pCtrl->Copy();
  3562. }
  3563. break;
  3564. case IDM_TB_NEW:
  3565. {
  3566. CWaitCursor cursorWait;
  3567. pCtrl->Reset();
  3568. }
  3569. break;
  3570. case IDM_TB_HELP:
  3571. {
  3572. return pCtrl->DisplayHelp ( hWnd );
  3573. }
  3574. default:
  3575. return DefWindowProc (hWnd, uiMsg, wParam, lParam);
  3576. }
  3577. break;
  3578. case WM_DROPFILES:
  3579. {
  3580. CWaitCursor cursorWait;
  3581. pCtrl->OnDropFile (wParam) ;
  3582. }
  3583. return (0) ;
  3584. case WM_ERASEBKGND:
  3585. GetClientRect(hWnd, &rect);
  3586. Fill((HDC)wParam, pCtrl->clrBackCtl(), &rect);
  3587. return TRUE;
  3588. case WM_SYSCOLORCHANGE:
  3589. pCtrl->UpdateNonAmbientSysColors();
  3590. case WM_PAINT:
  3591. pCtrl->Paint();
  3592. break ;
  3593. case WM_SIZE:
  3594. if (pCtrl != NULL) {
  3595. // Avoid extra cases of (SetDirty()) if size has not changed.
  3596. if ( !EqualRect ( pCtrl->GetCurrentClientRect(), pCtrl->GetNewClientRect() ) ) {
  3597. pCtrl->UpdateGraph(UPDGRPH_LAYOUT);
  3598. }
  3599. }
  3600. break ;
  3601. case WM_TIMER:
  3602. pCtrl->UpdateCounterValues(FALSE);
  3603. break;
  3604. case WM_SETFOCUS:
  3605. pCtrl->AssignFocus();
  3606. break;
  3607. case WM_GRAPH_UPDATE:
  3608. pCtrl->UpdateGraphData();
  3609. break;
  3610. case WM_HELP:
  3611. {
  3612. return pCtrl->DisplayHelp ( hWnd );
  3613. }
  3614. default:
  3615. return DefWindowProc (hWnd, uiMsg, wParam, lParam) ;
  3616. }
  3617. return (0);
  3618. }
  3619. HWND CSysmonControl::Window( VOID )
  3620. {
  3621. return m_hWnd;
  3622. }
  3623. void CSysmonControl::UpdateGraph( INT nUpdateType )
  3624. {
  3625. RECT rectStats;
  3626. RECT rectGraph;
  3627. PRECT prectUpdate = NULL;
  3628. RECT rectClient;
  3629. // Based on type of change either force redraw or resize components
  3630. switch (nUpdateType) {
  3631. case UPDGRPH_ADDCNTR:
  3632. case UPDGRPH_DELCNTR:
  3633. if ( m_bLogFileSource )
  3634. m_fPendingLogCntrChg = TRUE;
  3635. m_fPendingSizeChg = TRUE;
  3636. break;
  3637. case UPDGRPH_FONT:
  3638. m_fPendingFontChg = TRUE;
  3639. break;
  3640. case UPDGRPH_LOGVIEW:
  3641. m_fPendingLogViewChg = TRUE;
  3642. if (m_hWnd && m_pStatsBar ) {
  3643. m_pStatsBar->GetUpdateRect(&rectStats);
  3644. prectUpdate = &rectStats;
  3645. }
  3646. // Fall into plot area case
  3647. case UPDGRPH_PLOT:
  3648. if ( REPORT_GRAPH != m_pObj->m_Graph.Options.iDisplayType ) {
  3649. if (m_hWnd && m_pGraphDisp) {
  3650. m_pGraphDisp->GetPlotRect(&rectGraph);
  3651. if ( NULL == prectUpdate ) {
  3652. prectUpdate = &rectGraph;
  3653. } else {
  3654. ::UnionRect( prectUpdate, &rectStats, &rectGraph);
  3655. }
  3656. }
  3657. } else {
  3658. GetClientRect (m_hWnd, &rectClient);
  3659. prectUpdate = &rectClient;
  3660. }
  3661. break;
  3662. case UPDGRPH_COLOR:
  3663. //update the toolbar color
  3664. m_pToolbar->SetBackgroundColor ( clrBackCtl() );
  3665. m_fPendingSizeChg = TRUE;
  3666. break;
  3667. case UPDGRPH_LAYOUT:
  3668. case UPDGRPH_VIEW:
  3669. m_fPendingSizeChg = TRUE;
  3670. break;
  3671. }
  3672. // Set change pending flag to enable ApplyChanges
  3673. m_fPendingUpdate = TRUE;
  3674. // If we're ready to do updates
  3675. if (m_fViewInitialized) {
  3676. // Invalidate window to force redraw
  3677. InvalidateRect(m_hWnd, prectUpdate, TRUE);
  3678. // Notify container of change
  3679. m_pObj->SendAdvise(OBJECTCODE_DATACHANGED);
  3680. }
  3681. }
  3682. void CSysmonControl::UpdateGraphData( VOID )
  3683. {
  3684. HDC hDC = NULL;
  3685. PGRAPHDATA pGraph = &m_pObj->m_Graph;
  3686. if (m_fViewInitialized) {
  3687. UpdateAppPerfTimeData (TD_UPDATE_TIME, TD_BEGIN);
  3688. hDC = GetDC(m_hWnd);
  3689. // Update statistics if active
  3690. // Statistics are updated before the graph display in case the
  3691. // graph display selects a clipping region.
  3692. if (pGraph->Options.bValueBarChecked &&m_pSelectedItem != NULL) {
  3693. // The stats bar doesn't always use the hDC, so passing NULL
  3694. // hDC is okay.
  3695. m_pStatsBar->Update(hDC, m_pSelectedItem);
  3696. }
  3697. if ( NULL != hDC ) {
  3698. // Update graph display
  3699. m_pGraphDisp->Update(hDC);
  3700. m_pReport->Update();
  3701. ReleaseDC(m_hWnd, hDC);
  3702. }
  3703. UpdateAppPerfTimeData (TD_UPDATE_TIME, TD_END);
  3704. }
  3705. }
  3706. void CSysmonControl::Render(
  3707. HDC hDC,
  3708. HDC hAttribDC,
  3709. BOOL fMetafile,
  3710. BOOL fEntire,
  3711. LPRECT pRect )
  3712. {
  3713. HDC hLocalAttribDC = NULL;
  3714. // If not inited, return.
  3715. if ( m_fViewInitialized ) {
  3716. if ( NULL == hAttribDC ) {
  3717. hLocalAttribDC = GetDC(m_hWnd);
  3718. } else {
  3719. hLocalAttribDC = hAttribDC;
  3720. }
  3721. // Make sure layout is up to date.
  3722. ApplyChanges( hLocalAttribDC );
  3723. if ( NULL != hDC && NULL != hLocalAttribDC ) {
  3724. if ( REPORT_GRAPH == m_pObj->m_Graph.Options.iDisplayType ) {
  3725. m_pReport->Render( hDC, hLocalAttribDC, fMetafile, fEntire, pRect );
  3726. } else {
  3727. // Fill with background color
  3728. SetBkColor(hDC, clrBackCtl());
  3729. ClearRect(hDC, pRect);
  3730. m_pStatsBar->Draw(hDC, hLocalAttribDC, pRect);
  3731. m_pGraphDisp->Draw(hDC, hLocalAttribDC, fMetafile, fEntire, pRect );
  3732. m_pLegend->Render(hDC, hLocalAttribDC, fMetafile, fEntire, pRect);
  3733. }
  3734. if ( eBorderSingle == m_iBorderStyle ) {
  3735. if ( eAppear3D == m_iAppearance ) {
  3736. DrawEdge(hDC, pRect, EDGE_RAISED, BF_RECT);
  3737. } else {
  3738. SelectBrush (hDC, GetStockObject (HOLLOW_BRUSH)) ;
  3739. SelectPen (hDC, GetStockObject (BLACK_PEN)) ;
  3740. Rectangle (hDC, pRect->left, pRect->top, pRect->right, pRect->bottom );
  3741. }
  3742. }
  3743. }
  3744. if ( NULL != hLocalAttribDC && hAttribDC != hLocalAttribDC ) {
  3745. ReleaseDC ( m_hWnd, hLocalAttribDC );
  3746. }
  3747. }
  3748. }
  3749. void CSysmonControl::SetIntervalTimer()
  3750. {
  3751. HDC hDC = NULL;
  3752. PGRAPHDATA pGraph = &m_pObj->m_Graph;
  3753. // if not initialized or counter source is a log file, nothing to do
  3754. if (!m_fInitialized || IsLogSource() || !IsUserMode() )
  3755. return;
  3756. // Update statistics bar
  3757. m_pStatsBar->SetTimeSpan(
  3758. m_pObj->m_Graph.Options.fUpdateInterval
  3759. * m_pObj->m_Graph.Options.iDisplayFilter
  3760. * m_pHistCtrl->nMaxSamples );
  3761. hDC = GetDC(m_hWnd);
  3762. if ( NULL != hDC ) {
  3763. m_pStatsBar->Update(hDC, m_pSelectedItem);
  3764. ReleaseDC(m_hWnd,hDC);
  3765. }
  3766. // If conditions right for sampling, start new time interval.
  3767. // Otherwise, suspend the collection.
  3768. if (!pGraph->Options.bManualUpdate
  3769. && pGraph->Options.fUpdateInterval >= 0.001 // ??
  3770. && pGraph->CounterTree.NumCounters() != 0
  3771. && IsUserMode() ) {
  3772. m_CollectInfo.dwInterval= (DWORD)(pGraph->Options.fUpdateInterval * 1000);
  3773. m_CollectInfo.dwSampleTime = GetTickCount();
  3774. m_CollectInfo.iMode = COLLECT_ACTIVE;
  3775. }
  3776. else {
  3777. m_CollectInfo.iMode = COLLECT_SUSPEND;
  3778. }
  3779. assert ( NULL != m_CollectInfo.hEvent );
  3780. // Signal the collection thread
  3781. SetEvent(m_CollectInfo.hEvent);
  3782. // If no counters, reset sample time to start
  3783. if (pGraph->CounterTree.NumCounters() == 0) {
  3784. m_pHistCtrl->iCurrent = 0;
  3785. m_pHistCtrl->nSamples = 0;
  3786. pGraph->TimeStepper.Reset();
  3787. }
  3788. }
  3789. HRESULT CSysmonControl::AddSingleCounter(LPTSTR pszPath, PCGraphItem *pGItem)
  3790. {
  3791. PCGraphItem pGraphItem;
  3792. PGRAPHDATA pGraph = &m_pObj->m_Graph;
  3793. HRESULT hr;
  3794. BOOL bAddSuccessful = FALSE;
  3795. *pGItem = NULL;
  3796. // Create graph item
  3797. pGraphItem = new CGraphItem(this);
  3798. if (pGraphItem == NULL)
  3799. return E_OUTOFMEMORY;
  3800. LockCounterData();
  3801. // Add it to the counter tree
  3802. hr = pGraph->CounterTree.AddCounterItem(
  3803. pszPath,
  3804. pGraphItem,
  3805. pGraph->Options.bMonitorDuplicateInstances);
  3806. if (SUCCEEDED(hr)) {
  3807. // AddRef once for ourself
  3808. pGraphItem->AddRef();
  3809. // Set default attributes
  3810. pGraphItem->put_Color(IndexToStandardColor(m_iColorIndex));
  3811. pGraphItem->put_Width(IndexToWidth(m_iWidthIndex));
  3812. pGraphItem->put_LineStyle(IndexToStyle(m_iStyleIndex));
  3813. pGraphItem->put_ScaleFactor(m_iScaleFactor);
  3814. // Increment and reset for next counter
  3815. IncrementVisuals();
  3816. m_iScaleFactor = INT_MAX;
  3817. // Add item to graph's query
  3818. if ( NULL != m_hQuery ) {
  3819. hr = pGraphItem->AddToQuery(m_hQuery);
  3820. } else {
  3821. // Todo: Change AddToQuery to return bad status,
  3822. // Todo: Display error message
  3823. hr = E_FAIL;
  3824. }
  3825. if (SUCCEEDED(hr)) {
  3826. bAddSuccessful = TRUE;
  3827. // If control is initialized
  3828. if (m_fViewInitialized) {
  3829. // Add item to chart legend
  3830. m_pLegend->AddItem(pGraphItem);
  3831. m_pReport->AddItem(pGraphItem);
  3832. }
  3833. }
  3834. else {
  3835. // remove the item from the tree
  3836. pGraphItem->Instance()->RemoveItem(pGraphItem);
  3837. }
  3838. // If OK, Addref the returned interface
  3839. if (SUCCEEDED(hr)) {
  3840. pGraphItem->AddRef();
  3841. *pGItem = pGraphItem;
  3842. } // else released by RemoveItem above.
  3843. // Update messages seem to be combined, so histogram sometimes updates instead of
  3844. // repainting each entire bar. This forces total repaint.
  3845. if ( m_pGraphDisp) {
  3846. m_pGraphDisp->SetBarConfigChanged();
  3847. }
  3848. } else {
  3849. // AddCounterItem failed
  3850. delete pGraphItem;
  3851. }
  3852. UnlockCounterData();
  3853. // Send events outside of locks.
  3854. if ( bAddSuccessful ) {
  3855. // If first counter
  3856. if (pGraph->CounterTree.NumCounters() == 1) {
  3857. // Make it the selected counter and send event.
  3858. SelectCounter(pGraphItem);
  3859. // Start data collection
  3860. if ( ERROR_SUCCESS != ActivateQuery() ) {
  3861. hr = E_FAIL;
  3862. }
  3863. }
  3864. // Redraw the graph
  3865. UpdateGraph(UPDGRPH_ADDCNTR);
  3866. m_pObj->SendEvent(eEventOnCounterAdded, pGraph->CounterTree.NumCounters());
  3867. }
  3868. return hr;
  3869. }
  3870. PCCounterTree
  3871. CSysmonControl::CounterTree(
  3872. VOID
  3873. )
  3874. {
  3875. return &(m_pObj->m_Graph.CounterTree);
  3876. }
  3877. PCGraphItem
  3878. CSysmonControl::FirstCounter(
  3879. VOID
  3880. )
  3881. {
  3882. return m_pObj->m_Graph.CounterTree.FirstCounter();
  3883. }
  3884. PCGraphItem
  3885. CSysmonControl::LastCounter(
  3886. VOID
  3887. )
  3888. {
  3889. PCGraphItem pItem;
  3890. PCGraphItem pItemNext;
  3891. if (FirstCounter() == NULL)
  3892. return NULL;
  3893. // Locate last graph item
  3894. pItem = FirstCounter();
  3895. while ((pItemNext = pItem->Next()) != NULL)
  3896. pItem = pItemNext;
  3897. return pItem;
  3898. }
  3899. BOOL
  3900. CSysmonControl::IsLogSource(
  3901. VOID
  3902. )
  3903. {
  3904. return m_pHistCtrl->bLogSource;
  3905. }
  3906. BOOL
  3907. CSysmonControl::IsReadOnly(
  3908. VOID
  3909. )
  3910. {
  3911. BOOL bReturn = TRUE;
  3912. if (m_fInitialized ) {
  3913. bReturn = m_pObj->m_Graph.Options.bReadOnly;
  3914. }
  3915. return bReturn;
  3916. }
  3917. eReportValueTypeConstant
  3918. CSysmonControl::ReportValueType(
  3919. VOID
  3920. )
  3921. {
  3922. return ( (eReportValueTypeConstant) m_pObj->m_Graph.Options.iReportValueType );
  3923. }
  3924. INT CSysmonControl::CounterIndex(PCGraphItem pItem)
  3925. {
  3926. PCGraphItem pItemLoc;
  3927. INT iIndex;
  3928. // Traverse linked list until item matched
  3929. pItemLoc = FirstCounter();
  3930. iIndex = 1;
  3931. while (pItemLoc != pItem && pItemLoc != NULL) {
  3932. pItemLoc = pItemLoc->Next();
  3933. iIndex++;
  3934. }
  3935. return (pItemLoc == NULL) ? -1 : iIndex;
  3936. }
  3937. HRESULT CSysmonControl::DeleteCounter(PCGraphItem pItem, BOOL bPropagateUp)
  3938. {
  3939. PGRAPHDATA pGraph = &m_pObj->m_Graph;
  3940. if (pItem == NULL)
  3941. return E_INVALIDARG;
  3942. // Send event
  3943. m_pObj->SendEvent(eEventOnCounterDeleted, CounterIndex(pItem));
  3944. LockCounterData();
  3945. // If this is the selected counter, change selection to NULL
  3946. if (pItem == m_pSelectedItem)
  3947. m_pSelectedItem = NULL;
  3948. if (m_fViewInitialized) {
  3949. // Remove from legend and report
  3950. m_pLegend->DeleteItem(pItem);
  3951. m_pReport->DeleteItem(pItem);
  3952. // Remove from query
  3953. pItem->RemoveFromQuery();
  3954. }
  3955. // Proagate deletion up the tree if requested
  3956. if (bPropagateUp) {
  3957. pItem->Instance()->RemoveItem(pItem);
  3958. }
  3959. // If last counter, stop interval timer
  3960. if (pGraph->CounterTree.NumCounters() == 0)
  3961. SetIntervalTimer();
  3962. // Update messages seem to be combined, so histogram sometimes updates instead of
  3963. // repainting each entire bar. This forces total repaint.
  3964. if ( m_pGraphDisp) {
  3965. m_pGraphDisp->SetBarConfigChanged();
  3966. }
  3967. UnlockCounterData();
  3968. if ( m_fViewInitialized ) {
  3969. UpdateGraph(UPDGRPH_DELCNTR);
  3970. }
  3971. return NOERROR;
  3972. }
  3973. void CSysmonControl::SelectCounter(PCGraphItem pItem)
  3974. {
  3975. HDC hDC = NULL;
  3976. INT iIndex;
  3977. // Selection in the graph view is maintained independently
  3978. // of the selection in the report view.
  3979. if ( REPORT_GRAPH != m_pObj->m_Graph.Options.iDisplayType ) {
  3980. // Save as current item
  3981. m_pSelectedItem = pItem;
  3982. if (m_fViewInitialized) {
  3983. // Inform Legend
  3984. m_pLegend->SelectItem(pItem);
  3985. // Highlight selected item in graph display
  3986. if (m_pObj->m_Graph.Options.bHighlight) {
  3987. m_pGraphDisp->HiliteItem(pItem);
  3988. UpdateGraph(UPDGRPH_PLOT);
  3989. }
  3990. // Update statistics bar
  3991. if ( m_fViewInitialized )
  3992. hDC = GetDC(m_hWnd);
  3993. m_pStatsBar->Update(hDC, pItem);
  3994. if ( NULL != hDC )
  3995. ReleaseDC(m_hWnd,hDC);
  3996. }
  3997. }
  3998. // Send event
  3999. iIndex = (pItem == NULL) ? 0 : CounterIndex(pItem);
  4000. m_pObj->SendEvent(eEventOnCounterSelected, iIndex);
  4001. }
  4002. HRESULT
  4003. CSysmonControl::PasteFromBuffer( LPTSTR pszData, BOOL bAllData )
  4004. {
  4005. HRESULT hr = NOERROR;
  4006. CImpIPropertyBag IPropBag;
  4007. hr = IPropBag.LoadData( pszData );
  4008. if ( SUCCEEDED ( hr ) ) {
  4009. INT nLogType = SMON_CTRL_LOG;
  4010. //get the log type from the pPropBag and compare it with service(cookie) type
  4011. //Determine log type from property bag. Default to -1 SMON_CTRL_LOG
  4012. hr = IntegerFromPropertyBag (
  4013. &IPropBag,
  4014. NULL,
  4015. ResourceString(IDS_HTML_LOG_TYPE),
  4016. nLogType);
  4017. if(nLogType == SLQ_TRACE_LOG){
  4018. MessageBox(
  4019. m_hWnd,
  4020. ResourceString(IDS_TRACE_LOG_ERR_MSG),
  4021. ResourceString(IDS_APP_NAME),
  4022. MB_OK
  4023. );
  4024. } else {
  4025. if ( bAllData ) {
  4026. hr = LoadFromPropertyBag( &IPropBag, NULL );
  4027. } else {
  4028. // Do not load sample data for Paste or Drop File.
  4029. hr = LoadCountersFromPropertyBag (&IPropBag, NULL, FALSE );
  4030. }
  4031. }
  4032. }
  4033. return hr;
  4034. }
  4035. HRESULT CSysmonControl::Paste()
  4036. {
  4037. HRESULT hResReturn = NOERROR;
  4038. HANDLE hMemClipboard;
  4039. // get the clipboard
  4040. if (OpenClipboard (Window())) {
  4041. // read the CF_TEXT or CF_UNICODE data from the clipboard to the local buffer
  4042. hMemClipboard = GetClipboardData (
  4043. #if UNICODE
  4044. CF_UNICODETEXT); // UNICODE text in the clipboard
  4045. #else
  4046. CF_TEXT); // ANSI text in the clipboard
  4047. #endif
  4048. if (hMemClipboard != NULL) {
  4049. LPTSTR pszData;
  4050. if ( ConfirmSampleDataOverwrite ( ) ) {
  4051. pszData = (LPTSTR)GlobalLock (hMemClipboard);// (LPTSTR)hMemClipboard;
  4052. if ( NULL != pszData ) {
  4053. hResReturn = PasteFromBuffer ( pszData, FALSE );
  4054. GlobalUnlock ( hMemClipboard );
  4055. }
  4056. }
  4057. }
  4058. // release the clipboard
  4059. CloseClipboard();
  4060. } else {
  4061. // unable to open the clipboard
  4062. hResReturn = HRESULT_FROM_WIN32(GetLastError());
  4063. }
  4064. return hResReturn;
  4065. }
  4066. HRESULT
  4067. CSysmonControl::CopyToBuffer ( LPTSTR& rpszData, DWORD& rdwBufferSize )
  4068. {
  4069. HRESULT hr = S_OK;
  4070. LPTSTR pszHeader = NULL;
  4071. LPTSTR pszFooter = NULL;
  4072. CImpIPropertyBag IPropBag;
  4073. assert ( NULL == rpszData );
  4074. rdwBufferSize = 0;
  4075. if (NULL!=m_pObj->m_pImpIPersistPropertyBag) {
  4076. hr = m_pObj->m_pImpIPersistPropertyBag->Save (&IPropBag, FALSE, TRUE );
  4077. }
  4078. if ( SUCCEEDED ( hr ) ) {
  4079. DWORD dwBufferLength;
  4080. LPTSTR pszConfig;
  4081. pszHeader = ResourceString ( IDS_HTML_OBJECT_HEADER );
  4082. pszFooter = ResourceString ( IDS_HTML_OBJECT_FOOTER );
  4083. pszConfig = IPropBag.GetData();
  4084. // Buffer length includes 1 for NULL terminator.
  4085. dwBufferLength = lstrlen ( pszHeader ) + lstrlen ( pszFooter ) + lstrlen ( pszConfig ) + 1;
  4086. rpszData = new TCHAR[dwBufferLength];
  4087. if ( NULL == rpszData ) {
  4088. hr = E_OUTOFMEMORY;
  4089. } else {
  4090. rdwBufferSize = dwBufferLength * sizeof(TCHAR);
  4091. rpszData[0] = _T('\0');
  4092. lstrcpy ( rpszData, pszHeader );
  4093. lstrcat ( rpszData, pszConfig );
  4094. lstrcat ( rpszData, pszFooter );
  4095. }
  4096. }
  4097. return hr;
  4098. }
  4099. HRESULT CSysmonControl::Copy()
  4100. {
  4101. HGLOBAL hBuffer = NULL;
  4102. HRESULT hResReturn = NOERROR;
  4103. LPTSTR pszBuffer = NULL;
  4104. DWORD dwBufferSize;
  4105. HANDLE hMemClipboard;
  4106. hResReturn = CopyToBuffer( pszBuffer, dwBufferSize);
  4107. if ( SUCCEEDED ( hResReturn ) ) {
  4108. LPTSTR pszGlobalBuffer = NULL;
  4109. hBuffer = GlobalAlloc ((GMEM_MOVEABLE | GMEM_DDESHARE), dwBufferSize);
  4110. pszGlobalBuffer = (LPTSTR)GlobalLock (hBuffer);
  4111. if ( NULL == pszGlobalBuffer ) {
  4112. // allocation or lock failed so bail out
  4113. GlobalFree (hBuffer);
  4114. hResReturn = E_OUTOFMEMORY;
  4115. }
  4116. if ( SUCCEEDED ( hResReturn ) ) {
  4117. lstrcpy ( pszGlobalBuffer, pszBuffer );
  4118. }
  4119. delete pszBuffer;
  4120. GlobalUnlock (hBuffer);
  4121. }
  4122. if ( NULL != hBuffer ) {
  4123. // then there's something to copy so...
  4124. // get the clipboard
  4125. if (OpenClipboard (m_hWnd)) {
  4126. // copy the counter list to the clipboard
  4127. if (EmptyClipboard()) {
  4128. hMemClipboard = SetClipboardData (
  4129. #if UNICODE
  4130. CF_UNICODETEXT, // UNICODE text in the clipboard
  4131. #else
  4132. CF_TEXT, // ANSI text in the clipboard
  4133. #endif
  4134. hBuffer);
  4135. if (hMemClipboard == NULL) {
  4136. //free memory since it didn't make it to the clipboard
  4137. GlobalFree (hBuffer);
  4138. // unable to set data in the clipboard
  4139. hResReturn = HRESULT_FROM_WIN32(GetLastError());
  4140. }
  4141. } else {
  4142. //free memory since it didn't make it to the clipboard
  4143. GlobalFree (hBuffer);
  4144. // unable to empty the clipboard
  4145. hResReturn = HRESULT_FROM_WIN32(GetLastError());
  4146. }
  4147. // release the clipboard
  4148. CloseClipboard();
  4149. } else {
  4150. //free memory since it didn't make it to the clipboard
  4151. GlobalFree (hBuffer);
  4152. // unable to open the clipboard
  4153. hResReturn = HRESULT_FROM_WIN32(GetLastError());
  4154. }
  4155. }
  4156. return hResReturn;
  4157. }
  4158. HRESULT CSysmonControl::Reset()
  4159. {
  4160. PCGraphItem pItem;
  4161. // Request each counter from the control, to compute
  4162. // required buffer size
  4163. while ((pItem = FirstCounter())!= NULL) {
  4164. // delete this counter
  4165. DeleteCounter (pItem, TRUE);
  4166. }
  4167. m_iColorIndex = 0;
  4168. m_iWidthIndex = 0;
  4169. m_iStyleIndex = 0;
  4170. return NOERROR;
  4171. }
  4172. void CSysmonControl::DblClickCounter(PCGraphItem pItem)
  4173. {
  4174. INT iIndex;
  4175. // Send event
  4176. iIndex = (pItem == NULL) ? 0 : CounterIndex(pItem);
  4177. m_pObj->SendEvent(eEventOnDblClick, iIndex);
  4178. }
  4179. BOOL
  4180. CSysmonControl::ConfirmSampleDataOverwrite ( )
  4181. {
  4182. BOOL bOverwrite = TRUE;
  4183. if ( m_bSampleDataLoaded ) {
  4184. // Confirm overwrite of view-only data.
  4185. INT iOverwrite = IDNO;
  4186. assert ( FALSE == m_fInitialized );
  4187. iOverwrite = MessageBox(
  4188. Window(),
  4189. ResourceString(IDS_SAMPLE_DATA_OVERWRITE),
  4190. ResourceString(IDS_APP_NAME),
  4191. MB_YESNO );
  4192. if ( IDYES == iOverwrite ) {
  4193. m_bSampleDataLoaded = FALSE;
  4194. bOverwrite = Init ( g_hWndFoster );
  4195. UpdateGraph(UPDGRPH_LAYOUT); // If toolbar enabled, must resize
  4196. // Also clears the graph
  4197. } else {
  4198. bOverwrite = FALSE;
  4199. }
  4200. }
  4201. return bOverwrite;
  4202. }
  4203. void
  4204. CSysmonControl::Clear ( void )
  4205. {
  4206. if ( ConfirmSampleDataOverwrite() ) {
  4207. PCGraphItem pItem;
  4208. m_pHistCtrl->nMaxSamples = MAX_GRAPH_SAMPLES;
  4209. m_pHistCtrl->iCurrent = 0;
  4210. m_pHistCtrl->nSamples = 0;
  4211. m_pHistCtrl->nBacklog = 0;
  4212. m_pObj->m_Graph.TimeStepper.Reset();
  4213. m_pStatsBar->Clear();
  4214. // Reset history for all counters
  4215. for (pItem = FirstCounter(); pItem != NULL; pItem = pItem->Next()) {
  4216. pItem->ClearHistory();
  4217. }
  4218. // Repaint the graph and value bar
  4219. UpdateGraph(UPDGRPH_VIEW);
  4220. }
  4221. }
  4222. PDH_STATUS
  4223. CSysmonControl::UpdateCounterValues ( BOOL fValidSample )
  4224. {
  4225. PDH_STATUS stat = ERROR_SUCCESS;
  4226. PCGraphItem pItem;
  4227. PGRAPHDATA pGraph = &m_pObj->m_Graph;
  4228. // If no query or no counters assign, nothing to do
  4229. if ( NULL == m_hQuery
  4230. || pGraph->CounterTree.NumCounters() == 0
  4231. || !IsUserMode() ) {
  4232. stat = ERROR_SUCCESS;
  4233. } else {
  4234. if ( ConfirmSampleDataOverwrite () ) {
  4235. // If valid sample, collect the data
  4236. if (fValidSample) {
  4237. UpdateAppPerfTimeData (TD_P_QUERY_TIME, TD_BEGIN);
  4238. stat = PdhCollectQueryData(m_hQuery);
  4239. UpdateAppPerfTimeData (TD_P_QUERY_TIME, TD_END);
  4240. }
  4241. if ( ERROR_SUCCESS == stat ) {
  4242. UpdateAppPerfTimeData (TD_S_QUERY_TIME, TD_BEGIN);
  4243. LockCounterData();
  4244. // Update history control and all counter history arrays
  4245. m_pHistCtrl->iCurrent++;
  4246. if (m_pHistCtrl->iCurrent == m_pHistCtrl->nMaxSamples)
  4247. m_pHistCtrl->iCurrent = 0;
  4248. if (m_pHistCtrl->nSamples < m_pHistCtrl->nMaxSamples)
  4249. m_pHistCtrl->nSamples++;
  4250. // Update history for all counters
  4251. for (pItem = FirstCounter(); pItem != NULL; pItem = pItem->Next()) {
  4252. pItem->UpdateHistory(fValidSample);
  4253. }
  4254. // If we're initialized and have at least two samples
  4255. if (m_fInitialized && m_pHistCtrl->nSamples >= 2) {
  4256. // If no backlogged updates, post an update message
  4257. if (m_pHistCtrl->nBacklog == 0) {
  4258. PostMessage(m_hWnd, WM_GRAPH_UPDATE, 0, 0);
  4259. }
  4260. m_pHistCtrl->nBacklog++;
  4261. }
  4262. UnlockCounterData();
  4263. // If event sync present, send notification outside of lock.
  4264. m_pObj->SendEvent(eEventOnSampleCollected, 0);
  4265. UpdateAppPerfTimeData (TD_S_QUERY_TIME, TD_END);
  4266. }
  4267. }
  4268. }
  4269. return ERROR_SUCCESS;
  4270. }
  4271. void CSysmonControl::Activate( VOID )
  4272. {
  4273. if (!m_fUIDead) {
  4274. m_pObj->UIActivate();
  4275. }
  4276. }
  4277. void CSysmonControl::put_Appearance(INT iAppearance, BOOL fAmbient)
  4278. {
  4279. INT iLocalAppearance;
  4280. if (fAmbient && m_pObj->m_Graph.Options.iAppearance != NULL_APPEARANCE)
  4281. return;
  4282. if (!fAmbient) {
  4283. m_pObj->m_Graph.Options.iAppearance = iAppearance;
  4284. }
  4285. // Any non-zero value translates to 3D. In ambient case, the high bits are sometimes set.
  4286. if ( iAppearance ) {
  4287. iLocalAppearance = eAppear3D;
  4288. } else {
  4289. iLocalAppearance = eAppearFlat;
  4290. }
  4291. m_iAppearance = iLocalAppearance;
  4292. UpdateGraph(UPDGRPH_COLOR);
  4293. }
  4294. void CSysmonControl::put_BorderStyle(INT iBorderStyle, BOOL fAmbient)
  4295. {
  4296. if (fAmbient && m_pObj->m_Graph.Options.iBorderStyle != NULL_BORDERSTYLE)
  4297. return;
  4298. if (!fAmbient) {
  4299. m_pObj->m_Graph.Options.iBorderStyle = iBorderStyle;
  4300. }
  4301. m_iBorderStyle = iBorderStyle;
  4302. UpdateGraph(UPDGRPH_COLOR);
  4303. }
  4304. void CSysmonControl::put_BackCtlColor(OLE_COLOR Color)
  4305. {
  4306. m_pObj->m_Graph.Options.clrBackCtl = Color;
  4307. OleTranslateColor(Color, NULL, &m_clrBackCtl);
  4308. UpdateGraph(UPDGRPH_COLOR);
  4309. }
  4310. void CSysmonControl::put_FgndColor (
  4311. OLE_COLOR Color,
  4312. BOOL fAmbient
  4313. )
  4314. {
  4315. if (fAmbient && m_pObj->m_Graph.Options.clrFore != NULL_COLOR)
  4316. return;
  4317. if (!fAmbient)
  4318. m_pObj->m_Graph.Options.clrFore = Color;
  4319. OleTranslateColor(Color, NULL, &m_clrFgnd);
  4320. UpdateGraph(UPDGRPH_COLOR);
  4321. }
  4322. void CSysmonControl::put_BackPlotColor (
  4323. OLE_COLOR Color,
  4324. BOOL fAmbient
  4325. )
  4326. {
  4327. if (fAmbient && m_pObj->m_Graph.Options.clrBackPlot != NULL_COLOR)
  4328. return;
  4329. if (!fAmbient)
  4330. m_pObj->m_Graph.Options.clrBackPlot = Color;
  4331. OleTranslateColor(Color, NULL, &m_clrBackPlot);
  4332. UpdateGraph(UPDGRPH_PLOT);
  4333. }
  4334. void CSysmonControl::put_GridColor (
  4335. OLE_COLOR Color
  4336. )
  4337. {
  4338. // Options color is the OLE_COLOR.
  4339. // Color in control is translated from OLE_COLOR.
  4340. m_pObj->m_Graph.Options.clrGrid = Color;
  4341. OleTranslateColor(Color, NULL, &m_clrGrid);
  4342. UpdateGraph(UPDGRPH_PLOT);
  4343. }
  4344. void CSysmonControl::put_TimeBarColor (
  4345. OLE_COLOR Color
  4346. )
  4347. {
  4348. // Options color is the OLE_COLOR.
  4349. // Color in control is translated from OLE_COLOR.
  4350. m_pObj->m_Graph.Options.clrTimeBar = Color;
  4351. OleTranslateColor(Color, NULL, &m_clrTimeBar);
  4352. UpdateGraph(UPDGRPH_PLOT);
  4353. }
  4354. HRESULT CSysmonControl::put_Font (
  4355. LPFONT pIFont,
  4356. BOOL fAmbient
  4357. )
  4358. {
  4359. HRESULT hr = NOERROR;
  4360. if ( NULL == pIFont ) {
  4361. hr = E_INVALIDARG;
  4362. } else {
  4363. if ( fAmbient && FALSE == m_pObj->m_Graph.Options.bAmbientFont ) {
  4364. hr = NOERROR;
  4365. } else {
  4366. if (!fAmbient) {
  4367. m_pObj->m_Graph.Options.bAmbientFont = FALSE;
  4368. }
  4369. hr = m_OleFont.SetIFont(pIFont);
  4370. }
  4371. }
  4372. return hr;
  4373. }
  4374. void CSysmonControl::FontChanged(
  4375. void
  4376. )
  4377. {
  4378. m_pReport->ChangeFont();
  4379. UpdateGraph(UPDGRPH_FONT);
  4380. }
  4381. void
  4382. CSysmonControl::SetMissedSample ( void )
  4383. {
  4384. if ( !m_bLoadingCounters ) {
  4385. m_bMissedSample = TRUE;
  4386. }
  4387. };
  4388. DWORD WINAPI
  4389. CollectProc (
  4390. IN PSYSMONCTRL pCtrl
  4391. )
  4392. {
  4393. DWORD dwElapsedTime;
  4394. DWORD dwTimeout = INFINITE;
  4395. COLLECT_PROC_INFO *pCollectInfo = &pCtrl->m_CollectInfo;
  4396. while (TRUE) {
  4397. // Wait for event or next sample period
  4398. WaitForSingleObject(pCollectInfo->hEvent, dwTimeout);
  4399. // If quit request, exit loop
  4400. if (pCollectInfo->iMode == COLLECT_QUIT)
  4401. break;
  4402. // If suspended, wait for an event
  4403. if (pCollectInfo->iMode == COLLECT_SUSPEND) {
  4404. dwTimeout = INFINITE;
  4405. continue;
  4406. }
  4407. // Take a sample
  4408. pCtrl->UpdateCounterValues(TRUE);
  4409. // Get elapsed time from last sample time
  4410. dwElapsedTime = GetTickCount() - pCollectInfo->dwSampleTime;
  4411. if (dwElapsedTime > 100000)
  4412. dwElapsedTime = 0;
  4413. // Have we missed any sample times?
  4414. while (dwElapsedTime > pCollectInfo->dwInterval) {
  4415. // By how much?
  4416. dwElapsedTime -= pCollectInfo->dwInterval;
  4417. // If less than 1/2 an interval, take the sample now
  4418. // otherwise record a missed one
  4419. if (dwElapsedTime < pCollectInfo->dwInterval/2) {
  4420. pCtrl->UpdateCounterValues(TRUE);
  4421. } else {
  4422. pCtrl->SetMissedSample();
  4423. pCtrl->UpdateCounterValues(FALSE);
  4424. }
  4425. // Advance to next sample time
  4426. pCollectInfo->dwSampleTime += pCollectInfo->dwInterval;
  4427. }
  4428. // Set timeout to wait until next sample time
  4429. dwTimeout = pCollectInfo->dwInterval - dwElapsedTime;
  4430. pCollectInfo->dwSampleTime += pCollectInfo->dwInterval;
  4431. }
  4432. return 0;
  4433. }
  4434. HRESULT
  4435. CSysmonControl::InitLogFileIntervals ( void )
  4436. {
  4437. HRESULT hr = S_OK;
  4438. PDH_STATUS pdhstat;
  4439. DWORD nLogEntries = 0;
  4440. DWORD nBufSize;
  4441. PDH_TIME_INFO TimeInfo;
  4442. if ( m_bLogFileSource ) {
  4443. // Get time and sample count info
  4444. nBufSize = sizeof(TimeInfo);
  4445. pdhstat = PdhGetDataSourceTimeRangeH(GetDataSourceHandle(),
  4446. & nLogEntries,
  4447. & TimeInfo,
  4448. & nBufSize );
  4449. if ( ERROR_SUCCESS != pdhstat ) {
  4450. if ( ERROR_NOT_ENOUGH_MEMORY == pdhstat ) {
  4451. pdhstat = SMON_STATUS_LOG_FILE_SIZE_LIMIT;
  4452. }
  4453. hr = (HRESULT)pdhstat;
  4454. } else if ( 2 > TimeInfo.SampleCount ) {
  4455. hr = (HRESULT)SMON_STATUS_TOO_FEW_SAMPLES;
  4456. m_DataSourceInfo.llInterval = 1;
  4457. } else {
  4458. // Setup time range info
  4459. m_DataSourceInfo.llBeginTime = TimeInfo.StartTime;
  4460. m_DataSourceInfo.llEndTime = TimeInfo.EndTime;
  4461. // The start or stop time might no longer be valid, so check for
  4462. // relationship between the them as well as for start/begin, stop/end.
  4463. if ( (m_DataSourceInfo.llStartDisp < m_DataSourceInfo.llBeginTime)
  4464. || (m_DataSourceInfo.llStartDisp > m_DataSourceInfo.llEndTime) )
  4465. m_DataSourceInfo.llStartDisp = m_DataSourceInfo.llBeginTime;
  4466. if ( (m_DataSourceInfo.llStopDisp > m_DataSourceInfo.llEndTime)
  4467. || (m_DataSourceInfo.llStopDisp < m_DataSourceInfo.llStartDisp) )
  4468. m_DataSourceInfo.llStopDisp = m_DataSourceInfo.llEndTime;
  4469. m_DataSourceInfo.nSamples = TimeInfo.SampleCount;
  4470. m_DataSourceInfo.llInterval = (m_DataSourceInfo.llEndTime - m_DataSourceInfo.llBeginTime + m_DataSourceInfo.nSamples/2) / (m_DataSourceInfo.nSamples - 1);
  4471. UpdateGraph(UPDGRPH_LOGVIEW);
  4472. }
  4473. } else {
  4474. assert ( FALSE );
  4475. hr = E_FAIL;
  4476. }
  4477. return hr;
  4478. }
  4479. HRESULT
  4480. CSysmonControl::AddSingleLogFile(
  4481. LPCTSTR pszPath,
  4482. CLogFileItem** ppLogFile )
  4483. {
  4484. HRESULT hr = NOERROR;
  4485. CLogFileItem* pLogFile = NULL;
  4486. CLogFileItem* pLocalLogFileItem = NULL;
  4487. if ( NULL != pszPath ) {
  4488. if ( NULL != ppLogFile ) {
  4489. *ppLogFile = NULL;
  4490. }
  4491. // Check to ensure that current data source is NOT log files.
  4492. if ( sysmonLogFiles == m_pObj->m_Graph.Options.iDataSourceType ) {
  4493. hr = SMON_STATUS_LOG_FILE_DATA_SOURCE;
  4494. } else {
  4495. // Check for duplicate log file name.
  4496. pLogFile = FirstLogFile();
  4497. while ( NULL != pLogFile ) {
  4498. if ( 0 == lstrcmpi ( pszPath, pLogFile->GetPath() ) ) {
  4499. hr = SMON_STATUS_DUPL_LOG_FILE_PATH;
  4500. break;
  4501. }
  4502. pLogFile = pLogFile->Next();
  4503. }
  4504. if (SUCCEEDED(hr)) {
  4505. // Create log file item
  4506. pLocalLogFileItem = new CLogFileItem ( this );
  4507. if ( NULL == pLocalLogFileItem ) {
  4508. hr = E_OUTOFMEMORY;
  4509. } else {
  4510. hr = pLocalLogFileItem->Initialize ( pszPath, &m_DataSourceInfo.pFirstLogFile );
  4511. }
  4512. // TodoLogFiles: ??? Test log file type? Or leave that up to the "SetDataSource" time?
  4513. // TodoLogFiles: Add log file type to the data source info structure
  4514. // TodoLogFiles: If allow the user to add files while data source set to log files,
  4515. // then check that condition here. If log file data source, then resample with
  4516. // new log file.
  4517. // If OK, Addref the returned interface
  4518. if (SUCCEEDED(hr)) {
  4519. // AddRef once for ourselves
  4520. pLocalLogFileItem->AddRef();
  4521. m_DataSourceInfo.lLogFileCount++;
  4522. if ( NULL != ppLogFile ) {
  4523. // AddRef the returned interface
  4524. pLocalLogFileItem->AddRef();
  4525. *ppLogFile = pLocalLogFileItem;
  4526. }
  4527. }
  4528. else {
  4529. if (pLocalLogFileItem != NULL) {
  4530. delete pLocalLogFileItem;
  4531. pLocalLogFileItem = NULL;
  4532. }
  4533. }
  4534. }
  4535. }
  4536. } else {
  4537. hr = E_INVALIDARG;
  4538. }
  4539. return hr;
  4540. }
  4541. HRESULT
  4542. CSysmonControl::RemoveSingleLogFile (
  4543. CLogFileItem* pLogFile )
  4544. {
  4545. HRESULT hr = ERROR_SUCCESS;
  4546. CLogFileItem* pNext;
  4547. CLogFileItem* pPrevious;
  4548. // Check to ensure that current data source is NOT log files.
  4549. if ( sysmonLogFiles == m_pObj->m_Graph.Options.iDataSourceType ) {
  4550. hr = SMON_STATUS_LOG_FILE_DATA_SOURCE;
  4551. } else {
  4552. pNext = FirstLogFile();
  4553. if ( pNext == pLogFile ) {
  4554. m_DataSourceInfo.pFirstLogFile = pNext->Next();
  4555. } else {
  4556. do {
  4557. pPrevious = pNext;
  4558. pNext = pNext->Next();
  4559. if ( pNext == pLogFile ) {
  4560. break;
  4561. }
  4562. } while ( NULL != pNext );
  4563. if ( NULL != pNext ) {
  4564. pPrevious->SetNext ( pNext->Next() );
  4565. } else {
  4566. // Something is wrong with the list.
  4567. assert ( FALSE );
  4568. hr = E_FAIL;
  4569. }
  4570. }
  4571. m_DataSourceInfo.lLogFileCount--;
  4572. pLogFile->Release();
  4573. }
  4574. return hr;
  4575. }
  4576. HRESULT
  4577. CSysmonControl::ProcessDataSourceType (
  4578. LPCTSTR szDataSourceName,
  4579. INT iDataSourceType )
  4580. {
  4581. HRESULT hr = NOERROR;
  4582. HQUERY hTestQuery = NULL;
  4583. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4584. HLOG hTestLog = H_REALTIME_DATASOURCE;
  4585. if ( sysmonNullDataSource != iDataSourceType ) {
  4586. // Open the new query
  4587. if (iDataSourceType == sysmonLogFiles ||
  4588. iDataSourceType == sysmonSqlLog) {
  4589. pdhStatus = PdhBindInputDataSource(& hTestLog, szDataSourceName);
  4590. }
  4591. else if (iDataSourceType == sysmonCurrentActivity) {
  4592. m_DataSourceInfo.hDataSource = H_REALTIME_DATASOURCE;
  4593. }
  4594. else {
  4595. pdhStatus = PDH_INVALID_HANDLE;
  4596. }
  4597. if (pdhStatus == ERROR_SUCCESS) {
  4598. pdhStatus = PdhOpenQueryH (hTestLog, 1, & hTestQuery );
  4599. }
  4600. }
  4601. if ( ERROR_SUCCESS != pdhStatus ) {
  4602. if ( ERROR_NOT_ENOUGH_MEMORY == pdhStatus ) {
  4603. hr = (HRESULT)SMON_STATUS_LOG_FILE_SIZE_LIMIT;
  4604. } else {
  4605. hr = (HRESULT)pdhStatus;
  4606. }
  4607. } else {
  4608. // Close the current query
  4609. CloseQuery();
  4610. // At this point, the previous query no longer exists.
  4611. // If any problems with the new query, close it and
  4612. // reset the data source to realtime.
  4613. // Set the data source type
  4614. // The previous log file name is deleted in CloseQuery()
  4615. // For sysmonNullDataSource, the current query is closed,
  4616. // and the query handle is set to NULL.
  4617. m_pObj->m_Graph.Options.iDataSourceType = iDataSourceType;
  4618. // TodoLogFiles: Eliminate use of m_bLogFileSource,
  4619. // using m_pObj->m_Graph.Options.iDataSourceType instead.
  4620. m_bLogFileSource = ( sysmonLogFiles == iDataSourceType
  4621. || sysmonSqlLog == iDataSourceType);
  4622. m_hQuery = hTestQuery;
  4623. m_DataSourceInfo.hDataSource = hTestLog;
  4624. if ( m_bLogFileSource ) {
  4625. hr = InitLogFileIntervals();
  4626. }
  4627. if ( SUCCEEDED ( hr ) && sysmonNullDataSource != iDataSourceType ) {
  4628. // Initialize the new query. For log files, this can be done after
  4629. // InitLogFileIntervals because the methods operate on different fields.
  4630. if ( ERROR_SUCCESS != InitializeQuery() ) {
  4631. hr = E_FAIL;
  4632. } else {
  4633. if ( m_fInitialized ) {
  4634. if ( ERROR_SUCCESS != ActivateQuery() )
  4635. hr = E_FAIL;
  4636. }
  4637. }
  4638. if ( SUCCEEDED ( hr ) && !m_bLogFileSource ) {
  4639. // If note log file data source, pass new time span to statistics bar.
  4640. m_pStatsBar->SetTimeSpan (
  4641. m_pObj->m_Graph.Options.fUpdateInterval
  4642. * m_pObj->m_Graph.Options.iDisplayFilter
  4643. * m_pHistCtrl->nMaxSamples);
  4644. }
  4645. }
  4646. }
  4647. if ( FAILED ( hr ) ) {
  4648. if ( sysmonLogFiles == iDataSourceType
  4649. || sysmonSqlLog == iDataSourceType )
  4650. {
  4651. // If failed with log file query, retry with realtime query.
  4652. assert ( m_bLogFileSource );
  4653. // Status returned is for the original query, not the realtime query.
  4654. // TodoLogFiles: Need to activate query?
  4655. put_DataSourceType ( sysmonCurrentActivity );
  4656. } else {
  4657. // This leaves the control in an odd state with no active query.
  4658. // TodoLogFiles: At least message to user
  4659. CloseQuery();
  4660. put_DataSourceType ( sysmonNullDataSource );
  4661. }
  4662. }
  4663. return hr;
  4664. }
  4665. HRESULT
  4666. CSysmonControl::get_DataSourceType (
  4667. eDataSourceTypeConstant& reDataSourceType )
  4668. {
  4669. HRESULT hr = NOERROR;
  4670. reDataSourceType = (eDataSourceTypeConstant)m_pObj->m_Graph.Options.iDataSourceType;
  4671. return hr;
  4672. }
  4673. HRESULT
  4674. CSysmonControl::put_DataSourceType (
  4675. INT iDataSourceType )
  4676. {
  4677. HRESULT hr = NOERROR;
  4678. DWORD dwStatus = ERROR_SUCCESS;
  4679. LPTSTR szDataSourceName = NULL;
  4680. // TodoLogFiles: Implement multi-file.
  4681. // TodoLogFiles: Use single data source name?
  4682. //
  4683. if (sysmonLogFiles == iDataSourceType) {
  4684. CLogFileItem * pLogFile = FirstLogFile();
  4685. ULONG ulListLen = 0;
  4686. if (pLogFile == NULL) {
  4687. hr = E_INVALIDARG;
  4688. }
  4689. else {
  4690. dwStatus = BuildLogFileList (
  4691. NULL,
  4692. FALSE,
  4693. &ulListLen );
  4694. szDataSourceName = (LPWSTR) malloc(ulListLen * sizeof(WCHAR));
  4695. if ( NULL != szDataSourceName ) {
  4696. dwStatus = BuildLogFileList (
  4697. szDataSourceName,
  4698. FALSE,
  4699. &ulListLen );
  4700. } else {
  4701. hr = E_OUTOFMEMORY;
  4702. }
  4703. }
  4704. }
  4705. else if (sysmonSqlLog == iDataSourceType) {
  4706. if ( m_DataSourceInfo.szSqlDsnName && m_DataSourceInfo.szSqlLogSetName ) {
  4707. if ( m_DataSourceInfo.szSqlDsnName[0] != _T('\0') && m_DataSourceInfo.szSqlLogSetName[0] != _T('\0')) {
  4708. ULONG ulLogFileNameLen = 0;
  4709. DWORD dwStatus = FormatSqlDataSourceName (
  4710. m_DataSourceInfo.szSqlDsnName,
  4711. m_DataSourceInfo.szSqlLogSetName,
  4712. NULL,
  4713. &ulLogFileNameLen );
  4714. if ( ERROR_SUCCESS == dwStatus ) {
  4715. szDataSourceName = (LPWSTR) malloc(ulLogFileNameLen * sizeof(WCHAR));
  4716. if (szDataSourceName == NULL) {
  4717. hr = E_OUTOFMEMORY;
  4718. } else {
  4719. dwStatus = FormatSqlDataSourceName (
  4720. m_DataSourceInfo.szSqlDsnName,
  4721. m_DataSourceInfo.szSqlLogSetName,
  4722. szDataSourceName,
  4723. &ulLogFileNameLen );
  4724. }
  4725. }
  4726. }
  4727. }
  4728. else {
  4729. hr = E_INVALIDARG;
  4730. }
  4731. }
  4732. if (SUCCEEDED(hr)) {
  4733. hr = ProcessDataSourceType((LPCTSTR) szDataSourceName, iDataSourceType);
  4734. }
  4735. if (szDataSourceName) {
  4736. free(szDataSourceName);
  4737. }
  4738. return hr;
  4739. }
  4740. void
  4741. CSysmonControl::IncrementVisuals (
  4742. void
  4743. )
  4744. {
  4745. // Increment the visual indices in color, width, style order
  4746. if (++m_iColorIndex >= NumStandardColorIndices()) {
  4747. m_iColorIndex = 0;
  4748. if (++m_iWidthIndex >= NumWidthIndices()) {
  4749. m_iWidthIndex = 0;
  4750. if (++m_iStyleIndex < NumStyleIndices()) {
  4751. m_iStyleIndex = 0;
  4752. }
  4753. }
  4754. }
  4755. }
  4756. void
  4757. CSysmonControl::SampleLogFile (
  4758. BOOL bViewChange
  4759. )
  4760. {
  4761. typedef struct {
  4762. PCGraphItem pItem;
  4763. double dMin;
  4764. double dMax;
  4765. double dAvg;
  4766. INT nAvgCnt;
  4767. PDH_RAW_COUNTER rawValue[1];
  4768. } LogWorkBuf, *PLogWorkBuf;
  4769. INT nCounters;
  4770. INT nLogSamples;
  4771. INT nDispSamples;
  4772. INT iNonDisp;
  4773. PCGraphItem pItem;
  4774. #define LLTIME_TICS_PER_SECOND (10000000)
  4775. // Todo: If query is null, call put_LogFileName to create it?
  4776. // Todo: Error message if m_hQuery is (still) null.
  4777. if ( NULL != m_hQuery ) {
  4778. // Determine number of counters to update
  4779. nCounters = 0;
  4780. // If log view change, we have to update all counters
  4781. if (bViewChange) {
  4782. for (pItem = FirstCounter(); pItem; pItem = pItem->Next()) {
  4783. pItem->m_bUpdateLog = TRUE;
  4784. nCounters++;
  4785. }
  4786. }
  4787. // otherwise, just any new counters
  4788. else {
  4789. for (pItem = FirstCounter(); pItem; pItem = pItem->Next()) {
  4790. if (pItem->m_bUpdateLog)
  4791. nCounters++;
  4792. }
  4793. }
  4794. // If none, nothing to do
  4795. if ( nCounters > 0) {
  4796. // Number of log samples in displayed interval
  4797. // Add 1 extra at the beginning. PdhSetQueryTimeRange returns one sample
  4798. // before the specified start time, if it exists.
  4799. // Add extra 1 because ?
  4800. if (m_DataSourceInfo.nSamples > 1) {
  4801. assert ( 0 != m_DataSourceInfo.llInterval );
  4802. nLogSamples = (INT)((m_DataSourceInfo.llStopDisp - m_DataSourceInfo.llStartDisp) / m_DataSourceInfo.llInterval) + 2;
  4803. } else {
  4804. nLogSamples = m_DataSourceInfo.nSamples;
  4805. }
  4806. // Number of display samples
  4807. nDispSamples = min(nLogSamples, m_pHistCtrl->nMaxSamples);
  4808. // Setup history control
  4809. m_pHistCtrl->nSamples = nDispSamples;
  4810. m_pHistCtrl->iCurrent = 0;
  4811. m_pHistCtrl->nBacklog = 0;
  4812. if ( nDispSamples > 1 ) {
  4813. INT nCompSamples;
  4814. INT iSampleDiff;
  4815. INT nPasses;
  4816. INT iComp;
  4817. INT iCtr;
  4818. INT iDisp;
  4819. PLogWorkBuf pWorkBuffers;
  4820. PLogWorkBuf pWorkBuf;
  4821. INT nWorkBufSize;
  4822. PDH_TIME_INFO TimeInfo;
  4823. PDH_STATISTICS Statistics;
  4824. DWORD dwCtrType;
  4825. PDH_STATUS stat;
  4826. // Number of log samples to compress to one display values
  4827. // Add an extra 1 for rate counters becuase it takes 2 raw sample to get one formatted value.
  4828. // The first sample of each buffer is ignored for non-rate counters.
  4829. nCompSamples = (nLogSamples / nDispSamples) + 1;
  4830. // Length of one work buffer
  4831. // Note that LogWorkBuf includes the first raw value so there are really nCompSamples + 1
  4832. // (an extra 1 is needed because some intervals will be one sample longer to make it
  4833. // come out even at the end (e.g. 10 samples div into 3 intervals = (3, 4, 3))
  4834. nWorkBufSize = sizeof(LogWorkBuf) + nCompSamples * sizeof(PDH_RAW_COUNTER);
  4835. // Allocate work buffers of nCompSamples samples for each counter
  4836. pWorkBuffers = (PLogWorkBuf)malloc( nCounters * nWorkBufSize);
  4837. if (pWorkBuffers == NULL)
  4838. return;
  4839. // Place selected counter item pointers in work buffers
  4840. // and init statistics
  4841. pWorkBuf = pWorkBuffers;
  4842. for (pItem = FirstCounter(); pItem; pItem = pItem->Next()) {
  4843. if (pItem->m_bUpdateLog) {
  4844. pWorkBuf->pItem = pItem;
  4845. pWorkBuf->dMin = (double)10e8;
  4846. pWorkBuf->dMax = (double)-10e8;
  4847. pWorkBuf->dAvg = 0.0;
  4848. pWorkBuf->nAvgCnt = 0;
  4849. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4850. }
  4851. }
  4852. // Set time range for pdh
  4853. TimeInfo.StartTime = m_DataSourceInfo.llStartDisp;
  4854. TimeInfo.EndTime = m_DataSourceInfo.llStopDisp;
  4855. PdhSetQueryTimeRange(m_hQuery, &TimeInfo);
  4856. iSampleDiff = nLogSamples;
  4857. for (iDisp = 0; iDisp<nDispSamples; iDisp++) {
  4858. // Do the differential calc to see if it's time for an extra sample
  4859. if ((iSampleDiff -= nDispSamples) <= 0) {
  4860. iSampleDiff += nLogSamples;
  4861. nPasses = nCompSamples;
  4862. }
  4863. else {
  4864. nPasses = nCompSamples + 1;
  4865. }
  4866. // Fill the work buffers with a set of samples
  4867. // Set bad status for sample zero first time through.
  4868. // Sample zero is only used for rate counters.
  4869. // Other passes will reuse last sample of previous pass.
  4870. iComp = 0;
  4871. if ( 0 == iDisp ) {
  4872. // Special handling for the first sample.
  4873. // Set bad status for each
  4874. pWorkBuf = pWorkBuffers;
  4875. for (iCtr=0; iCtr < nCounters; iCtr++) {
  4876. pWorkBuf->rawValue[0].CStatus = PDH_CSTATUS_INVALID_DATA;
  4877. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4878. }
  4879. // If iDisp == 0, Query the data and check the timestamp for the first raw data value.
  4880. // If that timestamp is before the official Start time, store it in buffer 0
  4881. // Otherwise, put that data in buffer 1 and skip the first sample collection of the
  4882. // regular loop below.
  4883. stat = PdhCollectQueryData(m_hQuery);
  4884. if (stat == 0) {
  4885. PDH_RAW_COUNTER rawSingleValue;
  4886. // Get a raw sample for each counter. Check the timestamp of the first counter to
  4887. // determine which buffer to use.
  4888. pWorkBuf = pWorkBuffers;
  4889. iCtr = 0;
  4890. PdhGetRawCounterValue(pWorkBuf->pItem->Handle(), &dwCtrType, &rawSingleValue);
  4891. // Increment the buffer index to 1 if the time stamp is after Start time.
  4892. // Otherwise, write the data to buffer 0, which is only used to process rate counters.
  4893. if ( *((LONGLONG*)&rawSingleValue.TimeStamp) >= m_DataSourceInfo.llStartDisp ) {
  4894. iComp = 1;
  4895. }
  4896. pWorkBuf->rawValue[iComp] = rawSingleValue;
  4897. // Increment to the next counter, and continue normal processing for the first sample,
  4898. // using iComp buffer index.
  4899. iCtr++;
  4900. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4901. for ( ; iCtr < nCounters; iCtr++) {
  4902. PdhGetRawCounterValue(pWorkBuf->pItem->Handle(), &dwCtrType, &pWorkBuf->rawValue[iComp]);
  4903. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4904. }
  4905. } // else bad status already set in 0 buffer for each counter.
  4906. }
  4907. // Only rate counter values use work buffer 0
  4908. // Buffer 0 is set to value from previous sample, except when iDisp 0, in which case it might have
  4909. // been filled in the (if 0 == iDisp) clause above.
  4910. // Skip past any special handling for the first iDisp pass above. If buffer 1 is not filled by that
  4911. // special handling, then iComp is set to 1.
  4912. iComp++;
  4913. for ( ; iComp < nPasses; iComp++) {
  4914. stat = PdhCollectQueryData(m_hQuery);
  4915. if (stat == 0) {
  4916. // Get a raw sample for each counter
  4917. pWorkBuf = pWorkBuffers;
  4918. for (iCtr = 0; iCtr < nCounters; iCtr++) {
  4919. PdhGetRawCounterValue(pWorkBuf->pItem->Handle(), &dwCtrType, &pWorkBuf->rawValue[iComp]);
  4920. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4921. }
  4922. }
  4923. else {
  4924. // Set bad status for each
  4925. pWorkBuf = pWorkBuffers;
  4926. for (iCtr=0; iCtr < nCounters; iCtr++) {
  4927. pWorkBuf->rawValue[iComp].CStatus = PDH_CSTATUS_INVALID_DATA;
  4928. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4929. }
  4930. }
  4931. }
  4932. // generate one display sample by averaging each compression buffer
  4933. pWorkBuf = pWorkBuffers;
  4934. for (iCtr=0; iCtr < nCounters; iCtr++) {
  4935. INT iPassesThisCounter;
  4936. INT iWorkBufIndex;
  4937. if ( pWorkBuf->pItem->IsRateCounter() ) {
  4938. iPassesThisCounter = nPasses;
  4939. iWorkBufIndex = 0;
  4940. } else {
  4941. // Non-rate counters do not use the first sample buffer.
  4942. iPassesThisCounter = nPasses - 1;
  4943. iWorkBufIndex = 1;
  4944. }
  4945. stat = PdhComputeCounterStatistics (pWorkBuf->pItem->Handle(), PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
  4946. 0, iPassesThisCounter, &pWorkBuf->rawValue[iWorkBufIndex], &Statistics );
  4947. if (stat == 0 && Statistics.mean.CStatus == PDH_CSTATUS_VALID_DATA) {
  4948. LONGLONG llTruncatedTimeStamp;
  4949. LONGLONG llTmpTimeStamp;
  4950. pWorkBuf->pItem->SetLogEntry(iDisp, Statistics.min.doubleValue,
  4951. Statistics.max.doubleValue,
  4952. Statistics.mean.doubleValue);
  4953. // Use the final sample timestamp. It is valid for both rates and numbers.
  4954. llTmpTimeStamp = MAKELONGLONG(
  4955. pWorkBuf->rawValue[nPasses - 1].TimeStamp.dwLowDateTime,
  4956. pWorkBuf->rawValue[nPasses - 1].TimeStamp.dwHighDateTime);
  4957. TruncateLLTime(llTmpTimeStamp, & llTruncatedTimeStamp);
  4958. pWorkBuf->pItem->SetLogEntryTimeStamp ( iDisp, *((FILETIME*)&llTruncatedTimeStamp) );
  4959. if (Statistics.max.doubleValue > pWorkBuf->dMax)
  4960. pWorkBuf->dMax = Statistics.max.doubleValue;
  4961. if (Statistics.min.doubleValue < pWorkBuf->dMin)
  4962. pWorkBuf->dMin = Statistics.min.doubleValue;
  4963. pWorkBuf->dAvg += Statistics.mean.doubleValue;
  4964. pWorkBuf->nAvgCnt++;
  4965. }
  4966. else {
  4967. pWorkBuf->pItem->SetLogEntry(iDisp, -1.0, -1.0, -1.0);
  4968. }
  4969. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4970. }
  4971. // If a rate counter, move last sample to first sample
  4972. // for next compress interval
  4973. pWorkBuf = pWorkBuffers;
  4974. for (iCtr=0; iCtr < nCounters; iCtr++) {
  4975. if ( pWorkBuf->pItem->IsRateCounter() ) {
  4976. pWorkBuf->rawValue[0] = pWorkBuf->rawValue[nPasses-1];
  4977. }
  4978. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4979. }
  4980. }
  4981. // Set the log statistics for empty samples.
  4982. for (iNonDisp = nDispSamples; iNonDisp<m_pHistCtrl->nMaxSamples; iNonDisp++) {
  4983. pWorkBuf = pWorkBuffers;
  4984. for (iCtr=0; iCtr < nCounters; iCtr++) {
  4985. pWorkBuf->pItem->SetLogEntry(iNonDisp, -1.0, -1.0, -1.0);
  4986. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4987. }
  4988. }
  4989. // Store the final statistics and clear the update flags
  4990. pWorkBuf = pWorkBuffers;
  4991. for (iCtr=0; iCtr < nCounters; iCtr++) {
  4992. pWorkBuf->pItem->m_bUpdateLog = FALSE;
  4993. if (pWorkBuf->nAvgCnt)
  4994. pWorkBuf->dAvg /= pWorkBuf->nAvgCnt;
  4995. pWorkBuf->pItem->SetLogStats(pWorkBuf->dMin, pWorkBuf->dMax, pWorkBuf->dAvg);
  4996. pWorkBuf = (PLogWorkBuf)((CHAR*)pWorkBuf + nWorkBufSize);
  4997. }
  4998. // Free the work buffers
  4999. free(pWorkBuffers);
  5000. } else {
  5001. // No data to display. Clear the history buffers by setting all status to Invalid.
  5002. for (pItem = FirstCounter(); pItem; pItem = pItem->Next()) {
  5003. for (iNonDisp = 0; iNonDisp < m_pHistCtrl->nMaxSamples; iNonDisp++) {
  5004. pItem->SetLogEntry(iNonDisp, -1.0, -1.0, -1.0);
  5005. }
  5006. }
  5007. }
  5008. // Update statistics bar
  5009. m_pStatsBar->SetTimeSpan((double)(m_DataSourceInfo.llStopDisp - m_DataSourceInfo.llStartDisp) / LLTIME_TICS_PER_SECOND);
  5010. m_pStatsBar->Update(NULL, m_pSelectedItem);
  5011. }
  5012. }
  5013. }
  5014. void
  5015. CSysmonControl::CalcZoomFactor ( void )
  5016. {
  5017. RECT rectPos;
  5018. RECT rectExtent;
  5019. double dHeightPos;
  5020. double dHeightExtent;
  5021. // Calculate zoom factor based on height.
  5022. // The Zoom calculation is prcPos (set by container) divided by the extent.
  5023. // See technical note 40 - TN040.
  5024. rectExtent = m_pObj->m_RectExt;
  5025. GetClientRect ( m_hWnd, &rectPos );
  5026. dHeightPos = rectPos.bottom - rectPos.top;
  5027. dHeightExtent = rectExtent.bottom - rectExtent.top;
  5028. m_dZoomFactor = ( dHeightPos ) / ( dHeightExtent );
  5029. }
  5030. BOOL
  5031. CSysmonControl::DisplayMissedSampleMessage ( void )
  5032. {
  5033. BOOL bDisplay = FALSE;
  5034. bDisplay = m_bMissedSample ;
  5035. if ( bDisplay ) {
  5036. // Missed at least one sample in this session.
  5037. // Display the message only once per session.
  5038. if ( m_bDisplayedMissedSampleMessage ) {
  5039. bDisplay = FALSE;
  5040. } else {
  5041. m_bDisplayedMissedSampleMessage = TRUE;
  5042. }
  5043. }
  5044. return bDisplay;
  5045. }
  5046. void
  5047. CSysmonControl::ResetLogViewTempTimeRange ()
  5048. /*++
  5049. Routine Description:
  5050. Reset the log view temporary time range steppers to the ends of the visible
  5051. part of the log file.
  5052. Arguments:
  5053. Return Value:
  5054. --*/
  5055. {
  5056. assert ( IsLogSource() );
  5057. if ( IsLogSource() ) {
  5058. INT iNewStopStepNum = 0;
  5059. m_pObj->m_Graph.LogViewStartStepper.Reset();
  5060. m_pObj->m_Graph.LogViewStopStepper.Reset();
  5061. if ( FirstCounter() ) {
  5062. GetNewLogViewStepNum( m_DataSourceInfo.llStopDisp, iNewStopStepNum );
  5063. m_pObj->m_Graph.LogViewStopStepper.StepTo( iNewStopStepNum );
  5064. }
  5065. }
  5066. }
  5067. void
  5068. CSysmonControl::FindNextValidStepNum (
  5069. BOOL bDecrease,
  5070. PCGraphItem pItem,
  5071. LONGLONG llNewTime,
  5072. INT& riNewStepNum,
  5073. DWORD& rdwStatus )
  5074. {
  5075. DWORD dwPdhStatus = ERROR_SUCCESS;
  5076. DWORD dwLocalStatus = ERROR_SUCCESS;
  5077. LONGLONG llNextTimeStamp = 0;
  5078. INT iLocalStepNum;
  5079. INT iTempLocalStepNum;
  5080. assert ( NULL != pItem );
  5081. if ( NULL != pItem ) {
  5082. iLocalStepNum = riNewStepNum;
  5083. iTempLocalStepNum = iLocalStepNum;
  5084. dwLocalStatus = rdwStatus;
  5085. if ( bDecrease ) {
  5086. // Start by decreasing steps to find first valid step.
  5087. while ( ( ERROR_SUCCESS == dwPdhStatus )
  5088. && ( ERROR_SUCCESS != dwLocalStatus )
  5089. && ( iLocalStepNum > 0 ) ) {
  5090. iTempLocalStepNum = iLocalStepNum;
  5091. iTempLocalStepNum--;
  5092. dwPdhStatus = pItem->GetLogEntryTimeStamp( iTempLocalStepNum, llNextTimeStamp, &dwLocalStatus );
  5093. iLocalStepNum = iTempLocalStepNum;
  5094. }
  5095. // Subtract 1 from nSamples because stepper is 0-based,
  5096. while ( ( ERROR_SUCCESS == dwPdhStatus )
  5097. && ( ERROR_SUCCESS != dwLocalStatus )
  5098. && ( iLocalStepNum < m_pHistCtrl->nSamples - 1 ) ) {
  5099. iTempLocalStepNum++;
  5100. dwPdhStatus = pItem->GetLogEntryTimeStamp( iTempLocalStepNum, llNextTimeStamp, &dwLocalStatus );
  5101. iLocalStepNum = iTempLocalStepNum;
  5102. }
  5103. } else {
  5104. // Start by increasing steps to find first valid step.
  5105. // Subtract 1 from nSamples because stepper is 0-based,
  5106. while ( ( ERROR_SUCCESS == dwPdhStatus )
  5107. && ( ERROR_SUCCESS != dwLocalStatus )
  5108. && ( iLocalStepNum < m_pHistCtrl->nSamples - 1 ) ) {
  5109. iTempLocalStepNum++;
  5110. dwPdhStatus = pItem->GetLogEntryTimeStamp( iTempLocalStepNum, llNextTimeStamp, &dwLocalStatus );
  5111. iLocalStepNum = iTempLocalStepNum;
  5112. }
  5113. while ( ( ERROR_SUCCESS == dwPdhStatus )
  5114. && ( ERROR_SUCCESS != dwLocalStatus )
  5115. && ( iLocalStepNum > 0 ) ) {
  5116. iTempLocalStepNum = iLocalStepNum;
  5117. iTempLocalStepNum--;
  5118. dwPdhStatus = pItem->GetLogEntryTimeStamp( iTempLocalStepNum, llNextTimeStamp, &dwLocalStatus );
  5119. iLocalStepNum = iTempLocalStepNum;
  5120. }
  5121. }
  5122. if ( ERROR_SUCCESS == dwLocalStatus ) {
  5123. riNewStepNum = iLocalStepNum;
  5124. llNewTime = llNextTimeStamp;
  5125. rdwStatus = dwLocalStatus;
  5126. }
  5127. }
  5128. return;
  5129. }
  5130. void
  5131. CSysmonControl::GetNewLogViewStepNum (
  5132. LONGLONG llNewTime,
  5133. INT& riNewStepNum )
  5134. /*++
  5135. Routine Description:
  5136. Given the new time and original stepnum, find the stepnum that matches
  5137. the new time.
  5138. Arguments:
  5139. llNewTime New time stamp to match
  5140. riNewStepNum (IN) Current step num
  5141. (OUT) Step num that matches the new time stamp.
  5142. Return Value:
  5143. --*/
  5144. {
  5145. PCGraphItem pItem = NULL;
  5146. LONGLONG llNextTimeStamp = 0;
  5147. PDH_STATUS dwPdhStatus = ERROR_SUCCESS;
  5148. DWORD dwStatus = ERROR_SUCCESS;
  5149. INT iLocalStepNum = 0;
  5150. assert ( IsLogSource() );
  5151. iLocalStepNum = riNewStepNum;
  5152. // Check only the first counter for log file time stamp data.
  5153. pItem = FirstCounter();
  5154. if ( NULL != pItem ) {
  5155. dwPdhStatus = pItem->GetLogEntryTimeStamp( iLocalStepNum, llNextTimeStamp, &dwStatus );
  5156. // If the stepper is positioned on a sample with bad status,
  5157. // move n steps in either direction to find a valid sample to start with.
  5158. if ( ( ERROR_SUCCESS == dwPdhStatus ) && ( ERROR_SUCCESS != dwStatus ) ) {
  5159. FindNextValidStepNum ( FALSE, pItem, llNextTimeStamp, iLocalStepNum, dwStatus );
  5160. }
  5161. if ( ERROR_SUCCESS == dwStatus ) {
  5162. if ( ( llNewTime < llNextTimeStamp ) || ( MAX_TIME_VALUE == llNextTimeStamp ) ) {
  5163. while ( iLocalStepNum > 0 ) {
  5164. iLocalStepNum--;
  5165. pItem->GetLogEntryTimeStamp( iLocalStepNum, llNextTimeStamp, &dwStatus );
  5166. if ( ERROR_SUCCESS == dwStatus ) {
  5167. if ( llNewTime == llNextTimeStamp ) {
  5168. break;
  5169. } else if ( llNewTime > llNextTimeStamp ) {
  5170. iLocalStepNum++;
  5171. break;
  5172. }
  5173. }
  5174. }
  5175. } else if ( llNewTime > llNextTimeStamp ) {
  5176. // Subtract 1 from nSamples because stepper is 0-based,
  5177. while ( iLocalStepNum < m_pHistCtrl->nSamples - 1 ) {
  5178. iLocalStepNum++;
  5179. pItem->GetLogEntryTimeStamp( iLocalStepNum, llNextTimeStamp, &dwStatus );
  5180. if ( ERROR_SUCCESS == dwStatus ) {
  5181. if ( llNewTime <= llNextTimeStamp ) {
  5182. break;
  5183. }
  5184. }
  5185. }
  5186. }
  5187. riNewStepNum = iLocalStepNum;
  5188. } // else if NO valid samples, leave the start/stop time stepper where it is.
  5189. } // Non-null FirstCounter()
  5190. return;
  5191. }
  5192. void
  5193. CSysmonControl::SetLogViewTempTimeRange (
  5194. LONGLONG llStart,
  5195. LONGLONG llStop
  5196. )
  5197. /*++
  5198. Routine Description:
  5199. Set the log view temporary time range. This routine provides the Source
  5200. property page a way to give range to the control, so that the control
  5201. can draw temporary timeline guides on the line graph.
  5202. Arguments:
  5203. llStart Temporary log view start time (FILETIME format)
  5204. llEnd Temporary log view end time (FILETIME format)
  5205. Return Value:
  5206. --*/
  5207. {
  5208. assert ( llStart <= llStop );
  5209. if ( IsLogSource() ) {
  5210. INT iNewStepNum;
  5211. // No time range to modify if no counters selected.
  5212. if ( NULL != FirstCounter() ) {
  5213. // Start/Stop time range bars are turned off if llStart and llStop are set
  5214. // to MIN and MAX values, so no need to update steppers.
  5215. if ( MIN_TIME_VALUE != llStart ) {
  5216. // Search through sample values to find the appropriate step for the start bar.
  5217. if ( llStart != m_pObj->m_Graph.LogViewTempStart ) {
  5218. // Start with current position.
  5219. iNewStepNum = m_pObj->m_Graph.LogViewStartStepper.StepNum();
  5220. GetNewLogViewStepNum ( llStart, iNewStepNum );
  5221. if ( iNewStepNum != m_pObj->m_Graph.LogViewStartStepper.StepNum() ) {
  5222. m_pObj->m_Graph.LogViewStartStepper.StepTo ( iNewStepNum );
  5223. }
  5224. }
  5225. }
  5226. if ( MAX_TIME_VALUE != llStop ) {
  5227. // Search through sample values to find the appropriate step for the stop bar.
  5228. if ( llStop != m_pObj->m_Graph.LogViewTempStop ) {
  5229. // Start with current position.
  5230. iNewStepNum = m_pObj->m_Graph.LogViewStopStepper.StepNum();
  5231. GetNewLogViewStepNum ( llStop, iNewStepNum );
  5232. if ( iNewStepNum != m_pObj->m_Graph.LogViewStopStepper.StepNum() ) {
  5233. m_pObj->m_Graph.LogViewStopStepper.StepTo ( iNewStepNum );
  5234. }
  5235. }
  5236. }
  5237. }
  5238. }
  5239. if ( ( m_pObj->m_Graph.LogViewTempStart != llStart )
  5240. || ( m_pObj->m_Graph.LogViewTempStop != llStop ) ) {
  5241. m_pObj->m_Graph.LogViewTempStart = llStart;
  5242. m_pObj->m_Graph.LogViewTempStop = llStop;
  5243. if ( sysmonLineGraph == m_pObj->m_Graph.Options.iDisplayType ) {
  5244. // Cause redraw
  5245. UpdateGraph(UPDGRPH_PLOT);
  5246. }
  5247. }
  5248. }
  5249. PRECT
  5250. CSysmonControl::GetNewClientRect ( void )
  5251. {
  5252. return &m_pObj->m_RectExt;
  5253. }
  5254. PRECT
  5255. CSysmonControl::GetCurrentClientRect ( void )
  5256. {
  5257. return &m_rectCurrentClient;
  5258. }
  5259. void
  5260. CSysmonControl::SetCurrentClientRect ( PRECT prectNew )
  5261. {
  5262. m_rectCurrentClient = *prectNew;
  5263. }
  5264. void
  5265. CSysmonControl::UpdateNonAmbientSysColors ( void )
  5266. {
  5267. HRESULT hr;
  5268. COLORREF newColor;
  5269. PGRAPH_OPTIONS pOptions = &m_pObj->m_Graph.Options;
  5270. hr = OleTranslateColor(pOptions->clrBackCtl, NULL, &newColor);
  5271. if ( SUCCEEDED( hr ) ) {
  5272. m_clrBackCtl = newColor;
  5273. }
  5274. if (pOptions->clrBackPlot != NULL_COLOR) {
  5275. hr = OleTranslateColor(pOptions->clrBackPlot, NULL, &newColor);
  5276. if ( SUCCEEDED( hr ) ) {
  5277. m_clrBackPlot = newColor;
  5278. }
  5279. }
  5280. if (pOptions->clrFore != NULL_COLOR) {
  5281. hr = OleTranslateColor(pOptions->clrFore, NULL, &newColor);
  5282. if ( SUCCEEDED( hr ) ) {
  5283. m_clrFgnd = newColor;
  5284. }
  5285. }
  5286. hr = OleTranslateColor(pOptions->clrGrid, NULL, &newColor);
  5287. if ( SUCCEEDED( hr ) ) {
  5288. m_clrGrid = newColor;
  5289. }
  5290. hr = OleTranslateColor(pOptions->clrTimeBar, NULL, &newColor);
  5291. if ( SUCCEEDED( hr ) ) {
  5292. m_clrTimeBar = newColor;
  5293. }
  5294. }
  5295. LPCTSTR
  5296. CSysmonControl::GetDataSourceName ( void )
  5297. {
  5298. LPTSTR szReturn = NULL;
  5299. CLogFileItem* pLogFile = NULL;
  5300. if ( sysmonLogFiles == m_pObj->m_Graph.Options.iDataSourceType ) {
  5301. pLogFile = FirstLogFile();
  5302. if ( NULL != pLogFile ) {
  5303. szReturn = const_cast<LPTSTR>((LPCTSTR)pLogFile->GetPath());
  5304. }
  5305. }
  5306. // TodoLogFiles: Use the m_DataSourceInfo.szDataSourceName field? When multi-file?
  5307. return szReturn;
  5308. }
  5309. HRESULT
  5310. CSysmonControl::GetSelectedCounter ( CGraphItem** ppItem )
  5311. {
  5312. HRESULT hr = E_POINTER;
  5313. if ( NULL != ppItem ) {
  5314. *ppItem = m_pSelectedItem;
  5315. hr = NOERROR;
  5316. }
  5317. return hr;
  5318. }
  5319. DWORD
  5320. CSysmonControl::BuildLogFileList (
  5321. LPWSTR szLogFileList,
  5322. BOOL bIsCommaDelimiter,
  5323. ULONG* pulBufLen )
  5324. {
  5325. DWORD dwStatus = ERROR_SUCCESS;
  5326. ULONG ulListLen;
  5327. CLogFileItem* pLogFile = FirstLogFile();
  5328. LPCWSTR szThisLogFile = NULL;
  5329. LPWSTR szLogFileCurrent = NULL;
  5330. const WCHAR cwComma = L',';
  5331. if ( NULL != pulBufLen ) {
  5332. ulListLen = 0;
  5333. while (pLogFile != NULL) {
  5334. szThisLogFile= pLogFile->GetPath();
  5335. ulListLen += (lstrlen(szThisLogFile) + 1);
  5336. pLogFile = pLogFile->Next();
  5337. }
  5338. ulListLen ++; // for the single final NULL character.
  5339. if ( ulListLen <= *pulBufLen ) {
  5340. if ( NULL != szLogFileList ) {
  5341. ZeroMemory(szLogFileList, (ulListLen * sizeof(WCHAR)));
  5342. pLogFile = FirstLogFile();
  5343. szLogFileCurrent = (LPTSTR) szLogFileList;
  5344. while (pLogFile != NULL) {
  5345. szThisLogFile = pLogFile->GetPath();
  5346. lstrcpy(szLogFileCurrent, szThisLogFile);
  5347. szLogFileCurrent += lstrlen(szThisLogFile);
  5348. *szLogFileCurrent = L'\0';
  5349. pLogFile = pLogFile->Next();
  5350. if ( bIsCommaDelimiter && NULL != pLogFile ) {
  5351. // If comma delimited, replace the NULL char with a comma
  5352. *szLogFileCurrent = cwComma;
  5353. }
  5354. szLogFileCurrent ++;
  5355. }
  5356. if ( !bIsCommaDelimiter ) {
  5357. *szLogFileCurrent = L'\0';
  5358. }
  5359. }
  5360. } else if ( NULL != szLogFileList ) {
  5361. dwStatus = ERROR_MORE_DATA;
  5362. }
  5363. *pulBufLen = ulListLen;
  5364. } else {
  5365. dwStatus = ERROR_INVALID_PARAMETER;
  5366. assert ( FALSE );
  5367. }
  5368. return dwStatus;
  5369. }
  5370. HRESULT
  5371. CSysmonControl::LoadLogFilesFromMultiSz (
  5372. LPCWSTR szLogFileList )
  5373. {
  5374. HRESULT hr = NOERROR;
  5375. LPWSTR szNext = NULL;
  5376. szNext = const_cast<LPWSTR>(szLogFileList);
  5377. while ( NULL != szNext ) {
  5378. hr = AddSingleLogFile ( szNext );
  5379. if ( FAILED ( hr ) ) {
  5380. break;
  5381. }
  5382. szNext += lstrlen (szNext) + 1;
  5383. }
  5384. return hr;
  5385. }
  5386. void
  5387. CSysmonControl::ClearErrorPathList ( void )
  5388. {
  5389. if ( NULL != m_szErrorPathList ) {
  5390. delete m_szErrorPathList;
  5391. }
  5392. m_szErrorPathList = NULL;
  5393. m_dwErrorPathListLen = 0;
  5394. m_dwErrorPathBufLen = 0;
  5395. }
  5396. LPCWSTR
  5397. CSysmonControl::GetErrorPathList ( DWORD* pdwListLen )
  5398. {
  5399. if ( NULL != pdwListLen ) {
  5400. *pdwListLen = m_dwErrorPathListLen;
  5401. }
  5402. return m_szErrorPathList;
  5403. }
  5404. DWORD
  5405. CSysmonControl::AddToErrorPathList ( LPCWSTR szPath )
  5406. {
  5407. DWORD dwStatus = ERROR_SUCCESS;
  5408. DWORD dwPathLen = 0;
  5409. LPWSTR szNewBuffer = NULL;
  5410. LPWSTR szNextCounter = NULL;
  5411. const LPCWSTR cszNewLine = L"\n";
  5412. const DWORD cdwAddLen = 2048;
  5413. if ( NULL != szPath ) {
  5414. dwPathLen = lstrlen ( szPath );
  5415. if ( cdwAddLen > dwPathLen ) {
  5416. if ( m_dwErrorPathBufLen < m_dwErrorPathListLen + dwPathLen + 1 ) {
  5417. m_dwErrorPathBufLen += cdwAddLen;
  5418. szNewBuffer = new WCHAR[m_dwErrorPathBufLen];
  5419. if ( NULL != szNewBuffer ) {
  5420. if ( NULL != m_szErrorPathList ) {
  5421. memcpy ( szNewBuffer, m_szErrorPathList, m_dwErrorPathListLen * sizeof(WCHAR) );
  5422. delete m_szErrorPathList;
  5423. }
  5424. m_szErrorPathList = szNewBuffer;
  5425. } else {
  5426. dwStatus = ERROR_OUTOFMEMORY;
  5427. }
  5428. }
  5429. if ( ERROR_SUCCESS == dwStatus ) {
  5430. // Point to ending null character.
  5431. szNextCounter = m_szErrorPathList;
  5432. if ( 0 < m_dwErrorPathListLen ) {
  5433. szNextCounter += m_dwErrorPathListLen - 1;
  5434. }
  5435. if ( 0 == m_dwErrorPathListLen ) {
  5436. //Increment first counter length for the ending null character.
  5437. m_dwErrorPathListLen++;
  5438. } else {
  5439. memcpy ( szNextCounter, cszNewLine, sizeof(cszNewLine) );
  5440. szNextCounter++;
  5441. m_dwErrorPathListLen++; // Increment 1 for the comma
  5442. }
  5443. lstrcpy ( szNextCounter, szPath );
  5444. m_dwErrorPathListLen += dwPathLen;
  5445. }
  5446. } else {
  5447. dwStatus = ERROR_INVALID_PARAMETER;
  5448. }
  5449. } else {
  5450. dwStatus = ERROR_INVALID_PARAMETER;
  5451. }
  5452. return dwStatus;
  5453. }