Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3040 lines
87 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998.
  5. //
  6. // File: C O N N L I S T . C P P
  7. //
  8. // Contents: Connection list class -- subclass of the stl list<> code.
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 19 Feb 1998
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "foldinc.h" // Standard shell\folder includes
  18. #include "ncnetcon.h"
  19. #include "ctrayui.h"
  20. #include "traymsgs.h"
  21. #include "ncerror.h"
  22. #include "notify.h"
  23. #include "ncperms.h"
  24. #include "cmdtable.h"
  25. #include "foldres.h"
  26. #include "winuserp.h"
  27. extern HWND g_hwndTray;
  28. const DWORD c_dwInvalidCookie = -1;
  29. DWORD CConnectionList::m_dwNotifyThread = NULL;
  30. HANDLE CConnectionList::m_hNotifyThread = NULL;
  31. // use this for debugging. We don't usually want more than one advise, so for
  32. // now I'm going to assert on this being false on advise creation
  33. //
  34. DWORD g_dwAdvisesActive = 0;
  35. CTrayIconData::CTrayIconData(const CTrayIconData& TrayIconData) throw()
  36. {
  37. m_uiTrayIconId = TrayIconData.m_uiTrayIconId;
  38. m_ncs = TrayIconData.m_ncs;
  39. m_pcpStat = TrayIconData.m_pcpStat;
  40. m_pnseStats = TrayIconData.m_pnseStats;
  41. m_pccts = TrayIconData.m_pccts;
  42. m_dwLastBalloonMessage = TrayIconData.m_dwLastBalloonMessage;
  43. m_pfnBalloonFunction = TrayIconData.m_pfnBalloonFunction;
  44. m_szCookie = SysAllocStringByteLen(reinterpret_cast<LPCSTR>(TrayIconData.m_szCookie), SysStringByteLen(TrayIconData.m_szCookie));
  45. DWORD dwpcpStatCount = 0;
  46. DWORD dwpnseStats = 0;
  47. DWORD dwpccts = 0;
  48. if (m_pcpStat)
  49. {
  50. dwpcpStatCount = m_pcpStat->AddRef();
  51. }
  52. if (m_pnseStats)
  53. {
  54. dwpnseStats = m_pnseStats->AddRef();
  55. }
  56. if (m_pccts)
  57. {
  58. dwpccts = m_pccts->AddRef();
  59. }
  60. AssertSz(dwpcpStatCount < 100, "Possible IConnectionPoint reference leak");
  61. AssertSz(dwpnseStats < 100, "Possible INetStatisticsEngine* reference leak");
  62. AssertSz(dwpccts < 100, "Possible CConnectionTrayStats* reference leak");
  63. TraceTag(ttidConnectionList, "CTrayIconData::CTrayIconData(CTrayIconData&) [%d %d %d]", dwpcpStatCount, dwpnseStats, dwpccts);
  64. }
  65. CTrayIconData::CTrayIconData(IN UINT uiTrayIconId,
  66. IN NETCON_STATUS ncs,
  67. IN IConnectionPoint * pcpStat,
  68. IN INetStatisticsEngine * pnseStats,
  69. IN CConnectionTrayStats * pccts) throw()
  70. {
  71. m_uiTrayIconId = uiTrayIconId;
  72. m_ncs = ncs;
  73. m_pcpStat= pcpStat;
  74. m_pnseStats = pnseStats;
  75. m_pccts = pccts;
  76. m_szCookie = NULL;
  77. m_dwLastBalloonMessage = BALLOON_NOTHING;
  78. m_pfnBalloonFunction = NULL;
  79. DWORD dwpcpStatCount = 0;
  80. DWORD dwpnseStats = 0;
  81. DWORD dwpccts = 0;
  82. if (m_pcpStat)
  83. {
  84. dwpcpStatCount = m_pcpStat->AddRef();
  85. }
  86. if (m_pnseStats)
  87. {
  88. dwpnseStats = m_pnseStats->AddRef();
  89. }
  90. if (m_pccts)
  91. {
  92. dwpccts = m_pccts->AddRef();
  93. }
  94. SetBalloonInfo(0, NULL, NULL);
  95. AssertSz(dwpcpStatCount < 100, "Possible IConnectionPoint reference leak");
  96. AssertSz(dwpnseStats < 100, "Possible INetStatisticsEngine* reference leak");
  97. AssertSz(dwpccts < 100, "Possible CConnectionTrayStats* reference leak");
  98. #ifdef DBG
  99. if (FIsDebugFlagSet(dfidTraceFileFunc))
  100. {
  101. TraceTag(ttidConnectionList, "CTrayIconData::CTrayIconData(UINT, BOOL...) [%d %d %d]", dwpcpStatCount, dwpnseStats, dwpccts);
  102. }
  103. #endif
  104. }
  105. CTrayIconData::~CTrayIconData() throw()
  106. {
  107. DWORD dwpcpStatCount = 0;
  108. DWORD dwpnseStats = 0;
  109. DWORD dwpccts = 0;
  110. if (m_pccts)
  111. {
  112. dwpccts = m_pccts->Release();
  113. }
  114. if (m_pcpStat)
  115. {
  116. dwpcpStatCount = m_pcpStat->Release();
  117. }
  118. if (m_pnseStats)
  119. {
  120. dwpnseStats = m_pnseStats->Release();
  121. }
  122. if (m_szCookie)
  123. {
  124. SysFreeString(m_szCookie);
  125. }
  126. AssertSz(dwpcpStatCount < 100, "Possible IConnectionPoint reference leak");
  127. AssertSz(dwpnseStats < 100, "Possible INetStatisticsEngine* reference leak");
  128. AssertSz(dwpccts < 100, "Possible CConnectionTrayStats* reference leak");
  129. #ifdef DBG
  130. if (FIsDebugFlagSet(dfidTraceFileFunc))
  131. {
  132. TraceTag(ttidConnectionList, "CTrayIconData::~CTrayIconData [%d %d %d]", dwpcpStatCount, dwpnseStats, dwpccts);
  133. }
  134. #endif
  135. }
  136. HRESULT CTrayIconData::SetBalloonInfo(IN DWORD dwLastBalloonMessage,
  137. IN BSTR szCookie,
  138. IN FNBALLOONCLICK* pfnBalloonFunction)
  139. {
  140. m_dwLastBalloonMessage = dwLastBalloonMessage;
  141. m_pfnBalloonFunction = pfnBalloonFunction;
  142. if (szCookie)
  143. {
  144. m_szCookie = SysAllocStringByteLen(reinterpret_cast<LPCSTR>(szCookie), SysStringByteLen(szCookie));;
  145. }
  146. else
  147. {
  148. m_szCookie = NULL;
  149. }
  150. return S_OK;
  151. }
  152. //+---------------------------------------------------------------------------
  153. //
  154. // Member: CConnectionList::Initialize
  155. //
  156. // Purpose: Initialize class members.
  157. //
  158. // Arguments:
  159. // fTieToTray [in] Use this list for tray support. This should be passed
  160. // in as FALSE when the list is being used for temporary
  161. // work.
  162. //
  163. // Returns:
  164. //
  165. // Author: jeffspr 17 Nov 1998
  166. //
  167. // Notes:
  168. //
  169. VOID CConnectionList::Initialize(IN BOOL fTieToTray, IN BOOL fAdviseOnThis) throw()
  170. {
  171. TraceFileFunc(ttidConnectionList);
  172. m_pcclc = NULL;
  173. m_fPopulated = false;
  174. m_dwAdviseCookie = c_dwInvalidCookie;
  175. m_fTiedToTray = fTieToTray;
  176. m_fAdviseOnThis = fAdviseOnThis;
  177. #if DBG
  178. m_dwCritSecRef = 0;
  179. m_dwWriteLockRef = 0;
  180. #endif
  181. InitializeCriticalSection(&m_csMain);
  182. InitializeCriticalSection(&m_csWriteLock);
  183. }
  184. //+---------------------------------------------------------------------------
  185. //
  186. // Member: CConnectionList::Uninitialize
  187. //
  188. // Purpose: Flush the connection list and do all cleanup
  189. // of tray icons and interfaces and such.
  190. //
  191. // Arguments:
  192. // (none)
  193. //
  194. // Returns:
  195. //
  196. // Author: jeffspr 24 Sep 1998
  197. //
  198. // Notes: Don't make COM calls from this function if fFinalUninitialize is true. It's called from DllMain.
  199. // No need for EnsureConPointNotifyRemoved() as it's removed from
  200. // CConnectionTray::HrHandleTrayClose
  201. VOID CConnectionList::Uninitialize(IN BOOL fFinalUninitialize) throw()
  202. {
  203. TraceFileFunc(ttidConnectionList);
  204. if (fFinalUninitialize)
  205. {
  206. Assert(FImplies(m_dwNotifyThread, m_hNotifyThread));
  207. if (m_dwNotifyThread && m_hNotifyThread)
  208. {
  209. PostThreadMessage(m_dwNotifyThread, WM_QUIT, NULL, NULL);
  210. if (WAIT_TIMEOUT == WaitForSingleObject(m_hNotifyThread, 30000))
  211. {
  212. TraceTag(ttidError, "Timeout waiting for Notify Thread to quit");
  213. }
  214. }
  215. }
  216. FlushConnectionList();
  217. delete m_pcclc;
  218. m_pcclc = NULL;
  219. Assert(m_dwCritSecRef == 0);
  220. Assert(m_dwWriteLockRef == 0);
  221. DeleteCriticalSection(&m_csWriteLock);
  222. DeleteCriticalSection(&m_csMain);
  223. }
  224. HRESULT ConnListEntry::SetTrayIconData(IN const CTrayIconData& TrayIconData)
  225. {
  226. TraceFileFunc(ttidConnectionList);
  227. if (m_pTrayIconData)
  228. {
  229. delete m_pTrayIconData;
  230. m_pTrayIconData = NULL;
  231. }
  232. m_pTrayIconData = new CTrayIconData(TrayIconData);
  233. if (!m_pTrayIconData)
  234. {
  235. return E_OUTOFMEMORY;
  236. }
  237. return S_OK;
  238. }
  239. CONST_IFSTRICT CTrayIconData* ConnListEntry::GetTrayIconData() const
  240. {
  241. return m_pTrayIconData;
  242. }
  243. BOOL ConnListEntry::HasTrayIconData() const throw()
  244. {
  245. return (m_pTrayIconData != NULL);
  246. }
  247. HRESULT ConnListEntry::DeleteTrayIconData()
  248. {
  249. if (m_pTrayIconData)
  250. {
  251. delete m_pTrayIconData;
  252. m_pTrayIconData = NULL;
  253. }
  254. return S_OK;
  255. }
  256. //
  257. // Is this the main shell process? (eg the one that owns the desktop window)
  258. //
  259. // NOTE: if the desktop window has not been created, we assume that this is NOT the
  260. // main shell process and return FALSE;
  261. //
  262. STDAPI_(BOOL) IsMainShellProcess() throw()
  263. {
  264. static int s_fIsMainShellProcess = -1;
  265. if (s_fIsMainShellProcess == -1)
  266. {
  267. s_fIsMainShellProcess = FALSE;
  268. HWND hwndDesktop = GetShellWindow();
  269. if (hwndDesktop)
  270. {
  271. DWORD dwPid;
  272. if (GetWindowThreadProcessId(hwndDesktop, &dwPid))
  273. {
  274. if (GetCurrentProcessId() == dwPid)
  275. {
  276. s_fIsMainShellProcess = TRUE;
  277. }
  278. }
  279. }
  280. else
  281. {
  282. TraceTag(ttidError, "IsMainShellProcess: hwndDesktop does not exist, assuming we are NOT the main shell process");
  283. return FALSE;
  284. }
  285. if (s_fIsMainShellProcess)
  286. {
  287. TraceTag(ttidNotifySink, "We are running inside the main explorer process.");
  288. }
  289. else
  290. {
  291. TraceTag(ttidNotifySink, "We are NOT running inside the main explorer process.");
  292. }
  293. }
  294. return s_fIsMainShellProcess ? TRUE : FALSE;
  295. }
  296. //+---------------------------------------------------------------------------
  297. //
  298. // Member: CConnectionList::NotifyThread
  299. //
  300. // Purpose: Create a thread to listen for notifications from netman
  301. //
  302. // Arguments:
  303. // pConnectionList [out] The CConnectionList to be updated by netman events
  304. //
  305. // Returns:
  306. //
  307. // Author: deonb 2001
  308. //
  309. // Notes: This thread is used in the case where we are running the Connection
  310. // folder outside of the context of explorer.exe. In that case we don't
  311. // have the explorer tray icon thread to listen to events from netman.
  312. //
  313. DWORD CConnectionList::NotifyThread(IN OUT LPVOID pConnectionList) throw()
  314. {
  315. CConnectionList *pThis = reinterpret_cast<CConnectionList *>(pConnectionList);
  316. HRESULT hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
  317. if (SUCCEEDED(hr))
  318. {
  319. pThis->EnsureConPointNotifyAdded();
  320. MSG msg;
  321. while (GetMessage (&msg, 0, 0, 0))
  322. {
  323. DispatchMessage (&msg);
  324. }
  325. // Don't call EnsureConPointNotifyRemoved() since this function is called from DllMain.
  326. // We'll have to rely on Netman to detect by itself that this thread has died.
  327. CoUninitialize();
  328. }
  329. return SUCCEEDED(hr);
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Member: CConnectionList::HrRetrieveConManEntries
  334. //
  335. // Purpose: Get the connection data from the enumerator, and build the
  336. // connection list and tray
  337. //
  338. // Arguments:
  339. // papidlOut [out] Retrieved entry pidl vector
  340. //
  341. // Returns:
  342. //
  343. // Author: jeffspr 24 Sep 1998
  344. //
  345. // Notes:
  346. //
  347. HRESULT CConnectionList::HrRetrieveConManEntries(
  348. OUT PCONFOLDPIDLVEC& apidlOut)
  349. {
  350. TraceFileFunc(ttidConnectionList);
  351. HRESULT hr = S_OK;
  352. DWORD cpidl = 0;
  353. NETCFG_TRY
  354. ConnListEntry cle;
  355. BOOL fLockAcquired = FALSE;
  356. // If we haven't yet populated our list, do so.
  357. //
  358. if (!m_fPopulated)
  359. {
  360. static LONG lSyncAquired = 0;
  361. if (!InterlockedExchange(&lSyncAquired, 1))
  362. {
  363. if (!IsMainShellProcess() && (!g_dwAdvisesActive) && (m_fAdviseOnThis) )
  364. {
  365. m_hNotifyThread = CreateThread(NULL, STACK_SIZE_SMALL, NotifyThread, this, 0, &m_dwNotifyThread);
  366. if (!m_hNotifyThread)
  367. {
  368. TraceTag(ttidError, "Could not create sink thread");
  369. }
  370. }
  371. }
  372. hr = HrRefreshConManEntries();
  373. if (FAILED(hr))
  374. {
  375. goto Exit;
  376. }
  377. m_fPopulated = true;
  378. }
  379. if (m_pcclc)
  380. {
  381. AcquireLock();
  382. fLockAcquired = TRUE;
  383. // Get the count of the elements
  384. //
  385. cpidl = m_pcclc->size();
  386. // Allocate an array to store the pidls that we'll retrieve
  387. //
  388. ConnListCore::const_iterator clcIter;
  389. DWORD dwLoop = 0;
  390. // Iterate through the list and build the ppidl array
  391. //
  392. for (clcIter = m_pcclc->begin();
  393. clcIter != m_pcclc->end();
  394. clcIter++)
  395. {
  396. Assert(!clcIter->second.empty());
  397. cle = clcIter->second;
  398. Assert(!cle.ccfe.empty() );
  399. if (!cle.ccfe.empty())
  400. {
  401. // Convert the confoldentry to a pidl, so we can
  402. // retrieve the size
  403. //
  404. PCONFOLDPIDL pConFoldPidlTmp;
  405. hr = cle.ccfe.ConvertToPidl(pConFoldPidlTmp);
  406. if (FAILED(hr))
  407. {
  408. goto Exit;
  409. }
  410. apidlOut.push_back(pConFoldPidlTmp);
  411. }
  412. else
  413. {
  414. hr = E_OUTOFMEMORY;
  415. }
  416. }
  417. // Do NOT do FlushTrayPosts here. It doesn't work, and it causes a deadlock.
  418. }
  419. Exit:
  420. if (fLockAcquired)
  421. {
  422. ReleaseLock();
  423. }
  424. NETCFG_CATCH(hr)
  425. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrRetrieveConManEntries");
  426. return hr;
  427. }
  428. //+---------------------------------------------------------------------------
  429. //
  430. // Member: CConnectionList::HrRemove
  431. //
  432. // Purpose: Remove a connection from the list based on a pccfe
  433. //
  434. // Arguments:
  435. // pccfe [in] Connection data (so we can find)
  436. // pfFlushPosts [out] Whether we should flush the tray icons
  437. //
  438. // Returns:
  439. //
  440. // Author: jeffspr 24 Sep 1998
  441. //
  442. // Notes:
  443. //
  444. HRESULT CConnectionList::HrRemove(IN const CONFOLDENTRY& ccfe, OUT BOOL * pfFlushPosts)
  445. {
  446. TraceFileFunc(ttidConnectionList);
  447. HRESULT hr = S_OK;
  448. AcquireLock();
  449. ConnListCore::iterator clcIter;
  450. if (m_pcclc)
  451. {
  452. // Iterate through the list looking for the entry with the
  453. // matching guid.
  454. //
  455. for (clcIter = m_pcclc->begin();
  456. clcIter != m_pcclc->end();
  457. clcIter++)
  458. {
  459. ConnListEntry& cleIter = clcIter->second;
  460. if (InlineIsEqualGUID(cleIter.ccfe.GetGuidID(), ccfe.GetGuidID()))
  461. {
  462. // Remove the entry, then break 'cause the ++
  463. // in the for loop would explode if we didn't
  464. //
  465. hr = HrRemoveByIter(clcIter, pfFlushPosts);
  466. break;
  467. }
  468. }
  469. }
  470. ReleaseLock();
  471. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrRemove");
  472. return hr;
  473. }
  474. //+---------------------------------------------------------------------------
  475. //
  476. // Member: CConnectionList::HrRemoveByIter
  477. //
  478. // Purpose: Remove a list entry, using the list entry itself as
  479. // the search element.
  480. //
  481. // Arguments:
  482. //
  483. // Returns:
  484. //
  485. // Author: jeffspr 10 Apr 1998
  486. //
  487. // Notes:
  488. //
  489. HRESULT CConnectionList::HrRemoveByIter(IN ConnListCore::iterator clcIter,
  490. OUT BOOL *pfFlushTrayPosts)
  491. {
  492. TraceFileFunc(ttidConnectionList);
  493. HRESULT hr = S_OK;
  494. ConnListEntry& cle = clcIter->second;
  495. Assert(!cle.empty());
  496. AcquireLock();
  497. // If there's a tray item for this connection
  498. //
  499. if (cle.HasTrayIconData() )
  500. {
  501. // Since we're deleting the entry, remove the tray
  502. // icon associated with this entry. Ignore the return
  503. //
  504. if (m_fTiedToTray && g_pCTrayUI)
  505. {
  506. // Set the flag to inform the caller that they will need to flush this stuff.
  507. //
  508. if (pfFlushTrayPosts)
  509. {
  510. *pfFlushTrayPosts = TRUE;
  511. }
  512. CTrayIconData * pTrayIconData = new CTrayIconData(*cle.GetTrayIconData());
  513. cle.DeleteTrayIconData();
  514. TraceTag(ttidSystray, "HrRemoveByIter: Removing tray icon for %S", cle.ccfe.GetName());
  515. PostMessage(g_hwndTray, MYWM_REMOVETRAYICON, reinterpret_cast<WPARAM>(pTrayIconData), (LPARAM) 0);
  516. }
  517. }
  518. // release the branding info
  519. //
  520. // icon path
  521. CON_BRANDING_INFO * pcbi = cle.pcbi;
  522. if (pcbi)
  523. {
  524. CoTaskMemFree(pcbi->szwLargeIconPath);
  525. CoTaskMemFree(pcbi->szwTrayIconPath);
  526. CoTaskMemFree(pcbi);
  527. }
  528. // menu items
  529. CON_TRAY_MENU_DATA * pMenuData = cle.pctmd;
  530. if (pMenuData)
  531. {
  532. DWORD dwCount = pMenuData->dwCount;
  533. CON_TRAY_MENU_ENTRY * pMenuEntry = pMenuData->pctme;
  534. while (dwCount)
  535. {
  536. Assert(pMenuEntry);
  537. CoTaskMemFree(pMenuEntry->szwMenuText);
  538. CoTaskMemFree(pMenuEntry->szwMenuCmdLine);
  539. CoTaskMemFree(pMenuEntry->szwMenuParams);
  540. dwCount--;
  541. pMenuEntry++;
  542. }
  543. CoTaskMemFree(pMenuData->pctme);
  544. CoTaskMemFree(pMenuData);
  545. }
  546. // Remove the actual element from the list
  547. //
  548. Assert(m_pcclc);
  549. m_pcclc->erase(clcIter);
  550. ReleaseLock();
  551. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrRemoveByIter");
  552. return hr;
  553. }
  554. //+---------------------------------------------------------------------------
  555. //
  556. // Member: CConnectionList::FlushTrayIcons
  557. //
  558. // Purpose: Remove all of our icons from the tray, since we're about
  559. // to either flush the connection list or turn off the tray.
  560. //
  561. // Arguments:
  562. // (none)
  563. //
  564. // Returns:
  565. //
  566. // Author: jeffspr 24 Sep 1998
  567. //
  568. // Notes:
  569. //
  570. VOID CConnectionList::FlushTrayIcons() throw()
  571. {
  572. TraceFileFunc(ttidConnectionList);
  573. AssertSz(m_fTiedToTray, "This connection list not allowed to modify tray");
  574. if (!g_pCTrayUI || !m_fTiedToTray)
  575. {
  576. return;
  577. }
  578. AcquireLock();
  579. ConnListCore::iterator clcIter;
  580. ConnListCore::const_iterator clcNext;
  581. BOOL fFlushPosts = FALSE;
  582. if (m_pcclc)
  583. {
  584. // Iterate through the list and build the ppidl array
  585. //
  586. for (clcIter = m_pcclc->begin();
  587. clcIter != m_pcclc->end();
  588. clcIter = clcNext)
  589. {
  590. Assert(!clcIter->second.empty());
  591. clcNext = clcIter;
  592. clcNext++;
  593. ConnListEntry& cle = clcIter->second; // using non-const reference for renaming only (calling cle.DeleteTrayIconData).
  594. if ( cle.HasTrayIconData() )
  595. {
  596. fFlushPosts = TRUE;
  597. CTrayIconData *pTrayIconData = new CTrayIconData(*cle.GetTrayIconData());
  598. cle.DeleteTrayIconData();
  599. TraceTag(ttidSystray, "FlushTrayIcons: Removing tray icon for %S", cle.ccfe.GetName());
  600. PostMessage(g_hwndTray, MYWM_REMOVETRAYICON, (WPARAM) pTrayIconData , (LPARAM) 0);
  601. }
  602. }
  603. }
  604. g_pCTrayUI->ResetIconCount();
  605. ReleaseLock();
  606. if (fFlushPosts)
  607. {
  608. FlushTrayPosts(g_hwndTray);
  609. }
  610. }
  611. //+---------------------------------------------------------------------------
  612. //
  613. // Member: CConnectionList::EnsureIconsPresent
  614. //
  615. // Purpose: Given an existing list, ensure that all of the tray
  616. // icons that should be shown are being shown. This needs to
  617. // be called when the tray was turned on AFTER enumeration.
  618. //
  619. // Arguments:
  620. // (none)
  621. //
  622. // Returns:
  623. //
  624. // Author: jeffspr 24 Sep 1998
  625. //
  626. // Notes:
  627. //
  628. VOID CConnectionList::EnsureIconsPresent() throw()
  629. {
  630. TraceFileFunc(ttidConnectionList);
  631. Assert(m_fTiedToTray);
  632. if (!g_pCTrayUI || !m_fTiedToTray)
  633. {
  634. return;
  635. }
  636. AcquireLock();
  637. ConnListCore::iterator clcIter;
  638. ConnListCore::const_iterator clcNext;
  639. if (m_pcclc)
  640. {
  641. // Iterate through the list and build the ppidl array
  642. //
  643. for (clcIter = m_pcclc->begin();
  644. clcIter != m_pcclc->end();
  645. clcIter = clcNext)
  646. {
  647. Assert(!clcIter->second.empty());
  648. clcNext = clcIter;
  649. clcNext++;
  650. const ConnListEntry& cle = clcIter->second;
  651. if ((!cle.HasTrayIconData() ) &&
  652. cle.ccfe.FShouldHaveTrayIconDisplayed())
  653. {
  654. CONFOLDENTRY pccfeDup;
  655. HRESULT hr = pccfeDup.HrDupFolderEntry(cle.ccfe);
  656. if (SUCCEEDED(hr))
  657. {
  658. TraceTag(ttidSystray, "EnsureIconsPresent: Adding tray icon for %S", cle.ccfe.GetName());
  659. PostMessage(g_hwndTray, MYWM_ADDTRAYICON, (WPARAM) pccfeDup.TearOffItemIdList(), (LPARAM) 0);
  660. }
  661. }
  662. }
  663. }
  664. ReleaseLock();
  665. }
  666. //+---------------------------------------------------------------------------
  667. //
  668. // Member: CConnectionList::FlushConnectionList
  669. //
  670. // Purpose: Remove all entries from the connection list
  671. //
  672. // Arguments:
  673. // (none)
  674. //
  675. // Returns:
  676. //
  677. // Author: jeffspr 24 Sep 1998
  678. //
  679. // Notes:
  680. //
  681. VOID CConnectionList::FlushConnectionList() throw()
  682. {
  683. TraceFileFunc(ttidConnectionList);
  684. AcquireLock();
  685. ConnListCore::const_iterator clcIter;
  686. ConnListCore::const_iterator clcNext;
  687. BOOL fFlushTrayPosts = FALSE;
  688. TraceTag(ttidConnectionList, "Flushing the connection list");
  689. TraceStack(ttidConnectionList);
  690. if (m_pcclc)
  691. {
  692. // Iterate through the list and build the ppidl array
  693. //
  694. for (clcIter = m_pcclc->begin();
  695. clcIter != m_pcclc->end();
  696. clcIter = clcNext)
  697. {
  698. Assert(!clcIter->second.empty());
  699. clcNext = clcIter;
  700. clcNext++;
  701. (VOID) HrRemoveByIter(clcIter, &fFlushTrayPosts);
  702. }
  703. if (m_pcclc->size() != 0)
  704. {
  705. AssertSz(FALSE, "List not clear after deleting all elements in FlushConnectionList");
  706. // Flush the list itself
  707. //
  708. m_pcclc->clear();
  709. }
  710. }
  711. // Reset the icon's icon ID count, as we've cleared out all icons
  712. //
  713. if (g_pCTrayUI && m_fTiedToTray)
  714. {
  715. g_pCTrayUI->ResetIconCount();
  716. }
  717. m_fPopulated = FALSE;
  718. ReleaseLock();
  719. // If we need to do the SendMessage to flush any PostMessages to the tray
  720. // do so
  721. //
  722. if (g_pCTrayUI && g_hwndTray && fFlushTrayPosts)
  723. {
  724. FlushTrayPosts(g_hwndTray);
  725. }
  726. }
  727. //+---------------------------------------------------------------------------
  728. //
  729. // Member: CConnectionList::HrRetrieveConManEntries
  730. //
  731. // Purpose: Retrieve the connection entries from the connection manager
  732. //
  733. // Arguments:
  734. // None
  735. //
  736. // Returns:
  737. //
  738. // Author: jeffspr 20 Feb 1998
  739. //
  740. // Notes:
  741. //
  742. HRESULT CConnectionList::HrRefreshConManEntries()
  743. {
  744. TraceFileFunc(ttidConnectionList);
  745. HRESULT hr = S_OK;
  746. CONFOLDENTRY ccfe;
  747. PCONFOLDPIDL pidlMNCWizard;
  748. PCONFOLDPIDL pidlHNWWizard;
  749. CComPtr<INetConnectionManager2> pconMan2;
  750. // Create an instance of the connection manager
  751. //
  752. hr = HrCreateInstance(
  753. CLSID_ConnectionManager2,
  754. CLSCTX_LOCAL_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  755. &pconMan2);
  756. TraceHr(ttidError, FAL, hr, FALSE, "HrCreateInstance");
  757. if (SUCCEEDED(hr))
  758. {
  759. HRESULT hrDebug = S_OK;
  760. HRESULT hrProp = S_OK;
  761. // Iterate through the connections
  762. //
  763. SAFEARRAY* psaConnectionProperties;
  764. HRESULT hrEnumConnections = pconMan2->EnumConnectionProperties(&psaConnectionProperties);
  765. if (SUCCEEDED(hrEnumConnections))
  766. {
  767. FlushConnectionList();
  768. AcquireWriteLock();
  769. AcquireLock();
  770. if (m_pcclc)
  771. {
  772. m_pcclc->clear(); // Make sure somebody else didn't come in in between the two calls and added stuff to the list
  773. }
  774. ReleaseLock();
  775. // Add the wizards to the beginning of the list
  776. //
  777. PCONFOLDPIDLVEC pcfpvEmpty;
  778. NCCS_STATE nccs = NCCS_ENABLED;
  779. DWORD dwResourceId;
  780. // Add the Make New Connection Wizard, regardless if there were any connections or not
  781. // Check for permissions etc.
  782. HrGetCommandState(pcfpvEmpty, CMIDM_NEW_CONNECTION, nccs, &dwResourceId, 0xffffffff, NB_FLAG_ON_TOPMENU);
  783. if (NCCS_ENABLED == nccs)
  784. {
  785. hr = HrCreateConFoldPidl(WIZARD_MNC, NULL, pidlMNCWizard);
  786. if (SUCCEEDED(hr))
  787. {
  788. // Convert the pidl to a ConFoldEntry
  789. //
  790. hr = pidlMNCWizard.ConvertToConFoldEntry(ccfe);
  791. if (SUCCEEDED(hr))
  792. {
  793. // Insert the wizard item
  794. //
  795. // $$NOTE: Let this fall through, even if the Insert of the wizard
  796. // didn't work. Yeah, we'd be in a bad position, but we'd be even
  797. // worse off if we just left an empty list. Whatever the case, it
  798. // would be next to impossible for this to fail.
  799. //
  800. hr = HrInsert(ccfe);
  801. }
  802. }
  803. }
  804. // Now check if we had found any connections
  805. if (S_OK == hrEnumConnections)
  806. {
  807. Assert(psaConnectionProperties);
  808. // Add the Network Setup Wizard
  809. nccs = NCCS_ENABLED;
  810. // Check for permissions etc.
  811. HrGetCommandState(pcfpvEmpty, CMIDM_HOMENET_WIZARD, nccs, &dwResourceId, 0xffffffff, NB_FLAG_ON_TOPMENU);
  812. if (NCCS_ENABLED == nccs)
  813. {
  814. hr = HrCreateConFoldPidl(WIZARD_HNW, NULL, pidlHNWWizard);
  815. if (SUCCEEDED(hr))
  816. {
  817. // Convert the pidl to a ConFoldEntry
  818. //
  819. hr = pidlHNWWizard.ConvertToConFoldEntry(ccfe);
  820. if (SUCCEEDED(hr))
  821. {
  822. hr = HrInsert(ccfe);
  823. }
  824. }
  825. }
  826. LONG lLBound;
  827. LONG lUBound;
  828. m_fPopulated = TRUE;
  829. hr = SafeArrayGetLBound(psaConnectionProperties, 1, &lLBound);
  830. if (SUCCEEDED(hr))
  831. {
  832. hr = SafeArrayGetUBound(psaConnectionProperties, 1, &lUBound);
  833. if (SUCCEEDED(hr))
  834. {
  835. for (LONG i = lLBound; i <= lUBound; i++)
  836. {
  837. CComVariant varRecord;
  838. hr = SafeArrayGetElement(psaConnectionProperties, &i, reinterpret_cast<LPVOID>(&varRecord));
  839. if (FAILED(hr))
  840. {
  841. SafeArrayDestroy(psaConnectionProperties);
  842. break;
  843. }
  844. Assert( (VT_ARRAY | VT_VARIANT) == varRecord.vt);
  845. if ( (VT_ARRAY | VT_VARIANT) != varRecord.vt)
  846. {
  847. SafeArrayDestroy(psaConnectionProperties);
  848. break;
  849. }
  850. NETCON_PROPERTIES_EX *pPropsEx;
  851. hrDebug = HrNetConPropertiesExFromSafeArray(varRecord.parray, &pPropsEx);
  852. if (SUCCEEDED(hr))
  853. {
  854. // don't insert incoming connection in transit state
  855. if (!((pPropsEx->dwCharacter & NCCF_INCOMING_ONLY) &&
  856. (pPropsEx->ncMediaType != NCM_NONE) &&
  857. !(fIsConnectedStatus(pPropsEx->ncStatus)) ))
  858. {
  859. // Get this for debugging only.
  860. PCONFOLDPIDL pcfpEmpty;
  861. hrDebug = HrInsertFromNetConPropertiesEx(*pPropsEx, pcfpEmpty);
  862. TraceError("Could not Insert from NetConProperties", hrDebug);
  863. }
  864. HrFreeNetConProperties2(pPropsEx);
  865. }
  866. else
  867. {
  868. TraceError("Could not obtain properties from Safe Array", hrDebug);
  869. }
  870. }
  871. }
  872. }
  873. }
  874. else
  875. {
  876. TraceHr(ttidError, FAL, hr, FALSE, "EnumConnectionProperties of the Connection Manager failed");
  877. } // if S_OK == hr
  878. ReleaseWriteLock();
  879. } // if SUCCEEDED(hrEnumConnections)
  880. }
  881. else
  882. {
  883. TraceHr(ttidError, FAL, hr, FALSE, "CoCreateInstance of the Connection Manager v2 failed. "
  884. "If you're in the process of shutting down, this is expected, as we can't do "
  885. "a CoCreate that would force a process to start (netman.exe). If you're not "
  886. "shutting down, then let us know the error code");
  887. }
  888. #ifdef DBG
  889. if (SUCCEEDED(hr))
  890. {
  891. AcquireLock();
  892. TraceTag(ttidNotifySink, "CConnectionList::HrRefreshConManEntries:");
  893. if (m_pcclc)
  894. {
  895. for (ConnListCore::const_iterator i = m_pcclc->begin(); i != m_pcclc->end(); i++)
  896. {
  897. const CONFOLDENTRY& cfe = i->second.ccfe;
  898. WCHAR szTrace[MAX_PATH*2];
  899. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  900. StringFromGUID2(cfe.GetGuidID(), szGuidString, MAX_GUID_STRING_LEN);
  901. TraceTag(ttidNotifySink, " ==>%S [%s:%s:%s:%s]",
  902. cfe.GetName(), DbgNcm(cfe.GetNetConMediaType()), DbgNcsm(cfe.GetNetConSubMediaType()), DbgNcs(cfe.GetNetConStatus()), DbgNccf(cfe.GetCharacteristics()) );
  903. }
  904. }
  905. ReleaseLock();
  906. }
  907. #endif
  908. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrRetrieveConManEntries");
  909. return hr;
  910. }
  911. //+---------------------------------------------------------------------------
  912. //
  913. // Member: CConnectionList::HrGetBrandingInfo
  914. //
  915. // Purpose: Get the branding-specific information off of this particular
  916. // connection. It MUST be an NCCF_BRANDING-type connection, or
  917. // this information will not be present.
  918. //
  919. // Arguments:
  920. // cle [in, out] The entry for this connection. cle.ccfe must have been
  921. // set before this call.
  922. //
  923. // Returns:
  924. //
  925. // Author: jeffspr 25 Mar 1998
  926. //
  927. // Notes:
  928. //
  929. HRESULT CConnectionList::HrGetBrandingInfo(
  930. IN OUT ConnListEntry& cle)
  931. {
  932. TraceFileFunc(ttidConnectionList);
  933. HRESULT hr = S_OK;
  934. INetConnectionBrandingInfo * pncbi = NULL;
  935. Assert(!cle.empty());
  936. Assert(!cle.ccfe.empty());
  937. if (cle.empty() || cle.ccfe.empty())
  938. {
  939. hr = E_POINTER;
  940. }
  941. else
  942. {
  943. Assert(cle.ccfe.GetCharacteristics() & NCCF_BRANDED);
  944. hr = cle.ccfe.HrGetNetCon(IID_INetConnectionBrandingInfo,
  945. reinterpret_cast<VOID**>(&pncbi));
  946. if (SUCCEEDED(hr))
  947. {
  948. // Everything is kosher. Grab the paths.
  949. //
  950. hr = pncbi->GetBrandingIconPaths(&(cle.pcbi));
  951. if (SUCCEEDED(hr))
  952. {
  953. // Trace the icon paths for debugging
  954. //
  955. if (cle.pcbi->szwLargeIconPath)
  956. {
  957. TraceTag(ttidConnectionList, " Branded icon [large]: %S",
  958. cle.pcbi->szwLargeIconPath);
  959. }
  960. if (cle.pcbi->szwTrayIconPath)
  961. {
  962. TraceTag(ttidConnectionList, " Branded icon [tray]: %S",
  963. cle.pcbi->szwTrayIconPath);
  964. }
  965. }
  966. // Grab any menu items
  967. hr = pncbi->GetTrayMenuEntries(&(cle.pctmd));
  968. if (SUCCEEDED(hr))
  969. {
  970. // Trace the menu items for debugging
  971. CON_TRAY_MENU_DATA * pMenuData = cle.pctmd;
  972. if (pMenuData)
  973. {
  974. CON_TRAY_MENU_ENTRY * pMenuEntry = pMenuData->pctme;
  975. DWORD dwCount = pMenuData->dwCount;
  976. while (dwCount)
  977. {
  978. Assert(pMenuEntry);
  979. TraceTag(ttidConnectionList, "***CM menu:*** \nItem: %S \nCommand: %S \nParameters: %S",
  980. pMenuEntry->szwMenuText,
  981. pMenuEntry->szwMenuCmdLine,
  982. pMenuEntry->szwMenuParams);
  983. dwCount--;
  984. pMenuEntry++;
  985. }
  986. }
  987. }
  988. ReleaseObj(pncbi); // 180240
  989. }
  990. else
  991. {
  992. // Not a problem -- just doesn't have branding information
  993. //
  994. hr = S_OK;
  995. }
  996. }
  997. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrGetBrandingInfo");
  998. return hr;
  999. }
  1000. //+---------------------------------------------------------------------------
  1001. //
  1002. // Member: CConnectionList::EnsureConPointNotifyAdded
  1003. //
  1004. // Purpose: Ensure that we create the con point notify
  1005. //
  1006. // Arguments:
  1007. // (none)
  1008. //
  1009. // Returns:
  1010. //
  1011. // Author: jeffspr 5 Oct 1998
  1012. //
  1013. // Notes:
  1014. //
  1015. VOID CConnectionList::EnsureConPointNotifyAdded() throw()
  1016. {
  1017. TraceFileFunc(ttidConnectionList);
  1018. HRESULT hr = S_OK; // Not returned, but used for debugging
  1019. IConnectionPoint * pConPoint = NULL;
  1020. INetConnectionNotifySink * pSink = NULL;
  1021. AssertSz(m_fAdviseOnThis, "Shouldn't even be calling EnsureConPointNotifyAdded if "
  1022. "we don't want advises");
  1023. if (m_fAdviseOnThis)
  1024. {
  1025. if (!InSendMessage())
  1026. {
  1027. // If we don't already have an advise sink
  1028. //
  1029. if (c_dwInvalidCookie == m_dwAdviseCookie)
  1030. {
  1031. AssertSz(g_dwAdvisesActive == 0, "An advise already exists. We should never "
  1032. "be creating more than one Advise per Explorer instance");
  1033. // Make sure that we have a connection point.
  1034. //
  1035. hr = HrGetNotifyConPoint(&pConPoint);
  1036. if (SUCCEEDED(hr))
  1037. {
  1038. // Create the notify sink
  1039. //
  1040. hr = CConnectionNotifySink::CreateInstance(
  1041. IID_INetConnectionNotifySink,
  1042. (LPVOID*)&pSink);
  1043. if (SUCCEEDED(hr))
  1044. {
  1045. Assert(pSink);
  1046. hr = pConPoint->Advise(pSink, &m_dwAdviseCookie);
  1047. if (SUCCEEDED(hr))
  1048. {
  1049. TraceTag(ttidNotifySink, "Added advise sink. Cookie = %d", m_dwAdviseCookie);
  1050. g_dwAdvisesActive++;
  1051. }
  1052. TraceHr(ttidError, FAL, hr, FALSE, "pConPoint->Advise");
  1053. ReleaseObj(pSink);
  1054. }
  1055. ReleaseObj(pConPoint);
  1056. }
  1057. }
  1058. }
  1059. }
  1060. TraceHr(ttidError, FAL, hr, FALSE, "EnsureConPointNotifyAdded");
  1061. }
  1062. //+---------------------------------------------------------------------------
  1063. //
  1064. // Member: CConnectionList::EnsureConPointNotifyRemoved
  1065. //
  1066. // Purpose: Ensure that the connection point notify has been unadvised.
  1067. //
  1068. // Arguments:
  1069. // (none)
  1070. //
  1071. // Returns:
  1072. //
  1073. // Author: jeffspr 7 Oct 1998
  1074. //
  1075. // Notes:
  1076. //
  1077. VOID CConnectionList::EnsureConPointNotifyRemoved() throw()
  1078. {
  1079. TraceFileFunc(ttidConnectionList);
  1080. HRESULT hr = S_OK;
  1081. IConnectionPoint * pConPoint = NULL;
  1082. AssertSz(m_fAdviseOnThis, "EnsureConPointNotifyRemoved shouldn't be "
  1083. "called when we're not a notify capable connection list");
  1084. // No more objects, so remove the advise if present
  1085. //
  1086. if (m_dwAdviseCookie != c_dwInvalidCookie)
  1087. {
  1088. hr = HrGetNotifyConPoint(&pConPoint);
  1089. if (SUCCEEDED(hr))
  1090. {
  1091. // Unadvise
  1092. //
  1093. hr = pConPoint->Unadvise(m_dwAdviseCookie);
  1094. TraceTag(ttidNotifySink, "Removed advise sink. Cookie = d", m_dwAdviseCookie);
  1095. TraceHr(ttidError, FAL, hr, FALSE, "pConPoint->Unadvise");
  1096. m_dwAdviseCookie = c_dwInvalidCookie;
  1097. ReleaseObj(pConPoint);
  1098. g_dwAdvisesActive--;
  1099. }
  1100. }
  1101. TraceHr(ttidError, FAL, hr, FALSE, "EnsureConPointNotifyRemoved");
  1102. }
  1103. //+---------------------------------------------------------------------------
  1104. //
  1105. // Member: CConnectionList::HrInsert
  1106. //
  1107. // Purpose: Insert a connection into the list, based on a pre-built
  1108. // ConFoldEntry
  1109. //
  1110. // Arguments:
  1111. // pccfe [in] ConFoldEntry describing the connection
  1112. //
  1113. // Returns:
  1114. //
  1115. // Author: jeffspr 24 Sep 1998
  1116. //
  1117. // Notes:
  1118. //
  1119. HRESULT CConnectionList::HrInsert(IN const CONFOLDENTRY& pccfe)
  1120. {
  1121. TraceFileFunc(ttidConnectionList);
  1122. HRESULT hr = S_OK;
  1123. HRESULT hrFind = S_OK;
  1124. BOOL fLockHeld = FALSE;
  1125. Assert(!pccfe.empty());
  1126. // Get the lock, so our find/add can't allow a dupe.
  1127. //
  1128. // Fill the struct data, and push it on.
  1129. //
  1130. ConnListEntry cle;
  1131. cle.dwState = CLEF_NONE;
  1132. cle.ccfe = pccfe;
  1133. // Initialize the branding info
  1134. cle.pcbi = NULL;
  1135. cle.pctmd = NULL;
  1136. if (cle.ccfe.GetCharacteristics() & NCCF_BRANDED)
  1137. {
  1138. HrGetBrandingInfo(cle);
  1139. }
  1140. Assert(!cle.empty());
  1141. AcquireLock();
  1142. TraceTag(ttidConnectionList, "Adding %S to the connection list", pccfe.GetName());
  1143. ConnListEntry cleFind;
  1144. hrFind = HrFindConnectionByGuid(&(pccfe.GetGuidID()), cleFind);
  1145. if (hrFind == S_FALSE)
  1146. {
  1147. // Allocate our list if we haven't already.
  1148. //
  1149. if (!m_pcclc)
  1150. {
  1151. m_pcclc = new ConnListCore;
  1152. }
  1153. // Allocate the structure to be pushed onto the STL list.
  1154. //
  1155. if (!m_pcclc)
  1156. {
  1157. hr = E_OUTOFMEMORY;
  1158. ReleaseLock();
  1159. }
  1160. else
  1161. {
  1162. Assert(!cle.empty());
  1163. (*m_pcclc)[cle.ccfe.GetGuidID()] = cle;
  1164. ReleaseLock();
  1165. if (m_fTiedToTray && g_pCTrayUI && cle.ccfe.FShouldHaveTrayIconDisplayed())
  1166. {
  1167. CONFOLDENTRY ccfeDup;
  1168. hr = ccfeDup.HrDupFolderEntry(cle.ccfe);
  1169. if (SUCCEEDED(hr))
  1170. {
  1171. // Note: this must be a send message otherwise we can
  1172. // get duplicate icons in the tray. ;-( We should set the
  1173. // uiTrayIconId here (while we have the lock) and PostMessage
  1174. // to actually add the tray icon, but that's a big change.
  1175. //
  1176. TraceTag(ttidSystray, "HrInsert: Adding tray icon for %S", cle.ccfe.GetName());
  1177. PostMessage(g_hwndTray, MYWM_ADDTRAYICON, (WPARAM) ccfeDup.TearOffItemIdList(), (LPARAM) 0);
  1178. }
  1179. }
  1180. }
  1181. }
  1182. else
  1183. {
  1184. ReleaseLock();
  1185. if (S_OK == hrFind)
  1186. {
  1187. TraceTag(ttidConnectionList, "Avoiding adding duplicate connection to the connection list");
  1188. }
  1189. else
  1190. {
  1191. // We had a failure finding the connection. We're hosed.
  1192. TraceTag(ttidConnectionList, "Failure doing a findbyguid in the CConnectionList::HrInsert()");
  1193. }
  1194. }
  1195. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrInsert");
  1196. return hr;
  1197. }
  1198. //+---------------------------------------------------------------------------
  1199. //
  1200. // Member: CConnectionList::HrInsertFromNetCon
  1201. //
  1202. // Purpose: Given an INetConnection *, build the cle data and insert
  1203. // the new connection into the list. Return a PCONFOLDPIDL if
  1204. // requested.
  1205. //
  1206. // Arguments:
  1207. // pNetCon [in] The active INetConnection interface
  1208. // ppcfp [out] Return pointer for PCFP, if requested
  1209. //
  1210. // Returns:
  1211. //
  1212. // Author: jeffspr 24 Sep 1998
  1213. //
  1214. // Notes:
  1215. //
  1216. HRESULT CConnectionList::HrInsertFromNetCon(
  1217. IN INetConnection * pNetCon,
  1218. OUT PCONFOLDPIDL & ppcfp)
  1219. {
  1220. TraceFileFunc(ttidConnectionList);
  1221. HRESULT hr = S_OK;
  1222. PCONFOLDPIDL pidlConnection;
  1223. CONFOLDENTRY pccfe;
  1224. Assert(pNetCon);
  1225. NETCFG_TRY
  1226. // From the net connection, create the pidl
  1227. //
  1228. hr = HrCreateConFoldPidl(WIZARD_NOT_WIZARD, pNetCon, pidlConnection);
  1229. if (SUCCEEDED(hr))
  1230. {
  1231. // Convert the pidl to a ConFoldEntry.
  1232. //
  1233. hr = pidlConnection.ConvertToConFoldEntry(pccfe);
  1234. if (SUCCEEDED(hr))
  1235. {
  1236. // Insert the item into the connection list. HrInsert should
  1237. // take over this CONFOLDENTRY, so we can't delete it.
  1238. // Note: We should kill this on fail, but we must make
  1239. // sure that HrInsert doesn't keep the pointer anywhere on
  1240. // failure.
  1241. //
  1242. hr = HrInsert(pccfe);
  1243. }
  1244. }
  1245. if (SUCCEEDED(hr))
  1246. {
  1247. // Fill in the out param
  1248. if ( !(pidlConnection.empty()) )
  1249. {
  1250. ppcfp = pidlConnection;
  1251. }
  1252. }
  1253. NETCFG_CATCH(hr)
  1254. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrInsertFromNetCon");
  1255. return hr;
  1256. }
  1257. //+---------------------------------------------------------------------------
  1258. //
  1259. // Member: CConnectionList::HrInsertFromNetConPropertiesEx
  1260. //
  1261. // Purpose: Given an NETCON_PROPERTIES_EX&, build the cle data and insert
  1262. // the new connection into the list. Return a PCONFOLDPIDL
  1263. //
  1264. // Arguments:
  1265. // pPropsEx [in] The active NETCON_PROPERTIES_EX
  1266. // ppcfp [out] Return PCONFOLDPIDL
  1267. //
  1268. // Returns:
  1269. //
  1270. // Author: deonb 26 Mar 2001
  1271. //
  1272. // Notes:
  1273. //
  1274. HRESULT CConnectionList::HrInsertFromNetConPropertiesEx(
  1275. IN const NETCON_PROPERTIES_EX& pPropsEx,
  1276. OUT PCONFOLDPIDL & ppcfp)
  1277. {
  1278. TraceFileFunc(ttidConnectionList);
  1279. HRESULT hr = S_OK;
  1280. PCONFOLDPIDL pidlConnection;
  1281. CONFOLDENTRY pccfe;
  1282. //
  1283. hr = HrCreateConFoldPidl(pPropsEx, pidlConnection);
  1284. if (SUCCEEDED(hr))
  1285. {
  1286. // Convert the pidl to a ConFoldEntry.
  1287. //
  1288. hr = pidlConnection.ConvertToConFoldEntry(pccfe);
  1289. if (SUCCEEDED(hr))
  1290. {
  1291. // Insert the item into the connection list. HrInsert should
  1292. // take over this CONFOLDENTRY, so we can't delete it.
  1293. // Note: We should kill this on fail, but we must make
  1294. // sure that HrInsert doesn't keep the pointer anywhere on
  1295. // failure.
  1296. //
  1297. hr = HrInsert(pccfe);
  1298. }
  1299. }
  1300. if (SUCCEEDED(hr))
  1301. {
  1302. // Fill in the out param
  1303. if ( !(pidlConnection.empty()) )
  1304. {
  1305. ppcfp = pidlConnection;
  1306. }
  1307. }
  1308. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrInsertFromNetCon");
  1309. return hr;
  1310. }
  1311. // Old HrFindCallbackConnName
  1312. bool operator==(IN const ConnListCore::value_type& val, IN PCWSTR pszName) throw()
  1313. {
  1314. bool bRet = false;
  1315. Assert(pszName);
  1316. const ConnListEntry &cle = val.second;
  1317. Assert(!cle.empty());
  1318. Assert(!cle.ccfe.empty());
  1319. Assert(cle.ccfe.GetName());
  1320. if (lstrcmpiW(pszName, cle.ccfe.GetName()) == 0)
  1321. {
  1322. bRet = true;
  1323. }
  1324. return bRet;
  1325. }
  1326. // Old HrFindCallbackConFoldEntry
  1327. bool operator==(IN const ConnListCore::value_type& val, IN const CONFOLDENTRY& cfe) throw()
  1328. {
  1329. bool bRet = false;
  1330. Assert(!cfe.empty())
  1331. const ConnListEntry &cle = val.second;
  1332. Assert(!cle.empty());
  1333. Assert(!cfe.empty());
  1334. Assert(!cle.ccfe.empty());
  1335. Assert(cle.ccfe.GetName());
  1336. if (cle.ccfe.GetWizard() && cfe.GetWizard())
  1337. {
  1338. bRet = true;
  1339. }
  1340. else
  1341. {
  1342. if (InlineIsEqualGUID(cfe.GetGuidID(), cle.ccfe.GetGuidID()))
  1343. {
  1344. bRet = true;
  1345. }
  1346. }
  1347. return bRet;
  1348. }
  1349. // Old HrFindCallbackTrayIconId
  1350. bool operator==(IN const ConnListCore::value_type& val, IN const UINT& uiIcon) throw()
  1351. {
  1352. bool bRet = false;
  1353. const ConnListEntry &cle = val.second;
  1354. Assert(!cle.empty());
  1355. Assert(!cle.ccfe.empty());
  1356. if (cle.HasTrayIconData() &&
  1357. (cle.GetTrayIconData()->GetTrayIconId() == uiIcon))
  1358. {
  1359. bRet = true;
  1360. }
  1361. return bRet;
  1362. }
  1363. // Old HrFindCallbackGuid
  1364. bool operator < (IN const GUID& rguid1, IN const GUID& rguid2) throw()
  1365. {
  1366. return memcmp(&rguid1, &rguid2, sizeof(GUID)) < 0;
  1367. }
  1368. BOOL ConnListEntry::empty() const throw()
  1369. {
  1370. return (ccfe.empty());
  1371. }
  1372. void ConnListEntry::clear() throw()
  1373. {
  1374. dwState = NULL;
  1375. ccfe.clear();
  1376. pctmd = NULL;
  1377. pcbi = NULL;
  1378. DeleteTrayIconData();
  1379. }
  1380. VOID CConnectionList::InternalAcquireLock() throw()
  1381. {
  1382. TraceFileFunc(ttidConnectionList);
  1383. EnterCriticalSection(&m_csMain);
  1384. #if DBG
  1385. m_dwCritSecRef++;
  1386. // TraceTag(ttidConnectionList, "CConnectionList::AcquireLock (%d)", m_dwCritSecRef);
  1387. #endif
  1388. }
  1389. VOID CConnectionList::InternalReleaseLock() throw()
  1390. {
  1391. TraceFileFunc(ttidConnectionList);
  1392. #if DBG
  1393. m_dwCritSecRef--;
  1394. // TraceTag(ttidConnectionList, "CConnectionList::ReleaseLock (%d)", m_dwCritSecRef);
  1395. #endif
  1396. LeaveCriticalSection(&m_csMain);
  1397. }
  1398. //+---------------------------------------------------------------------------
  1399. //
  1400. // Member: CConnectionList::HrFindConnectionByName
  1401. //
  1402. // Purpose: Find a connection in the connection list, using
  1403. // the connection name as the search key
  1404. //
  1405. // Arguments:
  1406. // pszName [in] Name of the connection to find
  1407. // cle [out] Return pointer for the connection entry
  1408. //
  1409. // Returns:
  1410. //
  1411. // Author: jeffspr 20 Mar 1998
  1412. //
  1413. // Notes:
  1414. //
  1415. inline HRESULT CConnectionList::HrFindConnectionByName(
  1416. IN PCWSTR pszName,
  1417. OUT ConnListEntry& cle)
  1418. {
  1419. TraceFileFunc(ttidConnectionList);
  1420. return HrFindConnectionByType( pszName, cle );
  1421. }
  1422. inline HRESULT CConnectionList::HrFindConnectionByConFoldEntry(
  1423. IN const CONFOLDENTRY& cfe,
  1424. OUT ConnListEntry& cle)
  1425. {
  1426. TraceFileFunc(ttidConnectionList);
  1427. return HrFindConnectionByType( cfe, cle );
  1428. }
  1429. inline HRESULT CConnectionList::HrFindConnectionByTrayIconId(
  1430. IN UINT uiIcon,
  1431. OUT ConnListEntry& cle)
  1432. {
  1433. TraceFileFunc(ttidConnectionList);
  1434. return HrFindConnectionByType( uiIcon, cle );
  1435. }
  1436. //+---------------------------------------------------------------------------
  1437. //
  1438. // Member: CConnectionList::HrFindRasServerConnection
  1439. //
  1440. // Purpose: Find the RAS Server connection
  1441. //
  1442. // Arguments:
  1443. // cle [out] The connection list entry
  1444. //
  1445. // Returns:
  1446. //
  1447. // Author: deonb 26 Apr 2001
  1448. //
  1449. // Notes:
  1450. //
  1451. HRESULT CConnectionList::HrFindRasServerConnection(
  1452. OUT ConnListEntry& cle)
  1453. {
  1454. HRESULT hr = S_FALSE;
  1455. if (m_pcclc)
  1456. {
  1457. AcquireLock();
  1458. ConnListCore::const_iterator clcIter;
  1459. // Try to find the connection
  1460. //
  1461. for (clcIter = m_pcclc->begin(); clcIter != m_pcclc->end(); clcIter++)
  1462. {
  1463. cle = clcIter->second;
  1464. if (!cle.ccfe.empty())
  1465. {
  1466. if (cle.ccfe.GetCharacteristics() & NCCF_INCOMING_ONLY)
  1467. {
  1468. if (cle.ccfe.GetNetConMediaType() == NCM_NONE)
  1469. {
  1470. hr = S_OK;
  1471. break;
  1472. }
  1473. }
  1474. }
  1475. }
  1476. ReleaseLock();
  1477. }
  1478. else
  1479. {
  1480. hr = E_UNEXPECTED;
  1481. }
  1482. return hr;
  1483. }
  1484. //+---------------------------------------------------------------------------
  1485. //
  1486. // Member: CConnectionList::HrFindPidlByGuid
  1487. //
  1488. // Purpose: Using a GUID, find the connection in the connection list
  1489. // and, using the conlist pccfe member, generate a pidl. This
  1490. // will be used in most of the notify sink refresh operations.
  1491. //
  1492. // Arguments:
  1493. // pguid [in] Connection GUID
  1494. // ppidl [out] Out param for the generated pidl
  1495. //
  1496. // Returns:
  1497. //
  1498. // Author: jeffspr 28 Aug 1998
  1499. //
  1500. // Notes:
  1501. //
  1502. HRESULT CConnectionList::HrFindPidlByGuid(
  1503. IN const GUID * pguid,
  1504. OUT PCONFOLDPIDL& pidl)
  1505. {
  1506. TraceFileFunc(ttidConnectionList);
  1507. HRESULT hr = S_OK;
  1508. ConnListEntry cle;
  1509. hr = HrFindConnectionByGuid(pguid, cle);
  1510. if (S_OK == hr)
  1511. {
  1512. // convert to pidl and call the deleteccl
  1513. //
  1514. hr = cle.ccfe.ConvertToPidl(pidl);
  1515. }
  1516. TraceHr(ttidError, FAL, hr, (S_FALSE == hr),
  1517. "CConnectionList::HrFindPidlByGuid");
  1518. return hr;
  1519. }
  1520. //+---------------------------------------------------------------------------
  1521. //
  1522. // Member: CConnectionList::HrFindConnectionByGuid
  1523. //
  1524. // Purpose: Find the connection list entry based on the unique GUID
  1525. // of the connection. Return the list entry to the caller.
  1526. //
  1527. // Arguments:
  1528. // pguid [in] Lookup key
  1529. // cle [out] Return pointer for the list entry (see Notes:)
  1530. //
  1531. // Returns: S_OK, S_FALSE, or an error
  1532. //
  1533. // Author: jeffspr 24 Sep 1998
  1534. //
  1535. // Notes: The list must be locked until the caller stops using
  1536. // the returned entry
  1537. //
  1538. HRESULT CConnectionList::HrFindConnectionByGuid(
  1539. IN const GUID UNALIGNED*pguid,
  1540. OUT ConnListEntry & cle)
  1541. {
  1542. TraceFileFunc(ttidConnectionList);
  1543. HRESULT hr = S_FALSE;
  1544. GUID alignedGuid;
  1545. Assert(pguid);
  1546. alignedGuid = *pguid;
  1547. // Pre-NULL this out in case of failure.
  1548. //
  1549. if (m_pcclc)
  1550. {
  1551. AcquireLock();
  1552. ConnListCore::const_iterator iter = m_pcclc->find(alignedGuid);
  1553. if (iter != m_pcclc->end() )
  1554. {
  1555. cle = iter->second;
  1556. Assert(!cle.ccfe.empty() );
  1557. if (!cle.ccfe.empty())
  1558. {
  1559. cle.UpdateCreationTime();
  1560. hr = S_OK;
  1561. }
  1562. else
  1563. {
  1564. hr = E_OUTOFMEMORY;
  1565. }
  1566. }
  1567. else
  1568. {
  1569. hr = S_FALSE;
  1570. }
  1571. ReleaseLock();
  1572. }
  1573. else
  1574. {
  1575. hr = S_FALSE;
  1576. }
  1577. return hr;
  1578. }
  1579. //+---------------------------------------------------------------------------
  1580. //
  1581. // Member: CConnectionList::HrGetCurrentStatsForTrayIconId
  1582. //
  1583. // Purpose: Get the current statistics data from the connection
  1584. // with the specified tray icon id.
  1585. //
  1586. // Arguments:
  1587. // uiIcon [in] Tray icon id.
  1588. // ppData [out] Address of where to return pointer to data.
  1589. // pstrName [out] Address of a tstring where the name of the connection
  1590. // is returned.
  1591. //
  1592. // Returns: S_OK, S_FALSE if not found, or an error.
  1593. //
  1594. // Author: shaunco 7 Nov 1998
  1595. //
  1596. // Notes: Free the *ppData with CoTaskMemFree.
  1597. //
  1598. HRESULT CConnectionList::HrGetCurrentStatsForTrayIconId(
  1599. IN UINT uiIcon,
  1600. OUT STATMON_ENGINEDATA** ppData,
  1601. OUT tstring* pstrName)
  1602. {
  1603. TraceFileFunc(ttidConnectionList);
  1604. HRESULT hr;
  1605. ConnListEntry cle;
  1606. INetStatisticsEngine* pnse = NULL;
  1607. // Initialize the output parameter.
  1608. //
  1609. if (ppData)
  1610. {
  1611. *ppData = NULL;
  1612. }
  1613. pstrName->erase();
  1614. // Lock the list only long enough to find the entry and
  1615. // get an AddRef'd copy of its INetStatisticsEngine interface pointer.
  1616. // It's very important not to use this pointer while our lock is
  1617. // held because doing so will cause it to try to get it's own lock.
  1618. // If, on some other thread, that statistics engine is trying to call
  1619. // back into us (and it already has its lock held), we'd have a dead lock.
  1620. // AddRefing it ensures that the interface is valid even after we
  1621. // release our lock.
  1622. //
  1623. AcquireLock();
  1624. hr = HrFindConnectionByTrayIconId(uiIcon, cle);
  1625. if (S_OK == hr)
  1626. {
  1627. Assert(cle.HasTrayIconData() );
  1628. pnse = cle.GetTrayIconData()->GetNetStatisticsEngine();
  1629. AddRefObj(pnse);
  1630. // Make a copy of the name for the caller.
  1631. //
  1632. pstrName->assign(cle.ccfe.GetName());
  1633. }
  1634. ReleaseLock();
  1635. // If we found the entry and obtained it's INetStatisticsEngine interface,
  1636. // get the current statistics data from it and release it.
  1637. //
  1638. if (pnse && ppData)
  1639. {
  1640. hr = pnse->GetStatistics(ppData);
  1641. }
  1642. if (pnse)
  1643. {
  1644. ReleaseObj(pnse);
  1645. }
  1646. TraceHr(ttidError, FAL, hr, (S_FALSE == hr),
  1647. "CConnectionList::HrGetCurrentStatsForTrayIconId");
  1648. return hr;
  1649. }
  1650. //+---------------------------------------------------------------------------
  1651. //
  1652. // Member: CConnectionList::HrUpdateTrayIconIdByName
  1653. //
  1654. // Purpose: Update the connection list entry for a particular connection,
  1655. // as the icon id has changed.
  1656. //
  1657. // Arguments:
  1658. // pszName [in] Name of the connection to update
  1659. // pccts [in] Tray stats interface
  1660. // pcpStat [in] Interface used for Advise
  1661. // pnseStats [in] More statistics object crap
  1662. // uiIcon [in] Icon ID to be stored in that entry
  1663. //
  1664. // Returns: S_OK, S_FALSE if not found, or an error code.
  1665. //
  1666. // Author: jeffspr 20 Mar 1998
  1667. //
  1668. // Notes:
  1669. //
  1670. HRESULT CConnectionList::HrUpdateTrayIconDataByGuid(
  1671. IN const GUID * pguid,
  1672. IN CConnectionTrayStats * pccts,
  1673. IN IConnectionPoint * pcpStat,
  1674. IN INetStatisticsEngine * pnseStats,
  1675. IN UINT uiIcon)
  1676. {
  1677. TraceFileFunc(ttidConnectionList);
  1678. HRESULT hr = S_OK;
  1679. ConnListEntry cle;
  1680. AcquireWriteLock();
  1681. hr = HrFindConnectionByGuid(pguid, cle);
  1682. if (hr == S_OK)
  1683. {
  1684. Assert(!cle.empty());
  1685. CTrayIconData pTrayIconData(uiIcon, cle.ccfe.GetNetConStatus(), pcpStat, pnseStats, pccts);
  1686. cle.SetTrayIconData(pTrayIconData);
  1687. hr = HrUpdateConnectionByGuid(pguid, cle);
  1688. }
  1689. ReleaseWriteLock();
  1690. TraceHr(ttidError, FAL, hr, (S_FALSE == hr),
  1691. "CConnectionList::HrUpdateTrayIconDataByGuid");
  1692. return hr;
  1693. }
  1694. //+---------------------------------------------------------------------------
  1695. //
  1696. // Member: CConnectionList::HrUpdateTrayBalloonInfoByGuid
  1697. //
  1698. // Purpose: Update the balloon entry for a particular connection,
  1699. //
  1700. // Arguments:
  1701. // pguid [in] Guid of the connection to update
  1702. // dwLastBalloonMessage [in] BALLOONS enum
  1703. // szCookie [in] Cookie
  1704. // pfnBalloonFunction [in] Balloon callback function if BALLOONS == BALLOON_CALLBACK
  1705. //
  1706. // Returns: S_OK, S_FALSE if not found, or an error code.
  1707. //
  1708. // Author: deon 22 Mar 2001
  1709. //
  1710. // Notes:
  1711. //
  1712. HRESULT CConnectionList::HrUpdateTrayBalloonInfoByGuid(IN const GUID * pguid,
  1713. IN DWORD dwLastBalloonMessage,
  1714. IN BSTR szCookie,
  1715. IN FNBALLOONCLICK* pfnBalloonFunction)
  1716. {
  1717. TraceFileFunc(ttidConnectionList);
  1718. HRESULT hr = S_OK;
  1719. ConnListEntry cle;
  1720. AcquireWriteLock();
  1721. hr = HrFindConnectionByGuid(pguid, cle);
  1722. if (hr == S_OK)
  1723. {
  1724. Assert(!cle.empty());
  1725. CTrayIconData * pTrayIconData = cle.GetTrayIconData();
  1726. if (pTrayIconData != NULL)
  1727. {
  1728. hr = pTrayIconData->SetBalloonInfo(dwLastBalloonMessage, szCookie, pfnBalloonFunction);
  1729. if (SUCCEEDED(hr))
  1730. {
  1731. hr = HrUpdateConnectionByGuid(pguid, cle);
  1732. }
  1733. }
  1734. }
  1735. ReleaseWriteLock();
  1736. TraceHr(ttidError, FAL, hr, (S_FALSE == hr),
  1737. "CConnectionList::HrUpdateTrayBalloonInfoByGuid");
  1738. return hr;
  1739. }
  1740. HRESULT CConnectionList::HrUpdateConnectionByGuid(IN const GUID * pguid,
  1741. IN const ConnListEntry& cle )
  1742. {
  1743. TraceFileFunc(ttidConnectionList);
  1744. HRESULT hr = S_OK;
  1745. GUID alignedGuid;
  1746. Assert(pguid);
  1747. alignedGuid = *pguid;
  1748. if (m_pcclc)
  1749. {
  1750. ConnListEntry cleCopy(cle);
  1751. AcquireLock();
  1752. ConnListCore::iterator iter = m_pcclc->find(alignedGuid);
  1753. if (iter != m_pcclc->end() )
  1754. {
  1755. // If what we have in the list is already more recent, just discard the change
  1756. if ( iter->second.GetCreationTime() <= cleCopy.GetCreationTime() )
  1757. {
  1758. iter->second = cleCopy;
  1759. hr = S_OK;
  1760. }
  1761. else
  1762. {
  1763. TraceError("HrUpdateConnectionByGuid discarded older ConnectionListEntry", E_FAIL);
  1764. hr = S_FALSE;
  1765. }
  1766. Assert(!cleCopy.empty());
  1767. }
  1768. else
  1769. {
  1770. hr = E_FAIL;
  1771. }
  1772. ReleaseLock();
  1773. }
  1774. else
  1775. {
  1776. hr = E_FAIL;
  1777. }
  1778. return hr;
  1779. }
  1780. //+---------------------------------------------------------------------------
  1781. //
  1782. // Member: CConnectionList::HrUpdateNameByGuid
  1783. //
  1784. // Purpose: Update the list with the new connection name. Search for the
  1785. // connection using the guid. Depending on the value of fForce,
  1786. // either fail a duplicate connection name or force the issue
  1787. // (since this might be as a result of a shell call, which we
  1788. // have no control over)
  1789. //
  1790. // Arguments:
  1791. // pguid [in] Lookup key
  1792. // pszNewName [in] New name for the connection
  1793. // ppidlOut [out] Output pidl, if requested
  1794. // fForce [in] Force the name change, or fail on duplicate?
  1795. //
  1796. // Returns:
  1797. //
  1798. // Author: jeffspr 24 Sep 1998
  1799. //
  1800. // Notes:
  1801. //
  1802. HRESULT CConnectionList::HrUpdateNameByGuid(
  1803. IN const GUID * pguid,
  1804. IN PCWSTR pszNewName,
  1805. OUT PCONFOLDPIDL & pidlOut,
  1806. IN BOOL fForce)
  1807. {
  1808. TraceFileFunc(ttidConnectionList);
  1809. HRESULT hr = S_OK;
  1810. ConnListEntry cle;
  1811. Assert(pguid);
  1812. Assert(pszNewName);
  1813. AcquireWriteLock();
  1814. hr = HrFindConnectionByGuid(pguid, cle);
  1815. if (S_OK == hr)
  1816. {
  1817. // Check to see if we already have an entry with this name
  1818. //
  1819. ConnListEntry cleDupe;
  1820. hr = HrFindConnectionByName(pszNewName, cleDupe);
  1821. if (S_OK == hr && !fForce)
  1822. {
  1823. Assert(!cleDupe.empty());
  1824. hr = NETCFG_E_NAME_IN_USE;
  1825. }
  1826. else
  1827. {
  1828. // This is what we want.. Either there's not already a connection
  1829. // with this name or we are allowing ourselves to rename it to
  1830. // a duplicate string (this can occur when RAS is notifying us of
  1831. // a change -- you know, separate phonebooks and all).
  1832. //
  1833. if ((S_FALSE == hr) || (hr == S_OK && fForce))
  1834. {
  1835. PWSTR pszNewNameCopy = NULL;
  1836. if (!(cle.ccfe.GetWizard()))
  1837. {
  1838. hr = HrDupeShellString(pszNewName, &pszNewNameCopy);
  1839. if (SUCCEEDED(hr))
  1840. {
  1841. Assert(pszNewNameCopy);
  1842. // If it's not the static wizard string, and it's non-NULL then
  1843. // free it
  1844. //
  1845. cle.ccfe.SetPName(pszNewNameCopy);
  1846. // If we're to return a new PIDL for this entry
  1847. //
  1848. // Convert the class back to the pidl format
  1849. //
  1850. hr = cle.ccfe.ConvertToPidl(pidlOut);
  1851. }
  1852. }
  1853. }
  1854. else
  1855. {
  1856. AssertSz(FALSE, "Error occurred while attempting to find a dupe in HrUpdateNameByGuid");
  1857. }
  1858. }
  1859. if (SUCCEEDED(hr))
  1860. {
  1861. hr = HrUpdateConnectionByGuid(pguid, cle);
  1862. }
  1863. }
  1864. ReleaseWriteLock();
  1865. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrUpdateNameByGuid");
  1866. return hr;
  1867. }
  1868. //+---------------------------------------------------------------------------
  1869. //
  1870. // Member: CConnectionList::HrUpdateTrayIconByGuid
  1871. //
  1872. // Purpose: Update the icon image based on the connection changes.
  1873. // Do the lookup by GUID.
  1874. //
  1875. // Arguments:
  1876. // pguid [in] GUID of the changed connection
  1877. //
  1878. // Returns:
  1879. //
  1880. // Author: jeffspr 24 Sep 1998
  1881. //
  1882. // Notes:
  1883. //
  1884. HRESULT CConnectionList::HrUpdateTrayIconByGuid(
  1885. IN const GUID * pguid,
  1886. OUT BOOL fBrieflyShowBalloon)
  1887. {
  1888. TraceFileFunc(ttidConnectionList);
  1889. HRESULT hr = S_OK;
  1890. ConnListEntry cle;
  1891. Assert(m_fTiedToTray);
  1892. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid");
  1893. if (!g_pCTrayUI || !m_fTiedToTray)
  1894. {
  1895. TraceTag(ttidConnectionList, "!g_pCTrayUI || !m_fTiedToTray, so no updates");
  1896. return S_OK;
  1897. }
  1898. Assert(pguid);
  1899. AcquireWriteLock();
  1900. hr = HrFindConnectionByGuid(pguid, cle);
  1901. if (S_OK == hr)
  1902. {
  1903. GUID * pguidCopy = NULL;
  1904. BOOL fShouldHaveIcon = cle.ccfe.FShouldHaveTrayIconDisplayed();
  1905. BOOL fShouldRemoveOld = FALSE;
  1906. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Found. fShouldHave: %d",
  1907. fShouldHaveIcon);
  1908. // If there's an existing icon, see if it needs to go away
  1909. if (cle.HasTrayIconData())
  1910. {
  1911. // If we need to remove a media-disconnected icon, do so.
  1912. //
  1913. if (cle.ccfe.GetNetConStatus() != cle.GetTrayIconData()->GetConnected()) // If the status has changed.
  1914. {
  1915. NETCON_STATUS ncsOldStatus = cle.GetTrayIconData()->GetConnected();
  1916. NETCON_STATUS ncsNewStatus = cle.ccfe.GetNetConStatus();
  1917. if ( (NCS_INVALID_ADDRESS == ncsNewStatus) || // Definitely changes the icon
  1918. (NCS_MEDIA_DISCONNECTED == ncsNewStatus) || // Definitely changes the icon
  1919. (NCS_INVALID_ADDRESS == ncsOldStatus) || // Definitely changes the icon
  1920. (NCS_MEDIA_DISCONNECTED == ncsOldStatus) || // Definitely changes the icon
  1921. ( (fIsConnectedStatus(ncsOldStatus) != fIsConnectedStatus(ncsNewStatus)) && // From connect to disconnect or disconnect to connect
  1922. !((NCS_DISCONNECTING == ncsOldStatus) && (NCS_CONNECTED == ncsNewStatus)) && // BUT NOT going from Disconnecting to Connect (BAP dialup failure)
  1923. !((NCS_CONNECTED == ncsOldStatus) && (NCS_CONNECTING == ncsNewStatus)) // Or from Connect to Connecting (BAP dialup failure)
  1924. )
  1925. )
  1926. {
  1927. // if we are changing to one of these states, we need to remove whatever was there previously
  1928. TraceTag(ttidConnectionList, "HrUpdateTrayByGuid: Need to remove icon");
  1929. fShouldRemoveOld = TRUE;
  1930. }
  1931. }
  1932. // Else if we just don't need one anymore...
  1933. //
  1934. else if (!fShouldHaveIcon)
  1935. {
  1936. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Shouldn't have a tray icon. Need to remove");
  1937. fShouldRemoveOld = TRUE;
  1938. }
  1939. }
  1940. else
  1941. {
  1942. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid. No existing icon (for removal)");
  1943. pguidCopy = new GUID;
  1944. // Copy the guid
  1945. if (pguidCopy)
  1946. {
  1947. CopyMemory(pguidCopy, pguid, sizeof(GUID));
  1948. }
  1949. }
  1950. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Found. fShouldHave: %d, fShouldRemove: %d",
  1951. fShouldHaveIcon, fShouldRemoveOld);
  1952. if (fShouldRemoveOld || pguidCopy)
  1953. {
  1954. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Posting icon removal");
  1955. if (cle.HasTrayIconData())
  1956. {
  1957. CTrayIconData* pTrayIconData = new CTrayIconData(*cle.GetTrayIconData());
  1958. cle.DeleteTrayIconData();
  1959. TraceTag(ttidSystray, "HrUpdateTrayIconByGuid: Removing tray icon for %S", cle.ccfe.GetName());
  1960. PostMessage(g_hwndTray, MYWM_REMOVETRAYICON, (WPARAM) pTrayIconData, (LPARAM) 0);
  1961. }
  1962. else
  1963. {
  1964. TraceTag(ttidSystray, "HrUpdateTrayIconByGuid: Removing tray icon [FROM GUID] for %S", cle.ccfe.GetName());
  1965. PostMessage(g_hwndTray, MYWM_REMOVETRAYICON, (WPARAM) 0, (LPARAM) pguidCopy);
  1966. }
  1967. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Back from icon removal");
  1968. }
  1969. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: cle.pTrayIconData: 0x%08x, fShouldHave: %d",
  1970. cle.GetTrayIconData(), fShouldHaveIcon);
  1971. // If there's no tray icon, but the characteristics say that there should be,
  1972. // add one.
  1973. //
  1974. if ((!cle.HasTrayIconData()) && fShouldHaveIcon)
  1975. {
  1976. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Adding tray icon");
  1977. CONFOLDENTRY ccfeDup;
  1978. hr = ccfeDup.HrDupFolderEntry(cle.ccfe);
  1979. if (SUCCEEDED(hr))
  1980. {
  1981. TraceTag(ttidSystray, "HrUpdateTrayIconByGuid: Adding tray icon for %S", cle.ccfe.GetName());
  1982. PostMessage(g_hwndTray, MYWM_ADDTRAYICON, (WPARAM) ccfeDup.TearOffItemIdList(), (LPARAM) fBrieflyShowBalloon);
  1983. }
  1984. }
  1985. else
  1986. {
  1987. TraceTag(ttidConnectionList, "HrUpdateTrayIconByGuid: Not adding an icon");
  1988. }
  1989. if (SUCCEEDED(hr))
  1990. {
  1991. hr = HrUpdateConnectionByGuid(pguid, cle);
  1992. }
  1993. }
  1994. ReleaseWriteLock();
  1995. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrUpdateTrayIconByGuid");
  1996. return hr;
  1997. }
  1998. //+---------------------------------------------------------------------------
  1999. //
  2000. // Member: CConnectionList::HrSuggestNameForDuplicate
  2001. //
  2002. // Purpose: Given an existing connection name, suggest a new name
  2003. // based on name conflict resolution rules
  2004. //
  2005. // Arguments:
  2006. // pszOriginal [in] Name being copied
  2007. // ppszNew [out] Suggested duplicate
  2008. //
  2009. // Returns:
  2010. //
  2011. // Author: jeffspr 24 Sep 1998
  2012. //
  2013. // Notes:
  2014. //
  2015. HRESULT CConnectionList::HrSuggestNameForDuplicate(
  2016. IN PCWSTR pszOriginal,
  2017. OUT PWSTR * ppszNew)
  2018. {
  2019. TraceFileFunc(ttidConnectionList);
  2020. HRESULT hr = S_OK;
  2021. PWSTR pszReturn = NULL;
  2022. DWORD dwLength = lstrlenW(pszOriginal);
  2023. BOOL fUnique = FALSE;
  2024. ConnListEntry cle;
  2025. // Maximum # of digits for resolving duplicates = 999999
  2026. static const DWORD c_cmaxDigits = 6;
  2027. static const DWORD c_cmaxSuggest = 999999;
  2028. if (dwLength == 0)
  2029. {
  2030. hr = E_INVALIDARG;
  2031. }
  2032. else
  2033. {
  2034. dwLength += lstrlenW(SzLoadIds(IDS_CONFOLD_DUPLICATE_PREFIX2)) +
  2035. c_cmaxDigits;
  2036. pszReturn = new WCHAR[dwLength + 1];
  2037. if (!pszReturn)
  2038. {
  2039. hr = E_FAIL;
  2040. }
  2041. else
  2042. {
  2043. INT cSuggest = 0;
  2044. while (!fUnique && SUCCEEDED(hr) && (cSuggest <= c_cmaxSuggest))
  2045. {
  2046. if (!cSuggest)
  2047. {
  2048. // Try "Copy of <foo>" first
  2049. DwFormatString(SzLoadIds(IDS_CONFOLD_DUPLICATE_PREFIX1),
  2050. pszReturn, dwLength, pszOriginal);
  2051. }
  2052. else
  2053. {
  2054. WCHAR szDigits[c_cmaxDigits + 1];
  2055. wsprintfW(szDigits, L"%lu", cSuggest + 1);
  2056. // Try "Copy (x) of <foo>" now.
  2057. DwFormatString(SzLoadIds(IDS_CONFOLD_DUPLICATE_PREFIX2),
  2058. pszReturn, dwLength, szDigits,
  2059. pszOriginal);
  2060. }
  2061. if (lstrlenW(pszReturn) > 255)
  2062. {
  2063. pszReturn[255] = '\0'; // Truncate if too long
  2064. }
  2065. // See if it already exists
  2066. //
  2067. hr = HrFindConnectionByName(pszReturn, cle);
  2068. if (SUCCEEDED(hr))
  2069. {
  2070. if (hr == S_FALSE)
  2071. {
  2072. // Normalize the hr -- don't want to return S_FALSE;
  2073. //
  2074. hr = S_OK;
  2075. fUnique = TRUE;
  2076. }
  2077. }
  2078. cSuggest++;
  2079. }
  2080. // If we're still not unique, then we're out of range, and fail out.
  2081. //
  2082. if (!fUnique)
  2083. {
  2084. hr = E_FAIL;
  2085. }
  2086. }
  2087. }
  2088. if (SUCCEEDED(hr))
  2089. {
  2090. *ppszNew = pszReturn;
  2091. }
  2092. else
  2093. {
  2094. if (pszReturn)
  2095. {
  2096. delete [] pszReturn;
  2097. }
  2098. }
  2099. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionList::HrSuggestNameForDuplicate");
  2100. return hr;
  2101. }
  2102. //+---------------------------------------------------------------------------
  2103. //
  2104. // Member: CConnectionList::HrGetCachedPidlCopyFromPidl
  2105. //
  2106. // Purpose: Given an existing (likely outdated) pidl, retrieve the
  2107. // cached info from the list and build an up-to-date pidl
  2108. //
  2109. // Arguments:
  2110. // pidl [in] Not-necessarily-new pidl
  2111. // ppcfp [out] New pidl using cached data
  2112. //
  2113. // Returns:
  2114. //
  2115. // Author: jeffspr 24 Sep 1998
  2116. //
  2117. // Notes:
  2118. //
  2119. HRESULT CConnectionList::HrGetCachedPidlCopyFromPidl(
  2120. IN const PCONFOLDPIDL& pidl,
  2121. OUT PCONFOLDPIDL & pcfp)
  2122. {
  2123. TraceFileFunc(ttidConnectionList);
  2124. HRESULT hr = S_OK;
  2125. ConnListEntry cle;
  2126. Assert(!pidl.empty());
  2127. NETCFG_TRY
  2128. pcfp.Clear();
  2129. // Verify that this is a confoldpidl
  2130. //
  2131. if (pidl->IsPidlOfThisType())
  2132. {
  2133. hr = HrFindConnectionByGuid(&(pidl->guidId), cle);
  2134. if (S_OK == hr)
  2135. {
  2136. Assert(!cle.empty());
  2137. Assert(!cle.ccfe.empty());
  2138. const CONFOLDENTRY &pccfe = cle.ccfe;
  2139. hr = pccfe.ConvertToPidl(pcfp);
  2140. }
  2141. else
  2142. {
  2143. pcfp = pidl;
  2144. }
  2145. }
  2146. else
  2147. {
  2148. pcfp = pidl;
  2149. hr = S_OK;
  2150. }
  2151. NETCFG_CATCH(hr)
  2152. TraceHr(ttidError, FAL, hr, (S_FALSE == hr),
  2153. "CConnectionList::HrGetCachedPidlCopyFromPidl");
  2154. return hr;
  2155. }
  2156. //+---------------------------------------------------------------------------
  2157. //
  2158. // Function: HrMapCMHiddenConnectionToOwner
  2159. //
  2160. // Purpose: Maps a child connection to its parent connection.
  2161. //
  2162. // Connection Manager has two stages: Dialup and VPN.
  2163. // For the Dialup it creates a hidden connectoid that the
  2164. // folder (netshell) does not see. However netman caches
  2165. // the name, guid and status of this connectedoid. Both
  2166. // the parent and child connectoid have the same name. When
  2167. // the status of the hidden connectiod is updated the folder
  2168. // recives the guid of the hidden connectoid and maps the
  2169. // connectiod to it parent (Connection Manager) by searching
  2170. // netmans cache for the name of the hidden connectoid. Then it
  2171. // searches the connections in the folder for that name and thus
  2172. // gets the guid of the parent connectoid.
  2173. //
  2174. // When the folder gets a notify message from netman for the hidden
  2175. // connection it uses this function to find the parent and update the
  2176. // parent's status. The hidden connection is not displayed.
  2177. //
  2178. // Arguments:
  2179. // guidHidden [in] GUID of the hidden connectiod
  2180. // pguidOwner [out] GUID of the parent connectiod
  2181. //
  2182. // Returns: S_OK -- mapped the hidden connection to its parent
  2183. //
  2184. // Author: omiller 1 Jun 2000
  2185. //
  2186. // Notes:
  2187. //
  2188. HRESULT CConnectionList::HrMapCMHiddenConnectionToOwner(IN REFGUID guidHidden,
  2189. OUT GUID * pguidOwner)
  2190. {
  2191. TraceFileFunc(ttidConnectionList);
  2192. INetConnectionCMUtil * pCMUtil;
  2193. HRESULT hr = S_OK;
  2194. hr = HrCreateInstance(
  2195. CLSID_ConnectionManager,
  2196. CLSCTX_LOCAL_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  2197. &pCMUtil);
  2198. if( SUCCEEDED(hr) )
  2199. {
  2200. // Map the hidden connection to its parent.
  2201. //
  2202. hr = pCMUtil->MapCMHiddenConnectionToOwner(guidHidden, pguidOwner);
  2203. ReleaseObj(pCMUtil);
  2204. }
  2205. return hr;
  2206. }
  2207. //+---------------------------------------------------------------------------
  2208. //
  2209. // Function: HrUnsetCurrentDefault
  2210. //
  2211. // Purpose: Searches for the current default connection and clear
  2212. // the default flag.
  2213. //
  2214. // Arguments:
  2215. // guidHidden [in] GUID of the hidden connectiod
  2216. // pguidOwner [out] GUID of the parent connectiod
  2217. //
  2218. // Returns: S_OK -- mapped the hidden connection to its parent
  2219. //
  2220. // Author: deonb 4 Apr 2001
  2221. //
  2222. // Notes:
  2223. //
  2224. HRESULT CConnectionList::HrUnsetCurrentDefault(OUT PCONFOLDPIDL& cfpPreviousDefault)
  2225. {
  2226. HRESULT hr = S_FALSE;
  2227. AcquireLock();
  2228. ConnListCore::iterator clcIter;
  2229. // Iterate through the list and search for the old default connection.
  2230. //
  2231. for (clcIter = m_pcclc->begin(); clcIter != m_pcclc->end(); clcIter++)
  2232. {
  2233. ConnListEntry &cle = clcIter->second;
  2234. if (!cle.ccfe.empty())
  2235. {
  2236. if (cle.ccfe.GetCharacteristics() & NCCF_DEFAULT)
  2237. {
  2238. cle.ccfe.SetCharacteristics(cle.ccfe.GetCharacteristics() & ~NCCF_DEFAULT);
  2239. hr = cle.ccfe.ConvertToPidl(cfpPreviousDefault);
  2240. break;
  2241. }
  2242. }
  2243. else
  2244. {
  2245. hr = E_OUTOFMEMORY;
  2246. }
  2247. }
  2248. ReleaseLock();
  2249. return hr;
  2250. }
  2251. //+---------------------------------------------------------------------------
  2252. //
  2253. // Function: HrHasActiveIncomingConnections
  2254. //
  2255. // Purpose: See if there are active incoming connections active (apart from
  2256. // the RAS server).
  2257. //
  2258. // Arguments: pdwCount [out] Number of incoming connections
  2259. //
  2260. // Returns: S_OK -- Has active incoming connections
  2261. // S_FALSE -- Does not have active incoming connections
  2262. // FAILED(HRESULT) if failed
  2263. //
  2264. // Author: deonb 24 Apr 2001
  2265. //
  2266. // Notes:
  2267. //
  2268. HRESULT CConnectionList::HasActiveIncomingConnections(OUT LPDWORD pdwCount)
  2269. {
  2270. HRESULT hr = S_FALSE;
  2271. Assert(pdwCount);
  2272. *pdwCount = 0;
  2273. AcquireLock();
  2274. ConnListCore::const_iterator clcIter;
  2275. BOOL bRasServer = FALSE;
  2276. // Iterate through the list and search for the old default connection.
  2277. //
  2278. for (clcIter = m_pcclc->begin(); clcIter != m_pcclc->end(); clcIter++)
  2279. {
  2280. const ConnListEntry &cle = clcIter->second;
  2281. if (!cle.ccfe.empty())
  2282. {
  2283. if (cle.ccfe.GetCharacteristics() & NCCF_INCOMING_ONLY)
  2284. {
  2285. if (cle.ccfe.GetNetConMediaType() == NCM_NONE)
  2286. {
  2287. AssertSz(!bRasServer, "How did you get more than one RAS Server?");
  2288. bRasServer = TRUE;
  2289. }
  2290. else
  2291. {
  2292. (*pdwCount)++;
  2293. }
  2294. }
  2295. }
  2296. else
  2297. {
  2298. hr = E_OUTOFMEMORY;
  2299. }
  2300. }
  2301. ReleaseLock();
  2302. if (SUCCEEDED(hr))
  2303. {
  2304. if (*pdwCount)
  2305. {
  2306. AssertSz(bRasServer, "How did you get Incoming Connections without a RAS Server?")
  2307. hr = S_OK;
  2308. }
  2309. else
  2310. {
  2311. hr = S_FALSE;
  2312. }
  2313. }
  2314. return hr;
  2315. }
  2316. //+---------------------------------------------------------------------------
  2317. //
  2318. // Function: HrCheckForActivation
  2319. //
  2320. // Purpose: Check to see if this connection is in the process of
  2321. // activating (so we can disallow delete/rename/etc.).
  2322. //
  2323. // Arguments:
  2324. // pccfe [in] ConFoldEntry to check
  2325. // pfActivating [out] Return pointer for activating yes/no
  2326. //
  2327. // Returns: S_OK on success, S_FALSE if connection not found, or
  2328. // any upstream error code.
  2329. //
  2330. // Author: jeffspr 4 Jun 1998
  2331. //
  2332. // Notes:
  2333. //
  2334. HRESULT HrCheckForActivation(
  2335. IN const PCONFOLDPIDL& pcfp,
  2336. IN const CONFOLDENTRY& pccfe,
  2337. OUT BOOL * pfActivating)
  2338. {
  2339. HRESULT hr = S_OK;
  2340. ConnListEntry cle;
  2341. BOOL fActivating = FALSE;
  2342. Assert(pfActivating);
  2343. Assert(! (pccfe.empty() && pcfp.empty()) ); // Must specify one of the two
  2344. if (!pccfe.empty())
  2345. {
  2346. hr = g_ccl.HrFindConnectionByConFoldEntry(pccfe, cle);
  2347. }
  2348. else
  2349. {
  2350. hr = g_ccl.HrFindConnectionByGuid(&(pcfp->guidId), cle);
  2351. }
  2352. if (S_OK == hr)
  2353. {
  2354. fActivating = (cle.dwState & CLEF_ACTIVATING);
  2355. }
  2356. if (SUCCEEDED(hr))
  2357. {
  2358. *pfActivating = fActivating;
  2359. }
  2360. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "HrCheckForActivation");
  2361. return hr;
  2362. }
  2363. //+---------------------------------------------------------------------------
  2364. //
  2365. // Function: HrSetActivationFlag
  2366. //
  2367. // Purpose: Set the activation flag for a particular connection
  2368. //
  2369. // Arguments:
  2370. // pcfp [in] Either this pidl or the pconfoldentry below
  2371. // pccfe [in] must be valid.
  2372. // fActivating [out] Current activation status
  2373. //
  2374. // Returns:
  2375. //
  2376. // Author: jeffspr 5 Jun 1998
  2377. //
  2378. // Notes:
  2379. //
  2380. HRESULT HrSetActivationFlag(
  2381. IN const PCONFOLDPIDL& pcfp,
  2382. IN const CONFOLDENTRY& pccfe,
  2383. IN BOOL fActivating)
  2384. {
  2385. HRESULT hr = S_OK;
  2386. ConnListEntry cle;
  2387. // If the pccfe is valid, use that. Otherwise, use the guid from the pidl
  2388. //
  2389. #ifdef DBG
  2390. if (FIsDebugFlagSet(dfidTraceFileFunc))
  2391. {
  2392. TraceTag(ttidConnectionList, "Acquiring LOCK: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
  2393. }
  2394. #endif
  2395. g_ccl.AcquireWriteLock();
  2396. if (!pccfe.empty())
  2397. {
  2398. hr = g_ccl.HrFindConnectionByConFoldEntry(pccfe, cle);
  2399. }
  2400. else
  2401. {
  2402. Assert(!pcfp.empty());
  2403. hr = g_ccl.HrFindConnectionByGuid(&(pcfp->guidId), cle);
  2404. }
  2405. if (S_OK == hr)
  2406. {
  2407. // Assert that the state isn't already set this way.
  2408. //
  2409. // Assert((!!(cle.dwState & CLEF_ACTIVATING)) != fActivating);
  2410. if (fActivating)
  2411. {
  2412. cle.dwState |= CLEF_ACTIVATING;
  2413. }
  2414. else
  2415. {
  2416. cle.dwState &= ~CLEF_ACTIVATING;
  2417. }
  2418. g_ccl.HrUpdateConnectionByGuid(&(cle.ccfe.GetGuidID()), cle);
  2419. }
  2420. #ifdef DBG
  2421. if (FIsDebugFlagSet(dfidTraceFileFunc))
  2422. {
  2423. TraceTag(ttidConnectionList, "Releasing LOCK: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
  2424. }
  2425. #endif
  2426. g_ccl.ReleaseWriteLock();
  2427. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "HrSetActivationFlag");
  2428. return hr;
  2429. }
  2430. //+---------------------------------------------------------------------------
  2431. //
  2432. // Function: HrGetTrayIconLock
  2433. //
  2434. // Purpose: Get a lock for the tray icon -- keeps us from getting
  2435. // duplicate icons in the tray if two enumerations are occurring
  2436. // simultaneously
  2437. //
  2438. // Arguments:
  2439. // pguid [in] Item for which to set the lock
  2440. //
  2441. // Returns: S_OK if the lock could be set. S_FALSE otherwise.
  2442. //
  2443. // Author: jeffspr 23 Oct 1998
  2444. //
  2445. // Notes:
  2446. //
  2447. HRESULT HrGetTrayIconLock(
  2448. IN const GUID * pguid,
  2449. OUT UINT * puiIcon,
  2450. OUT LPDWORD pdwLockingThreadId)
  2451. {
  2452. HRESULT hr = S_OK;
  2453. ConnListEntry cle;
  2454. Assert(pguid);
  2455. // Otherwise, use the guid from the pidl
  2456. //
  2457. TraceTag(ttidSystray, "Acquiring Tray icon lock");
  2458. g_ccl.AcquireWriteLock();
  2459. hr = g_ccl.HrFindConnectionByGuid(pguid, cle);
  2460. if (S_OK == hr)
  2461. {
  2462. if (cle.dwState & CLEF_TRAY_ICON_LOCKED)
  2463. {
  2464. hr = S_FALSE;
  2465. #ifdef DBG
  2466. // if (pdwLockingThreadId)
  2467. {
  2468. Assert(cle.dwLockingThreadId);
  2469. *pdwLockingThreadId = cle.dwLockingThreadId;
  2470. }
  2471. #endif
  2472. }
  2473. else
  2474. {
  2475. cle.dwState |= CLEF_TRAY_ICON_LOCKED;
  2476. #ifdef DBG
  2477. cle.dwLockingThreadId = GetCurrentThreadId();
  2478. #endif
  2479. if (puiIcon)
  2480. {
  2481. if (cle.HasTrayIconData())
  2482. {
  2483. *puiIcon = cle.GetTrayIconData()->GetTrayIconId();
  2484. }
  2485. else
  2486. {
  2487. *puiIcon = BOGUS_TRAY_ICON_ID;
  2488. }
  2489. }
  2490. g_ccl.HrUpdateConnectionByGuid(pguid, cle);
  2491. Assert(cle.dwLockingThreadId);
  2492. }
  2493. }
  2494. else
  2495. {
  2496. hr = E_FILE_NOT_FOUND;
  2497. }
  2498. g_ccl.ReleaseWriteLock();
  2499. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "HrGetTrayIconLock");
  2500. return hr;
  2501. }
  2502. //+---------------------------------------------------------------------------
  2503. //
  2504. // Function: ReleaseTrayIconLock
  2505. //
  2506. // Purpose: Release a lock (if held) on a particular tray icon
  2507. //
  2508. // Arguments:
  2509. // pguid [in] Item for which to release the lock
  2510. //
  2511. // Returns:
  2512. //
  2513. // Author: jeffspr 23 Oct 1998
  2514. //
  2515. // Notes:
  2516. //
  2517. VOID ReleaseTrayIconLock(
  2518. IN const GUID * pguid) throw()
  2519. {
  2520. HRESULT hr = S_OK;
  2521. ConnListEntry cle;
  2522. g_ccl.AcquireWriteLock();
  2523. Assert(pguid);
  2524. hr = g_ccl.HrFindConnectionByGuid(pguid, cle);
  2525. if (S_OK == hr)
  2526. {
  2527. // Ignore whether or not this flag has already been removed.
  2528. //
  2529. cle.dwState &= ~CLEF_TRAY_ICON_LOCKED;
  2530. #ifdef DBG
  2531. cle.dwLockingThreadId = 0;
  2532. #endif
  2533. g_ccl.HrUpdateConnectionByGuid(pguid, cle);
  2534. }
  2535. g_ccl.ReleaseWriteLock();
  2536. TraceTag(ttidSystray, "Releasing Tray icon lock");
  2537. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "ReleaseTrayIconLock");
  2538. }
  2539. ConnListEntry::ConnListEntry() throw() : dwState(0), m_pTrayIconData(NULL), pctmd(NULL), pcbi(NULL)
  2540. {
  2541. TraceFileFunc(ttidConnectionList);
  2542. m_CreationTime = GetTickCount();
  2543. #ifdef DBG
  2544. dwLockingThreadId = 0;
  2545. #endif
  2546. }
  2547. ConnListEntry::ConnListEntry(const ConnListEntry& ConnectionListEntry) throw()
  2548. {
  2549. TraceFileFunc(ttidConnectionList);
  2550. #ifdef DBG
  2551. dwLockingThreadId = ConnectionListEntry.dwLockingThreadId;
  2552. #endif
  2553. m_CreationTime = ConnectionListEntry.m_CreationTime;
  2554. dwState = ConnectionListEntry.dwState;
  2555. ccfe = ConnectionListEntry.ccfe;
  2556. if (ConnectionListEntry.HasTrayIconData())
  2557. {
  2558. m_pTrayIconData = new CTrayIconData(*ConnectionListEntry.GetTrayIconData());
  2559. }
  2560. else
  2561. {
  2562. m_pTrayIconData = NULL;
  2563. }
  2564. pctmd = ConnectionListEntry.pctmd;
  2565. pcbi = ConnectionListEntry.pcbi;
  2566. }
  2567. ConnListEntry& ConnListEntry::operator =(const ConnListEntry& ConnectionListEntry)
  2568. {
  2569. TraceFileFunc(ttidConnectionList);
  2570. m_CreationTime = ConnectionListEntry.m_CreationTime;
  2571. #ifdef DBG
  2572. dwLockingThreadId = ConnectionListEntry.dwLockingThreadId;
  2573. #endif
  2574. dwState = ConnectionListEntry.dwState;
  2575. ccfe = ConnectionListEntry.ccfe;
  2576. if (ConnectionListEntry.HasTrayIconData())
  2577. {
  2578. if (m_pTrayIconData)
  2579. {
  2580. delete m_pTrayIconData;
  2581. m_pTrayIconData = NULL;
  2582. }
  2583. m_pTrayIconData = new CTrayIconData(*ConnectionListEntry.GetTrayIconData());
  2584. }
  2585. else
  2586. {
  2587. if (m_pTrayIconData)
  2588. {
  2589. delete m_pTrayIconData;
  2590. m_pTrayIconData = NULL;
  2591. }
  2592. else
  2593. {
  2594. m_pTrayIconData = NULL;
  2595. }
  2596. }
  2597. pctmd = ConnectionListEntry.pctmd;
  2598. pcbi = ConnectionListEntry.pcbi;
  2599. return *this;
  2600. }
  2601. ConnListEntry::~ConnListEntry()
  2602. {
  2603. TraceFileFunc(ttidConnectionList);
  2604. delete m_pTrayIconData;
  2605. m_pTrayIconData = NULL;
  2606. }
  2607. void CConnectionList::AcquireWriteLock() throw()
  2608. {
  2609. EnterCriticalSection(&m_csWriteLock);
  2610. #ifdef DBG
  2611. m_dwWriteLockRef++;
  2612. TraceTag(ttidConnectionList, "CConnectionList::AcquireWriteLock (%d)", m_dwWriteLockRef);
  2613. #endif
  2614. }
  2615. void CConnectionList::ReleaseWriteLock() throw()
  2616. {
  2617. #ifdef DBG
  2618. m_dwWriteLockRef--;
  2619. TraceTag(ttidConnectionList, "CConnectionList::ReleaseWriteLock (%d)", m_dwWriteLockRef);
  2620. #endif
  2621. LeaveCriticalSection(&m_csWriteLock);
  2622. }