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.

710 lines
20 KiB

  1. /*---------------------------------------------------------------------------
  2. File: AgentMonitorDlg.cpp
  3. Comments: This dialog shows a list of the computers the agent is being dispatched to
  4. along with their status.
  5. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  6. Proprietary and confidential to Mission Critical Software, Inc.
  7. REVISION LOG ENTRY
  8. Revision By: Christy Boles
  9. ---------------------------------------------------------------------------
  10. */// AgentMonitorDlg.cpp : implementation file
  11. //
  12. #include "stdafx.h"
  13. #include "resource.h"
  14. #include "MonDlg.h"
  15. #include "DetDlg.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #include "Common.hpp"
  22. #include "UString.hpp"
  23. #include "TNode.hpp"
  24. #include "ServList.hpp"
  25. #include "Monitor.h"
  26. #include "Globals.h"
  27. #include "ResStr.h"
  28. #include <htmlhelp.h>
  29. #include "helpid.h"
  30. #define COLUMN_COMPUTER 0
  31. #define COLUMN_TIMESTAMP 1
  32. #define COLUMN_STATUS 2
  33. #define COLUMN_MESSAGE 3
  34. #define SORT_COLUMN_BITS 0x03
  35. #define SORT_REVERSE 0x80000000
  36. BOOL bWaiting = FALSE;
  37. // This is the sort function for the CListView
  38. int CALLBACK SortFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  39. {
  40. int result = 0;
  41. TServerNode * n1 = (TServerNode*)lParam1;
  42. TServerNode * n2 = (TServerNode*)lParam2;
  43. if ( n1 && n2 )
  44. {
  45. switch ( lParamSort & SORT_COLUMN_BITS )
  46. {
  47. case COLUMN_COMPUTER:
  48. // Sort by names
  49. result = UStrICmp(n1->GetServer(),n2->GetServer());
  50. break;
  51. case COLUMN_TIMESTAMP:
  52. result = UStrICmp(n1->GetTimeStamp(),n2->GetTimeStamp());
  53. break;
  54. case COLUMN_STATUS:
  55. if ( n1->GetStatus() == n2->GetStatus() )
  56. result = 0;
  57. else if ( n1->GetStatus() < n2->GetStatus() )
  58. result = -1;
  59. else
  60. result = 1;
  61. break;
  62. case COLUMN_MESSAGE:
  63. result = UStrICmp(n1->GetMessageText(),n2->GetMessageText());
  64. break;
  65. default:
  66. MCSVERIFY(FALSE);
  67. break;
  68. }
  69. }
  70. if ( lParamSort & SORT_REVERSE )
  71. {
  72. result *= -1;
  73. }
  74. return result;
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CAgentMonitorDlg dialog
  78. CAgentMonitorDlg::CAgentMonitorDlg(CWnd* pParent /*=NULL*/)
  79. : CPropertyPage(CAgentMonitorDlg::IDD)
  80. {
  81. //{{AFX_DATA_INIT(CAgentMonitorDlg)
  82. //}}AFX_DATA_INIT
  83. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  84. m_SortColumn = 0;
  85. m_bReverseSort = FALSE;
  86. m_bSecTrans = TRUE;
  87. m_bReporting = FALSE;
  88. }
  89. void CAgentMonitorDlg::DoDataExchange(CDataExchange* pDX)
  90. {
  91. CPropertyPage::DoDataExchange(pDX);
  92. //{{AFX_DATA_MAP(CAgentMonitorDlg)
  93. DDX_Control(pDX, IDC_DETAILS, m_DetailsButton);
  94. DDX_Control(pDX, IDC_SERVERLIST, m_ServerList);
  95. //}}AFX_DATA_MAP
  96. }
  97. BEGIN_MESSAGE_MAP(CAgentMonitorDlg, CPropertyPage)
  98. //{{AFX_MSG_MAP(CAgentMonitorDlg)
  99. ON_WM_SYSCOMMAND()
  100. ON_WM_PAINT()
  101. ON_WM_QUERYDRAGICON()
  102. ON_NOTIFY(NM_DBLCLK, IDC_SERVERLIST, OnDblclkServerlist)
  103. ON_BN_CLICKED(IDC_VIEW_DISPATCH, OnViewDispatch)
  104. ON_BN_CLICKED(IDC_DETAILS, OnDetails)
  105. ON_NOTIFY(LVN_COLUMNCLICK, IDC_SERVERLIST, OnColumnclickServerlist)
  106. ON_NOTIFY(NM_CLICK, IDC_SERVERLIST, OnClickServerlist)
  107. ON_NOTIFY(LVN_GETDISPINFO, IDC_SERVERLIST, OnGetdispinfoServerlist)
  108. ON_NOTIFY(LVN_SETDISPINFO, IDC_SERVERLIST, OnSetdispinfoServerlist)
  109. ON_NOTIFY(HDN_ITEMCLICK, IDC_SERVERLIST, OnHeaderItemClickServerlist)
  110. ON_WM_HELPINFO()
  111. //}}AFX_MSG_MAP
  112. ON_MESSAGE(DCT_UPDATE_ENTRY, OnUpdateServerEntry)
  113. ON_MESSAGE(DCT_ERROR_ENTRY, OnServerError)
  114. END_MESSAGE_MAP()
  115. /////////////////////////////////////////////////////////////////////////////
  116. // CAgentMonitorDlg message handlers
  117. BOOL CAgentMonitorDlg::OnInitDialog()
  118. {
  119. CPropertyPage::OnInitDialog();
  120. // Setup the columns for the server list
  121. CString heading;
  122. heading.LoadString(IDS_ComputerColumnHeading);
  123. m_ServerList.InsertColumn(COLUMN_COMPUTER,heading,LVCFMT_LEFT,120);
  124. heading.LoadString(IDS_TimestampColumnHeading);
  125. m_ServerList.InsertColumn(COLUMN_TIMESTAMP,heading,LVCFMT_LEFT,120);
  126. heading.LoadString(IDS_StatusColumnHeading);
  127. m_ServerList.InsertColumn(COLUMN_STATUS,heading,LVCFMT_LEFT,120);
  128. heading.LoadString(IDS_MessageColumnHeading);
  129. m_ServerList.InsertColumn(COLUMN_MESSAGE,heading,LVCFMT_LEFT,200);
  130. // Read the server list to get any information we may have missed so far
  131. TNodeListEnum e;
  132. TServerList * pServerList = gData.GetUnsafeServerList();
  133. TServerNode * pServer;
  134. gData.Lock();
  135. for ( pServer = (TServerNode *)e.OpenFirst(pServerList) ; pServer ; pServer = (TServerNode *)e.Next() )
  136. {
  137. if ( pServer->Include() )
  138. {
  139. // OnUpdateServerEntry(0,(long)pServer);
  140. OnUpdateServerEntry(0,(LPARAM)pServer);
  141. }
  142. }
  143. e.Close();
  144. gData.Unlock();
  145. gData.SetListWindow(m_hWnd);
  146. m_DetailsButton.EnableWindow(m_ServerList.GetSelectedCount());
  147. CString str;
  148. str.LoadString(IDS_WaitingMessage);
  149. m_ServerList.InsertItem(0,str);
  150. bWaiting = TRUE;
  151. return TRUE; // return TRUE unless you set the focus to a control
  152. }
  153. void CAgentMonitorDlg::OnSysCommand(UINT nID, LPARAM lParam)
  154. {
  155. CPropertyPage::OnSysCommand(nID, lParam);
  156. }
  157. // If you add a minimize button to your dialog, you will need the code below
  158. // to draw the icon. For MFC applications using the document/view model,
  159. // this is automatically done for you by the framework.
  160. void CAgentMonitorDlg::OnPaint()
  161. {
  162. if (IsIconic())
  163. {
  164. CPaintDC dc(this); // device context for painting
  165. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  166. // Center icon in client rectangle
  167. int cxIcon = GetSystemMetrics(SM_CXICON);
  168. int cyIcon = GetSystemMetrics(SM_CYICON);
  169. CRect rect;
  170. GetClientRect(&rect);
  171. int x = (rect.Width() - cxIcon + 1) / 2;
  172. int y = (rect.Height() - cyIcon + 1) / 2;
  173. // Draw the icon
  174. dc.DrawIcon(x, y, m_hIcon);
  175. }
  176. else
  177. {
  178. CPropertyPage::OnPaint();
  179. }
  180. }
  181. // The system calls this to obtain the cursor to display while the user drags
  182. // the minimized window.
  183. HCURSOR CAgentMonitorDlg::OnQueryDragIcon()
  184. {
  185. return (HCURSOR) m_hIcon;
  186. }
  187. //LRESULT CAgentMonitorDlg::OnUpdateServerEntry(UINT nID, long x)
  188. LRESULT CAgentMonitorDlg::OnUpdateServerEntry(UINT nID, LPARAM x)
  189. {
  190. TServerNode * pNode = (TServerNode *)x;
  191. LVFINDINFO findInfo;
  192. CString timestamp;
  193. CWaitCursor w;
  194. memset(&findInfo,0,(sizeof findInfo));
  195. // This turns off the initial hourglass in the dispatch monitor
  196. if ( bWaiting )
  197. {
  198. if ( pNode )
  199. {
  200. AfxGetApp()->DoWaitCursor(-1);
  201. if ( m_ServerList.GetItemCount() == 1 )
  202. {
  203. m_ServerList.DeleteItem(0);
  204. }
  205. }
  206. else
  207. {
  208. BOOL bLDone;
  209. gData.GetLogDone(&bLDone);
  210. if ( bLDone )
  211. {
  212. AfxGetApp()->DoWaitCursor(-1);
  213. if ( m_ServerList.GetItemCount() == 1 )
  214. {
  215. m_ServerList.DeleteItem(0);
  216. CString str;
  217. str.LoadString(IDS_NoServersMessage);
  218. m_ServerList.InsertItem(0,str);
  219. }
  220. }
  221. }
  222. }
  223. bWaiting = FALSE;
  224. if ( pNode )
  225. {
  226. findInfo.flags = LVFI_STRING;
  227. findInfo.psz = pNode->GetServer();
  228. int ndx = m_ServerList.FindItem(&findInfo);
  229. if ( ndx == -1 )
  230. {
  231. // add the server to the list
  232. ndx = m_ServerList.GetItemCount();
  233. // m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(long)pNode);
  234. m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(LPARAM)pNode);
  235. if ( m_bReverseSort )
  236. {
  237. m_ServerList.SortItems(&SortFunction,m_SortColumn | SORT_REVERSE);
  238. }
  239. else
  240. {
  241. m_ServerList.SortItems(&SortFunction,m_SortColumn);
  242. }
  243. }
  244. m_ServerList.RedrawItems(ndx,ndx);
  245. }
  246. return 0;
  247. }
  248. //LRESULT CAgentMonitorDlg::OnServerError(UINT nID, long x)
  249. LRESULT CAgentMonitorDlg::OnServerError(UINT nID, LPARAM x)
  250. {
  251. TServerNode * pNode = (TServerNode *)x;
  252. LVFINDINFO findInfo;
  253. CString timestamp;
  254. CWaitCursor w;
  255. memset(&findInfo,0,(sizeof findInfo));
  256. // This turns off the initial hourglass in the dispatch monitor
  257. if ( bWaiting )
  258. {
  259. if ( pNode )
  260. {
  261. AfxGetApp()->DoWaitCursor(-1);
  262. if ( m_ServerList.GetItemCount() == 1 )
  263. {
  264. m_ServerList.DeleteItem(0);
  265. }
  266. }
  267. else
  268. {
  269. BOOL bLDone;
  270. gData.GetLogDone(&bLDone);
  271. if ( bLDone )
  272. {
  273. AfxGetApp()->DoWaitCursor(-1);
  274. if ( m_ServerList.GetItemCount() == 1 )
  275. {
  276. m_ServerList.DeleteItem(0);
  277. CString str;
  278. str.LoadString(IDS_NoServersMessage);
  279. m_ServerList.InsertItem(0,str);
  280. }
  281. }
  282. }
  283. }
  284. bWaiting = FALSE;
  285. findInfo.flags = LVFI_STRING;
  286. findInfo.psz = pNode->GetServer();
  287. int ndx = m_ServerList.FindItem(&findInfo);
  288. if ( ndx == -1 )
  289. {
  290. // add the server to the list
  291. ndx = m_ServerList.GetItemCount();
  292. // m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(long)pNode);
  293. m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(LPARAM)pNode);
  294. if ( m_bReverseSort )
  295. {
  296. m_ServerList.SortItems(&SortFunction,m_SortColumn | SORT_REVERSE);
  297. }
  298. else
  299. {
  300. m_ServerList.SortItems(&SortFunction,m_SortColumn);
  301. }
  302. }
  303. timestamp = pNode->GetTimeStamp();
  304. if ( timestamp.Right(1) == "\n" )
  305. {
  306. timestamp = timestamp.Left(timestamp.GetLength() - 1);
  307. }
  308. // the subitems will be callbacks
  309. m_ServerList.RedrawItems(ndx,ndx);
  310. return 0;
  311. }
  312. void CAgentMonitorDlg::OnDblclkServerlist(NMHDR* pNMHDR, LRESULT* pResult)
  313. {
  314. OnDetails();
  315. *pResult = 0;
  316. }
  317. void CAgentMonitorDlg::OnViewDispatch()
  318. {
  319. WCHAR filename[MAX_PATH];
  320. CString cmd;
  321. STARTUPINFO startupInfo;
  322. PROCESS_INFORMATION processInfo;
  323. memset(&startupInfo,0,(sizeof startupInfo));
  324. startupInfo.cb = (sizeof startupInfo);
  325. gData.GetReadableLogFile(filename);
  326. cmd.FormatMessage(IDS_NotepadCommandLine,filename);
  327. CreateProcess(NULL,cmd.GetBuffer(0),NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo);
  328. }
  329. void CAgentMonitorDlg::OnDetails()
  330. {
  331. const int NOT_FOUND = -1; //indicates no match in search - PRT
  332. const int WHOLE_LIST = -1; //index to start search of whole list - PRT
  333. UpdateData(TRUE);
  334. // POSITION p = m_ServerList.GetFirstSelectedItemPosition();
  335. // if ( p )
  336. // {
  337. // int ndx = m_ServerList.GetNextSelectedItem(p);
  338. //search whole list control for first (and only) selected item
  339. int ndx = m_ServerList.GetNextItem(WHOLE_LIST, LVNI_SELECTED); //PRT
  340. //if found selected item, disply it's details
  341. if (ndx != NOT_FOUND) //PRT
  342. { //PRT
  343. CString serverName;
  344. serverName = m_ServerList.GetItemText(ndx,0);
  345. if ( serverName.GetLength() )
  346. {
  347. // Launch the details dialog
  348. CAgentDetailDlg det;
  349. gData.Lock();
  350. TServerNode * s = gData.GetUnsafeServerList()->FindServer((LPCTSTR)serverName);
  351. gData.Unlock();
  352. if ( s )
  353. {
  354. det.SetNode(s);
  355. if ( ! m_bSecTrans )
  356. {
  357. det.SetFormat(-1);
  358. }
  359. if ( m_bReporting )
  360. {
  361. det.SetGatheringInfo(TRUE);
  362. }
  363. if ( s->IsFinished() && *s->GetJobFile() )
  364. {
  365. DetailStats detailStats;
  366. WCHAR directory[MAX_PATH];
  367. WCHAR filename[MAX_PATH];
  368. CString plugInText;
  369. gData.GetResultDir(directory);
  370. memset(&detailStats,0,(sizeof detailStats));
  371. swprintf(filename,GET_STRING(IDS_AgentResultFileFmt),s->GetJobFile());
  372. if ( SUCCEEDED(CoInitialize(NULL)) )
  373. {
  374. if ( ReadResults(s,directory,filename,&detailStats,plugInText,FALSE) )
  375. {
  376. det.SetStats(&detailStats);
  377. det.SetPlugInText(plugInText);
  378. det.SetLogFile(s->GetLogPath());
  379. }
  380. CoUninitialize();
  381. }
  382. }
  383. det.DoModal();
  384. if ( s->IsRunning() && ! det.IsAgentAlive() )
  385. {
  386. // the agent is not really running, update it's status to failed.
  387. if (! det.IsStatusUnknown() )
  388. {
  389. s->SetSeverity(2);
  390. s->SetFailed();
  391. // OnServerError(0,(long)s);
  392. OnServerError(0,(LPARAM)s);
  393. }
  394. // update the counts on the summary screen
  395. ComputerStats stats;
  396. HWND gSummaryWnd;
  397. gData.GetComputerStats(&stats);
  398. stats.numError++;
  399. stats.numRunning--;
  400. gData.SetComputerStats(&stats);
  401. gData.GetSummaryWindow(&gSummaryWnd);
  402. // ::SendMessage(gSummaryWnd,DCT_UPDATE_COUNTS,0,(long)&stats);
  403. ::SendMessage(gSummaryWnd,DCT_UPDATE_COUNTS,0,(LPARAM)&stats);
  404. }
  405. }
  406. }
  407. }
  408. UpdateData(FALSE);
  409. }
  410. void CAgentMonitorDlg::OnColumnclickServerlist(NMHDR* pNMHDR, LRESULT* pResult)
  411. {
  412. CWaitCursor w;
  413. NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR;
  414. // sort by pNMListView->iSubItem
  415. if ( m_SortColumn == pNMListView->iSubItem )
  416. {
  417. m_bReverseSort = ! m_bReverseSort;
  418. }
  419. else
  420. {
  421. m_bReverseSort = FALSE;
  422. }
  423. m_SortColumn = pNMListView->iSubItem;
  424. if ( m_bReverseSort )
  425. {
  426. m_ServerList.SortItems(&SortFunction,m_SortColumn | SORT_REVERSE);
  427. }
  428. else
  429. {
  430. m_ServerList.SortItems(&SortFunction,m_SortColumn);
  431. }
  432. *pResult = 0;
  433. }
  434. void CAgentMonitorDlg::OnClickServerlist(NMHDR* pNMHDR, LRESULT* pResult)
  435. {
  436. const int NOT_FOUND = -1; //indicates no match in search - PRT
  437. const int WHOLE_LIST = -1; //index to start search of whole list - PRT
  438. UpdateData(TRUE);
  439. if ( m_ServerList.GetSelectedCount() )
  440. {
  441. // POSITION p = m_ServerList.GetFirstSelectedItemPosition();
  442. // if ( p )
  443. // {
  444. //search whole list control for first (and only) selected item
  445. int ndx = m_ServerList.GetNextItem(WHOLE_LIST, LVNI_SELECTED); //PRT
  446. //if found selected item, disply it's details
  447. if (ndx != NOT_FOUND) //PRT
  448. { //PRT
  449. CString msg1;
  450. CString msg2;
  451. // int ndx = m_ServerList.GetNextSelectedItem(p);
  452. CString serverName;
  453. serverName = m_ServerList.GetItemText(ndx,0);
  454. msg1.LoadString(IDS_WaitingMessage);
  455. msg2.LoadString(IDS_NoServersMessage);
  456. if ( serverName.Compare(msg1) && serverName.Compare(msg2) )
  457. {
  458. m_DetailsButton.EnableWindow(TRUE);
  459. }
  460. else
  461. {
  462. m_DetailsButton.EnableWindow(FALSE);
  463. }
  464. }
  465. }
  466. else
  467. {
  468. m_DetailsButton.EnableWindow(FALSE);
  469. }
  470. UpdateData(FALSE);
  471. *pResult = 0;
  472. }
  473. WCHAR gMessage[1000];
  474. void CAgentMonitorDlg::OnGetdispinfoServerlist(NMHDR* pNMHDR, LRESULT* pResult)
  475. {
  476. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  477. // find iItem in the serverList, and set the pszText for the iSubItem appropriately
  478. CString status;
  479. TServerNode * pNode = NULL;
  480. CString timestamp;
  481. WCHAR * text = gMessage;
  482. CString serverName;
  483. status.LoadString(IDS_Status_Unknown);
  484. serverName = m_ServerList.GetItemText(pDispInfo->item.iItem,0);
  485. if ( serverName.GetLength() )
  486. {
  487. gData.Lock();
  488. pNode = gData.GetUnsafeServerList()->FindServer(serverName.GetBuffer(0));
  489. gData.Unlock();
  490. if ( pNode )
  491. {
  492. switch ( pDispInfo->item.iSubItem )
  493. {
  494. case COLUMN_TIMESTAMP:
  495. timestamp = pNode->GetTimeStamp();
  496. if ( timestamp.Right(1) == "\n" )
  497. {
  498. timestamp = timestamp.Left(timestamp.GetLength() - 1);
  499. }
  500. //text = new char[timestamp.GetLength() + 1];
  501. UStrCpy(text,timestamp.GetBuffer(0));
  502. pDispInfo->item.pszText = text;
  503. break;
  504. case COLUMN_STATUS:
  505. if ( pNode->HasFailed() )
  506. {
  507. status.LoadString(IDS_Status_InstallFailed);
  508. }
  509. if ( pNode->IsInstalled() )
  510. {
  511. if ( ! pNode->HasFailed() )
  512. status.LoadString(IDS_Status_Installed);
  513. else
  514. status.LoadString(IDS_Status_DidNotStart);
  515. }
  516. if ( pNode->GetStatus() & Agent_Status_Started )
  517. {
  518. if ( ! pNode->HasFailed() )
  519. status.LoadString(IDS_Status_Running);
  520. else
  521. status.LoadString(IDS_Status_Failed);
  522. }
  523. if ( pNode->IsFinished() )
  524. {
  525. if ( ! pNode->HasFailed() && ! pNode->GetSeverity() )
  526. status.LoadString(IDS_Status_Completed);
  527. else if ( pNode->GetSeverity() )
  528. {
  529. switch ( pNode->GetSeverity() )
  530. {
  531. case 1:
  532. status.LoadString(IDS_Status_Completed_With_Warnings);
  533. break;
  534. case 2:
  535. status.LoadString(IDS_Status_Completed_With_Errors);
  536. break;
  537. case 3:
  538. default:
  539. status.LoadString(IDS_Status_Completed_With_SErrors);
  540. break;
  541. }
  542. }
  543. else
  544. status.LoadString(IDS_Status_NotRunning);
  545. }
  546. UStrCpy(text,status);
  547. pDispInfo->item.pszText = text;
  548. break;
  549. case COLUMN_MESSAGE:
  550. if ( pNode->HasFailed() || pNode->QueryFailed() || pNode->GetSeverity() )
  551. {
  552. UStrCpy(text,pNode->GetMessageText());
  553. pDispInfo->item.pszText = text;
  554. }
  555. break;
  556. }
  557. }
  558. }
  559. *pResult = 0;
  560. }
  561. BOOL CAgentMonitorDlg::OnSetActive()
  562. {
  563. BOOL rc = CPropertyPage::OnSetActive();
  564. CancelToClose();
  565. return rc;
  566. }
  567. void CAgentMonitorDlg::OnSetdispinfoServerlist(NMHDR* pNMHDR, LRESULT* pResult)
  568. {
  569. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  570. // TODO: Add your control notification handler code here
  571. *pResult = 0;
  572. }
  573. void CAgentMonitorDlg::OnHeaderItemClickServerlist(NMHDR* pNMHDR, LRESULT* pResult)
  574. {
  575. HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
  576. // TODO: Add your control notification handler code here
  577. *pResult = 0;
  578. }
  579. void CAgentMonitorDlg::OnOK()
  580. {
  581. CPropertyPage::OnOK();
  582. }
  583. BOOL CAgentMonitorDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  584. {
  585. LPNMHDR lpnm = (LPNMHDR) lParam;
  586. switch (lpnm->code)
  587. {
  588. case PSN_HELP :
  589. helpWrapper(m_hWnd, IDH_WINDOW_AGENT_SERVER_LIST );
  590. break;
  591. }
  592. return CPropertyPage::OnNotify(wParam, lParam, pResult);
  593. }
  594. BOOL CAgentMonitorDlg::OnHelpInfo(HELPINFO* pHelpInfo)
  595. {
  596. helpWrapper(m_hWnd, IDH_WINDOW_AGENT_SERVER_LIST );
  597. return CPropertyPage::OnHelpInfo(pHelpInfo);
  598. }