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.

981 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998.
  5. //
  6. // File: S M E N G . C P P
  7. //
  8. // Contents: The engine that provides statistics to the status monitor
  9. //
  10. // Notes:
  11. //
  12. // Author: CWill 7 Oct 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "sminc.h"
  18. #include "ncnetcon.h"
  19. #include "ncui.h"
  20. #include "smpsh.h"
  21. #include "smutil.h"
  22. #include "smhelp.h"
  23. extern const WCHAR c_szNetShellDll[];
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Member: CNetStatisticsEngine::CNetStatisticsEngine
  27. //
  28. // Purpose: Initialization
  29. //
  30. // Arguments: None
  31. //
  32. // Returns: Nothing
  33. //
  34. CNetStatisticsEngine::CNetStatisticsEngine(VOID) :
  35. m_pnsc(NULL),
  36. m_psmEngineData(NULL),
  37. m_ppsmg(NULL),
  38. m_ppsmt(NULL),
  39. m_ppsmr(NULL),
  40. m_ppsms(NULL),
  41. m_hwndPsh(NULL),
  42. m_cStatRef(0),
  43. m_fRefreshIcon(FALSE),
  44. m_dwChangeFlags(SMDCF_NULL),
  45. m_fCreatingDialog(FALSE)
  46. {
  47. TraceFileFunc(ttidStatMon);
  48. ::ZeroMemory(&m_PersistConn, sizeof(m_PersistConn));
  49. ::ZeroMemory(&m_guidId, sizeof(m_guidId));
  50. }
  51. //+---------------------------------------------------------------------------
  52. //
  53. // Member: CNetStatisticsEngine::~CNetStatisticsEngine
  54. //
  55. // Purpose: Cleans up all data before destroying the object
  56. //
  57. // Arguments: None
  58. //
  59. // Returns: Nothing
  60. //
  61. CNetStatisticsEngine::~CNetStatisticsEngine(VOID)
  62. {
  63. // Make sure we don't try to update our stats while destroying
  64. //
  65. m_cStatRef = 0;
  66. // Make sure we are no longer in the global list if we are valid
  67. //
  68. if ((GUID_NULL != m_guidId) && (NULL != m_pnsc))
  69. {
  70. (VOID) m_pnsc->RemoveNetStatisticsEngine(&m_guidId);
  71. }
  72. //
  73. // Clear the data
  74. //
  75. if (m_psmEngineData)
  76. {
  77. delete(m_psmEngineData);
  78. m_psmEngineData = NULL;
  79. }
  80. // Release the object because we AddRefed it
  81. //
  82. ::ReleaseObj(m_ppsmg);
  83. delete m_ppsmt;
  84. m_ppsmt = NULL;
  85. delete m_ppsmr;
  86. m_ppsmr = NULL;
  87. delete m_ppsms;
  88. m_ppsms = NULL;
  89. AssertSz(FImplies(m_PersistConn.pbBuf, m_PersistConn.ulSize),
  90. "Buffer with no size.");
  91. MemFree(m_PersistConn.pbBuf);
  92. ::ReleaseObj(m_pnsc);
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Member: CNetStatisticsEngine::HrInitStatEngine
  97. //
  98. // Purpose: Initilaizes the statistics engine
  99. //
  100. // Arguments: ccfe - The connection folder entry associated with this
  101. // statistics engine
  102. //
  103. // Returns: Error code
  104. //
  105. HRESULT CNetStatisticsEngine::HrInitStatEngine(const CONFOLDENTRY& ccfe)
  106. {
  107. TraceFileFunc(ttidStatMon);
  108. HRESULT hr;
  109. Assert(!ccfe.empty());
  110. ULONG cb = ccfe.GetPersistSize();
  111. hr = HrMalloc(cb, (PVOID*)&m_PersistConn.pbBuf);
  112. if (SUCCEEDED(hr))
  113. {
  114. CopyMemory(m_PersistConn.pbBuf, ccfe.GetPersistData(), cb);
  115. m_PersistConn.ulSize = cb;
  116. m_PersistConn.clsid = ccfe.GetCLSID();
  117. m_guidId = ccfe.GetGuidID();
  118. }
  119. TraceError("CNetStatisticsEngine::HrInitStatEngine", hr);
  120. return hr;
  121. }
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Member: CNetStatisticsEngine::StartStatistics
  125. //
  126. // Purpose: Start retrieving statistics off of the engine
  127. //
  128. // Arguments: None
  129. //
  130. // Returns: Error code
  131. //
  132. HRESULT CNetStatisticsEngine::StartStatistics(VOID)
  133. {
  134. TraceFileFunc(ttidStatMon);
  135. HRESULT hr = S_OK;
  136. ::InterlockedIncrement(&m_cStatRef);
  137. m_fRefreshIcon = TRUE;
  138. TraceError("CNetStatisticsEngine::StartStatistics", hr);
  139. return hr;
  140. }
  141. //+---------------------------------------------------------------------------
  142. //
  143. // Member: CNetStatisticsEngine::StopStatistics
  144. //
  145. // Purpose: Tell the engine that that statistics are no longer needed
  146. //
  147. // Arguments: None
  148. //
  149. // Returns: Error code
  150. //
  151. HRESULT CNetStatisticsEngine::StopStatistics(VOID)
  152. {
  153. TraceFileFunc(ttidStatMon);
  154. HRESULT hr = S_OK;
  155. if (0 == ::InterlockedDecrement(&m_cStatRef))
  156. {
  157. //$ REVIEW (cwill) 5 Feb 1998: We can stop doing statistics now.
  158. }
  159. TraceError("CNetStatisticsEngine::StopStatistics", hr);
  160. return hr;
  161. }
  162. DWORD CNetStatisticsEngine::MonitorThread(CNetStatisticsEngine * pnse)
  163. {
  164. TraceFileFunc(ttidStatMon);
  165. HRESULT hr;
  166. BOOL fUninitCom = TRUE;
  167. CWaitCursor WaitCursor;
  168. BOOL fHasSupportPage = FALSE;
  169. int iIndexSupportPage = 0;
  170. // Initialize COM on this thread
  171. //
  172. hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
  173. if (RPC_E_CHANGED_MODE == hr)
  174. {
  175. hr = S_OK;
  176. fUninitCom = FALSE;
  177. }
  178. if (SUCCEEDED(hr))
  179. {
  180. INetConnection* pncStatEng;
  181. // Get INetConnection and initialize the pages
  182. //
  183. hr = pnse->HrGetConnectionFromBlob(&pncStatEng);
  184. if (SUCCEEDED(hr))
  185. {
  186. // Initialize the general page
  187. //
  188. hr = pnse->m_ppsmg->HrInitGenPage(pnse, pncStatEng,
  189. g_aHelpIDs_IDD_STATMON_GENERAL);
  190. if (SUCCEEDED(hr))
  191. {
  192. // Initialize the tool page
  193. //
  194. hr = pnse->m_ppsmt->HrInitToolPage(pncStatEng,
  195. g_aHelpIDs_IDD_STATMON_TOOLS);
  196. if (SUCCEEDED(hr))
  197. {
  198. if (pnse->m_ppsmr)
  199. {
  200. // Initialize the RAS page
  201. //
  202. hr = pnse->m_ppsmr->HrInitRasPage(pncStatEng,
  203. pnse->m_ppsmg,
  204. g_aHelpIDs_IDD_STATMON_RAS);
  205. }
  206. if (SUCCEEDED(hr))
  207. {
  208. PROPSHEETHEADER pshTemp = { 0 };
  209. INT nPages = 1; // Start with only the general page
  210. HPROPSHEETPAGE ahpspTemp[4];
  211. // Put together the required property pages
  212. // If we have a RAS page
  213. //
  214. if (pnse->m_ppsmr)
  215. {
  216. ahpspTemp[0] = pnse->m_ppsmg->CreatePage(IDD_STATMON_GENERAL_RAS,
  217. PSP_DEFAULT);
  218. // Create the RAS page
  219. //
  220. ahpspTemp[nPages] = pnse->m_ppsmr->CreatePage(IDD_STATMON_RAS,
  221. PSP_DEFAULT);
  222. nPages++;
  223. }
  224. else if(NCM_LAN == pnse->m_ncmType || NCM_BRIDGE == pnse->m_ncmType)
  225. {
  226. ahpspTemp[0] = pnse->m_ppsmg->CreatePage(IDD_STATMON_GENERAL_LAN,
  227. PSP_DEFAULT);
  228. }
  229. else if(NCM_SHAREDACCESSHOST_LAN == pnse->m_ncmType || NCM_SHAREDACCESSHOST_RAS == pnse->m_ncmType)
  230. {
  231. ahpspTemp[0] = pnse->m_ppsmg->CreatePage(IDD_STATMON_GENERAL_SHAREDACCESS,
  232. PSP_DEFAULT);
  233. }
  234. else
  235. {
  236. AssertSz(FALSE, "Unknown media type");
  237. }
  238. HICON hIcon = NULL;
  239. hr = HrGetIconFromMediaType(GetSystemMetrics(SM_CXSMICON), pnse->m_ncmType, pnse->m_ncsmType, 7, 0, &hIcon);
  240. if (NCM_LAN == pnse->m_ncmType || NCM_BRIDGE == pnse->m_ncmType)
  241. {
  242. hr = pnse->m_ppsms->HrInitPage(pncStatEng,
  243. g_aHelpIDs_IDD_PROPPAGE_IPCFG);
  244. if (SUCCEEDED(hr))
  245. {
  246. ahpspTemp[nPages] = pnse->m_ppsms->CreatePage(IDD_PROPPAGE_IPCFG,
  247. PSP_DEFAULT);
  248. fHasSupportPage = TRUE;
  249. iIndexSupportPage = nPages;
  250. nPages++;
  251. }
  252. }
  253. // If we have any tools to display
  254. //
  255. if (!pnse->m_ppsmt->FToolListEmpty())
  256. {
  257. ahpspTemp[nPages] = pnse->m_ppsmt->CreatePage(IDD_STATMON_TOOLS,
  258. PSP_DEFAULT);
  259. nPages++;
  260. }
  261. // Fill in the property sheet header
  262. //
  263. pshTemp.dwSize = sizeof(PROPSHEETHEADER);
  264. pshTemp.dwFlags = PSH_NOAPPLYNOW | PSH_USECALLBACK;
  265. pshTemp.hwndParent = NULL;
  266. pshTemp.hInstance = _Module.GetResourceInstance();
  267. pshTemp.hIcon = NULL;
  268. pshTemp.nPages = nPages;
  269. if (hIcon)
  270. {
  271. pshTemp.dwFlags |= PSH_USEHICON;
  272. pshTemp.hIcon = hIcon;
  273. }
  274. pshTemp.phpage = ahpspTemp;
  275. pshTemp.pfnCallback = static_cast<PFNPROPSHEETCALLBACK>(
  276. CNetStatisticsEngine::PshCallback);
  277. pshTemp.hbmWatermark = NULL;
  278. pshTemp.hplWatermark = NULL;
  279. pshTemp.hbmHeader = NULL;
  280. // Set propertysheet title
  281. PWSTR pszCaption = NULL;
  282. NETCON_PROPERTIES* pProps;
  283. if (SUCCEEDED(pncStatEng->GetProperties(&pProps)))
  284. {
  285. // Get the title each time in case it has
  286. // changed
  287. //
  288. AssertSz(pProps->pszwName,
  289. "We should have a pProps->pszwName");
  290. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  291. FORMAT_MESSAGE_FROM_STRING |
  292. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  293. SzLoadIds(IDS_SM_CAPTION),
  294. 0, 0, (PWSTR)&pszCaption, 0,
  295. (va_list *)&pProps->pszwName);
  296. pshTemp.pszCaption = pszCaption;
  297. // Get the connection status. If the status is NCS_INVALID_ADDRESS,
  298. // then put the "Support" tab as the start page
  299. if (fHasSupportPage && NCS_INVALID_ADDRESS == pProps->Status)
  300. {
  301. pshTemp.nStartPage = iIndexSupportPage;
  302. Assert(pnse->m_ppsms);
  303. //set the support tab as the first page and m_ppsms is responsible
  304. //for initialize the propsheet
  305. pnse->m_ppsms->SetAsFirstPage(TRUE);
  306. }
  307. else
  308. {
  309. pshTemp.nStartPage = 0;
  310. Assert(pnse->m_ppsmg);
  311. //set the support tab as the first page and m_ppsmg is responsible
  312. //for initialize the propsheet
  313. pnse->m_ppsmg->SetAsFirstPage(TRUE);
  314. }
  315. FreeNetconProperties(pProps);
  316. }
  317. else
  318. {
  319. //$ REVIEW : CWill : 02/17/98 : Better default?
  320. pshTemp.pszCaption = SzLoadIds(IDS_SM_ERROR_CAPTION);
  321. }
  322. // Launch the page
  323. //
  324. INT iRet = ::PropertySheet(&pshTemp);
  325. if (NULL == iRet)
  326. {
  327. hr = ::HrFromLastWin32Error();
  328. }
  329. if (hIcon)
  330. {
  331. DestroyIcon(hIcon);
  332. }
  333. if (NULL != pszCaption)
  334. {
  335. LocalFree(pszCaption);
  336. }
  337. }
  338. }
  339. }
  340. // Make sure the general page clean up correctly.
  341. // Since the "General" page may not be the first page (support page will be the
  342. // first one when the address is invalid, the OnDestroy method (which calls HrCleanupGenPage)
  343. // of the general page may not called in such case. So we always do a cleanup here. It's
  344. // OK to call HrCleanupGenPage mutliple times.
  345. // general page
  346. AssertSz(pnse->m_ppsmg, "We should have a m_ppsmg");
  347. (VOID) pnse->m_ppsmg->HrCleanupGenPage();
  348. //also cleanup the Support page if it exists. It's safe to call this routine mutliple times.
  349. if (fHasSupportPage)
  350. {
  351. pnse->m_ppsms->CleanupPage();
  352. }
  353. // leaving creating mode
  354. pnse->m_fCreatingDialog = FALSE;
  355. ReleaseObj(pncStatEng);
  356. }
  357. if (fUninitCom)
  358. {
  359. CoUninitialize();
  360. }
  361. } // Initialize com succeeded
  362. // Release the 'pnse' object because it was addref'd before
  363. // the thread was created.
  364. //
  365. ReleaseObj(static_cast<INetStatisticsEngine *>(pnse));
  366. // release the dll
  367. //
  368. FreeLibraryAndExitThread(GetModuleHandle(c_szNetShellDll), 1);
  369. return 1;
  370. }
  371. //+---------------------------------------------------------------------------
  372. //
  373. // Member: CNetStatisticsEngine::ShowStatusMonitor
  374. //
  375. // Purpose: Create an launch the UI for the status monitor
  376. //
  377. // Arguments: None
  378. //
  379. // Returns: Error code
  380. //
  381. HRESULT CNetStatisticsEngine::ShowStatusMonitor(VOID)
  382. {
  383. TraceFileFunc(ttidStatMon);
  384. HRESULT hr = S_OK;
  385. CExceptionSafeComObjectLock EsLock(m_pnsc);
  386. // Create the property sheet pages if they don't already exist
  387. //
  388. if (!m_ppsmg)
  389. {
  390. CPspStatusMonitorGen* pObj = NULL;
  391. // Make sure we have read in the tools
  392. //
  393. (VOID) m_pnsc->HrReadTools();
  394. if (m_ncmType == NCM_LAN || m_ncmType == NCM_BRIDGE)
  395. {
  396. CPspLanGen* pLanObj = NULL;
  397. // Make the Tool property page
  398. m_ppsmt = new CPspLanTool;
  399. // Create the object
  400. pLanObj = new CComObject <CPspLanGen>;
  401. if (pLanObj)
  402. {
  403. pLanObj->put_MediaType(m_ncmType, m_ncsmType);
  404. }
  405. // Give it back to the page
  406. pObj = pLanObj;
  407. m_ppsms = new CPspStatusMonitorIpcfg;
  408. }
  409. else if(m_ncmType == NCM_SHAREDACCESSHOST_LAN || m_ncmType == NCM_SHAREDACCESSHOST_RAS)
  410. {
  411. m_ppsmt = new CPspSharedAccessTool;
  412. CPspSharedAccessGen* pSharedAccessGen = new CComObject<CPspSharedAccessGen>;
  413. pSharedAccessGen->put_MediaType(m_ncmType, m_ncsmType);
  414. pObj = pSharedAccessGen;
  415. }
  416. else if ((m_dwCharacter & NCCF_INCOMING_ONLY) ||
  417. (m_dwCharacter & NCCF_OUTGOING_ONLY))
  418. {
  419. // RAS connections
  420. CPspRasGen* pRasObj = NULL;
  421. // Make the Tool property page
  422. //
  423. m_ppsmt = new CPspRasTool;
  424. // Make the RAS property page and let it be known there are
  425. // now three pages
  426. //
  427. m_ppsmr = new CPspStatusMonitorRas;
  428. // Create the object
  429. //
  430. pRasObj = new CComObject <CPspRasGen>;
  431. if (pRasObj)
  432. {
  433. pRasObj->put_MediaType(m_ncmType, m_ncsmType);
  434. pRasObj->put_Character(m_dwCharacter);
  435. }
  436. // Give it back to the page
  437. //
  438. pObj = pRasObj;
  439. }
  440. else
  441. {
  442. AssertSz(FALSE, "Unknown connection type.");
  443. }
  444. if (NULL != pObj)
  445. {
  446. // Do the standard CComCreator::CreateInstance stuff.
  447. //
  448. pObj->SetVoid(NULL);
  449. pObj->InternalFinalConstructAddRef();
  450. hr = pObj->FinalConstruct();
  451. pObj->InternalFinalConstructRelease();
  452. if (SUCCEEDED(hr))
  453. {
  454. m_ppsmg = static_cast<CPspStatusMonitorGen*>(pObj);
  455. // Hold on to the interface
  456. ::AddRefObj(m_ppsmg);
  457. }
  458. // Make sure we clean up nicely
  459. //
  460. if (FAILED(hr))
  461. {
  462. delete pObj;
  463. }
  464. }
  465. // Clean up the other pages on failure
  466. //
  467. if (FAILED(hr))
  468. {
  469. if (m_ppsmt)
  470. {
  471. delete m_ppsmt;
  472. m_ppsmt = NULL;
  473. }
  474. if (m_ppsmr)
  475. {
  476. delete m_ppsmr;
  477. m_ppsmr = NULL;
  478. }
  479. }
  480. }
  481. //
  482. // Show the property sheets
  483. //
  484. if (SUCCEEDED(hr))
  485. {
  486. // NOTE: The variable m_fCreatingDialog is reset to FALSE in the following
  487. // 3 places, which should cover all senarios:
  488. //
  489. // 1) In CPspStatusMonitorGen::OnInitDialog, after m_hWnd is assigned.
  490. // 2) In CNetStatisticsEngine::ShowStatusMonitor, in case CreateThread failed.
  491. // 3) In CNetStatisticsEngine::MonitorThread, just before exiting
  492. // (in case of failing to create UI).
  493. //
  494. if (m_hwndPsh)
  495. {
  496. // Bring the existing property sheet page to the foreground
  497. //
  498. ::SetForegroundWindow(m_hwndPsh);
  499. }
  500. else if (!m_fCreatingDialog)
  501. {
  502. // Addref 'this' object
  503. //
  504. AddRefObj(static_cast<INetStatisticsEngine *>(this));
  505. // entering creating mode
  506. m_fCreatingDialog = TRUE;
  507. // Create the property sheet on a different thread
  508. //
  509. // Make sure the dll don't get unloaded while the thread is active
  510. HINSTANCE hInst = LoadLibrary(c_szNetShellDll);
  511. HANDLE hthrd = NULL;
  512. if (hInst)
  513. {
  514. DWORD dwThreadId;
  515. hthrd = CreateThread(NULL, STACK_SIZE_TINY,
  516. (LPTHREAD_START_ROUTINE)CNetStatisticsEngine::MonitorThread,
  517. (LPVOID)this, 0, &dwThreadId);
  518. if (NULL != hthrd)
  519. {
  520. CloseHandle(hthrd);
  521. }
  522. }
  523. // clean up on failure
  524. if (!hthrd)
  525. {
  526. // Release 'this' object on failure
  527. //
  528. ReleaseObj(static_cast<INetStatisticsEngine *>(this));
  529. // Release the dll
  530. //
  531. if (hInst)
  532. FreeLibrary(hInst);
  533. // leaving creating mode
  534. m_fCreatingDialog = FALSE;
  535. hr = HrFromLastWin32Error();
  536. }
  537. }
  538. }
  539. TraceError("CNetStatisticsEngine::ShowStatusMonitor", hr);
  540. return hr;
  541. }
  542. //+---------------------------------------------------------------------------
  543. //
  544. // Member: CNetStatisticsEngine::GetStatistics
  545. //
  546. // Purpose:
  547. //
  548. // Arguments:
  549. //
  550. // Returns:
  551. //
  552. HRESULT CNetStatisticsEngine::GetStatistics(
  553. STATMON_ENGINEDATA** ppseAllData)
  554. {
  555. TraceFileFunc(ttidStatMon);
  556. HRESULT hr = S_OK;
  557. // Make sure we have a valid pointer
  558. if (ppseAllData)
  559. {
  560. STATMON_ENGINEDATA * pEngineData = NULL;
  561. // Allocate space and copy the data ..
  562. EnterCriticalSection(&g_csStatmonData);
  563. if (!m_psmEngineData)
  564. {
  565. DWORD dwChangeFlags;
  566. BOOL fNoLongerConnected;
  567. hr = HrUpdateData(&dwChangeFlags, &fNoLongerConnected);
  568. }
  569. if (m_psmEngineData)
  570. {
  571. DWORD dwBytes = sizeof(STATMON_ENGINEDATA);
  572. PVOID pbBuf;
  573. hr = HrCoTaskMemAlloc(dwBytes, &pbBuf);
  574. if (SUCCEEDED(hr))
  575. {
  576. pEngineData = reinterpret_cast<STATMON_ENGINEDATA *>(pbBuf);
  577. // fill in the data
  578. *pEngineData = *m_psmEngineData;
  579. }
  580. }
  581. LeaveCriticalSection(&g_csStatmonData);
  582. *ppseAllData = pEngineData;
  583. }
  584. else
  585. {
  586. // We should have good data
  587. hr = E_INVALIDARG;
  588. }
  589. TraceError("CNetStatisticsEngine::GetStatistics", hr);
  590. return hr;
  591. }
  592. //+---------------------------------------------------------------------------
  593. //
  594. // Member: CNetStatisticsEngine::UpdateStatistics
  595. //
  596. // Purpose: Get the new statistics from the devices and notify all the
  597. // advises that the data has changed
  598. //
  599. // Arguments: None
  600. //
  601. // Returns: Error code
  602. //
  603. HRESULT
  604. CNetStatisticsEngine::UpdateStatistics (
  605. BOOL* pfNoLongerConnected)
  606. {
  607. TraceFileFunc(ttidStatMon);
  608. HRESULT hr = S_OK;
  609. Assert (pfNoLongerConnected);
  610. // Initialize the output parameter.
  611. //
  612. *pfNoLongerConnected = FALSE;
  613. // Don't bother doing anything if we don't have any ref count
  614. //
  615. if (m_cStatRef)
  616. {
  617. // Get the new data
  618. //
  619. DWORD dwChangeFlags;
  620. hr = HrUpdateData(&dwChangeFlags, pfNoLongerConnected);
  621. // If it represents a change, notify our connection points.
  622. //
  623. if (SUCCEEDED(hr) &&
  624. (m_fRefreshIcon || // Bug#319276, force a refresh if new client is added
  625. (dwChangeFlags != m_dwChangeFlags) ||
  626. (*pfNoLongerConnected)))
  627. {
  628. m_fRefreshIcon = FALSE;
  629. ULONG cpUnk;
  630. IUnknown** apUnk;
  631. hr = HrCopyIUnknownArrayWhileLocked (
  632. this,
  633. &m_vec,
  634. &cpUnk,
  635. &apUnk);
  636. if (SUCCEEDED(hr) && cpUnk && apUnk)
  637. {
  638. // Notify everyone that we have changed
  639. //
  640. for (ULONG i = 0; i < cpUnk; i++)
  641. {
  642. INetConnectionStatisticsNotifySink* pSink =
  643. static_cast<INetConnectionStatisticsNotifySink*>(apUnk[i]);
  644. hr = pSink->OnStatisticsChanged(dwChangeFlags);
  645. ReleaseObj(pSink);
  646. }
  647. MemFree(apUnk);
  648. }
  649. // Remember the change flags for comparison next time.
  650. //
  651. m_dwChangeFlags = dwChangeFlags;
  652. }
  653. }
  654. TraceError("CNetStatisticsEngine::UpdateStatistics", hr);
  655. return hr;
  656. }
  657. //+---------------------------------------------------------------------------
  658. //
  659. // Member: CNetStatisticsEngine::UpdateTitle
  660. //
  661. // Purpose: If the status monitor UI is up, change the title
  662. //
  663. // Arguments: pszwNewName
  664. //
  665. // Returns: None
  666. //
  667. HRESULT CNetStatisticsEngine::UpdateTitle (PCWSTR pszwNewName)
  668. {
  669. TraceFileFunc(ttidStatMon);
  670. if (m_hwndPsh)
  671. {
  672. // Set propertysheet title
  673. PWSTR pszCaption = NULL;
  674. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  675. FORMAT_MESSAGE_FROM_STRING |
  676. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  677. SzLoadIds(IDS_SM_CAPTION),
  678. 0, 0, (PWSTR)&pszCaption, 0,
  679. (va_list *)&pszwNewName);
  680. PropSheet_SetTitle(m_hwndPsh,0,pszCaption);
  681. }
  682. return S_OK;
  683. }
  684. //+---------------------------------------------------------------------------
  685. //
  686. // Member: CNetStatisticsEngine::CloseStatusMonitor
  687. //
  688. // Purpose: If the status monitor UI is up, close it
  689. //
  690. // Arguments: None
  691. //
  692. // Returns: None
  693. //
  694. HRESULT CNetStatisticsEngine::CloseStatusMonitor()
  695. {
  696. TraceFileFunc(ttidStatMon);
  697. if (m_hwndPsh)
  698. {
  699. PropSheet_PressButton(m_hwndPsh, PSBTN_CANCEL);
  700. }
  701. return S_OK;
  702. }
  703. //+---------------------------------------------------------------------------
  704. //
  705. // Member: CNetStatisticsEngine::UpdateRasLinkList
  706. //
  707. // Purpose: If the status monitor UI is up and on the RAS page, update
  708. // the multi-link combo-box and button state
  709. //
  710. // Arguments: None
  711. //
  712. // Returns: Error code
  713. //
  714. HRESULT CNetStatisticsEngine::UpdateRasLinkList()
  715. {
  716. TraceFileFunc(ttidStatMon);
  717. HRESULT hr = S_OK;
  718. if (m_hwndPsh)
  719. {
  720. HWND hwndDlg = PropSheet_GetCurrentPageHwnd(m_hwndPsh);
  721. if (hwndDlg)
  722. {
  723. if (GetDlgItem(hwndDlg, IDC_TXT_SM_NUM_DEVICES_VAL))
  724. {
  725. // we are on the RAS page, update the combo box, active link count etc.
  726. ::PostMessage(hwndDlg, PWM_UPDATE_RAS_LINK_LIST, 0, 0);
  727. }
  728. }
  729. }
  730. TraceError("CNetStatisticsEngine::UpdateRasLinkList", hr);
  731. return hr;
  732. }
  733. //+---------------------------------------------------------------------------
  734. //
  735. // Member: CNetStatisticsEngine::GetGuidId
  736. //
  737. // Purpose: Gets the Connection GUID of the engine into a pre-allocated
  738. // buffer
  739. //
  740. // Arguments: pguidId - Location of buffer to hold the GUID
  741. //
  742. // Returns: Error code
  743. //
  744. HRESULT CNetStatisticsEngine::GetGuidId(GUID* pguidId)
  745. {
  746. TraceFileFunc(ttidStatMon);
  747. HRESULT hr = S_OK;
  748. // Pass back the GUID
  749. //
  750. if (pguidId)
  751. {
  752. *pguidId = m_guidId;
  753. }
  754. else
  755. {
  756. hr = E_POINTER;
  757. }
  758. TraceError("CNetStatisticsEngine::GetGuidId", hr);
  759. return hr;
  760. }
  761. //+------------------------------------------------------------------
  762. //
  763. // CNetStatisticsEngine::PshCallback
  764. //
  765. // Purpose:
  766. //
  767. //
  768. // Parameters:
  769. // hwndDlg [in]
  770. // uMsg [in]
  771. // lParam [in]
  772. //
  773. // Returns:
  774. // a
  775. //
  776. // Side Effects:
  777. //
  778. INT CALLBACK CNetStatisticsEngine::PshCallback(HWND hwndDlg,
  779. UINT uMsg, LPARAM lParam)
  780. {
  781. TraceFileFunc(ttidStatMon);
  782. switch (uMsg)
  783. {
  784. // called before the dialog is created, hwndPropSheet = NULL,
  785. // lParam points to dialog resource
  786. // This would hide the context help "?" on toolbar
  787. #if 0
  788. case PSCB_PRECREATE:
  789. {
  790. LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
  791. lpTemplate->style &= ~DS_CONTEXTHELP;
  792. }
  793. break;
  794. #endif
  795. case PSCB_INITIALIZED:
  796. {
  797. HWND hwndTemp = NULL;
  798. // Cancel button becomes close
  799. //
  800. hwndTemp = ::GetDlgItem(hwndDlg, IDCANCEL);
  801. if (NULL != hwndTemp)
  802. {
  803. ::SetWindowText(hwndTemp, ::SzLoadIds(IDS_SM_PSH_CLOSE));
  804. }
  805. HICON hIcon;
  806. hIcon = (HICON)SendMessage(hwndDlg,
  807. WM_GETICON,
  808. ICON_SMALL,
  809. 0);
  810. // Assert(hIcon);
  811. if (hIcon)
  812. {
  813. SendMessage(hwndDlg,
  814. WM_SETICON,
  815. ICON_BIG,
  816. (LPARAM)hIcon);
  817. }
  818. }
  819. break;
  820. }
  821. return 0;
  822. }